dtcalc: change from obsoleted MAXFLOAT to FLT_MAX from std C
[oweals/cde.git] / cde / lib / DtHelp / Callbacks.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: Callbacks.c /main/21 1996/10/22 12:22:33 cde-hp $ */
24 /************************************<+>*************************************
25  ****************************************************************************
26  **
27  **   File:        Callbacks.c
28  **
29  **   Project:     Display Area Library
30  **
31  **  
32  **   Description: This body of code handles the callbacks for the
33  **                Display Area.
34  **
35  ****************************************************************************
36  ************************************<+>*************************************/
37 /*
38  * (c) Copyright 1996 Digital Equipment Corporation.
39  * (c) Copyright 1987-1994, 1996 Hewlett-Packard Company.
40  * (c) Copyright 1993, 1994, 1996 International Business Machines Corp.
41  * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.
42  * (c) Copyright 1993, 1994, 1996 Novell, Inc. 
43  * (c) Copyright 1996 FUJITSU LIMITED.
44  * (c) Copyright 1996 Hitachi.
45  */
46
47 /*
48  * system includes
49  */
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <limits.h>
53 #include <X11/Xlib.h>
54 #include <X11/Xatom.h>
55 #include <X11/Intrinsic.h>
56 #include <Xm/Xm.h>
57 #include <Xm/AtomMgr.h>
58 #include <Xm/DrawnB.h>
59 #include <Xm/CutPaste.h>
60 #include <Xm/XmPrivate.h>
61
62
63 /*
64  * Canvas Engine
65  */
66 #include "CanvasP.h"
67
68 /*
69  * private includes
70  */
71 #include "Access.h"
72 #include "DisplayAreaP.h"
73 #include "CallbacksI.h"
74 #include "FontI.h"
75 #include "FontAttrI.h"
76 #include "HyperTextI.h"
77 #include "SetListI.h"
78 #include "HelposI.h"
79 #include "XInterfaceI.h"
80
81 #ifdef NLS16
82 #endif
83
84 /********    Private Function Declarations    ********/
85 static  Boolean  ConvertSelectionCB (
86                         Widget           widget,
87                         Atom            *selection,
88                         Atom            *target,
89                         Atom            *type,
90                         XtPointer       *value,
91                         unsigned long   *length,
92                         int             *format );
93 static  void     ScrollTimerCB (
94                         XtPointer        client_data,
95                         XtIntervalId    *id );
96 static  void     StartSelection (
97                         Widget          widget,
98                         XtPointer       client_data );
99 /********    End Private Function Declarations    ********/
100
101 /********    Private Defines                 ********/
102 #define SCROLL_BAR_FLAGS 0x03
103 #define HORIZONTAL       0
104 #define VERTICAL         1
105
106 /********    End Private Defines             ********/
107
108 /********    Private Variable Declarations    ********/
109
110 /********    End Private Variable Declarations    ********/
111
112 /******************************************************************************
113  *                             Private Functions
114  ******************************************************************************/
115 /*****************************************************************************
116  * Function: ConvertSelectionCB
117  *
118  *    ConvertSelectionCB - this routine is called when someone asks for
119  *                              our selection.
120  *
121  *****************************************************************************/
122 static  Boolean
123 ConvertSelectionCB (
124         Widget           widget,
125         Atom            *selection,
126         Atom            *target,
127         Atom            *type,
128         XtPointer       *value,
129         unsigned long   *length,
130         int             *format )
131 {
132     Atom  TARGETS    = XmInternAtom(XtDisplay(widget), "TARGETS"  , False);
133     Atom  TIMESTAMP  = XmInternAtom(XtDisplay(widget), "TIMESTAMP", False);
134     Atom  TEXT       = XmInternAtom(XtDisplay(widget), "TEXT"     , False);
135     Atom  CMP_TEXT   = XmInternAtom(XtDisplay(widget), "COMPOUND_TEXT",False);
136     Atom  LOCALE;
137     int   retStatus  = 0;
138     char *testString = "ABC";  /* these are characters in XPCS, so... safe */
139     char *tmpString  = NULL;
140     Arg    args[2];
141     DtHelpDispAreaStruct *pDAS;
142
143     XTextProperty  tmpProp;
144
145     XtSetArg(args[0], XmNuserData, &pDAS);
146     XtGetValues(widget, args, 1);
147
148     if (pDAS == NULL || pDAS->primary == False || *selection != XA_PRIMARY)
149         return False;
150
151     retStatus = XmbTextListToTextProperty(XtDisplay(widget), &testString, 1,
152                                 (XICCEncodingStyle)XTextStyle, &tmpProp);
153
154     LOCALE = (Atom) 9999; /* XmbTextList... should always be able
155                                      * to convert XPCS characters; but in
156                                      * case its broken, this prevents a core
157                                      * dump.
158                                      */
159     if (retStatus == Success)
160       {
161         LOCALE = tmpProp.encoding;
162         XFree(tmpProp.value);
163       }
164
165     /*
166      * List the targets understood
167      */
168     if (*target == TARGETS)
169       {
170         Atom *targs = (Atom *)XtMalloc((unsigned) (5 * sizeof(Atom)));
171
172         *value   = (char *) targs;
173         *targs++ = LOCALE;
174         *targs++ = TIMESTAMP;
175         *targs++ = TEXT;
176         *targs++ = CMP_TEXT;
177         *targs++ = XA_STRING;
178
179         *type   = XA_ATOM;
180         *length = (5 * sizeof(Atom)) >> 2;
181         *format = 32;
182       }
183     else if (*target == TIMESTAMP)
184       {
185         Time *timestamp;
186         timestamp  = (Time *) XtMalloc(sizeof(Time));
187         *timestamp = pDAS->anchor_time;
188
189         *value  = (char *) timestamp;
190         *type   = XA_INTEGER;
191         *length = sizeof(Time);
192         *format = 32;
193       }
194     else if (*target == XA_STRING)
195       {
196         /*
197          * initialize the return type here in case we fail
198          */
199         *type   = (Atom) XA_STRING;
200         *format = 8;
201
202         /*
203          * get the string
204          */
205         _DtCanvasGetSelection (pDAS->canvas,
206                                 (_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
207                                                 (_DtCvPointer *)(&tmpString));
208         retStatus = -1;
209         if (tmpString != NULL && *tmpString != '\0')
210             retStatus = XmbTextListToTextProperty(XtDisplay(widget),
211                                 &tmpString, 1,
212                                 (XICCEncodingStyle)XStringStyle, &tmpProp);
213
214         /*
215          * free the original copy of the string and check the results
216          */
217         if (tmpString != NULL)
218             free(tmpString);
219
220         if (retStatus == Success || retStatus > 0)
221           {
222             *value  = (XtPointer) tmpProp.value;
223             *length = tmpProp.nitems;
224           }
225         else
226           {
227             *value = NULL;
228             *length = 0;
229             return False;
230           }
231       }
232     else if (*target == TEXT)
233       {
234         /*
235          * set the type and format to those calculated
236          */
237         *type   = TEXT;
238         *format = 8;
239
240         /*
241          * get the string
242          */
243         _DtCanvasGetSelection (pDAS->canvas, 
244                                 (_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
245                                                 (_DtCvPointer *)(&tmpString));
246
247         retStatus = -1;
248         if (tmpString != NULL && *tmpString != '\0')
249             retStatus = XmbTextListToTextProperty(XtDisplay(widget),
250                                 &tmpString, 1,
251                                 (XICCEncodingStyle)XStdICCTextStyle, &tmpProp);
252
253         /*
254          * free the original copy of the string and check the results
255          */
256         if (tmpString != NULL)
257             free(tmpString);
258
259         if (retStatus == Success || retStatus > 0)
260           {
261             *value  = (XtPointer) tmpProp.value;
262             *length = tmpProp.nitems;
263           }
264         else
265           {
266             *value = NULL;
267             *length = 0;
268             return False;
269           }
270       }
271     else if (*target == LOCALE)
272       {
273         /*
274          * pass the string straight through
275          */
276         *type   = LOCALE;
277         *format = 8;
278
279         _DtCanvasGetSelection (pDAS->canvas, 
280                                 (_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
281                                                 (_DtCvPointer *)(value));
282         *length = 0;
283         if (*value != NULL)
284             *length = strlen((char *)(*value));
285       }
286     else if (*target == CMP_TEXT)
287       {
288         *type   = CMP_TEXT;
289         *format = 8;
290
291         /*
292          * get the selected text.
293          */
294         _DtCanvasGetSelection (pDAS->canvas, 
295                                 (_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
296                                                 (_DtCvPointer *)(&tmpString));
297
298         retStatus = -1;
299         if (tmpString != NULL && *tmpString != '\0')
300             retStatus = XmbTextListToTextProperty(XtDisplay(widget),
301                         &tmpString, 1,
302                         (XICCEncodingStyle)XCompoundTextStyle, &tmpProp);
303
304         /*
305          * free the original copy of the string and check the results
306          */
307         if (tmpString != NULL)
308             free(tmpString);
309
310         if (retStatus == Success || retStatus > 0)
311           {
312             *value  = (XtPointer) tmpProp.value;
313             *length = tmpProp.nitems;
314           }
315         else
316           {
317             *value = NULL;
318             *length = 0;
319             return False;
320           }
321       }
322     else
323         return False;
324
325     return True;
326
327 } /* End ConvertSelectionCB */
328
329 /*****************************************************************************
330  * Function: ScrollTimerCB
331  *
332  *    ScrollTimerCB - This routine is called when we have a timer
333  *              go off with the mouse outside the Display Area during a
334  *              selection.
335  *
336  *****************************************************************************/
337 static  void
338 ScrollTimerCB (
339         XtPointer        client_data,   /*  data from applicaiton   */
340         XtIntervalId    *id )           /*  timer id                */
341 {
342     int    diffY = 0;
343     int    diffX = 0;
344     int    x;
345     int    y;
346     int    scrollTimeOut;
347     int    maxY;
348     int    dispY;
349     Arg    args[2];
350     XmScrollBarCallbackStruct callData;
351     DtHelpDispAreaStruct  *pDAS = (DtHelpDispAreaStruct *) client_data;
352
353     if (*id != pDAS->scr_timer_id)
354       return;
355
356     pDAS->scr_timer_id = 0;
357
358     maxY  = pDAS->maxYpos;
359     dispY = pDAS->firstVisible + pDAS->dispUseHeight;
360
361     if ((pDAS->scr_timer_data.vertical_reason == XmCR_INCREMENT && maxY <= dispY)
362                 ||
363         (pDAS->scr_timer_data.vertical_reason == XmCR_DECREMENT &&
364                 !pDAS->firstVisible))
365         pDAS->scr_timer_data.vertical_reason = XmCR_NONE;
366
367     if ((pDAS->scr_timer_data.horizontal_reason == XmCR_INCREMENT &&
368         pDAS->maxX <= pDAS->virtualX + ((int)pDAS->dispUseWidth))
369                 ||
370         (pDAS->scr_timer_data.horizontal_reason == XmCR_DECREMENT &&
371                 !pDAS->virtualX))
372         pDAS->scr_timer_data.horizontal_reason = XmCR_NONE;
373
374     if ( pDAS->scr_timer_data.vertical_reason == XmCR_NONE &&
375                 pDAS->scr_timer_data.horizontal_reason == XmCR_NONE)
376         return;
377
378     y = pDAS->firstVisible;
379     if (pDAS->scr_timer_data.vertical_reason == XmCR_NONE)
380         y = pDAS->scr_timer_y - pDAS->decorThickness;
381     else if (pDAS->scr_timer_data.vertical_reason == XmCR_INCREMENT)
382       {
383         y = y + pDAS->dispUseHeight + pDAS->lineHeight;
384         if (y > pDAS->maxYpos)
385             y = pDAS->maxYpos;
386
387         diffY = y - pDAS->firstVisible - pDAS->dispUseHeight;
388       }
389     else if (pDAS->scr_timer_data.vertical_reason == XmCR_DECREMENT)
390       {
391         y -= pDAS->lineHeight;
392         if (y < 0)
393             y = 0;
394
395         diffY = y - pDAS->firstVisible;
396       }
397
398     if (pDAS->scr_timer_data.horizontal_reason == XmCR_NONE)
399         x = pDAS->scr_timer_x - pDAS->decorThickness;
400     else
401       {
402         if (pDAS->scr_timer_data.horizontal_reason == XmCR_INCREMENT)
403           {
404             diffX = (int) (pDAS->charWidth / 10);
405             x = pDAS->dispUseWidth;
406
407             if (x + pDAS->virtualX + diffX > pDAS->maxX)
408                 diffX = pDAS->maxX - x - pDAS->virtualX;
409           }
410         else if (pDAS->scr_timer_data.horizontal_reason == XmCR_DECREMENT)
411           {
412             diffX = -((int)(pDAS->charWidth / 10));
413             x = 0;
414
415             if (pDAS->virtualX + diffX < 0)
416                 diffX = -(pDAS->virtualX);
417           }
418       }
419    
420     _DtCanvasProcessSelection (pDAS->canvas,
421                         (x + diffX + pDAS->virtualX - pDAS->decorThickness),
422                         y, _DtCvSELECTION_UPDATE);
423
424     callData.event = NULL;
425     if (diffX)
426       {
427         scrollTimeOut   = pDAS->horz_rep_scr;
428         callData.reason = pDAS->scr_timer_data.horizontal_reason;
429         callData.value  = pDAS->virtualX + diffX;
430         _DtHelpHorzScrollCB (pDAS->horzScrollWid, client_data,
431                                         (XtPointer) &callData);
432
433         if (pDAS->horzScrollWid)
434           {
435             XtSetArg (args[0], XmNvalue, pDAS->virtualX);
436             XtSetValues (pDAS->horzScrollWid, args, 1);
437           }
438
439         if (diffY != 0 && pDAS->vertScrollWid)
440           {
441             XtSetArg (args[0], XmNvalue, y);
442             XtSetValues (pDAS->vertScrollWid, args, 1);
443             if (pDAS->vScrollNotify)
444               (pDAS->vScrollNotify)(pDAS->clientData, y);
445           }
446       }
447     else
448       {
449         scrollTimeOut   = pDAS->vert_rep_scr;
450         callData.reason = pDAS->scr_timer_data.vertical_reason;
451         callData.value  = pDAS->firstVisible + diffY;
452         _DtHelpVertScrollCB (pDAS->vertScrollWid, client_data,
453                                         (XtPointer) &callData);
454
455         if (pDAS->vertScrollWid)
456           {
457             XtSetArg (args[0], XmNvalue, pDAS->firstVisible);
458             XtSetValues (pDAS->vertScrollWid, args, 1);
459             if (pDAS->vScrollNotify)
460               (pDAS->vScrollNotify)(pDAS->clientData, pDAS->firstVisible);
461           }
462       }
463
464     pDAS->scr_timer_id = XtAppAddTimeOut (
465                 XtWidgetToApplicationContext (pDAS->dispWid),
466                 ((unsigned long) scrollTimeOut),
467                 ScrollTimerCB, client_data);
468
469 } /* End ScrollTimerCB */
470
471 /******************************************************************************
472  * Function: DrawWholeCanvas
473  *
474  *****************************************************************************/
475 static void
476 DrawWholeCanvas(
477     DtHelpDispAreaStruct  *pDAS)
478 {
479     _DtCvUnit    top;
480     _DtCvUnit    bottom;
481     _DtCvUnit    right;
482     _DtCvUnit    next_y;
483
484     _DtCanvasMoveTraversal(pDAS->canvas,_DtCvTRAVERSAL_OFF, False,
485                                 (XtIsRealized(pDAS->dispWid) ? True : False),
486                                 NULL, NULL, NULL, NULL, NULL);
487
488     top     = pDAS->firstVisible;
489     bottom  = top + pDAS->dispUseHeight;
490     right   = pDAS->virtualX + pDAS->dispUseWidth;
491
492     _DtCanvasRender (pDAS->canvas, pDAS->virtualX, top, right, bottom,
493                      pDAS->render_type, _DtCvTRUE, NULL, &next_y);
494     pDAS->nextNonVisible =
495         (pDAS->render_type == _DtCvRENDER_PARTIAL) ? bottom : next_y;
496
497     /*
498      * If we have a hypertext link boxed, draw it
499      */
500     _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ON, False,
501                                 (XtIsRealized(pDAS->dispWid) ? True : False),
502                                         NULL, NULL, NULL, NULL, NULL);
503     /*
504      * if the toc exists within this area, draw it.
505      */
506     if ((pDAS->toc_flag & _DT_HELP_TOC_ON) &&
507                 pDAS->toc_y + pDAS->toc_height >= top && pDAS->toc_y <  bottom)
508         _DtHelpDATocMarker((XtPointer) pDAS, True);
509
510 } /* End DrawWholeCanvas */
511
512 /******************************************************************************
513  *                          Semi Public Functions
514  *****************************************************************************/
515 /******************************************************************************
516  * Function: _DtHelpCleanAndDrawWholeCanvas
517  *
518  *****************************************************************************/
519 void
520 _DtHelpCleanAndDrawWholeCanvas(
521     XtPointer  client_data)
522 {
523     DtHelpDispAreaStruct  *pDAS = (DtHelpDispAreaStruct *) client_data;
524
525     XClearArea (XtDisplay(pDAS->dispWid), XtWindow(pDAS->dispWid),
526                                 pDAS->decorThickness, pDAS->decorThickness,
527                                 pDAS->dispUseWidth,
528                                 pDAS->dispUseHeight,
529                                 False);
530     DrawWholeCanvas (pDAS);
531
532 }
533
534 void
535 _DtHelpSearchMoveTraversal(XtPointer client_data, int search_hit_index)
536 {
537     _DtCvUnit baseline, ascend, descend;
538
539     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
540
541     if (_DtCvGetSearchLineMetrics(pDAS->canvas, search_hit_index,
542                                         &baseline, &descend, &ascend) == 0) {
543
544         _DtCvUnit top, hitY, height;
545
546         top    = pDAS->firstVisible;
547         hitY   = baseline - ascend - pDAS->lineThickness;
548         height = ascend + descend + 2 * pDAS->lineThickness;
549
550         if (hitY < top)
551             top = hitY;
552         else if (hitY + height > top + ((int) pDAS->dispUseHeight))
553             top = hitY + height - ((int) pDAS->dispUseHeight);
554
555         if (top != pDAS->firstVisible) {
556
557             _DtCvUnit dispUseHeightHalf =
558                         pDAS->dispUseHeight / 2 + pDAS->dispUseHeight % 2;
559
560             /* put search hit in the middle of the viewport */
561             if (top == hitY)
562                 top -= dispUseHeightHalf - height;
563             else {
564                 top += dispUseHeightHalf + height;
565                 if (top + ((int)pDAS->dispUseHeight) > pDAS->maxYpos)
566                     top = pDAS->maxYpos - pDAS->dispUseHeight;
567             }
568             if (top < 0)
569                 top = 0;
570
571             if (top != pDAS->firstVisible) {
572
573                 Arg arg;
574
575                 pDAS->firstVisible = top;
576
577                 XtSetArg(arg, XmNvalue, pDAS->firstVisible);
578                 XtSetValues(pDAS->vertScrollWid, &arg, 1);
579
580                 if (pDAS->vScrollNotify)
581                   (pDAS->vScrollNotify)(pDAS->clientData, pDAS->firstVisible);
582
583                 _DtHelpCleanAndDrawWholeCanvas(pDAS);
584             }
585         }
586     }
587 }
588
589 /******************************************************************************
590  * Function: _DtHelpCancelSelection
591  *
592  * Returns : True    if a selection was active and cancelled.
593  *           False   if a selection was not active.
594  *
595  *****************************************************************************/
596 Boolean
597 _DtHelpCancelSelection(
598     XtPointer  client_data)
599 {
600     Boolean selActive = False;
601     DtHelpDispAreaStruct  *pDAS = (DtHelpDispAreaStruct *) client_data;
602
603     if (pDAS->select_state == _DtHelpSelectingText && pDAS->primary == True)
604       {
605         selActive = True;
606         if (pDAS->scr_timer_id)
607           {
608             XtRemoveTimeOut (pDAS->scr_timer_id);
609             pDAS->scr_timer_id = 0;
610           }
611         _DtHelpClearSelection (client_data);
612       }
613
614     return selActive;
615 }
616
617 /******************************************************************************
618  *                          Public Functions
619  *****************************************************************************/
620 /******************************************************************************
621  * Function: _DtHelpExposeCB
622  *
623  *    _DtHelpExposeCB handles the exposure events for a Text Graphic Area.
624  *
625  *****************************************************************************/
626 void
627 _DtHelpExposeCB(
628         Widget  widget,
629         XtPointer client_data,
630         XtPointer call_data )
631 {
632     Arg    args[4];
633
634     Dimension  height;
635     Dimension  width;
636
637     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
638
639     XmDrawnButtonCallbackStruct *callback =
640                                 (XmDrawnButtonCallbackStruct *) call_data;
641
642     if (callback->reason != XmCR_EXPOSE ||
643                 (pDAS->neededFlags & (1 << (VisibilityFullyObscured + 3))))
644         return;
645
646     /*
647      * get the width and height.
648      */
649     XtSetArg(args[0], XmNwidth, &width);
650     XtSetArg(args[1], XmNheight, &height);
651     XtGetValues(widget, args, 2);
652
653     /*
654      * if this exposure is a result of a resize,
655      * wait for the resize to handle it.
656      */
657     if (width != pDAS->dispWidth || height != pDAS->dispHeight)
658         return;
659
660     if (!(callback->event) || callback->event->xexpose.count)
661         return;
662
663     /*
664      * re-draw the information in the display area
665      */
666     DrawWholeCanvas (pDAS);
667
668 }  /* End _DtHelpExposeCB */
669
670 /*********************************************************************
671  * Function: _DtHelpResizeCB
672  *
673  *    _DtHelpResizeCB handles the exposure events for a Text Graphic Area.
674  *
675  *********************************************************************/
676 void
677 _DtHelpResizeCB(
678         Widget  widget,
679         XtPointer client_data,
680         XtPointer call_data )
681 {
682     Arg  args[4];
683     Dimension width;
684     Dimension height;
685
686     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
687     XmDrawnButtonCallbackStruct *callback =
688                                 (XmDrawnButtonCallbackStruct *) call_data;
689
690     if (callback->reason != XmCR_RESIZE)
691         return;
692
693     /*
694      * get the width and height of the form.
695      */
696     XtSetArg(args[0], XmNwidth, &width);
697     XtSetArg(args[1], XmNheight, &height);
698     XtGetValues(XtParent(widget), args, 2);
699     if (width == pDAS->formWidth && height == pDAS->formHeight)
700         return;
701
702     pDAS->formWidth  = width;
703     pDAS->formHeight = height;
704
705     /*
706      * get the width and height.
707      */
708     XtSetArg(args[0], XmNwidth, &width);
709     XtSetArg(args[1], XmNheight, &height);
710     XtGetValues(widget, args, 2);
711
712     if (width == pDAS->dispWidth && height == pDAS->dispHeight)
713         return;
714
715     /*
716
717     _DtHelpClearSelection (pDAS);
718      * reset the scroll bars and possibly reformat the text for the size.
719      */
720     (void) _DtHelpSetScrollBars (client_data, width, height);
721     if (XtIsRealized (pDAS->dispWid))
722         _DtHelpCleanAndDrawWholeCanvas (client_data);
723
724     /*
725      * I will get an expose event after the resize.
726      */
727
728 }  /* End _DtHelpResizeCB */
729
730 /***************************************************************************
731  * Function:  _DtHelpVertScrollCB
732  *
733  * _DtHelpVertScrollCB is called when the vertical scroll bar is changed.
734  *
735  **************************************************************************/
736 void 
737 _DtHelpVertScrollCB(
738         Widget widget,
739         XtPointer clientData,
740         XtPointer callData )
741 {
742     DtHelpDispAreaStruct      *pDAS     = (DtHelpDispAreaStruct *) clientData;
743     XmScrollBarCallbackStruct *callBack =
744                                         (XmScrollBarCallbackStruct *) callData;
745     int         diff   = pDAS->lineHeight;
746     int         srcY, dstY;
747     int         clearY;
748     int         reason = callBack->reason;
749     _DtCvUnit   absTop;
750     _DtCvUnit   absBot;
751     Display    *dpy;
752     Window      win;
753   
754     /*
755      * if the policy is XmEXPLICIT, don't want the focus on the scrollbar
756      */
757     if (callBack->event != NULL && callBack->event->type == ButtonPress &&
758               _XmGetFocusPolicy(XtParent(XtParent(pDAS->dispWid))) != XmPOINTER)
759         XmProcessTraversal(pDAS->dispWid, XmTRAVERSE_CURRENT);
760
761     /*
762      * check to make sure we don't do a rerender when we don't have to.
763      */
764     if (pDAS->firstVisible == callBack->value)
765         return;
766
767     /* If a drag occured, reset the reason to increment, decrement, page    */
768     /* increment, or page decrement depending on the distance and direction */
769     /* dragged. */
770     if (callBack->reason == XmCR_DRAG || callBack->reason == XmCR_VALUE_CHANGED)
771       {
772         diff = callBack->value - pDAS->firstVisible;
773
774         if (diff > 0 && diff <= ((int) pDAS->dispUseHeight))
775             reason = XmCR_INCREMENT;
776         else if (diff < 0 && -(diff) <= ((int) pDAS->dispUseHeight))
777           {
778             reason = XmCR_DECREMENT;
779             diff   = -diff;
780           }
781         else if (diff > ((int) pDAS->dispUseHeight))
782             reason = XmCR_PAGE_DECREMENT;
783         else
784             reason = XmCR_PAGE_INCREMENT;
785       }
786     else if (callBack->reason == XmCR_INCREMENT ||
787                                         callBack->reason == XmCR_DECREMENT)
788       {
789         diff = callBack->value - pDAS->firstVisible;
790         if (diff < 0)
791             diff = -diff;
792       }
793
794     /* Reset first visible to the returned scrollbar value. */
795     pDAS->firstVisible = callBack->value;
796
797     /* For page increment and decrement, call _DtHelpCleanAndDrawWholeCanvas
798      * to clear the view area and redisplay the text.
799      *
800      * For increment and decrement, 
801      * use XCopyArea to move the visible lines and draw the cleared out line.
802      */
803     if (!pDAS->maxYpos ||
804                 (pDAS->neededFlags & (1 << (VisibilityFullyObscured + 3))))
805         return;
806   
807     dpy = XtDisplay (widget);
808     win = XtWindow (pDAS->dispWid);
809
810     if (reason == XmCR_PAGE_INCREMENT || reason == XmCR_PAGE_DECREMENT ||
811                 reason == XmCR_TO_TOP || reason == XmCR_TO_BOTTOM)
812         _DtHelpCleanAndDrawWholeCanvas (clientData);
813     else
814       {
815         if (reason == XmCR_INCREMENT)
816           {
817             dstY   = pDAS->decorThickness;
818             srcY   = dstY + diff;
819             clearY = pDAS->dispHeight - pDAS->decorThickness - diff;
820           }
821         else
822           {
823             srcY   = pDAS->decorThickness;
824             dstY   = srcY + diff;
825             clearY = srcY;
826           }
827         XCopyArea(dpy, win, win, pDAS->normalGC, pDAS->decorThickness, srcY,
828                 pDAS->dispUseWidth, (pDAS->dispUseHeight - diff),
829                 pDAS->decorThickness, dstY);
830
831         XClearArea(dpy, win, pDAS->decorThickness, clearY,
832                  pDAS->dispUseWidth, ((unsigned int) diff), False);
833
834         if (pDAS->neededFlags & (1 << (VisibilityPartiallyObscured + 3)))
835           {
836             /*
837              * redraw all the information
838              */
839             DrawWholeCanvas (pDAS);
840           }
841         else
842           {
843             /*
844              * draw the line that sits on the cleared line
845              */
846             absTop = clearY + pDAS->firstVisible - pDAS->decorThickness;
847             absBot = absTop + diff;
848
849             _DtCanvasRender (pDAS->canvas, 0, absTop,
850                                 pDAS->virtualX + pDAS->dispWidth, absBot,
851                                 _DtCvRENDER_PARTIAL, _DtCvFALSE, NULL, NULL);
852             /*
853              * if the toc exists within this area, draw it.
854              */
855             if ((pDAS->toc_flag & _DT_HELP_TOC_ON)
856                                 && pDAS->toc_y + pDAS->toc_height >= absTop
857                                 && pDAS->toc_y < absBot)
858                 _DtHelpDATocMarker((XtPointer) pDAS, True);
859           }
860       }
861
862 }  /* End _DtHelpVertScrollCB */
863
864 /***************************************************************************
865  * Function:  _DtHelpHorzScrollCB
866  *
867  * _DtHelpHorzScrollCB is called when the horizontal scroll bar is changed.
868  *
869  **************************************************************************/
870 void 
871 _DtHelpHorzScrollCB(
872         Widget widget,
873         XtPointer clientData,
874         XtPointer callData )
875 {
876     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) clientData;
877     XmScrollBarCallbackStruct *callBack =
878                                         (XmScrollBarCallbackStruct *) callData;
879     int          diff = (int)(pDAS->charWidth / 10);
880     int          srcX;
881     int          dstX;
882     int          clearX;
883     int          reason = callBack->reason;
884     _DtCvUnit    absLeft;
885     _DtCvUnit    absRight;
886     _DtCvUnit    absY;
887     Display     *dpy;
888     Window       win;
889
890     /*
891      * if the policy is XmEXPLICIT, don't want the focus on the scrollbar
892      */
893     if (callBack->event != NULL && callBack->event->type == ButtonPress &&
894               _XmGetFocusPolicy(XtParent(XtParent(pDAS->dispWid))) != XmPOINTER)
895         XmProcessTraversal(pDAS->dispWid, XmTRAVERSE_CURRENT);
896
897     /*
898      * check to make sure we don't do a rerender when we don't have to.
899      */
900     if (pDAS->virtualX == callBack->value)
901         return;
902
903     /* If a drag occured, reset the reason to increment, decrement, page    */
904     /* increment, or page decrement depending on the distance and direction */
905     /* dragged. */
906     if (callBack->reason == XmCR_DRAG || callBack->reason == XmCR_VALUE_CHANGED)
907       {
908         diff = callBack->value - pDAS->virtualX;
909
910         if (diff > 0 && diff <= ((int) pDAS->dispUseWidth))
911             reason = XmCR_INCREMENT;
912         else if (diff < 0 && -(diff) <= ((int) pDAS->dispUseWidth))
913           {
914             reason = XmCR_DECREMENT;
915             diff   = -diff;
916           }
917         else if (diff > ((int) pDAS->dispUseWidth))
918             reason = XmCR_PAGE_DECREMENT;
919         else
920             reason = XmCR_PAGE_INCREMENT;
921       }
922     else if (callBack->reason == XmCR_INCREMENT ||
923                                         callBack->reason == XmCR_DECREMENT)
924       {
925         diff = callBack->value - pDAS->virtualX;
926         if (diff < 0)
927             diff = -diff;
928       }
929
930     /* Reset first visible to the returned scrollbar value. */
931     pDAS->virtualX = callBack->value;
932
933     /* For page increment and decrement, call _DtHelpCleanAndDrawWholeCanvas
934      * to clear the view area and redisplay the text.
935      *
936      * For increment and decrement, 
937      * use XCopyArea to move the visible lines and draw the cleared out line.
938      */
939     if (!pDAS->maxX || !pDAS->visibleCount ||
940                 (pDAS->neededFlags & (1 << (VisibilityFullyObscured + 3))))
941         return;
942   
943     dpy = XtDisplay (widget);
944     win = XtWindow (pDAS->dispWid);
945
946     /* For page increment and decrement, clear the view area and call
947      * View_DtHelpExposeCB to redisplay the text. For increment and decrement,
948      * use XCopyArea to move the visible lines and draw the cleared out line.
949      */
950     if (reason == XmCR_PAGE_INCREMENT || reason == XmCR_PAGE_DECREMENT ||
951                 reason == XmCR_TO_TOP || reason == XmCR_TO_BOTTOM)
952         _DtHelpCleanAndDrawWholeCanvas (clientData);
953     else
954       {
955         if (reason == XmCR_INCREMENT)
956           {
957             dstX   = pDAS->decorThickness;
958             srcX   = dstX + diff;
959             clearX = pDAS->dispWidth - pDAS->decorThickness - diff;
960           }
961         else
962           {
963             srcX   = pDAS->decorThickness;
964             dstX   = srcX + diff;
965             clearX = srcX;
966           }
967
968         XCopyArea(dpy, win, win, pDAS->normalGC, srcX, pDAS->decorThickness,
969                         pDAS->dispUseWidth - diff, pDAS->dispUseHeight,
970                         dstX, pDAS->decorThickness);
971
972         XClearArea(dpy, win, clearX, pDAS->decorThickness,
973                 ((unsigned int) diff), pDAS->dispUseHeight, False);
974
975         if (pDAS->neededFlags & (1 << (VisibilityPartiallyObscured + 3)))
976           {
977             /*
978              * redraw all the information
979              */
980             DrawWholeCanvas (pDAS);
981           }
982         else
983           {
984             /*
985              * draw the line that sits on the cleared line
986              */
987             absLeft  = clearX + pDAS->virtualX - pDAS->decorThickness;
988             absRight = absLeft + diff;
989             absY     = pDAS->firstVisible - pDAS->decorThickness;
990
991             _DtCanvasRender (pDAS->canvas, absLeft, absY,
992                                 absRight, absY + pDAS->dispHeight,
993                                 _DtCvRENDER_PARTIAL, _DtCvFALSE, NULL, NULL);
994
995             /*
996              * if the toc exists within this area, draw it.
997              */
998             if ((pDAS->toc_flag & _DT_HELP_TOC_ON)
999                 && ((int) (pDAS->toc_y + pDAS->toc_height)) >= ((int) absY)
1000                 && ((int) pDAS->toc_y) < ((int) (absY + pDAS->dispHeight)))
1001                 _DtHelpDATocMarker((XtPointer) pDAS, True);
1002
1003           }
1004       }
1005
1006 }  /* End _DtHelpHorzScrollCB */
1007
1008 /***************************************************************************
1009  * Function:  _DtHelpClickOrSelectCB
1010  *
1011  * _DtHelpClickOrSelectCB is called when the vertical scroll bar is changed.
1012  *
1013  **************************************************************************/
1014 void 
1015 _DtHelpClickOrSelectCB(
1016         Widget widget,
1017         XtPointer clientData,
1018         XtPointer callData )
1019 {
1020     XmDrawnButtonCallbackStruct *callBack =
1021                                 (XmDrawnButtonCallbackStruct *) callData;
1022     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) clientData;
1023
1024     /*
1025      * If this is not an ARM call or entered through an Arm&Activate
1026      * (event-type will be keypress or keyrelease) throw it away.
1027      */
1028     if (callBack->reason != XmCR_ARM || callBack->event == NULL ||
1029         callBack->event->type == KeyPress ||
1030         callBack->event->type == KeyRelease)
1031         return;
1032
1033     pDAS->timerX       = callBack->event->xbutton.x;
1034     pDAS->timerY       = callBack->event->xbutton.y;
1035     pDAS->select_state = _DtHelpCopyOrLink;
1036
1037     if (NULL != pDAS->armCallback)
1038         (pDAS->armCallback)(pDAS->clientData);
1039
1040 }  /* End _DtHelpClickOrSelectCB */
1041
1042 /*****************************************************************************
1043  * Function: _DtHelpEndSelectionCB
1044  *
1045  *
1046  * Called by: Callback for the Selection mechanism
1047  *****************************************************************************/
1048 void
1049 _DtHelpEndSelectionCB (
1050         Widget          w,              /*  widget id           */
1051         XtPointer       client_data,    /*  data from applicaiton   */
1052         XtPointer       call_data )     /*  data from widget class  */
1053 {
1054     XmDrawnButtonCallbackStruct *callback =
1055                                 (XmDrawnButtonCallbackStruct *) call_data;
1056     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) client_data;
1057     int    newX;
1058     int    newY;
1059
1060     if (callback->reason != XmCR_DISARM || callback->event == NULL ||
1061         callback->event->type == KeyPress ||
1062         callback->event->type == KeyRelease)
1063         return;
1064
1065     /*
1066      * if a scroll timer is active, we are selecting text.
1067      * stop it.
1068      */
1069     if (pDAS->scr_timer_id)
1070       {
1071         XtRemoveTimeOut (pDAS->scr_timer_id);
1072         pDAS->scr_timer_id = 0;
1073       }
1074
1075     newX = callback->event->xbutton.x;
1076     newY = callback->event->xbutton.y;
1077     if (pDAS->select_state == _DtHelpCopyOrLink)
1078       {
1079         if (abs (pDAS->timerX - newX) <= pDAS->moveThreshold &&
1080                         abs (pDAS->timerY - newY) <= pDAS->moveThreshold)
1081           {
1082             _DtHelpClearSelection (client_data);
1083
1084             /*
1085              * If this is null, we came the the Arm&Activate routine
1086              * which means a key was pressed, so we ignore this call.
1087              */
1088             if (callback->event)
1089                 /*
1090                  * find the hypertext link and process it.
1091                  */
1092                 _DtHelpProcessHyperSelection (client_data,
1093                                                 pDAS->timerX, pDAS->timerY,
1094                                                 callback->event);
1095           }
1096         else
1097             StartSelection (w, client_data);
1098         return;
1099       }
1100
1101     /*
1102      * The user was doing a selection, finish it up.
1103      */
1104     if (pDAS->select_state != _DtHelpNothingDoing)
1105       {
1106         _DtCanvasProcessSelection(pDAS->canvas,
1107                 (newX + pDAS->virtualX - pDAS->decorThickness),
1108                 (newY + pDAS->firstVisible - pDAS->decorThickness),
1109                 _DtCvSELECTION_END);
1110         _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ON, False, True,
1111                                 NULL, NULL, NULL, NULL, NULL);
1112
1113       }
1114
1115     pDAS->select_state = _DtHelpNothingDoing;
1116     return;
1117
1118 }  /* End _DtHelpEndSelectionCB */
1119
1120 /***************************************************************************
1121  * Function:  _DtHelpMouseMoveCB
1122  *
1123  * _DtHelpMouseMoveCB tracks the mouse movement for the Selection mechanism
1124  *
1125  **************************************************************************/
1126 void 
1127 _DtHelpMouseMoveCB(
1128         Widget     widget,
1129         XtPointer  client_data,
1130         XEvent    *event )
1131 {
1132     _DtCvUnit   newX;
1133     _DtCvUnit   newY;
1134     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1135
1136     /*
1137      * If a selection is not in progress, don't do anything.
1138      */
1139     if (pDAS->select_state == _DtHelpNothingDoing || event->type != MotionNotify)
1140         return;
1141
1142     if (pDAS->scr_timer_id)
1143       {
1144         XtRemoveTimeOut (pDAS->scr_timer_id);
1145         pDAS->scr_timer_id = 0;
1146       }
1147
1148     newX = event->xmotion.x;
1149     newY = event->xmotion.y;
1150
1151     if (pDAS->select_state == _DtHelpCopyOrLink)
1152       {
1153         if (abs (newX - pDAS->timerX) < pDAS->moveThreshold &&
1154                         abs (newY - pDAS->timerY) < pDAS->moveThreshold)
1155             return;
1156
1157         StartSelection (widget, client_data);
1158         return;
1159       }
1160
1161     if (newY < ((int) pDAS->decorThickness) && pDAS->firstVisible)
1162         pDAS->scr_timer_data.vertical_reason = XmCR_DECREMENT;
1163
1164     else if ((newY >
1165             (((int) pDAS->dispHeight)-((int)pDAS->decorThickness))) &&
1166             (pDAS->maxYpos >
1167                 (((int)pDAS->firstVisible)
1168                                 + ((int)pDAS->dispUseHeight))))
1169         pDAS->scr_timer_data.vertical_reason = XmCR_INCREMENT;
1170     else
1171         pDAS->scr_timer_data.vertical_reason = XmCR_NONE;
1172
1173     if (newX < ((int) pDAS->decorThickness) && pDAS->virtualX)
1174         pDAS->scr_timer_data.horizontal_reason = XmCR_DECREMENT;
1175     else if (newX > ((int) pDAS->dispWidth) &&
1176             pDAS->maxX > pDAS->virtualX + ((int) pDAS->dispUseWidth))
1177         pDAS->scr_timer_data.horizontal_reason = XmCR_INCREMENT;
1178     else
1179         pDAS->scr_timer_data.horizontal_reason = XmCR_NONE;
1180
1181     if (pDAS->scr_timer_data.vertical_reason != XmCR_NONE ||
1182         pDAS->scr_timer_data.horizontal_reason != XmCR_NONE)
1183       {
1184         int scrollTimeOut = pDAS->vert_init_scr;
1185
1186         if (pDAS->scr_timer_data.horizontal_reason != XmCR_NONE)
1187             scrollTimeOut = pDAS->horz_init_scr;
1188
1189         pDAS->scr_timer_x  = newX;
1190         pDAS->scr_timer_y  = newY;
1191         pDAS->scr_timer_id =
1192                         XtAppAddTimeOut(XtWidgetToApplicationContext(widget),
1193                                 ((unsigned long) scrollTimeOut),
1194                                 ScrollTimerCB, (XtPointer) pDAS);
1195         return;
1196       }
1197
1198     newX = newX + pDAS->virtualX - pDAS->decorThickness;
1199     if (newX < 0)
1200         newX = 0;
1201
1202     newY = newY + pDAS->firstVisible - pDAS->decorThickness;
1203     if (newY < 0)
1204         newY = 0;
1205
1206     _DtCanvasProcessSelection(pDAS->canvas, newX, newY, _DtCvSELECTION_UPDATE);
1207
1208 } /* End _DtHelpMouseMoveCB */
1209
1210 /*****************************************************************************
1211  * Function: StartSelection
1212  *
1213  *    StartSelection - If this routine is called, the user has initiated a
1214  *                   selection.
1215  *
1216  *****************************************************************************/
1217 static  void
1218 StartSelection (
1219         Widget          widget,         /*  widget id               */
1220         XtPointer       client_data )   /*  data from applicaiton   */
1221 {
1222     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) client_data;
1223
1224     /*
1225      * If this widget doesn't own the primary selection, get it.
1226      */
1227     _DtHelpGetClearSelection(widget, client_data);
1228
1229     /*
1230      * check to see if we have the primary selection.
1231      */
1232     if (pDAS->primary == True)
1233       {
1234         _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_OFF, False, True,
1235                                 NULL, NULL, NULL, NULL, NULL);
1236         _DtCanvasProcessSelection(pDAS->canvas,
1237                         pDAS->timerX + pDAS->virtualX - pDAS->decorThickness,
1238                         pDAS->timerY + pDAS->firstVisible -pDAS->decorThickness,
1239                         _DtCvSELECTION_START);
1240
1241         pDAS->select_state  = _DtHelpSelectingText;
1242         pDAS->text_selected = True;
1243       }
1244
1245 }  /* End StartSelection */
1246
1247 /*****************************************************************************
1248  * Function: _DtHelpLoseSelectionCB
1249  *
1250  *    _DtHelpLoseSelectionCB - This routine is called when we lose the selection
1251  *
1252  *****************************************************************************/
1253 void
1254 _DtHelpLoseSelectionCB (
1255         Widget   widget,
1256         Atom    *selection )
1257 {
1258     Arg    args[2];
1259     DtHelpDispAreaStruct *pDAS;
1260
1261     XtSetArg(args[0], XmNuserData, &pDAS);
1262     XtGetValues(widget, args, 1);
1263
1264     if (pDAS != NULL && pDAS->dispWid == widget && *selection == XA_PRIMARY)
1265       {
1266         _DtHelpClearSelection ((XtPointer) pDAS);
1267         pDAS->primary       = False;
1268         pDAS->text_selected = False;
1269       }
1270 } /* End _DtHelpLoseSelectionCB */
1271
1272 /*****************************************************************************
1273  * Function: _DtHelpClearSelection
1274  *
1275  *    Clears the selection pointers and variables
1276  *
1277  *****************************************************************************/
1278 void
1279 _DtHelpClearSelection ( XtPointer client_data)
1280 {
1281     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) client_data;
1282
1283     if (pDAS->primary == True)
1284       {
1285         if (NULL != pDAS->canvas)
1286           {
1287             _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_OFF, False, True,
1288                                    NULL, NULL, NULL, NULL, NULL);
1289             _DtCanvasProcessSelection(pDAS->canvas, 0, 0, _DtCvSELECTION_CLEAR);
1290             _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ON, False, True,
1291                                    NULL, NULL, NULL, NULL, NULL);
1292           }
1293         pDAS->select_state  = _DtHelpNothingDoing;
1294         pDAS->text_selected = False;
1295       }
1296 }
1297
1298 /***************************************************************************
1299  * Function:  _DtHelpFocusCB
1300  *
1301  * _DtHelpFocusCB tracks the traversal of the hypertext.
1302  *
1303  **************************************************************************/
1304 void 
1305 _DtHelpFocusCB(
1306         Widget     widget,
1307         XtPointer  client_data,
1308         XEvent    *event )
1309 {
1310     Boolean                oldFlag;
1311     Boolean                newFlag = False;
1312     DtHelpDispAreaStruct  *pDAS = (DtHelpDispAreaStruct *) client_data;
1313
1314     if (pDAS->hyperCall == NULL ||
1315                 (event->type != FocusIn && event->type != FocusOut) ||
1316                 !event->xfocus.send_event)
1317         return;
1318
1319     /*
1320      * get the old flag
1321      */
1322     oldFlag = (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG) ? True : False;
1323
1324     /*
1325      * get the new flag
1326      */
1327     if (event->type == FocusIn)
1328         newFlag = True;
1329
1330     if (oldFlag != newFlag)
1331       {
1332         if (newFlag == False)
1333           {
1334             _DtCanvasMoveTraversal (pDAS->canvas, _DtCvTRAVERSAL_OFF, False,
1335                                 (XtIsRealized(widget) ? True : False),
1336                                 NULL, NULL, NULL, NULL, NULL);
1337             pDAS->neededFlags = pDAS->neededFlags & ~(_DT_HELP_FOCUS_FLAG);
1338           }
1339         else
1340           {
1341             pDAS->neededFlags = pDAS->neededFlags | _DT_HELP_FOCUS_FLAG;
1342             _DtCanvasMoveTraversal (pDAS->canvas, _DtCvTRAVERSAL_ON, False,
1343                                 (XtIsRealized(widget) ? True : False),
1344                                 NULL, NULL, NULL, NULL, NULL);
1345           }
1346       }
1347
1348 } /* End _DtHelpFocusCB */
1349
1350 /***************************************************************************
1351  * Function:  _DtHelpEnterLeaveCB
1352  *
1353  * _DtHelpEnterLeaveCB tracks the traversal of the hypertext.
1354  *
1355  **************************************************************************/
1356 void
1357 _DtHelpEnterLeaveCB(
1358         Widget     widget,
1359         XtPointer  client_data,
1360         XEvent    *event )
1361 {
1362     Boolean                oldFlag;
1363     Boolean                newFlag = False;
1364     DtHelpDispAreaStruct  *pDAS = (DtHelpDispAreaStruct *) client_data;
1365
1366     if (pDAS->hyperCall == NULL ||
1367                 (event->type != EnterNotify && event->type != LeaveNotify))
1368         return;
1369
1370     /*
1371      * get the old flag
1372      */
1373     oldFlag = (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG) ? True : False;
1374
1375     /*
1376      * get the new flag
1377      */
1378     if (event->type == FocusIn)
1379         newFlag = True;
1380
1381     if (oldFlag != newFlag)
1382       {
1383         if (oldFlag == True)
1384           {
1385             _DtCanvasMoveTraversal (pDAS->canvas, _DtCvTRAVERSAL_OFF, False,
1386                                 (XtIsRealized(widget) ? True : False),
1387                                 NULL, NULL, NULL, NULL, NULL);
1388             pDAS->neededFlags = pDAS->neededFlags & ~(_DT_HELP_FOCUS_FLAG);
1389           }
1390         else
1391           {
1392             pDAS->neededFlags = pDAS->neededFlags | _DT_HELP_FOCUS_FLAG;
1393             _DtCanvasMoveTraversal (pDAS->canvas, _DtCvTRAVERSAL_ON, False,
1394                                 (XtIsRealized(widget) ? True : False),
1395                                 NULL, NULL, NULL, NULL, NULL);
1396           }
1397       }
1398 } /* End _DtHelpEnterLeaveCB */
1399
1400 /***************************************************************************
1401  * Function:  _DtHelpVisibilityCB
1402  *
1403  * _DtHelpVisibilityCB tracks whether the window becomes obscured.
1404  *
1405  **************************************************************************/
1406 void 
1407 _DtHelpVisibilityCB(
1408         Widget     widget,
1409         XtPointer  client_data,
1410         XEvent    *event )
1411 {
1412     DtHelpDispAreaStruct  *pDAS = (DtHelpDispAreaStruct *) client_data;
1413
1414     if (event->type != VisibilityNotify)
1415         return;
1416
1417     /*
1418      * save the scrollbar and focus flags while clearing the visibility flags.
1419      */
1420     pDAS->neededFlags = pDAS->neededFlags &
1421                                 (_DT_HELP_FOCUS_FLAG | SCROLL_BAR_FLAGS);
1422
1423     /*
1424      * set the visibility flag
1425      */
1426     pDAS->neededFlags = pDAS->neededFlags |
1427                                 (1 << (event->xvisibility.state + 3));
1428
1429 } /* End _DtHelpVisibilityCB */
1430
1431 /*****************************************************************************
1432  * Function: _DtHelpInitiateClipboard
1433  *
1434  *    _DtHelpInitiateClipboard
1435  *
1436  *****************************************************************************/
1437 void
1438 _DtHelpInitiateClipboard (
1439     XtPointer  client_data)
1440 {
1441     DtHelpDispAreaStruct  *pDAS = (DtHelpDispAreaStruct *) client_data;
1442
1443     /*
1444      * check to see if we have the primary selection
1445      * before trying for the clipboard.
1446      */
1447     if (pDAS->primary == True && pDAS->text_selected == True)
1448       {
1449         long      itemId = 0L;                       /* clipboard item id */
1450         long      dataId = 0L;                       /* clipboard data id */
1451         int       status;                            /* clipboard status  */
1452         XmString  clipLabel;
1453         Display  *dpy = XtDisplay(pDAS->dispWid);
1454         Window    win = XtWindow(pDAS->dispWid);
1455         char     *atomName;
1456         char     *tmpString;
1457         XTextProperty tmpProp;
1458
1459         /*
1460          * get the selected text
1461          */
1462         _DtCanvasGetSelection (pDAS->canvas, 
1463                                 (_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
1464                                                 (_DtCvPointer *)(&tmpString));
1465
1466         /*
1467          * Using the Xm clipboard facilities,
1468          * copy the selected text to the clipboard
1469          */
1470         if (tmpString != NULL)
1471           {
1472             clipLabel = XmStringCreateLocalized ("DT_HELP");
1473
1474             /*
1475              * start copy to clipboard
1476              */
1477             status = XmClipboardStartCopy(dpy, win, clipLabel,
1478                                         XtLastTimestampProcessed(dpy),
1479                                         pDAS->dispWid, NULL, &itemId);
1480
1481             /*
1482              * no longer need the label
1483              */
1484             XmStringFree(clipLabel);
1485
1486             if (status != ClipboardSuccess)
1487               {
1488                 free(tmpString);
1489                 return;
1490               }
1491    
1492             status = XmbTextListToTextProperty(dpy, &tmpString, 1,
1493                                             (XICCEncodingStyle)XStdICCTextStyle,
1494                                             &tmpProp);
1495             /*
1496              * free the original copy of the string and check the results.
1497              */
1498             free(tmpString);
1499
1500             if (status != Success && status <= 0)
1501               {
1502                 XmClipboardCancelCopy(dpy, win, itemId);
1503                 return;
1504               }
1505
1506             atomName = XGetAtomName(dpy, tmpProp.encoding);
1507
1508             /* move the data to the clipboard */
1509             status = XmClipboardCopy(dpy, win, itemId, atomName,
1510                                   (XtPointer)tmpProp.value, tmpProp.nitems,
1511                                   0, &dataId);
1512
1513             XtFree(atomName);
1514
1515             if (status != ClipboardSuccess)
1516               {
1517                 XmClipboardCancelCopy(dpy, win, itemId);
1518                 XFree((char*)tmpProp.value);
1519                 return;
1520               }
1521
1522             /*
1523              * end the copy to the clipboard
1524              */
1525             status = XmClipboardEndCopy (dpy, win, itemId);
1526
1527             XFree((char*)tmpProp.value);
1528           }
1529       }
1530
1531 }  /* End _DtHelpInitiateClipboard */
1532
1533 /***************************************************************************
1534  * Function:  _DtHelpMoveBtnFocusCB
1535  *
1536  * _DtHelpMoveBtnFocusCB tracks the mouse movement for the Selection mechanism
1537  *
1538  **************************************************************************/
1539 void 
1540 _DtHelpMoveBtnFocusCB(
1541         Widget     widget,
1542         XtPointer  client_data,
1543         XEvent    *event )
1544 {
1545     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1546
1547     /*
1548      * if the policy is XmEXPLICIT, don't want the focus on the scrollbar
1549      */
1550     if (event->type == ButtonPress &&
1551               _XmGetFocusPolicy(XtParent(XtParent(pDAS->dispWid))) != XmPOINTER)
1552         XmProcessTraversal(pDAS->dispWid, XmTRAVERSE_CURRENT);
1553
1554 }
1555
1556 /*****************************************************************************
1557  * Function: _DtHelpGetClearSelection
1558  *
1559  *  _DtHelpGetClearSelection - If this routine is called,
1560  *            the user has initiated a selection.
1561  *
1562  *****************************************************************************/
1563  void
1564 _DtHelpGetClearSelection (
1565         Widget          widget,         /*  widget id               */
1566         XtPointer       client_data )   /*  data from applicaiton   */
1567 {
1568     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1569
1570     /*
1571      * If this widget doesn't own the primary selection, get it.
1572      */
1573     if (pDAS->primary != True)
1574       {
1575         if (XtOwnSelection (widget, XA_PRIMARY,
1576                         XtLastTimestampProcessed(XtDisplay(widget)),
1577                         (XtConvertSelectionProc) ConvertSelectionCB,
1578                         (XtLoseSelectionProc) _DtHelpLoseSelectionCB,
1579                         (XtSelectionDoneProc) NULL))
1580           {
1581             pDAS->primary = True;
1582             pDAS->anchor_time = XtLastTimestampProcessed(XtDisplay(widget));
1583           }
1584       }
1585     else
1586         _DtHelpClearSelection (client_data);
1587
1588 }  /* End _DtHelpGetClearSelection */