1 /* $TOG: HyperText.c /main/9 1999/10/14 14:45:38 mgreess $ */
2 /************************************<+>*************************************
3 ****************************************************************************
7 ** Project: Text Graphic Display Library
9 ** Description: This body of code does all the work for hypertext links
12 ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
14 ** (c) Copyright 1993, 1994 Hewlett-Packard Company
15 ** (c) Copyright 1993, 1994 International Business Machines Corp.
16 ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
17 ** (c) Copyright 1993, 1994 Novell, Inc.
21 ****************************************************************************
22 ************************************<+>*************************************/
32 #else /* SUN and IBM */
34 #include <sys/select.h>
37 #include <sys/types.h>
41 #include <Xm/DialogS.h>
52 #include "HelpErrorP.h"
53 #include "DisplayAreaP.h"
54 #include "DisplayAreaI.h"
56 #include "HourGlassI.h"
57 #include "HyperTextI.h"
63 /******** Private Function Declarations ********/
64 static void ProcessEvents (
65 DtHelpDispAreaStruct *pDAS,
68 /******** End Private Function Declarations ********/
70 /*********************************************************************
72 *********************************************************************/
80 /*********************************************************************
82 *********************************************************************/
83 /*********************************************************************
86 * ProcessEvents will do a select on the socket until the child
89 *********************************************************************/
92 DtHelpDispAreaStruct *pDAS,
101 struct timeval *topPtr;
102 struct timeval toStruct;
104 Display *dpy = XtDisplay (pDAS->dispWid);
109 * set a small time out.
111 toStruct.tv_usec = 500000; /* 500 miliseconds */
116 * get the socket's file descriptor
118 myFd = ConnectionNumber (dpy);
122 rMask = (1 << (myFd % 32)); /* on t.o. select will clear */
127 result = select(myFd+1, &rMask, 0, 0, topPtr);
129 result = select(myFd+1, ((fd_set *)&rMask), 0, 0, topPtr);
133 * check to see if the select happened because of
134 * a system interrupt.
137 * otherwise an exposure event happened.
138 * fall through and XPending will be true,
139 * forcing us to go to the XmUpdateDisplay call.
145 * SYSTEM - Use XtDisplatchEvent????
147 XNextEvent (dpy, &event);
148 if (event.type == Expose)
149 XmUpdateDisplay (pDAS->dispWid);
153 * check to see if the child is still going
155 pid = waitpid (child_pid, (int *) 0, WNOHANG);
156 if (pid == child_pid || pid == -1)
159 } while (!child_flag);
162 /*********************************************************************
163 * Internal Public Functions
164 *********************************************************************/
165 /*********************************************************************
166 * _DtHelpExecProcedure
168 * _DtHelpExecProcedure will fork/exec the command passed in. It will
169 * then allow only exposure events to be processed until the
172 *********************************************************************/
174 _DtHelpExecProcedure (
175 XtPointer client_data,
179 XWindowAttributes attr;
182 Boolean childFlag = False;
184 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
187 * Turn on the wait cursor.
189 shellWidget = pDAS->dispWid;
190 while (!XtIsSubclass(shellWidget, xmDialogShellWidgetClass))
191 shellWidget = XtParent(shellWidget);
193 _DtHelpTurnOnHourGlass(shellWidget);
195 * Get the window event mask via the window attributes. Remember it.
196 * Set the Input to only Exposure events.
198 XGetWindowAttributes (XtDisplay(pDAS->dispWid), XtWindow (pDAS->dispWid),
200 XSelectInput (XtDisplay(pDAS->dispWid), XtWindow (pDAS->dispWid),
203 XSync (XtDisplay(pDAS->dispWid), 0);
206 * initialize the global flag and variable.
212 * fork a child process.
221 * If the child, exec the cmd with a shell parent
222 * so if the cmd ends in an ampersand, the command
223 * will be put in the background and the shell will
224 * die and return, creating a SIGCLD for us to catch.
228 execlp (pShell, pShell, "-c", cmd, ((char *) 0));
233 * Check to make sure the vfork was successful.
238 * check to see if the child is still going
240 pid = waitpid (childPid, (int *) 0, WNOHANG);
241 if (!(pid == childPid || pid == -1))
243 * process the exposure events in a special routine.
245 ProcessEvents (pDAS, childPid, childFlag);
249 * reset the input mask
251 XSelectInput (XtDisplay(pDAS->dispWid), XtWindow (pDAS->dispWid),
252 (attr.your_event_mask));
254 * turn off the wait cursor
256 _DtHelpTurnOffHourGlass(shellWidget);
258 } /* End _DtHelpExecProcedure */
260 /*********************************************************************
261 * Function: _DtHelpProcessHyperSelection
263 * Determine if the user selected a segment that is a hypertext
264 * link. If so, call the appropriate function to process it.
266 *********************************************************************/
268 _DtHelpProcessHyperSelection (
269 XtPointer client_data,
278 _DtCvLinkInfo ceHyper;
279 DtHelpHyperTextStruct callData;
280 DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
282 if (pDAS->hyperCall == NULL)
285 downY = downY + pDAS->firstVisible - pDAS->decorThickness;
286 downX = downX + pDAS->virtualX - pDAS->decorThickness;
287 upX = event->xbutton.x + pDAS->virtualX - pDAS->decorThickness;
288 upY = event->xbutton.y + pDAS->firstVisible - pDAS->decorThickness;
291 * turn off the old traversal
293 if (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG)
295 pDAS->toc_flag |= _DT_HELP_DRAW_TOC_IND;
296 _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_OFF, False,
297 (XtIsRealized(pDAS->dispWid) ? True : False),
298 NULL, NULL, NULL, NULL, NULL);
301 if (_DtCvSTATUS_OK ==
302 _DtCanvasGetPosLink(pDAS->canvas,downX,downY,upX,upY,&ceHyper))
305 * turn the traversal on for the selected hyptext link.
307 if (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG)
309 pDAS->toc_flag |= _DT_HELP_DRAW_TOC_IND;
310 _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ID, False,
311 (XtIsRealized(pDAS->dispWid) ? True : False),
312 ceHyper.specification,
313 NULL, NULL, NULL, NULL);
316 callData.reason = XmCR_ACTIVATE;
317 callData.event = event;
318 callData.window = XtWindow (pDAS->dispWid);
319 callData.specification = ceHyper.specification;
320 callData.hyper_type = ceHyper.hyper_type;
321 callData.window_hint = ceHyper.win_hint;
323 (*(pDAS->hyperCall)) (pDAS, pDAS->clientData, &callData);
325 else if (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG)
327 * turn the traversal back on
329 _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ON, False,
330 (XtIsRealized(pDAS->dispWid) ? True : False),
331 NULL, NULL, NULL, NULL, NULL);
333 } /* End _DtHelpProcessHyperSelection */