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