212ec0203af946e7e816deacd9173ab7beac99da
[oweals/cde.git] / cde / lib / DtHelp / VolSelect.c
1 /* $XConsortium: VolSelect.c /main/5 1996/08/28 16:48:11 drk $ */
2 /************************************<+>*************************************
3  ****************************************************************************
4  **
5  **   File:     VolSelect.c
6  **
7  **   Project:  Cde DtHelp
8  **
9  **   Description: Displays and manages a dialog to select volumes
10  **
11  **  (c) Copyright 1993, 1994 Hewlett-Packard Company
12  **  (c) Copyright 1993, 1994 International Business Machines Corp.
13  **  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
14  **  (c) Copyright 1993, 1994 Novell, Inc.
15  **
16  **
17  ****************************************************************************
18  ************************************<+>*************************************/
19
20 /*
21  * system includes
22  */
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 #include <X11/Xlib.h>
30 #include <X11/Intrinsic.h>
31 #include <X11/Xresource.h>
32
33 #include <Xm/MwmUtil.h>   /* for MWM_ consts */
34 #include <Xm/Protocols.h>
35
36 #include <Xm/BulletinB.h>
37 #include <Xm/DialogS.h>
38 #include <Xm/Form.h>
39 #include <Xm/LabelG.h>
40 #include <Xm/List.h>
41 #include <Xm/PushB.h>
42 #include <Xm/PushBG.h>
43 #include <Xm/SelectioB.h>
44 #include <Xm/SeparatoG.h>
45
46 #include <Dt/Help.h>
47
48 /*
49  * private includes
50  */
51 #include "HelpI.h"
52 #include "HelposI.h"        /* DTGETMESSAGE */
53 #include "HelpDialogP.h"
54 #include "HelpAccessI.h"
55 #include "FileListUtilsI.h"
56 #include "FileUtilsI.h"
57 #include "HelpUtilI.h"
58 #include "VolSelectI.h"
59
60 #ifdef NLS16
61 #endif
62
63 /******** constants *********/
64
65 /* message catalog set for VolSelect.c */
66 #define FUSET     10
67 /******** types *********/
68 typedef struct FLSelDlgRec
69 {
70    _DtHelpFileList     fileList;
71    Boolean             modalDialog;
72    _DtHelpFileDlgChildren dlgWidgets;
73 } FLSelDlgRec;
74
75 /******** variables *********/
76 /* Setup for the Retrun Translation set for the text field */
77 /* static char defaultTranslations[] = "<Key>Return: Activate()"; */
78
79 /******** functions *********/
80 \f
81 /*****************************************************************************
82  * Function:        void DestroyDialogCB(Widget w,
83  *                                  XtPointer clientData,
84  *                                  XtPointer callData);
85  *
86  *
87  *
88  * Parameters:
89  *
90  * Return Value:    Void.
91  *
92  * Purpose:         Free selection dialog memory
93  *
94  *****************************************************************************/
95 static void DestroyDialogCB(
96     Widget w,
97     XtPointer clientData,
98     XtPointer callData)
99 {
100    FLSelDlgRec * selDlgData = (FLSelDlgRec *) clientData;
101
102    /* recall that the file list is not owned by the dialog */
103    XtFree((String)selDlgData);
104 }
105
106
107 /*****************************************************************************
108  * Function:        void CloseDialogCB(Widget w,
109  *                                  XtPointer clientData,
110  *                                  XtPointer callData);
111  *
112  *
113  *
114  * Parameters:
115  *
116  * Return Value:    Void.
117  *
118  * Purpose:         Closes the dialog
119  *
120  *****************************************************************************/
121 static void CloseDialogCB(
122     Widget w,
123     XtPointer clientData,
124     XtPointer callData)
125 {
126    FLSelDlgRec * selDlgData = (FLSelDlgRec *) clientData;
127
128    /* unmanage the dialog; cause the close dialog callbacks to be called */
129    XtUnmanageChild(selDlgData->dlgWidgets.form);
130 }
131
132
133 \f
134 /*****************************************************************************
135  * Function:        void SetSelectionCB(Widget w,
136  *                                  XtPointer clientData,
137  *                                  XtPointer callData);
138  *
139  *
140  *
141  * Parameters:
142  *
143  * Return Value:    Void.
144  *
145  * Purpose:         Set the selections in the file list
146  *
147  *****************************************************************************/
148 static void SetSelectionCB(
149     Widget w,
150     XtPointer clientData,
151     XtPointer callData)
152 {
153    FLSelDlgRec * selDlgData = (FLSelDlgRec *) clientData;
154    int *         selList = NULL;
155    int           selCnt = 0;
156    int           setCnt = 0;
157    int           pos = 0;
158    Boolean       freeMem = True;
159    _DtHelpFileEntry file;
160
161    /* get the list */
162
163    /* get the list of selected list items */
164    XmListGetSelectedPos(selDlgData->dlgWidgets.list, &selList,&selCnt);
165    if (NULL == selList)
166    {  /* no more items selected ==> deselected last item */
167       selCnt = 0;          /* 0 < 1, which is minimum pos */
168       selList = &selCnt;
169       freeMem = False;     /* not owned by me */
170    }
171
172    /* set the files */
173    for ( file = selDlgData->fileList, pos = 1, setCnt = 0;
174          NULL != file && NULL != selList && setCnt <= selCnt;
175          file = _DtHelpFileListGetNext(NULL,file), pos++ )
176    {
177         if (   setCnt < selCnt  /* fixes bug due to valid value at selList[selCnt] */
178             && pos == selList[setCnt] ) 
179         {
180            file->fileSelected = True;
181            setCnt++;
182         }
183         else
184         {
185            file->fileSelected = False;
186         }
187    }
188
189    if (freeMem) XtFree((String)selList);
190 }
191
192
193 \f
194 /*****************************************************************************
195  * Function:        Widget CreateFileSelDialog()
196  *
197  *
198  * Return Value:    dialog widget
199  *
200  * Purpose:         Create and display an instance of a file sel dialog.
201  *
202  *****************************************************************************/
203 static Widget CreateFileSelDialog(
204         DtHelpDialogWidget hw,
205         Widget         parent,
206         Boolean        modalDialog,
207         char *         dlgTitle,
208         _DtHelpFileList   in_out_list,
209         _DtHelpFileDlgChildren * out_struct)
210 {
211   FLSelDlgRec *  selDlgData;       /* selection Dialog Data */
212   XmString       labelString;
213   DtHelpListStruct *pHelpInfo;
214   int            n;
215   Arg            args[20];
216
217 #define FSWIDGETS  selDlgData->dlgWidgets             /* short hand */
218
219    /* create and init the dlg data */
220    selDlgData = (FLSelDlgRec *) XtCalloc(1,sizeof(FLSelDlgRec));
221    if (NULL == selDlgData) return NULL;
222    selDlgData->fileList = in_out_list;
223    selDlgData->modalDialog = modalDialog;
224
225    /*  Create the shell and form used for the dialog.  */
226    if (NULL == dlgTitle)
227       dlgTitle = (char *)_DTGETMESSAGE (FUSET, 1, "Help - Volume Selection");
228
229    dlgTitle = XtNewString(dlgTitle);
230    n = 0;
231    XtSetArg (args[n], XmNtitle, dlgTitle);                              n++;
232    XtSetArg (args[n], XmNallowShellResize, TRUE);                       n++;
233    FSWIDGETS.shell = (Widget) XmCreateDialogShell(parent, "fileSelectShell", args, n);
234    XtFree(dlgTitle);
235    XtAddCallback(FSWIDGETS.shell, XmNdestroyCallback, 
236                              DestroyDialogCB,(XtPointer)selDlgData);
237
238    /* Set the useAsyncGeo on the shell */
239    n = 0;
240    XtSetArg (args[n], XmNuseAsyncGeometry, True); n++;
241    XtSetValues (XtParent(FSWIDGETS.shell), args, n);
242
243    /* put the form in the shell */
244    n = 0;
245    XtSetArg (args[n], XmNmarginWidth, 1);                               n++;
246    XtSetArg (args[n], XmNmarginHeight, 1);                              n++;
247    XtSetArg (args[n], XmNshadowThickness, 1);                           n++;
248    XtSetArg (args[n], XmNshadowType, XmSHADOW_OUT);                     n++;
249    XtSetArg (args[n], XmNautoUnmanage, False);                          n++;
250    XtSetArg (args[n], XmNuserData, selDlgData);                         n++;
251 /* XtSetArg (args[n], XmNdialogStyle, (modalDialog ? 
252          XmDIALOG_PRIMARY_APPLICATION_MODAL : XmDIALOG_MODELESS));      n++;*/
253    FSWIDGETS.form = (Widget) XmCreateForm (FSWIDGETS.shell, "selectForm", args, n);
254
255    /* put the list label in the form */
256    labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
257                        (FUSET, 2,"Help Volumes")));
258    n = 0;
259    XtSetArg (args[n], XmNlabelString, labelString);                     n++;
260    XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM);                n++;
261    XtSetArg (args[n], XmNleftOffset, 5);                                n++;
262    XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM);                 n++;
263    XtSetArg (args[n], XmNtopOffset, 10);                                n++;
264    XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM);               n++;
265    XtSetArg (args[n], XmNrightOffset, 5);                               n++;
266    XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING);             n++;
267    FSWIDGETS.label = (Widget)  
268          XmCreateLabelGadget (FSWIDGETS.form, "listLabel", args, n);
269    XtManageChild (FSWIDGETS.label);
270    XmStringFree (labelString);
271
272    /* Create the select scrolled list */
273    n = 0;
274    XtSetArg (args[n], XmNlistSizePolicy, XmCONSTANT);                   n++;
275    XtSetArg (args[n], XmNselectionPolicy, XmMULTIPLE_SELECT);           n++;
276    XtSetArg (args[n], XmNdoubleClickInterval, 10);/*basically disables*/n++;
277    XtSetArg (args[n], XmNhighlightOnEnter, True);                       n++;
278    FSWIDGETS.list = (Widget) XmCreateScrolledList (FSWIDGETS.form, "selList", args, n);
279    XtManageChild(FSWIDGETS.list);
280
281    XtAddCallback(FSWIDGETS.list, XmNsingleSelectionCallback,
282                    SetSelectionCB,(XtPointer) selDlgData);
283    XtAddCallback(FSWIDGETS.list, XmNmultipleSelectionCallback,
284                    SetSelectionCB,(XtPointer) selDlgData);
285    XtAddCallback(FSWIDGETS.list, XmNextendedSelectionCallback,
286                    SetSelectionCB,(XtPointer) selDlgData);
287 /* XtAddCallback(FSWIDGETS.list, XmNdefaultActionCallback, 
288                    SetSelectionCB, (XtPointer) selDlgData);*/
289
290    /* Set the constraints on our scrolled list */
291    n = 0;
292    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET);               n++;
293    XtSetArg (args[n], XmNtopWidget, FSWIDGETS.label);                   n++;
294    XtSetArg (args[n], XmNtopOffset, 5);                                 n++;
295    XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM);                n++;
296    XtSetArg (args[n], XmNleftOffset, 10);                               n++;
297    XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM);               n++;
298    XtSetArg (args[n], XmNrightOffset, 10);                              n++;
299    XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM);              n++;
300    XtSetArg (args[n], XmNbottomOffset, 100);                            n++;
301    /* 100 is just a rough guess of the one that we'll calc & install later */
302    XtSetValues (XtParent (FSWIDGETS.list), args, n);
303
304    /* put the prompt label in the form */
305    labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
306                        (FUSET, 3,"Select one or more help volumes")));
307    n = 0;
308    XtSetArg (args[n], XmNlabelString, labelString);                     n++;
309    XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM);                n++;
310    XtSetArg (args[n], XmNleftOffset, 20);                               n++;
311    XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM);               n++;
312    XtSetArg (args[n], XmNrightOffset, 20);                              n++;
313    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET);               n++;
314    XtSetArg (args[n], XmNtopWidget, XtParent(FSWIDGETS.list));          n++;
315    XtSetArg (args[n], XmNtopOffset, 5);                                 n++;
316    FSWIDGETS.prompt =(Widget)  
317          XmCreateLabelGadget (FSWIDGETS.form, "prompt", args, n);
318    XtManageChild (FSWIDGETS.prompt);
319    XmStringFree (labelString);
320
321    /*  Create a separator between the buttons  */
322    n = 0;
323    XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM);                n++;
324    XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM);               n++;
325    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET);               n++;
326    XtSetArg (args[n], XmNtopWidget,FSWIDGETS.prompt);                   n++;
327    XtSetArg (args[n], XmNtopOffset, 5);                                 n++;
328    FSWIDGETS.separator =  (Widget) XmCreateSeparatorGadget (
329                                FSWIDGETS.form, "separator", args, n);
330    XtManageChild (FSWIDGETS.separator);
331
332    /**  Create the action buttons along the bottom **/
333
334    /*  Create the close button */
335    labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
336                             (FUSET, 4,"Close")));
337    n = 0;
338    XtSetArg (args[n], XmNlabelString, labelString);                     n++;
339    XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION);            n++;
340    XtSetArg (args[n], XmNleftPosition, 10);                             n++;
341    XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION);           n++;
342    XtSetArg (args[n], XmNrightPosition, 35);                            n++;
343    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET);               n++;
344    XtSetArg (args[n], XmNtopWidget, FSWIDGETS.separator);               n++;
345    XtSetArg (args[n], XmNtopOffset, 4);                                 n++;
346    XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM);              n++;
347    XtSetArg (args[n], XmNbottomOffset, 4);                              n++;
348    XtSetArg (args[n], XmNmarginHeight, 3);                              n++;
349    FSWIDGETS.closeBtn = (Widget) XmCreatePushButtonGadget (
350                            FSWIDGETS.form, "closeBtn", args, n);
351    XtManageChild (FSWIDGETS.closeBtn);
352    XmStringFree (labelString);
353    
354    XtAddCallback(FSWIDGETS.closeBtn, XmNactivateCallback, 
355                 (XtCallbackProc)CloseDialogCB, (XtPointer) selDlgData);
356              
357    /* Build the Help button */
358    labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
359                             (FUSET, 5,"Help")));
360    n = 0;
361    XtSetArg (args[n], XmNlabelString, labelString);                     n++;
362    XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION);            n++;
363    XtSetArg (args[n], XmNleftPosition, 65);                             n++;
364    XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION);           n++;
365    XtSetArg (args[n], XmNrightPosition, 90);                            n++;
366    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET);               n++;
367    XtSetArg (args[n], XmNtopWidget, FSWIDGETS.separator);               n++;
368    XtSetArg (args[n], XmNtopOffset, 4);                                 n++;
369    XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM);              n++;
370    XtSetArg (args[n], XmNbottomOffset, 4);                              n++;
371    XtSetArg (args[n], XmNmarginHeight, 3);                              n++;
372    FSWIDGETS.helpBtn = (Widget) XmCreatePushButtonGadget (
373                           FSWIDGETS.form, "helpBtn", args, n);
374    XtManageChild (FSWIDGETS.helpBtn);
375    XmStringFree (labelString);
376
377    pHelpInfo = _DtHelpListAdd(DtHELP_volSelectHelpBtn_STR,
378                         (Widget) hw, &hw->help_dialog.help, 
379                         &hw->help_dialog.help.pHelpListHead);
380    XtAddCallback(FSWIDGETS.helpBtn, XmNactivateCallback, 
381                 _DtHelpCB, (XtPointer) pHelpInfo);
382
383    /* set the forms default and cancel button (for KCancel) */
384    n = 0;
385    XtSetArg (args[n], XmNcancelButton, FSWIDGETS.closeBtn); n++;
386    XtSetArg (args[n], XmNdefaultButton, FSWIDGETS.closeBtn); n++;
387    XtSetValues (FSWIDGETS.form, args, n);
388
389    /* Set the traversal rules */
390    XtSetArg (args[0], XmNnavigationType, XmSTICKY_TAB_GROUP); /* tab */
391    XtSetValues(FSWIDGETS.list,args,1);
392    XtSetValues(FSWIDGETS.closeBtn,args,1);
393    XtSetValues(FSWIDGETS.helpBtn,args,1);
394
395    /* set initial focus to list */
396    XmProcessTraversal(FSWIDGETS.list,XmTRAVERSE_CURRENT);
397
398 #if 0
399    /*  Adjust the decorations for the dialog shell of the dialog  */
400    n = 0;
401    XtSetArg(args[n], XmNmwmFunctions,  MWM_FUNC_MOVE);                 n++;
402    XtSetArg(args[n], XmNmwmDecorations, 
403              MWM_DECOR_BORDER | MWM_DECOR_TITLE);                      n++;
404    XtSetValues (FSWIDGETS.shell, args, n);
405 #endif
406
407    { /* set the proper offset between the bottom of the list
408         and the bottom of the form to maintain a constant sized
409         button bar. */
410    int offset = 0;
411    Dimension widgetBorderHeight = 0;
412    Dimension widgetHeight = 0;
413
414    /* first calc offset of list to form bottom based on earlier sizes */
415 #define KNOWN_OFFSETS_BELOW_LIST 24   /* 2*(4+3) + 2*5 */
416    offset = KNOWN_OFFSETS_BELOW_LIST;
417    n = 0;
418    XtSetArg(args[n], XmNborderWidth, &widgetBorderHeight);      n++;
419    XtSetArg(args[n], XmNheight, &widgetHeight);                 n++;
420    XtGetValues(FSWIDGETS.closeBtn, args, n);
421    offset += widgetHeight + 2 * widgetBorderHeight;
422    XtGetValues(FSWIDGETS.separator, args, n);
423    offset += widgetHeight + 2 * widgetBorderHeight;
424    XtGetValues(FSWIDGETS.prompt, args, n);
425    offset += widgetHeight + 2 * widgetBorderHeight;
426    XtGetValues(XtParent(FSWIDGETS.list), args, 1);  /* get only first arg */
427    offset += widgetBorderHeight;
428
429    /* then set the offset */
430    n = 0;
431    XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM);              n++;
432    XtSetArg (args[n], XmNbottomOffset, offset);                         n++;
433    XtSetValues (XtParent (FSWIDGETS.list), args, n);
434    }
435
436    /* Add the popup position callback to our select dialog */
437    XtAddCallback (FSWIDGETS.shell, XmNpopupCallback, 
438                   (XtCallbackProc)_DtHelpMapCB, (XtPointer) XtParent(parent));
439  
440    /* Add our help callback to the form of the dialog  */
441    pHelpInfo = _DtHelpListAdd(DtHELP_volSelectShell_STR,
442                         (Widget) hw, &hw->help_dialog.help, 
443                         &hw->help_dialog.help.pHelpListHead);
444    XtAddCallback(FSWIDGETS.form, XmNhelpCallback, 
445                         _DtHelpCB, (XtPointer) pHelpInfo);
446
447    if (out_struct) *out_struct = FSWIDGETS;
448    return FSWIDGETS.form;
449 }
450
451
452 \f
453 /*****************************************************************************
454  * Function:        void _DtHelpFileListCreateSelectionDialog()
455  *                             
456  * 
457  * Parameters:      parent      Specifies the parent widget
458  *                  modelDialog should the dialog be modal or not
459  *                  fileList    list of files from which to select
460  *
461  * Return Value:    widget for the modal dialog box
462  *
463  * Purpose:         Setup the selection dialog, 
464  *                  displays the dialog, allow user selection, and return.
465  *
466  *****************************************************************************/
467 Widget _DtHelpFileListCreateSelectionDialog (
468         DtHelpDialogWidget hw,
469         Widget         parent,
470         Boolean        modalDialog,
471         char *         dlgTitle,
472         XmFontList *   io_titlesFontList,
473         _DtHelpFileList   in_out_list,
474         _DtHelpFileDlgChildren * out_widgets)
475 {
476    Widget    selDlg;     /* selection dialog */
477    _DtHelpFileDlgChildren widgets;
478    XmFontList fontList;
479    _DtHelpFileEntry file;
480    Arg       args[5];
481  
482    /* create the dialog */
483    selDlg = CreateFileSelDialog(hw, parent, modalDialog, 
484                               dlgTitle, in_out_list, &widgets);
485
486    /* put the fonts and files in it */
487    /** Set the fontlist of our scrolled list **/
488    /* first get the font list */
489    XtSetArg (args[0], XmNfontList, &fontList);
490    XtGetValues (widgets.list, args, 1);
491
492    /* merge with font list of volume titles */
493    /* do this by stepping through the fontList's entries and
494       appending them to the volume title's font list */
495    {
496       XmFontContext context;
497
498       if (    (NULL != io_titlesFontList)
499            && XmFontListInitFontContext(&context,fontList) == True)
500       {
501          XmFontListEntry entry;
502          for ( entry = XmFontListNextEntry(context) ;
503                NULL != entry ;
504                entry = XmFontListNextEntry(context) )
505          {
506             *io_titlesFontList = 
507                    XmFontListAppendEntry(*io_titlesFontList,entry);
508          }
509          XmFontListFreeFontContext(context);
510          fontList = *io_titlesFontList;
511
512          /* and install in place */
513          XtSetArg (args[0], XmNfontList, fontList);
514          XtSetValues (widgets.list, args, 1);
515       }
516    }  /* end of scope */
517
518    /* populate the list with volumes */
519    for ( file = in_out_list;
520          NULL != file;
521          file = _DtHelpFileListGetNext(NULL,file) )
522    {
523       XmListAddItem(widgets.list,file->fileTitleXmStr,0);
524
525       /* select item if file is selected */
526       if (file->fileSelected) XmListSelectPos(widgets.list,0,False);
527    }
528
529    /* manage the dialog and map it */
530    XtManageChild(selDlg);
531  
532    /* pass widgets back to caller */
533    if (out_widgets) *out_widgets = widgets;
534
535    return selDlg;
536 }   
537