2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $XConsortium: Callbacks.c /main/21 1996/10/22 12:22:33 cde-hp $ */
24 /************************************<+>*************************************
25 ****************************************************************************
29 ** Project: Display Area Library
32 ** Description: This body of code handles the callbacks for the
35 ****************************************************************************
36 ************************************<+>*************************************/
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.
54 #include <X11/Xatom.h>
55 #include <X11/Intrinsic.h>
57 #include <Xm/AtomMgr.h>
58 #include <Xm/DrawnB.h>
59 #include <Xm/CutPaste.h>
60 #include <Xm/XmPrivate.h>
72 #include "DisplayAreaP.h"
73 #include "CallbacksI.h"
75 #include "FontAttrI.h"
76 #include "HyperTextI.h"
79 #include "XInterfaceI.h"
84 /******** Private Function Declarations ********/
85 static Boolean ConvertSelectionCB (
91 unsigned long *length,
93 static void ScrollTimerCB (
94 XtPointer client_data,
96 static void StartSelection (
98 XtPointer client_data );
99 /******** End Private Function Declarations ********/
101 /******** Private Defines ********/
102 #define SCROLL_BAR_FLAGS 0x03
106 /******** End Private Defines ********/
108 /******** Private Variable Declarations ********/
110 /******** End Private Variable Declarations ********/
112 /******************************************************************************
114 ******************************************************************************/
115 /*****************************************************************************
116 * Function: ConvertSelectionCB
118 * ConvertSelectionCB - this routine is called when someone asks for
121 *****************************************************************************/
129 unsigned long *length,
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);
138 char *testString = "ABC"; /* these are characters in XPCS, so... safe */
139 char *tmpString = NULL;
141 DtHelpDispAreaStruct *pDAS;
143 XTextProperty tmpProp;
145 XtSetArg(args[0], XmNuserData, &pDAS);
146 XtGetValues(widget, args, 1);
148 if (pDAS == NULL || pDAS->primary == False || *selection != XA_PRIMARY)
151 retStatus = XmbTextListToTextProperty(XtDisplay(widget), &testString, 1,
152 (XICCEncodingStyle)XTextStyle, &tmpProp);
154 LOCALE = (Atom) 9999; /* XmbTextList... should always be able
155 * to convert XPCS characters; but in
156 * case its broken, this prevents a core
159 if (retStatus == Success)
161 LOCALE = tmpProp.encoding;
162 XFree(tmpProp.value);
166 * List the targets understood
168 if (*target == TARGETS)
170 Atom *targs = (Atom *)XtMalloc((unsigned) (5 * sizeof(Atom)));
172 *value = (char *) targs;
174 *targs++ = TIMESTAMP;
177 *targs++ = XA_STRING;
180 *length = (5 * sizeof(Atom)) >> 2;
183 else if (*target == TIMESTAMP)
186 timestamp = (Time *) XtMalloc(sizeof(Time));
187 *timestamp = pDAS->anchor_time;
189 *value = (char *) timestamp;
191 *length = sizeof(Time);
194 else if (*target == XA_STRING)
197 * initialize the return type here in case we fail
199 *type = (Atom) XA_STRING;
205 _DtCanvasGetSelection (pDAS->canvas,
206 (_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
207 (_DtCvPointer *)(&tmpString));
209 if (tmpString != NULL && *tmpString != '\0')
210 retStatus = XmbTextListToTextProperty(XtDisplay(widget),
212 (XICCEncodingStyle)XStringStyle, &tmpProp);
215 * free the original copy of the string and check the results
217 if (tmpString != NULL)
220 if (retStatus == Success || retStatus > 0)
222 *value = (XtPointer) tmpProp.value;
223 *length = tmpProp.nitems;
232 else if (*target == TEXT)
235 * set the type and format to those calculated
243 _DtCanvasGetSelection (pDAS->canvas,
244 (_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
245 (_DtCvPointer *)(&tmpString));
248 if (tmpString != NULL && *tmpString != '\0')
249 retStatus = XmbTextListToTextProperty(XtDisplay(widget),
251 (XICCEncodingStyle)XStdICCTextStyle, &tmpProp);
254 * free the original copy of the string and check the results
256 if (tmpString != NULL)
259 if (retStatus == Success || retStatus > 0)
261 *value = (XtPointer) tmpProp.value;
262 *length = tmpProp.nitems;
271 else if (*target == LOCALE)
274 * pass the string straight through
279 _DtCanvasGetSelection (pDAS->canvas,
280 (_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
281 (_DtCvPointer *)(value));
284 *length = strlen((char *)(*value));
286 else if (*target == CMP_TEXT)
292 * get the selected text.
294 _DtCanvasGetSelection (pDAS->canvas,
295 (_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
296 (_DtCvPointer *)(&tmpString));
299 if (tmpString != NULL && *tmpString != '\0')
300 retStatus = XmbTextListToTextProperty(XtDisplay(widget),
302 (XICCEncodingStyle)XCompoundTextStyle, &tmpProp);
305 * free the original copy of the string and check the results
307 if (tmpString != NULL)
310 if (retStatus == Success || retStatus > 0)
312 *value = (XtPointer) tmpProp.value;
313 *length = tmpProp.nitems;
327 } /* End ConvertSelectionCB */
329 /*****************************************************************************
330 * Function: ScrollTimerCB
332 * ScrollTimerCB - This routine is called when we have a timer
333 * go off with the mouse outside the Display Area during a
336 *****************************************************************************/
339 XtPointer client_data, /* data from applicaiton */
340 XtIntervalId *id ) /* timer id */
350 XmScrollBarCallbackStruct callData;
351 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
353 if (*id != pDAS->scr_timer_id)
356 pDAS->scr_timer_id = 0;
358 maxY = pDAS->maxYpos;
359 dispY = pDAS->firstVisible + pDAS->dispUseHeight;
361 if ((pDAS->scr_timer_data.vertical_reason == XmCR_INCREMENT && maxY <= dispY)
363 (pDAS->scr_timer_data.vertical_reason == XmCR_DECREMENT &&
364 !pDAS->firstVisible))
365 pDAS->scr_timer_data.vertical_reason = XmCR_NONE;
367 if ((pDAS->scr_timer_data.horizontal_reason == XmCR_INCREMENT &&
368 pDAS->maxX <= pDAS->virtualX + ((int)pDAS->dispUseWidth))
370 (pDAS->scr_timer_data.horizontal_reason == XmCR_DECREMENT &&
372 pDAS->scr_timer_data.horizontal_reason = XmCR_NONE;
374 if ( pDAS->scr_timer_data.vertical_reason == XmCR_NONE &&
375 pDAS->scr_timer_data.horizontal_reason == XmCR_NONE)
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)
383 y = y + pDAS->dispUseHeight + pDAS->lineHeight;
384 if (y > pDAS->maxYpos)
387 diffY = y - pDAS->firstVisible - pDAS->dispUseHeight;
389 else if (pDAS->scr_timer_data.vertical_reason == XmCR_DECREMENT)
391 y -= pDAS->lineHeight;
395 diffY = y - pDAS->firstVisible;
398 if (pDAS->scr_timer_data.horizontal_reason == XmCR_NONE)
399 x = pDAS->scr_timer_x - pDAS->decorThickness;
402 if (pDAS->scr_timer_data.horizontal_reason == XmCR_INCREMENT)
404 diffX = (int) (pDAS->charWidth / 10);
405 x = pDAS->dispUseWidth;
407 if (x + pDAS->virtualX + diffX > pDAS->maxX)
408 diffX = pDAS->maxX - x - pDAS->virtualX;
410 else if (pDAS->scr_timer_data.horizontal_reason == XmCR_DECREMENT)
412 diffX = -((int)(pDAS->charWidth / 10));
415 if (pDAS->virtualX + diffX < 0)
416 diffX = -(pDAS->virtualX);
420 _DtCanvasProcessSelection (pDAS->canvas,
421 (x + diffX + pDAS->virtualX - pDAS->decorThickness),
422 y, _DtCvSELECTION_UPDATE);
424 callData.event = NULL;
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);
433 if (pDAS->horzScrollWid)
435 XtSetArg (args[0], XmNvalue, pDAS->virtualX);
436 XtSetValues (pDAS->horzScrollWid, args, 1);
439 if (diffY != 0 && pDAS->vertScrollWid)
441 XtSetArg (args[0], XmNvalue, y);
442 XtSetValues (pDAS->vertScrollWid, args, 1);
443 if (pDAS->vScrollNotify)
444 (pDAS->vScrollNotify)(pDAS->clientData, y);
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);
455 if (pDAS->vertScrollWid)
457 XtSetArg (args[0], XmNvalue, pDAS->firstVisible);
458 XtSetValues (pDAS->vertScrollWid, args, 1);
459 if (pDAS->vScrollNotify)
460 (pDAS->vScrollNotify)(pDAS->clientData, pDAS->firstVisible);
464 pDAS->scr_timer_id = XtAppAddTimeOut (
465 XtWidgetToApplicationContext (pDAS->dispWid),
466 ((unsigned long) scrollTimeOut),
467 ScrollTimerCB, client_data);
469 } /* End ScrollTimerCB */
471 /******************************************************************************
472 * Function: DrawWholeCanvas
474 *****************************************************************************/
477 DtHelpDispAreaStruct *pDAS)
484 _DtCanvasMoveTraversal(pDAS->canvas,_DtCvTRAVERSAL_OFF, False,
485 (XtIsRealized(pDAS->dispWid) ? True : False),
486 NULL, NULL, NULL, NULL, NULL);
488 top = pDAS->firstVisible;
489 bottom = top + pDAS->dispUseHeight;
490 right = pDAS->virtualX + pDAS->dispUseWidth;
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;
498 * If we have a hypertext link boxed, draw it
500 _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ON, False,
501 (XtIsRealized(pDAS->dispWid) ? True : False),
502 NULL, NULL, NULL, NULL, NULL);
504 * if the toc exists within this area, draw it.
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);
510 } /* End DrawWholeCanvas */
512 /******************************************************************************
513 * Semi Public Functions
514 *****************************************************************************/
515 /******************************************************************************
516 * Function: _DtHelpCleanAndDrawWholeCanvas
518 *****************************************************************************/
520 _DtHelpCleanAndDrawWholeCanvas(
521 XtPointer client_data)
523 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
525 XClearArea (XtDisplay(pDAS->dispWid), XtWindow(pDAS->dispWid),
526 pDAS->decorThickness, pDAS->decorThickness,
530 DrawWholeCanvas (pDAS);
535 _DtHelpSearchMoveTraversal(XtPointer client_data, int search_hit_index)
537 _DtCvUnit baseline, ascend, descend;
539 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
541 if (_DtCvGetSearchLineMetrics(pDAS->canvas, search_hit_index,
542 &baseline, &descend, &ascend) == 0) {
544 _DtCvUnit top, hitY, height;
546 top = pDAS->firstVisible;
547 hitY = baseline - ascend - pDAS->lineThickness;
548 height = ascend + descend + 2 * pDAS->lineThickness;
552 else if (hitY + height > top + ((int) pDAS->dispUseHeight))
553 top = hitY + height - ((int) pDAS->dispUseHeight);
555 if (top != pDAS->firstVisible) {
557 _DtCvUnit dispUseHeightHalf =
558 pDAS->dispUseHeight / 2 + pDAS->dispUseHeight % 2;
560 /* put search hit in the middle of the viewport */
562 top -= dispUseHeightHalf - height;
564 top += dispUseHeightHalf + height;
565 if (top + ((int)pDAS->dispUseHeight) > pDAS->maxYpos)
566 top = pDAS->maxYpos - pDAS->dispUseHeight;
571 if (top != pDAS->firstVisible) {
575 pDAS->firstVisible = top;
577 XtSetArg(arg, XmNvalue, pDAS->firstVisible);
578 XtSetValues(pDAS->vertScrollWid, &arg, 1);
580 if (pDAS->vScrollNotify)
581 (pDAS->vScrollNotify)(pDAS->clientData, pDAS->firstVisible);
583 _DtHelpCleanAndDrawWholeCanvas(pDAS);
589 /******************************************************************************
590 * Function: _DtHelpCancelSelection
592 * Returns : True if a selection was active and cancelled.
593 * False if a selection was not active.
595 *****************************************************************************/
597 _DtHelpCancelSelection(
598 XtPointer client_data)
600 Boolean selActive = False;
601 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
603 if (pDAS->select_state == _DtHelpSelectingText && pDAS->primary == True)
606 if (pDAS->scr_timer_id)
608 XtRemoveTimeOut (pDAS->scr_timer_id);
609 pDAS->scr_timer_id = 0;
611 _DtHelpClearSelection (client_data);
617 /******************************************************************************
619 *****************************************************************************/
620 /******************************************************************************
621 * Function: _DtHelpExposeCB
623 * _DtHelpExposeCB handles the exposure events for a Text Graphic Area.
625 *****************************************************************************/
629 XtPointer client_data,
630 XtPointer call_data )
637 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
639 XmDrawnButtonCallbackStruct *callback =
640 (XmDrawnButtonCallbackStruct *) call_data;
642 if (callback->reason != XmCR_EXPOSE ||
643 (pDAS->neededFlags & (1 << (VisibilityFullyObscured + 3))))
647 * get the width and height.
649 XtSetArg(args[0], XmNwidth, &width);
650 XtSetArg(args[1], XmNheight, &height);
651 XtGetValues(widget, args, 2);
654 * if this exposure is a result of a resize,
655 * wait for the resize to handle it.
657 if (width != pDAS->dispWidth || height != pDAS->dispHeight)
660 if (!(callback->event) || callback->event->xexpose.count)
664 * re-draw the information in the display area
666 DrawWholeCanvas (pDAS);
668 } /* End _DtHelpExposeCB */
670 /*********************************************************************
671 * Function: _DtHelpResizeCB
673 * _DtHelpResizeCB handles the exposure events for a Text Graphic Area.
675 *********************************************************************/
679 XtPointer client_data,
680 XtPointer call_data )
686 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
687 XmDrawnButtonCallbackStruct *callback =
688 (XmDrawnButtonCallbackStruct *) call_data;
690 if (callback->reason != XmCR_RESIZE)
694 * get the width and height of the form.
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)
702 pDAS->formWidth = width;
703 pDAS->formHeight = height;
706 * get the width and height.
708 XtSetArg(args[0], XmNwidth, &width);
709 XtSetArg(args[1], XmNheight, &height);
710 XtGetValues(widget, args, 2);
712 if (width == pDAS->dispWidth && height == pDAS->dispHeight)
717 _DtHelpClearSelection (pDAS);
718 * reset the scroll bars and possibly reformat the text for the size.
720 (void) _DtHelpSetScrollBars (client_data, width, height);
721 if (XtIsRealized (pDAS->dispWid))
722 _DtHelpCleanAndDrawWholeCanvas (client_data);
725 * I will get an expose event after the resize.
728 } /* End _DtHelpResizeCB */
730 /***************************************************************************
731 * Function: _DtHelpVertScrollCB
733 * _DtHelpVertScrollCB is called when the vertical scroll bar is changed.
735 **************************************************************************/
739 XtPointer clientData,
742 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) clientData;
743 XmScrollBarCallbackStruct *callBack =
744 (XmScrollBarCallbackStruct *) callData;
745 int diff = pDAS->lineHeight;
748 int reason = callBack->reason;
755 * if the policy is XmEXPLICIT, don't want the focus on the scrollbar
757 if (callBack->event != NULL && callBack->event->type == ButtonPress &&
758 _XmGetFocusPolicy(XtParent(XtParent(pDAS->dispWid))) != XmPOINTER)
759 XmProcessTraversal(pDAS->dispWid, XmTRAVERSE_CURRENT);
762 * check to make sure we don't do a rerender when we don't have to.
764 if (pDAS->firstVisible == callBack->value)
767 /* If a drag occured, reset the reason to increment, decrement, page */
768 /* increment, or page decrement depending on the distance and direction */
770 if (callBack->reason == XmCR_DRAG || callBack->reason == XmCR_VALUE_CHANGED)
772 diff = callBack->value - pDAS->firstVisible;
774 if (diff > 0 && diff <= ((int) pDAS->dispUseHeight))
775 reason = XmCR_INCREMENT;
776 else if (diff < 0 && -(diff) <= ((int) pDAS->dispUseHeight))
778 reason = XmCR_DECREMENT;
781 else if (diff > ((int) pDAS->dispUseHeight))
782 reason = XmCR_PAGE_DECREMENT;
784 reason = XmCR_PAGE_INCREMENT;
786 else if (callBack->reason == XmCR_INCREMENT ||
787 callBack->reason == XmCR_DECREMENT)
789 diff = callBack->value - pDAS->firstVisible;
794 /* Reset first visible to the returned scrollbar value. */
795 pDAS->firstVisible = callBack->value;
797 /* For page increment and decrement, call _DtHelpCleanAndDrawWholeCanvas
798 * to clear the view area and redisplay the text.
800 * For increment and decrement,
801 * use XCopyArea to move the visible lines and draw the cleared out line.
803 if (!pDAS->maxYpos ||
804 (pDAS->neededFlags & (1 << (VisibilityFullyObscured + 3))))
807 dpy = XtDisplay (widget);
808 win = XtWindow (pDAS->dispWid);
810 if (reason == XmCR_PAGE_INCREMENT || reason == XmCR_PAGE_DECREMENT ||
811 reason == XmCR_TO_TOP || reason == XmCR_TO_BOTTOM)
812 _DtHelpCleanAndDrawWholeCanvas (clientData);
815 if (reason == XmCR_INCREMENT)
817 dstY = pDAS->decorThickness;
819 clearY = pDAS->dispHeight - pDAS->decorThickness - diff;
823 srcY = pDAS->decorThickness;
827 XCopyArea(dpy, win, win, pDAS->normalGC, pDAS->decorThickness, srcY,
828 pDAS->dispUseWidth, (pDAS->dispUseHeight - diff),
829 pDAS->decorThickness, dstY);
831 XClearArea(dpy, win, pDAS->decorThickness, clearY,
832 pDAS->dispUseWidth, ((unsigned int) diff), False);
834 if (pDAS->neededFlags & (1 << (VisibilityPartiallyObscured + 3)))
837 * redraw all the information
839 DrawWholeCanvas (pDAS);
844 * draw the line that sits on the cleared line
846 absTop = clearY + pDAS->firstVisible - pDAS->decorThickness;
847 absBot = absTop + diff;
849 _DtCanvasRender (pDAS->canvas, 0, absTop,
850 pDAS->virtualX + pDAS->dispWidth, absBot,
851 _DtCvRENDER_PARTIAL, _DtCvFALSE, NULL, NULL);
853 * if the toc exists within this area, draw it.
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);
862 } /* End _DtHelpVertScrollCB */
864 /***************************************************************************
865 * Function: _DtHelpHorzScrollCB
867 * _DtHelpHorzScrollCB is called when the horizontal scroll bar is changed.
869 **************************************************************************/
873 XtPointer clientData,
876 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) clientData;
877 XmScrollBarCallbackStruct *callBack =
878 (XmScrollBarCallbackStruct *) callData;
879 int diff = (int)(pDAS->charWidth / 10);
883 int reason = callBack->reason;
891 * if the policy is XmEXPLICIT, don't want the focus on the scrollbar
893 if (callBack->event != NULL && callBack->event->type == ButtonPress &&
894 _XmGetFocusPolicy(XtParent(XtParent(pDAS->dispWid))) != XmPOINTER)
895 XmProcessTraversal(pDAS->dispWid, XmTRAVERSE_CURRENT);
898 * check to make sure we don't do a rerender when we don't have to.
900 if (pDAS->virtualX == callBack->value)
903 /* If a drag occured, reset the reason to increment, decrement, page */
904 /* increment, or page decrement depending on the distance and direction */
906 if (callBack->reason == XmCR_DRAG || callBack->reason == XmCR_VALUE_CHANGED)
908 diff = callBack->value - pDAS->virtualX;
910 if (diff > 0 && diff <= ((int) pDAS->dispUseWidth))
911 reason = XmCR_INCREMENT;
912 else if (diff < 0 && -(diff) <= ((int) pDAS->dispUseWidth))
914 reason = XmCR_DECREMENT;
917 else if (diff > ((int) pDAS->dispUseWidth))
918 reason = XmCR_PAGE_DECREMENT;
920 reason = XmCR_PAGE_INCREMENT;
922 else if (callBack->reason == XmCR_INCREMENT ||
923 callBack->reason == XmCR_DECREMENT)
925 diff = callBack->value - pDAS->virtualX;
930 /* Reset first visible to the returned scrollbar value. */
931 pDAS->virtualX = callBack->value;
933 /* For page increment and decrement, call _DtHelpCleanAndDrawWholeCanvas
934 * to clear the view area and redisplay the text.
936 * For increment and decrement,
937 * use XCopyArea to move the visible lines and draw the cleared out line.
939 if (!pDAS->maxX || !pDAS->visibleCount ||
940 (pDAS->neededFlags & (1 << (VisibilityFullyObscured + 3))))
943 dpy = XtDisplay (widget);
944 win = XtWindow (pDAS->dispWid);
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.
950 if (reason == XmCR_PAGE_INCREMENT || reason == XmCR_PAGE_DECREMENT ||
951 reason == XmCR_TO_TOP || reason == XmCR_TO_BOTTOM)
952 _DtHelpCleanAndDrawWholeCanvas (clientData);
955 if (reason == XmCR_INCREMENT)
957 dstX = pDAS->decorThickness;
959 clearX = pDAS->dispWidth - pDAS->decorThickness - diff;
963 srcX = pDAS->decorThickness;
968 XCopyArea(dpy, win, win, pDAS->normalGC, srcX, pDAS->decorThickness,
969 pDAS->dispUseWidth - diff, pDAS->dispUseHeight,
970 dstX, pDAS->decorThickness);
972 XClearArea(dpy, win, clearX, pDAS->decorThickness,
973 ((unsigned int) diff), pDAS->dispUseHeight, False);
975 if (pDAS->neededFlags & (1 << (VisibilityPartiallyObscured + 3)))
978 * redraw all the information
980 DrawWholeCanvas (pDAS);
985 * draw the line that sits on the cleared line
987 absLeft = clearX + pDAS->virtualX - pDAS->decorThickness;
988 absRight = absLeft + diff;
989 absY = pDAS->firstVisible - pDAS->decorThickness;
991 _DtCanvasRender (pDAS->canvas, absLeft, absY,
992 absRight, absY + pDAS->dispHeight,
993 _DtCvRENDER_PARTIAL, _DtCvFALSE, NULL, NULL);
996 * if the toc exists within this area, draw it.
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);
1006 } /* End _DtHelpHorzScrollCB */
1008 /***************************************************************************
1009 * Function: _DtHelpClickOrSelectCB
1011 * _DtHelpClickOrSelectCB is called when the vertical scroll bar is changed.
1013 **************************************************************************/
1015 _DtHelpClickOrSelectCB(
1017 XtPointer clientData,
1018 XtPointer callData )
1020 XmDrawnButtonCallbackStruct *callBack =
1021 (XmDrawnButtonCallbackStruct *) callData;
1022 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) clientData;
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.
1028 if (callBack->reason != XmCR_ARM || callBack->event == NULL ||
1029 callBack->event->type == KeyPress ||
1030 callBack->event->type == KeyRelease)
1033 pDAS->timerX = callBack->event->xbutton.x;
1034 pDAS->timerY = callBack->event->xbutton.y;
1035 pDAS->select_state = _DtHelpCopyOrLink;
1037 if (NULL != pDAS->armCallback)
1038 (pDAS->armCallback)(pDAS->clientData);
1040 } /* End _DtHelpClickOrSelectCB */
1042 /*****************************************************************************
1043 * Function: _DtHelpEndSelectionCB
1046 * Called by: Callback for the Selection mechanism
1047 *****************************************************************************/
1049 _DtHelpEndSelectionCB (
1050 Widget w, /* widget id */
1051 XtPointer client_data, /* data from applicaiton */
1052 XtPointer call_data ) /* data from widget class */
1054 XmDrawnButtonCallbackStruct *callback =
1055 (XmDrawnButtonCallbackStruct *) call_data;
1056 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) client_data;
1060 if (callback->reason != XmCR_DISARM || callback->event == NULL ||
1061 callback->event->type == KeyPress ||
1062 callback->event->type == KeyRelease)
1066 * if a scroll timer is active, we are selecting text.
1069 if (pDAS->scr_timer_id)
1071 XtRemoveTimeOut (pDAS->scr_timer_id);
1072 pDAS->scr_timer_id = 0;
1075 newX = callback->event->xbutton.x;
1076 newY = callback->event->xbutton.y;
1077 if (pDAS->select_state == _DtHelpCopyOrLink)
1079 if (abs (pDAS->timerX - newX) <= pDAS->moveThreshold &&
1080 abs (pDAS->timerY - newY) <= pDAS->moveThreshold)
1082 _DtHelpClearSelection (client_data);
1085 * If this is null, we came the the Arm&Activate routine
1086 * which means a key was pressed, so we ignore this call.
1088 if (callback->event)
1090 * find the hypertext link and process it.
1092 _DtHelpProcessHyperSelection (client_data,
1093 pDAS->timerX, pDAS->timerY,
1097 StartSelection (w, client_data);
1102 * The user was doing a selection, finish it up.
1104 if (pDAS->select_state != _DtHelpNothingDoing)
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);
1115 pDAS->select_state = _DtHelpNothingDoing;
1118 } /* End _DtHelpEndSelectionCB */
1120 /***************************************************************************
1121 * Function: _DtHelpMouseMoveCB
1123 * _DtHelpMouseMoveCB tracks the mouse movement for the Selection mechanism
1125 **************************************************************************/
1129 XtPointer client_data,
1134 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1137 * If a selection is not in progress, don't do anything.
1139 if (pDAS->select_state == _DtHelpNothingDoing || event->type != MotionNotify)
1142 if (pDAS->scr_timer_id)
1144 XtRemoveTimeOut (pDAS->scr_timer_id);
1145 pDAS->scr_timer_id = 0;
1148 newX = event->xmotion.x;
1149 newY = event->xmotion.y;
1151 if (pDAS->select_state == _DtHelpCopyOrLink)
1153 if (abs (newX - pDAS->timerX) < pDAS->moveThreshold &&
1154 abs (newY - pDAS->timerY) < pDAS->moveThreshold)
1157 StartSelection (widget, client_data);
1161 if (newY < ((int) pDAS->decorThickness) && pDAS->firstVisible)
1162 pDAS->scr_timer_data.vertical_reason = XmCR_DECREMENT;
1165 (((int) pDAS->dispHeight)-((int)pDAS->decorThickness))) &&
1167 (((int)pDAS->firstVisible)
1168 + ((int)pDAS->dispUseHeight))))
1169 pDAS->scr_timer_data.vertical_reason = XmCR_INCREMENT;
1171 pDAS->scr_timer_data.vertical_reason = XmCR_NONE;
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;
1179 pDAS->scr_timer_data.horizontal_reason = XmCR_NONE;
1181 if (pDAS->scr_timer_data.vertical_reason != XmCR_NONE ||
1182 pDAS->scr_timer_data.horizontal_reason != XmCR_NONE)
1184 int scrollTimeOut = pDAS->vert_init_scr;
1186 if (pDAS->scr_timer_data.horizontal_reason != XmCR_NONE)
1187 scrollTimeOut = pDAS->horz_init_scr;
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);
1198 newX = newX + pDAS->virtualX - pDAS->decorThickness;
1202 newY = newY + pDAS->firstVisible - pDAS->decorThickness;
1206 _DtCanvasProcessSelection(pDAS->canvas, newX, newY, _DtCvSELECTION_UPDATE);
1208 } /* End _DtHelpMouseMoveCB */
1210 /*****************************************************************************
1211 * Function: StartSelection
1213 * StartSelection - If this routine is called, the user has initiated a
1216 *****************************************************************************/
1219 Widget widget, /* widget id */
1220 XtPointer client_data ) /* data from applicaiton */
1222 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) client_data;
1225 * If this widget doesn't own the primary selection, get it.
1227 _DtHelpGetClearSelection(widget, client_data);
1230 * check to see if we have the primary selection.
1232 if (pDAS->primary == True)
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);
1241 pDAS->select_state = _DtHelpSelectingText;
1242 pDAS->text_selected = True;
1245 } /* End StartSelection */
1247 /*****************************************************************************
1248 * Function: _DtHelpLoseSelectionCB
1250 * _DtHelpLoseSelectionCB - This routine is called when we lose the selection
1252 *****************************************************************************/
1254 _DtHelpLoseSelectionCB (
1259 DtHelpDispAreaStruct *pDAS;
1261 XtSetArg(args[0], XmNuserData, &pDAS);
1262 XtGetValues(widget, args, 1);
1264 if (pDAS != NULL && pDAS->dispWid == widget && *selection == XA_PRIMARY)
1266 _DtHelpClearSelection ((XtPointer) pDAS);
1267 pDAS->primary = False;
1268 pDAS->text_selected = False;
1270 } /* End _DtHelpLoseSelectionCB */
1272 /*****************************************************************************
1273 * Function: _DtHelpClearSelection
1275 * Clears the selection pointers and variables
1277 *****************************************************************************/
1279 _DtHelpClearSelection ( XtPointer client_data)
1281 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) client_data;
1283 if (pDAS->primary == True)
1285 if (NULL != pDAS->canvas)
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);
1293 pDAS->select_state = _DtHelpNothingDoing;
1294 pDAS->text_selected = False;
1298 /***************************************************************************
1299 * Function: _DtHelpFocusCB
1301 * _DtHelpFocusCB tracks the traversal of the hypertext.
1303 **************************************************************************/
1307 XtPointer client_data,
1311 Boolean newFlag = False;
1312 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1314 if (pDAS->hyperCall == NULL ||
1315 (event->type != FocusIn && event->type != FocusOut) ||
1316 !event->xfocus.send_event)
1322 oldFlag = (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG) ? True : False;
1327 if (event->type == FocusIn)
1330 if (oldFlag != newFlag)
1332 if (newFlag == False)
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);
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);
1348 } /* End _DtHelpFocusCB */
1350 /***************************************************************************
1351 * Function: _DtHelpEnterLeaveCB
1353 * _DtHelpEnterLeaveCB tracks the traversal of the hypertext.
1355 **************************************************************************/
1357 _DtHelpEnterLeaveCB(
1359 XtPointer client_data,
1363 Boolean newFlag = False;
1364 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1366 if (pDAS->hyperCall == NULL ||
1367 (event->type != EnterNotify && event->type != LeaveNotify))
1373 oldFlag = (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG) ? True : False;
1378 if (event->type == FocusIn)
1381 if (oldFlag != newFlag)
1383 if (oldFlag == True)
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);
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);
1398 } /* End _DtHelpEnterLeaveCB */
1400 /***************************************************************************
1401 * Function: _DtHelpVisibilityCB
1403 * _DtHelpVisibilityCB tracks whether the window becomes obscured.
1405 **************************************************************************/
1407 _DtHelpVisibilityCB(
1409 XtPointer client_data,
1412 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1414 if (event->type != VisibilityNotify)
1418 * save the scrollbar and focus flags while clearing the visibility flags.
1420 pDAS->neededFlags = pDAS->neededFlags &
1421 (_DT_HELP_FOCUS_FLAG | SCROLL_BAR_FLAGS);
1424 * set the visibility flag
1426 pDAS->neededFlags = pDAS->neededFlags |
1427 (1 << (event->xvisibility.state + 3));
1429 } /* End _DtHelpVisibilityCB */
1431 /*****************************************************************************
1432 * Function: _DtHelpInitiateClipboard
1434 * _DtHelpInitiateClipboard
1436 *****************************************************************************/
1438 _DtHelpInitiateClipboard (
1439 XtPointer client_data)
1441 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1444 * check to see if we have the primary selection
1445 * before trying for the clipboard.
1447 if (pDAS->primary == True && pDAS->text_selected == True)
1449 long itemId = 0L; /* clipboard item id */
1450 long dataId = 0L; /* clipboard data id */
1451 int status; /* clipboard status */
1453 Display *dpy = XtDisplay(pDAS->dispWid);
1454 Window win = XtWindow(pDAS->dispWid);
1457 XTextProperty tmpProp;
1460 * get the selected text
1462 _DtCanvasGetSelection (pDAS->canvas,
1463 (_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
1464 (_DtCvPointer *)(&tmpString));
1467 * Using the Xm clipboard facilities,
1468 * copy the selected text to the clipboard
1470 if (tmpString != NULL)
1472 clipLabel = XmStringCreateLocalized ("DT_HELP");
1475 * start copy to clipboard
1477 status = XmClipboardStartCopy(dpy, win, clipLabel,
1478 XtLastTimestampProcessed(dpy),
1479 pDAS->dispWid, NULL, &itemId);
1482 * no longer need the label
1484 XmStringFree(clipLabel);
1486 if (status != ClipboardSuccess)
1492 status = XmbTextListToTextProperty(dpy, &tmpString, 1,
1493 (XICCEncodingStyle)XStdICCTextStyle,
1496 * free the original copy of the string and check the results.
1500 if (status != Success && status <= 0)
1502 XmClipboardCancelCopy(dpy, win, itemId);
1506 atomName = XGetAtomName(dpy, tmpProp.encoding);
1508 /* move the data to the clipboard */
1509 status = XmClipboardCopy(dpy, win, itemId, atomName,
1510 (XtPointer)tmpProp.value, tmpProp.nitems,
1515 if (status != ClipboardSuccess)
1517 XmClipboardCancelCopy(dpy, win, itemId);
1518 XFree((char*)tmpProp.value);
1523 * end the copy to the clipboard
1525 status = XmClipboardEndCopy (dpy, win, itemId);
1527 XFree((char*)tmpProp.value);
1531 } /* End _DtHelpInitiateClipboard */
1533 /***************************************************************************
1534 * Function: _DtHelpMoveBtnFocusCB
1536 * _DtHelpMoveBtnFocusCB tracks the mouse movement for the Selection mechanism
1538 **************************************************************************/
1540 _DtHelpMoveBtnFocusCB(
1542 XtPointer client_data,
1545 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1548 * if the policy is XmEXPLICIT, don't want the focus on the scrollbar
1550 if (event->type == ButtonPress &&
1551 _XmGetFocusPolicy(XtParent(XtParent(pDAS->dispWid))) != XmPOINTER)
1552 XmProcessTraversal(pDAS->dispWid, XmTRAVERSE_CURRENT);
1556 /*****************************************************************************
1557 * Function: _DtHelpGetClearSelection
1559 * _DtHelpGetClearSelection - If this routine is called,
1560 * the user has initiated a selection.
1562 *****************************************************************************/
1564 _DtHelpGetClearSelection (
1565 Widget widget, /* widget id */
1566 XtPointer client_data ) /* data from applicaiton */
1568 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
1571 * If this widget doesn't own the primary selection, get it.
1573 if (pDAS->primary != True)
1575 if (XtOwnSelection (widget, XA_PRIMARY,
1576 XtLastTimestampProcessed(XtDisplay(widget)),
1577 (XtConvertSelectionProc) ConvertSelectionCB,
1578 (XtLoseSelectionProc) _DtHelpLoseSelectionCB,
1579 (XtSelectionDoneProc) NULL))
1581 pDAS->primary = True;
1582 pDAS->anchor_time = XtLastTimestampProcessed(XtDisplay(widget));
1586 _DtHelpClearSelection (client_data);
1588 } /* End _DtHelpGetClearSelection */