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