1 /* $XConsortium: HelpCache.c /main/4 1995/11/08 09:17:54 rswiston $ */
2 /*************************************<+>*************************************
3 *****************************************************************************
7 ** Project: dthelpdemo demo program
9 ** Description: Contains the Help Callbacks and Utility functions for our
10 ** demo tool dthelpdemo.
13 ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994
14 ** 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 Unix System Labs, Inc., a subsidiary of
20 ****************************************************************************
21 ************************************<+>*************************************/
23 /* System Include Files */
31 #include <Dt/HelpDialog.h>
32 #include <Dt/HelpQuickD.h>
36 #include "HelpCacheI.h"
37 #include "HourGlassI.h"
40 /******** Static Function Declarations ********/
43 static void CloseHelpCB (
47 static Boolean GetFromCache(
49 CacheListStruct **pCurrentNode);
53 /* Global Main Help Dialog Widget */
54 static Widget helpMain=NULL;
55 static Widget versionMain=NULL;
58 /*****************************************************************************
59 * Function: void HelpMapCB()
63 * Parameters: clientData is the widget in reference to
64 * which widget w is placed
68 * Purpose: Determins where a new child dialog should be mapped in
69 * relation to its parent.
71 * Algorithm: 1. attempt left or right placement with no overlap
72 * 2. if fails, attempt up or down placement with no overlap
73 * 3. if fails, determines location with least
74 * amount of overlap, and places there.
76 *****************************************************************************/
77 XtCallbackProc HelpMapCB(
86 Position centeredY, bestX, bestY, pX, pY;
87 Dimension pHeight, myHeight, pWidth, myWidth;
89 int rhsX, lhsX, topY, botY; /* needs to be int, not Dimension */
94 parent = (Widget)clientData;
95 display = XtDisplay(w);
97 screenNumber = XScreenNumberOfScreen(screen);
102 pHeight = XtHeight(parent);
103 pWidth = XtWidth(parent);
104 myHeight = XtHeight(w);
105 myWidth = XtWidth(w);
106 maxX = XDisplayWidth(display,screenNumber);
107 maxY = XDisplayHeight(display,screenNumber);
110 * 1. attempt left or right placement with no overlap
111 * 2. if fails, attempt up or down placement with no overlap
112 * 3. if fails, places on the right in the middle
115 /* first try left right placement */
116 bestY = pY + pHeight/2 - myHeight/2;
119 lhsX = pX - myWidth - 8; /* 8: account for border */
120 if ( (rhsX + myWidth) < maxX ) bestX = rhsX;
121 else if ( lhsX > 0 ) bestX = lhsX;
124 /* then try up down placement */
125 bestX = pX + pWidth/2 - myWidth/2;
127 topY = pY - myHeight - 44; /* 44: account for menu border */
128 if ( (botY + myWidth) < maxY ) bestY = botY;
129 else if ( topY > 0 ) bestY = topY;
132 /* otherwise, center vertically and on the right */
133 bestX = maxX - myWidth;
138 XtSetArg(args[0], XmNx, bestX);
139 XtSetArg(args[1], XmNy, bestY);
140 XtSetValues(w, args, 2);
142 return((XtCallbackProc) NULL);
147 /****************************************************************************
148 * Function: CloseHelpCB(
150 * XtPointer clientData,
155 * Return Value: Void.
157 * Purpose: Process close requests on all Help Dialog widgets
158 * created and managed by this application.
160 ***************************************************************************/
161 static void CloseHelpCB (
163 XtPointer clientData,
167 Widget helpDialog = (Widget) clientData;
169 CacheListStruct *pTemp;
171 pTemp = pCacheListHead;
173 /* Search our Cache List for the closed help dialog */
174 while ((pTemp->helpDialog != helpDialog) && (pTemp != NULL))
175 pTemp = pTemp->pNext;
180 printf("We did not find our help dialog widget in the cache list??? /n");
182 /* Un Map and Clean up the help widget */
183 XtUnmanageChild(helpDialog);
184 pTemp->inUseFlag = FALSE;
191 /****************************************************************************
192 * Function: CloseMainCB(
194 * XtPointer clientData,
199 * Return Value: Void.
201 * Purpose: Process close requests on our main help dialog.
203 ***************************************************************************/
204 static void CloseMainCB (
206 XtPointer clientData,
209 Widget currentDialog = (Widget) clientData;
213 /* Un Map and Clean up the help widget */
214 XtUnmanageChild(currentDialog);
221 /****************************************************************************
222 * Function: void ProcessLinkCB(
224 * XtPointer clientData,
229 * Return Value: Void.
231 * Purpose: Process JUMP-NEW and APP-LINK hypertext requests in a
232 * given Help Dialog Window.
234 * This is the callback used for the DtNhyperLinkCallback
235 * on each of the help dialog widges created.
237 ****************************************************************************/
240 XtPointer clientData,
249 static Dimension width=0;
250 static Dimension height=0;
251 static Boolean goBigger=TRUE;
253 DtHelpDialogCallbackStruct * hyperData =
254 (DtHelpDialogCallbackStruct *) callData;
257 switch (hyperData->hyperType)
259 case DtHELP_LINK_JUMP_NEW:
261 DisplayTopic (XtParent(w), hyperData->helpVolume,
262 hyperData->locationId);
266 case DtHELP_LINK_MAN_PAGE:
268 /* Create and display the requested man page */
269 DisplayMan(XtParent(w), hyperData->specification);
274 case DtHELP_LINK_TEXT_FILE:
276 /* Create a quick help dialog and display the text file in it */
280 case DtHELP_LINK_APP_DEFINE:
282 appLinkNum = atoi(hyperData->specification);
284 if (appLinkNum == 100) /* Move the window */
287 /* First Place the window in the upper left */
289 XtSetArg(args[n], XmNx, 0); ++n;
290 XtSetArg(args[n], XmNy, 0); ++n;
291 XtSetValues(topLevel, args, n);
293 /* Now move it down to the center of the display */
295 for (count = 1;count < 500; count= count+5)
298 XtSetArg(args[n], XmNx, count); ++n;
299 XtSetArg(args[n], XmNy, count); ++n;
300 XtSetValues(topLevel, args, n);
301 XmUpdateDisplay(topLevel);
307 if (appLinkNum == 101) /* Resize the window */
312 /* Get the current dialog size */
314 XtSetArg (args[n], XmNheight, &height); n++;
315 XtSetArg (args[n], XmNwidth, &width); n++;
316 XtGetValues(topLevel, args, n);
322 XtSetArg (args[n], XmNheight, height+100); n++;
323 XtSetArg (args[n], XmNwidth, width+50); n++;
324 XtSetValues(topLevel, args, n);
331 XtSetArg (args[n], XmNheight, height); n++;
332 XtSetArg (args[n], XmNwidth, width); n++;
333 XtSetValues(topLevel, args, n);
340 if (appLinkNum == 102)
345 if (appLinkNum == 103)
352 default: /* Catches any other applicaion definded link types */
354 printf("We some how got a bogus hyptertext link type/n");
357 } /* End Switch Statement */
364 /****************************************************************************
365 * Function: void DisplayMan()
369 * Return Value: Void.
371 * Purpose: Displays a UNIX man page in a quick help dialog.
373 ****************************************************************************/
385 XmUpdateDisplay(topLevel);
389 if (manWidget == NULL)
391 /* Create the QuickHelpDialog widget for help on help */
392 title = XtNewString(man);
395 XtSetArg (args[n], XmNuseAsyncGeometry, True); n++;
396 XtSetArg (args[n], XmNtitle, title); n++;
397 XtSetArg (args[n], DtNhelpType,DtHELP_TYPE_MAN_PAGE); n++;
398 XtSetArg (args[n], DtNmanPage, man); n++;
399 manWidget = DtCreateHelpQuickDialog(topLevel,"manBox", args, n);
400 XtFree((char*) title);
403 XtAddCallback(manWidget, DtNcloseCallback,
404 CloseMainCB, (XtPointer) manWidget);
406 /* Add the popup position callback to our man dialog */
407 XtAddCallback (XtParent(manWidget), XmNpopupCallback,
408 (XtCallbackProc)HelpMapCB,
409 (XtPointer)topLevel);
414 /* We do not want a help button for now so we unmap it */
415 helpWidget = DtHelpQuickDialogGetChild (manWidget,
416 DtHELP_QUICK_HELP_BUTTON);
417 XtUnmanageChild (helpWidget);
419 XtManageChild(manWidget);
423 TurnOnHourGlass(manWidget);
425 /* We already have a quick help dialog so re-use it */
427 XtSetArg (args[n], DtNhelpType,DtHELP_TYPE_MAN_PAGE); n++;
428 XtSetArg (args[n], DtNmanPage, man); n++;
430 XtSetValues(manWidget, args, n);
433 title = XtNewString(man);
435 XtSetArg (args[n], XmNtitle, title); n++;
436 XtSetValues(XtParent(manWidget), args, n);
437 XtFree((char*) title);
439 XtManageChild(manWidget);
440 XtMapWidget(XtParent(manWidget));
441 XRaiseWindow(XtDisplay(parent), XtWindow(XtParent(manWidget)));
442 TurnOffHourGlass(manWidget);
449 /****************************************************************************
450 * Function: void DisplayTopic(
457 * Return Value: Void.
459 * Purpose: Creats and displays a new help dialog w/the requested help
462 ****************************************************************************/
472 CacheListStruct *pCurrentNode = NULL;
473 Boolean cachedNode = FALSE;
476 /* Get a inuse node if we have one or a Cached one */
477 cachedNode = GetFromCache(parent, &pCurrentNode);
480 /* If we got a free one from the Cache, use it */
481 /* Set Values on current free one, then map it */
485 XtSetArg (args[n], XmNtitle, "HelpDemo Help"); n++;
486 if (helpVolume != NULL)
488 XtSetArg (args[n],DtNhelpVolume,helpVolume); n++;
490 XtSetArg (args[n], DtNlocationId,locationId); n++;
491 XtSetValues(pCurrentNode->helpDialog, args, n);
493 XtManageChild(pCurrentNode->helpDialog);
494 XtMapWidget(XtParent(pCurrentNode->helpDialog));
498 while (!XtIsSubclass(parent, applicationShellWidgetClass))
499 parent = XtParent(parent);
503 /* Build a new one in our cached list */
505 XtSetArg (args[n], XmNtitle, "Helpdemo Help"); n++;
506 if (helpVolume != NULL)
508 XtSetArg (args[n],DtNhelpVolume,helpVolume); n++;
510 XtSetArg (args[n], DtNlocationId,locationId); n++;
511 pCurrentNode->helpDialog =
512 DtCreateHelpDialog(parent, "helpWidget", args, n);
515 XtAddCallback(pCurrentNode->helpDialog, DtNhyperLinkCallback,
516 ProcessLinkCB, NULL);
518 XtAddCallback(pCurrentNode->helpDialog, DtNcloseCallback,
519 CloseHelpCB, (XtPointer) pCurrentNode->helpDialog);
521 XtManageChild(pCurrentNode->helpDialog);
522 XtMapWidget(XtParent(pCurrentNode->helpDialog));
530 /****************************************************************************
531 * Function: void DisplayMain(
538 * Return Value: Void.
540 * Purpose: Displays help for helpdemo in the one helpDialog window
541 * created for the applicaiton.
543 ****************************************************************************/
553 if (helpMain != NULL)
556 XtSetArg (args[n], XmNtitle, "hemodemo Help"); n++;
557 if (helpVolume != NULL)
559 XtSetArg (args[n],DtNhelpVolume,helpVolume); n++;
561 XtSetArg (args[n], DtNlocationId,locationId); n++;
562 XtSetValues(helpMain, args, n);
564 XtManageChild(helpMain);
569 while (!XtIsSubclass(parent, applicationShellWidgetClass))
570 parent = XtParent(parent);
573 /* Build a new one in our cached list */
575 XtSetArg (args[n], XmNtitle, "Helpdemo Help"); n++;
576 if (helpVolume != NULL)
578 XtSetArg (args[n],DtNhelpVolume,helpVolume); n++;
580 XtSetArg (args[n], DtNlocationId,locationId); n++;
581 helpMain = DtCreateHelpDialog(parent, "helpWidget", args, n);
583 XtAddCallback(helpMain, DtNhyperLinkCallback,
584 ProcessLinkCB, NULL);
586 XtAddCallback(helpMain, DtNcloseCallback,
587 CloseMainCB, (XtPointer) helpMain);
589 /* Add the popup position callback to our main help dialog */
590 XtAddCallback (XtParent(helpMain), XmNpopupCallback,
591 (XtCallbackProc)HelpMapCB,
594 XtManageChild(helpMain);
604 /****************************************************************************
605 * Function: void DisplayVersion(
612 * Return Value: Void.
614 * Purpose: Displays the version dialog for the helpdemo program.
616 ****************************************************************************/
617 void DisplayVersion (
630 if (versionMain != NULL)
633 XtSetArg (args[n], XmNtitle, "Helpdemo Version Dialog"); n++;
634 if (helpVolume != NULL)
636 XtSetArg (args[n],DtNhelpVolume,helpVolume); n++;
638 XtSetArg (args[n], DtNlocationId,locationId); n++;
639 XtSetValues(versionMain, args, n);
641 XtManageChild(versionMain);
646 while (!XtIsSubclass(parent, applicationShellWidgetClass))
647 parent = XtParent(parent);
650 /* Build a new one in our cached list */
652 XtSetArg (args[n], XmNtitle, "Helpdemo Version Dialog"); n++;
653 if (helpVolume != NULL)
655 XtSetArg (args[n],DtNhelpVolume,helpVolume); n++;
657 XtSetArg (args[n], DtNlocationId,locationId); n++;
658 XtSetArg (args[n], DtNhelpType, DtHELP_TYPE_TOPIC); n++;
659 versionMain = DtCreateHelpQuickDialog(parent,"versionWidget",args,n);
661 XtAddCallback(versionMain, DtNcloseCallback,
662 CloseMainCB, (XtPointer) versionMain);
665 /* We do not want a print button for now so we unmap it */
666 printWidget = DtHelpQuickDialogGetChild (versionMain,
667 DtHELP_QUICK_PRINT_BUTTON);
668 XtUnmanageChild (printWidget);
671 /* We do not want a help button for now so we unmap it */
672 helpWidget = DtHelpQuickDialogGetChild (versionMain,
673 DtHELP_QUICK_HELP_BUTTON);
674 XtUnmanageChild (helpWidget);
676 backWidget = DtHelpQuickDialogGetChild (versionMain,
677 DtHELP_QUICK_BACK_BUTTON);
678 XtUnmanageChild (backWidget);
680 XtManageChild(versionMain);
690 /****************************************************************************
691 * Function: static CacheListStruct GetFromCache(
696 * Return Value: Void.
698 * Purpose: Gets a free help node form our cache list. If none are
699 * free, it will return fallse and the calling routine will
700 * create a new help dialog widget.
702 ****************************************************************************/
703 static Boolean GetFromCache(
705 CacheListStruct **pCurrentNode)
709 CacheListStruct *pTemp;
711 if (pCacheListHead == NULL)
713 /* We have a new list so lets create one and pass it back */
715 (CacheListStruct *) XtMalloc((sizeof(CacheListStruct)));
717 /* Assign the default values to our node */
718 pCacheListHead->helpDialog = NULL;
719 pCacheListHead->inUseFlag = TRUE;
720 pCacheListHead->pNext = NULL;
721 pCacheListHead->pPrevious = NULL;
723 /* Assign our tale pointer */
724 pCacheListTale = pCacheListHead;
726 /* Make sure or totalNodes counter is correct, e.g. force it to 1 */
729 /* Return our head pointer because it's our first and only node */
730 *pCurrentNode = pCacheListHead;
736 /* We have need for an in-use help dialog or a new one, so look */
737 pTemp = pCacheListHead;
739 while (pTemp != NULL)
741 if (pTemp->inUseFlag == FALSE)
743 pTemp->inUseFlag = TRUE;
744 *pCurrentNode = pTemp;
748 pTemp = pTemp->pNext;
752 /* If we did not find a free nod then we must add a new one to the
753 * top of the list, and return it.
756 pTemp = (CacheListStruct *) XtMalloc((sizeof(CacheListStruct)));
758 /* Assign the default values to our node */
759 pTemp->helpDialog = NULL;
760 pTemp->inUseFlag = TRUE;
762 pTemp->pNext = pCacheListHead;
763 pTemp->pPrevious = NULL;
765 pCacheListHead->pPrevious = pTemp;
767 /* Re-Assign our head pointer to point to the new head of the list */
768 pCacheListHead = pTemp;
770 /* Make sure or totalNodes counter is correct, e.g. force it to 1 */
771 totalCacheNodes = totalCacheNodes + 1;
773 /* Return our head pointer because it's our new node */
774 *pCurrentNode = pCacheListHead;