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