0e67de46096e8cdb2a5ff352efd515ed4fe43933
[oweals/cde.git] / cde / lib / DtHelp / History.c
1 /* $XConsortium: History.c /main/10 1996/11/22 12:25:49 cde-hp $ */
2 /************************************<+>*************************************
3  ****************************************************************************
4  **
5  **   File:        History.c
6  **
7  **   Project:     Cache Creek (Rivers) Project
8  **
9  **   Description: Creates an instance of a Cache Creek History Dialog.
10  ** 
11  **
12  **  (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
13  **
14  **  (c) Copyright 1993, 1994 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 Novell, Inc.
18  **
19  **
20  ****************************************************************************
21  ************************************<+>*************************************/
22 #include <sys/param.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <X11/Intrinsic.h>
27 #include <X11/Shell.h>
28 #include <X11/Xutil.h>
29 #include <X11/keysymdef.h>
30
31 /* These includes work in R4 and R5 */
32 #include <Xm/MwmUtil.h>
33 #include <Xm/Protocols.h>
34
35 #include <Xm/Xm.h>
36 #include <Xm/XmP.h>
37 #include <Xm/TextF.h>
38 #include <Xm/Form.h>
39 #include <Xm/LabelG.h>
40 #include <Xm/ScrolledW.h>
41 #include <Xm/SeparatoG.h>
42 #include <Xm/PushBG.h>
43 #include <Xm/List.h>
44 #include <Xm/DialogS.h>
45
46 /* Dt  Includes */
47 #include "Access.h"
48 #include "bufioI.h"
49
50 #include <Dt/Help.h>
51 #include "DisplayAreaI.h"
52 #include "StringFuncsI.h"
53 #include "HelposI.h"
54 #include "HistoryI.h"
55 #include "HelpDialogI.h"
56 #include "HelpDialogP.h"
57 #include "HelpUtilI.h"
58 #include "HelpAccessI.h"
59 #include "FormatI.h"
60
61
62 /*
63  * Local Includes
64  */
65
66
67 static void CloseHistoryCB (
68     Widget w,
69     XtPointer client_data,
70     XtPointer call_data);
71 static void ProcessTopicSelectionCB(
72     Widget w,
73     XtPointer client_data,
74     XtPointer call_data);
75 static void ProcessVolumeSelectionCB(
76     Widget w,
77     XtPointer client_data,
78     XtPointer call_data);
79 static void CreateHistoryDialog(
80     Widget nw);
81 static DtHistoryListStruct *AddItemToHistoryList(
82      DtHistoryListStruct **pHead,
83      XmString  title,
84      int topicType,
85      Boolean *duplicateItem);
86 static DtTopicListStruct *PullTopicListFromSelVolumeList(
87      Widget nw);
88 static void UpdateTopicList(
89     DtHistoryListStruct *pHistoryList,
90     Widget nw,
91     int topicType);    
92 static Boolean IsTopicInHistoryList(
93     DtTopicListStruct *pTopicList,
94     XmString topicTitle);
95
96 /************************************************************************
97  * Function: CloseHistoryCB()
98  *
99  *      Close the History Dialog
100  *
101  ************************************************************************/
102 static void CloseHistoryCB (
103     Widget w,
104     XtPointer client_data,
105     XtPointer call_data)
106 {
107   DtHelpDialogWidget hw = (DtHelpDialogWidget) client_data;
108  
109   /* We unmap the history dialog */
110   XtUnmanageChild(hw->help_dialog.history.historyWidget);
111   
112   /* Re-sensatize the search button so the user can select it agan */
113   XtSetSensitive(hw->help_dialog.menu.historyBtn, TRUE);
114   XtSetSensitive(hw->help_dialog.browser.btnBoxHistoryBtn, TRUE);
115 }
116
117
118 /*****************************************************************************
119  * Function:        Boolean _DtHelpDisplayHistoryInfo(Widget nw);
120  *                             
121  * 
122  * Parameters:      nw        Specifies the name of the current help dialog 
123  *                            widget.
124  *
125  * Return Value:
126  *
127  * Purpose:         Displays the pre-created history dialog.
128  *
129  *****************************************************************************/
130 void _DtHelpDisplayHistoryInfo(
131     Widget nw)
132 {
133
134   DtHelpDialogWidget hw = (DtHelpDialogWidget) nw;
135  
136   if (hw->help_dialog.history.historyWidget == NULL)
137      CreateHistoryDialog((Widget) hw);
138   
139    /* if its not managed, manage it */
140    if ( XtIsManaged(hw->help_dialog.history.historyWidget) == False )
141    {
142       /* manage and map the History Dialog */
143       XtManageChild(hw->help_dialog.history.historyWidget);
144       XtMapWidget(XtParent((Widget)hw->help_dialog.history.historyWidget));
145    }
146    else  /* if it is managed, bring it forward */
147    {
148      Widget parent = XtParent(hw->help_dialog.history.historyWidget);
149      XRaiseWindow ( XtDisplay(parent), XtWindow(parent) );
150    }
151 }
152
153
154
155 /*****************************************************************************
156  * Function:        Boolean IsTopicInHistoryList(nw)
157  *                             
158  * 
159  * Parameters:      nw        Specifies the name of the current help dialog 
160  *                            widget.
161  *
162  * Return Value:
163  *
164  * Purpose:         checks the current topic list for a matching value, and
165  *                  returns true if found, false if not.
166  *
167  *****************************************************************************/
168 static Boolean IsTopicInHistoryList(
169     DtTopicListStruct *pTopicList,
170     XmString topicTitle)
171 {
172
173   Boolean done=FALSE;
174   
175   while (!done && (pTopicList != NULL))
176     {
177       if (XmStringCompare (topicTitle, pTopicList->topicTitleLbl) == True)
178          done= TRUE;
179       pTopicList = pTopicList->pNext;
180     }
181
182   return(done);
183
184 }
185
186 \f
187 /*****************************************************************************
188  * Function:        void UpdateTopicList(
189  *                     DtHistoryListStruct *pTopics,
190  *                     Widget topicList
191  *
192  *
193  *
194  * Parameters:  
195  *
196  * Return Value:    Void.
197  *
198  * Purpose:         Cleans and recreates a new topic list
199  *
200  *****************************************************************************/
201 static void UpdateTopicList(
202     DtHistoryListStruct *pHistoryList,
203     Widget nw,
204     int topicType)    
205 {
206    int i;
207    int n;
208    Arg args[5];
209    XmString labelString;
210    XmString *items;
211    DtTopicListStruct *pTopicList=NULL;
212    DtHelpDialogWidget hw = (DtHelpDialogWidget) nw;
213    
214
215    /* Flush the current history topic list */
216    XmListDeselectAllItems(hw->help_dialog.history.topicList);
217    XmListDeleteAllItems(hw->help_dialog.history.topicList);
218
219    /* Grab the top of our current topic list from our history list struct */
220    pTopicList = pHistoryList->pTopicHead;
221    
222    /* Loop through and build up a new visible topics list */
223    items = (XmString *) XtMalloc(sizeof(XmString) * pHistoryList->totalNodes);
224    for (i = 0; i < pHistoryList->totalNodes; i++)
225      {
226        items[i]   = pTopicList->topicTitleLbl;
227        pTopicList = pTopicList->pNext;
228      }
229
230    XtSetArg(args[0], XmNitems,items);
231    XtSetArg(args[1], XmNitemCount, pHistoryList->totalNodes);
232    XtSetValues(hw->help_dialog.history.topicList, args, 2);
233
234    XtFree((char *)items);
235
236    /* Now, modify the label if we need to */
237
238    switch (topicType)
239      {
240        case DtHELP_TYPE_TOPIC:
241          labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
242                             (3, 8,"Help Topics Visited:")));
243          break;  
244
245
246        case DtHELP_TYPE_FILE:
247          labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
248                             (3, 9,"Help Files Visited:")));
249          break;
250
251
252        case DtHELP_TYPE_MAN_PAGE:
253          labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
254                             (3, 10,"Man Pages Visited:")));
255          break;
256
257
258       case DtHELP_TYPE_STRING:
259       case DtHELP_TYPE_DYNAMIC_STRING:
260         labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
261                             (3, 11,"Help Messages Visited:")));
262          break;
263  
264       default:  
265         /* Bogus type, how did we ever get here ??? */
266         break;
267
268     }  /* End Switch Statement */
269
270    n = 0;
271    XtSetArg (args[n], XmNlabelString, labelString);                     n++;
272    XtSetValues (hw->help_dialog.history.topicsListLabel, args, n);
273    XmStringFree(labelString);
274
275
276 }
277
278 \f
279 /*****************************************************************************
280  * Function:        void ProcessVolumeSelectionCB(Widget w,
281  *                                              XtPointer client_data,
282  *                                              XtPointer call_data);
283  *
284  *
285  *
286  * Parameters:  
287  *
288  * Return Value:    Void.
289  *
290  * Purpose:         Process user selection of an item in the Volume List
291  *                  of the history dialo.
292  *
293  *****************************************************************************/
294 static void ProcessVolumeSelectionCB(
295     Widget w,
296     XtPointer client_data,
297     XtPointer call_data)
298 {
299    XmListCallbackStruct *selectedItem = (XmListCallbackStruct *) call_data;
300    DtHelpDialogWidget hw = (DtHelpDialogWidget) client_data;
301    DtHistoryListStruct *pTemp= NULL;
302    int topicPosition=0;  
303    int i;   
304    XmString labelString;
305    int * topicPosList = NULL;
306    int   topicCnt = 0;
307    Boolean mod = False;
308    Arg          args[2];
309    XmFontList   fontList;
310
311    /* Determin the item selected in the volume list */
312    topicPosition = selectedItem->item_position;
313
314    /* To fix the bug of having no volume selected, check
315       whether user clicked again on the currently selected item,
316       deselecting it and leaving no other selected, and just
317       reselect that item and do nothing else */
318    /* for reasons unknown, selectedItem->selected_item_positions
319       doesnt seem properly initialized and leads to a core dump;
320       so use XmListGetSelectedPos() instead */
321    if (   False == XmListGetSelectedPos(w, &topicPosList, &topicCnt)
322        && NULL == topicPosList )
323    {
324       XmListSelectPos(w,topicPosition,False); /* False=dont notify */
325       return;                               /* RETURN */
326    }
327    XtFree((char *)topicPosList);
328
329    /* and find that item in our list */
330    pTemp = hw->help_dialog.history.pHistoryListHead;
331    for (i=1;i < topicPosition; i++)
332       pTemp = pTemp->pNext;
333   
334   
335    UpdateTopicList(pTemp, (Widget)hw, pTemp->topicType);
336       
337    /* Look to see if we have the current visible topic matches something in
338     * in the topic list. If so, highlight the item in the topic list
339     */
340    XtSetArg(args[0], XmNfontList, &fontList);
341    XtGetValues(hw->help_dialog.history.topicList, args, 1);
342
343    if (   _DtHelpFormatTopicTitle (hw->help_dialog.help.pDisplayArea,
344                                    hw->help_dialog.display.volumeHandle,
345                                    hw->help_dialog.display.locationId,
346                                    &labelString, &fontList, &mod) != 0 
347        || NULL == labelString)
348    {
349        labelString = XmStringCreateLocalized(hw->help_dialog.display.locationId);
350    }
351
352    if (True == mod)
353    {
354        /* must set the fontlist, otherwise this will cause a dangle later. */
355        XtSetArg(args[0], XmNfontList, fontList);
356        XtSetValues(hw->help_dialog.history.topicList, args, 1);
357        XmFontListFree(fontList);
358    }
359
360    XmListSelectItem(hw->help_dialog.history.topicList,labelString, FALSE);
361    XmListSetBottomItem(hw->help_dialog.history.topicList,labelString);
362    XmStringFree(labelString);
363 }
364
365
366
367
368 \f
369 /*****************************************************************************
370  * Function:        void ProcessTopicSelectionCB(Widget w,
371  *                                              XtPointer client_data,
372  *                                              XtPointer call_data);
373  *
374  *
375  *
376  * Parameters:  
377  *
378  * Return Value:    Void.
379  *
380  * Purpose:         Process user selection of an item in the History List.
381  *
382  *****************************************************************************/
383 static void ProcessTopicSelectionCB(
384     Widget w,
385     XtPointer client_data,
386     XtPointer call_data)
387 {
388    XmListCallbackStruct *selectedItem = (XmListCallbackStruct *) call_data;
389    DtHelpDialogWidget hw = (DtHelpDialogWidget) client_data;
390    
391    DtTopicListStruct *pTemp= NULL;
392    int topicPosition=0;  
393    int i;
394
395
396    /* First, find out what item is currently selected in our 
397     * volume list.  From this, we can get the proper topic list to
398     * travers.
399     */
400
401    pTemp = PullTopicListFromSelVolumeList((Widget)hw); 
402
403    if (pTemp == NULL)
404      {
405        /*FIX: We have a problem, this should never happen; decide what to do*/
406        return;
407      }
408
409
410    /* Determin the item selected and find that item in our list */
411    topicPosition = selectedItem->item_position;
412    
413    for (i=1;i < topicPosition; i++)
414       pTemp = pTemp->pNext;
415   
416    hw->help_dialog.display.helpType = pTemp->topicType;
417
418    if (hw->help_dialog.display.helpType != DtHELP_TYPE_TOPIC)
419      {
420        if (hw->help_dialog.display.topicTitleLbl != NULL)
421            XmStringFree(hw->help_dialog.display.topicTitleLbl);
422        hw->help_dialog.display.topicTitleLbl =
423                                         XmStringCopy(pTemp->topicTitleLbl);
424      }
425    
426
427    switch (pTemp->topicType)
428      {
429        case DtHELP_TYPE_TOPIC:
430          /* Look and see if we need to update our helpVolue to a new value */
431          if (   pTemp->helpVolume != NULL
432              && (   hw->help_dialog.display.helpVolume == NULL
433                  || strcmp(hw->help_dialog.display.helpVolume,pTemp->helpVolume) != 0))
434          {
435            XtFree(hw->help_dialog.display.helpVolume);
436            hw->help_dialog.display.helpVolume  = XtNewString(pTemp->helpVolume);
437          
438            /* Set our help volume flag so we open the proper volume */
439            hw->help_dialog.ghelp.volumeFlag         = FALSE;
440          }
441
442          XtFree(hw->help_dialog.display.locationId);
443          hw->help_dialog.display.locationId = XtNewString(pTemp->locationId);
444         
445          /* set the topicType flag to process correctly */
446          hw->help_dialog.display.helpType = DtHELP_TYPE_TOPIC;
447
448          break;
449
450        case DtHELP_TYPE_STRING:
451          XtFree(hw->help_dialog.display.stringData);
452          hw->help_dialog.display.stringData = XtNewString(pTemp->locationId);
453         
454          /* set the topicType flag to process correctly */
455          hw->help_dialog.display.helpType = DtHELP_TYPE_STRING;
456
457          break;
458   
459        case DtHELP_TYPE_DYNAMIC_STRING:
460          XtFree(hw->help_dialog.display.stringData);
461          hw->help_dialog.display.stringData = XtNewString(pTemp->locationId);
462         
463          /* set the topicType flag to process correctly */
464          hw->help_dialog.display.helpType = DtHELP_TYPE_DYNAMIC_STRING;
465
466          break;
467
468        case DtHELP_TYPE_MAN_PAGE:
469          XtFree(hw->help_dialog.display.manPage);
470          hw->help_dialog.display.manPage = XtNewString(pTemp->locationId);
471         
472          /* set the topicType flag to process correctly */
473          hw->help_dialog.display.helpType = DtHELP_TYPE_MAN_PAGE;
474
475          break;
476
477        case DtHELP_TYPE_FILE:
478          XtFree(hw->help_dialog.display.helpFile);
479          hw->help_dialog.display.helpFile = XtNewString(pTemp->locationId);
480         
481          /* set the topicType flag to process correctly */
482          hw->help_dialog.display.helpType = DtHELP_TYPE_FILE;
483
484          break;
485
486        default:  
487  
488         /* ERROR-MESSAGE */
489         /* We should never get here, because we using the proper types */
490         return;
491
492     }  /* End Switch Statement */
493   
494     _DtHelpSetupDisplayType(hw, FALSE, DtHISTORY_AND_JUMP);   
495
496 }
497
498
499
500
501
502 /*****************************************************************************
503  * Function:        void CreateHistoryDialog(
504  *                             Widget nw);
505  *
506  *
507  * Parameters:      helpDialogWidget   Specifies the current Help Dialog to 
508  *                                     create the history dialog for.
509  *
510  *
511  * Return Value:   
512  *
513  * Purpose:         Create and display an instance of a history dialog.
514  *
515  *****************************************************************************/
516 static void CreateHistoryDialog(
517     Widget nw)
518 {
519   Widget historyForm;
520   Widget volumeListLabel;
521   Widget separator;
522   Widget cancelBtn, helpBtn;
523   Widget historyShell;
524   
525
526   XmString labelString;
527   Arg args[20];
528   int n;
529   char * title;
530   DtHelpListStruct *pHelpInfo;
531   int offset=0;
532   Dimension btnHeight=0;
533   Dimension widgetBorderHeight=0;
534
535   DtHelpDialogWidget hw = (DtHelpDialogWidget) nw ;
536
537   /*  Create the shell and form used for the dialog.  */
538
539    title = XtNewString(((char *)_DTGETMESSAGE(3, 1,"Help - History Browser")));
540    n = 0;
541    XtSetArg (args[n], XmNtitle, title);                                 n++;
542    XtSetArg (args[n], XmNallowShellResize, TRUE);                       n++;
543    historyShell = XmCreateDialogShell((Widget) hw, "historyShell", args, n);
544    XtFree(title);
545
546    /* Set the useAsyncGeo on the shell */
547    n = 0;
548    XtSetArg (args[n], XmNuseAsyncGeometry, True); n++;
549    XtSetValues (XtParent(historyShell), args, n);
550
551
552    n = 0;
553    XtSetArg (args[n], XmNmarginWidth, 1);                               n++;
554    XtSetArg (args[n], XmNmarginHeight, 1);                              n++;
555    XtSetArg (args[n], XmNshadowThickness, 1);                           n++;
556    XtSetArg (args[n], XmNshadowType, XmSHADOW_OUT);                     n++;
557    XtSetArg (args[n], XmNautoUnmanage, False);                          n++;
558    historyForm = XmCreateForm (historyShell, "historyForm", args, n);
559
560  
561    labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
562                             (3, 2,"Help Volumes Visited:")));
563    n = 0;
564    XtSetArg (args[n], XmNlabelString, labelString);                     n++;
565    XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM);                n++;
566    XtSetArg (args[n], XmNleftOffset, 5);                                n++;
567    XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM);                 n++;
568    XtSetArg (args[n], XmNtopOffset, 10);                                n++;
569    volumeListLabel = 
570          XmCreateLabelGadget (historyForm, "volumeListLabel", args, n);
571    XtManageChild (volumeListLabel);
572    XmStringFree (labelString);
573
574
575    /* Create our history scrolled list */
576    n = 0;
577    XtSetArg (args[n], XmNlistSizePolicy, XmCONSTANT);                   n++;
578    XtSetArg (args[n], XmNselectionPolicy, XmSINGLE_SELECT);             n++;
579    XtSetArg (args[n], XmNresizable, FALSE);                             n++;
580    hw->help_dialog.history.volumeList =
581             XmCreateScrolledList (historyForm, "historyVolumeList", args, n);
582    XtManageChild (hw->help_dialog.history.volumeList);
583
584    XtAddCallback (hw->help_dialog.history.volumeList, 
585                  XmNsingleSelectionCallback, 
586                  (XtCallbackProc)ProcessVolumeSelectionCB, (XtPointer) hw);
587    
588    /* Set the constraints on our scrolled list */
589    n = 0;
590    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET);               n++;
591    XtSetArg (args[n], XmNtopWidget, volumeListLabel);                   n++;
592    XtSetArg (args[n], XmNtopOffset, 5);                                 n++;
593    XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM);                n++;
594    XtSetArg (args[n], XmNleftOffset, 10);                               n++;
595    XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM);               n++;
596    XtSetArg (args[n], XmNrightOffset, 10);                              n++;
597    XtSetValues (XtParent (hw->help_dialog.history.volumeList), args, n);
598
599
600    /* Create the Result Label and scrolled list */
601
602    /* Create Result List Label */
603    labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
604                      (3, 8,"Help Topics Visited:")));
605    n = 0;
606    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET);               n++;
607    XtSetArg (args[n], XmNtopWidget, 
608                   XtParent(hw->help_dialog.history.volumeList));        n++;
609    XtSetArg (args[n], XmNtopOffset, 10);                                n++;
610    XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM);                n++;
611    XtSetArg (args[n], XmNleftOffset, 10);                               n++;
612    XtSetArg (args[n], XmNlabelString, labelString);                     n++;
613    hw->help_dialog.history.topicsListLabel = 
614          XmCreateLabelGadget (historyForm, "topicsListLabel", args, n);
615    XtManageChild (hw->help_dialog.history.topicsListLabel);
616    XmStringFree (labelString);
617
618
619    /* Create our volume topics list */
620    n = 0;
621    XtSetArg (args[n], XmNlistSizePolicy, XmCONSTANT);                   n++;
622    XtSetArg (args[n], XmNselectionPolicy, XmSINGLE_SELECT);             n++;
623    XtSetArg (args[n], XmNresizable, FALSE);                             n++;
624    hw->help_dialog.history.topicList =
625             XmCreateScrolledList (historyForm, "historyTopicList", args, n);
626    XtManageChild (hw->help_dialog.history.topicList);
627
628    XtAddCallback (hw->help_dialog.history.topicList, 
629                   XmNsingleSelectionCallback, 
630                   (XtCallbackProc)ProcessTopicSelectionCB,
631                   (XtPointer) hw);
632   
633    XtAddCallback (hw->help_dialog.history.topicList, 
634                   XmNdefaultActionCallback, 
635                   (XtCallbackProc)ProcessTopicSelectionCB,
636                   (XtPointer) hw);
637
638    /* Set the constraints on our scrolled list */
639    n = 0;
640    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET);               n++;
641    XtSetArg (args[n], XmNtopWidget, hw->help_dialog.history.topicsListLabel);   n++;
642    XtSetArg (args[n], XmNtopOffset, 5);                                 n++;
643    XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM);                n++;
644    XtSetArg (args[n], XmNleftOffset, 10);                               n++;
645    XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM);               n++;
646    XtSetArg (args[n], XmNrightOffset, 10);                              n++;
647    XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM);              n++;
648    XtSetArg (args[n], XmNbottomOffset, 70);                             n++;
649    XtSetValues (XtParent (hw->help_dialog.history.topicList), args, n);
650
651   
652    /*  Create a separator between the buttons  */
653
654    n = 0;
655    XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM);                n++;
656    XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM);               n++;
657    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET);               n++;
658    XtSetArg (args[n], XmNtopWidget,
659                         XtParent(hw->help_dialog.history.topicList));   n++;
660    XtSetArg (args[n], XmNtopOffset, 8);                         n++;
661    separator =  XmCreateSeparatorGadget (historyForm, "separator", args, n);
662    XtManageChild (separator);
663
664
665    /*  Create the action buttons along the bottom */
666    labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
667                             (3, 3,"Close")));
668    n = 0;
669    XtSetArg (args[n], XmNlabelString, labelString);                     n++;
670    XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION);            n++;
671    XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION);           n++;
672    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET);               n++;
673    XtSetArg (args[n], XmNtopWidget, separator);                         n++;
674    XtSetArg (args[n], XmNtopOffset, 5);                                 n++;
675    XtSetArg (args[n], XmNmarginHeight, 4);                              n++;
676    XtSetArg (args[n], XmNmarginWidth, 6);                               n++;
677    /*XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM);            n++;
678     *XtSetArg (args[n], XmNbottomOffset, 3);                            n++;
679     */
680    cancelBtn = XmCreatePushButtonGadget (historyForm, "cancelBtn", args, n);
681    
682    XtAddCallback(cancelBtn, XmNactivateCallback, 
683                 (XtCallbackProc)CloseHistoryCB, (XtPointer) hw);
684              
685    XtManageChild (cancelBtn);
686    XmStringFree (labelString);
687
688    XtSetArg (args[0], XmNdefaultButton, cancelBtn);
689    XtSetValues (historyForm, args, 1);
690
691    /* set the cancel button (for KCancel) */
692    n = 0;
693    XtSetArg (args[n], XmNcancelButton, cancelBtn); n++;
694    XtSetValues (historyForm, args, n);
695
696
697    /* Build the Help button */
698
699    labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
700                             (3, 4,"Help")));
701    n = 0;
702    XtSetArg (args[n], XmNlabelString, labelString);                     n++;
703    XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION);            n++;
704    XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION);           n++;
705    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET);               n++;
706    XtSetArg (args[n], XmNtopWidget, separator);                         n++;
707    XtSetArg (args[n], XmNtopOffset, 5);                                 n++;
708    XtSetArg (args[n], XmNmarginHeight, 4);                              n++;
709    XtSetArg (args[n], XmNmarginWidth, 6);                               n++;
710    helpBtn = XmCreatePushButtonGadget (historyForm, "helpBtn", args, n);
711    XtManageChild (helpBtn);
712
713    /* Setup and add our help callback for this button */
714    pHelpInfo = _DtHelpListAdd(DtHELP_historyHelpBtn_STR,
715                         (Widget) hw, &hw->help_dialog.help, 
716                         &hw->help_dialog.help.pHelpListHead);
717    XtAddCallback (helpBtn, XmNactivateCallback,
718                   _DtHelpCB, (XtPointer) pHelpInfo);
719    
720    XmStringFree (labelString);
721
722
723    /*  Adjust the decorations for the dialog shell of the dialog  */
724     n = 0;
725     XtSetArg(args[n], XmNmwmFunctions,  
726              MWM_FUNC_MOVE |MWM_FUNC_RESIZE);                           n++;
727     XtSetArg (args[n], XmNmwmDecorations, 
728              MWM_DECOR_BORDER | MWM_DECOR_TITLE | MWM_DECOR_RESIZEH);   n++;
729     XtSetValues (historyShell, args, n);
730     
731    /* calculate and set the buttons' positions on the form */
732    {
733    Widget btnList[2];
734    unsigned long avgWidth = 73; /* default size, in 10ths of pixel */
735    Dimension formWidth;
736    XmFontList fontList = NULL;
737    Atom xa_ave_width;
738 #define BTN_MARGINS   4
739 #define BETW_BTN_SPC  5
740
741    XtSetArg(args[0], XmNfontList, &fontList);
742    XtGetValues(hw->help_dialog.history.topicList, args, 1);
743
744    btnList[0] = cancelBtn;
745    btnList[1] = helpBtn;
746
747    /* get the average width of the topic list's font */
748    xa_ave_width = XmInternAtom(XtDisplay(cancelBtn), "AVERAGE_WIDTH", False);
749    _DtHelpXmFontListGetPropertyMax(fontList, xa_ave_width, &avgWidth);
750
751    /* xa_ave_width is given in 10ths of a pixel; convert to pixels by div thru 10 */
752    /* we want a 25 column minimum width */
753    formWidth = avgWidth * 25 / 10;
754
755    _DtHelpSetButtonPositions(btnList, 2, formWidth, BTN_MARGINS, BETW_BTN_SPC);
756    }
757
758    /* Perform the final form layout so our dialog resizes correctly. */
759    /* Get height of: bottom buttons and separator */
760    n = 0;
761    XtSetArg(args[n], XmNheight, &btnHeight);                    n++;
762    XtSetArg(args[n], XmNborderWidth, &widgetBorderHeight);      n++;
763    XtGetValues(cancelBtn, args, n);
764    offset = btnHeight + widgetBorderHeight + 15;
765                     /* 20 =='s fudge factor */
766   
767    n = 0;
768    XtSetArg(args[n], XmNborderWidth, &widgetBorderHeight);      n++;
769    XtSetArg(args[n], XmNheight, &btnHeight);                    n++;
770    XtGetValues(separator, args, n);
771    offset += btnHeight + widgetBorderHeight;
772  
773
774
775    /* make the bottom attachment for the seporator such that things will fit,
776     * and the dialog will size properly.
777     */
778    n = 0;
779    XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM);              n++;
780    XtSetArg (args[n], XmNbottomOffset, offset);                         n++;
781    XtSetValues (XtParent (hw->help_dialog.history.topicList), args, n); 
782    
783    /* We may have some history values already, so update our newlly 
784     * created scrolled list widget.
785     */
786    
787   
788    /* Add the popup position callback to our history dialog */
789    XtAddCallback (historyShell, XmNpopupCallback, (XtCallbackProc)_DtHelpMapCB,
790                   (XtPointer) XtParent(hw));
791  
792    /* Add our help callback to the shell of the dialog  */
793    pHelpInfo = _DtHelpListAdd(DtHELP_historyShell_STR,
794                         (Widget) hw, &hw->help_dialog.help, 
795                         &hw->help_dialog.help.pHelpListHead);
796    XtAddCallback(historyForm, XmNhelpCallback,
797                  _DtHelpCB, (XtPointer) pHelpInfo);
798    
799   /* Assign our new search dialog to our widget instance */
800   hw->help_dialog.history.historyWidget = historyForm;
801
802 }
803
804
805
806 \f
807 /*****************************************************************************
808  * Function:        void _DtHelpUpdateHistoryList(char *locationId,
809  *                                 int topicType,
810  *                                 Widget nw);  
811  *
812  *
813  * Parameters:      parent      Specifies the ID string for the new topic we
814  *                              are going to display in the HelpDialog widget.
815  *
816  *                  helpDialogWidget  Specifies the current help dialog widget.
817  *
818  * Return Value:    Void.
819  *
820  * Purpose:         Updates the Path Display area on top of the help
821  *                  dialog.
822  *
823  *****************************************************************************/
824 void _DtHelpUpdateHistoryList(
825     char *locationId,
826     int topicType,
827     Boolean vol_changed,
828     Widget nw)
829 {
830   DtHistoryListStruct *pCurrentHistoryList=NULL;
831   XmString   topicTitle       = NULL;
832   XmString   currentItemTitle = NULL;
833   Boolean allocTopic=FALSE;
834   Boolean dupItem=FALSE;
835   Boolean changedSelectedVolume=FALSE;
836   Boolean mod=FALSE;
837   XmFontList    fontList;
838   Arg           args[2];
839
840   DtHelpDialogWidget hw = (DtHelpDialogWidget) nw;
841
842
843    /* Lets just build a history dialog so we can start populating it. 
844     * We won't manage it tell we need it 
845     */
846    if (hw->help_dialog.history.historyWidget == NULL)
847      CreateHistoryDialog((Widget) hw);
848
849   /* Find out what type of topic we are currently processing */
850   switch (topicType)
851     {
852       case DtHELP_TYPE_TOPIC:
853
854         /*
855          * get the font list for the volume list.
856          */
857         XtSetArg(args[0], XmNfontList, &fontList);
858         XtGetValues(hw->help_dialog.history.topicList, args, 1);
859
860         /* First we get the current topics Title */
861         allocTopic = True;
862         mod        = False;
863         if (_DtHelpFormatTopicTitle (hw->help_dialog.help.pDisplayArea,
864                                         hw->help_dialog.display.volumeHandle,
865                                         locationId, &topicTitle,
866                                         &fontList, &mod) != 0
867                 || NULL == topicTitle)
868             topicTitle = XmStringCreateLocalized(locationId);
869
870         if (mod == True)
871           {
872             XtSetArg(args[0], XmNfontList, fontList);
873             XtSetValues(hw->help_dialog.history.topicList, args, 1);
874             XmFontListFree(fontList);
875           }
876
877         /*
878          * get the font list for the volume list.
879          */
880         XtSetArg(args[0], XmNfontList, &fontList);
881         XtGetValues(hw->help_dialog.history.volumeList, args, 1);
882
883         /* Second, we get the current volume title */
884         mod = False;
885         _DtHelpFormatVolumeTitle (hw->help_dialog.help.pDisplayArea,
886                                  hw->help_dialog.display.volumeHandle,
887                                  &currentItemTitle, &fontList, &mod);   
888
889         if(currentItemTitle == NULL &&
890                                 NULL != hw->help_dialog.display.helpVolume)
891           currentItemTitle = XmStringCreateLocalized(
892                                         hw->help_dialog.display.helpVolume);
893         if (mod == True)
894           {
895             XtSetArg(args[0], XmNfontList, fontList);
896             XtSetValues(hw->help_dialog.history.volumeList, args, 1);
897             XmFontListFree(fontList);
898           }
899
900         break;  
901
902
903       case DtHELP_TYPE_FILE:
904         currentItemTitle = XmStringCreateLocalized(
905                                 ((char *)_DTGETMESSAGE(3, 5, "Help Files")));
906         topicTitle       = hw->help_dialog.display.topicTitleLbl;
907         break;
908
909
910       case DtHELP_TYPE_MAN_PAGE:
911         currentItemTitle = XmStringCreateLocalized(
912                                 ((char *)_DTGETMESSAGE(3, 6, "Man Pages")));
913         topicTitle       = hw->help_dialog.display.topicTitleLbl;
914         break;
915
916
917       case DtHELP_TYPE_STRING:
918       case DtHELP_TYPE_DYNAMIC_STRING:
919         currentItemTitle = XmStringCreateLocalized(
920                                 ((char *)_DTGETMESSAGE(3, 7, "Help Messages")));
921         topicTitle       = hw->help_dialog.display.topicTitleLbl;
922         break;
923  
924       default:  
925         /* Bogus type, how did we ever get here ??? */
926         break;
927
928     }  /* End Switch Statement */
929
930
931   /* Now add this item to the history list if necessary.  This fuction
932    * will return a pointer to the current working history list item.
933    */
934    pCurrentHistoryList = AddItemToHistoryList(
935                                 &(hw->help_dialog.history.pHistoryListHead),
936                                 currentItemTitle, topicType, &dupItem);
937
938    if (dupItem != TRUE)
939      {
940        /* We can skip this if it already exists in our history list,else
941         * we add the new history item  to the top of the scrolled window
942         */
943         XmListAddItem(hw->help_dialog.history.volumeList,currentItemTitle, 1);
944         XmListSelectPos(hw->help_dialog.history.volumeList,1, FALSE);
945      }
946    else /* dupItem == True */
947      {
948        /* We changed to a diferent volume or help type so force it selected */
949        XmListSelectItem(hw->help_dialog.history.volumeList,
950                                                 currentItemTitle, FALSE);
951        changedSelectedVolume = TRUE;
952        if (NULL != currentItemTitle)
953            XmStringFree(currentItemTitle);
954      }
955
956   /* Now add this item to the proper Topic List. */
957   if (pCurrentHistoryList != NULL)
958     {
959
960       if (!IsTopicInHistoryList(pCurrentHistoryList->pTopicHead, topicTitle))
961         {
962           /* Add the new topic to the history top of the history list */
963           _DtHelpTopicListAddToHead(locationId, topicTitle,topicType, 
964                              DtHISTORY_LIST_MAX,
965                              hw->help_dialog.display.helpVolume,
966                              &(pCurrentHistoryList->pTopicHead),
967                              &(pCurrentHistoryList->pTopicTale),
968                              &(pCurrentHistoryList->totalNodes),
969                              hw->help_dialog.backtr.scrollPosition);
970
971           XmUpdateDisplay((Widget) hw);
972           UpdateTopicList(pCurrentHistoryList, (Widget)hw, topicType);
973
974       
975           /* Force the top item to be selected */
976           XmListSelectPos(hw->help_dialog.history.topicList,1, FALSE);
977         }
978       else
979         {
980           if (changedSelectedVolume)
981             {
982               if (TRUE == vol_changed)
983                   UpdateTopicList(pCurrentHistoryList, (Widget)hw, topicType);
984               XmListSelectItem(hw->help_dialog.history.topicList,topicTitle,
985                              FALSE);
986               /* Make sure the item is visible */
987             }
988         }
989     }
990   if (allocTopic == True)
991       XmStringFree(topicTitle);
992 }
993
994
995
996 /*****************************************************************************
997  * Function:        static DtHistoryListStruct *AddItemToHistoryList(
998  *                                
999  * Parameters:
1000  *              title   Specifies the XmString of the title.  If
1001  *                      'duplicateItem' returns False, the caller
1002  *                      must not modify or free this parameter.
1003  *
1004  *
1005  * Return Value:   Pointer to the current history list node that we are going
1006  *                 to add the item.
1007  *
1008  * Purpose:        Add or update our history list with a new item
1009  *
1010  *****************************************************************************/
1011 static DtHistoryListStruct *AddItemToHistoryList(
1012      DtHistoryListStruct **pHead,
1013      XmString  title,
1014      int topicType,
1015      Boolean *duplicateItem)
1016 {
1017   DtHistoryListStruct *pTemp=NULL;
1018   Boolean done=FALSE;
1019
1020    /*
1021     * Walk the list.
1022     */
1023    pTemp = (*pHead); 
1024    *duplicateItem = False;
1025  
1026    while (!done && (pTemp != NULL))
1027      {
1028        if (XmStringCompare (title, pTemp->itemTitle) == True)
1029           {
1030             /* We have a match, so lets use it */
1031             *duplicateItem = TRUE;
1032             done = TRUE;
1033           }
1034        else
1035          pTemp = pTemp->pNext;
1036
1037      }
1038
1039    if (pTemp == NULL)
1040      {
1041        /* We did not find a match, so lets add one to the top of 
1042         * our current list.
1043         */
1044        pTemp =(DtHistoryListStruct *) XtMalloc((sizeof(DtHistoryListStruct)));
1045     
1046        
1047        pTemp->itemTitle        = title;
1048        pTemp->totalNodes       = 0;
1049        pTemp->topicType        = topicType;
1050        pTemp->pNext            = (*pHead);
1051        pTemp->pTopicHead       = NULL;
1052        pTemp->pTopicTale       = NULL;
1053
1054        /* Re-Assign our head pointer to point to the new 
1055         * head of the list
1056         */
1057        (*pHead) = pTemp;
1058      }
1059
1060   return (pTemp);
1061
1062 }
1063
1064
1065 /*****************************************************************************
1066  * Function:        static DtHistoryListStruct PullTopicListFromSelVolumeList
1067  *                                
1068  *
1069  *
1070  *
1071  * Return Value:   Pointer to the current history list node that we are going
1072  *                 to add the item.
1073  *
1074  * Purpose:        Add or update our history list with a new item
1075  *
1076  *****************************************************************************/
1077 static DtTopicListStruct *PullTopicListFromSelVolumeList(
1078      Widget nw)
1079 {
1080   DtHelpDialogWidget hw = (DtHelpDialogWidget) nw;
1081   DtHistoryListStruct *pTemp=NULL;
1082   Boolean itemsSelected=FALSE;
1083   int positionCount;
1084   int *positionList;  /* Should always be only one item */
1085   int i;
1086
1087   
1088   pTemp = hw->help_dialog.history.pHistoryListHead;
1089
1090   /* Find out what item is currently selected in our visited volumes list */
1091
1092   itemsSelected = XmListGetSelectedPos(hw->help_dialog.history.volumeList,
1093                                             &positionList, &positionCount);
1094
1095   if (itemsSelected)
1096     {
1097       /* We should get in here every time */
1098          
1099       for (i=1;i < positionList[0]; i++)
1100         pTemp = pTemp->pNext;
1101
1102       free(positionList);  
1103       return (pTemp->pTopicHead);
1104     }
1105   else
1106     {
1107       free(positionList);
1108       return (NULL);
1109       /* error condition we must account for */
1110     }
1111
1112  
1113 }
1114
1115
1116
1117