Merge branch 'master' into cde-next
[oweals/cde.git] / cde / programs / dtfile / MultiView.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: MultiView.c /main/5 1996/10/15 10:08:30 mustafa $ */
24 /************************************<+>*************************************
25  ****************************************************************************
26  *
27  *   FILE:           MultiView.c
28  *
29  *   COMPONENT_NAME: Desktop File Manager (dtfile)
30  *
31  *   Description:    Contains the shared code for managing multiple toplevel
32  *                   main application window.
33  *
34  *   FUNCTIONS: CreateMenuBtn
35  *              _DtCreateMenuSystem
36  *              _DtGlobalRestoreMenuSensitivity
37  *              _DtGlobalSetMenuSensitivity
38  *              _DtGlobalUpdateMenuItemState
39  *
40  *   (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
41  *   (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
42  *   (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
43  *   (c) Copyright 1993, 1994, 1995 Novell, Inc.
44  *
45  ****************************************************************************
46  ************************************<+>*************************************/
47
48  
49
50 #include <stdio.h>
51 #include <signal.h>
52 #include <pwd.h>
53 #include <time.h>
54
55 #include <Xm/XmP.h>
56 #include <Xm/CascadeBG.h>
57 #include <Xm/PushBG.h>
58 #include <Xm/RowColumn.h>
59 #include <Xm/SeparatoG.h>
60 #include <Xm/ToggleBG.h>
61 #include <Xm/MenuShellP.h>
62
63 #include <X11/ShellP.h>
64
65 #include <Dt/DtP.h>
66 #include <Dt/DtNlUtils.h>
67 #include <Dt/Connect.h>
68
69 #include <Xm/XmPrivate.h> /* _XmGetActiveTopLevelMenu */
70
71 #include "Encaps.h"
72 #include "MultiView.h"
73
74
75 /********    Static Function Declarations    ********/
76
77 extern void _DtGlobalUpdateMenuItemState(
78                         Widget btn,
79                         unsigned int mask,
80                         unsigned int on,
81                         unsigned int * globalMenuStates) ;
82 extern void _DtGlobalSetMenuSensitivity(
83                         Widget w,
84                         XtPointer client_data,
85                         XtPointer call_data) ;
86 extern void _DtGlobalRestoreMenuSensitivity(
87                         Widget w,
88                         XtPointer client_data,
89                         XtPointer call_data) ;
90 static Widget CreateMenuBtn(
91                         Widget parent,
92                         Boolean isPushButton,
93                         MenuDesc * menuDesc,
94                         int btnIndex) ;
95
96 /********    End Static Function Declarations    ********/
97
98 extern Widget * findBtn;
99 extern Widget * change_directoryBtn;
100 extern Widget * preferencesBtn;
101 extern Widget * defaultEnvBtn;
102 extern Widget * filterBtn;
103
104 Widget
105 _DtCreateMenuSystem(
106         Widget parent,
107         char * menuBarName,
108         XtCallbackProc helpCallback,
109         XtPointer helpData,
110         Boolean createSharedComponents,
111         MenuDesc * menuDesc,
112         int numMenuComponents,
113         void (*getMenuDataProc)(),
114         void (*setMenuSensitivity)(),
115         void (*restoreMenuSensitivity)() )
116
117 {
118    int n;
119    int i;
120    Arg args[20];
121    Widget menubar;
122    Widget lastCascadeBtn = NULL;
123    Widget lastMenuPane = NULL;
124    char lastMenuPaneType = MENU_PANE;
125    Boolean firstMenuPane = True;
126    Widget child;
127    XmString labelString;
128    int pulldownIndex = 1;
129    int menuPaneIndex = 1;
130    int menuBtnIndex = 1;
131
132    /* Use our own menu control functions, if none specified */
133    if (setMenuSensitivity == NULL)
134       setMenuSensitivity = _DtGlobalSetMenuSensitivity;
135    if (restoreMenuSensitivity == NULL)
136       restoreMenuSensitivity = _DtGlobalRestoreMenuSensitivity;
137
138    /*  Create the pulldown menu  */
139    n = 0;
140    XtSetArg(args[n], XmNorientation, XmHORIZONTAL);     n++;
141    XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
142    XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM);        n++;
143    XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM);  n++;
144    menubar = XmCreateMenuBar(parent, menuBarName, args, n);
145    XtManageChild(menubar);
146    if (helpCallback)
147       XtAddCallback(menubar, XmNhelpCallback, helpCallback, helpData);
148
149    for (i = 0; i < numMenuComponents; i++)
150    {
151       n = 0;
152
153       switch (menuDesc[i].type)
154       {
155          case MENU_PULLDOWN_BUTTON:
156          {
157             labelString = XmStringCreateLocalized(menuDesc[i].label);
158             XtSetArg(args[n], XmNlabelString, labelString);   n++;
159             if (menuDesc[i].mnemonic)
160             {
161                XtSetArg(args[n], XmNmnemonic, menuDesc[i].mnemonic[0]);   n++;
162             }
163             XtSetArg(args[n], XmNmarginWidth, 6);   n++;
164             child = XmCreateCascadeButtonGadget(menubar, menuDesc[i].name, 
165                                                 args, n);
166             if (menuDesc[i].helpCallback)
167             {
168                XtAddCallback(child, XmNhelpCallback, 
169                              menuDesc[i].helpCallback, menuDesc[i].helpData);
170             }
171             if (menuDesc[i].isHelpBtn)
172             {
173                XtSetArg(args[0], XmNmenuHelpWidget, child);
174                XtSetValues(menubar, args, 1);
175             }
176             XtManageChild(child);
177             XmStringFree(labelString);
178             lastCascadeBtn = menuDesc[i].widget = child;
179             pulldownIndex++;
180             break;
181          }
182
183          case SHARED_MENU_PANE:
184          case MENU_PANE:
185          {
186             if (createSharedComponents || (menuDesc[i].type == MENU_PANE))
187             {
188                child = XmCreatePulldownMenu(menubar, menuDesc[i].name, NULL, 0);
189
190                if (firstMenuPane)
191                {
192                   XtAddCallback(XtParent(child), XmNpopupCallback, 
193                                 setMenuSensitivity, 
194                                 (XtPointer)getMenuDataProc);
195                   XtAddCallback(XtParent(child), XmNpopdownCallback, 
196                                 restoreMenuSensitivity, 
197                                 (XtPointer)getMenuDataProc);
198                   firstMenuPane = False;
199                }
200
201                if (menuDesc[i].helpCallback)
202                {
203                   XtAddCallback(child, XmNhelpCallback, 
204                              menuDesc[i].helpCallback, menuDesc[i].helpData);
205                }
206
207                menuDesc[i].widget = child;
208             }
209
210             lastMenuPane = menuDesc[i].widget;
211             lastMenuPaneType = menuDesc[i].type;
212             XtSetArg(args[0], XmNsubMenuId, lastMenuPane);
213             XtSetValues(lastCascadeBtn, args, 1);
214             menuBtnIndex = 1;
215             menuPaneIndex++;
216             break;
217          }
218
219          case MENU_TOGGLE_BUTTON:
220          case MENU_BUTTON:
221          {
222             /* Need to always make btns for non-shared menupanes */
223             if ((createSharedComponents) || (lastMenuPaneType == MENU_PANE))
224             {
225                child = CreateMenuBtn (lastMenuPane, 
226                                       (menuDesc[i].type == MENU_BUTTON),
227                                       menuDesc + i, menuBtnIndex);
228                XtManageChild(child);
229                menuDesc[i].widget = child;
230             }
231             menuBtnIndex++;
232             break;
233          }
234
235          case MENU_SEPARATOR:
236          {
237             /* Need to always make components for non-shared menupanes */
238             if ((createSharedComponents) || (lastMenuPaneType == MENU_PANE))
239             {
240                child = XmCreateSeparatorGadget(lastMenuPane, menuDesc[i].name, 
241                                                NULL, 0);
242                XtManageChild(child);
243                menuDesc[i].widget = child;
244             }
245             break;
246          }
247       }
248    }
249
250
251    return(menubar);
252 }
253
254
255
256 /* ARGSUSED */
257 void
258 _DtGlobalSetMenuSensitivity(
259         Widget w,
260         XtPointer client_data,
261         XtPointer call_data )
262
263 {
264    Arg menuPaneArgs[1];
265    Widget mbar;
266    XmMenuShellWidget mshell = (XmMenuShellWidget) w;
267    void (*getMenuData)() = (void(*)())client_data;
268    XtPointer mainRecord;
269    MenuDesc * menuDesc;
270    int menuItemCount;
271    unsigned int * globalMenuStates;
272    unsigned int * viewMenuStates;
273    int i;
274
275    _XmGetActiveTopLevelMenu(mshell->composite.children[0], &mbar);
276    (*getMenuData)(mbar, &mainRecord, &menuDesc, &menuItemCount,
277                   &globalMenuStates, &viewMenuStates);
278    XtSetArg(menuPaneArgs[0], XmNuserData, mainRecord);
279
280    for (i = 0; i < menuItemCount; i++)
281    {
282       switch (menuDesc[i].type)
283       {
284          case SHARED_MENU_PANE:
285          case MENU_PANE:
286          {
287             /* Need to do this to get help working */
288             XtSetValues(menuDesc[i].widget, menuPaneArgs, 1);
289             break;
290          }
291
292          case MENU_BUTTON:
293          {
294             if ((menuDesc[i].maskBit) &&
295                ((*globalMenuStates & menuDesc[i].maskBit) != 
296                 (*viewMenuStates & menuDesc[i].maskBit)))
297             {
298                _DtGlobalUpdateMenuItemState(menuDesc[i].widget, 
299                                          menuDesc[i].maskBit, 
300                                          *viewMenuStates & menuDesc[i].maskBit,
301                                          globalMenuStates);
302             }
303             break;
304          }
305       }
306    }
307 }
308
309
310 /* ARGSUSED */
311 void
312 _DtGlobalRestoreMenuSensitivity(
313         Widget w,
314         XtPointer client_data,
315         XtPointer call_data )
316
317 {
318    Widget mbar;
319    XmMenuShellWidget mshell = (XmMenuShellWidget) w;
320    void (*getMenuData)() = (void (*)())client_data;
321    XtPointer mainRecord;
322    MenuDesc * menuDesc;
323    int menuItemCount;
324    unsigned int * globalMenuStates;
325    unsigned int * viewMenuStates;
326    int i;
327
328    _XmGetActiveTopLevelMenu(mshell->composite.children[0], &mbar);
329    (*getMenuData)(mbar, &mainRecord, &menuDesc, &menuItemCount,
330                   &globalMenuStates, &viewMenuStates);
331
332    for (i = 0; i < menuItemCount; i++)
333    {
334       if (menuDesc[i].type == MENU_BUTTON)
335       {
336          if ((menuDesc[i].maskBit) && 
337              ((*globalMenuStates & menuDesc[i].maskBit) == 0))
338          {
339             _DtGlobalUpdateMenuItemState(menuDesc[i].widget, 
340                                       menuDesc[i].maskBit, 
341                                       True,
342                                       globalMenuStates);
343          }
344       }
345    }
346 }
347
348
349 void
350 _DtGlobalUpdateMenuItemState(
351         Widget btn,
352         unsigned int mask,
353         unsigned int on,
354         unsigned int * globalMenuStates )
355
356 {
357    if (on != 0)
358    {
359       XtSetSensitive(btn, True);
360       *globalMenuStates |= mask;
361    }
362    else
363    {
364       if(btn != *findBtn             &&
365          btn != *change_directoryBtn && 
366          btn != *preferencesBtn      && 
367          btn != *defaultEnvBtn       && 
368          btn != *filterBtn               ) 
369       {
370         XtSetSensitive(btn, False);
371         *globalMenuStates &= ~mask;
372       }
373    }
374 }
375
376
377 static Widget
378 CreateMenuBtn (
379    Widget parent,
380    Boolean isPushButton,
381    MenuDesc * menuDesc,
382    int btnIndex )
383 {
384    int n;
385    Arg args[10];
386    Widget child;
387    XmString labelString;
388
389    n = 0;
390    labelString = XmStringCreateLocalized(menuDesc->label);
391    XtSetArg(args[n], XmNlabelString, labelString);              n++;
392    XtSetArg(args[n], XmNmnemonic, menuDesc->mnemonic[0]);       n++;
393    if (isPushButton)
394       child = XmCreatePushButtonGadget(parent, menuDesc->name, args, n);
395    else
396    {
397       XtSetArg(args[n], XmNvisibleWhenOff,TRUE);n++;
398       child = XmCreateToggleButtonGadget(parent, menuDesc->name, args, n);
399    }
400    if (menuDesc->helpCallback)
401    {
402       XtAddCallback(child, XmNhelpCallback, menuDesc->helpCallback, 
403                     menuDesc->helpData);
404    }
405    if (menuDesc->activateCallback)
406    {
407       if (isPushButton)
408       {
409          XtAddCallback(child, XmNactivateCallback, menuDesc->activateCallback, 
410                        menuDesc->activateData);
411       }
412       else
413       {
414          XtAddCallback(child, XmNvalueChangedCallback, 
415                        menuDesc->activateCallback, menuDesc->activateData);
416       }
417    }
418    XmStringFree(labelString);
419    return (child);
420 }