Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtfile / HelpCB.c
1 /* $XConsortium: HelpCB.c /main/7 1996/11/08 14:32:02 mustafa $ */
2 /************************************<+>*************************************
3  ****************************************************************************
4  *
5  *   FILE:           HelpCB.c
6  *
7  *   COMPONENT_NAME: Desktop File Manager (dtfile)
8  *
9  *   Description:    This file contains the help callbacks for the annotator.
10  *
11  *   FUNCTIONS: DTHelpRequestCB
12  *              HelpRequestCB
13  *              IsFilterIcon
14  *              IsMainWinDialog
15  *              IsMenuWidget
16  *              LocateRecordStructure
17  *              MapIconWidgetToFileType
18  *              ObjectHelp
19  *              ProcessItemHelp
20  *              ReusePrimaryHelpWindow
21  *              TrashHelpRequestCB
22  *              closeCB_mainHelpDialog
23  *
24  *   (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
25  *   (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
26  *   (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
27  *   (c) Copyright 1993, 1994, 1995 Novell, Inc.
28  *
29  ****************************************************************************
30  ************************************<+>*************************************/
31
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/param.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <limits.h>
38 #include <errno.h>
39 #include <malloc.h>
40 #include <nl_types.h>
41
42 #include <Xm/XmP.h>
43 #include <Xm/MessageB.h>
44 #include <Xm/MwmUtil.h>
45
46 #include <X11/Shell.h>
47 #include <X11/Xatom.h>
48
49 #include <Xm/Protocols.h>
50
51 #include <Dt/DtP.h>
52 #include <Dt/UserMsg.h>
53 #include <Dt/DtNlUtils.h>
54 #include <Dt/FileM.h>
55 #include <Dt/Action.h>
56 #include "Encaps.h"
57
58 #include <Dt/HelpDialog.h>
59
60 #include "Desktop.h"
61 #include "Main.h"
62 #include "Help.h"
63 #include "FileMgr.h"
64 #include "Prefs.h"
65 #include "Filter.h"
66 #include "SharedMsgs.h"
67
68
69 /********    Static Function Declarations    ********/
70
71 static Boolean IsMainWinDialog( 
72                         DialogData *dialogData) ;
73 static XtPointer MapIconWidgetToFileType(
74                         Widget w,
75                         FileMgrData * fileMgrData) ;
76 static Boolean IsMenuWidget(
77                         Widget w,
78                         FileMgrRec * fileMgrRec,
79                         FileMgrData * fileMgrData,
80                         String * aName,
81                         String * ftName) ;
82 static Boolean IsFilterIcon(
83                         Widget w,
84                         FileMgrData * fileMgrData,
85                         String * ftName) ;
86 static Boolean ProcessItemHelp(
87                         Widget shell) ;
88 static void ReusePrimaryHelpWindow(
89                         DialogData * primaryHelpDialog,
90                         char * idString,
91                         char * volume,
92                         char * topicTitle,
93                         char * fileType,
94                         int helpType) ;
95
96 /********    End Static Function Declarations    ********/
97
98
99
100 /************************************************************************
101  *
102  *   The main help callback
103  *
104  ************************************************************************/
105
106 void 
107 HelpRequestCB(
108         Widget w,
109         XtPointer clientData,
110         XtPointer callData )
111
112 {
113    XtPointer recordStruct;
114    DialogData * dialogData;
115    Arg args[8];
116    int n;
117    String topicTitle = NULL;
118    int helpType;
119    Boolean freeClientData;
120    String fileType;
121    String strVal;
122    char *vol;
123    char *locId;
124
125    /* Refresh the display */
126    /* printf ("in HelpRequestCB: clientdata=\"%s\"\n",(char *)clientData); */
127    XmUpdateDisplay(w);
128
129    if (recordStruct = LocateRecordStructure(w))
130    {
131       if (dialogData = _DtGetInstanceData(recordStruct))
132       {
133          if (IsMainWinDialog(dialogData))
134          {
135             FileMgrData * fileMgrData = (FileMgrData *)dialogData->data;
136             FileMgrRec * fileMgrRec = (FileMgrRec *)recordStruct;
137
138             /* Check for item help */
139             if (clientData && strcmp(clientData, HELP_HELP_MODE_STR) == 0)
140             {
141               if( !ProcessItemHelp( fileMgrRec->shell ) )
142               {
143                 char *tmpStr, *title, *msg;
144
145                 tmpStr = GetSharedMessage(ITEM_HELP_ERROR_TITLE);
146                 title = XtNewString(tmpStr);
147
148                 if( fileMgrData->toolbox )
149                 {
150                   tmpStr = GetSharedMessage( AMITEM_HELP_ERROR );
151                   msg = XtNewString(tmpStr);
152                 }
153                 else
154                 {
155                   tmpStr = GetSharedMessage( ITEM_HELP_ERROR ),
156                   msg = XtNewString(tmpStr);
157                 }
158
159                 _DtMessage(fileMgrRec->shell, title, msg, NULL,
160                            HelpRequestCB);
161                 XtFree(title);
162                 XtFree(msg);
163               }
164               return;
165             }
166             /* Item help comes in with a NULL client data */
167             if (clientData)
168             {
169                fileType = NULL;
170                topicTitle = NULL;
171                helpType = DtHELP_TYPE_TOPIC;
172                freeClientData = False;
173             }
174             else
175             {
176                if(fileMgrData->selected_file_count > 1)
177                {
178                  Widget warn;
179                  String s;
180                  XmString xmstr;
181
182                  n=0;
183                  XtSetArg(args[n], XmNokLabelString, okXmString);                        n++;
184                  XtSetArg(args[n], XmNcancelLabelString, cancelXmString);                n++;
185                  s = GETMESSAGE(29,10, "Help is not available for multiple selected objects.");
186                  xmstr = XmStringCreateLocalized(s);
187
188                  XtSetArg(args[n], XmNmessageString, xmstr);                             n++;
189                  XtSetArg(args[n], XmNtitle, (GETMESSAGE(29,1, "File Manager Help")));   n++;
190
191                  warn = XmCreateWarningDialog(fileMgrRec->shell, "warn_msg", args, n);
192
193                  XtUnmanageChild(XmMessageBoxGetChild(warn,XmDIALOG_HELP_BUTTON));
194                  XtManageChild(warn);
195                  XmStringFree(xmstr);
196
197                  return;
198                }
199
200                /* Action/Filetype Help */
201                topicTitle = GetSharedMessage(ACTION_FT_HELP_TITLE);
202                helpType = DtHELP_TYPE_DYNAMIC_STRING;
203                fileType = NULL;
204
205                /* Determine string, and set clientData accordingly */
206                if ((clientData =
207                       MapIconWidgetToFileType(w, fileMgrData)) == NULL)
208                {
209                   /* Not a file icon; is it an action menu item? */
210                   if (!IsMenuWidget(w, fileMgrRec, fileMgrData, &strVal, 
211                                     &fileType))
212                   {
213                      if (! IsFilterIcon(w, fileMgrData, &strVal))
214                         return;
215                   }
216                   clientData = (XtPointer)strVal;
217                }
218                freeClientData = True;
219             }
220
221             /* printf ("topic = %s\n", clientData); */
222
223             /* Special check for 'Using Help'; required different volume */
224             locId = (char *)clientData;
225             if ((w == *usingHelp) && (strcmp(locId, HELP_HOME_TOPIC) == 0))
226                vol = "Help4Help";
227             else
228                vol = fileMgrData->helpVol;
229
230             if (fileMgrData->primaryHelpDialog)
231             {
232                ReusePrimaryHelpWindow( fileMgrData->primaryHelpDialog, 
233                                        clientData, vol, topicTitle,
234                                        fileType, helpType);
235             }
236             else
237             {
238                /* Create the main help window for this view */
239                ShowHelpDialog(fileMgrRec->shell, (XtPointer)fileMgrRec,
240                               MAIN_HELP_DIALOG, 
241                               NULL, clientData, vol,
242                               topicTitle, fileType, helpType);
243             }
244
245             if (freeClientData)
246             {
247                XtFree(fileType);
248                XtFree(clientData);
249             }
250          }
251       }
252    }
253       else if (clientData)
254       {
255          Widget mainHelpDialog=NULL;
256          Arg args[10];
257          int i=0;
258
259          XtSetArg(args[0],XmNuserData,&mainHelpDialog);
260          XtGetValues(w,args,1);
261
262          XtSetArg(args[i], DtNhelpType,(unsigned char) DtHELP_TYPE_TOPIC); i++;
263          XtSetArg(args[i], DtNhelpVolume, DTFILE_HELP_NAME); i++;
264          XtSetArg(args[i], DtNlocationId, clientData); i++;
265          XtSetArg(args[i], XmNtitle, (GETMESSAGE(29,1, "File Manager Help")));i++;
266          if(!mainHelpDialog || ( mainHelpDialog && !XtIsManaged(mainHelpDialog)) )
267          {
268
269              mainHelpDialog = DtCreateHelpDialog(w, "mainHelpDialog", args, i);
270              XtAddCallback(mainHelpDialog, DtNcloseCallback,
271                        closeCB_mainHelpDialog,
272                        (XtPointer)NULL);
273              XtManageChild(mainHelpDialog);
274              XtSetArg(args[0],XmNuserData,mainHelpDialog);
275              XtSetValues(w,args,1);
276          }
277          else
278            XtSetValues(mainHelpDialog, args, i);
279       }
280 }
281
282
283 /************************************************************************
284  *
285  *   The main help callback for desktop items
286  *
287  ************************************************************************/
288
289 void 
290 DTHelpRequestCB(
291         Widget w,
292         XtPointer clientData,
293         XtPointer callData )
294
295 {
296    DesktopRec * dtInfo;
297    Arg args[8];
298    int n,i;
299    String topicTitle = NULL;
300    int helpType;
301    String filetypeOrActionName;
302    String fileType = NULL;
303
304    /* Refresh the display */
305    XmUpdateDisplay(w);
306
307    /* 
308     * For all of the following cases, the desktop information is
309     * attached as userData to the direct child of the closest shell.
310     */
311    if ((dtInfo = (DesktopRec *)LocateRecordStructure(w)) == NULL)
312       return;
313
314    /*
315     * If the clientData is not NULL, then it represents the topic string.
316     */
317    if (clientData)
318    {
319       helpType = DtHELP_TYPE_TOPIC;
320       filetypeOrActionName = clientData;
321    }
322    else
323    {
324       /* Context sensitive help (menu items or the file icon) */
325       if (XtParent(w) == desktop_data->popupMenu->popup)
326       {
327          /* 
328           * One of the action related menu items. The command
329           * string for the action is attached as userData.
330           */
331          topicTitle = GetSharedMessage(ACTION_FT_HELP_TITLE);
332          helpType = DtHELP_TYPE_DYNAMIC_STRING;
333          XtSetArg(args[0], XmNuserData, &filetypeOrActionName);
334          XtGetValues(w, args, 1);
335
336          /* Get the filetype from the active item */
337          fileType = dtInfo->file_view_data->file_data->logical_type;
338       }
339       else
340       {
341          /* The desktop icon itself */
342          topicTitle = GetSharedMessage(ACTION_FT_HELP_TITLE);
343          helpType = DtHELP_TYPE_DYNAMIC_STRING;
344
345          /* Determine string, and set clientData accordingly */
346          filetypeOrActionName = dtInfo->file_view_data->file_data->logical_type;
347       }
348    }
349
350    /* printf ("topic = %s\n", filetypeOrActionName); */
351    for(i=0;i<desktop_data->numWorkspaces;i++)
352      if(desktop_data->workspaceData[i]->number == dtInfo->workspace_num)
353        break;
354    if(desktop_data->workspaceData[i]->primaryHelpDialog)
355    {
356       ReusePrimaryHelpWindow(desktop_data->workspaceData[i]->primaryHelpDialog,
357                              filetypeOrActionName, DTFILE_HELP_NAME, 
358                              topicTitle, fileType, helpType);
359    }
360    else
361    {
362       /* Create the main help window for this workspace */
363       ShowDTHelpDialog(NULL, i, MAIN_HELP_DIALOG, 
364                        NULL, filetypeOrActionName, DTFILE_HELP_NAME,
365                        topicTitle, fileType, helpType);
366    }
367 }
368
369
370
371 /************************************************************************
372  *
373  *   The trash window's help callback
374  *
375  ************************************************************************/
376
377 void 
378 TrashHelpRequestCB(
379         Widget w,
380         XtPointer clientData,
381         XtPointer callData )
382
383 {
384    Arg args[5];
385    char *vol;
386    char *locId;
387
388    /* Refresh the display */
389    XmUpdateDisplay(w);
390
391    /* printf ("topic = %s\n", clientData); */
392
393    /* Check for item help */
394    if (strcmp(clientData, HELP_HELP_MODE_STR) == 0)
395    {
396       if( ! ProcessItemHelp(trashShell) )
397       {
398         char *tmpStr, *title, *msg;
399
400         tmpStr = GetSharedMessage(ITEM_HELP_ERROR_TITLE);
401         title = XtNewString(tmpStr);
402
403         tmpStr = GetSharedMessage( ITEM_HELP_ERROR ),
404         msg = XtNewString(tmpStr);
405
406         _DtMessage(trashShell, title, msg, NULL,
407                    HelpRequestCB);
408         XtFree(title);
409         XtFree(msg);
410       }
411       return;
412    }
413
414    /* Special check for 'Using Help'; required different volume */
415    locId = (char *)clientData;
416    if ((w == *usingHelpTrash) && (strcmp(locId, HELP_HOME_TOPIC) == 0))
417       vol = "Help4Help";
418    else
419       vol = DTFILE_HELP_NAME;
420
421    if (primaryTrashHelpDialog)
422    {
423       ReusePrimaryHelpWindow(primaryTrashHelpDialog,
424                              clientData, vol, NULL, NULL, DtHELP_TYPE_TOPIC);
425    }
426    else
427    {
428       /* Create the main help window for this view */
429       ShowTrashHelpDialog(trashShell, MAIN_HELP_DIALOG, NULL, clientData, 
430                           vol);
431    }
432 }
433
434
435 /*
436  * Given a widget, trace up through its ancestors, until you come to the
437  * shell.  Get the userData from the shell's child; this gets the 'record' 
438  * structure, which can then be used to determine which view's help window 
439  * to use.
440  */
441
442 XtPointer 
443 LocateRecordStructure(
444         Widget w )
445
446 {
447    Arg args[2];
448    XtPointer recordPtr;
449
450    while (XtParent(w) && !XtIsShell(XtParent(w)))
451       w = XtParent(w);
452
453    if (XtParent(w))
454    {
455       XtSetArg(args[0], XmNuserData, &recordPtr);
456       XtGetValues(w, args, 1);
457       return(recordPtr);
458    }
459
460    return(NULL);
461 }
462
463
464 /*
465  *  Check to see if this is the dialog data for one of the top level
466  * application windows.
467  */
468
469 static Boolean 
470 IsMainWinDialog(
471         DialogData * dialogData )
472
473 {
474    int i;
475
476    for (i = 0; i < view_count; i++)
477    {
478       if (view_set[i]->dialog_data == (XtPointer)dialogData)
479          return(True);
480    }
481
482    if( (FileMgrData *)dialogData->data == trashFileMgrData)
483         return(True);
484    return(False);
485 }
486
487
488 /*
489  * The application must free up the returned string.
490  */
491
492 static XtPointer
493 MapIconWidgetToFileType(
494    Widget w,
495    FileMgrData * fileMgrData )
496
497 {
498    int i;
499    int j;
500    int directoryCount;
501    char * ftName;
502
503    /* Based on whether in directory graph mode */
504    if (fileMgrData->show_type == SINGLE_DIRECTORY)
505       directoryCount = 1;
506    else
507       directoryCount = fileMgrData->directory_count;
508
509    for (i = directoryCount - 1; i >= 0; i--)
510    {
511       for (j = 0; j < fileMgrData->directory_set[i]->file_count; j++)
512       {
513          if (w == fileMgrData->directory_set[i]->file_view_data[j]->widget)
514          {
515             ftName = 
516      fileMgrData->directory_set[i]->file_view_data[j]->file_data->logical_type;
517             return (XtNewString(ftName));
518          }
519       }
520    }
521
522    /* The icon was unknown; should never happen */
523    return(NULL);
524 }
525
526
527
528 /*
529  * This function takes a widget, and determines if it is one of the
530  * menu buttons in the action menupane, or the action popup.  If so, 
531  * then it returns the action name and the associated filetype string.
532  *
533  * The caller must free up the returned string values.
534  */
535
536 static Boolean
537 IsMenuWidget(
538    Widget w,
539    FileMgrRec * fileMgrRec,
540    FileMgrData * fileMgrData,
541    String * aName,
542    String * ftName )
543
544 {
545    int i;
546    CompositeWidget action_pane = (CompositeWidget)fileMgrRec->action_pane;
547    String actionName;
548    Arg args[2];
549
550    if (action_pane == NULL)
551       return(False);
552
553    /* First, check if this is a menubar item */
554    for (i = 0; i < action_pane->composite.num_children; i++)
555    {
556       if (w == action_pane->composite.children[i])
557       {
558          XtSetArg(args[0], XmNuserData, &actionName);
559          XtGetValues(w, args, 1);
560          *aName = XtNewString(actionName);
561
562          /* Get the filetype from the active item */
563          *ftName = XtNewString(
564                      fileMgrData->selection_list[0]->file_data->logical_type);
565          return (True);
566       }
567    }
568
569    /* Secondly, check if this is a fileMgr popup item */
570    if (XtParent(w) == fileMgrPopup.menu)
571    {
572       XtSetArg(args[0], XmNuserData, &actionName);
573       XtGetValues(w, args, 1);
574       *aName = XtNewString(actionName);
575
576       /* Get the filetype from the active item */
577       *ftName = XtNewString(
578                   fileMgrData->popup_menu_icon->file_data->logical_type);
579       fileMgrData->popup_menu_icon = NULL;
580       return (True);
581    }
582
583    /* This was not a menu item */
584    return(False);
585 }
586
587
588
589 /*
590  * This function takes a widget, and determines if it is one of the
591  * filetype icons in the filter dialog.  If so, then it returns the 
592  * filetype string associated with the icon.
593  *
594  * The caller must free up the returned string values.
595  */
596
597 static Boolean
598 IsFilterIcon(
599    Widget w,
600    FileMgrData * fileMgrData,
601    String * ftName )
602
603 {
604    Arg args[2];
605    DialogData * filterEditDialogData;
606    FilterData * filterData;
607    FilterRec * filterRec;
608    FTData * filterEntryData;
609
610    filterEditDialogData = fileMgrData->filter_edit;
611    if (!filterEditDialogData)
612       return(False);
613
614    filterData = (FilterData *)filterEditDialogData->data;
615
616    if (!filterData->displayed)
617       return(False);
618
619    filterRec = (FilterRec *) _DtGetDialogInstance(filterEditDialogData);
620
621    /* Check if the parent of the widget is the filter's drawingArea */
622    if (XtParent(w) != filterRec->file_window)
623       return(False);
624
625    /*
626     * Each icon in the filter dialog has attached as its userData a
627     * pointer to a structure of information about the associated
628     * filetype; get this structure, to get the filetype index.
629     */
630    XtSetArg(args[0], XmNuserData, &filterEntryData);
631    XtGetValues(w, args, 1);
632    *ftName = XtNewString(filterEntryData->filetype);
633    return (True);
634 }
635
636
637 static Boolean
638 ProcessItemHelp(
639    Widget shell )
640
641 {
642    Widget selectedWidget;
643    int returnVal;
644
645    returnVal = DtHelpReturnSelectedWidgetId(shell, NULL, &selectedWidget);
646    switch(returnVal)
647    {  
648       case DtHELP_SELECT_VALID:
649       {
650          while (!XtIsShell(selectedWidget))
651          {
652             if (XtHasCallbacks(selectedWidget, XmNhelpCallback)
653                   == XtCallbackHasSome)
654             {
655                XtCallCallbacks(selectedWidget, 
656                                   XmNhelpCallback, NULL);
657                return True;
658             }
659
660             selectedWidget = XtParent(selectedWidget);
661          }
662          break;
663       }
664
665       case DtHELP_SELECT_INVALID:
666          return False;
667
668       case DtHELP_SELECT_ABORT:
669       case DtHELP_SELECT_ERROR:
670       default:
671          break;
672    }
673    return True;
674 }
675
676
677 static void
678 ReusePrimaryHelpWindow(
679    DialogData * primaryHelpDialog,
680    char * idString,
681    char * volume,
682    char * topicTitle,
683    char * fileType,
684    int helpType )
685
686 {
687    HelpData * helpData;
688    HelpRec * helpRec;
689    String helpString = NULL;
690    int n;
691    Arg args[10];
692
693    /* Reuse the existing main help window for this view */
694    helpData = (HelpData *)primaryHelpDialog->data;
695    XtFree(helpData->idString);
696    XtFree(helpData->volString);
697    XtFree(helpData->topicTitle);
698    XtFree(helpData->fileType);
699    helpData->idString = XtNewString(idString);
700    helpData->volString = XtNewString(volume);
701    helpData->topicTitle = XtNewString(topicTitle);
702    helpData->fileType = XtNewString(fileType);
703    helpData->helpType = helpType;
704    helpRec = (HelpRec *) _DtGetDialogInstance(primaryHelpDialog);
705    n = 0;
706    XtSetArg(args[n], DtNhelpType, (unsigned char )helpType); n++;
707    XtSetArg(args[n], DtNhelpType, helpType); n++;
708    if (helpType == DtHELP_TYPE_TOPIC)
709    {
710       XtSetArg(args[n], DtNlocationId, helpData->idString); n++;
711    }
712    else
713    {
714       helpString = MapFileTypeToHelpString(helpData->idString,
715                                            helpData->fileType);
716       XtSetArg(args[n], DtNstringData, helpString); n++;
717       XtSetArg(args[n], DtNtopicTitle, helpData->topicTitle); n++;
718    }
719    XtSetValues(helpRec->helpDialog, args, n);
720    XtFree(helpString);
721 }
722
723 void 
724 ObjectHelp(
725         Widget w,
726         XtPointer clientData,
727         XtPointer callData )
728
729 {
730   XtCallCallbacks((Widget)clientData, XmNhelpCallback, NULL);
731 }
732
733
734 /******************************************************************************/
735 /*                                                                            */
736 /* closeCB_mainHelpDialog                                                     */
737 /*                                                                            */
738 /* INPUT:  Widget wid - widget id                                             */
739 /*         XtPointer cd - client data                                         */
740 /*         XtPointer cbs - callback data                                      */
741 /* OUTPUT: none                                                               */
742 /*                                                                            */
743 /******************************************************************************/
744
745 void
746 closeCB_mainHelpDialog(Widget wid, XtPointer client_data,
747                            XtPointer cbs)
748 {
749   XtDestroyWidget(wid);
750 }
751