658 lines
18 KiB
C
658 lines
18 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 libraries and programs; if not, write
|
||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||
* Floor, Boston, MA 02110-1301 USA
|
||
*/
|
||
/* $XConsortium: Util.c /main/5 1996/09/30 11:29:05 cde-hp $ */
|
||
/*************************************<+>*************************************
|
||
*****************************************************************************
|
||
**
|
||
** File: Util.c
|
||
**
|
||
** Project: Cache Creek
|
||
**
|
||
** Description: Contains the Help Callback and Utility functions for or
|
||
** preview tool and DT 3.0 help browser tool.
|
||
**
|
||
** (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 Include Files */
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <signal.h>
|
||
|
||
#include <X11/Intrinsic.h>
|
||
#include <X11/Shell.h>
|
||
#include <X11/Xatom.h>
|
||
#include <X11/Xutil.h>
|
||
|
||
#include <Xm/MwmUtil.h>
|
||
#include <Xm/Protocols.h>
|
||
#include <Xm/Xm.h>
|
||
#include <Xm/XmP.h>
|
||
#include <Xm/Text.h>
|
||
|
||
#include <Dt/Help.h>
|
||
#include <Dt/HelpP.h>
|
||
#include <Dt/HelpDialog.h>
|
||
#include <Dt/HelpQuickD.h>
|
||
|
||
|
||
#include <DtI/HelposI.h>
|
||
#include <DtI/HourGlassI.h>
|
||
/* Local Includes */
|
||
#include "Main.h"
|
||
#include "UtilI.h"
|
||
|
||
|
||
/******** Static Function Declarations ********/
|
||
|
||
|
||
|
||
static void CloseQuickHelpCB(
|
||
Widget w,
|
||
XtPointer clientData,
|
||
XtPointer callData);
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/****************************************************************************
|
||
* Function: CloseAndExitCB(
|
||
* Widget w,
|
||
* XtPointer clientData,
|
||
* XtPointer callData
|
||
*
|
||
* Parameters:
|
||
*
|
||
* Return Value: Void.
|
||
*
|
||
* Purpose: Closes the helpview process when the users
|
||
* closes either a man page view or a ascii
|
||
* text file view.
|
||
*
|
||
***************************************************************************/
|
||
void CloseAndExitCB(
|
||
Widget w,
|
||
XtPointer clientData,
|
||
XtPointer callData)
|
||
{
|
||
|
||
/* We just want to go away here */
|
||
exit (0);
|
||
}
|
||
|
||
|
||
|
||
|
||
/****************************************************************************
|
||
* Function: CloseQuickHelpCB(
|
||
* Widget w,
|
||
* XtPointer clientData,
|
||
* XtPointer callData
|
||
*
|
||
* Parameters:
|
||
*
|
||
* Return Value: Void.
|
||
*
|
||
* Purpose: Closes the Quick Help dialog without exiting.
|
||
*
|
||
***************************************************************************/
|
||
static void CloseQuickHelpCB(
|
||
Widget w,
|
||
XtPointer clientData,
|
||
XtPointer callData)
|
||
{
|
||
|
||
/* We just unmanage the dialog */
|
||
XtUnmanageChild(viewWidget);
|
||
}
|
||
|
||
|
||
|
||
|
||
/****************************************************************************
|
||
* Function: CloseHelpCB(
|
||
* Widget w,
|
||
* XtPointer clientData,
|
||
* XtPointer callData
|
||
*
|
||
* Parameters:
|
||
*
|
||
* Return Value: Void.
|
||
*
|
||
* Purpose: Process close requests on all Help Dialog widgets
|
||
* created and managed by this application.
|
||
*
|
||
***************************************************************************/
|
||
void CloseHelpCB (
|
||
Widget w,
|
||
XtPointer clientData,
|
||
XtPointer callData)
|
||
{
|
||
|
||
Widget helpDialog = (Widget) clientData;
|
||
|
||
CacheListStruct *pTemp;
|
||
CacheListStruct *pTempCurrent;
|
||
|
||
pTemp = pCacheListHead;
|
||
|
||
/* Search our Cache List for the closed help dialog */
|
||
while ((pTemp != NULL) && (pTemp->helpDialog != helpDialog))
|
||
pTemp = pTemp->pNext;
|
||
|
||
|
||
if (pTemp == NULL) {
|
||
/* ERROR */
|
||
printf("We did not find our help dialog widget in the cache list??? /n");
|
||
/* TODO what error handling here? */
|
||
return;
|
||
}
|
||
|
||
/* Un Map and Clean up the help widget */
|
||
XtUnmanageChild(helpDialog);
|
||
pTemp->inUseFlag = FALSE;
|
||
|
||
|
||
/* Re-Assign our pTemp to point to our head so we can see
|
||
* if we have any in-use help dialog in our list.
|
||
*/
|
||
pTemp = pCacheListHead;
|
||
|
||
/* Check and see if we should exit */
|
||
while (pTemp != NULL && (pTemp->inUseFlag != TRUE))
|
||
pTemp = pTemp->pNext;
|
||
|
||
if (pTemp == NULL) /* We have no dialog mapped so exit */
|
||
{
|
||
/* Lets clean up our cache list just for fun, prior to exiting */
|
||
pTemp = pCacheListHead;
|
||
while (pTemp != NULL)
|
||
{
|
||
pTempCurrent = pTemp;
|
||
pTemp = pTemp->pNext;
|
||
XtDestroyWidget(pTempCurrent->helpDialog);
|
||
}
|
||
|
||
exit (0);
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
/****************************************************************************
|
||
* Function: void ProcessLinkCB(
|
||
* Widget w,
|
||
* XtPointer clientData,
|
||
* XtPointer callData
|
||
*
|
||
* Parameters:
|
||
*
|
||
* Return Value: Void.
|
||
*
|
||
* Purpose: Process JUMP-NEW and APP-LINK hypertext requests in a
|
||
* given Help Dialog Window.
|
||
*
|
||
* This is the callback used for the DtNhyperLinkCallback
|
||
* on each of the help dialog widges created.
|
||
*
|
||
****************************************************************************/
|
||
void ProcessLinkCB (
|
||
Widget w,
|
||
XtPointer clientData,
|
||
XtPointer callData)
|
||
|
||
{
|
||
|
||
DtHelpDialogCallbackStruct * hyperData =
|
||
(DtHelpDialogCallbackStruct *) callData;
|
||
|
||
|
||
switch (hyperData->hyperType)
|
||
{
|
||
case DtHELP_LINK_JUMP_NEW:
|
||
|
||
DisplayTopic (topLevel, hyperData->helpVolume,
|
||
hyperData->locationId, 0, NULL);
|
||
|
||
break;
|
||
|
||
|
||
case DtHELP_LINK_MAN_PAGE:
|
||
/* Add support for man links */
|
||
DisplayMan(topLevel, hyperData->specification, NO_EXIT_ON_CLOSE);
|
||
|
||
break;
|
||
|
||
case DtHELP_LINK_APP_DEFINE:
|
||
/* Send out the proper warning (e.g. message 14) */
|
||
break;
|
||
|
||
|
||
default:
|
||
|
||
/* ERROR */
|
||
/* Send out warning (e.g. message 15) */
|
||
break;
|
||
|
||
|
||
} /* End Switch Statement */
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/****************************************************************************
|
||
* Function: void DisplayTopic(
|
||
* Widget parent,
|
||
* char *helpVolume,
|
||
* char *locationId)
|
||
*
|
||
* Parameters:
|
||
*
|
||
* Return Value: Void.
|
||
*
|
||
* Purpose: Displays a new Cache Creek help topic in a new/cached
|
||
* help dialog widget.
|
||
*
|
||
****************************************************************************/
|
||
void DisplayTopic (
|
||
Widget parent,
|
||
char *helpVolume,
|
||
char *locationId,
|
||
int argc,
|
||
char **argv)
|
||
|
||
{
|
||
Arg args[15];
|
||
int n;
|
||
CacheListStruct *pCurrentNode = NULL;
|
||
Boolean cachedNode = FALSE;
|
||
char *titleString;
|
||
|
||
/* If we have a null location id within helpview we want to force
|
||
* it to the default: _HOMETOPIC.
|
||
*/
|
||
if (locationId == NULL)
|
||
locationId = XtNewString("_HOMETOPIC");
|
||
|
||
/* Get a used or new node form our cache if we have one */
|
||
cachedNode = GetFromCache(parent, &pCurrentNode);
|
||
|
||
|
||
titleString = XtNewString((char*)_DTGETMESSAGE (7,20,"Help Viewer"));
|
||
|
||
/* If we got a free one from the Cache, use it */
|
||
/* Set Values on current free one, then map it */
|
||
if (cachedNode)
|
||
{
|
||
|
||
n = 0;
|
||
XtSetArg (args[n], XmNtitle, titleString); n++;
|
||
if (helpVolume != NULL)
|
||
{
|
||
XtSetArg (args[n],DtNhelpVolume,helpVolume); n++;
|
||
}
|
||
XtSetArg (args[n], DtNlocationId,locationId); n++;
|
||
XtSetArg (args[n], DtNhelpType, DtHELP_TYPE_TOPIC); n++;
|
||
|
||
XtSetValues(pCurrentNode->helpDialog, args, n);
|
||
|
||
XtManageChild(pCurrentNode->helpDialog);
|
||
}
|
||
else
|
||
{
|
||
/* Build a new one in our cached list */
|
||
n = 0;
|
||
XtSetArg (args[n], XmNuseAsyncGeometry, True); n++;
|
||
XtSetArg (args[n], XmNtitle, titleString); n++;
|
||
XtSetArg (args[n], DtNshowTopLevelButton, TRUE); n++;
|
||
XtSetArg (args[n], DtNshowNewWindowButton, TRUE); n++;
|
||
if (helpVolume != NULL)
|
||
{
|
||
XtSetArg (args[n],DtNhelpVolume,helpVolume); n++;
|
||
}
|
||
XtSetArg (args[n], DtNlocationId,locationId); n++;
|
||
pCurrentNode->helpDialog =
|
||
DtCreateHelpDialog(parent, "helpWidget", args, n);
|
||
|
||
|
||
XtAddCallback(pCurrentNode->helpDialog, DtNhyperLinkCallback,
|
||
ProcessLinkCB, NULL);
|
||
|
||
XtAddCallback(pCurrentNode->helpDialog, DtNcloseCallback,
|
||
CloseHelpCB,(XtPointer) pCurrentNode->helpDialog);
|
||
|
||
XtManageChild(pCurrentNode->helpDialog);
|
||
|
||
/* Set the wm_command property on the help dialog window */
|
||
if (argc != 0)
|
||
XSetCommand(appDisplay,
|
||
XtWindow(XtParent(pCurrentNode->helpDialog)), argv, argc);
|
||
|
||
}
|
||
|
||
XtFree(titleString);
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/****************************************************************************
|
||
* Function: CacheListStruct GetFromCache(
|
||
* Widget parent);
|
||
*
|
||
* Parameters:
|
||
*
|
||
* Return Value: Void.
|
||
*
|
||
* Purpose: Gets a free help node form our cache list. If none are
|
||
* free, it will return fallse and the calling routine will
|
||
* create a new help dialog widget.
|
||
*
|
||
****************************************************************************/
|
||
Boolean GetFromCache(
|
||
Widget parent,
|
||
CacheListStruct **pCurrentNode)
|
||
|
||
{
|
||
|
||
CacheListStruct *pTemp;
|
||
|
||
if (pCacheListHead == NULL)
|
||
{
|
||
/* We have a new list so lets create one and pass it back */
|
||
pCacheListHead =
|
||
(CacheListStruct *) XtMalloc((sizeof(CacheListStruct)));
|
||
|
||
/* Assign the default values to our node */
|
||
pCacheListHead->helpDialog = NULL;
|
||
pCacheListHead->inUseFlag = TRUE;
|
||
pCacheListHead->pNext = NULL;
|
||
pCacheListHead->pPrevious = NULL;
|
||
|
||
/* Assign our tale pointer */
|
||
pCacheListTale = pCacheListHead;
|
||
|
||
/* Make sure or totalNodes counter is correct, e.g. force it to 1 */
|
||
totalCacheNodes = 1;
|
||
|
||
/* Return our head pointer because it's our first and only node */
|
||
*pCurrentNode = pCacheListHead;
|
||
return (FALSE);
|
||
|
||
}
|
||
else
|
||
{
|
||
/* We have some nodes so search for a free one first */
|
||
pTemp = pCacheListHead;
|
||
|
||
while (pTemp != NULL)
|
||
{
|
||
if (pTemp->inUseFlag == FALSE)
|
||
{
|
||
pTemp->inUseFlag = TRUE;
|
||
*pCurrentNode = pTemp;
|
||
return (TRUE);
|
||
}
|
||
else
|
||
pTemp = pTemp->pNext;
|
||
}
|
||
|
||
|
||
/* If we did not find a free nod then we must add a new one to the
|
||
* top of the list, and return it.
|
||
*/
|
||
|
||
pTemp = (CacheListStruct *) XtMalloc((sizeof(CacheListStruct)));
|
||
|
||
/* Assign the default values to our node */
|
||
pTemp->helpDialog = NULL;
|
||
pTemp->inUseFlag = TRUE;
|
||
|
||
pTemp->pNext = pCacheListHead;
|
||
pTemp->pPrevious = NULL;
|
||
|
||
pCacheListHead->pPrevious = pTemp;
|
||
|
||
/* Re-Assign our head pointer to point to the new head of the list */
|
||
pCacheListHead = pTemp;
|
||
|
||
/* Make sure or totalNodes counter is correct, e.g. force it to 1 */
|
||
totalCacheNodes = totalCacheNodes + 1;
|
||
|
||
/* Return our head pointer because it's our new node */
|
||
*pCurrentNode = pCacheListHead;
|
||
return (FALSE);
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/****************************************************************************
|
||
* Function: void DisplayFile(
|
||
*
|
||
* Parameters:
|
||
*
|
||
* Return Value: Void.
|
||
*
|
||
* Purpose: Displays a ascii file in a quick help dialog.
|
||
*
|
||
****************************************************************************/
|
||
void DisplayFile (
|
||
Widget parent,
|
||
char *file)
|
||
|
||
{
|
||
|
||
Arg args[20];
|
||
int n;
|
||
Widget helpWidget;
|
||
Widget backWidget;
|
||
char *title;
|
||
XmString printString;
|
||
XmString exitString;
|
||
|
||
|
||
/* Create the QuickHelpDialog widget for help on help */
|
||
title = XtNewString(file);
|
||
printString = XmStringCreateLocalized((char *)_DTGETMESSAGE(7,19,"Print ..."));
|
||
exitString = XmStringCreateLocalized((char *)_DTGETMESSAGE(7, 16, "Exit"));
|
||
|
||
n =0;
|
||
XtSetArg (args[n], XmNuseAsyncGeometry, True); n++;
|
||
XtSetArg (args[n], XmNtitle, title); n++;
|
||
XtSetArg (args[n], DtNprintLabelString, printString); n++;
|
||
XtSetArg (args[n], XmNokLabelString, exitString); n++;
|
||
XtSetArg (args[n], DtNhelpType,DtHELP_TYPE_FILE); n++;
|
||
XtSetArg (args[n], DtNhelpFile, file); n++;
|
||
XtSetArg (args[n], XmNscrollBarPlacement,
|
||
DtHELP_AS_NEEDED_SCROLLBARS); n++;
|
||
viewWidget = DtCreateHelpQuickDialog(parent,"fileBox", args, n);
|
||
XmStringFree(printString);
|
||
XmStringFree(exitString);
|
||
XtFree((char*) title);
|
||
|
||
/* Catch the close callback so we can destroy the widget */
|
||
XtAddCallback(viewWidget, DtNcloseCallback,
|
||
CloseAndExitCB, (XtPointer) NULL);
|
||
|
||
/* We do not want a help button for now so we unmap it */
|
||
helpWidget = DtHelpQuickDialogGetChild (viewWidget,DtHELP_QUICK_HELP_BUTTON);
|
||
XtUnmanageChild (helpWidget);
|
||
|
||
/* We do not want a backtrack button for now so we unmap it */
|
||
backWidget = DtHelpQuickDialogGetChild (viewWidget,DtHELP_QUICK_BACK_BUTTON);
|
||
XtUnmanageChild (backWidget);
|
||
|
||
/* Display the dialog */
|
||
XtManageChild(viewWidget);
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/****************************************************************************
|
||
* Function: void DisplayMan()
|
||
*
|
||
* Parameters:
|
||
*
|
||
* Return Value: Void.
|
||
*
|
||
* Purpose: Displays a UNIX man page in a quick help dialog.
|
||
*
|
||
****************************************************************************/
|
||
void DisplayMan (
|
||
Widget parent,
|
||
char *man,
|
||
int closeOption)
|
||
|
||
{
|
||
|
||
Arg args[20];
|
||
int n;
|
||
Widget helpWidget;
|
||
char *title;
|
||
XmString printString;
|
||
XmString exitString;
|
||
XmString backString;
|
||
|
||
XmUpdateDisplay(topLevel);
|
||
|
||
|
||
if (viewWidget == NULL)
|
||
{
|
||
/* Create the QuickHelpDialog widget for help on help */
|
||
title = XtNewString(man);
|
||
printString = XmStringCreateLocalized((char *)_DTGETMESSAGE(
|
||
7, 19, "Print ..."));
|
||
|
||
backString = XmStringCreateLocalized((char *)_DTGETMESSAGE(
|
||
7, 18, "Backtrack"));
|
||
|
||
if (closeOption == EXIT_ON_CLOSE)
|
||
{
|
||
exitString = XmStringCreateLocalized((char *)_DTGETMESSAGE(
|
||
7, 16, "Exit"));
|
||
}
|
||
else
|
||
{
|
||
exitString = XmStringCreateLocalized((char *)_DTGETMESSAGE(
|
||
7, 17, "Close"));
|
||
}
|
||
|
||
n =0;
|
||
XtSetArg (args[n], XmNuseAsyncGeometry, True); n++;
|
||
XtSetArg (args[n], XmNtitle, title); n++;
|
||
XtSetArg (args[n], DtNbackLabelString, backString); n++;
|
||
XtSetArg (args[n], DtNprintLabelString, printString); n++;
|
||
XtSetArg (args[n], XmNokLabelString, exitString); n++;
|
||
XtSetArg (args[n], DtNhelpType,DtHELP_TYPE_MAN_PAGE); n++;
|
||
XtSetArg (args[n], DtNmanPage, man); n++;
|
||
XtSetArg (args[n], XmNscrollBarPlacement,
|
||
DtHELP_AS_NEEDED_SCROLLBARS); n++;
|
||
viewWidget = DtCreateHelpQuickDialog(parent,"manBox", args, n);
|
||
XmStringFree(printString);
|
||
XmStringFree(exitString);
|
||
XmStringFree(backString);
|
||
XtFree((char*) title);
|
||
|
||
if (closeOption == EXIT_ON_CLOSE)
|
||
{
|
||
XtAddCallback(viewWidget, DtNcloseCallback,
|
||
CloseAndExitCB, (XtPointer) NULL);
|
||
|
||
}
|
||
else
|
||
{
|
||
XtAddCallback(viewWidget, DtNcloseCallback,
|
||
CloseQuickHelpCB, (XtPointer) NULL);
|
||
}
|
||
|
||
/* We do not want a help button for now so we unmap it */
|
||
helpWidget = DtHelpQuickDialogGetChild (viewWidget,DtHELP_QUICK_HELP_BUTTON);
|
||
XtUnmanageChild (helpWidget);
|
||
|
||
XtManageChild(viewWidget);
|
||
}
|
||
else
|
||
{
|
||
_DtHelpTurnOnHourGlass(viewWidget);
|
||
|
||
/* We already have a quick help dialog so re-use it */
|
||
n = 0;
|
||
XtSetArg (args[n], DtNhelpType,DtHELP_TYPE_MAN_PAGE); n++;
|
||
XtSetArg (args[n], DtNmanPage, man); n++;
|
||
|
||
XtSetValues(viewWidget, args, n);
|
||
|
||
|
||
title = XtNewString(man);
|
||
n = 0;
|
||
XtSetArg (args[n], XmNtitle, title); n++;
|
||
XtSetValues(XtParent(viewWidget), args, n);
|
||
XtFree((char*) title);
|
||
|
||
XtManageChild(viewWidget);
|
||
XtMapWidget(XtParent(viewWidget));
|
||
XRaiseWindow(appDisplay, XtWindow(XtParent(viewWidget)));
|
||
_DtHelpTurnOffHourGlass(viewWidget);
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|