dtcalc: change from obsoleted MAXFLOAT to FLT_MAX from std C
[oweals/cde.git] / cde / lib / DtHelp / HyperText.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: HyperText.c /main/9 1999/10/14 14:45:38 mgreess $ */
24 /************************************<+>*************************************
25  ****************************************************************************
26  **
27  **   File:        HyperText.c
28  **
29  **   Project:     Text Graphic Display Library
30  **
31  **   Description: This body of code does all the work for hypertext links
32  **
33  **
34  **  (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
35  **
36  **  (c) Copyright 1993, 1994 Hewlett-Packard Company
37  **  (c) Copyright 1993, 1994 International Business Machines Corp.
38  **  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
39  **  (c) Copyright 1993, 1994 Novell, Inc.
40  **
41  **
42  **
43  ****************************************************************************
44  ************************************<+>*************************************/
45
46 /*
47  * system includes
48  */
49 #include <errno.h>
50 #include <signal.h>
51 #include <stdlib.h>
52 #ifdef __hpux
53 #include <time.h>
54 #else /* SUN and IBM */
55 #ifdef  _AIX
56 #include <sys/select.h>
57 #endif
58 #include <sys/time.h>
59 #include <sys/types.h>
60 #endif
61 #include <unistd.h>
62 #include <sys/wait.h>
63 #include <Xm/DialogS.h>
64
65
66 /*
67  * Canvas Engine
68  */
69 #include "CanvasP.h"
70
71 /*
72  * private includes
73  */
74 #include "HelpErrorP.h"
75 #include "DisplayAreaP.h"
76 #include "DisplayAreaI.h"
77 #include "FontI.h"
78 #include "HourGlassI.h"
79 #include "HyperTextI.h"
80 #include "HelposI.h"
81
82 #ifdef NLS16
83 #endif
84
85 /********    Private Function Declarations    ********/
86 static  void    ProcessEvents (
87                         DtHelpDispAreaStruct    *pDAS,
88                         pid_t                    child_pid,
89                         Boolean                  child_flag);
90 /********    End Private Function Declarations    ********/
91
92 /*********************************************************************
93  *              Private Variables
94  *********************************************************************/
95
96 typedef struct {
97         char    *link_spec;
98         int      type;
99         char    *descrip;
100 } HyperList;
101
102 /*********************************************************************
103  *              Private Functions
104  *********************************************************************/
105 /*********************************************************************
106  * ProcessEvents
107  * 
108  *    ProcessEvents will do a select on the socket until the child
109  *       dies.
110  *
111  *********************************************************************/
112 static void
113 ProcessEvents (
114     DtHelpDispAreaStruct        *pDAS,
115     pid_t                        child_pid,
116     Boolean                      child_flag)
117 {
118     int    result;
119
120     int   rMask;
121     int   myFd;
122     pid_t pid;
123     struct timeval *topPtr;
124     struct timeval  toStruct;
125
126     Display *dpy = XtDisplay (pDAS->dispWid);
127     XEvent   event;
128
129
130     /*
131      * set a small time out.
132      */
133     toStruct.tv_usec = 500000;          /* 500 miliseconds */
134     toStruct.tv_sec  = 0;
135     topPtr = &toStruct;
136
137     /*
138      * get the socket's file descriptor
139      */
140     myFd = ConnectionNumber (dpy);
141
142     do
143       {
144         rMask = (1 << (myFd % 32));             /* on t.o. select will clear */
145
146         if (!XPending(dpy))
147           {
148 #if     0
149             result = select(myFd+1, &rMask, 0, 0, topPtr);
150 #else
151             result = select(myFd+1, ((fd_set *)&rMask), 0, 0, topPtr);
152 #endif
153
154             /*
155              * check to see if the select happened because of
156              * a system interrupt.
157              */
158             /*
159              * otherwise an exposure event happened.
160              * fall through and XPending will be true,
161              * forcing us to go to the XmUpdateDisplay call.
162              */
163           }
164         else
165           {
166 /*
167  * SYSTEM - Use XtDisplatchEvent????
168  */
169             XNextEvent (dpy, &event);
170             if (event.type == Expose)
171                 XmUpdateDisplay (pDAS->dispWid);
172           }
173
174         /*
175          * check to see if the child is still going
176          */
177         pid = waitpid (child_pid, (int *) 0, WNOHANG);
178         if (pid == child_pid || pid == -1)
179             child_flag = True;
180
181       } while (!child_flag);
182 }
183
184 /*********************************************************************
185  *              Internal Public Functions
186  *********************************************************************/
187 /*********************************************************************
188  * _DtHelpExecProcedure
189  * 
190  *    _DtHelpExecProcedure will fork/exec the command passed in. It will
191  *       then allow only exposure events to be processed until the
192  *       child dies.
193  *
194  *********************************************************************/
195 void
196 _DtHelpExecProcedure (
197         XtPointer       client_data,
198         char *cmd )
199 {
200     pid_t pid;
201     XWindowAttributes attr;
202     char        *pShell = "sh";
203     Widget       shellWidget;
204     Boolean      childFlag = False;
205     pid_t        childPid;
206     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
207
208     /*
209      * Turn on the wait cursor.
210      */
211     shellWidget = pDAS->dispWid;
212     while (!XtIsSubclass(shellWidget, xmDialogShellWidgetClass))
213         shellWidget = XtParent(shellWidget);
214     
215      _DtHelpTurnOnHourGlass(shellWidget);
216     /*
217      * Get the window event mask via the window attributes. Remember it.
218      * Set the Input to only Exposure events.
219      */
220     XGetWindowAttributes (XtDisplay(pDAS->dispWid), XtWindow (pDAS->dispWid),
221                                                                 &attr);
222     XSelectInput (XtDisplay(pDAS->dispWid), XtWindow (pDAS->dispWid),
223                                                                 ExposureMask);
224
225     XSync (XtDisplay(pDAS->dispWid), 0);
226
227     /*
228      * initialize the global flag and variable.
229      */
230     childPid  = -1;
231     childFlag = False;
232
233     /*
234      * fork a child process.
235      */
236 #ifdef __hpux
237     childPid = vfork ();
238 #else
239     childPid = fork ();
240 #endif /* __hpux */
241
242     /*
243      * If the child, exec the cmd with a shell parent
244      * so if the cmd ends in an ampersand, the command
245      * will be put in the background and the shell will
246      * die and return, creating a SIGCLD for us to catch.
247      */
248     if (childPid == 0)
249       {
250         execlp (pShell, pShell, "-c", cmd, ((char *) 0));
251         _exit (1);
252       }
253
254     /*
255      * Check to make sure the vfork was successful.
256      */
257     if (childPid != -1)
258       {
259         /*
260          * check to see if the child is still going
261          */
262         pid = waitpid (childPid, (int *) 0, WNOHANG);
263         if (!(pid == childPid || pid == -1))
264             /*
265              * process the exposure events in a special routine.
266              */
267             ProcessEvents (pDAS, childPid, childFlag);
268       }
269
270     /*
271      * reset the input mask
272      */
273     XSelectInput (XtDisplay(pDAS->dispWid), XtWindow (pDAS->dispWid),
274                                                 (attr.your_event_mask));
275     /*
276      * turn off the wait cursor
277      */
278     _DtHelpTurnOffHourGlass(shellWidget);
279
280 } /* End _DtHelpExecProcedure */
281
282 /*********************************************************************
283  * Function: _DtHelpProcessHyperSelection
284  *
285  *    Determine if the user selected a segment that is a hypertext
286  *        link. If so, call the appropriate function to process it.
287  *
288  *********************************************************************/
289 void
290 _DtHelpProcessHyperSelection (
291         XtPointer        client_data,
292         int              downX,
293         int              downY,
294         XEvent          *event )
295 {
296
297     int    upX;
298     int    upY;
299
300     _DtCvLinkInfo  ceHyper;
301     DtHelpHyperTextStruct callData;
302     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
303
304     if (pDAS->hyperCall == NULL)
305         return;
306
307     downY = downY + pDAS->firstVisible - pDAS->decorThickness;
308     downX = downX + pDAS->virtualX     - pDAS->decorThickness;
309     upX   = event->xbutton.x + pDAS->virtualX     - pDAS->decorThickness;
310     upY   = event->xbutton.y + pDAS->firstVisible - pDAS->decorThickness;
311
312     /*
313      * turn off the old traversal
314      */
315     if (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG)
316       {
317         pDAS->toc_flag |= _DT_HELP_DRAW_TOC_IND;
318         _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_OFF, False,
319                                 (XtIsRealized(pDAS->dispWid) ? True : False),
320                                         NULL, NULL, NULL, NULL, NULL);
321       }
322
323     if (_DtCvSTATUS_OK ==
324                 _DtCanvasGetPosLink(pDAS->canvas,downX,downY,upX,upY,&ceHyper))
325       {
326         /*
327          * turn the traversal on for the selected hyptext link.
328          */
329         if (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG)
330           {
331             pDAS->toc_flag |= _DT_HELP_DRAW_TOC_IND;
332             _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ID, False,
333                                 (XtIsRealized(pDAS->dispWid) ? True : False),
334                                         ceHyper.specification,
335                                         NULL, NULL, NULL, NULL);
336           }
337
338         callData.reason        = XmCR_ACTIVATE;
339         callData.event         = event;
340         callData.window        = XtWindow (pDAS->dispWid);
341         callData.specification = ceHyper.specification;
342         callData.hyper_type    = ceHyper.hyper_type;
343         callData.window_hint   = ceHyper.win_hint;
344
345         (*(pDAS->hyperCall)) (pDAS, pDAS->clientData, &callData);
346       }
347     else if (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG)
348         /*
349          * turn the traversal back on
350          */
351         _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ON, False,
352                                 (XtIsRealized(pDAS->dispWid) ? True : False),
353                                         NULL, NULL, NULL, NULL, NULL);
354
355 }  /* End _DtHelpProcessHyperSelection */
356