1 /* $XConsortium: Callbacks.c /main/21 1996/10/22 12:22:33 cde-hp $ */
2 /************************************<+>*************************************
3 ****************************************************************************
7 ** Project: Display Area Library
10 ** Description: This body of code handles the callbacks for the
13 ****************************************************************************
14 ************************************<+>*************************************/
16 * (c) Copyright 1996 Digital Equipment Corporation.
17 * (c) Copyright 1987-1994, 1996 Hewlett-Packard Company.
18 * (c) Copyright 1993, 1994, 1996 International Business Machines Corp.
19 * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.
20 * (c) Copyright 1993, 1994, 1996 Novell, Inc.
21 * (c) Copyright 1996 FUJITSU LIMITED.
22 * (c) Copyright 1996 Hitachi.
32 #include <X11/Xatom.h>
33 #include <X11/Intrinsic.h>
35 #include <Xm/AtomMgr.h>
36 #include <Xm/DrawnB.h>
37 #include <Xm/CutPaste.h>
48 #include "DisplayAreaP.h"
49 #include "CallbacksI.h"
51 #include "FontAttrI.h"
52 #include "HyperTextI.h"
55 #include "XInterfaceI.h"
60 /******** Private Function Declarations ********/
61 static Boolean ConvertSelectionCB (
67 unsigned long *length,
69 static void ScrollTimerCB (
70 XtPointer client_data,
72 static void StartSelection (
74 XtPointer client_data );
75 /******** End Private Function Declarations ********/
77 /******** Private Defines ********/
78 #define SCROLL_BAR_FLAGS 0x03
82 /******** End Private Defines ********/
84 /******** Private Variable Declarations ********/
86 /******** End Private Variable Declarations ********/
88 /******************************************************************************
90 ******************************************************************************/
91 /*****************************************************************************
92 * Function: ConvertSelectionCB
94 * ConvertSelectionCB - this routine is called when someone asks for
97 *****************************************************************************/
105 unsigned long *length,
108 Atom TARGETS = XmInternAtom(XtDisplay(widget), "TARGETS" , False);
109 Atom TIMESTAMP = XmInternAtom(XtDisplay(widget), "TIMESTAMP", False);
110 Atom TEXT = XmInternAtom(XtDisplay(widget), "TEXT" , False);
111 Atom CMP_TEXT = XmInternAtom(XtDisplay(widget), "COMPOUND_TEXT",False);
114 char *testString = "ABC"; /* these are characters in XPCS, so... safe */
115 char *tmpString = NULL;
117 DtHelpDispAreaStruct *pDAS;
119 XTextProperty tmpProp;
121 XtSetArg(args[0], XmNuserData, &pDAS);
122 XtGetValues(widget, args, 1);
124 if (pDAS == NULL || pDAS->primary == False || *selection != XA_PRIMARY)
127 retStatus = XmbTextListToTextProperty(XtDisplay(widget), &testString, 1,
128 (XICCEncodingStyle)XTextStyle, &tmpProp);
130 LOCALE = (Atom) 9999; /* XmbTextList... should always be able
131 * to convert XPCS characters; but in
132 * case its broken, this prevents a core
135 if (retStatus == Success)
137 LOCALE = tmpProp.encoding;
138 XFree(tmpProp.value);
142 * List the targets understood
144 if (*target == TARGETS)
146 Atom *targs = (Atom *)XtMalloc((unsigned) (5 * sizeof(Atom)));
148 *value = (char *) targs;
150 *targs++ = TIMESTAMP;
153 *targs++ = XA_STRING;
156 *length = (5 * sizeof(Atom)) >> 2;
159 else if (*target == TIMESTAMP)
162 timestamp = (Time *) XtMalloc(sizeof(Time));
163 *timestamp = pDAS->anchor_time;
165 *value = (char *) timestamp;
167 *length = sizeof(Time);
170 else if (*target == XA_STRING)
173 * initialize the return type here in case we fail
175 *type = (Atom) XA_STRING;
181 _DtCanvasGetSelection (pDAS->canvas,
182 (_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
183 (_DtCvPointer *)(&tmpString));
185 if (tmpString != NULL && *tmpString != '\0')
186 retStatus = XmbTextListToTextProperty(XtDisplay(widget),
188 (XICCEncodingStyle)XStringStyle, &tmpProp);
191 * free the original copy of the string and check the results
193 if (tmpString != NULL)
196 if (retStatus == Success || retStatus > 0)
198 *value = (XtPointer) tmpProp.value;
199 *length = tmpProp.nitems;
208 else if (*target == TEXT)
211 * set the type and format to those calculated
219 _DtCanvasGetSelection (pDAS->canvas,
220 (_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
221 (_DtCvPointer *)(&tmpString));
224 if (tmpString != NULL && *tmpString != '\0')
225 retStatus = XmbTextListToTextProperty(XtDisplay(widget),
227 (XICCEncodingStyle)XStdICCTextStyle, &tmpProp);
230 * free the original copy of the string and check the results
232 if (tmpString != NULL)
235 if (retStatus == Success || retStatus > 0)
237 *value = (XtPointer) tmpProp.value;
238 *length = tmpProp.nitems;
247 else if (*target == LOCALE)
250 * pass the string straight through
255 _DtCanvasGetSelection (pDAS->canvas,
256 (_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
257 (_DtCvPointer *)(value));
260 *length = strlen((char *)(*value));
262 else if (*target == CMP_TEXT)
268 * get the selected text.
270 _DtCanvasGetSelection (pDAS->canvas,
271 (_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
272 (_DtCvPointer *)(&tmpString));
275 if (tmpString != NULL && *tmpString != '\0')
276 retStatus = XmbTextListToTextProperty(XtDisplay(widget),
278 (XICCEncodingStyle)XCompoundTextStyle, &tmpProp);
281 * free the original copy of the string and check the results
283 if (tmpString != NULL)
286 if (retStatus == Success || retStatus > 0)
288 *value = (XtPointer) tmpProp.value;
289 *length = tmpProp.nitems;
303 } /* End ConvertSelectionCB */
305 /*****************************************************************************
306 * Function: ScrollTimerCB
308 * ScrollTimerCB - This routine is called when we have a timer
309 * go off with the mouse outside the Display Area during a
312 *****************************************************************************/
315 XtPointer client_data, /* data from applicaiton */
316 XtIntervalId *id ) /* timer id */
326 XmScrollBarCallbackStruct callData;
327 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
329 if (*id != pDAS->scr_timer_id)
332 pDAS->scr_timer_id = NULL;
334 maxY = pDAS->maxYpos;
335 dispY = pDAS->firstVisible + pDAS->dispUseHeight;
337 if ((pDAS->scr_timer_data.vertical_reason == XmCR_INCREMENT && maxY <= dispY)
339 (pDAS->scr_timer_data.vertical_reason == XmCR_DECREMENT &&
340 !pDAS->firstVisible))
341 pDAS->scr_timer_data.vertical_reason = XmCR_NONE;
343 if ((pDAS->scr_timer_data.horizontal_reason == XmCR_INCREMENT &&
344 pDAS->maxX <= pDAS->virtualX + ((int)pDAS->dispUseWidth))
346 (pDAS->scr_timer_data.horizontal_reason == XmCR_DECREMENT &&
348 pDAS->scr_timer_data.horizontal_reason = XmCR_NONE;
350 if ( pDAS->scr_timer_data.vertical_reason == XmCR_NONE &&
351 pDAS->scr_timer_data.horizontal_reason == XmCR_NONE)
354 y = pDAS->firstVisible;
355 if (pDAS->scr_timer_data.vertical_reason == XmCR_NONE)
356 y = pDAS->scr_timer_y - pDAS->decorThickness;
357 else if (pDAS->scr_timer_data.vertical_reason == XmCR_INCREMENT)
359 y = y + pDAS->dispUseHeight + pDAS->lineHeight;
360 if (y > pDAS->maxYpos)
363 diffY = y - pDAS->firstVisible - pDAS->dispUseHeight;
365 else if (pDAS->scr_timer_data.vertical_reason == XmCR_DECREMENT)
367 y -= pDAS->lineHeight;
371 diffY = y - pDAS->firstVisible;
374 if (pDAS->scr_timer_data.horizontal_reason == XmCR_NONE)
375 x = pDAS->scr_timer_x - pDAS->decorThickness;
378 if (pDAS->scr_timer_data.horizontal_reason == XmCR_INCREMENT)
380 diffX = (int) (pDAS->charWidth / 10);
381 x = pDAS->dispUseWidth;
383 if (x + pDAS->virtualX + diffX > pDAS->maxX)
384 diffX = pDAS->maxX - x - pDAS->virtualX;
386 else if (pDAS->scr_timer_data.horizontal_reason == XmCR_DECREMENT)
388 diffX = -((int)(pDAS->charWidth / 10));
391 if (pDAS->virtualX + diffX < 0)
392 diffX = -(pDAS->virtualX);
396 _DtCanvasProcessSelection (pDAS->canvas,
397 (x + diffX + pDAS->virtualX - pDAS->decorThickness),
398 y, _DtCvSELECTION_UPDATE);
400 callData.event = NULL;
403 scrollTimeOut = pDAS->horz_rep_scr;
404 callData.reason = pDAS->scr_timer_data.horizontal_reason;
405 callData.value = pDAS->virtualX + diffX;
406 _DtHelpHorzScrollCB (pDAS->horzScrollWid, client_data,
407 (XtPointer) &callData);
409 if (pDAS->horzScrollWid)
411 XtSetArg (args[0], XmNvalue, pDAS->virtualX);
412 XtSetValues (pDAS->horzScrollWid, args, 1);
415 if (diffY != 0 && pDAS->vertScrollWid)
417 XtSetArg (args[0], XmNvalue, y);
418 XtSetValues (pDAS->vertScrollWid, args, 1);
419 if (pDAS->vScrollNotify)
420 (pDAS->vScrollNotify)(pDAS->clientData, y);
425 scrollTimeOut = pDAS->vert_rep_scr;
426 callData.reason = pDAS->scr_timer_data.vertical_reason;
427 callData.value = pDAS->firstVisible + diffY;
428 _DtHelpVertScrollCB (pDAS->vertScrollWid, client_data,
429 (XtPointer) &callData);
431 if (pDAS->vertScrollWid)
433 XtSetArg (args[0], XmNvalue, pDAS->firstVisible);
434 XtSetValues (pDAS->vertScrollWid, args, 1);
435 if (pDAS->vScrollNotify)
436 (pDAS->vScrollNotify)(pDAS->clientData, pDAS->firstVisible);
440 pDAS->scr_timer_id = XtAppAddTimeOut (
441 XtWidgetToApplicationContext (pDAS->dispWid),
442 ((unsigned long) scrollTimeOut),
443 ScrollTimerCB, client_data);
445 } /* End ScrollTimerCB */
447 /******************************************************************************
448 * Function: DrawWholeCanvas
450 *****************************************************************************/
453 DtHelpDispAreaStruct *pDAS)
460 _DtCanvasMoveTraversal(pDAS->canvas,_DtCvTRAVERSAL_OFF, False,
461 (XtIsRealized(pDAS->dispWid) ? True : False),
462 NULL, NULL, NULL, NULL, NULL);
464 top = pDAS->firstVisible;
465 bottom = top + pDAS->dispUseHeight;
466 right = pDAS->virtualX + pDAS->dispUseWidth;
468 _DtCanvasRender (pDAS->canvas, pDAS->virtualX, top, right, bottom,
469 pDAS->render_type, _DtCvTRUE, NULL, &next_y);
470 pDAS->nextNonVisible =
471 (pDAS->render_type == _DtCvRENDER_PARTIAL) ? bottom : next_y;
474 * If we have a hypertext link boxed, draw it
476 _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ON, False,
477 (XtIsRealized(pDAS->dispWid) ? True : False),
478 NULL, NULL, NULL, NULL, NULL);
480 * if the toc exists within this area, draw it.
482 if ((pDAS->toc_flag & _DT_HELP_TOC_ON) &&
483 pDAS->toc_y + pDAS->toc_height >= top && pDAS->toc_y < bottom)
484 _DtHelpDATocMarker((XtPointer) pDAS, True);
486 } /* End DrawWholeCanvas */
488 /******************************************************************************
489 * Semi Public Functions
490 *****************************************************************************/
491 /******************************************************************************
492 * Function: _DtHelpCleanAndDrawWholeCanvas
494 *****************************************************************************/
496 _DtHelpCleanAndDrawWholeCanvas(
497 XtPointer client_data)
499 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
501 XClearArea (XtDisplay(pDAS->dispWid), XtWindow(pDAS->dispWid),
502 pDAS->decorThickness, pDAS->decorThickness,
506 DrawWholeCanvas (pDAS);
511 _DtHelpSearchMoveTraversal(XtPointer client_data, int search_hit_index)
513 _DtCvUnit baseline, ascend, descend;
515 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
517 if (_DtCvGetSearchLineMetrics(pDAS->canvas, search_hit_index,
518 &baseline, &descend, &ascend) == 0) {
520 _DtCvUnit top, hitY, height;
522 top = pDAS->firstVisible;
523 hitY = baseline - ascend - pDAS->lineThickness;
524 height = ascend + descend + 2 * pDAS->lineThickness;
528 else if (hitY + height > top + ((int) pDAS->dispUseHeight))
529 top = hitY + height - ((int) pDAS->dispUseHeight);
531 if (top != pDAS->firstVisible) {
533 _DtCvUnit dispUseHeightHalf =
534 pDAS->dispUseHeight / 2 + pDAS->dispUseHeight % 2;
536 /* put search hit in the middle of the viewport */
538 top -= dispUseHeightHalf - height;
540 top += dispUseHeightHalf + height;
541 if (top + ((int)pDAS->dispUseHeight) > pDAS->maxYpos)
542 top = pDAS->maxYpos - pDAS->dispUseHeight;
547 if (top != pDAS->firstVisible) {
551 pDAS->firstVisible = top;
553 XtSetArg(arg, XmNvalue, pDAS->firstVisible);
554 XtSetValues(pDAS->vertScrollWid, &arg, 1);
556 if (pDAS->vScrollNotify)
557 (pDAS->vScrollNotify)(pDAS->clientData, pDAS->firstVisible);
559 _DtHelpCleanAndDrawWholeCanvas(pDAS);
565 /******************************************************************************
566 * Function: _DtHelpCancelSelection
568 * Returns : True if a selection was active and cancelled.
569 * False if a selection was not active.
571 *****************************************************************************/
573 _DtHelpCancelSelection(
574 XtPointer client_data)
576 Boolean selActive = False;
577 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
579 if (pDAS->select_state == _DtHelpSelectingText && pDAS->primary == True)
582 if (pDAS->scr_timer_id)
584 XtRemoveTimeOut (pDAS->scr_timer_id);
585 pDAS->scr_timer_id = NULL;
587 _DtHelpClearSelection (client_data);
593 /******************************************************************************
595 *****************************************************************************/
596 /******************************************************************************
597 * Function: _DtHelpExposeCB
599 * _DtHelpExposeCB handles the exposure events for a Text Graphic Area.
601 *****************************************************************************/
605 XtPointer client_data,
606 XtPointer call_data )
613 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
615 XmDrawnButtonCallbackStruct *callback =
616 (XmDrawnButtonCallbackStruct *) call_data;
618 if (callback->reason != XmCR_EXPOSE ||
619 (pDAS->neededFlags & (1 << (VisibilityFullyObscured + 3))))
623 * get the width and height.
625 XtSetArg(args[0], XmNwidth, &width);
626 XtSetArg(args[1], XmNheight, &height);
627 XtGetValues(widget, args, 2);
630 * if this exposure is a result of a resize,
631 * wait for the resize to handle it.
633 if (width != pDAS->dispWidth || height != pDAS->dispHeight)
636 if (!(callback->event) || callback->event->xexpose.count)
640 * re-draw the information in the display area
642 DrawWholeCanvas (pDAS);
644 } /* End _DtHelpExposeCB */
646 /*********************************************************************
647 * Function: _DtHelpResizeCB
649 * _DtHelpResizeCB handles the exposure events for a Text Graphic Area.
651 *********************************************************************/
655 XtPointer client_data,
656 XtPointer call_data )
662 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
663 XmDrawnButtonCallbackStruct *callback =
664 (XmDrawnButtonCallbackStruct *) call_data;
666 if (callback->reason != XmCR_RESIZE)
670 * get the width and height of the form.
672 XtSetArg(args[0], XmNwidth, &width);
673 XtSetArg(args[1], XmNheight, &height);
674 XtGetValues(XtParent(widget), args, 2);
675 if (width == pDAS->formWidth && height == pDAS->formHeight)
678 pDAS->formWidth = width;
679 pDAS->formHeight = height;
682 * get the width and height.
684 XtSetArg(args[0], XmNwidth, &width);
685 XtSetArg(args[1], XmNheight, &height);
686 XtGetValues(widget, args, 2);
688 if (width == pDAS->dispWidth && height == pDAS->dispHeight)
693 _DtHelpClearSelection (pDAS);
694 * reset the scroll bars and possibly reformat the text for the size.
696 (void) _DtHelpSetScrollBars (client_data, width, height);
697 if (XtIsRealized (pDAS->dispWid))
698 _DtHelpCleanAndDrawWholeCanvas (client_data);
701 * I will get an expose event after the resize.
704 } /* End _DtHelpResizeCB */
706 /***************************************************************************
707 * Function: _DtHelpVertScrollCB
709 * _DtHelpVertScrollCB is called when the vertical scroll bar is changed.
711 **************************************************************************/
715 XtPointer clientData,
718 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) clientData;
719 XmScrollBarCallbackStruct *callBack =
720 (XmScrollBarCallbackStruct *) callData;
721 int diff = pDAS->lineHeight;
724 int reason = callBack->reason;
731 * if the policy is XmEXPLICIT, don't want the focus on the scrollbar
733 if (callBack->event != NULL && callBack->event->type == ButtonPress &&
734 _XmGetFocusPolicy(XtParent(XtParent(pDAS->dispWid))) != XmPOINTER)
735 XmProcessTraversal(pDAS->dispWid, XmTRAVERSE_CURRENT);
738 * check to make sure we don't do a rerender when we don't have to.
740 if (pDAS->firstVisible == callBack->value)
743 /* If a drag occured, reset the reason to increment, decrement, page */
744 /* increment, or page decrement depending on the distance and direction */
746 if (callBack->reason == XmCR_DRAG || callBack->reason == XmCR_VALUE_CHANGED)
748 diff = callBack->value - pDAS->firstVisible;
750 if (diff > 0 && diff <= ((int) pDAS->dispUseHeight))
751 reason = XmCR_INCREMENT;
752 else if (diff < 0 && -(diff) <= ((int) pDAS->dispUseHeight))
754 reason = XmCR_DECREMENT;
757 else if (diff > ((int) pDAS->dispUseHeight))
758 reason = XmCR_PAGE_DECREMENT;
760 reason = XmCR_PAGE_INCREMENT;
762 else if (callBack->reason == XmCR_INCREMENT ||
763 callBack->reason == XmCR_DECREMENT)
765 diff = callBack->value - pDAS->firstVisible;
770 /* Reset first visible to the returned scrollbar value. */
771 pDAS->firstVisible = callBack->value;
773 /* For page increment and decrement, call _DtHelpCleanAndDrawWholeCanvas
774 * to clear the view area and redisplay the text.
776 * For increment and decrement,
777 * use XCopyArea to move the visible lines and draw the cleared out line.
779 if (!pDAS->maxYpos ||
780 (pDAS->neededFlags & (1 << (VisibilityFullyObscured + 3))))
783 dpy = XtDisplay (widget);
784 win = XtWindow (pDAS->dispWid);
786 if (reason == XmCR_PAGE_INCREMENT || reason == XmCR_PAGE_DECREMENT ||
787 reason == XmCR_TO_TOP || reason == XmCR_TO_BOTTOM)
788 _DtHelpCleanAndDrawWholeCanvas (clientData);
791 if (reason == XmCR_INCREMENT)
793 dstY = pDAS->decorThickness;
795 clearY = pDAS->dispHeight - pDAS->decorThickness - diff;
799 srcY = pDAS->decorThickness;
803 XCopyArea(dpy, win, win, pDAS->normalGC, pDAS->decorThickness, srcY,
804 pDAS->dispUseWidth, (pDAS->dispUseHeight - diff),
805 pDAS->decorThickness, dstY);
807 XClearArea(dpy, win, pDAS->decorThickness, clearY,
808 pDAS->dispUseWidth, ((unsigned int) diff), False);
810 if (pDAS->neededFlags & (1 << (VisibilityPartiallyObscured + 3)))
813 * redraw all the information
815 DrawWholeCanvas (pDAS);
820 * draw the line that sits on the cleared line
822 absTop = clearY + pDAS->firstVisible - pDAS->decorThickness;
823 absBot = absTop + diff;
825 _DtCanvasRender (pDAS->canvas, 0, absTop,
826 pDAS->virtualX + pDAS->dispWidth, absBot,
827 _DtCvRENDER_PARTIAL, _DtCvFALSE, NULL, NULL);
829 * if the toc exists within this area, draw it.
831 if ((pDAS->toc_flag & _DT_HELP_TOC_ON)
832 && pDAS->toc_y + pDAS->toc_height >= absTop
833 && pDAS->toc_y < absBot)
834 _DtHelpDATocMarker((XtPointer) pDAS, True);
838 } /* End _DtHelpVertScrollCB */
840 /***************************************************************************
841 * Function: _DtHelpHorzScrollCB
843 * _DtHelpHorzScrollCB is called when the horizontal scroll bar is changed.
845 **************************************************************************/
849 XtPointer clientData,
852 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) clientData;
853 XmScrollBarCallbackStruct *callBack =
854 (XmScrollBarCallbackStruct *) callData;
855 int diff = (int)(pDAS->charWidth / 10);
859 int reason = callBack->reason;
867 * if the policy is XmEXPLICIT, don't want the focus on the scrollbar
869 if (callBack->event != NULL && callBack->event->type == ButtonPress &&
870 _XmGetFocusPolicy(XtParent(XtParent(pDAS->dispWid))) != XmPOINTER)
871 XmProcessTraversal(pDAS->dispWid, XmTRAVERSE_CURRENT);
874 * check to make sure we don't do a rerender when we don't have to.
876 if (pDAS->virtualX == callBack->value)
879 /* If a drag occured, reset the reason to increment, decrement, page */
880 /* increment, or page decrement depending on the distance and direction */
882 if (callBack->reason == XmCR_DRAG || callBack->reason == XmCR_VALUE_CHANGED)
884 diff = callBack->value - pDAS->virtualX;
886 if (diff > 0 && diff <= ((int) pDAS->dispUseWidth))
887 reason = XmCR_INCREMENT;
888 else if (diff < 0 && -(diff) <= ((int) pDAS->dispUseWidth))
890 reason = XmCR_DECREMENT;
893 else if (diff > ((int) pDAS->dispUseWidth))
894 reason = XmCR_PAGE_DECREMENT;
896 reason = XmCR_PAGE_INCREMENT;
898 else if (callBack->reason == XmCR_INCREMENT ||
899 callBack->reason == XmCR_DECREMENT)
901 diff = callBack->value - pDAS->virtualX;
906 /* Reset first visible to the returned scrollbar value. */
907 pDAS->virtualX = callBack->value;
909 /* For page increment and decrement, call _DtHelpCleanAndDrawWholeCanvas
910 * to clear the view area and redisplay the text.
912 * For increment and decrement,
913 * use XCopyArea to move the visible lines and draw the cleared out line.
915 if (!pDAS->maxX || !pDAS->visibleCount ||
916 (pDAS->neededFlags & (1 << (VisibilityFullyObscured + 3))))
919 dpy = XtDisplay (widget);
920 win = XtWindow (pDAS->dispWid);
922 /* For page increment and decrement, clear the view area and call
923 * View_DtHelpExposeCB to redisplay the text. For increment and decrement,
924 * use XCopyArea to move the visible lines and draw the cleared out line.
926 if (reason == XmCR_PAGE_INCREMENT || reason == XmCR_PAGE_DECREMENT ||
927 reason == XmCR_TO_TOP || reason == XmCR_TO_BOTTOM)
928 _DtHelpCleanAndDrawWholeCanvas (clientData);
931 if (reason == XmCR_INCREMENT)
933 dstX = pDAS->decorThickness;
935 clearX = pDAS->dispWidth - pDAS->decorThickness - diff;
939 srcX = pDAS->decorThickness;
944 XCopyArea(dpy, win, win, pDAS->normalGC, srcX, pDAS->decorThickness,
945 pDAS->dispUseWidth - diff, pDAS->dispUseHeight,
946 dstX, pDAS->decorThickness);
948 XClearArea(dpy, win, clearX, pDAS->decorThickness,
949 ((unsigned int) diff), pDAS->dispUseHeight, False);
951 if (pDAS->neededFlags & (1 << (VisibilityPartiallyObscured + 3)))
954 * redraw all the information
956 DrawWholeCanvas (pDAS);
961 * draw the line that sits on the cleared line
963 absLeft = clearX + pDAS->virtualX - pDAS->decorThickness;
964 absRight = absLeft + diff;
965 absY = pDAS->firstVisible - pDAS->decorThickness;
967 _DtCanvasRender (pDAS->canvas, absLeft, absY,
968 absRight, absY + pDAS->dispHeight,
969 _DtCvRENDER_PARTIAL, _DtCvFALSE, NULL, NULL);
972 * if the toc exists within this area, draw it.
974 if ((pDAS->toc_flag & _DT_HELP_TOC_ON)
975 && ((int) (pDAS->toc_y + pDAS->toc_height)) >= ((int) absY)
976 && ((int) pDAS->toc_y) < ((int) (absY + pDAS->dispHeight)))
977 _DtHelpDATocMarker((XtPointer) pDAS, True);
982 } /* End _DtHelpHorzScrollCB */
984 /***************************************************************************
985 * Function: _DtHelpClickOrSelectCB
987 * _DtHelpClickOrSelectCB is called when the vertical scroll bar is changed.
989 **************************************************************************/
991 _DtHelpClickOrSelectCB(
993 XtPointer clientData,
996 XmDrawnButtonCallbackStruct *callBack =
997 (XmDrawnButtonCallbackStruct *) callData;
998 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) clientData;
1001 * If this is not an ARM call or entered through an Arm&Activate
1002 * (event-type will be keypress or keyrelease) throw it away.
1004 if (callBack->reason != XmCR_ARM || callBack->event == NULL ||
1005 callBack->event->type == KeyPress ||
1006 callBack->event->type == KeyRelease)
1009 pDAS->timerX = callBack->event->xbutton.x;
1010 pDAS->timerY = callBack->event->xbutton.y;
1011 pDAS->select_state = _DtHelpCopyOrLink;
1013 if (NULL != pDAS->armCallback)
1014 (pDAS->armCallback)(pDAS->clientData);
1016 } /* End _DtHelpClickOrSelectCB */
1018 /*****************************************************************************
1019 * Function: _DtHelpEndSelectionCB
1022 * Called by: Callback for the Selection mechanism
1023 *****************************************************************************/
1025 _DtHelpEndSelectionCB (
1026 Widget w, /* widget id */
1027 XtPointer client_data, /* data from applicaiton */
1028 XtPointer call_data ) /* data from widget class */
1030 XmDrawnButtonCallbackStruct *callback =
1031 (XmDrawnButtonCallbackStruct *) call_data;
1032 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) client_data;
1036 if (callback->reason != XmCR_DISARM || callback->event == NULL ||
1037 callback->event->type == KeyPress ||
1038 callback->event->type == KeyRelease)
1042 * if a scroll timer is active, we are selecting text.
1045 if (pDAS->scr_timer_id)
1047 XtRemoveTimeOut (pDAS->scr_timer_id);
1048 pDAS->scr_timer_id = NULL;
1051 newX = callback->event->xbutton.x;
1052 newY = callback->event->xbutton.y;
1053 if (pDAS->select_state == _DtHelpCopyOrLink)
1055 if (abs (pDAS->timerX - newX) <= pDAS->moveThreshold &&
1056 abs (pDAS->timerY - newY) <= pDAS->moveThreshold)
1058 _DtHelpClearSelection (client_data);
1061 * If this is null, we came the the Arm&Activate routine
1062 * which means a key was pressed, so we ignore this call.
1064 if (callback->event)
1066 * find the hypertext link and process it.
1068 _DtHelpProcessHyperSelection (client_data,
1069 pDAS->timerX, pDAS->timerY,
1073 StartSelection (w, client_data);
1078 * The user was doing a selection, finish it up.
1080 if (pDAS->select_state != _DtHelpNothingDoing)
1082 _DtCanvasProcessSelection(pDAS->canvas,
1083 (newX + pDAS->virtualX - pDAS->decorThickness),
1084 (newY + pDAS->firstVisible - pDAS->decorThickness),
1085 _DtCvSELECTION_END);
1086 _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ON, False, True,
1087 NULL, NULL, NULL, NULL, NULL);
1091 pDAS->select_state = _DtHelpNothingDoing;
1094 } /* End _DtHelpEndSelectionCB */
1096 /***************************************************************************
1097 * Function: _DtHelpMouseMoveCB
1099 * _DtHelpMouseMoveCB tracks the mouse movement for the Selection mechanism
1101 **************************************************************************/
1105 XtPointer client_data,
1110 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1113 * If a selection is not in progress, don't do anything.
1115 if (pDAS->select_state == _DtHelpNothingDoing || event->type != MotionNotify)
1118 if (pDAS->scr_timer_id)
1120 XtRemoveTimeOut (pDAS->scr_timer_id);
1121 pDAS->scr_timer_id = NULL;
1124 newX = event->xmotion.x;
1125 newY = event->xmotion.y;
1127 if (pDAS->select_state == _DtHelpCopyOrLink)
1129 if (abs (newX - pDAS->timerX) < pDAS->moveThreshold &&
1130 abs (newY - pDAS->timerY) < pDAS->moveThreshold)
1133 StartSelection (widget, client_data);
1137 if (newY < ((int) pDAS->decorThickness) && pDAS->firstVisible)
1138 pDAS->scr_timer_data.vertical_reason = XmCR_DECREMENT;
1141 (((int) pDAS->dispHeight)-((int)pDAS->decorThickness))) &&
1143 (((int)pDAS->firstVisible)
1144 + ((int)pDAS->dispUseHeight))))
1145 pDAS->scr_timer_data.vertical_reason = XmCR_INCREMENT;
1147 pDAS->scr_timer_data.vertical_reason = XmCR_NONE;
1149 if (newX < ((int) pDAS->decorThickness) && pDAS->virtualX)
1150 pDAS->scr_timer_data.horizontal_reason = XmCR_DECREMENT;
1151 else if (newX > ((int) pDAS->dispWidth) &&
1152 pDAS->maxX > pDAS->virtualX + ((int) pDAS->dispUseWidth))
1153 pDAS->scr_timer_data.horizontal_reason = XmCR_INCREMENT;
1155 pDAS->scr_timer_data.horizontal_reason = XmCR_NONE;
1157 if (pDAS->scr_timer_data.vertical_reason != XmCR_NONE ||
1158 pDAS->scr_timer_data.horizontal_reason != XmCR_NONE)
1160 int scrollTimeOut = pDAS->vert_init_scr;
1162 if (pDAS->scr_timer_data.horizontal_reason != XmCR_NONE)
1163 scrollTimeOut = pDAS->horz_init_scr;
1165 pDAS->scr_timer_x = newX;
1166 pDAS->scr_timer_y = newY;
1167 pDAS->scr_timer_id =
1168 XtAppAddTimeOut(XtWidgetToApplicationContext(widget),
1169 ((unsigned long) scrollTimeOut),
1170 ScrollTimerCB, (XtPointer) pDAS);
1174 newX = newX + pDAS->virtualX - pDAS->decorThickness;
1178 newY = newY + pDAS->firstVisible - pDAS->decorThickness;
1182 _DtCanvasProcessSelection(pDAS->canvas, newX, newY, _DtCvSELECTION_UPDATE);
1184 } /* End _DtHelpMouseMoveCB */
1186 /*****************************************************************************
1187 * Function: StartSelection
1189 * StartSelection - If this routine is called, the user has initiated a
1192 *****************************************************************************/
1195 Widget widget, /* widget id */
1196 XtPointer client_data ) /* data from applicaiton */
1198 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) client_data;
1201 * If this widget doesn't own the primary selection, get it.
1203 _DtHelpGetClearSelection(widget, client_data);
1206 * check to see if we have the primary selection.
1208 if (pDAS->primary == True)
1210 _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_OFF, False, True,
1211 NULL, NULL, NULL, NULL, NULL);
1212 _DtCanvasProcessSelection(pDAS->canvas,
1213 pDAS->timerX + pDAS->virtualX - pDAS->decorThickness,
1214 pDAS->timerY + pDAS->firstVisible -pDAS->decorThickness,
1215 _DtCvSELECTION_START);
1217 pDAS->select_state = _DtHelpSelectingText;
1218 pDAS->text_selected = True;
1221 } /* End StartSelection */
1223 /*****************************************************************************
1224 * Function: _DtHelpLoseSelectionCB
1226 * _DtHelpLoseSelectionCB - This routine is called when we lose the selection
1228 *****************************************************************************/
1230 _DtHelpLoseSelectionCB (
1235 DtHelpDispAreaStruct *pDAS;
1237 XtSetArg(args[0], XmNuserData, &pDAS);
1238 XtGetValues(widget, args, 1);
1240 if (pDAS != NULL && pDAS->dispWid == widget && *selection == XA_PRIMARY)
1242 _DtHelpClearSelection ((XtPointer) pDAS);
1243 pDAS->primary = False;
1244 pDAS->text_selected = False;
1246 } /* End _DtHelpLoseSelectionCB */
1248 /*****************************************************************************
1249 * Function: _DtHelpClearSelection
1251 * Clears the selection pointers and variables
1253 *****************************************************************************/
1255 _DtHelpClearSelection ( XtPointer client_data)
1257 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) client_data;
1259 if (pDAS->primary == True)
1261 if (NULL != pDAS->canvas)
1263 _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_OFF, False, True,
1264 NULL, NULL, NULL, NULL, NULL);
1265 _DtCanvasProcessSelection(pDAS->canvas, 0, 0, _DtCvSELECTION_CLEAR);
1266 _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ON, False, True,
1267 NULL, NULL, NULL, NULL, NULL);
1269 pDAS->select_state = _DtHelpNothingDoing;
1270 pDAS->text_selected = False;
1274 /***************************************************************************
1275 * Function: _DtHelpFocusCB
1277 * _DtHelpFocusCB tracks the traversal of the hypertext.
1279 **************************************************************************/
1283 XtPointer client_data,
1287 Boolean newFlag = False;
1288 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1290 if (pDAS->hyperCall == NULL ||
1291 (event->type != FocusIn && event->type != FocusOut) ||
1292 !event->xfocus.send_event)
1298 oldFlag = (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG) ? True : False;
1303 if (event->type == FocusIn)
1306 if (oldFlag != newFlag)
1308 if (newFlag == False)
1310 _DtCanvasMoveTraversal (pDAS->canvas, _DtCvTRAVERSAL_OFF, False,
1311 (XtIsRealized(widget) ? True : False),
1312 NULL, NULL, NULL, NULL, NULL);
1313 pDAS->neededFlags = pDAS->neededFlags & ~(_DT_HELP_FOCUS_FLAG);
1317 pDAS->neededFlags = pDAS->neededFlags | _DT_HELP_FOCUS_FLAG;
1318 _DtCanvasMoveTraversal (pDAS->canvas, _DtCvTRAVERSAL_ON, False,
1319 (XtIsRealized(widget) ? True : False),
1320 NULL, NULL, NULL, NULL, NULL);
1324 } /* End _DtHelpFocusCB */
1326 /***************************************************************************
1327 * Function: _DtHelpEnterLeaveCB
1329 * _DtHelpEnterLeaveCB tracks the traversal of the hypertext.
1331 **************************************************************************/
1333 _DtHelpEnterLeaveCB(
1335 XtPointer client_data,
1339 Boolean newFlag = False;
1340 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1342 if (pDAS->hyperCall == NULL ||
1343 (event->type != EnterNotify && event->type != LeaveNotify))
1349 oldFlag = (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG) ? True : False;
1354 if (event->type == FocusIn)
1357 if (oldFlag != newFlag)
1359 if (oldFlag == True)
1361 _DtCanvasMoveTraversal (pDAS->canvas, _DtCvTRAVERSAL_OFF, False,
1362 (XtIsRealized(widget) ? True : False),
1363 NULL, NULL, NULL, NULL, NULL);
1364 pDAS->neededFlags = pDAS->neededFlags & ~(_DT_HELP_FOCUS_FLAG);
1368 pDAS->neededFlags = pDAS->neededFlags | _DT_HELP_FOCUS_FLAG;
1369 _DtCanvasMoveTraversal (pDAS->canvas, _DtCvTRAVERSAL_ON, False,
1370 (XtIsRealized(widget) ? True : False),
1371 NULL, NULL, NULL, NULL, NULL);
1374 } /* End _DtHelpEnterLeaveCB */
1376 /***************************************************************************
1377 * Function: _DtHelpVisibilityCB
1379 * _DtHelpVisibilityCB tracks whether the window becomes obscured.
1381 **************************************************************************/
1383 _DtHelpVisibilityCB(
1385 XtPointer client_data,
1388 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1390 if (event->type != VisibilityNotify)
1394 * save the scrollbar and focus flags while clearing the visibility flags.
1396 pDAS->neededFlags = pDAS->neededFlags &
1397 (_DT_HELP_FOCUS_FLAG | SCROLL_BAR_FLAGS);
1400 * set the visibility flag
1402 pDAS->neededFlags = pDAS->neededFlags |
1403 (1 << (event->xvisibility.state + 3));
1405 } /* End _DtHelpVisibilityCB */
1407 /*****************************************************************************
1408 * Function: _DtHelpInitiateClipboard
1410 * _DtHelpInitiateClipboard
1412 *****************************************************************************/
1414 _DtHelpInitiateClipboard (
1415 XtPointer client_data)
1417 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1420 * check to see if we have the primary selection
1421 * before trying for the clipboard.
1423 if (pDAS->primary == True && pDAS->text_selected == True)
1425 long itemId = 0L; /* clipboard item id */
1426 long dataId = 0L; /* clipboard data id */
1427 int status; /* clipboard status */
1429 Display *dpy = XtDisplay(pDAS->dispWid);
1430 Window win = XtWindow(pDAS->dispWid);
1433 XTextProperty tmpProp;
1436 * get the selected text
1438 _DtCanvasGetSelection (pDAS->canvas,
1439 (_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
1440 (_DtCvPointer *)(&tmpString));
1443 * Using the Xm clipboard facilities,
1444 * copy the selected text to the clipboard
1446 if (tmpString != NULL)
1448 clipLabel = XmStringCreateLocalized ("DT_HELP");
1451 * start copy to clipboard
1453 status = XmClipboardStartCopy(dpy, win, clipLabel,
1454 XtLastTimestampProcessed(dpy),
1455 pDAS->dispWid, NULL, &itemId);
1458 * no longer need the label
1460 XmStringFree(clipLabel);
1462 if (status != ClipboardSuccess)
1468 status = XmbTextListToTextProperty(dpy, &tmpString, 1,
1469 (XICCEncodingStyle)XStdICCTextStyle,
1472 * free the original copy of the string and check the results.
1476 if (status != Success && status <= 0)
1478 XmClipboardCancelCopy(dpy, win, itemId);
1482 atomName = XGetAtomName(dpy, tmpProp.encoding);
1484 /* move the data to the clipboard */
1485 status = XmClipboardCopy(dpy, win, itemId, atomName,
1486 (XtPointer)tmpProp.value, tmpProp.nitems,
1491 if (status != ClipboardSuccess)
1493 XmClipboardCancelCopy(dpy, win, itemId);
1494 XFree((char*)tmpProp.value);
1499 * end the copy to the clipboard
1501 status = XmClipboardEndCopy (dpy, win, itemId);
1503 XFree((char*)tmpProp.value);
1507 } /* End _DtHelpInitiateClipboard */
1509 /***************************************************************************
1510 * Function: _DtHelpMoveBtnFocusCB
1512 * _DtHelpMoveBtnFocusCB tracks the mouse movement for the Selection mechanism
1514 **************************************************************************/
1516 _DtHelpMoveBtnFocusCB(
1518 XtPointer client_data,
1521 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1524 * if the policy is XmEXPLICIT, don't want the focus on the scrollbar
1526 if (event->type == ButtonPress &&
1527 _XmGetFocusPolicy(XtParent(XtParent(pDAS->dispWid))) != XmPOINTER)
1528 XmProcessTraversal(pDAS->dispWid, XmTRAVERSE_CURRENT);
1532 /*****************************************************************************
1533 * Function: _DtHelpGetClearSelection
1535 * _DtHelpGetClearSelection - If this routine is called,
1536 * the user has initiated a selection.
1538 *****************************************************************************/
1540 _DtHelpGetClearSelection (
1541 Widget widget, /* widget id */
1542 XtPointer client_data ) /* data from applicaiton */
1544 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1547 * If this widget doesn't own the primary selection, get it.
1549 if (pDAS->primary != True)
1551 if (XtOwnSelection (widget, XA_PRIMARY,
1552 XtLastTimestampProcessed(XtDisplay(widget)),
1553 (XtConvertSelectionProc) ConvertSelectionCB,
1554 (XtLoseSelectionProc) _DtHelpLoseSelectionCB,
1555 (XtSelectionDoneProc) NULL))
1557 pDAS->primary = True;
1558 pDAS->anchor_time = XtLastTimestampProcessed(XtDisplay(widget));
1562 _DtHelpClearSelection (client_data);
1564 } /* End _DtHelpGetClearSelection */