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