Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dthelp / dthelpdemo / HelpCache.c
1 /* $XConsortium: HelpCache.c /main/4 1995/11/08 09:17:54 rswiston $ */
2 /*************************************<+>*************************************
3  *****************************************************************************
4  **
5  **  File:        HelpCache.c
6  **
7  **  Project:      dthelpdemo demo program
8  **
9  **  Description: Contains the Help Callbacks and Utility functions for our
10  **               demo tool dthelpdemo.
11  **
12  **
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
18  **      Novell, Inc.
19  **
20  ****************************************************************************
21  ************************************<+>*************************************/
22
23 /* System Include Files  */
24
25
26 #include <Xm/Xm.h>
27 #include <Xm/XmP.h>
28
29
30 #include <Dt/Help.h>
31 #include <Dt/HelpDialog.h>
32 #include <Dt/HelpQuickD.h>
33
34 /* Local Includes */
35 #include "Main.h"
36 #include "HelpCacheI.h"
37 #include "HourGlassI.h"
38
39
40 /********    Static Function Declarations    ********/
41
42
43 static void CloseHelpCB (
44     Widget w,
45     XtPointer clientData,
46     XtPointer callData);
47 static Boolean GetFromCache(
48     Widget parent,
49     CacheListStruct **pCurrentNode);
50
51
52
53 /* Global Main Help Dialog Widget */
54 static Widget helpMain=NULL;
55 static Widget versionMain=NULL;
56
57
58 /*****************************************************************************
59  * Function:        void HelpMapCB()
60  *                   
61  *                            
62  *
63  * Parameters:      clientData is the widget in reference to
64  *                  which widget w is placed
65  *
66  * Return Value:    Void.
67  *
68  * Purpose:         Determins where a new child dialog should be mapped in
69  *                  relation to its parent.
70  *
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.
75  *
76  *****************************************************************************/
77 XtCallbackProc HelpMapCB(
78     Widget w,
79     XtPointer clientData,
80     XtPointer callData)
81
82 {
83
84     Arg         args[2];
85     Widget      parent;
86     Position    centeredY, bestX, bestY, pX, pY; 
87     Dimension   pHeight, myHeight, pWidth, myWidth;
88     Dimension   maxX, maxY;
89     int         rhsX, lhsX, topY, botY;   /* needs to be int, not Dimension */
90     Display *   display;
91     Screen *    screen;
92     int         screenNumber;
93
94     parent = (Widget)clientData;
95     display = XtDisplay(w);
96     screen = XtScreen(w);
97     screenNumber = XScreenNumberOfScreen(screen);
98     pX = XtX(parent);
99     pY = XtY(parent);
100     if (pX < 0) pX = 0;
101     if (pY < 0) pY = 0;
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);
108
109     /* algorithm 
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
113      */
114     
115     /* first try left right placement */
116     bestY = pY + pHeight/2 - myHeight/2;
117     centeredY = bestY;
118     rhsX = pX + pWidth;
119     lhsX = pX - myWidth - 8;     /* 8: account for border */
120     if ( (rhsX + myWidth) < maxX ) bestX = rhsX;
121     else if ( lhsX > 0 ) bestX = lhsX;
122     else
123     {
124           /* then try up down placement */
125         bestX = pX + pWidth/2 - myWidth/2;
126         botY = pY + pHeight;
127         topY = pY - myHeight - 44;     /* 44: account for menu border */
128         if ( (botY + myWidth) < maxY ) bestY = botY;
129         else if ( topY > 0 ) bestY = topY;
130         else
131         {
132             /* otherwise, center vertically and on the right */
133             bestX = maxX - myWidth;
134             bestY = centeredY;
135         }
136     }
137
138     XtSetArg(args[0], XmNx, bestX);
139     XtSetArg(args[1], XmNy,  bestY);
140     XtSetValues(w, args, 2);
141
142     return((XtCallbackProc) NULL);
143
144 }
145
146 \f
147 /****************************************************************************
148  * Function:         CloseHelpCB(
149  *                              Widget w,
150  *                              XtPointer clientData, 
151  *                              XtPointer callData
152  *
153  * Parameters:      
154  *
155  * Return Value:    Void.
156  *
157  * Purpose:         Process close requests on all Help Dialog widgets 
158  *                  created and managed by this application.
159  *
160  ***************************************************************************/
161 static void CloseHelpCB (
162     Widget w,
163     XtPointer clientData,
164     XtPointer callData)
165 {
166
167   Widget helpDialog = (Widget) clientData;
168
169   CacheListStruct *pTemp; 
170  
171   pTemp = pCacheListHead;
172   
173   /* Search our Cache List for the closed help dialog */
174   while ((pTemp->helpDialog != helpDialog) && (pTemp != NULL))
175      pTemp = pTemp->pNext;
176  
177
178   if (pTemp == NULL)
179     /* ERROR */
180     printf("We did not find our help dialog widget in the cache list??? /n");
181
182   /* Un Map and Clean up the help widget */
183    XtUnmanageChild(helpDialog);
184   pTemp->inUseFlag  = FALSE;
185    
186
187 }
188
189
190 \f
191 /****************************************************************************
192  * Function:         CloseMainCB(
193  *                              Widget w,
194  *                              XtPointer clientData, 
195  *                              XtPointer callData
196  *
197  * Parameters:      
198  *
199  * Return Value:    Void.
200  *
201  * Purpose:         Process close requests on our main help dialog.
202  *
203  ***************************************************************************/
204 static void CloseMainCB (
205     Widget w,
206     XtPointer clientData,
207     XtPointer callData)
208 {
209    Widget currentDialog = (Widget) clientData;
210  
211
212
213   /* Un Map and Clean up the help widget */
214    XtUnmanageChild(currentDialog);
215
216 }
217
218
219
220 \f
221 /****************************************************************************
222  * Function:        void ProcessLinkCB(
223  *                              Widget w,
224  *                              XtPointer  clientData, 
225  *                              XtPointer callData
226  *
227  * Parameters:      
228  *
229  * Return Value:    Void.
230  *
231  * Purpose:         Process JUMP-NEW and APP-LINK hypertext requests in a 
232  *                  given Help Dialog Window.
233  *                 
234  *                  This is the callback used for the DtNhyperLinkCallback
235  *                  on each of the help dialog widges created.
236  *
237  ****************************************************************************/
238 void ProcessLinkCB (
239     Widget w,
240     XtPointer clientData,
241     XtPointer callData)
242
243 {
244   Arg               args[20];
245   int               n;
246   Position          xPos, yPos;
247   int               appLinkNum=0;
248   int               count;
249   static Dimension  width=0;
250   static Dimension  height=0;
251   static Boolean    goBigger=TRUE;
252
253   DtHelpDialogCallbackStruct * hyperData = 
254                          (DtHelpDialogCallbackStruct *) callData;
255   
256
257   switch (hyperData->hyperType)
258     {
259       case DtHELP_LINK_JUMP_NEW:
260
261         DisplayTopic (XtParent(w), hyperData->helpVolume,
262                       hyperData->locationId);
263         
264         break;
265
266        case  DtHELP_LINK_MAN_PAGE:
267
268          /* Create and display the requested man page */
269         DisplayMan(XtParent(w), hyperData->specification);
270
271         
272          break;
273
274       case  DtHELP_LINK_TEXT_FILE:
275
276          /* Create a quick help dialog and display the text file in it */
277         
278          break;
279
280        case  DtHELP_LINK_APP_DEFINE:
281
282        appLinkNum = atoi(hyperData->specification);
283
284       if (appLinkNum == 100)     /* Move the window */
285         {
286
287           /* First Place the window in the upper left */
288           n = 0;
289           XtSetArg(args[n], XmNx, 0); ++n; 
290           XtSetArg(args[n], XmNy, 0); ++n;
291           XtSetValues(topLevel, args, n);
292         
293           /* Now move it down to the center of the display */
294
295           for (count = 1;count < 500; count= count+5)
296             {
297               n = 0;
298               XtSetArg(args[n], XmNx, count); ++n; 
299               XtSetArg(args[n], XmNy, count); ++n;
300               XtSetValues(topLevel, args, n);
301               XmUpdateDisplay(topLevel);
302             }
303
304         }
305
306
307       if (appLinkNum == 101)      /* Resize the window */
308         {
309
310         if (width == 0)
311           {
312             /* Get the current dialog size */
313             n =0;
314             XtSetArg (args[n], XmNheight, &height);  n++;
315             XtSetArg (args[n], XmNwidth, &width);   n++;
316             XtGetValues(topLevel, args, n);
317           }
318
319         if (goBigger)
320           {
321             n =0;
322             XtSetArg (args[n], XmNheight, height+100);  n++;
323             XtSetArg (args[n], XmNwidth, width+50);   n++;
324             XtSetValues(topLevel, args, n);
325             goBigger = FALSE;
326           }
327         else
328           {
329             /* Go smaller */
330             n =0;
331             XtSetArg (args[n], XmNheight, height);  n++;
332             XtSetArg (args[n], XmNwidth, width);   n++;
333             XtSetValues(topLevel, args, n);
334             goBigger = TRUE;
335           }
336
337         }
338  
339
340       if (appLinkNum == 102)  
341         {
342
343         }
344
345       if (appLinkNum == 103)  
346         {
347
348         }
349
350       break;
351
352       default:  /* Catches any other  applicaion definded link types */
353
354          printf("We some how got a bogus hyptertext link type/n");
355
356
357     }  /* End Switch Statement */
358  
359 }
360
361
362
363 \f
364 /****************************************************************************
365  * Function:        void DisplayMan()
366  *
367  * Parameters:      
368  *
369  * Return Value:    Void.
370  *
371  * Purpose:         Displays a UNIX man page in a quick help dialog.
372  *
373  ****************************************************************************/
374 void DisplayMan(
375     Widget  parent,
376     char    *man)
377
378 {
379
380   Arg  args[20];
381   int    n;
382   Widget helpWidget;
383   char *title;
384
385   XmUpdateDisplay(topLevel);
386  
387
388
389   if (manWidget == NULL)
390     {    
391       /* Create the QuickHelpDialog widget for help on help */
392       title = XtNewString(man);
393  
394       n =0;
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);
401
402
403       XtAddCallback(manWidget, DtNcloseCallback,
404                     CloseMainCB, (XtPointer) manWidget);
405  
406       /* Add the popup position callback to our man dialog */
407       XtAddCallback (XtParent(manWidget), XmNpopupCallback,
408                     (XtCallbackProc)HelpMapCB, 
409                     (XtPointer)topLevel);
410  
411
412
413
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);
418
419       XtManageChild(manWidget);  
420     }
421   else
422     {
423        TurnOnHourGlass(manWidget);
424   
425        /* We already have a quick help dialog so re-use it */
426        n = 0;
427        XtSetArg (args[n], DtNhelpType,DtHELP_TYPE_MAN_PAGE); n++; 
428        XtSetArg (args[n], DtNmanPage, man);                   n++;
429      
430        XtSetValues(manWidget, args, n);
431        
432
433        title = XtNewString(man);
434        n = 0;
435        XtSetArg (args[n], XmNtitle, title);                   n++;
436        XtSetValues(XtParent(manWidget), args, n);
437        XtFree((char*) title);
438
439        XtManageChild(manWidget); 
440        XtMapWidget(XtParent(manWidget));    
441        XRaiseWindow(XtDisplay(parent), XtWindow(XtParent(manWidget)));
442        TurnOffHourGlass(manWidget);       
443
444      }
445
446 }
447
448   
449 /****************************************************************************
450  * Function:        void DisplayTopic(
451  *                              Widget parent,
452  *                              char *helpVolume,
453  *                              char *locationId)
454  *
455  * Parameters:      
456  *
457  * Return Value:    Void.
458  *
459  * Purpose:         Creats and displays a new help dialog w/the requested help
460  *                  volume and topic.
461  *
462  ****************************************************************************/
463 void DisplayTopic(
464     Widget  parent,
465     char    *helpVolume,
466     char    *locationId)
467
468 {
469   Arg           args[10];       
470   int           n;
471
472  CacheListStruct *pCurrentNode = NULL;
473   Boolean       cachedNode = FALSE;
474
475
476   /* Get a inuse node if we have one or a Cached one */
477   cachedNode = GetFromCache(parent, &pCurrentNode);
478
479
480   /* If we got a free one from the Cache, use it */
481   /* Set Values on current free one, then map it */
482   if (cachedNode)
483     {
484        n = 0;
485        XtSetArg (args[n], XmNtitle, "HelpDemo Help");          n++;
486        if (helpVolume != NULL)
487          {
488            XtSetArg (args[n],DtNhelpVolume,helpVolume);     n++; 
489          }
490        XtSetArg (args[n], DtNlocationId,locationId);        n++;
491        XtSetValues(pCurrentNode->helpDialog, args, n);
492   
493        XtManageChild(pCurrentNode->helpDialog);    
494        XtMapWidget(XtParent(pCurrentNode->helpDialog));
495      }
496    else
497      {
498        while (!XtIsSubclass(parent, applicationShellWidgetClass))
499          parent = XtParent(parent);
500      
501
502
503         /* Build a new one in our cached list */
504         n = 0;
505         XtSetArg (args[n], XmNtitle, "Helpdemo Help");          n++;
506        if (helpVolume != NULL)
507          {
508            XtSetArg (args[n],DtNhelpVolume,helpVolume);     n++; 
509          }
510         XtSetArg (args[n], DtNlocationId,locationId);        n++;
511         pCurrentNode->helpDialog =  
512                    DtCreateHelpDialog(parent, "helpWidget", args, n);
513
514
515         XtAddCallback(pCurrentNode->helpDialog, DtNhyperLinkCallback,
516                        ProcessLinkCB, NULL);
517              
518         XtAddCallback(pCurrentNode->helpDialog, DtNcloseCallback,
519                       CloseHelpCB, (XtPointer) pCurrentNode->helpDialog);
520
521         XtManageChild(pCurrentNode->helpDialog);    
522         XtMapWidget(XtParent(pCurrentNode->helpDialog));
523      }
524 }
525
526
527
528
529 \f
530 /****************************************************************************
531  * Function:        void DisplayMain(
532  *                              Widget parent,
533  *                              char *helpVolume,
534  *                              char *locationId)
535  *
536  * Parameters:      
537  *
538  * Return Value:    Void.
539  *
540  * Purpose:         Displays help for helpdemo in the one helpDialog window 
541  *                  created for the applicaiton.
542  *
543  ****************************************************************************/
544 void DisplayMain (
545     Widget  parent,
546     char    *helpVolume,
547     char    *locationId)
548
549 {
550   Arg           args[10];       
551   int           n;
552  
553   if (helpMain != NULL)
554     {
555        n = 0;
556        XtSetArg (args[n], XmNtitle, "hemodemo Help");          n++;
557        if (helpVolume != NULL)
558          {
559            XtSetArg (args[n],DtNhelpVolume,helpVolume);     n++; 
560          }
561        XtSetArg (args[n], DtNlocationId,locationId);        n++;
562        XtSetValues(helpMain, args, n);
563   
564        XtManageChild(helpMain);    
565        
566      }
567    else
568      {
569        while (!XtIsSubclass(parent, applicationShellWidgetClass))
570          parent = XtParent(parent);
571      
572
573         /* Build a new one in our cached list */
574         n = 0;
575         XtSetArg (args[n], XmNtitle, "Helpdemo Help");       n++;
576        if (helpVolume != NULL)
577          {
578            XtSetArg (args[n],DtNhelpVolume,helpVolume);     n++; 
579          }
580         XtSetArg (args[n], DtNlocationId,locationId);        n++;
581         helpMain = DtCreateHelpDialog(parent, "helpWidget", args, n);
582
583         XtAddCallback(helpMain, DtNhyperLinkCallback,
584                        ProcessLinkCB, NULL);
585              
586         XtAddCallback(helpMain, DtNcloseCallback,
587                       CloseMainCB, (XtPointer) helpMain);
588
589         /* Add the popup position callback to our main help dialog */
590         XtAddCallback (XtParent(helpMain), XmNpopupCallback,
591                         (XtCallbackProc)HelpMapCB, 
592                         (XtPointer)parent);
593  
594         XtManageChild(helpMain);    
595         
596      }
597 }
598
599
600
601
602
603 \f
604 /****************************************************************************
605  * Function:        void DisplayVersion(
606  *                              Widget parent,
607  *                              char *helpVolume,
608  *                              char *locationId)
609  *
610  * Parameters:      
611  *
612  * Return Value:    Void.
613  *
614  * Purpose:         Displays the version dialog for the helpdemo program.
615  *
616  ****************************************************************************/
617 void DisplayVersion (
618     Widget  parent,
619     char    *helpVolume,
620     char    *locationId)
621
622 {
623   Arg           args[10];       
624   int           n;
625   Widget        printWidget;
626   Widget        helpWidget;
627   Widget        backWidget;
628
629  
630   if (versionMain != NULL)
631     {
632        n = 0;
633        XtSetArg (args[n], XmNtitle, "Helpdemo Version Dialog");          n++;
634        if (helpVolume != NULL)
635          {
636            XtSetArg (args[n],DtNhelpVolume,helpVolume);     n++; 
637          }
638        XtSetArg (args[n], DtNlocationId,locationId);        n++;
639        XtSetValues(versionMain, args, n);
640   
641        XtManageChild(versionMain);    
642        
643      }
644    else
645      {
646        while (!XtIsSubclass(parent, applicationShellWidgetClass))
647          parent = XtParent(parent);
648      
649
650         /* Build a new one in our cached list */
651         n = 0;
652         XtSetArg (args[n], XmNtitle, "Helpdemo Version Dialog");       n++;
653        if (helpVolume != NULL)
654          {
655            XtSetArg (args[n],DtNhelpVolume,helpVolume);     n++; 
656          }
657         XtSetArg (args[n], DtNlocationId,locationId);        n++;
658         XtSetArg (args[n], DtNhelpType, DtHELP_TYPE_TOPIC);  n++;
659         versionMain = DtCreateHelpQuickDialog(parent,"versionWidget",args,n);
660
661         XtAddCallback(versionMain, DtNcloseCallback,
662                       CloseMainCB, (XtPointer) versionMain);
663
664
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);
669   
670
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);
675   
676         backWidget = DtHelpQuickDialogGetChild (versionMain, 
677                                         DtHELP_QUICK_BACK_BUTTON);
678         XtUnmanageChild (backWidget);
679
680         XtManageChild(versionMain);    
681         
682      }
683 }
684
685
686
687
688
689 \f
690 /****************************************************************************
691  * Function:        static CacheListStruct GetFromCache(
692  *                                  Widget parent);
693  *
694  * Parameters:      
695  *
696  * Return Value:    Void.
697  *
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.
701  *
702  ****************************************************************************/
703 static Boolean GetFromCache(
704     Widget parent,
705     CacheListStruct **pCurrentNode)
706
707 {
708
709   CacheListStruct *pTemp; 
710  
711   if (pCacheListHead == NULL)
712     {
713        /* We have a new list so lets create one and pass it back */
714        pCacheListHead = 
715                 (CacheListStruct *) XtMalloc((sizeof(CacheListStruct)));
716
717        /* Assign the default values to our node */
718        pCacheListHead->helpDialog = NULL;
719        pCacheListHead->inUseFlag  = TRUE;
720        pCacheListHead->pNext      = NULL;
721        pCacheListHead->pPrevious = NULL;
722
723        /* Assign our tale pointer */
724        pCacheListTale = pCacheListHead;
725
726        /* Make sure or totalNodes counter is correct, e.g. force it to 1 */
727        totalCacheNodes = 1;
728     
729        /* Return our head pointer because it's our first and only node */
730        *pCurrentNode = pCacheListHead;
731        return (FALSE);
732
733     }
734   else
735     { 
736        /* We have need for an in-use help dialog or a new one, so look */
737        pTemp = pCacheListHead;
738       
739        while (pTemp != NULL)
740          {
741            if (pTemp->inUseFlag == FALSE)
742              {
743                 pTemp->inUseFlag = TRUE;
744                 *pCurrentNode = pTemp;
745                 return (TRUE);
746               }
747            else
748              pTemp = pTemp->pNext;
749          }
750       
751
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.
754         */
755
756        pTemp =  (CacheListStruct *) XtMalloc((sizeof(CacheListStruct)));
757
758        /* Assign the default values to our node */
759        pTemp->helpDialog = NULL;
760        pTemp->inUseFlag  = TRUE;
761      
762        pTemp->pNext      = pCacheListHead;
763        pTemp->pPrevious  = NULL;
764
765        pCacheListHead->pPrevious = pTemp;
766
767        /* Re-Assign our head pointer to point to the new head of the list */
768        pCacheListHead = pTemp;
769
770        /* Make sure or totalNodes counter is correct, e.g. force it to 1 */
771        totalCacheNodes = totalCacheNodes + 1;
772
773        /* Return our head pointer because it's our new node */
774        *pCurrentNode = pCacheListHead;
775        return (FALSE);
776
777      }
778   
779
780 }
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799