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