Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtwm / WmInitWs.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 /* 
24  * (c) Copyright 1989, 1990, 1991, 1992, 1993, 1994 OPEN SOFTWARE FOUNDATION, INC. 
25  * ALL RIGHTS RESERVED 
26 */ 
27 /* 
28  * Motif Release 1.2.4
29 */ 
30 #ifdef REV_INFO
31 #ifndef lint
32 static char rcsid[] = "$TOG: WmInitWs.c /main/18 1999/09/20 15:18:22 mgreess $"
33 #endif
34 #endif
35 /*
36  * (c) Copyright 1987, 1988, 1989, 1990, 1993, 1994 HEWLETT-PACKARD COMPANY 
37  * (c) Copyright 1993, 1994 International Business Machines Corp.
38  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
39  * (c) Copyright 1993, 1994 Novell, Inc.
40  */
41
42 /*
43  * Included Files:
44  */
45
46 #include "WmGlobal.h"
47 #include "WmResNames.h"
48 #ifdef WSM
49 #include "WmHelp.h"
50 #endif /* WSM */
51 #include "WmICCC.h"
52 #ifdef PANELIST
53 #define DTWM_NEED_FNTPL
54 #include "WmIBitmap.h"
55 #endif /* PANELIST */
56 #ifndef NO_OL_COMPAT
57 #include "WmOL.h"
58 #endif /* NO_OL_COMPAT */
59 #include <X11/Xos.h>
60 #include <X11/cursorfont.h>
61 #include <Xm/Xm.h>
62 #include <X11/Shell.h>
63 #include <X11/Core.h>
64 #include <X11/keysym.h>
65 #ifndef NO_HP_KEY_REMAP
66 #include <Xm/VirtKeysP.h>
67
68 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
69 # include <Xm/DrawingA.h>
70 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
71
72 typedef struct
73   {
74     String default_name ;
75     String new_name ;
76   } str_xref_rec, *str_xref ;
77 #endif /* NO_HP_KEY_REMAP */
78 #ifdef WSM
79 #include <Dt/GetDispRes.h>
80 #include <Dt/SessionP.h>
81 #include <Dt/DtP.h>
82 #include <Dt/Message.h>
83 #include <Dt/WsmM.h>
84 #endif /* WSM */
85
86 /* Busy is also defined in the BMS  -> bms.h. This conflicts with
87  * /usr/include/X11/Xasync.h on ibm.
88  */
89 #ifdef _AIX
90 #ifdef Busy
91 #undef Busy
92 #endif
93 #endif
94 #include <X11/Xlibint.h>
95
96 /*
97  * include extern functions
98  */
99 #ifdef WSM
100 #include "WmBackdrop.h"
101 #endif /* WSM */
102 #include "WmCDInfo.h"
103 #include "WmColormap.h"
104 #include "WmError.h"
105 #include "WmEvent.h"
106 #include "WmFeedback.h"
107 #include "WmFunction.h"
108 #include "WmIDecor.h"
109 #ifdef WSM
110 #include "WmIPC.h"
111 #endif /* WSM */
112 #include "WmIPlace.h"
113 #include "WmIconBox.h"
114 #include "WmKeyFocus.h"
115 #ifdef PANELIST
116 #include "WmPanelP.h"  /* for typedef in WmManage.h */
117 #endif /* PANELIST */
118 #include "WmManage.h"
119 #include "WmMenu.h"
120 #ifdef WSM
121 #include "WmPresence.h"
122 #endif /* WSM */
123 #include "WmProperty.h"
124 #include "WmResCvt.h"
125 #include "WmResource.h"
126 #include "WmSignal.h"
127 #include "WmProtocol.h"
128 #include "WmCDecor.h"
129 #include "stdio.h"
130 #include "WmResParse.h"
131 #ifdef WSM
132 #include <stdlib.h>
133 #endif /* WSM */
134 #include "WmXSMP.h"
135
136 /*
137  * Function Declarations:
138  */
139
140 #include "WmInitWs.h"
141
142 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
143 # include "WmWsmLib/wsm_proto.h"
144 # include "WmWsmLib/utm_send.h"
145 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
146
147 #ifdef WSM
148 static void InsureDefaultBackdropDir(char **ppchBackdropDirs);
149 #endif /* WSM */
150 void InitWmDisplayEnv (void);
151 #ifndef NO_MESSAGE_CATALOG
152 void InitNlsStrings (void);
153 #endif
154 #ifndef NO_HP_KEY_REMAP
155 Boolean VirtKeys4DIN(Display *dpy); 
156 #endif /* NO_HP_KEY_REMAP */
157
158 #ifdef WSM
159 /* limited to 3 chars max */
160 #define UNSPECIFIED_SCREEN_NAME         "fbk"
161 char        **dpy2Argv;    /* copy  for second display */
162 int           dpy2Argc;
163 #ifndef PANELIST
164 WmScreenData *dtSD;       /* for the "DT screen" of the display */
165 #endif /* PANELIST */
166 #endif  /* WSM */
167 /*
168  * Global Variables:
169  */
170 extern int firstTime;
171 #ifndef NO_MESSAGE_CATALOG
172 extern char * pWarningStringFile;
173 extern char * pWarningStringLine;
174 #endif
175
176 /*
177  * InitMouseBinding
178  *
179  * Special case for a two button mouse; move the BMENU binding 
180  * from Button3 to Button2.  Fails for one-button mice.
181  */
182 static void
183 InitMouseBinding(void)
184 {
185     wmGD.numMouseButtons = XGetPointerMapping(DISPLAY, (unsigned char *)0, 0);
186     
187     if (wmGD.numMouseButtons < 3) {
188         wmGD.bMenuButton = Button2;
189     } else {
190         wmGD.bMenuButton = Button3;
191     }
192 }
193
194 /******************************<->*************************************
195  *
196  *  BuildLockMaskSequence ()
197  *
198  *  Set up the sequence of modifier masks to use to when grabbing 
199  *  key- and button-bindings. This sequence of masks is NULL
200  *  terminated.
201  *
202  *  Input:
203  *      wmGD.lockingModMask
204  *
205  *  Output:
206  *      wmGD.pLockMaskSequence
207  *
208  *
209  *************************************<->***********************************/
210 static void
211 BuildLockMaskSequence(void)
212 {
213     int i, j, k;
214     unsigned int mask;
215     unsigned int thisbit;
216     Boolean bit_on;
217     int num_masks;
218     int num_bits;
219     int bit;
220     int run;
221
222     /*
223      * Count the bits to determine the number of elements in 
224      * the mask sequence.  The actual number of masks is
225      * 2^<bitcount> - 1. We're not interested in the case
226      * where there none of the mask bits are set.
227      */
228     mask = wmGD.lockingModMask;
229
230     num_bits=0;
231     while (mask)
232     {
233         if (mask & 0x1)
234         {
235             num_bits++;
236         }
237         mask = mask >> 1;
238     }
239     num_masks = (0x1 << num_bits) - 1;
240
241     /*
242      * Allocate the space for the mask sequence + terminator.
243      */
244     wmGD.pLockMaskSequence = (unsigned int *) 
245                         XtCalloc (num_masks+1, sizeof (unsigned int));
246
247     /*
248      * Fill in the mask sequence
249      */
250     mask = wmGD.lockingModMask;
251     thisbit = 0x1;
252     bit = 0;
253     while (mask && thisbit)
254     {
255         /* find next bit */
256         while (!(thisbit & mask))
257         {
258             thisbit = thisbit << 1;
259         }
260
261         /* clear it from mask */
262         mask &= ~thisbit;
263
264         bit++;
265
266         /* 
267          * Set it in the appropriate slots in the
268          * mask sequence. The start of the loop is
269          * funny because we skip the case of all the
270          * bits cleared.
271          */
272         run = (0x1 << bit-1);   /* number of consecutive masks to set
273                                    bits in */
274         bit_on = False;         /* are we setting bits or not? */
275
276         for (j=0, k=run-1; j<num_masks; j++, k--)
277         {
278             if (k < 1)
279             {
280                 if (bit_on)
281                     bit_on = False;
282                 else
283                     bit_on = True;
284
285                 k = run; 
286             }
287
288             if (bit_on) wmGD.pLockMaskSequence[j] |= thisbit;
289         }
290     }
291 }
292
293
294 /******************************<->*************************************
295  *
296  *  SetupLockingModifierMask ()
297  *
298  *  Set up the mask used to ignore locking modifier keys (e.g. Shift Lock)
299  *  when processing key- and button-bindings.
300  *
301  *  We want to try to ignore the set of locking modifers 
302  *  such as Shift Lock, Num Lock, Kana Lock, etc. This involves
303  *  some amount of guessing since these things can be mapped
304  *  onto any of the Mod1-Mod5 modifiers. The approach taken is to 
305  *  identify the mapping of the locking modifier keysyms to
306  *  Mod1-Mod5 and build the set of masks needed to ignore them.
307  *
308  *************************************<->***********************************/
309
310 /*
311  * This is the set of locking modifiers keysyms that might be
312  * bound to Mod1-Mod5. (Caps Lock is handled independently of
313  * this set.)
314  */
315 static KeySym pksLockingMods[] = {
316     XK_Scroll_Lock,
317     XK_Kana_Lock,
318     XK_Num_Lock,
319     XK_Mode_switch
320 };
321
322 #define NUM_LOCKING_MODS (sizeof(pksLockingMods)/sizeof(KeySym))
323
324 static void
325 SetupLockingModifierMask(void)
326 {
327     int i, j, start_index;
328     XModifierKeymap *modifier_map = NULL;
329     static Modifiers mod_masks[] = { None, Mod1Mask, Mod2Mask,
330                                         Mod3Mask, Mod4Mask, Mod5Mask };
331     Display *dpy = wmGD.display;
332     int pkcLockingMods[NUM_LOCKING_MODS];
333
334     int kcq, kc;
335
336     for (i=0; i<NUM_LOCKING_MODS; i++)
337     {
338         pkcLockingMods[i] = XKeysymToKeycode(dpy, pksLockingMods[i]);
339     }
340
341     /* 
342      * Start out with Caps lock and add others we discover.
343      */
344     wmGD.lockingModMask = LockMask;
345
346     modifier_map = XGetModifierMapping(dpy);
347
348     /* just check Mod1 through Mod5 */
349     start_index = modifier_map->max_keypermod * Mod1MapIndex;
350
351     for (i = start_index; i < modifier_map->max_keypermod * 8; i++) {
352         int this_mod = ((i - start_index) / modifier_map->max_keypermod) + 1;
353  
354         kc = modifier_map->modifiermap[i];
355         if (kc)
356         {
357             for (j=0; j<NUM_LOCKING_MODS; j++)
358             {
359                 if (pkcLockingMods[j] == kc)
360                 {
361                     wmGD.lockingModMask |= mod_masks[this_mod];
362                     break;
363                 }
364             }
365         }
366     }
367
368     BuildLockMaskSequence();
369
370     if(modifier_map != NULL)
371         XFreeModifiermap(modifier_map);
372
373 }
374
375 /******************************<->*************************************
376  *
377  *  MappingEventHandler (Widget, XtPointer, XEvent *, Boolean *)
378  *
379  *  Catch and handle changes to the mapping of the modifier keys.
380  *
381  *************************************<->***********************************/
382
383 static void
384 MappingEventHandler(
385         Widget w,
386         XtPointer client_data,
387         XEvent *event,
388         Boolean *cont_to_dispatch)
389 {
390         if(event->xany.type != MappingNotify ||
391                 event->xmapping.request == MappingPointer)
392                 return;
393  
394         if(event->xmapping.request == MappingModifier)
395                 SetupLockingModifierMask();
396 }
397
398 \f
399 /******************************<->*************************************
400  *
401  *  InitWmGlobal (argc, argv, environ)
402  *
403  *
404  *  Description:
405  *  -----------
406  *  This function initializes the workspace manager.
407  *
408  *
409  *  Inputs:
410  *  ------
411  *  argc = number of command line arguments (+1)
412  *
413  *  argv = window manager command line arguments
414  *
415  *  environ = window manager environment
416  *
417  * 
418  *  Outputs:
419  *  -------
420  *  wmGD = (initialize the global data structure)
421  * 
422  *************************************<->***********************************/
423
424 void InitWmGlobal (int argc, char *argv [], char *environ [])
425 {
426     XSetWindowAttributes sAttributes;
427     int scr;
428     int managed = 0;
429     char pch[80];
430     Boolean activeSet = False;
431     Boolean processedGlobalResources = False;
432     WmScreenData *pSD;
433     Arg args[20];
434     int argnum;
435     char *res_class;
436     int savedArgc;
437
438     wmGD.errorFlag = False;
439 #ifdef WSM
440 #ifndef PANELIST
441     dtSD = NULL; 
442 #else /* PANELIST  */
443     wmGD.dtSD = NULL;
444     wmGD.iSlideUpsInProgress = 0;
445 #endif /*PANELIST  */
446 #endif  /* WSM */
447
448     SetupWmSignalHandlers (0); /* dummy paramater */
449
450
451     /*
452      * Do (pre-toolkit) initialization:
453      */
454
455     wmGD.windowContextType = XUniqueContext ();
456     wmGD.screenContextType = XUniqueContext ();
457 #ifndef IBM_169380
458     wmGD.cmapWindowContextType = XUniqueContext ();
459 #endif
460 #ifdef WSM
461     wmGD.mwmWindowContextType = XUniqueContext ();
462 #endif /* WSM */
463
464     /* copy argv (the XtInititalize changes the original) for use in restart */
465     savedArgc = argc;
466     CopyArgv (argc, argv);
467
468     wmGD.environ = environ;
469
470 #ifdef WSM
471     wmGD.pWmPB = _DtWmParseNewBuf();
472 #endif /* WSM */
473
474
475
476     /* set our name */
477     if ((wmGD.mwmName = (char*)strrchr (wmGD.argv[0], '/')) != NULL)
478     {
479         wmGD.mwmName++;
480     }
481     else
482     {
483         wmGD.mwmName = wmGD.argv[0];
484     }
485 #ifdef WSM
486     if (MwmBehavior)
487     {
488         res_class = WM_RESOURCE_CLASS;
489     }
490     else 
491     {
492         res_class = DT_WM_RESOURCE_CLASS;
493     }
494     wmGD.statusColorServer = CSERVE_NOT_AVAILABLE;
495
496 #else /* WSM */
497     res_class = WM_RESOURCE_CLASS;
498 #endif /* WSM */
499
500     wmGD.display = (Display *)NULL;
501     wmGD.topLevelW = (Widget)NULL;
502
503     /*
504      * Do X Tookit initialization:
505      */   
506
507     XtToolkitInitialize();
508
509     wmGD.mwmAppContext = XtCreateApplicationContext();
510     AddWmResourceConverters ();
511     wmGD.display = XtOpenDisplay (wmGD.mwmAppContext,
512                                   NULL,
513                                   wmGD.mwmName,
514                                   res_class,
515                                   NULL,
516                                   0,
517                                   &argc, /* R5 changed from Cardinal to int*/
518                                   argv);
519     
520     if (!wmGD.display)
521     {
522         Warning(((char *)GETMESSAGE(40, 1, "Could not open display.")));
523         ExitWM (WM_ERROR_EXIT_VALUE);
524     }
525
526 #if defined(sun) && defined(ALLPLANES)
527     {
528         int dummy;
529
530         wmGD.allplanes = XAllPlanesQueryExtension(wmGD.display, 
531                                 &dummy, &dummy);        
532     }
533 #endif /* defined(sun) && defined(ALLPLANES) */
534
535     /*
536      * Setup error handling:
537      */
538
539     WmInitErrorHandler(wmGD.display);
540
541     /*
542      * Initialize cursor size info and 
543      * display the startup cursor.
544      */
545     
546     InitCursorInfo ();
547 #ifdef WSM
548     InitWmDisplayEnv ();
549 #endif
550     ShowWaitState (TRUE);
551
552     /*
553      * Initialize support for BMenu virtual mouse binding
554      */
555     InitMouseBinding();
556     /*
557      * Set up the _MOTIF_BINDINGS property on the root window
558      * of screen 0.  Must do this before we create shells.
559      */
560     
561     ProcessMotifBindings ();
562 #ifndef NO_HP_KEY_REMAP
563
564     /* VirtKeys4DIN deals with a shortcoming in the OSF/Motif
565      *   mechanism for selecting a virtual key binding table.
566      * When a client connects to a display, code inside of libXm
567      *   gets the vendor identifier from the server and uses this
568      *   identifier to select a default virtual key binding table
569      *   from an internal list of possible tables (provided to
570      *   OSF by vendors).  A virtual key binding table maps OSF
571      *   virtual keysyms to an "appropriate" set of X keysyms for
572      *   a particular server vendor.  The problem with this
573      *   mechanism is that it only allows for a _single_ default
574      *   virtual key binding table per server vendor.  If a
575      *   hardware vendor ships more than one distinct keyboard,
576      *   then the single virtual key binding table selected for
577      *   that server might not be appropriate for all keyboards.
578      * The HP migration from the "ITF" keyboard to the "PC-style"
579      *   keyboard causes this problem to be exposed for Motif
580      *   clients.  The default HP virtual key binding table maps
581      *   osfInsert and osfDelete to hpInsertChar and hpDeleteChar,
582      *   respectively.  But since hpInsertChar and hpDeleteChar
583      *   are absent from the PC-style keyboard, HP servers with
584      *   this keyboard do not generate key events that map to the
585      *   important osfInsert and osfDelete virtual keys.
586      * The Motif 1.2 version of libXm installs (one or two)
587      *   properties on the root window, these properties exporting
588      *   the virtual key binding table to be used by all (subsequently
589      *   connected) Motif clients.  The VirtKeys4DIN routine attempts
590      *   to ensure that the virtual key binding table exported by
591      *   those properties does not include dependencies on keysyms
592      *   that are not available in the server's current modmap.
593      *   The routine accomplishes this by searching the keyboard
594      *   mapping of the display for the absence of known problematic
595      *   keysyms.  For those keysyms that are missing from the
596      *   keyboard map, the corresponding dependencies in the
597      *   virtual key binding table are altered to use pre-determined
598      *   substitutes (which are generic X keysyms that are present
599      *   on the PC-style keyboard mapping).
600      * The side-effects of this routine are that if there are no
601      *   key binding properties on the root window when this routine
602      *   is called, there will be a property installed (this occurs
603      *   with all Motif 1.2 clients anyway).  Since the virtual key
604      *   binding table is only altered if it contains a keysym that
605      *   is missing from the server's keyboard mapping, there is
606      *   little chance of deleterious effects.
607      */
608     VirtKeys4DIN(DISPLAY);
609 #endif /* NO_HP_KEY_REMAP */
610     
611     argnum = 0;
612     XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
613     XtSetArg (args[argnum], XtNx, 10000);       argnum++;
614     XtSetArg (args[argnum], XtNy, 0);           argnum++;
615     XtSetArg (args[argnum], XtNwidth, 10);      argnum++;
616     XtSetArg (args[argnum], XtNheight, 10);     argnum++;
617     XtSetArg (args[argnum], XtNmappedWhenManaged, False);       argnum++;
618     XtSetArg (args[argnum], XtNjoinSession, True);              argnum++;
619 #ifdef WSM
620     XtSetArg (args[argnum], XtNrestartStyle, SmRestartNever);   argnum++;
621 #else
622     XtSetArg (args[argnum], XtNrestartStyle, SmRestartIfRunning); argnum++;
623 #endif
624     XtSetArg (args[argnum], XtNargc, savedArgc); argnum++;
625     XtSetArg (args[argnum], XtNargv, wmGD.argv); argnum++;
626
627     /* create topmost shell (application shell) */
628     wmGD.topLevelW = XtAppCreateShell (NULL, 
629                               res_class,
630                               sessionShellWidgetClass,
631                               DISPLAY,
632                               args,
633                               argnum);
634
635 #ifdef __osf__
636     _XmColorObjCreate ( wmGD.topLevelW, NULL, NULL);
637     _XmColorObjCreate ( wmGD.topLevelW, NULL, NULL);
638 #endif
639
640     XtAddEventHandler(wmGD.topLevelW, NoEventMask, True,
641                         MappingEventHandler, NULL);
642
643     /* Add callbacks used for communication with Session Manager. */
644     AddSMCallbacks ();
645
646     /* allocate namespace for screens */
647     InitScreenNames();
648     
649     /* 
650      * Determine the screen management policy (all or none)
651      * Process command line arguments that we handle 
652      * This could change the number of screens we manage 
653      */
654     ProcessGlobalScreenResources ();
655     ProcessCommandLine (argc, argv);
656
657 #ifdef WSM
658     /*
659      * Make sure backdrops are in our icon search path. 
660      * This call MUST occur before ANY icons are looked up either
661      * explicitly or through resource processing!!!
662      * Uses variables set by ProcessGlobalScreenResources and
663      * ProcessCommandLine.
664      */
665     {
666         int sNum;
667         Boolean         useMaskRtn;
668         Boolean         useMultiColorIcons;
669         Boolean         useIconFileCacheRtn;
670         String          sBdPath;
671
672         sNum = (wmGD.numScreens == 1) ? DefaultScreen(DISPLAY) : 0;
673
674         XmeGetIconControlInfo(ScreenOfDisplay(DISPLAY, sNum), &useMaskRtn,
675                     &useMultiColorIcons, &useIconFileCacheRtn);
676
677         sBdPath = wmGD.backdropDirs;
678         InsureDefaultBackdropDir ((char **) &sBdPath);
679
680         _DtWsmSetBackdropSearchPath(XScreenOfDisplay(DISPLAY, sNum), 
681                         sBdPath, useMultiColorIcons);
682
683         XtFree(sBdPath);
684     }
685 #endif /* WSM */
686
687     /*
688      * Allocate data and initialize for screens we manage:
689      */
690
691     if (!(wmGD.Screens = (WmScreenData *) 
692             XtCalloc (wmGD.numScreens, sizeof(WmScreenData))))
693     {
694         ShowWaitState (FALSE);
695         Warning (((char *)GETMESSAGE(40, 2, "Insufficient memory for Screen data")));
696         ExitWM (WM_ERROR_EXIT_VALUE);
697     }
698     else 
699     {
700
701         sAttributes.event_mask = SubstructureRedirectMask;
702
703         for (scr=0; scr<wmGD.numScreens; scr++) 
704         {
705             int sNum;
706             
707             /* 
708              * Gain control of the root windows of each screen:
709              */
710
711             sNum = (wmGD.numScreens == 1) ? DefaultScreen(DISPLAY) : scr;
712             wmGD.errorFlag = False;
713
714             XChangeWindowAttributes (DISPLAY, RootWindow (DISPLAY, sNum), 
715                 CWEventMask, &sAttributes);
716             /*
717              * Do XSync to force server action and catch errors
718              * immediately.
719              */
720             XSync (DISPLAY, False /* do not discard events */);
721
722             if ((wmGD.errorFlag) &&
723                 (RootWindow (DISPLAY, sNum) == (Window) wmGD.errorResource) &&
724                 (wmGD.errorRequestCode == X_ChangeWindowAttributes))
725             {
726                 sprintf(pch, 
727                     ((char *)GETMESSAGE(40, 3, "Another window manager is running on screen %d")), sNum);
728                 Warning ((char *) &pch[0]);
729                 wmGD.Screens[scr].managed = False;
730             }
731             else 
732             {
733                 if (!processedGlobalResources)
734                 {
735 #ifdef WSM
736                     enum { 
737                       XA_DT_SESSION_HINTS, XA_DT_SM_WM_PROTOCOL,
738                       XA_DT_SM_START_ACK_WINDOWS, XA_DT_SM_STOP_ACK_WINDOWS,
739                       XA_DT_WM_WINDOW_ACK, XA_DT_WM_EXIT_SESSION,
740                       XA_DT_WM_LOCK_DISPLAY, XA_DT_WM_READY, NUM_ATOMS };
741                     static char *atom_names[] = {
742                       _XA_DT_SESSION_HINTS, _XA_DT_SM_WM_PROTOCOL,
743                       _XA_DT_SM_START_ACK_WINDOWS, _XA_DT_SM_STOP_ACK_WINDOWS,
744                       _XA_DT_WM_WINDOW_ACK, _XA_DT_WM_EXIT_SESSION,
745                       _XA_DT_WM_LOCK_DISPLAY, _XA_DT_WM_READY };
746
747                     Atom atoms[XtNumber(atom_names)];
748                     XInternAtoms(DISPLAY, atom_names, XtNumber(atom_names), 
749                                  False, atoms);
750
751                     wmGD.xa_DT_SESSION_HINTS = atoms[XA_DT_SESSION_HINTS];
752                     wmGD.xa_DT_SM_WM_PROTOCOL = atoms[XA_DT_SM_WM_PROTOCOL];
753                     wmGD.xa_DT_SM_START_ACK_WINDOWS =
754                       atoms[XA_DT_SM_START_ACK_WINDOWS]; 
755                     wmGD.xa_DT_SM_STOP_ACK_WINDOWS =
756                       atoms[XA_DT_SM_STOP_ACK_WINDOWS]; 
757                     wmGD.xa_DT_WM_WINDOW_ACK = atoms[XA_DT_WM_WINDOW_ACK];
758                     wmGD.xa_DT_WM_EXIT_SESSION = atoms[XA_DT_WM_EXIT_SESSION];
759                     wmGD.xa_DT_WM_LOCK_DISPLAY = atoms[XA_DT_WM_LOCK_DISPLAY];
760                     wmGD.xa_DT_WM_READY = atoms[XA_DT_WM_READY];
761 #endif /* WSM */
762 #ifndef NO_OL_COMPAT
763                     InitOLCompat();
764 #endif /* NO_OL_COMPAT */
765 #ifndef NO_SHAPE
766                     wmGD.hasShape = XShapeQueryExtension (DISPLAY,
767                                                           &wmGD.shapeEventBase,
768                                                           &wmGD.shapeErrorBase);
769 #endif /*  NO_SHAPE  */
770
771                     wmGD.replayEnterEvent = False;
772                     wmGD.menuActive = NULL;
773                     wmGD.menuUnpostKeySpec = NULL;
774                     wmGD.F_NextKeySpec = NULL;
775                     wmGD.F_PrevKeySpec = NULL;
776                     wmGD.passKeysActive = False;
777                     wmGD.passKeysKeySpec = NULL;
778                     wmGD.checkHotspot = False;
779                     wmGD.configAction = NO_ACTION;
780                     wmGD.configPart = FRAME_NONE;
781                     wmGD.configSet = False;
782                     wmGD.preMove = False;
783                     wmGD.gadgetClient = NULL;
784                     wmGD.wmTimers = NULL;
785                     wmGD.clientDefaultTitle = 
786                         XmStringCreateLocalized(DEFAULT_CLIENT_TITLE);
787                     wmGD.iconDefaultTitle = 
788                         XmStringCreateLocalized(DEFAULT_ICON_TITLE);
789                     wmGD.attributesWindow = (Window)NULL;
790                     wmGD.clickData.pCD = NULL;
791                     wmGD.clickData.clickPending = False;
792                     wmGD.clickData.doubleClickPending = False;
793                     wmGD.systemModalActive = False;
794                     wmGD.activeIconTextDisplayed = False;
795                     wmGD.movingIcon = False;
796                     wmGD.queryScreen = True;
797                     wmGD.dataType = GLOBAL_DATA_TYPE;
798
799                     wmGD.pLockMaskSequence = NULL;
800                     SetupLockingModifierMask ();
801 #ifdef WSM
802                     wmGD.requestContextWin = (Window) 0L;
803                     wmGD.cppCommand = NULL;
804                     wmGD.evLastButton.button = 0;
805                     wmGD.bReplayedButton = False;
806                     wmGD.bSuspendSecondaryRestack = False;
807                     /*
808                      *  Get a second display connection for 
809                      *  internal WM windows.
810                      */
811                     wmGD.display1 = XtOpenDisplay (wmGD.mwmAppContext,
812                                                    NULL,
813                                                    wmGD.mwmName,
814                                                    res_class,
815                                                    NULL,
816                                                    0,
817                                                    &dpy2Argc,
818                                                    dpy2Argv);
819                     if (!wmGD.display1)
820                     {
821                         ShowWaitState (FALSE);
822                         Warning(((char *)GETMESSAGE(40, 4, "Could not open second display connection.")));
823                         ExitWM (WM_ERROR_EXIT_VALUE);
824                     }
825
826                     _DtGetSmWindow(DISPLAY, 
827                                   RootWindow(DISPLAY, 0), 
828                                   &wmGD.dtSmWindow) ;
829 #ifdef PANACOMM
830                     /*
831                      * If this is the first screen we've managed,
832                      * tell the session manager we're ready 
833                      */
834                     if (!processedGlobalResources)
835                     {
836                         SendClientMsg( wmGD.dtSmWindow,
837                                       (long) wmGD.xa_DT_SM_WM_PROTOCOL,
838                                       (long) wmGD.xa_DT_WM_READY,
839                                       CurrentTime, NULL, 0);
840                     }
841 #endif /* PANACOMM */
842
843                     /* create topmost shell (application shell) */
844                     argnum = 0;
845                     XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
846                     XtSetArg (args[argnum], XtNx, 10000);       argnum++;
847                     XtSetArg (args[argnum], XtNy, 0);           argnum++;
848                     XtSetArg (args[argnum], XtNwidth, 10);      argnum++;
849                     XtSetArg (args[argnum], XtNheight, 10);     argnum++;
850                     XtSetArg (args[argnum], 
851                                 XtNmappedWhenManaged, False);   argnum++;
852
853                     wmGD.topLevelW1 = 
854                         XtAppCreateShell (NULL, 
855                                           res_class,
856                                           applicationShellWidgetClass,
857                                           DISPLAY1,
858                                           args,
859                                           argnum);
860
861 #endif /* WSM */
862                     
863
864                     /* 
865                      * if this is the first screen we can manage, 
866                      * process global.
867                      */
868                     
869                     processedGlobalResources = True;
870
871                     /*
872                      * Get the _MOTIF_WM_INFO property and determine 
873                      * the startup / restart state.
874                      */
875                     
876                     ProcessMotifWmInfo (RootWindow (DISPLAY, sNum));
877                     
878                     /*
879                      * Process global window manager resources:
880                      */
881 #ifndef NO_MESSAGE_CATALOG
882                     InitBuiltinSystemMenu();
883 #endif
884                     
885                     ProcessWmResources ();
886
887                 }
888                 
889                 InitWmScreen (&(wmGD.Screens[scr]), sNum);
890                 wmGD.Screens[scr].managed = True;
891                 managed++;
892 #ifdef WSM
893                 GetDtSessionHints(&(wmGD.Screens[scr]), sNum);
894 #endif /* WSM */
895
896                 if (!activeSet) 
897                 {
898                     activeSet = True;
899                     ACTIVE_PSD = &wmGD.Screens[scr];
900                 }
901             }
902         }
903
904         if (managed == 0) 
905         {
906             /*
907              * No screens for me to manage, give up.
908              */
909             ShowWaitState (FALSE);
910             Warning (((char *)GETMESSAGE(40, 5, "Unable to manage any screens on display.")));
911             ExitWM (WM_ERROR_EXIT_VALUE);
912         }
913     }
914 #ifdef WSM
915     /*  
916      * Initialize the IPC mechanism
917      */
918     dtInitialize(argv[0], wmGD.mwmAppContext);
919 #ifndef NO_MESSAGE_CATALOG
920     /*
921      * Set up NLS error messages.
922      * Must be done after DtInitialize.
923      */
924     InitNlsStrings ();
925 #endif
926
927     /*
928      *  For multiple connections to the server, turn off
929      *  the geometry manager's insistence on synchronous
930      *  management.
931      */
932
933     argnum = 0;
934     XtSetArg (args[argnum], XmNuseAsyncGeometry, True); argnum++;
935     XtSetValues (wmGD.topLevelW, args, argnum);
936     XtSetValues (wmGD.topLevelW1, args, argnum);
937
938 #endif /* WSM */
939     
940
941     /*
942      * Prepare to have child processes (e.g., exec'ed commands).
943      * The X connection should not be passed on to child processes
944      * (it should be automatically closed when a fork is done).
945      */
946
947     if (fcntl (ConnectionNumber (DISPLAY), F_SETFD, 1) == -1)
948     {
949         ShowWaitState (FALSE);
950         Warning (((char *)GETMESSAGE(40, 6, "Cannot configure X connection")));
951         ExitWM (WM_ERROR_EXIT_VALUE);
952     }
953
954 #ifdef WSM
955
956     {
957       enum { XA_DT_WORKSPACE_HINTS, XA_DT_WORKSPACE_PRESENCE,
958              XA_DT_WORKSPACE_INFO, XA_WmNall,
959              XA_DT_WORKSPACE_EMBEDDED_CLIENTS, XA_DT_WM_REQUEST,
960              XA_DT_WORKSPACE_LIST, XA_DT_WORKSPACE_CURRENT, NUM_ATOMS };
961       static char *atom_names[] = {
962              _XA_DT_WORKSPACE_HINTS, _XA_DT_WORKSPACE_PRESENCE,
963              _XA_DT_WORKSPACE_INFO, WmNall,
964              _XA_DT_WORKSPACE_EMBEDDED_CLIENTS, _XA_DT_WM_REQUEST,
965              _XA_DT_WORKSPACE_LIST, _XA_DT_WORKSPACE_CURRENT };
966
967       Atom atoms[XtNumber(atom_names)];
968       XInternAtoms(DISPLAY, atom_names, XtNumber(atom_names), False, atoms);
969
970       wmGD.xa_DT_WORKSPACE_HINTS = atoms[XA_DT_WORKSPACE_HINTS];
971       wmGD.xa_DT_WORKSPACE_PRESENCE = atoms[XA_DT_WORKSPACE_PRESENCE];
972       wmGD.xa_DT_WORKSPACE_INFO = atoms[XA_DT_WORKSPACE_INFO];
973       wmGD.xa_ALL_WORKSPACES = atoms[XA_WmNall];
974       wmGD.xa_DT_EMBEDDED_CLIENTS = atoms[XA_DT_WORKSPACE_EMBEDDED_CLIENTS];
975       wmGD.xa_DT_WM_REQUEST = atoms[XA_DT_WM_REQUEST];
976       wmGD.xa_DT_WORKSPACE_LIST = atoms[XA_DT_WORKSPACE_LIST];
977       wmGD.xa_DT_WORKSPACE_CURRENT = atoms[XA_DT_WORKSPACE_CURRENT];
978     }
979
980 #endif /* WSM */
981
982     /* Initialize properties used in session management. */
983     wmGD.xa_SM_CLIENT_ID =
984       XmInternAtom (DISPLAY, _XA_DT_SM_CLIENT_ID, False);
985     wmGD.xa_WMSAVE_HINT =
986       XmInternAtom (DISPLAY, _XA_DT_WMSAVE_HINT, False);
987
988     /* Load client resource database. */
989     wmGD.clientResourceDB = LoadClientResourceDB();
990
991     /*
992      * Make the window manager workspace window.
993      * Setup the _MOTIF_WM_INFO property on the root window.
994      */
995
996     SetupWmWorkspaceWindows ();
997
998
999     /* make the cursors that the window manager uses */
1000     MakeWorkspaceCursors ();
1001
1002
1003     /* Sync the table used by Mwm's modifier parser to actual modMasks used */
1004     SyncModifierStrings();
1005
1006     /*
1007      * Setup screen data and resources (after processing Wm resources.
1008      */
1009     for (scr = 0; scr < wmGD.numScreens; scr++)
1010     {
1011         pSD = &(wmGD.Screens[scr]);
1012
1013         if (pSD->managed)
1014         {
1015 #ifdef WSM
1016             if (XDefaultScreen (wmGD.display) == pSD->screen)
1017             {
1018                 wmGD.commandWindow = wmGD.Screens[scr].wmWorkspaceWin;
1019             }
1020
1021 #endif /* WSM */
1022             /*
1023              * Initialize workspace colormap data.
1024              */
1025
1026             InitWorkspaceColormap (pSD);
1027
1028             /*
1029              * Process the window manager resource description file (.mwmrc):
1030              */
1031
1032 #ifdef PANELIST
1033             ProcessWmFile (pSD, False /* not nested */);
1034
1035 #else /* PANELIST */
1036             ProcessWmFile (pSD);
1037 #endif /* PANELIST */
1038
1039
1040             /*
1041              * Setup default resources for the system menu and key bindings:
1042              */
1043
1044             SetupDefaultResources (pSD);
1045
1046
1047             /*
1048              * Make global window manager facilities:
1049              */
1050
1051             if(pSD->iconDecoration & ICON_ACTIVE_LABEL_PART)
1052             {
1053                 /* create active icon window */
1054                 CreateActiveIconTextWindow(pSD); 
1055             }
1056
1057
1058             /*
1059              * Make menus and other resources that are used by window manager
1060              * functions that are activated by menus, buttons and keys.
1061              */
1062
1063             MakeWmFunctionResources (pSD);
1064         }
1065
1066 #ifdef WSM
1067         /*
1068          *
1069          *  Set root cursor to be a pointer for dtwm
1070          *
1071          */
1072
1073 # ifdef __osf__
1074         /* Fixes problem on multiscreen where cursor is only
1075          * set on primary screen.
1076          */
1077         if (DtwmBehavior)
1078         {
1079             XDefineCursor (DISPLAY,
1080                 RootWindow (DISPLAY, scr),
1081                 wmGD.workspaceCursor);
1082         }
1083 # endif
1084 #endif /* WSM */
1085
1086     }
1087 #ifdef PANELIST
1088     /*
1089      * Remove any temp config file we created if we needed to
1090      * convert DT 2.0 syntax to DT 3.0
1091      */
1092     DeleteTempConfigFileIfAny();
1093 #endif /* PANELIST */
1094 #ifdef WSM
1095     /*
1096      * Point second display's resource data base
1097      * to the first display's resource data base
1098      * so dtwm "clients" change colors dynamically.
1099      *
1100      *  NEW LOCATION
1101      */
1102       wmGD.display1->db = wmGD.display->db;
1103 #endif /*  WSM */
1104
1105     /*
1106      * Realize the top level widget, make the window override
1107      * redirect so we don't manage it, and then move it out of the way
1108      */
1109
1110     XtRealizeWidget (wmGD.topLevelW);
1111 #ifdef WSM
1112     XtRealizeWidget (wmGD.topLevelW1);
1113
1114     /*
1115      * Initialize the message handling.
1116      * (This must be done after the realize because a window
1117      *  is required for ICCCM-style messaging).
1118      */
1119     dtInitializeMessaging (wmGD.topLevelW);
1120 #endif /* WSM */
1121
1122     sAttributes.override_redirect = True;
1123     XChangeWindowAttributes (DISPLAY, XtWindow (wmGD.topLevelW),
1124                 CWOverrideRedirect, &sAttributes);
1125
1126
1127     /* setup window manager inter-client communications conventions handling */
1128     SetupWmICCC ();
1129
1130     /*
1131      * Use the WM_SAVE_YOURSELF protocol
1132      * for notification of when to save ourself
1133      */
1134 #ifdef WSM
1135     SetMwmSaveSessionInfo(wmGD.commandWindow);
1136 #endif
1137     /*
1138      * Initialize window manager event handling:
1139      */
1140
1141     InitEventHandling ();
1142
1143
1144
1145     /*
1146      * Initialize frame component graphics
1147      */
1148     {
1149         for (scr = 0; scr < wmGD.numScreens; scr++)
1150         {
1151             pSD = &(wmGD.Screens[scr]);
1152
1153             if (pSD->managed)
1154             {
1155                 InitClientDecoration (pSD);
1156
1157                 /*
1158                  * Make an icon box if specificed:
1159                  */
1160                 if (pSD->useIconBox)
1161                 {
1162                     InitIconBox (pSD);
1163                 }
1164
1165                 /*
1166                  * Adopt client windows that exist before wm startup:
1167                  */
1168
1169                 AdoptInitialClients (pSD);
1170
1171                 /*
1172                  * Setup initial keyboard focus and colormap focus:
1173                  */
1174
1175                 InitColormapFocus (pSD);
1176
1177             }
1178         }
1179
1180         for (scr = 0; scr < wmGD.numScreens; scr++)
1181         {
1182 #ifdef WSM
1183             int iws;
1184 #endif /* WSM */
1185             pSD = &(wmGD.Screens[scr]);
1186             
1187             if (pSD->managed)
1188             {
1189                 ACTIVE_PSD = &wmGD.Screens[scr];
1190 #ifdef WSM
1191                 MapIconBoxes (pSD->pActiveWS);
1192
1193                 ChangeBackdrop (pSD->pActiveWS);
1194
1195 #ifdef HP_VUE
1196                 UpdateWorkspaceInfoProperty (pSD); /* backward compatible */
1197 #endif /* HP_VUE */
1198
1199                 SetCurrentWorkspaceProperty (pSD);
1200                 SetWorkspaceListProperty (pSD);
1201
1202                 for (iws=0; iws < pSD->numWorkspaces; iws++)
1203                 {
1204                     SetWorkspaceInfoProperty (&(pSD->pWS[iws]));
1205                 }
1206
1207
1208 XFlush (DISPLAY);
1209
1210
1211
1212                 /* MapWorkspaceBox (); */
1213
1214 #ifdef PANELIST
1215                 /*
1216                  * Allocate front panel widgets
1217                  */
1218                 if (wmGD.useFrontPanel &&  (pSD == wmGD.dtSD))
1219                 {
1220                     Pixmap      iconBitmap;
1221                     Arg         al[5];
1222                     int         ac;
1223                     Widget      wFpShell;
1224                     WmPanelistObject  pPanelist;
1225
1226                     wmGD.dtSD->wPanelist =
1227                        WmPanelistAllocate(pSD->screenTopLevelW1, 
1228                                           (XtPointer) &wmGD, (XtPointer) pSD);
1229
1230                     pPanelist = (WmPanelistObject) pSD->wPanelist;
1231
1232                     if (pPanelist != NULL && O_Shell(pPanelist))
1233                     {
1234                         /*
1235                          * Make a default front panel icon image.
1236                          */
1237                         iconBitmap = XCreateBitmapFromData (DISPLAY, 
1238                                     pSD->rootWindow, 
1239                                     (char *) fntpl_i_bm_bits, 
1240                                     fntpl_i_bm_width, 
1241                                     fntpl_i_bm_height);
1242
1243                         ac = 0; 
1244                         XtSetArg (al[ac], XmNiconPixmap, iconBitmap); ac++; 
1245                         XtSetValues (O_Shell(pPanelist), al, ac);
1246
1247                     }
1248                 }
1249
1250                 if (wmGD.useFrontPanel && pSD->wPanelist && 
1251                     (pSD == wmGD.dtSD))
1252                 {
1253                     /*
1254                      * Make the front panel visible
1255                      */
1256                     WmPanelistShow (pSD->wPanelist);
1257
1258                     /*
1259                      * Find special clients associated with the
1260                      * front panel. This needs to be done after
1261                      * WmPanelistShow where the data is set up.
1262                      */
1263                     ScanForPushRecallClients (pSD);
1264                     ScanForEmbeddedClients (pSD);
1265                 }
1266 #endif /* PANELIST */
1267                 
1268                 RestoreHelpDialogs(pSD);
1269 #else /* WSM */
1270                 MapIconBoxes (pSD->pActiveWS);
1271 #endif /* WSM */
1272             }
1273         }
1274         firstTime = 0;
1275     }
1276     
1277     InitKeyboardFocus ();
1278
1279 #ifndef WSM
1280     InitWmDisplayEnv ();
1281 #endif
1282     ShowWaitState (FALSE);
1283
1284 #ifdef WSM
1285     /*
1286      * Tell the rest of DT that we're up
1287      */
1288     dtReadyNotification();
1289 #endif /* WSM */
1290
1291 #ifdef DEBUG_RESOURCE_DATABASE
1292     XrmPutFileDatabase(wmGD.display->db, "/tmp/dtwm.resDB");
1293 #endif /* DEBUG_RESOURCE_DATABASE */
1294
1295 } /* END OF FUNCTION InitWmGlobal */
1296
1297
1298 \f
1299 /******************************<->*************************************
1300  *
1301  *  InitWmScreen
1302  *
1303  *
1304  *  Description:
1305  *  -----------
1306  *  This function initializes a screen data block.
1307  *
1308  *  Inputs:
1309  *  -------
1310  *  pSD = pointer to preallocated screen data block
1311  *  sNum = screen number for this screen
1312  *
1313  *  Outputs:
1314  *  -------
1315  *************************************<->***********************************/
1316
1317 void
1318 InitWmScreen (WmScreenData *pSD, int sNum)
1319 {
1320     Arg args[12];
1321     int argnum;
1322
1323 #ifdef WSM
1324     int wsnum;
1325     WmWorkspaceData *pwsI;
1326     int buf_size;
1327     int i;
1328     static int dupnum = 0;
1329     int iwsx;
1330 #endif /* WSM */
1331
1332     char *pDisplayName;
1333 #define LENCBUFFER 256
1334     char buffer[LENCBUFFER];            /* screen name & display name! */
1335     char displayName[LENCBUFFER];
1336     char *token1, *token2;
1337
1338
1339    /*
1340     * Set screen data values
1341     */
1342
1343     pSD->rootWindow = RootWindow (DISPLAY, sNum);
1344     pSD->clientCounter = 0;
1345     pSD->defaultSystemMenuUseBuiltin = TRUE;
1346     pSD->displayString = NULL;
1347     pSD->acceleratorMenuCount = 0;
1348     pSD->activeIconTextWin = (Window)NULL;
1349     pSD->focusPriority = 0;
1350     pSD->inputScreenWindow = (Window)NULL;
1351     pSD->colormapFocus = NULL;
1352     pSD->keySpecs = NULL;
1353     pSD->screen = sNum;
1354     pSD->confirmboxW[DEFAULT_BEHAVIOR_ACTION] = NULL;
1355     pSD->confirmboxW[CUSTOM_BEHAVIOR_ACTION] = NULL;
1356     pSD->confirmboxW[RESTART_ACTION] = NULL;
1357     pSD->confirmboxW[QUIT_MWM_ACTION] = NULL;
1358     pSD->feedbackWin = (Window)NULL;
1359     pSD->fbStyle = FB_OFF;
1360     pSD->fbWinWidth = 0;
1361     pSD->fbWinHeight = 0;
1362     pSD->fbLocation[0] = '\0';
1363     pSD->fbSize[0] = '\0';
1364     pSD->fbLocX = 0;
1365     pSD->fbLocY = 0;
1366     pSD->fbSizeX = 0;
1367     pSD->fbSizeY = 0;
1368     pSD->fbLastX = -1;
1369     pSD->fbLastY = -1;
1370     pSD->fbLastWidth = -1;
1371     pSD->fbLastHeight = -1;
1372     pSD->fbTop = NULL;
1373     pSD->fbBottom = NULL;
1374     pSD->actionNbr = -1;
1375     pSD->clientList = NULL;
1376     pSD->lastClient = NULL;
1377     pSD->lastInstalledColormap = (Colormap)NULL;
1378     pSD->shrinkWrapGC = NULL;
1379     pSD->bitmapCache = NULL;
1380     pSD->bitmapCacheSize = 0;
1381     pSD->bitmapCacheCount = 0;
1382     pSD->dataType = SCREEN_DATA_TYPE;
1383     pSD->managed = False;
1384 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
1385     pSD->cciTree = NULL;
1386 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
1387
1388 #ifdef WSM
1389     pSD->initialWorkspace=NULL;
1390     pSD->presence.shellW = NULL;
1391     pSD->presence.onScreen = False;
1392     pSD->presence.userDismissed = True;
1393     pSD->workspaceList = NULL;
1394     pSD->numWorkspaces = 0;
1395     pSD->numWsDataAllocated = 0;
1396     pSD->lastBackdropWin = NULL;
1397     pSD->pDtSessionItems = NULL;
1398     pSD->totalSessionItems = 0;
1399     pSD->remainingSessionItems = 0;
1400
1401     pSD->cachedHelp = NULL;
1402     pSD->dtHelp.shell  = (Widget)NULL;
1403     pSD->dtHelp.dialog = (Widget)NULL;
1404     pSD->dtHelp.errorDialog = (Widget)NULL;
1405     pSD->dtHelp.xPos = 0;
1406     pSD->dtHelp.yPos = 0;
1407     pSD->dtHelp.restored = False;
1408     pSD->dtHelp.onScreen = False;
1409     pSD->dtHelp.userDismissed = False;
1410     pSD->dtHelp.pCDforClient= NULL;
1411     pSD->helpResources=NULL;
1412     pSD->bMarqueeSelectionInitialized = False;
1413     pSD->woN = (Window) 0L;
1414     pSD->woS = (Window) 0L;
1415     pSD->woE = (Window) 0L;
1416     pSD->woW = (Window) 0L;
1417 #endif /* WSM */
1418 #ifdef PANELIST
1419     pSD->wPanelist = NULL;
1420     pSD->pECD = NULL;
1421     pSD->numPushRecallClients = 0;
1422     pSD->numEmbeddedClients = 0;
1423     pSD->pPRCD = NULL;
1424     pSD->iconBoxControl = False;
1425 #endif /* PANELIST */
1426 #ifdef WSM
1427     pSD->displayResolutionType = _DtGetDisplayResolution(DISPLAY, sNum);
1428
1429     /*
1430      *  We've got display resolution type--now, let's get color
1431      *  characteristics.
1432      */
1433
1434     ProcessWmColors (pSD);
1435
1436     if (!(strcmp ((char *)wmGD.screenNames[sNum], UNSPECIFIED_SCREEN_NAME)))
1437     {
1438         sprintf (buffer, "%d", sNum);
1439
1440         buf_size = strlen(buffer) + 1;
1441
1442         if ((wmGD.screenNames[sNum] = 
1443              (unsigned char *)XtRealloc (wmGD.screenNames[sNum], buf_size)) == NULL)
1444         {
1445             Warning (((char *)GETMESSAGE(40, 7, "Cannot create enough memory for the screen names")));
1446             ExitWM (WM_ERROR_EXIT_VALUE);
1447         }
1448         else
1449         {
1450             strcpy((char *)wmGD.screenNames[sNum], buffer);
1451         }
1452     } /* if wmGD.screenNames[sNum] == UNSPECIFIED_SCREEN_NAME */
1453
1454 #endif /* WSM */
1455     /*
1456      * Save screen context
1457      */
1458     XSaveContext (DISPLAY, pSD->rootWindow, wmGD.screenContextType,
1459         (caddr_t)pSD);
1460     /*
1461      * Create shell widget for screen resource hierarchy
1462      */
1463
1464     argnum = 0;
1465     XtSetArg (args[argnum], XtNgeometry, NULL); argnum++;
1466     XtSetArg (args[argnum], XtNx, 10000);       argnum++;
1467     XtSetArg (args[argnum], XtNy, 10000);       argnum++;
1468     XtSetArg (args[argnum], XtNwidth, 10);      argnum++;
1469     XtSetArg (args[argnum], XtNheight, 10);     argnum++;
1470     XtSetArg (args[argnum], XtNoverrideRedirect, True); argnum++;
1471
1472     XtSetArg (args[argnum], XtNdepth, 
1473             DefaultDepth(DISPLAY, sNum));       argnum++;
1474     XtSetArg (args[argnum], XtNscreen, 
1475             ScreenOfDisplay(DISPLAY, sNum));    argnum++;
1476     XtSetArg (args[argnum], XtNcolormap, 
1477             DefaultColormap(DISPLAY, sNum));    argnum++;
1478
1479     pSD->screenTopLevelW = XtCreatePopupShell ((String) wmGD.screenNames[sNum],
1480                                                vendorShellWidgetClass,
1481                                                wmGD.topLevelW,
1482                                                args,
1483                                                argnum);
1484
1485 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
1486     /* Create a DrawingArea as a child of the popupShell.  This will be used
1487      * to handle UTM traffic relating to cci.  We need this
1488      * particular widget to get the callbacks from conversion requests made
1489      * against Mwm and the requests Mwm makes against other clients.
1490      */
1491     pSD->utmShell = XmCreateDrawingArea(pSD->screenTopLevelW, "UTM_Shell",
1492                                         NULL, 0);
1493     XtManageChild(pSD->utmShell);
1494
1495     /*
1496      * Setup the destinationCallback handler to handle conversion
1497      * requests made by Mwm against other clients.
1498      */
1499     XtAddCallback(pSD->utmShell, XmNdestinationCallback, UTMDestinationProc,
1500                   NULL);
1501
1502     /* Must realize to own WM_i if unmapped, causes mwm to
1503        freeze when menu is displayed. */
1504     XtPopup(pSD->screenTopLevelW, XtGrabNone);
1505 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
1506
1507 #ifdef WSM
1508     argnum = 0;
1509     XtSetArg (args[argnum], XtNgeometry, NULL);                 argnum++;
1510     XtSetArg (args[argnum], XtNx, 10000);                       argnum++;
1511     XtSetArg (args[argnum], XtNy, 10000);                       argnum++;
1512     XtSetArg (args[argnum], XtNwidth, 10);                      argnum++;
1513     XtSetArg (args[argnum], XtNheight, 10);                     argnum++;
1514     XtSetArg (args[argnum], XtNoverrideRedirect, True);         argnum++;
1515     XtSetArg (args[argnum], XtNmappedWhenManaged, False);       argnum++;
1516
1517     XtSetArg (args[argnum], XtNdepth, 
1518             DefaultDepth(DISPLAY1, sNum));      argnum++;
1519     XtSetArg (args[argnum], XtNscreen, 
1520             ScreenOfDisplay(DISPLAY1, sNum));   argnum++;
1521     XtSetArg (args[argnum], XtNcolormap, 
1522             DefaultColormap(DISPLAY1, sNum));   argnum++;
1523
1524     pSD->screenTopLevelW1 = XtCreatePopupShell ((String) wmGD.screenNames[sNum],
1525                                                vendorShellWidgetClass,
1526                                                wmGD.topLevelW1,
1527                                                args,
1528                                                argnum);
1529     XtRealizeWidget (pSD->screenTopLevelW1);
1530 #endif /* WSM */
1531     /*
1532      * Fetch screen based resources
1533      */
1534     ProcessScreenResources (pSD, wmGD.screenNames[sNum]);
1535
1536     /*
1537      * Initialize other screen resources and parameters
1538      */
1539     MakeXorGC (pSD);
1540     InitIconSize(pSD);
1541
1542 #ifdef WSM
1543     /*
1544      *  Complete initialization of workspace structures
1545      */
1546     for (wsnum = 0, 
1547          pwsI = pSD->pWS; wsnum < pSD->numWorkspaces; 
1548          wsnum++, pwsI++)
1549     {
1550         /*
1551          * Set up workspace for this screen
1552          */
1553         InitWmWorkspace (pwsI, pSD);
1554
1555     }
1556
1557     if (pSD->initialWorkspace)
1558     {
1559         /* 
1560          * restore to the last initialWorkspace saved from
1561          * Quit, Restart, OR save session 
1562          */
1563
1564         /*
1565          * Compare initialWorkspace against workspace name,
1566          * NOT workspace title.
1567          */
1568         for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
1569         {
1570             if (!strcmp(pSD->pWS[iwsx].name, pSD->initialWorkspace))
1571             {
1572                 break;
1573             }
1574         }
1575         /* check bounds */
1576         if (iwsx >= pSD->numWorkspaces)
1577         {
1578             /* make first workspace in list the active one to start with */
1579             pSD->pActiveWS = pSD->pWS;
1580         }
1581         else
1582         {
1583             pSD->pActiveWS = &pSD->pWS[iwsx];
1584         }
1585     }
1586     else
1587     {
1588         /* make first workspace in list the active one to start with */
1589         pSD->pActiveWS = pSD->pWS;
1590     }
1591 #else /* WSM */
1592     /*
1593      *  Allocate and initialize a workspace structure
1594      */
1595     
1596     if (!(pSD->pWS = (WmWorkspaceData *) XtMalloc (sizeof(WmWorkspaceData))))
1597     {
1598         ShowWaitState (FALSE);
1599         Warning (((char *)GETMESSAGE(40, 8, "Insufficient memory for Workspace data")));
1600         ExitWM (WM_ERROR_EXIT_VALUE);
1601     }
1602
1603     /*
1604      * Set up workspace for this screen
1605      */
1606     InitWmWorkspace (pSD->pWS, pSD);
1607     pSD->pActiveWS = pSD->pWS;
1608 #endif /* WSM */
1609
1610
1611     pDisplayName = DisplayString (DISPLAY);
1612
1613     /*
1614      * Construct displayString for this string.  
1615      *
1616      * NOTE: The variable buffer is reused here. It was
1617      * used earlier to generate a screen name.
1618      */
1619
1620     strcpy(displayName, pDisplayName);
1621
1622     token1 = (char*)strtok(displayName, ":");           /* parse of hostname */
1623
1624     if((token2 = (char*)strtok(NULL, ".")) ||           /* parse off dpy & scr # */
1625        (token2 = (char*)strtok(NULL, "")) ||
1626        (displayName[0] == ':'))
1627     {
1628         if (displayName[0] == ':')              /* local dpy (special case) */
1629         {
1630             if ((token2 = (char*)strtok(token1, ".")) != NULL)  /* parse dpy# */
1631                 sprintf(buffer, "DISPLAY=:%s.%d",
1632                         token2, sNum);
1633         } else {                                /* otherwise process normally */
1634             sprintf(buffer, "DISPLAY=%s:%s.%d",
1635                     token1, token2, sNum);
1636         }
1637
1638         /*              
1639          * Allocate space for the display string
1640          */
1641     
1642         if ((pSD->displayString =
1643              (String)XtMalloc ((unsigned int) (strlen(buffer) + 1))) == NULL)
1644         {
1645             Warning (((char *)GETMESSAGE(40, 9, 
1646                                     "Insufficient memory for displayString")));
1647         }
1648         else
1649         {
1650             strcpy(pSD->displayString, buffer);
1651         }
1652
1653     }
1654
1655
1656
1657 } /* END OF FUNCTION  InitWmScreen */
1658
1659 \f
1660 /*************************************<->*************************************
1661  *
1662  *  InitWmWorkspace
1663  *
1664  *
1665  *  Description:
1666  *  -----------
1667  *  This function initializes a workspace data block.
1668  *
1669  *  Inputs:
1670  *  -------
1671  *  pWS = pointer to preallocated workspace data block
1672  *  pSD = ptr to parent screen data block
1673  *
1674  *  Outputs:
1675  *  -------
1676  *************************************<->***********************************/
1677
1678 void InitWmWorkspace (WmWorkspaceData *pWS, WmScreenData *pSD)
1679 {
1680     Arg args[10];
1681     int argnum;
1682
1683 #ifndef WSM
1684 #define DEFAULT_WS_NAME "workspace"
1685 #endif /* not WSM */
1686
1687     pWS->pSD = pSD;
1688     pWS->pIconBox = NULL;
1689     pWS->dataType = WORKSPACE_DATA_TYPE;
1690 #ifdef WSM
1691     pWS->backdrop.window = 0;
1692     pWS->backdrop.nameAtom = 0;
1693     pWS->backdrop.image = NULL;
1694     pWS->numClients = 0;
1695     pWS->sizeClientList = 0;
1696     pWS->ppClients = 0;
1697     pWS->buttonW = NULL;
1698 #else /* WSM */
1699
1700     if ((pWS->name = (char *) 
1701             XtMalloc ((1+strlen(DEFAULT_WS_NAME)) * sizeof (char))) == NULL)
1702     {
1703         ShowWaitState (FALSE);
1704         ExitWM (WM_ERROR_EXIT_VALUE);
1705     }
1706     strcpy (pWS->name, DEFAULT_WS_NAME);
1707 #endif /* WSM */
1708
1709     /*
1710      * Create widget for workspace resource hierarchy
1711      */
1712     argnum = 0;
1713     XtSetArg (args[argnum], XtNdepth, 
1714             DefaultDepth(DISPLAY, pSD->screen));        argnum++;
1715     XtSetArg (args[argnum], XtNscreen, 
1716             ScreenOfDisplay(DISPLAY, pSD->screen));     argnum++;
1717     XtSetArg (args[argnum], XtNcolormap, 
1718             DefaultColormap(DISPLAY, pSD->screen));     argnum++;
1719     XtSetArg (args[argnum], XtNwidth,  5);              argnum++;
1720     XtSetArg (args[argnum], XtNheight,  5);             argnum++;
1721
1722     pWS->workspaceTopLevelW = XtCreateWidget (  pWS->name,
1723                                                 xmPrimitiveWidgetClass,
1724                                                 pSD->screenTopLevelW,
1725                                                 args,
1726                                                 argnum);
1727
1728 #ifdef WSM
1729     /* internalize the workspace name */
1730     pWS->id = XInternAtom (DISPLAY, pWS->name, False);
1731 #endif /* WSM */
1732
1733     /*
1734      * Process workspace based resources
1735      */
1736     ProcessWorkspaceResources (pWS);    
1737
1738     /* setup icon placement */
1739     if (wmGD.iconAutoPlace)
1740     {
1741         InitIconPlacement (pWS); 
1742     }
1743
1744 } /* END OF FUNCTION  InitWmWorkspace */
1745
1746 #ifdef WSM
1747 \f
1748 /******************************<->*************************************
1749  *
1750  *  InsureDefaultBackdropDir(char **ppchBackdropDirs)
1751  *
1752  *
1753  *  Description:
1754  *  -----------
1755  *  This function checks and edits a directory path to insure
1756  *  that the system backdrop directroy (/usr/dt/backdrops) is in the 
1757  *  path. If not it adds it to the end. Further, it always adds the user's 
1758  *  backdrop directory ($HOME/.dt/backdrops) to the beginning of the path 
1759  *  and the system admin directory (/etc/dt/backdrops) before the system
1760  *  directory.
1761  *
1762  *  Inputs:
1763  *  -------
1764  *  ppchBackdropDirs  - Pointer to a pointer to a directory path 
1765  *                      (must be allocated memory)
1766  *
1767  *  Outputs:
1768  *  -------
1769  *  *ppchBackdropDirs - Directory path may be modified, path 
1770  *                      pointer may be realloc'ed.
1771  * 
1772  *  Comments:
1773  *  --------
1774  *  Assumes that the default directory does not start with a
1775  *  multi-byte character.
1776  * 
1777  ******************************<->***********************************/
1778 static void
1779 InsureDefaultBackdropDir(char **ppchBackdropDirs)
1780 {
1781   int len;
1782   Boolean bFound = False;
1783   char *pch, *pchEnd, *pch2, *tmpptr;
1784   char *pchD = DEFAULT_BACKDROP_DIR;
1785   unsigned int chlen;
1786   char * homeDir;
1787
1788   /*
1789    * Set up initial stuff
1790    */
1791   pch = *ppchBackdropDirs;
1792   len = strlen (pchD);
1793   pchEnd = pch + strlen(pch);
1794   
1795   while (!bFound && (pch != NULL) && (*pch != NULL))
1796     {
1797       if (strncmp (pch, pchD, len) == 0)
1798         {
1799           /* found partial match, confirm complete match ...
1800            * complete match if char off end of partial match
1801            * is a NULL or a colon 
1802            */
1803           pch2 = pch + len;     
1804           if ((pch2 <= pchEnd) &&
1805               ((*pch2 == NULL) ||
1806                (((mblen (pch2, MB_CUR_MAX) == 1) &&
1807                  (*pch2 == ':')))))
1808             {
1809               bFound = True;
1810             }
1811         }
1812       else 
1813         {
1814           /* find next path component */
1815           pch = strchr (pch, (int) ':'); 
1816           if ((pch != NULL) && (*pch != NULL))
1817             { 
1818               /* skip path separator */
1819               chlen = mblen (pch, MB_CUR_MAX);
1820               pch += chlen;
1821             }
1822         }
1823     }
1824   
1825
1826   /*
1827    * Always add the user's home directory to the beginning of the string
1828    */
1829   homeDir = (char *) XmeGetHomeDirName();  
1830     
1831   /*
1832    * If found add the user's home directory ($HOME/.dt/backdrops) and the 
1833    * admin directory /etc/dt/backdrops to the beginning of the string
1834    */
1835   
1836   if (bFound)  
1837     {
1838       len = strlen (homeDir) + strlen("/.dt/backdrops") + 
1839             strlen (*ppchBackdropDirs) + strlen("/etc/dt/backdrops") + 3;
1840       tmpptr = XtMalloc (len * sizeof (char *));
1841       strcpy (tmpptr, homeDir);
1842       strcat (tmpptr, "/.dt/backdrops");
1843       strcat (tmpptr, ":");
1844       strcat (tmpptr, "/etc/dt/backdrops");
1845       strcat (tmpptr, ":");
1846       strcat (tmpptr, *ppchBackdropDirs);
1847       *ppchBackdropDirs = tmpptr;
1848     }
1849   else
1850     /*
1851      * If string not found, then add home directory to the beginning of 
1852      * string and the admin directory and system directory to the end.
1853      */
1854     {
1855       len = strlen (homeDir) + strlen("/.dt/backdrops") + 
1856             strlen (*ppchBackdropDirs) + strlen(pchD) + 
1857             strlen("/etc/dt/backdrops") + 4;
1858       tmpptr = XtMalloc (len * sizeof (char *));
1859       strcpy (tmpptr, homeDir);
1860       strcat (tmpptr, "/.dt/backdrops");
1861       strcat (tmpptr, ":");
1862       strcat (tmpptr, *ppchBackdropDirs); 
1863       strcat (tmpptr, ":");
1864       strcat (tmpptr, "/etc/dt/backdrops"); 
1865       strcat (tmpptr, ":");
1866       strcat (tmpptr, pchD);
1867       *ppchBackdropDirs = tmpptr;
1868     }
1869   
1870 } /* END OF FUNCTION InsureDefaultBackdropDirs */
1871 #endif /* WSM */
1872
1873 \f
1874 /*************************************<->*************************************
1875  *
1876  *  ProcessMotifWmInfo (rootWindowOfScreen)
1877  *
1878  *
1879  *  Description:
1880  *  -----------
1881  *  This function is used retrieve and save the information in the 
1882  *  _MOTIF_WM_INFO property.  If the property does not exist then
1883  *  the start / restart state is set to initial startup with the
1884  *  user specified (not standard) configuration.
1885  *
1886  *
1887  *  Outputs:
1888  *  -------
1889  *  wmGD.useStandardBehavior = True if set indicated in property
1890  *
1891  *  wmGD.wmRestarted = True if the window manager was restarted
1892  * 
1893  *************************************<->***********************************/
1894
1895 void ProcessMotifWmInfo (Window rootWindowOfScreen)
1896 {
1897     MwmInfo *pMwmInfo;
1898
1899     wmGD.xa_MWM_INFO = XInternAtom (DISPLAY, _XA_MWM_INFO, False);
1900     if ((pMwmInfo = (MotifWmInfo *)GetMwmInfo (rootWindowOfScreen)) != NULL)
1901     {
1902         wmGD.useStandardBehavior =
1903                 (pMwmInfo->flags & MWM_INFO_STARTUP_STANDARD) ? True : False;
1904         wmGD.wmRestarted = True;
1905         XFree ((char *)pMwmInfo);
1906     }
1907     else
1908     {
1909         wmGD.useStandardBehavior = False;
1910         wmGD.wmRestarted = False;
1911     }
1912
1913 } /* END OF FUNCTION ProcessMotifWmInfo */
1914
1915
1916 \f
1917 /*************************************<->*************************************
1918  *
1919  *  SetupWmWorkspaceWindows ()
1920  *
1921  *
1922  *  Description:
1923  *  -----------
1924  *  This function is used to setup a window that can be used in doing window
1925  *  management functions.  This window is not visible on the screen.
1926  *
1927  *
1928  *  Outputs:
1929  *  -------
1930  *  pSD->wmWorkspaceWin = window that is used to hold wm properties
1931  * 
1932  *************************************<->***********************************/
1933
1934 void SetupWmWorkspaceWindows (void)
1935 {
1936     int scr;
1937     WmScreenData *pSD;
1938     XSetWindowAttributes sAttributes;
1939
1940     for (scr = 0; scr < wmGD.numScreens; scr++)
1941     {
1942         pSD = &(wmGD.Screens[scr]);
1943         if (pSD->managed)
1944         {
1945             sAttributes.override_redirect = True;
1946             sAttributes.event_mask = FocusChangeMask | PropertyChangeMask;
1947             pSD->wmWorkspaceWin = XCreateWindow (DISPLAY, pSD->rootWindow, 
1948                                       -100, -100, 10, 10, 0, 0, 
1949                                       InputOnly, CopyFromParent,
1950                                       (CWOverrideRedirect |CWEventMask),
1951                                       &sAttributes);
1952
1953             XMapWindow (DISPLAY, pSD->wmWorkspaceWin);
1954
1955             SetMwmInfo (pSD->rootWindow, 
1956                         (long) ((wmGD.useStandardBehavior) ?
1957                         MWM_INFO_STARTUP_STANDARD : MWM_INFO_STARTUP_CUSTOM), 
1958                         pSD->wmWorkspaceWin);
1959 #ifdef WSM
1960             XSaveContext (DISPLAY, pSD->wmWorkspaceWin, 
1961                     wmGD.mwmWindowContextType, (caddr_t)pSD);
1962 #endif /* WSM */
1963         }
1964     }
1965
1966 } /* END OF FUNCTION SetupWmWorkspaceWindow */
1967
1968
1969 \f
1970 /*************************************<->*************************************
1971  *
1972  *  MakeWorkspaceCursors ()
1973  *
1974  *
1975  *  Description:
1976  *  -----------
1977  *  This function makes the cursors that the window manager uses.
1978  *
1979  *
1980  *  Inputs:
1981  *  ------
1982  *  XXinput = ...
1983  *
1984  *  XXinput = ...
1985  *
1986  * 
1987  *  Outputs:
1988  *  -------
1989  *  wmGD = (stretchCursors ...)
1990  * 
1991  *************************************<->***********************************/
1992
1993 void MakeWorkspaceCursors (void)
1994 {
1995     wmGD.workspaceCursor = XCreateFontCursor (DISPLAY, XC_left_ptr);
1996
1997     wmGD.stretchCursors[STRETCH_NORTH_WEST] =
1998         XCreateFontCursor (DISPLAY, XC_top_left_corner);
1999     wmGD.stretchCursors[STRETCH_NORTH] =
2000         XCreateFontCursor (DISPLAY, XC_top_side);
2001     wmGD.stretchCursors[STRETCH_NORTH_EAST] =
2002         XCreateFontCursor (DISPLAY, XC_top_right_corner);
2003     wmGD.stretchCursors[STRETCH_EAST] =
2004         XCreateFontCursor (DISPLAY, XC_right_side);
2005     wmGD.stretchCursors[STRETCH_SOUTH_EAST] =
2006         XCreateFontCursor (DISPLAY, XC_bottom_right_corner);
2007     wmGD.stretchCursors[STRETCH_SOUTH] =
2008         XCreateFontCursor (DISPLAY, XC_bottom_side);
2009     wmGD.stretchCursors[STRETCH_SOUTH_WEST] =
2010         XCreateFontCursor (DISPLAY, XC_bottom_left_corner);
2011     wmGD.stretchCursors[STRETCH_WEST] =
2012         XCreateFontCursor (DISPLAY, XC_left_side);
2013
2014     wmGD.configCursor = XCreateFontCursor (DISPLAY, XC_fleur);
2015
2016     wmGD.movePlacementCursor = XCreateFontCursor (DISPLAY, XC_ul_angle);
2017     wmGD.sizePlacementCursor = XCreateFontCursor (DISPLAY, XC_lr_angle);
2018
2019
2020 } /* END OF FUNCTION MakeWorkspaceCursors */
2021
2022
2023 \f
2024 /*************************************<->*************************************
2025  *
2026  *  MakeWmFunctionResources (pSD)
2027  *
2028  *
2029  *  Description:
2030  *  -----------
2031  *  This function makes menus and other resources that are used by window
2032  *  manager functions.
2033  *
2034  *
2035  *  Inputs:
2036  *  ------
2037  *  wmGD  = (menuSpecs, keySpecs, buttonSpecs)
2038  *
2039  * 
2040  *  Outputs:
2041  *  -------
2042  *  wmGD (menuSpecs) = new menu panes, protocol atoms
2043  *
2044  *************************************<->***********************************/
2045
2046 void MakeWmFunctionResources (WmScreenData *pSD)
2047 {
2048     ButtonSpec *buttonSpec;
2049     KeySpec    *keySpec;
2050     MenuSpec   *menuSpec;
2051     Context     menuContext;
2052
2053
2054     /*
2055      * Scan through the menu specifications and make wm protocol atoms.
2056      */
2057
2058
2059     /*
2060      * Scan through the button binding specifications making menus if the
2061      * f.menu function is invoked.
2062      */
2063
2064     buttonSpec = pSD->buttonSpecs;
2065     while (buttonSpec)
2066     {
2067         if (buttonSpec->wmFunction == F_Menu)
2068         {
2069             if (buttonSpec->context & F_CONTEXT_WINDOW)
2070             {
2071                 menuContext = F_CONTEXT_WINDOW;
2072             }
2073             else if (buttonSpec->context & F_CONTEXT_ICON)
2074             {
2075                 menuContext = F_CONTEXT_ICON;
2076             }
2077             else
2078             {
2079                 menuContext = F_CONTEXT_ROOT;
2080             }
2081
2082             menuSpec = MAKE_MENU (pSD, NULL, buttonSpec->wmFuncArgs,
2083                                  menuContext,
2084                                  buttonSpec->context, 
2085                                  (MenuItem *) NULL, FALSE);
2086
2087             if (menuSpec)
2088             /* 
2089              * If successful, save in pSD->acceleratorMenuSpecs 
2090              * Note: these accelerators have nonzero contexts.
2091              */
2092             {
2093                 SaveMenuAccelerators (pSD, menuSpec);
2094             }
2095             else
2096             {
2097                 buttonSpec->wmFunction = F_Nop;
2098             }
2099         }
2100         buttonSpec = buttonSpec->nextButtonSpec;
2101     }
2102
2103
2104     /*
2105      * Scan through the key binding specifications making menus if the
2106      * f.menu function is invoked.
2107      */
2108
2109     keySpec = pSD->keySpecs;
2110     while (keySpec)
2111     {
2112         if (keySpec->wmFunction == F_Menu)
2113         {
2114             if (keySpec->context & F_CONTEXT_WINDOW)
2115             {
2116                 menuContext = F_CONTEXT_WINDOW;
2117             }
2118             else if (keySpec->context & F_CONTEXT_ICON)
2119             {
2120                 menuContext = F_CONTEXT_ICON;
2121             }
2122             else
2123             {
2124                 menuContext = F_CONTEXT_ROOT;
2125             }
2126
2127             menuSpec = MAKE_MENU (pSD, NULL, keySpec->wmFuncArgs, menuContext,
2128                                  keySpec->context, 
2129                                  (MenuItem *) NULL, FALSE);
2130
2131             if (menuSpec)
2132             /* 
2133              * If successful, save in pSD->acceleratorMenuSpecs 
2134              * Note: these accelerators have nonzero contexts.
2135              */
2136             {
2137                 SaveMenuAccelerators (pSD, menuSpec);
2138             }
2139             else
2140             {
2141                 keySpec->wmFunction = F_Nop;
2142             }
2143         }
2144         keySpec = keySpec->nextKeySpec;
2145     }
2146
2147
2148 } /* END OF FUNCTION MakeWmFunctionResources */
2149
2150
2151 \f
2152 /*************************************<->*************************************
2153  *
2154  *  MakeXorGC (pSD)
2155  *
2156  *
2157  *  Description:
2158  *  -----------
2159  *  Make an XOR graphic context for resizing and moving
2160  *
2161  *
2162  *  Inputs:
2163  *  ------
2164  *  pSD = pointer to screen data
2165  * 
2166  *  Outputs:
2167  *  -------
2168  *  Modifies global data
2169  *
2170  *  Comments:
2171  *  --------
2172  *  
2173  * 
2174  *************************************<->***********************************/
2175
2176 void MakeXorGC (WmScreenData *pSD)
2177 {
2178     XGCValues gcv;
2179     XtGCMask  mask;
2180
2181     mask = GCFunction | GCLineWidth | GCSubwindowMode | GCCapStyle;
2182     gcv.function = GXinvert;
2183     gcv.line_width = 0;
2184     gcv.cap_style = CapNotLast;
2185     gcv.subwindow_mode = IncludeInferiors;
2186
2187     /* Fix so that the rubberbanding for resize and move will
2188      *  have more contrasting colors.
2189      */
2190
2191     gcv.plane_mask = BlackPixelOfScreen( DefaultScreenOfDisplay( DISPLAY )) ^ 
2192                      WhitePixelOfScreen( DefaultScreenOfDisplay( DISPLAY ));
2193     mask = mask | GCPlaneMask;
2194
2195     pSD->xorGC = XCreateGC (DISPLAY, pSD->rootWindow, mask, &gcv);
2196
2197
2198 } /* END OF FUNCTION MakeXorGC */
2199
2200
2201 \f
2202 /*************************************<->*************************************
2203  *
2204  *  CopyArgv (argc, argv)
2205  *
2206  *
2207  *  Description:
2208  *  -----------
2209  *  This function makes a copy of the window manager's argv for use by
2210  *  the f.restart function.  A copy must be kept because XtInitialize
2211  *  changes argv.
2212  *
2213  *
2214  *  Inputs:
2215  *  ------
2216  *  argc = the number of strings in argv
2217  *
2218  *  argv = window manager parameters
2219  *
2220  * 
2221  *  Outputs:
2222  *  -------
2223  *  Return = a copy of argv
2224  *
2225  *************************************<->***********************************/
2226
2227
2228 void CopyArgv (int argc, char *argv [])
2229 {
2230     int i;
2231
2232
2233     if ((wmGD.argv = (char **)XtMalloc ((argc + 1) * sizeof (char *))) == NULL)
2234     {
2235         Warning (((char *)GETMESSAGE(40, 10, "Insufficient memory for window manager data")));
2236         wmGD.argv = argv;
2237 #ifdef WSM
2238         dpy2Argv = argv;
2239 #endif /* WSM */
2240     }
2241     else
2242     {
2243         for (i = 0; i < argc; i++)
2244         {
2245             wmGD.argv[i] = argv[i];
2246         }
2247         wmGD.argv[i] = NULL;
2248 #ifdef WSM
2249         if ((dpy2Argv = (char **)XtMalloc((argc + 1) * sizeof(char *))) == NULL)
2250         {
2251             Warning (((char *)GETMESSAGE(40, 11, "Insufficient memory for window manager data")));
2252             dpy2Argv = argv;
2253         }
2254         else
2255         {
2256             for (i = 0; i < argc; i++)
2257             {
2258                 dpy2Argv[i] = argv[i];
2259             }
2260             dpy2Argc = argc;
2261             dpy2Argv[i] = NULL;
2262         }
2263 #endif /* WSM */
2264     }
2265     
2266 } /* END OF FUNCTION CopyArgv */
2267
2268 \f
2269 /*************************************<->*************************************
2270  *
2271  *  InitScreenNames ()
2272  *
2273  *
2274  *  Description:
2275  *  -----------
2276  *  Initializes the name space for screen names
2277  *
2278  *  Outputs:
2279  *  -------
2280  *  Modifies global data
2281  *    + screenNames
2282  *
2283  *  Comments:
2284  *  --------
2285  *  Initializes screenNames to contain a numeric name for each screen
2286  *
2287  *************************************<->***********************************/
2288
2289 void InitScreenNames (void)
2290 {
2291     int num, numScreens;
2292     
2293     numScreens = ScreenCount (wmGD.display);
2294     
2295     if (!(wmGD.screenNames = 
2296           (unsigned char **) XtMalloc (numScreens * sizeof(char *))))
2297     {
2298         ShowWaitState (FALSE);
2299         Warning (((char *)GETMESSAGE(40, 12, "Insufficient memory for screen names")));
2300         ExitWM (WM_ERROR_EXIT_VALUE);
2301     }
2302     
2303     for (num=0; num<numScreens; num++)
2304     {
2305         if (!(wmGD.screenNames[num] = 
2306               (unsigned char *) XtMalloc (4*sizeof(char))))
2307         {
2308             ShowWaitState (FALSE);
2309             Warning (((char *)GETMESSAGE(40, 13, "Insufficient memory for screen names")));
2310             ExitWM (WM_ERROR_EXIT_VALUE);
2311         }
2312         /* default name is left justified, 3-chars max, zero terminated */
2313 #ifdef WSM
2314         sprintf((char *)wmGD.screenNames[num], UNSPECIFIED_SCREEN_NAME);
2315 #else  /* WSM */
2316         sprintf((char *)wmGD.screenNames[num],"%d",num%1000);
2317 #endif /* WSM */
2318     }
2319 }
2320 #ifndef NO_MESSAGE_CATALOG
2321
2322
2323 void InitNlsStrings (void)
2324 {
2325     char * tmpString;
2326
2327 #ifdef WSM
2328     /*
2329      * Initialize messages
2330      */
2331     wmGD.okLabel=XmStringCreateLocalized(_DtOkString);
2332     wmGD.cancelLabel=XmStringCreateLocalized(_DtCancelString);
2333     wmGD.helpLabel=XmStringCreateLocalized(_DtHelpString);
2334 #endif /* WSM */    
2335
2336     /*
2337      * catgets returns a pointer to an area that is over written
2338      * on each call to catgets.
2339      */
2340
2341     tmpString = ((char *)GETMESSAGE(40, 14, "Icons"));
2342     if ((wmNLS.default_icon_box_title =
2343          (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2344     {
2345         Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2346         wmNLS.default_icon_box_title = "Icons";
2347     }
2348     else
2349     {
2350         strcpy(wmNLS.default_icon_box_title, tmpString);
2351     }
2352
2353 #ifdef WSM
2354     tmpString = ((char *)GETMESSAGE(40, 20, "%s: %s on line %d of configuration file %s\n"));
2355     if ((pWarningStringFile =
2356          (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2357     {
2358         Warning (((char *)GETMESSAGE(40, 17, "Insufficient memory for local message string")));
2359         pWarningStringFile = "%s: %s on line %d of configuration file %s\n";
2360     }
2361     else
2362     {
2363         strcpy(pWarningStringFile, tmpString);
2364     }
2365
2366     tmpString = ((char *)GETMESSAGE(40, 21, "%s: %s on line %d of specification string\n"));
2367     if ((pWarningStringLine =
2368          (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2369     {
2370         Warning (((char *)GETMESSAGE(40, 19, "Insufficient memory for local message string")));
2371         pWarningStringLine = "%s: %s on line %d of specification string\n";
2372     }
2373     else
2374     {
2375         strcpy(pWarningStringLine, tmpString);
2376     }
2377
2378
2379     tmpString = ((char *)GETMESSAGE(40, 22, "About Workspace Manager"));
2380     if ((wmNLS.defaultVersionTitle =
2381          (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2382     {
2383         Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2384         wmNLS.defaultVersionTitle = "About Workspace Manager";
2385     }
2386     else
2387     {
2388         strcpy(wmNLS.defaultVersionTitle, tmpString);
2389     }
2390
2391     tmpString = ((char *)GETMESSAGE(40, 23, "Workspace Manager - Help"));
2392     if ((wmNLS.defaultDtwmHelpTitle =
2393          (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2394     {
2395         Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2396         wmNLS.defaultDtwmHelpTitle = "Workspace Manager - Help";
2397     }
2398     else
2399     {
2400         strcpy(wmNLS.defaultDtwmHelpTitle, tmpString);
2401     }
2402
2403     tmpString = ((char *)GETMESSAGE(40, 24, "Workspace Manager - Help"));
2404     if ((wmNLS.defaultHelpTitle =
2405          (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
2406     {
2407         Warning (((char *)GETMESSAGE(40, 15, "Insufficient memory for local message string")));
2408         wmNLS.defaultHelpTitle = "Workspace Manager - Help";
2409     }
2410     else
2411     {
2412         strcpy(wmNLS.defaultHelpTitle, tmpString);
2413     }
2414 #endif /* WSM */
2415
2416 } /* InitNlsStrings  */
2417 #endif
2418
2419
2420 \f
2421 /******************************<->*************************************
2422  *
2423  *  InitWmDisplayEnv
2424  *
2425  *
2426  *  Description:
2427  *  -----------
2428  *  This function saves the display string for putenv in F_Exec.
2429  *
2430  *  Inputs:
2431  *  -------
2432  *
2433  *  Outputs:
2434  *  -------
2435  *************************************<->***********************************/
2436
2437 void
2438 InitWmDisplayEnv (void)
2439 {
2440     char *pDisplayName;
2441     char buffer[256];
2442     char displayName[256];
2443
2444     pDisplayName = DisplayString (DISPLAY);
2445     
2446     /*
2447      * Construct displayString for this string.  
2448      */
2449     strcpy(displayName, pDisplayName);
2450     sprintf(buffer, "DISPLAY=%s",displayName);
2451     
2452     /*          
2453      * Allocate space for the display string
2454      */
2455     if ((wmGD.displayString =
2456          (String)XtMalloc ((unsigned int) (strlen(buffer) + 1))) == NULL)
2457     {
2458         wmGD.displayString = NULL;
2459         Warning (((char *)GETMESSAGE(40, 9, 
2460                                      "Insufficient memory for displayString")));
2461     }
2462     else
2463     {
2464         strcpy(wmGD.displayString, buffer);
2465 #ifdef WSM
2466         putenv(wmGD.displayString);
2467 #endif /* WSM */
2468     }
2469     
2470 } /* END OF FUNCTION  InitWmDisplayEnv */
2471
2472 #ifndef NO_HP_KEY_REMAP
2473 static str_xref
2474 GetReplacementList(
2475         Display *dsp,
2476         str_xref std_xref,
2477         int count)
2478 {
2479   int min_kc ;
2480   int max_kc ;
2481   int ks_per_kc ;
2482   int kc_count ;
2483   KeySym *key_map ; 
2484   unsigned i ;
2485   str_xref xref_rtn = NULL ;
2486   unsigned num_xref = 0 ;
2487
2488   XDisplayKeycodes( dsp, &min_kc, &max_kc) ;
2489   kc_count = max_kc + 1 - min_kc ;
2490   key_map = XGetKeyboardMapping( dsp, min_kc, kc_count, &ks_per_kc) ;
2491   if(    key_map == NULL    )
2492     {
2493       return NULL ;
2494     }
2495   kc_count *= ks_per_kc ;
2496
2497   i = 0 ;
2498   while(    i < count    )
2499     {
2500       KeySym ks = XStringToKeysym( std_xref[i].default_name) ;
2501       unsigned j = 0 ;
2502
2503       while(    j < kc_count    )
2504         {
2505           if(    key_map[j] == ks    )
2506             {
2507               /* Found keysym used in virtkey table in keymap,
2508                *   so break ->  j != kc_count
2509                */
2510               break ;
2511             }
2512           ++j ;
2513         }
2514       if(    j == kc_count    )
2515         {
2516           /* Didn't find keysym of virtkey table, so add record to
2517            *   returned list which will later cause replacement in
2518            *   virtkeys table.
2519            */
2520           xref_rtn = (str_xref) XtRealloc( (char *) xref_rtn,
2521                                       sizeof( str_xref_rec) * (num_xref + 2)) ;
2522           xref_rtn[num_xref++] = std_xref[i] ;
2523           xref_rtn[num_xref].default_name = NULL ;
2524         }
2525       ++i ;
2526     }
2527   XFree( (char *) key_map) ;
2528   return xref_rtn ;
2529 }
2530
2531 static Boolean
2532 GetBindingsProperty(
2533         Display *dsp,
2534         Atom property,
2535         String *binding)
2536 {
2537   Atom actual_type ;
2538   int actual_format ;
2539   unsigned long num_items ;
2540   unsigned long bytes_after ;
2541   unsigned char *prop = NULL ;
2542
2543   XGetWindowProperty( dsp, RootWindow( dsp, 0), property, 0, 1000000L,
2544       FALSE, XA_STRING, &actual_type, &actual_format, &num_items, &bytes_after,
2545                                                                        &prop) ;
2546   if(    (actual_type != XA_STRING)
2547       || (actual_format != 8)
2548       || (num_items == 0)    )
2549     {
2550       if(    prop != NULL    )
2551         {
2552           XFree( prop) ;
2553         }
2554       return FALSE ;
2555     }
2556   *binding = (String) prop ;
2557   return TRUE ;
2558 }
2559
2560 static void
2561 SetBindingsProperty(
2562         Display *dsp,
2563         Atom property,
2564         String binding)
2565 {
2566   XChangeProperty( dsp, RootWindow( dsp, 0), property, XA_STRING, 8,
2567                 PropModeReplace, (unsigned char *) binding, strlen( binding)) ;
2568 }
2569
2570 static String
2571 FixupBindingsString(
2572         String bindingsString,
2573         str_xref repl_xref)
2574 {
2575   String fixed_str = XtNewString( bindingsString) ;
2576   String ptr_next = fixed_str ;
2577
2578   while(    repl_xref->default_name != NULL    )
2579     {
2580       String ks_ptr = strstr( ptr_next, repl_xref->default_name) ;
2581       unsigned orig_len = strlen( repl_xref->default_name) ;
2582
2583       if(    ks_ptr == NULL    )
2584         {
2585           /* Only increment to next replacement when no other instances
2586            *   are found in fixed_str.
2587            */
2588           ++repl_xref ;
2589           ptr_next = fixed_str ;
2590           continue ;
2591         }
2592
2593       if(    (strpbrk( (ks_ptr - 1), " \t>") == (ks_ptr - 1))
2594           && (strpbrk( ks_ptr, " \t\n") == (ks_ptr + orig_len))    )
2595         {
2596           unsigned new_len = strlen( repl_xref->new_name) ;
2597           unsigned suffix_len = strlen( ks_ptr + orig_len) ;
2598
2599           if(    new_len > orig_len    )
2600             {
2601               unsigned new_ttl_len = strlen( fixed_str) + new_len - orig_len ;
2602               unsigned prefix_len ;
2603
2604               *ks_ptr = '\0' ;
2605               prefix_len = strlen( fixed_str) ;
2606               fixed_str = XtRealloc( fixed_str, (new_ttl_len + 1)) ;
2607               ks_ptr = fixed_str + prefix_len ;
2608             }
2609           memmove( (ks_ptr + new_len), (ks_ptr + orig_len), (suffix_len + 1)) ;
2610           memcpy( ks_ptr, repl_xref->new_name, new_len) ;
2611
2612           ptr_next = ks_ptr + new_len ;
2613         }
2614       else
2615         {
2616           ptr_next = ks_ptr + 1 ;
2617         }
2618     }
2619   return fixed_str ;
2620 }
2621
2622
2623 Boolean
2624 VirtKeys4DIN(
2625         Display *dsp)
2626 {
2627   /* This routine examines the X server's key map table to determine
2628    * if certain HP-specific keysyms are missing.  If they are, then
2629    * the Motif virtual binding table properties are updated to utilize
2630    * generic X keysyms instead of the missing HP vendor keysyms.
2631    * In particular, this fixes the Motif virtual key binding table for
2632    * correct operation on HP systems using the AT2/DIN style keyboard.
2633    */
2634   static char *prop_names[] = { "_MOTIF_BINDINGS",
2635                                 "_MOTIF_DEFAULT_BINDINGS" } ;
2636   static str_xref_rec std_xref[] = { { "hpInsertChar", "Insert" },
2637                                      { "hpDeleteChar", "Delete" },
2638                                      { "End", "F7" },
2639                                    } ;
2640   Boolean PropChanged4DIN = FALSE ;
2641   unsigned i ;
2642   char *bindingsString ;
2643   unsigned prop_existed ;
2644   Atom *prop_atoms ;
2645   str_xref vkeysym_xref ;
2646   unsigned num_props = XtNumber( prop_names) ;
2647
2648   vkeysym_xref = GetReplacementList( dsp, std_xref, XtNumber(std_xref)) ;
2649   if(    vkeysym_xref == NULL    )
2650     {
2651       return PropChanged4DIN ;
2652     }
2653
2654   prop_atoms = (Atom *) XtMalloc( sizeof( Atom) * num_props) ;
2655   XInternAtoms(dsp, prop_names, num_props, FALSE, prop_atoms);
2656
2657   prop_existed = FALSE ;
2658   i = 0 ;
2659   while(    i < num_props    )
2660     {
2661       if(    GetBindingsProperty( dsp, prop_atoms[i], &bindingsString)    )
2662         {
2663           String new_bstring = FixupBindingsString( bindingsString,
2664                                                                 vkeysym_xref) ;
2665           prop_existed = TRUE ;
2666           XFree( bindingsString) ;
2667
2668           if(    new_bstring != NULL    )
2669             {
2670               SetBindingsProperty( dsp, prop_atoms[i], new_bstring) ;
2671               XtFree( new_bstring) ;
2672             }
2673         }
2674       ++i ;
2675     }
2676   if(    !prop_existed    )
2677     {
2678       bindingsString = NULL ;
2679       _XmVirtKeysLoadFallbackBindings( dsp, &bindingsString) ;
2680       XtFree( bindingsString) ;
2681
2682       i = 0 ;
2683       while(    i < num_props    )
2684         {
2685           if(    GetBindingsProperty( dsp, prop_atoms[i], &bindingsString)    )
2686             {
2687               String new_bstring = FixupBindingsString( bindingsString,
2688                                                                 vkeysym_xref) ;
2689               XtFree( bindingsString) ;
2690               if(    new_bstring != NULL    )
2691                 {
2692                   PropChanged4DIN = TRUE ;
2693                   SetBindingsProperty( dsp, prop_atoms[i], new_bstring) ;
2694                   XtFree( new_bstring) ;
2695                 }
2696               XFree( bindingsString) ;
2697             }
2698           ++i ;
2699         }
2700     }
2701
2702   XtFree( (char *) vkeysym_xref) ;
2703   XtFree( (char *) prop_atoms) ;
2704   return PropChanged4DIN ;
2705 }
2706 #endif /* NO_HP_KEY_REMAP */
2707
2708 #ifdef WSM
2709 /****************************   eof    ***************************/
2710 #endif /* WSM */