357 lines
9.4 KiB
C
357 lines
9.4 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
|
|
*/
|
|
/* $TOG: HyperText.c /main/9 1999/10/14 14:45:38 mgreess $ */
|
|
/************************************<+>*************************************
|
|
****************************************************************************
|
|
**
|
|
** File: HyperText.c
|
|
**
|
|
** Project: Text Graphic Display Library
|
|
**
|
|
** Description: This body of code does all the work for hypertext links
|
|
**
|
|
**
|
|
** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
|
|
**
|
|
** (c) Copyright 1993, 1994 Hewlett-Packard Company
|
|
** (c) Copyright 1993, 1994 International Business Machines Corp.
|
|
** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
|
|
** (c) Copyright 1993, 1994 Novell, Inc.
|
|
**
|
|
**
|
|
**
|
|
****************************************************************************
|
|
************************************<+>*************************************/
|
|
|
|
/*
|
|
* system includes
|
|
*/
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include <stdlib.h>
|
|
#ifdef __hpux
|
|
#include <time.h>
|
|
#else /* SUN and IBM */
|
|
#ifdef _AIX
|
|
#include <sys/select.h>
|
|
#endif
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#endif
|
|
#include <unistd.h>
|
|
#include <sys/wait.h>
|
|
#include <Xm/DialogS.h>
|
|
|
|
|
|
/*
|
|
* Canvas Engine
|
|
*/
|
|
#include "CanvasP.h"
|
|
|
|
/*
|
|
* private includes
|
|
*/
|
|
#include "HelpErrorP.h"
|
|
#include "DisplayAreaP.h"
|
|
#include "DisplayAreaI.h"
|
|
#include "FontI.h"
|
|
#include "HourGlassI.h"
|
|
#include "HyperTextI.h"
|
|
#include "HelposI.h"
|
|
|
|
#ifdef NLS16
|
|
#endif
|
|
|
|
/******** Private Function Declarations ********/
|
|
static void ProcessEvents (
|
|
DtHelpDispAreaStruct *pDAS,
|
|
pid_t child_pid,
|
|
Boolean child_flag);
|
|
/******** End Private Function Declarations ********/
|
|
|
|
/*********************************************************************
|
|
* Private Variables
|
|
*********************************************************************/
|
|
|
|
typedef struct {
|
|
char *link_spec;
|
|
int type;
|
|
char *descrip;
|
|
} HyperList;
|
|
|
|
/*********************************************************************
|
|
* Private Functions
|
|
*********************************************************************/
|
|
/*********************************************************************
|
|
* ProcessEvents
|
|
*
|
|
* ProcessEvents will do a select on the socket until the child
|
|
* dies.
|
|
*
|
|
*********************************************************************/
|
|
static void
|
|
ProcessEvents (
|
|
DtHelpDispAreaStruct *pDAS,
|
|
pid_t child_pid,
|
|
Boolean child_flag)
|
|
{
|
|
int result;
|
|
|
|
int rMask;
|
|
int myFd;
|
|
pid_t pid;
|
|
struct timeval *topPtr;
|
|
struct timeval toStruct;
|
|
|
|
Display *dpy = XtDisplay (pDAS->dispWid);
|
|
XEvent event;
|
|
|
|
|
|
/*
|
|
* set a small time out.
|
|
*/
|
|
toStruct.tv_usec = 500000; /* 500 miliseconds */
|
|
toStruct.tv_sec = 0;
|
|
topPtr = &toStruct;
|
|
|
|
/*
|
|
* get the socket's file descriptor
|
|
*/
|
|
myFd = ConnectionNumber (dpy);
|
|
|
|
do
|
|
{
|
|
rMask = (1 << (myFd % 32)); /* on t.o. select will clear */
|
|
|
|
if (!XPending(dpy))
|
|
{
|
|
#if 0
|
|
result = select(myFd+1, &rMask, 0, 0, topPtr);
|
|
#else
|
|
result = select(myFd+1, ((fd_set *)&rMask), 0, 0, topPtr);
|
|
#endif
|
|
|
|
/*
|
|
* check to see if the select happened because of
|
|
* a system interrupt.
|
|
*/
|
|
/*
|
|
* otherwise an exposure event happened.
|
|
* fall through and XPending will be true,
|
|
* forcing us to go to the XmUpdateDisplay call.
|
|
*/
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* SYSTEM - Use XtDisplatchEvent????
|
|
*/
|
|
XNextEvent (dpy, &event);
|
|
if (event.type == Expose)
|
|
XmUpdateDisplay (pDAS->dispWid);
|
|
}
|
|
|
|
/*
|
|
* check to see if the child is still going
|
|
*/
|
|
pid = waitpid (child_pid, (int *) 0, WNOHANG);
|
|
if (pid == child_pid || pid == -1)
|
|
child_flag = True;
|
|
|
|
} while (!child_flag);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* Internal Public Functions
|
|
*********************************************************************/
|
|
/*********************************************************************
|
|
* _DtHelpExecProcedure
|
|
*
|
|
* _DtHelpExecProcedure will fork/exec the command passed in. It will
|
|
* then allow only exposure events to be processed until the
|
|
* child dies.
|
|
*
|
|
*********************************************************************/
|
|
void
|
|
_DtHelpExecProcedure (
|
|
XtPointer client_data,
|
|
char *cmd )
|
|
{
|
|
pid_t pid;
|
|
XWindowAttributes attr;
|
|
char *pShell = "sh";
|
|
Widget shellWidget;
|
|
Boolean childFlag = False;
|
|
pid_t childPid;
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
|
|
|
|
/*
|
|
* Turn on the wait cursor.
|
|
*/
|
|
shellWidget = pDAS->dispWid;
|
|
while (!XtIsSubclass(shellWidget, xmDialogShellWidgetClass))
|
|
shellWidget = XtParent(shellWidget);
|
|
|
|
_DtHelpTurnOnHourGlass(shellWidget);
|
|
/*
|
|
* Get the window event mask via the window attributes. Remember it.
|
|
* Set the Input to only Exposure events.
|
|
*/
|
|
XGetWindowAttributes (XtDisplay(pDAS->dispWid), XtWindow (pDAS->dispWid),
|
|
&attr);
|
|
XSelectInput (XtDisplay(pDAS->dispWid), XtWindow (pDAS->dispWid),
|
|
ExposureMask);
|
|
|
|
XSync (XtDisplay(pDAS->dispWid), 0);
|
|
|
|
/*
|
|
* initialize the global flag and variable.
|
|
*/
|
|
childPid = -1;
|
|
childFlag = False;
|
|
|
|
/*
|
|
* fork a child process.
|
|
*/
|
|
#ifdef __hpux
|
|
childPid = vfork ();
|
|
#else
|
|
childPid = fork ();
|
|
#endif /* __hpux */
|
|
|
|
/*
|
|
* If the child, exec the cmd with a shell parent
|
|
* so if the cmd ends in an ampersand, the command
|
|
* will be put in the background and the shell will
|
|
* die and return, creating a SIGCLD for us to catch.
|
|
*/
|
|
if (childPid == 0)
|
|
{
|
|
execlp (pShell, pShell, "-c", cmd, ((char *) 0));
|
|
_exit (1);
|
|
}
|
|
|
|
/*
|
|
* Check to make sure the vfork was successful.
|
|
*/
|
|
if (childPid != -1)
|
|
{
|
|
/*
|
|
* check to see if the child is still going
|
|
*/
|
|
pid = waitpid (childPid, (int *) 0, WNOHANG);
|
|
if (!(pid == childPid || pid == -1))
|
|
/*
|
|
* process the exposure events in a special routine.
|
|
*/
|
|
ProcessEvents (pDAS, childPid, childFlag);
|
|
}
|
|
|
|
/*
|
|
* reset the input mask
|
|
*/
|
|
XSelectInput (XtDisplay(pDAS->dispWid), XtWindow (pDAS->dispWid),
|
|
(attr.your_event_mask));
|
|
/*
|
|
* turn off the wait cursor
|
|
*/
|
|
_DtHelpTurnOffHourGlass(shellWidget);
|
|
|
|
} /* End _DtHelpExecProcedure */
|
|
|
|
/*********************************************************************
|
|
* Function: _DtHelpProcessHyperSelection
|
|
*
|
|
* Determine if the user selected a segment that is a hypertext
|
|
* link. If so, call the appropriate function to process it.
|
|
*
|
|
*********************************************************************/
|
|
void
|
|
_DtHelpProcessHyperSelection (
|
|
XtPointer client_data,
|
|
int downX,
|
|
int downY,
|
|
XEvent *event )
|
|
{
|
|
|
|
int upX;
|
|
int upY;
|
|
|
|
_DtCvLinkInfo ceHyper;
|
|
DtHelpHyperTextStruct callData;
|
|
DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
|
|
|
|
if (pDAS->hyperCall == NULL)
|
|
return;
|
|
|
|
downY = downY + pDAS->firstVisible - pDAS->decorThickness;
|
|
downX = downX + pDAS->virtualX - pDAS->decorThickness;
|
|
upX = event->xbutton.x + pDAS->virtualX - pDAS->decorThickness;
|
|
upY = event->xbutton.y + pDAS->firstVisible - pDAS->decorThickness;
|
|
|
|
/*
|
|
* turn off the old traversal
|
|
*/
|
|
if (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG)
|
|
{
|
|
pDAS->toc_flag |= _DT_HELP_DRAW_TOC_IND;
|
|
_DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_OFF, False,
|
|
(XtIsRealized(pDAS->dispWid) ? True : False),
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
}
|
|
|
|
if (_DtCvSTATUS_OK ==
|
|
_DtCanvasGetPosLink(pDAS->canvas,downX,downY,upX,upY,&ceHyper))
|
|
{
|
|
/*
|
|
* turn the traversal on for the selected hyptext link.
|
|
*/
|
|
if (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG)
|
|
{
|
|
pDAS->toc_flag |= _DT_HELP_DRAW_TOC_IND;
|
|
_DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ID, False,
|
|
(XtIsRealized(pDAS->dispWid) ? True : False),
|
|
ceHyper.specification,
|
|
NULL, NULL, NULL, NULL);
|
|
}
|
|
|
|
callData.reason = XmCR_ACTIVATE;
|
|
callData.event = event;
|
|
callData.window = XtWindow (pDAS->dispWid);
|
|
callData.specification = ceHyper.specification;
|
|
callData.hyper_type = ceHyper.hyper_type;
|
|
callData.window_hint = ceHyper.win_hint;
|
|
|
|
(*(pDAS->hyperCall)) (pDAS, pDAS->clientData, &callData);
|
|
}
|
|
else if (pDAS->neededFlags & _DT_HELP_FOCUS_FLAG)
|
|
/*
|
|
* turn the traversal back on
|
|
*/
|
|
_DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ON, False,
|
|
(XtIsRealized(pDAS->dispWid) ? True : False),
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
|
|
} /* End _DtHelpProcessHyperSelection */
|
|
|