mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
1586 lines
44 KiB
C
1586 lines
44 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these librararies and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* $XConsortium: Callbacks.c /main/21 1996/10/22 12:22:33 cde-hp $ */
|
|
/************************************<+>*************************************
|
|
****************************************************************************
|
|
**
|
|
** File: Callbacks.c
|
|
**
|
|
** Project: Display Area Library
|
|
**
|
|
**
|
|
** Description: This body of code handles the callbacks for the
|
|
** Display Area.
|
|
**
|
|
****************************************************************************
|
|
************************************<+>*************************************/
|
|
/*
|
|
* (c) Copyright 1996 Digital Equipment Corporation.
|
|
* (c) Copyright 1987-1994, 1996 Hewlett-Packard Company.
|
|
* (c) Copyright 1993, 1994, 1996 International Business Machines Corp.
|
|
* (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.
|
|
* (c) Copyright 1993, 1994, 1996 Novell, Inc.
|
|
* (c) Copyright 1996 FUJITSU LIMITED.
|
|
* (c) Copyright 1996 Hitachi.
|
|
*/
|
|
|
|
/*
|
|
* system includes
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <limits.h>
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xatom.h>
|
|
#include <X11/Intrinsic.h>
|
|
#include <Xm/Xm.h>
|
|
#include <Xm/AtomMgr.h>
|
|
#include <Xm/DrawnB.h>
|
|
#include <Xm/CutPaste.h>
|
|
|
|
|
|
/*
|
|
* Canvas Engine
|
|
*/
|
|
#include "CanvasP.h"
|
|
|
|
/*
|
|
* private includes
|
|
*/
|
|
#include "DisplayAreaP.h"
|
|
#include "CallbacksI.h"
|
|
#include "FontI.h"
|
|
#include "FontAttrI.h"
|
|
#include "HyperTextI.h"
|
|
#include "SetListI.h"
|
|
#include "HelposI.h"
|
|
#include "XInterfaceI.h"
|
|
|
|
#ifdef NLS16
|
|
#endif
|
|
|
|
/******** Private Function Declarations ********/
|
|
static Boolean ConvertSelectionCB (
|
|
Widget widget,
|
|
Atom *selection,
|
|
Atom *target,
|
|
Atom *type,
|
|
XtPointer *value,
|
|
unsigned long *length,
|
|
int *format );
|
|
static void ScrollTimerCB (
|
|
XtPointer client_data,
|
|
XtIntervalId *id );
|
|
static void StartSelection (
|
|
Widget widget,
|
|
XtPointer client_data );
|
|
/******** End Private Function Declarations ********/
|
|
|
|
/******** Private Defines ********/
|
|
#define SCROLL_BAR_FLAGS 0x03
|
|
#define HORIZONTAL 0
|
|
#define VERTICAL 1
|
|
|
|
/******** End Private Defines ********/
|
|
|
|
/******** Private Variable Declarations ********/
|
|
|
|
/******** End Private Variable Declarations ********/
|
|
|
|
/******************************************************************************
|
|
* Private Functions
|
|
******************************************************************************/
|
|
/*****************************************************************************
|
|
* Function: ConvertSelectionCB
|
|
*
|
|
* ConvertSelectionCB - this routine is called when someone asks for
|
|
* our selection.
|
|
*
|
|
*****************************************************************************/
|
|
static Boolean
|
|
ConvertSelectionCB (
|
|
Widget widget,
|
|
Atom *selection,
|
|
Atom *target,
|
|
Atom *type,
|
|
XtPointer *value,
|
|
unsigned long *length,
|
|
int *format )
|
|
{
|
|
Atom TARGETS = XmInternAtom(XtDisplay(widget), "TARGETS" , False);
|
|
Atom TIMESTAMP = XmInternAtom(XtDisplay(widget), "TIMESTAMP", False);
|
|
Atom TEXT = XmInternAtom(XtDisplay(widget), "TEXT" , False);
|
|
Atom CMP_TEXT = XmInternAtom(XtDisplay(widget), "COMPOUND_TEXT",False);
|
|
Atom LOCALE;
|
|
int retStatus = 0;
|
|
char *testString = "ABC"; /* these are characters in XPCS, so... safe */
|
|
char *tmpString = NULL;
|
|
Arg args[2];
|
|
DtHelpDispAreaStruct *pDAS;
|
|
|
|
XTextProperty tmpProp;
|
|
|
|
XtSetArg(args[0], XmNuserData, &pDAS);
|
|
XtGetValues(widget, args, 1);
|
|
|
|
if (pDAS == NULL || pDAS->primary == False || *selection != XA_PRIMARY)
|
|
return False;
|
|
|
|
retStatus = XmbTextListToTextProperty(XtDisplay(widget), &testString, 1,
|
|
(XICCEncodingStyle)XTextStyle, &tmpProp);
|
|
|
|
LOCALE = (Atom) 9999; /* XmbTextList... should always be able
|
|
* to convert XPCS characters; but in
|
|
* case its broken, this prevents a core
|
|
* dump.
|
|
*/
|
|
if (retStatus == Success)
|
|
{
|
|
LOCALE = tmpProp.encoding;
|
|
XFree(tmpProp.value);
|
|
}
|
|
|
|
/*
|
|
* List the targets understood
|
|
*/
|
|
if (*target == TARGETS)
|
|
{
|
|
Atom *targs = (Atom *)XtMalloc((unsigned) (5 * sizeof(Atom)));
|
|
|
|
*value = (char *) targs;
|
|
*targs++ = LOCALE;
|
|
*targs++ = TIMESTAMP;
|
|
*targs++ = TEXT;
|
|
*targs++ = CMP_TEXT;
|
|
*targs++ = XA_STRING;
|
|
|
|
*type = XA_ATOM;
|
|
*length = (5 * sizeof(Atom)) >> 2;
|
|
*format = 32;
|
|
}
|
|
else if (*target == TIMESTAMP)
|
|
{
|
|
Time *timestamp;
|
|
timestamp = (Time *) XtMalloc(sizeof(Time));
|
|
*timestamp = pDAS->anchor_time;
|
|
|
|
*value = (char *) timestamp;
|
|
*type = XA_INTEGER;
|
|
*length = sizeof(Time);
|
|
*format = 32;
|
|
}
|
|
else if (*target == XA_STRING)
|
|
{
|
|
/*
|
|
* initialize the return type here in case we fail
|
|
*/
|
|
*type = (Atom) XA_STRING;
|
|
*format = 8;
|
|
|
|
/*
|
|
* get the string
|
|
*/
|
|
_DtCanvasGetSelection (pDAS->canvas,
|
|
(_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
|
|
(_DtCvPointer *)(&tmpString));
|
|
retStatus = -1;
|
|
if (tmpString != NULL && *tmpString != '\0')
|
|
retStatus = XmbTextListToTextProperty(XtDisplay(widget),
|
|
&tmpString, 1,
|
|
(XICCEncodingStyle)XStringStyle, &tmpProp);
|
|
|
|
/*
|
|
* free the original copy of the string and check the results
|
|
*/
|
|
if (tmpString != NULL)
|
|
free(tmpString);
|
|
|
|
if (retStatus == Success || retStatus > 0)
|
|
{
|
|
*value = (XtPointer) tmpProp.value;
|
|
*length = tmpProp.nitems;
|
|
}
|
|
else
|
|
{
|
|
*value = NULL;
|
|
*length = 0;
|
|
return False;
|
|
}
|
|
}
|
|
else if (*target == TEXT)
|
|
{
|
|
/*
|
|
* set the type and format to those calculated
|
|
*/
|
|
*type = TEXT;
|
|
*format = 8;
|
|
|
|
/*
|
|
* get the string
|
|
*/
|
|
_DtCanvasGetSelection (pDAS->canvas,
|
|
(_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
|
|
(_DtCvPointer *)(&tmpString));
|
|
|
|
retStatus = -1;
|
|
if (tmpString != NULL && *tmpString != '\0')
|
|
retStatus = XmbTextListToTextProperty(XtDisplay(widget),
|
|
&tmpString, 1,
|
|
(XICCEncodingStyle)XStdICCTextStyle, &tmpProp);
|
|
|
|
/*
|
|
* free the original copy of the string and check the results
|
|
*/
|
|
if (tmpString != NULL)
|
|
free(tmpString);
|
|
|
|
if (retStatus == Success || retStatus > 0)
|
|
{
|
|
*value = (XtPointer) tmpProp.value;
|
|
*length = tmpProp.nitems;
|
|
}
|
|
else
|
|
{
|
|
*value = NULL;
|
|
*length = 0;
|
|
return False;
|
|
}
|
|
}
|
|
else if (*target == LOCALE)
|
|
{
|
|
/*
|
|
* pass the string straight through
|
|
*/
|
|
*type = LOCALE;
|
|
*format = 8;
|
|
|
|
_DtCanvasGetSelection (pDAS->canvas,
|
|
(_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
|
|
(_DtCvPointer *)(value));
|
|
*length = 0;
|
|
if (*value != NULL)
|
|
*length = strlen((char *)(*value));
|
|
}
|
|
else if (*target == CMP_TEXT)
|
|
{
|
|
*type = CMP_TEXT;
|
|
*format = 8;
|
|
|
|
/*
|
|
* get the selected text.
|
|
*/
|
|
_DtCanvasGetSelection (pDAS->canvas,
|
|
(_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
|
|
(_DtCvPointer *)(&tmpString));
|
|
|
|
retStatus = -1;
|
|
if (tmpString != NULL && *tmpString != '\0')
|
|
retStatus = XmbTextListToTextProperty(XtDisplay(widget),
|
|
&tmpString, 1,
|
|
(XICCEncodingStyle)XCompoundTextStyle, &tmpProp);
|
|
|
|
/*
|
|
* free the original copy of the string and check the results
|
|
*/
|
|
if (tmpString != NULL)
|
|
free(tmpString);
|
|
|
|
if (retStatus == Success || retStatus > 0)
|
|
{
|
|
*value = (XtPointer) tmpProp.value;
|
|
*length = tmpProp.nitems;
|
|
}
|
|
else
|
|
{
|
|
*value = NULL;
|
|
*length = 0;
|
|
return False;
|
|
}
|
|
}
|
|
else
|
|
return False;
|
|
|
|
return True;
|
|
|
|
} /* End ConvertSelectionCB */
|
|
|
|
/*****************************************************************************
|
|
* Function: ScrollTimerCB
|
|
*
|
|
* ScrollTimerCB - This routine is called when we have a timer
|
|
* go off with the mouse outside the Display Area during a
|
|
* selection.
|
|
*
|
|
*****************************************************************************/
|
|
static void
|
|
ScrollTimerCB (
|
|
XtPointer client_data, /* data from applicaiton */
|
|
XtIntervalId *id ) /* timer id */
|
|
{
|
|
int diffY = 0;
|
|
int diffX = 0;
|
|
int x;
|
|
int y;
|
|
int scrollTimeOut;
|
|
int maxY;
|
|
int dispY;
|
|
Arg args[2];
|
|
XmScrollBarCallbackStruct callData;
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
|
|
|
|
if (*id != pDAS->scr_timer_id)
|
|
return;
|
|
|
|
pDAS->scr_timer_id = NULL;
|
|
|
|
maxY = pDAS->maxYpos;
|
|
dispY = pDAS->firstVisible + pDAS->dispUseHeight;
|
|
|
|
if ((pDAS->scr_timer_data.vertical_reason == XmCR_INCREMENT && maxY <= dispY)
|
|
||
|
|
(pDAS->scr_timer_data.vertical_reason == XmCR_DECREMENT &&
|
|
!pDAS->firstVisible))
|
|
pDAS->scr_timer_data.vertical_reason = XmCR_NONE;
|
|
|
|
if ((pDAS->scr_timer_data.horizontal_reason == XmCR_INCREMENT &&
|
|
pDAS->maxX <= pDAS->virtualX + ((int)pDAS->dispUseWidth))
|
|
||
|
|
(pDAS->scr_timer_data.horizontal_reason == XmCR_DECREMENT &&
|
|
!pDAS->virtualX))
|
|
pDAS->scr_timer_data.horizontal_reason = XmCR_NONE;
|
|
|
|
if ( pDAS->scr_timer_data.vertical_reason == XmCR_NONE &&
|
|
pDAS->scr_timer_data.horizontal_reason == XmCR_NONE)
|
|
return;
|
|
|
|
y = pDAS->firstVisible;
|
|
if (pDAS->scr_timer_data.vertical_reason == XmCR_NONE)
|
|
y = pDAS->scr_timer_y - pDAS->decorThickness;
|
|
else if (pDAS->scr_timer_data.vertical_reason == XmCR_INCREMENT)
|
|
{
|
|
y = y + pDAS->dispUseHeight + pDAS->lineHeight;
|
|
if (y > pDAS->maxYpos)
|
|
y = pDAS->maxYpos;
|
|
|
|
diffY = y - pDAS->firstVisible - pDAS->dispUseHeight;
|
|
}
|
|
else if (pDAS->scr_timer_data.vertical_reason == XmCR_DECREMENT)
|
|
{
|
|
y -= pDAS->lineHeight;
|
|
if (y < 0)
|
|
y = 0;
|
|
|
|
diffY = y - pDAS->firstVisible;
|
|
}
|
|
|
|
if (pDAS->scr_timer_data.horizontal_reason == XmCR_NONE)
|
|
x = pDAS->scr_timer_x - pDAS->decorThickness;
|
|
else
|
|
{
|
|
if (pDAS->scr_timer_data.horizontal_reason == XmCR_INCREMENT)
|
|
{
|
|
diffX = (int) (pDAS->charWidth / 10);
|
|
x = pDAS->dispUseWidth;
|
|
|
|
if (x + pDAS->virtualX + diffX > pDAS->maxX)
|
|
diffX = pDAS->maxX - x - pDAS->virtualX;
|
|
}
|
|
else if (pDAS->scr_timer_data.horizontal_reason == XmCR_DECREMENT)
|
|
{
|
|
diffX = -((int)(pDAS->charWidth / 10));
|
|
x = 0;
|
|
|
|
if (pDAS->virtualX + diffX < 0)
|
|
diffX = -(pDAS->virtualX);
|
|
}
|
|
}
|
|
|
|
_DtCanvasProcessSelection (pDAS->canvas,
|
|
(x + diffX + pDAS->virtualX - pDAS->decorThickness),
|
|
y, _DtCvSELECTION_UPDATE);
|
|
|
|
callData.event = NULL;
|
|
if (diffX)
|
|
{
|
|
scrollTimeOut = pDAS->horz_rep_scr;
|
|
callData.reason = pDAS->scr_timer_data.horizontal_reason;
|
|
callData.value = pDAS->virtualX + diffX;
|
|
_DtHelpHorzScrollCB (pDAS->horzScrollWid, client_data,
|
|
(XtPointer) &callData);
|
|
|
|
if (pDAS->horzScrollWid)
|
|
{
|
|
XtSetArg (args[0], XmNvalue, pDAS->virtualX);
|
|
XtSetValues (pDAS->horzScrollWid, args, 1);
|
|
}
|
|
|
|
if (diffY != 0 && pDAS->vertScrollWid)
|
|
{
|
|
XtSetArg (args[0], XmNvalue, y);
|
|
XtSetValues (pDAS->vertScrollWid, args, 1);
|
|
if (pDAS->vScrollNotify)
|
|
(pDAS->vScrollNotify)(pDAS->clientData, y);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
scrollTimeOut = pDAS->vert_rep_scr;
|
|
callData.reason = pDAS->scr_timer_data.vertical_reason;
|
|
callData.value = pDAS->firstVisible + diffY;
|
|
_DtHelpVertScrollCB (pDAS->vertScrollWid, client_data,
|
|
(XtPointer) &callData);
|
|
|
|
if (pDAS->vertScrollWid)
|
|
{
|
|
XtSetArg (args[0], XmNvalue, pDAS->firstVisible);
|
|
XtSetValues (pDAS->vertScrollWid, args, 1);
|
|
if (pDAS->vScrollNotify)
|
|
(pDAS->vScrollNotify)(pDAS->clientData, pDAS->firstVisible);
|
|
}
|
|
}
|
|
|
|
pDAS->scr_timer_id = XtAppAddTimeOut (
|
|
XtWidgetToApplicationContext (pDAS->dispWid),
|
|
((unsigned long) scrollTimeOut),
|
|
ScrollTimerCB, client_data);
|
|
|
|
} /* End ScrollTimerCB */
|
|
|
|
/******************************************************************************
|
|
* Function: DrawWholeCanvas
|
|
*
|
|
*****************************************************************************/
|
|
static void
|
|
DrawWholeCanvas(
|
|
DtHelpDispAreaStruct *pDAS)
|
|
{
|
|
_DtCvUnit top;
|
|
_DtCvUnit bottom;
|
|
_DtCvUnit right;
|
|
_DtCvUnit next_y;
|
|
|
|
_DtCanvasMoveTraversal(pDAS->canvas,_DtCvTRAVERSAL_OFF, False,
|
|
(XtIsRealized(pDAS->dispWid) ? True : False),
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
|
|
top = pDAS->firstVisible;
|
|
bottom = top + pDAS->dispUseHeight;
|
|
right = pDAS->virtualX + pDAS->dispUseWidth;
|
|
|
|
_DtCanvasRender (pDAS->canvas, pDAS->virtualX, top, right, bottom,
|
|
pDAS->render_type, _DtCvTRUE, NULL, &next_y);
|
|
pDAS->nextNonVisible =
|
|
(pDAS->render_type == _DtCvRENDER_PARTIAL) ? bottom : next_y;
|
|
|
|
/*
|
|
* If we have a hypertext link boxed, draw it
|
|
*/
|
|
_DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ON, False,
|
|
(XtIsRealized(pDAS->dispWid) ? True : False),
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
/*
|
|
* if the toc exists within this area, draw it.
|
|
*/
|
|
if ((pDAS->toc_flag & _DT_HELP_TOC_ON) &&
|
|
pDAS->toc_y + pDAS->toc_height >= top && pDAS->toc_y < bottom)
|
|
_DtHelpDATocMarker((XtPointer) pDAS, True);
|
|
|
|
} /* End DrawWholeCanvas */
|
|
|
|
/******************************************************************************
|
|
* Semi Public Functions
|
|
*****************************************************************************/
|
|
/******************************************************************************
|
|
* Function: _DtHelpCleanAndDrawWholeCanvas
|
|
*
|
|
*****************************************************************************/
|
|
void
|
|
_DtHelpCleanAndDrawWholeCanvas(
|
|
XtPointer client_data)
|
|
{
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
|
|
|
|
XClearArea (XtDisplay(pDAS->dispWid), XtWindow(pDAS->dispWid),
|
|
pDAS->decorThickness, pDAS->decorThickness,
|
|
pDAS->dispUseWidth,
|
|
pDAS->dispUseHeight,
|
|
False);
|
|
DrawWholeCanvas (pDAS);
|
|
|
|
}
|
|
|
|
void
|
|
_DtHelpSearchMoveTraversal(XtPointer client_data, int search_hit_index)
|
|
{
|
|
_DtCvUnit baseline, ascend, descend;
|
|
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
|
|
|
|
if (_DtCvGetSearchLineMetrics(pDAS->canvas, search_hit_index,
|
|
&baseline, &descend, &ascend) == 0) {
|
|
|
|
_DtCvUnit top, hitY, height;
|
|
|
|
top = pDAS->firstVisible;
|
|
hitY = baseline - ascend - pDAS->lineThickness;
|
|
height = ascend + descend + 2 * pDAS->lineThickness;
|
|
|
|
if (hitY < top)
|
|
top = hitY;
|
|
else if (hitY + height > top + ((int) pDAS->dispUseHeight))
|
|
top = hitY + height - ((int) pDAS->dispUseHeight);
|
|
|
|
if (top != pDAS->firstVisible) {
|
|
|
|
_DtCvUnit dispUseHeightHalf =
|
|
pDAS->dispUseHeight / 2 + pDAS->dispUseHeight % 2;
|
|
|
|
/* put search hit in the middle of the viewport */
|
|
if (top == hitY)
|
|
top -= dispUseHeightHalf - height;
|
|
else {
|
|
top += dispUseHeightHalf + height;
|
|
if (top + ((int)pDAS->dispUseHeight) > pDAS->maxYpos)
|
|
top = pDAS->maxYpos - pDAS->dispUseHeight;
|
|
}
|
|
if (top < 0)
|
|
top = 0;
|
|
|
|
if (top != pDAS->firstVisible) {
|
|
|
|
Arg arg;
|
|
|
|
pDAS->firstVisible = top;
|
|
|
|
XtSetArg(arg, XmNvalue, pDAS->firstVisible);
|
|
XtSetValues(pDAS->vertScrollWid, &arg, 1);
|
|
|
|
if (pDAS->vScrollNotify)
|
|
(pDAS->vScrollNotify)(pDAS->clientData, pDAS->firstVisible);
|
|
|
|
_DtHelpCleanAndDrawWholeCanvas(pDAS);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function: _DtHelpCancelSelection
|
|
*
|
|
* Returns : True if a selection was active and cancelled.
|
|
* False if a selection was not active.
|
|
*
|
|
*****************************************************************************/
|
|
Boolean
|
|
_DtHelpCancelSelection(
|
|
XtPointer client_data)
|
|
{
|
|
Boolean selActive = False;
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
|
|
|
|
if (pDAS->select_state == _DtHelpSelectingText && pDAS->primary == True)
|
|
{
|
|
selActive = True;
|
|
if (pDAS->scr_timer_id)
|
|
{
|
|
XtRemoveTimeOut (pDAS->scr_timer_id);
|
|
pDAS->scr_timer_id = NULL;
|
|
}
|
|
_DtHelpClearSelection (client_data);
|
|
}
|
|
|
|
return selActive;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Public Functions
|
|
*****************************************************************************/
|
|
/******************************************************************************
|
|
* Function: _DtHelpExposeCB
|
|
*
|
|
* _DtHelpExposeCB handles the exposure events for a Text Graphic Area.
|
|
*
|
|
*****************************************************************************/
|
|
void
|
|
_DtHelpExposeCB(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data )
|
|
{
|
|
Arg args[4];
|
|
|
|
Dimension height;
|
|
Dimension width;
|
|
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
|
|
|
|
XmDrawnButtonCallbackStruct *callback =
|
|
(XmDrawnButtonCallbackStruct *) call_data;
|
|
|
|
if (callback->reason != XmCR_EXPOSE ||
|
|
(pDAS->neededFlags & (1 << (VisibilityFullyObscured + 3))))
|
|
return;
|
|
|
|
/*
|
|
* get the width and height.
|
|
*/
|
|
XtSetArg(args[0], XmNwidth, &width);
|
|
XtSetArg(args[1], XmNheight, &height);
|
|
XtGetValues(widget, args, 2);
|
|
|
|
/*
|
|
* if this exposure is a result of a resize,
|
|
* wait for the resize to handle it.
|
|
*/
|
|
if (width != pDAS->dispWidth || height != pDAS->dispHeight)
|
|
return;
|
|
|
|
if (!(callback->event) || callback->event->xexpose.count)
|
|
return;
|
|
|
|
/*
|
|
* re-draw the information in the display area
|
|
*/
|
|
DrawWholeCanvas (pDAS);
|
|
|
|
} /* End _DtHelpExposeCB */
|
|
|
|
/*********************************************************************
|
|
* Function: _DtHelpResizeCB
|
|
*
|
|
* _DtHelpResizeCB handles the exposure events for a Text Graphic Area.
|
|
*
|
|
*********************************************************************/
|
|
void
|
|
_DtHelpResizeCB(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data )
|
|
{
|
|
Arg args[4];
|
|
Dimension width;
|
|
Dimension height;
|
|
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
|
|
XmDrawnButtonCallbackStruct *callback =
|
|
(XmDrawnButtonCallbackStruct *) call_data;
|
|
|
|
if (callback->reason != XmCR_RESIZE)
|
|
return;
|
|
|
|
/*
|
|
* get the width and height of the form.
|
|
*/
|
|
XtSetArg(args[0], XmNwidth, &width);
|
|
XtSetArg(args[1], XmNheight, &height);
|
|
XtGetValues(XtParent(widget), args, 2);
|
|
if (width == pDAS->formWidth && height == pDAS->formHeight)
|
|
return;
|
|
|
|
pDAS->formWidth = width;
|
|
pDAS->formHeight = height;
|
|
|
|
/*
|
|
* get the width and height.
|
|
*/
|
|
XtSetArg(args[0], XmNwidth, &width);
|
|
XtSetArg(args[1], XmNheight, &height);
|
|
XtGetValues(widget, args, 2);
|
|
|
|
if (width == pDAS->dispWidth && height == pDAS->dispHeight)
|
|
return;
|
|
|
|
/*
|
|
|
|
_DtHelpClearSelection (pDAS);
|
|
* reset the scroll bars and possibly reformat the text for the size.
|
|
*/
|
|
(void) _DtHelpSetScrollBars (client_data, width, height);
|
|
if (XtIsRealized (pDAS->dispWid))
|
|
_DtHelpCleanAndDrawWholeCanvas (client_data);
|
|
|
|
/*
|
|
* I will get an expose event after the resize.
|
|
*/
|
|
|
|
} /* End _DtHelpResizeCB */
|
|
|
|
/***************************************************************************
|
|
* Function: _DtHelpVertScrollCB
|
|
*
|
|
* _DtHelpVertScrollCB is called when the vertical scroll bar is changed.
|
|
*
|
|
**************************************************************************/
|
|
void
|
|
_DtHelpVertScrollCB(
|
|
Widget widget,
|
|
XtPointer clientData,
|
|
XtPointer callData )
|
|
{
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) clientData;
|
|
XmScrollBarCallbackStruct *callBack =
|
|
(XmScrollBarCallbackStruct *) callData;
|
|
int diff = pDAS->lineHeight;
|
|
int srcY, dstY;
|
|
int clearY;
|
|
int reason = callBack->reason;
|
|
_DtCvUnit absTop;
|
|
_DtCvUnit absBot;
|
|
Display *dpy;
|
|
Window win;
|
|
|
|
/*
|
|
* if the policy is XmEXPLICIT, don't want the focus on the scrollbar
|
|
*/
|
|
if (callBack->event != NULL && callBack->event->type == ButtonPress &&
|
|
_XmGetFocusPolicy(XtParent(XtParent(pDAS->dispWid))) != XmPOINTER)
|
|
XmProcessTraversal(pDAS->dispWid, XmTRAVERSE_CURRENT);
|
|
|
|
/*
|
|
* check to make sure we don't do a rerender when we don't have to.
|
|
*/
|
|
if (pDAS->firstVisible == callBack->value)
|
|
return;
|
|
|
|
/* If a drag occured, reset the reason to increment, decrement, page */
|
|
/* increment, or page decrement depending on the distance and direction */
|
|
/* dragged. */
|
|
if (callBack->reason == XmCR_DRAG || callBack->reason == XmCR_VALUE_CHANGED)
|
|
{
|
|
diff = callBack->value - pDAS->firstVisible;
|
|
|
|
if (diff > 0 && diff <= ((int) pDAS->dispUseHeight))
|
|
reason = XmCR_INCREMENT;
|
|
else if (diff < 0 && -(diff) <= ((int) pDAS->dispUseHeight))
|
|
{
|
|
reason = XmCR_DECREMENT;
|
|
diff = -diff;
|
|
}
|
|
else if (diff > ((int) pDAS->dispUseHeight))
|
|
reason = XmCR_PAGE_DECREMENT;
|
|
else
|
|
reason = XmCR_PAGE_INCREMENT;
|
|
}
|
|
else if (callBack->reason == XmCR_INCREMENT ||
|
|
callBack->reason == XmCR_DECREMENT)
|
|
{
|
|
diff = callBack->value - pDAS->firstVisible;
|
|
if (diff < 0)
|
|
diff = -diff;
|
|
}
|
|
|
|
/* Reset first visible to the returned scrollbar value. */
|
|
pDAS->firstVisible = callBack->value;
|
|
|
|
/* For page increment and decrement, call _DtHelpCleanAndDrawWholeCanvas
|
|
* to clear the view area and redisplay the text.
|
|
*
|
|
* For increment and decrement,
|
|
* use XCopyArea to move the visible lines and draw the cleared out line.
|
|
*/
|
|
if (!pDAS->maxYpos ||
|
|
(pDAS->neededFlags & (1 << (VisibilityFullyObscured + 3))))
|
|
return;
|
|
|
|
dpy = XtDisplay (widget);
|
|
win = XtWindow (pDAS->dispWid);
|
|
|
|
if (reason == XmCR_PAGE_INCREMENT || reason == XmCR_PAGE_DECREMENT ||
|
|
reason == XmCR_TO_TOP || reason == XmCR_TO_BOTTOM)
|
|
_DtHelpCleanAndDrawWholeCanvas (clientData);
|
|
else
|
|
{
|
|
if (reason == XmCR_INCREMENT)
|
|
{
|
|
dstY = pDAS->decorThickness;
|
|
srcY = dstY + diff;
|
|
clearY = pDAS->dispHeight - pDAS->decorThickness - diff;
|
|
}
|
|
else
|
|
{
|
|
srcY = pDAS->decorThickness;
|
|
dstY = srcY + diff;
|
|
clearY = srcY;
|
|
}
|
|
XCopyArea(dpy, win, win, pDAS->normalGC, pDAS->decorThickness, srcY,
|
|
pDAS->dispUseWidth, (pDAS->dispUseHeight - diff),
|
|
pDAS->decorThickness, dstY);
|
|
|
|
XClearArea(dpy, win, pDAS->decorThickness, clearY,
|
|
pDAS->dispUseWidth, ((unsigned int) diff), False);
|
|
|
|
if (pDAS->neededFlags & (1 << (VisibilityPartiallyObscured + 3)))
|
|
{
|
|
/*
|
|
* redraw all the information
|
|
*/
|
|
DrawWholeCanvas (pDAS);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* draw the line that sits on the cleared line
|
|
*/
|
|
absTop = clearY + pDAS->firstVisible - pDAS->decorThickness;
|
|
absBot = absTop + diff;
|
|
|
|
_DtCanvasRender (pDAS->canvas, 0, absTop,
|
|
pDAS->virtualX + pDAS->dispWidth, absBot,
|
|
_DtCvRENDER_PARTIAL, _DtCvFALSE, NULL, NULL);
|
|
/*
|
|
* if the toc exists within this area, draw it.
|
|
*/
|
|
if ((pDAS->toc_flag & _DT_HELP_TOC_ON)
|
|
&& pDAS->toc_y + pDAS->toc_height >= absTop
|
|
&& pDAS->toc_y < absBot)
|
|
_DtHelpDATocMarker((XtPointer) pDAS, True);
|
|
}
|
|
}
|
|
|
|
} /* End _DtHelpVertScrollCB */
|
|
|
|
/***************************************************************************
|
|
* Function: _DtHelpHorzScrollCB
|
|
*
|
|
* _DtHelpHorzScrollCB is called when the horizontal scroll bar is changed.
|
|
*
|
|
**************************************************************************/
|
|
void
|
|
_DtHelpHorzScrollCB(
|
|
Widget widget,
|
|
XtPointer clientData,
|
|
XtPointer callData )
|
|
{
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) clientData;
|
|
XmScrollBarCallbackStruct *callBack =
|
|
(XmScrollBarCallbackStruct *) callData;
|
|
int diff = (int)(pDAS->charWidth / 10);
|
|
int srcX;
|
|
int dstX;
|
|
int clearX;
|
|
int reason = callBack->reason;
|
|
_DtCvUnit absLeft;
|
|
_DtCvUnit absRight;
|
|
_DtCvUnit absY;
|
|
Display *dpy;
|
|
Window win;
|
|
|
|
/*
|
|
* if the policy is XmEXPLICIT, don't want the focus on the scrollbar
|
|
*/
|
|
if (callBack->event != NULL && callBack->event->type == ButtonPress &&
|
|
_XmGetFocusPolicy(XtParent(XtParent(pDAS->dispWid))) != XmPOINTER)
|
|
XmProcessTraversal(pDAS->dispWid, XmTRAVERSE_CURRENT);
|
|
|
|
/*
|
|
* check to make sure we don't do a rerender when we don't have to.
|
|
*/
|
|
if (pDAS->virtualX == callBack->value)
|
|
return;
|
|
|
|
/* If a drag occured, reset the reason to increment, decrement, page */
|
|
/* increment, or page decrement depending on the distance and direction */
|
|
/* dragged. */
|
|
if (callBack->reason == XmCR_DRAG || callBack->reason == XmCR_VALUE_CHANGED)
|
|
{
|
|
diff = callBack->value - pDAS->virtualX;
|
|
|
|
if (diff > 0 && diff <= ((int) pDAS->dispUseWidth))
|
|
reason = XmCR_INCREMENT;
|
|
else if (diff < 0 && -(diff) <= ((int) pDAS->dispUseWidth))
|
|
{
|
|
reason = XmCR_DECREMENT;
|
|
diff = -diff;
|
|
}
|
|
else if (diff > ((int) pDAS->dispUseWidth))
|
|
reason = XmCR_PAGE_DECREMENT;
|
|
else
|
|
reason = XmCR_PAGE_INCREMENT;
|
|
}
|
|
else if (callBack->reason == XmCR_INCREMENT ||
|
|
callBack->reason == XmCR_DECREMENT)
|
|
{
|
|
diff = callBack->value - pDAS->virtualX;
|
|
if (diff < 0)
|
|
diff = -diff;
|
|
}
|
|
|
|
/* Reset first visible to the returned scrollbar value. */
|
|
pDAS->virtualX = callBack->value;
|
|
|
|
/* For page increment and decrement, call _DtHelpCleanAndDrawWholeCanvas
|
|
* to clear the view area and redisplay the text.
|
|
*
|
|
* For increment and decrement,
|
|
* use XCopyArea to move the visible lines and draw the cleared out line.
|
|
*/
|
|
if (!pDAS->maxX || !pDAS->visibleCount ||
|
|
(pDAS->neededFlags & (1 << (VisibilityFullyObscured + 3))))
|
|
return;
|
|
|
|
dpy = XtDisplay (widget);
|
|
win = XtWindow (pDAS->dispWid);
|
|
|
|
/* For page increment and decrement, clear the view area and call
|
|
* View_DtHelpExposeCB to redisplay the text. For increment and decrement,
|
|
* use XCopyArea to move the visible lines and draw the cleared out line.
|
|
*/
|
|
if (reason == XmCR_PAGE_INCREMENT || reason == XmCR_PAGE_DECREMENT ||
|
|
reason == XmCR_TO_TOP || reason == XmCR_TO_BOTTOM)
|
|
_DtHelpCleanAndDrawWholeCanvas (clientData);
|
|
else
|
|
{
|
|
if (reason == XmCR_INCREMENT)
|
|
{
|
|
dstX = pDAS->decorThickness;
|
|
srcX = dstX + diff;
|
|
clearX = pDAS->dispWidth - pDAS->decorThickness - diff;
|
|
}
|
|
else
|
|
{
|
|
srcX = pDAS->decorThickness;
|
|
dstX = srcX + diff;
|
|
clearX = srcX;
|
|
}
|
|
|
|
XCopyArea(dpy, win, win, pDAS->normalGC, srcX, pDAS->decorThickness,
|
|
pDAS->dispUseWidth - diff, pDAS->dispUseHeight,
|
|
dstX, pDAS->decorThickness);
|
|
|
|
XClearArea(dpy, win, clearX, pDAS->decorThickness,
|
|
((unsigned int) diff), pDAS->dispUseHeight, False);
|
|
|
|
if (pDAS->neededFlags & (1 << (VisibilityPartiallyObscured + 3)))
|
|
{
|
|
/*
|
|
* redraw all the information
|
|
*/
|
|
DrawWholeCanvas (pDAS);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* draw the line that sits on the cleared line
|
|
*/
|
|
absLeft = clearX + pDAS->virtualX - pDAS->decorThickness;
|
|
absRight = absLeft + diff;
|
|
absY = pDAS->firstVisible - pDAS->decorThickness;
|
|
|
|
_DtCanvasRender (pDAS->canvas, absLeft, absY,
|
|
absRight, absY + pDAS->dispHeight,
|
|
_DtCvRENDER_PARTIAL, _DtCvFALSE, NULL, NULL);
|
|
|
|
/*
|
|
* if the toc exists within this area, draw it.
|
|
*/
|
|
if ((pDAS->toc_flag & _DT_HELP_TOC_ON)
|
|
&& ((int) (pDAS->toc_y + pDAS->toc_height)) >= ((int) absY)
|
|
&& ((int) pDAS->toc_y) < ((int) (absY + pDAS->dispHeight)))
|
|
_DtHelpDATocMarker((XtPointer) pDAS, True);
|
|
|
|
}
|
|
}
|
|
|
|
} /* End _DtHelpHorzScrollCB */
|
|
|
|
/***************************************************************************
|
|
* Function: _DtHelpClickOrSelectCB
|
|
*
|
|
* _DtHelpClickOrSelectCB is called when the vertical scroll bar is changed.
|
|
*
|
|
**************************************************************************/
|
|
void
|
|
_DtHelpClickOrSelectCB(
|
|
Widget widget,
|
|
XtPointer clientData,
|
|
XtPointer callData )
|
|
{
|
|
XmDrawnButtonCallbackStruct *callBack =
|
|
(XmDrawnButtonCallbackStruct *) callData;
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) clientData;
|
|
|
|
/*
|
|
* If this is not an ARM call or entered through an Arm&Activate
|
|
* (event-type will be keypress or keyrelease) throw it away.
|
|
*/
|
|
if (callBack->reason != XmCR_ARM || callBack->event == NULL ||
|
|
callBack->event->type == KeyPress ||
|
|
callBack->event->type == KeyRelease)
|
|
return;
|
|
|
|
pDAS->timerX = callBack->event->xbutton.x;
|
|
pDAS->timerY = callBack->event->xbutton.y;
|
|
pDAS->select_state = _DtHelpCopyOrLink;
|
|
|
|
if (NULL != pDAS->armCallback)
|
|
(pDAS->armCallback)(pDAS->clientData);
|
|
|
|
} /* End _DtHelpClickOrSelectCB */
|
|
|
|
/*****************************************************************************
|
|
* Function: _DtHelpEndSelectionCB
|
|
*
|
|
*
|
|
* Called by: Callback for the Selection mechanism
|
|
*****************************************************************************/
|
|
void
|
|
_DtHelpEndSelectionCB (
|
|
Widget w, /* widget id */
|
|
XtPointer client_data, /* data from applicaiton */
|
|
XtPointer call_data ) /* data from widget class */
|
|
{
|
|
XmDrawnButtonCallbackStruct *callback =
|
|
(XmDrawnButtonCallbackStruct *) call_data;
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) client_data;
|
|
int newX;
|
|
int newY;
|
|
|
|
if (callback->reason != XmCR_DISARM || callback->event == NULL ||
|
|
callback->event->type == KeyPress ||
|
|
callback->event->type == KeyRelease)
|
|
return;
|
|
|
|
/*
|
|
* if a scroll timer is active, we are selecting text.
|
|
* stop it.
|
|
*/
|
|
if (pDAS->scr_timer_id)
|
|
{
|
|
XtRemoveTimeOut (pDAS->scr_timer_id);
|
|
pDAS->scr_timer_id = NULL;
|
|
}
|
|
|
|
newX = callback->event->xbutton.x;
|
|
newY = callback->event->xbutton.y;
|
|
if (pDAS->select_state == _DtHelpCopyOrLink)
|
|
{
|
|
if (abs (pDAS->timerX - newX) <= pDAS->moveThreshold &&
|
|
abs (pDAS->timerY - newY) <= pDAS->moveThreshold)
|
|
{
|
|
_DtHelpClearSelection (client_data);
|
|
|
|
/*
|
|
* If this is null, we came the the Arm&Activate routine
|
|
* which means a key was pressed, so we ignore this call.
|
|
*/
|
|
if (callback->event)
|
|
/*
|
|
* find the hypertext link and process it.
|
|
*/
|
|
_DtHelpProcessHyperSelection (client_data,
|
|
pDAS->timerX, pDAS->timerY,
|
|
callback->event);
|
|
}
|
|
else
|
|
StartSelection (w, client_data);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* The user was doing a selection, finish it up.
|
|
*/
|
|
if (pDAS->select_state != _DtHelpNothingDoing)
|
|
{
|
|
_DtCanvasProcessSelection(pDAS->canvas,
|
|
(newX + pDAS->virtualX - pDAS->decorThickness),
|
|
(newY + pDAS->firstVisible - pDAS->decorThickness),
|
|
_DtCvSELECTION_END);
|
|
_DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ON, False, True,
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
|
|
}
|
|
|
|
pDAS->select_state = _DtHelpNothingDoing;
|
|
return;
|
|
|
|
} /* End _DtHelpEndSelectionCB */
|
|
|
|
/***************************************************************************
|
|
* Function: _DtHelpMouseMoveCB
|
|
*
|
|
* _DtHelpMouseMoveCB tracks the mouse movement for the Selection mechanism
|
|
*
|
|
**************************************************************************/
|
|
void
|
|
_DtHelpMouseMoveCB(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XEvent *event )
|
|
{
|
|
_DtCvUnit newX;
|
|
_DtCvUnit newY;
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
|
|
|
|
/*
|
|
* If a selection is not in progress, don't do anything.
|
|
*/
|
|
if (pDAS->select_state == _DtHelpNothingDoing || event->type != MotionNotify)
|
|
return;
|
|
|
|
if (pDAS->scr_timer_id)
|
|
{
|
|
XtRemoveTimeOut (pDAS->scr_timer_id);
|
|
pDAS->scr_timer_id = NULL;
|
|
}
|
|
|
|
newX = event->xmotion.x;
|
|
newY = event->xmotion.y;
|
|
|
|
if (pDAS->select_state == _DtHelpCopyOrLink)
|
|
{
|
|
if (abs (newX - pDAS->timerX) < pDAS->moveThreshold &&
|
|
abs (newY - pDAS->timerY) < pDAS->moveThreshold)
|
|
return;
|
|
|
|
StartSelection (widget, client_data);
|
|
return;
|
|
}
|
|
|
|
if (newY < ((int) pDAS->decorThickness) && pDAS->firstVisible)
|
|
pDAS->scr_timer_data.vertical_reason = XmCR_DECREMENT;
|
|
|
|
else if ((newY >
|
|
(((int) pDAS->dispHeight)-((int)pDAS->decorThickness))) &&
|
|
(pDAS->maxYpos >
|
|
(((int)pDAS->firstVisible)
|
|
+ ((int)pDAS->dispUseHeight))))
|
|
pDAS->scr_timer_data.vertical_reason = XmCR_INCREMENT;
|
|
else
|
|
pDAS->scr_timer_data.vertical_reason = XmCR_NONE;
|
|
|
|
if (newX < ((int) pDAS->decorThickness) && pDAS->virtualX)
|
|
pDAS->scr_timer_data.horizontal_reason = XmCR_DECREMENT;
|
|
else if (newX > ((int) pDAS->dispWidth) &&
|
|
pDAS->maxX > pDAS->virtualX + ((int) pDAS->dispUseWidth))
|
|
pDAS->scr_timer_data.horizontal_reason = XmCR_INCREMENT;
|
|
else
|
|
pDAS->scr_timer_data.horizontal_reason = XmCR_NONE;
|
|
|
|
if (pDAS->scr_timer_data.vertical_reason != XmCR_NONE ||
|
|
pDAS->scr_timer_data.horizontal_reason != XmCR_NONE)
|
|
{
|
|
int scrollTimeOut = pDAS->vert_init_scr;
|
|
|
|
if (pDAS->scr_timer_data.horizontal_reason != XmCR_NONE)
|
|
scrollTimeOut = pDAS->horz_init_scr;
|
|
|
|
pDAS->scr_timer_x = newX;
|
|
pDAS->scr_timer_y = newY;
|
|
pDAS->scr_timer_id =
|
|
XtAppAddTimeOut(XtWidgetToApplicationContext(widget),
|
|
((unsigned long) scrollTimeOut),
|
|
ScrollTimerCB, (XtPointer) pDAS);
|
|
return;
|
|
}
|
|
|
|
newX = newX + pDAS->virtualX - pDAS->decorThickness;
|
|
if (newX < 0)
|
|
newX = 0;
|
|
|
|
newY = newY + pDAS->firstVisible - pDAS->decorThickness;
|
|
if (newY < 0)
|
|
newY = 0;
|
|
|
|
_DtCanvasProcessSelection(pDAS->canvas, newX, newY, _DtCvSELECTION_UPDATE);
|
|
|
|
} /* End _DtHelpMouseMoveCB */
|
|
|
|
/*****************************************************************************
|
|
* Function: StartSelection
|
|
*
|
|
* StartSelection - If this routine is called, the user has initiated a
|
|
* selection.
|
|
*
|
|
*****************************************************************************/
|
|
static void
|
|
StartSelection (
|
|
Widget widget, /* widget id */
|
|
XtPointer client_data ) /* data from applicaiton */
|
|
{
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) client_data;
|
|
|
|
/*
|
|
* If this widget doesn't own the primary selection, get it.
|
|
*/
|
|
_DtHelpGetClearSelection(widget, client_data);
|
|
|
|
/*
|
|
* check to see if we have the primary selection.
|
|
*/
|
|
if (pDAS->primary == True)
|
|
{
|
|
_DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_OFF, False, True,
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
_DtCanvasProcessSelection(pDAS->canvas,
|
|
pDAS->timerX + pDAS->virtualX - pDAS->decorThickness,
|
|
pDAS->timerY + pDAS->firstVisible -pDAS->decorThickness,
|
|
_DtCvSELECTION_START);
|
|
|
|
pDAS->select_state = _DtHelpSelectingText;
|
|
pDAS->text_selected = True;
|
|
}
|
|
|
|
} /* End StartSelection */
|
|
|
|
/*****************************************************************************
|
|
* Function: _DtHelpLoseSelectionCB
|
|
*
|
|
* _DtHelpLoseSelectionCB - This routine is called when we lose the selection
|
|
*
|
|
*****************************************************************************/
|
|
void
|
|
_DtHelpLoseSelectionCB (
|
|
Widget widget,
|
|
Atom *selection )
|
|
{
|
|
Arg args[2];
|
|
DtHelpDispAreaStruct *pDAS;
|
|
|
|
XtSetArg(args[0], XmNuserData, &pDAS);
|
|
XtGetValues(widget, args, 1);
|
|
|
|
if (pDAS != NULL && pDAS->dispWid == widget && *selection == XA_PRIMARY)
|
|
{
|
|
_DtHelpClearSelection ((XtPointer) pDAS);
|
|
pDAS->primary = False;
|
|
pDAS->text_selected = False;
|
|
}
|
|
} /* End _DtHelpLoseSelectionCB */
|
|
|
|
/*****************************************************************************
|
|
* Function: _DtHelpClearSelection
|
|
*
|
|
* Clears the selection pointers and variables
|
|
*
|
|
*****************************************************************************/
|
|
void
|
|
_DtHelpClearSelection ( XtPointer client_data)
|
|
{
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct*) client_data;
|
|
|
|
if (pDAS->primary == True)
|
|
{
|
|
if (NULL != pDAS->canvas)
|
|
{
|
|
_DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_OFF, False, True,
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
_DtCanvasProcessSelection(pDAS->canvas, 0, 0, _DtCvSELECTION_CLEAR);
|
|
_DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ON, False, True,
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
}
|
|
pDAS->select_state = _DtHelpNothingDoing;
|
|
pDAS->text_selected = False;
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
* Function: _DtHelpFocusCB
|
|
*
|
|
* _DtHelpFocusCB tracks the traversal of the hypertext.
|
|
*
|
|
**************************************************************************/
|
|
void
|
|
_DtHelpFocusCB(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XEvent *event )
|
|
{
|
|
Boolean oldFlag;
|
|
Boolean newFlag = False;
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
|
|
|
|
if (pDAS->hyperCall == NULL ||
|
|
(event->type != FocusIn && event->type != FocusOut) ||
|
|
!event->xfocus.send_event)
|
|
return;
|
|
|
|
/*
|
|
* get the old flag
|
|
*/
|
|
oldFlag = (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG) ? True : False;
|
|
|
|
/*
|
|
* get the new flag
|
|
*/
|
|
if (event->type == FocusIn)
|
|
newFlag = True;
|
|
|
|
if (oldFlag != newFlag)
|
|
{
|
|
if (newFlag == False)
|
|
{
|
|
_DtCanvasMoveTraversal (pDAS->canvas, _DtCvTRAVERSAL_OFF, False,
|
|
(XtIsRealized(widget) ? True : False),
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
pDAS->neededFlags = pDAS->neededFlags & ~(_DT_HELP_FOCUS_FLAG);
|
|
}
|
|
else
|
|
{
|
|
pDAS->neededFlags = pDAS->neededFlags | _DT_HELP_FOCUS_FLAG;
|
|
_DtCanvasMoveTraversal (pDAS->canvas, _DtCvTRAVERSAL_ON, False,
|
|
(XtIsRealized(widget) ? True : False),
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
} /* End _DtHelpFocusCB */
|
|
|
|
/***************************************************************************
|
|
* Function: _DtHelpEnterLeaveCB
|
|
*
|
|
* _DtHelpEnterLeaveCB tracks the traversal of the hypertext.
|
|
*
|
|
**************************************************************************/
|
|
void
|
|
_DtHelpEnterLeaveCB(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XEvent *event )
|
|
{
|
|
Boolean oldFlag;
|
|
Boolean newFlag = False;
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
|
|
|
|
if (pDAS->hyperCall == NULL ||
|
|
(event->type != EnterNotify && event->type != LeaveNotify))
|
|
return;
|
|
|
|
/*
|
|
* get the old flag
|
|
*/
|
|
oldFlag = (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG) ? True : False;
|
|
|
|
/*
|
|
* get the new flag
|
|
*/
|
|
if (event->type == FocusIn)
|
|
newFlag = True;
|
|
|
|
if (oldFlag != newFlag)
|
|
{
|
|
if (oldFlag == True)
|
|
{
|
|
_DtCanvasMoveTraversal (pDAS->canvas, _DtCvTRAVERSAL_OFF, False,
|
|
(XtIsRealized(widget) ? True : False),
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
pDAS->neededFlags = pDAS->neededFlags & ~(_DT_HELP_FOCUS_FLAG);
|
|
}
|
|
else
|
|
{
|
|
pDAS->neededFlags = pDAS->neededFlags | _DT_HELP_FOCUS_FLAG;
|
|
_DtCanvasMoveTraversal (pDAS->canvas, _DtCvTRAVERSAL_ON, False,
|
|
(XtIsRealized(widget) ? True : False),
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
}
|
|
}
|
|
} /* End _DtHelpEnterLeaveCB */
|
|
|
|
/***************************************************************************
|
|
* Function: _DtHelpVisibilityCB
|
|
*
|
|
* _DtHelpVisibilityCB tracks whether the window becomes obscured.
|
|
*
|
|
**************************************************************************/
|
|
void
|
|
_DtHelpVisibilityCB(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XEvent *event )
|
|
{
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
|
|
|
|
if (event->type != VisibilityNotify)
|
|
return;
|
|
|
|
/*
|
|
* save the scrollbar and focus flags while clearing the visibility flags.
|
|
*/
|
|
pDAS->neededFlags = pDAS->neededFlags &
|
|
(_DT_HELP_FOCUS_FLAG | SCROLL_BAR_FLAGS);
|
|
|
|
/*
|
|
* set the visibility flag
|
|
*/
|
|
pDAS->neededFlags = pDAS->neededFlags |
|
|
(1 << (event->xvisibility.state + 3));
|
|
|
|
} /* End _DtHelpVisibilityCB */
|
|
|
|
/*****************************************************************************
|
|
* Function: _DtHelpInitiateClipboard
|
|
*
|
|
* _DtHelpInitiateClipboard
|
|
*
|
|
*****************************************************************************/
|
|
void
|
|
_DtHelpInitiateClipboard (
|
|
XtPointer client_data)
|
|
{
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
|
|
|
|
/*
|
|
* check to see if we have the primary selection
|
|
* before trying for the clipboard.
|
|
*/
|
|
if (pDAS->primary == True && pDAS->text_selected == True)
|
|
{
|
|
long itemId = 0L; /* clipboard item id */
|
|
long dataId = 0L; /* clipboard data id */
|
|
int status; /* clipboard status */
|
|
XmString clipLabel;
|
|
Display *dpy = XtDisplay(pDAS->dispWid);
|
|
Window win = XtWindow(pDAS->dispWid);
|
|
char *atomName;
|
|
char *tmpString;
|
|
XTextProperty tmpProp;
|
|
|
|
/*
|
|
* get the selected text
|
|
*/
|
|
_DtCanvasGetSelection (pDAS->canvas,
|
|
(_DtCvSELECTED_TEXT | _DtCvSELECTED_REGION),
|
|
(_DtCvPointer *)(&tmpString));
|
|
|
|
/*
|
|
* Using the Xm clipboard facilities,
|
|
* copy the selected text to the clipboard
|
|
*/
|
|
if (tmpString != NULL)
|
|
{
|
|
clipLabel = XmStringCreateLocalized ("DT_HELP");
|
|
|
|
/*
|
|
* start copy to clipboard
|
|
*/
|
|
status = XmClipboardStartCopy(dpy, win, clipLabel,
|
|
XtLastTimestampProcessed(dpy),
|
|
pDAS->dispWid, NULL, &itemId);
|
|
|
|
/*
|
|
* no longer need the label
|
|
*/
|
|
XmStringFree(clipLabel);
|
|
|
|
if (status != ClipboardSuccess)
|
|
{
|
|
free(tmpString);
|
|
return;
|
|
}
|
|
|
|
status = XmbTextListToTextProperty(dpy, &tmpString, 1,
|
|
(XICCEncodingStyle)XStdICCTextStyle,
|
|
&tmpProp);
|
|
/*
|
|
* free the original copy of the string and check the results.
|
|
*/
|
|
free(tmpString);
|
|
|
|
if (status != Success && status <= 0)
|
|
{
|
|
XmClipboardCancelCopy(dpy, win, itemId);
|
|
return;
|
|
}
|
|
|
|
atomName = XGetAtomName(dpy, tmpProp.encoding);
|
|
|
|
/* move the data to the clipboard */
|
|
status = XmClipboardCopy(dpy, win, itemId, atomName,
|
|
(XtPointer)tmpProp.value, tmpProp.nitems,
|
|
0, &dataId);
|
|
|
|
XtFree(atomName);
|
|
|
|
if (status != ClipboardSuccess)
|
|
{
|
|
XmClipboardCancelCopy(dpy, win, itemId);
|
|
XFree((char*)tmpProp.value);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* end the copy to the clipboard
|
|
*/
|
|
status = XmClipboardEndCopy (dpy, win, itemId);
|
|
|
|
XFree((char*)tmpProp.value);
|
|
}
|
|
}
|
|
|
|
} /* End _DtHelpInitiateClipboard */
|
|
|
|
/***************************************************************************
|
|
* Function: _DtHelpMoveBtnFocusCB
|
|
*
|
|
* _DtHelpMoveBtnFocusCB tracks the mouse movement for the Selection mechanism
|
|
*
|
|
**************************************************************************/
|
|
void
|
|
_DtHelpMoveBtnFocusCB(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XEvent *event )
|
|
{
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
|
|
|
|
/*
|
|
* if the policy is XmEXPLICIT, don't want the focus on the scrollbar
|
|
*/
|
|
if (event->type == ButtonPress &&
|
|
_XmGetFocusPolicy(XtParent(XtParent(pDAS->dispWid))) != XmPOINTER)
|
|
XmProcessTraversal(pDAS->dispWid, XmTRAVERSE_CURRENT);
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Function: _DtHelpGetClearSelection
|
|
*
|
|
* _DtHelpGetClearSelection - If this routine is called,
|
|
* the user has initiated a selection.
|
|
*
|
|
*****************************************************************************/
|
|
void
|
|
_DtHelpGetClearSelection (
|
|
Widget widget, /* widget id */
|
|
XtPointer client_data ) /* data from applicaiton */
|
|
{
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
|
|
|
|
/*
|
|
* If this widget doesn't own the primary selection, get it.
|
|
*/
|
|
if (pDAS->primary != True)
|
|
{
|
|
if (XtOwnSelection (widget, XA_PRIMARY,
|
|
XtLastTimestampProcessed(XtDisplay(widget)),
|
|
(XtConvertSelectionProc) ConvertSelectionCB,
|
|
(XtLoseSelectionProc) _DtHelpLoseSelectionCB,
|
|
(XtSelectionDoneProc) NULL))
|
|
{
|
|
pDAS->primary = True;
|
|
pDAS->anchor_time = XtLastTimestampProcessed(XtDisplay(widget));
|
|
}
|
|
}
|
|
else
|
|
_DtHelpClearSelection (client_data);
|
|
|
|
} /* End _DtHelpGetClearSelection */
|