chiark / gitweb /
debian/changelog: start -4~
[vtwm.git] / add_window.c
1 /*****************************************************************************/
2 /**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
3 /**                          Salt Lake City, Utah                           **/
4 /**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **/
5 /**                        Cambridge, Massachusetts                         **/
6 /**                                                                         **/
7 /**                           All Rights Reserved                           **/
8 /**                                                                         **/
9 /**    Permission to use, copy, modify, and distribute this software and    **/
10 /**    its documentation  for  any  purpose  and  without  fee is hereby    **/
11 /**    granted, provided that the above copyright notice appear  in  all    **/
12 /**    copies and that both  that  copyright  notice  and  this  permis-    **/
13 /**    sion  notice appear in supporting  documentation,  and  that  the    **/
14 /**    names of Evans & Sutherland and M.I.T. not be used in advertising    **/
15 /**    in publicity pertaining to distribution of the  software  without    **/
16 /**    specific, written prior permission.                                  **/
17 /**                                                                         **/
18 /**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **/
19 /**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
20 /**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **/
21 /**    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
22 /**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
23 /**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
24 /**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
25 /**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
26 /*****************************************************************************/
27
28
29 /**********************************************************************
30  *
31  * $XConsortium: add_window.c,v 1.153 91/07/10 13:17:26 dave Exp $
32  *
33  * Add a new window, put the titlbar and other stuff around
34  * the window
35  *
36  * 31-Mar-88 Tom LaStrange        Initial Version.
37  *
38  **********************************************************************/
39
40 #include <stdio.h>
41 #include <string.h>
42 #include "twm.h"
43 #include <X11/Xatom.h>
44 #ifndef NO_XPM_SUPPORT
45 #include <X11/xpm.h>
46 #endif
47
48 #include "add_window.h"
49 #include "util.h"
50 #include "resize.h"
51 #include "parse.h"
52
53 /* djhjr - 4/19/96 */
54 #include "gram.h"
55
56 #include "list.h"
57 #include "events.h"
58 #include "menus.h"
59 #include "screen.h"
60 #include "iconmgr.h"
61 #include "desktop.h"
62
63 /* random placement coordinates */
64 #define PLACEMENT_START         50
65 #define PLACEMENT_INCR          30
66
67 /* 4/26/99 - djhjr */
68 extern int PlaceApplet();
69
70 #define gray_width 2
71 #define gray_height 2
72 static char gray_bits[] = {
73    0x02, 0x01};
74
75 /* djhjr - 4/19/96 */
76 static unsigned char black_bits[] = {
77    0xFF, 0xFF};
78
79 int AddingX;
80 int AddingY;
81 int AddingW;
82 int AddingH;
83
84 static void CreateWindowTitlebarButtons();
85 void SetHighlightPixmap();
86
87 /* djhjr - 4/14/98 */
88 static void AddMoveAndResize();
89
90 char NoName[] = "Untitled"; /* name if no name is specified */
91
92
93 /************************************************************************
94  *
95  *  Procedure:
96  *      GetGravityOffsets - map gravity to (x,y) offset signs for adding
97  *              to x and y when window is mapped to get proper placement.
98  *
99  ************************************************************************
100  */
101
102 void GetGravityOffsets (tmp, xp, yp)
103     TwmWindow *tmp;                     /* window from which to get gravity */
104     int *xp, *yp;                       /* return values */
105 {
106     static struct _gravity_offset {
107         int x, y;
108     } gravity_offsets[11] = {
109         {  0,  0 },                     /* ForgetGravity */
110         { -1, -1 },                     /* NorthWestGravity */
111         {  0, -1 },                     /* NorthGravity */
112         {  1, -1 },                     /* NorthEastGravity */
113         { -1,  0 },                     /* WestGravity */
114         {  0,  0 },                     /* CenterGravity */
115         {  1,  0 },                     /* EastGravity */
116         { -1,  1 },                     /* SouthWestGravity */
117         {  0,  1 },                     /* SouthGravity */
118         {  1,  1 },                     /* SouthEastGravity */
119         {  0,  0 },                     /* StaticGravity */
120     };
121     register int g = ((tmp->hints.flags & PWinGravity)
122                       ? tmp->hints.win_gravity : NorthWestGravity);
123
124     if (g < ForgetGravity || g > StaticGravity) {
125         *xp = *yp = 0;
126     } else {
127         *xp = gravity_offsets[g].x;
128         *yp = gravity_offsets[g].y;
129     }
130 }
131
132
133 /***********************************************************************
134  *
135  *  Procedure:
136  *      AddWindow - add a new window to the twm list
137  *
138  *  Returned Value:
139  *      (TwmWindow *) - pointer to the TwmWindow structure
140  *
141  *  Inputs:
142  *      w       - the window id of the window to add
143  *      iconm   - flag to tell if this is an icon manager window
144  *      iconp   - pointer to icon manager struct
145  *
146  ***********************************************************************
147  */
148
149 TwmWindow *
150 AddWindow(w, iconm, iconp)
151 Window w;
152 int iconm;
153 IconMgr *iconp;
154 {
155     TwmWindow *tmp_win;                 /* new twm window structure */
156     unsigned long valuemask;            /* mask for create windows */
157     XSetWindowAttributes attributes;    /* attributes for create windows */
158 #ifdef NO_I18N_SUPPORT
159     XTextProperty text_property;
160 #endif
161     Atom actual_type;
162     int actual_format;
163     unsigned long nitems, bytesafter;
164     int ask_user;               /* don't know where to put the window */
165     int *ppos_ptr, ppos_on;             /* djhjr - 9/24/02 */
166     int gravx, gravy;                   /* gravity signs for positioning */
167     int namelen;
168     int bw2;
169     char *icon_name; /* djhjr - 2/20/99 */
170 #ifndef NO_I18N_SUPPORT
171     char *name;
172 #endif
173     /* next two submitted by Jonathan Paisley - 11/8/02 */
174     Atom motifhints = XInternAtom( dpy, "_MOTIF_WM_HINTS", 0);
175     MotifWmHints *mwmhints;
176
177 #ifdef DEBUG
178     fprintf(stderr, "AddWindow: w = 0x%x\n", w);
179 #endif
180
181     /* allocate space for the twm window */
182     tmp_win = (TwmWindow *)calloc(1, sizeof(TwmWindow));
183     if (tmp_win == 0)
184     {
185         fprintf (stderr, "%s: Unable to allocate memory to manage window ID %lx.\n",
186                  ProgramName, w);
187         return NULL;
188     }
189     tmp_win->w = w;
190     tmp_win->zoomed = ZOOM_NONE;
191     tmp_win->iconmgr = iconm;
192     tmp_win->iconmgrp = iconp;
193     tmp_win->cmaps.number_cwins = 0;
194
195     XSelectInput(dpy, tmp_win->w, PropertyChangeMask);
196     XGetWindowAttributes(dpy, tmp_win->w, &tmp_win->attr);
197
198 /* djhjr - 9/14/03 */
199 #ifndef NO_I18N_SUPPORT
200         if (I18N_FetchName(dpy, tmp_win->w, &name))
201         {
202                 tmp_win->name = strdup(name);
203                 free(name);
204         }
205 #else
206         /*
207          * Ask the window manager for a name with "newer" R4 function -
208          * it was 'XFetchName()', which apparently failed more often.
209          * Submitted by Nicholas Jacobs
210          */
211         if (XGetWMName(dpy, tmp_win->w, &text_property) != 0)
212         {
213                 tmp_win->name = (char *)strdup(text_property.value);
214                 XFree(text_property.value);
215         }
216 #endif
217         else
218                 tmp_win->name = NoName;
219
220     tmp_win->class = NoClass;
221     XGetClassHint(dpy, tmp_win->w, &tmp_win->class);
222     FetchWmProtocols (tmp_win);
223     FetchWmColormapWindows (tmp_win);
224
225     /*
226      * do initial clip; should look at window gravity
227      */
228     if (tmp_win->attr.width > Scr->MaxWindowWidth)
229       tmp_win->attr.width = Scr->MaxWindowWidth;
230     if (tmp_win->attr.height > Scr->MaxWindowHeight)
231       tmp_win->attr.height = Scr->MaxWindowHeight;
232
233     tmp_win->wmhints = XGetWMHints(dpy, tmp_win->w);
234     if (tmp_win->wmhints && (tmp_win->wmhints->flags & WindowGroupHint))
235       tmp_win->group = tmp_win->wmhints->window_group;
236     else
237         tmp_win->group = tmp_win->w/* NULL */;
238
239     /* submitted by Jonathan Paisley - 11/8/02 */
240     tmp_win->mwmhints.flags = 0;
241     if (motifhints != None)
242     {
243         if (XGetWindowProperty(dpy, tmp_win->w, motifhints,
244                                0L, sizeof(MotifWmHints), False,
245                                motifhints, &actual_type, &actual_format,
246                                &nitems, &bytesafter,
247                                (unsigned char**)&mwmhints) == Success && actual_type != None)
248         {
249             if (mwmhints)
250             {
251                 tmp_win->mwmhints = *mwmhints;
252                 XFree(mwmhints);
253             }
254         }
255     }
256
257     /*
258      * The July 27, 1988 draft of the ICCCM ignores the size and position
259      * fields in the WM_NORMAL_HINTS property.
260      */
261
262     tmp_win->transient = Transient(tmp_win->w, &tmp_win->transientfor);
263
264     if (tmp_win->class.res_name == NULL)
265         tmp_win->class.res_name = NoName;
266     if (tmp_win->class.res_class == NULL)
267         tmp_win->class.res_class = NoName;
268
269     tmp_win->full_name = tmp_win->name;
270     namelen = strlen (tmp_win->name);
271
272         tmp_win->highlight = Scr->Highlight &&
273 /* djhjr - 4/22/98
274                 (!(short)(int) LookInList(Scr->NoHighlight, tmp_win->full_name,
275                         &tmp_win->class));
276 */
277                 (LookInList(Scr->NoHighlight, tmp_win->full_name,
278                         &tmp_win->class) == (char *)NULL);
279
280         tmp_win->stackmode = Scr->StackMode &&
281 /* djhjr - 4/22/98
282                 (!(short)(int) LookInList(Scr->NoStackModeL, tmp_win->full_name,
283                         &tmp_win->class));
284 */
285                 (LookInList(Scr->NoStackModeL, tmp_win->full_name,
286                         &tmp_win->class) == (char *)NULL);
287
288         tmp_win->titlehighlight = Scr->TitleHighlight &&
289 /* djhjr - 4/22/98
290                 (!(short)(int) LookInList(Scr->NoTitleHighlight, tmp_win->full_name,
291                         &tmp_win->class));
292 */
293                 (LookInList(Scr->NoTitleHighlight, tmp_win->full_name,
294                         &tmp_win->class) == (char *)NULL);
295
296         tmp_win->auto_raise = Scr->AutoRaiseDefault ||    /* RAISEDELAY */
297 /* djhjr - 4/22/98
298                 (short)(int) LookInList(Scr->AutoRaise, tmp_win->full_name,
299                         &tmp_win->class);
300 */
301                 (LookInList(Scr->AutoRaise, tmp_win->full_name,
302                         &tmp_win->class) != (char *)NULL);
303     if (tmp_win->auto_raise) Scr->NumAutoRaises++;
304
305         tmp_win->iconify_by_unmapping = Scr->IconifyByUnmapping;
306         if (Scr->IconifyByUnmapping)
307         {
308 /* djhjr - 9/21/99
309         tmp_win->iconify_by_unmapping = iconm ? FALSE :
310 */
311         tmp_win->iconify_by_unmapping =
312 /* djhjr - 4/22/98
313                 !(short)(int) LookInList(Scr->DontIconify, tmp_win->full_name,
314                         &tmp_win->class);
315 */
316                 (LookInList(Scr->DontIconify, tmp_win->full_name,
317                         &tmp_win->class) == (char *)NULL);
318         }
319         tmp_win->iconify_by_unmapping |=
320 /* djhjr - 4/22/98
321                 (short)(int) LookInList(Scr->IconifyByUn, tmp_win->full_name,
322                         &tmp_win->class);
323 */
324                 (LookInList(Scr->IconifyByUn, tmp_win->full_name,
325                         &tmp_win->class) != (char *)NULL);
326
327     /* Scr->NoWindowRingL submitted by Jonathan Paisley - 10/27/02 */
328     if ((Scr->UseWindowRing ||
329                 LookInList(Scr->WindowRingL, tmp_win->full_name,
330                            &tmp_win->class)) &&
331                 LookInList(Scr->NoWindowRingL, tmp_win->full_name,
332                              &tmp_win->class) == (char *)NULL)
333     {
334         /* in menus.c now - djhjr - 10/27/02 */
335         AddWindowToRing(tmp_win);
336     }
337     else
338       tmp_win->ring.next = tmp_win->ring.prev = NULL;
339 #ifdef ORIGINAL_WARPRINGCOORDINATES /* djhjr - 5/11/98 */
340     tmp_win->ring.cursor_valid = False;
341 #endif
342
343     if (LookInList(Scr->NailedDown, tmp_win->full_name, &tmp_win->class))
344             tmp_win->nailed = TRUE;
345     else
346             tmp_win->nailed = FALSE;
347
348     if (LookInList(Scr->DontShowInDisplay, tmp_win->full_name, &tmp_win->class))
349             tmp_win->showindesktopdisplay = FALSE;
350     else
351             tmp_win->showindesktopdisplay = TRUE;
352
353     tmp_win->squeeze_info = NULL;
354     /*
355      * get the squeeze information; note that this does not have to be freed
356      * since it is coming from the screen list
357      */
358     if (HasShape) {
359         if (!LookInList (Scr->DontSqueezeTitleL, tmp_win->full_name,
360                          &tmp_win->class)) {
361             tmp_win->squeeze_info = (SqueezeInfo *)
362               LookInList (Scr->SqueezeTitleL, tmp_win->full_name,
363                           &tmp_win->class);
364             if (!tmp_win->squeeze_info) {
365                 static SqueezeInfo default_squeeze = { J_LEFT, 0, 0 };
366                 if (Scr->SqueezeTitle)
367                   tmp_win->squeeze_info = &default_squeeze;
368             }
369         }
370       }
371
372     tmp_win->old_bw = tmp_win->attr.border_width;
373
374 #ifdef NEVER /* see the next '#ifdef NEVER's '#else' - C. F. Jalali */
375         /* djhjr - 4/19/96 */
376         /* was 'Scr->ThreeDBorderWidth' - djhjr - 8/11/98 */
377     tmp_win->frame_bw3D = Scr->BorderWidth;
378 #endif
379     /* added 'Scr->NoBorders' test - djhjr - 8/23/02 */
380     if (Scr->NoBorders || LookInList(Scr->NoBorder, tmp_win->full_name, &tmp_win->class))
381     {
382                 tmp_win->frame_bw = 0;
383                 tmp_win->frame_bw3D = 0;
384     }
385     else
386 #ifdef NEVER
387     if (tmp_win->frame_bw3D != 0)
388         {
389                 tmp_win->frame_bw = 0;
390                 Scr->ClientBorderWidth = FALSE;
391         }
392     else
393             if (Scr->ClientBorderWidth)
394                 tmp_win->frame_bw = tmp_win->old_bw;
395             else
396                 tmp_win->frame_bw = Scr->BorderWidth;
397 #else
398         /*
399          * Submitted by Caveh Frank Jalali - 8/25/98
400          */
401         {
402                 if (Scr->BorderBevelWidth > 0)
403                 {
404                         tmp_win->frame_bw3D = Scr->BorderWidth;
405                         tmp_win->frame_bw = 0;
406                         Scr->ClientBorderWidth = FALSE;
407                 }
408                 else
409                 {
410                         tmp_win->frame_bw3D = 0;
411                         if (Scr->ClientBorderWidth)
412                                 tmp_win->frame_bw = tmp_win->old_bw;
413                         else
414                                 tmp_win->frame_bw = Scr->BorderWidth;
415                 }
416         }
417 #endif
418
419     /* submitted by Jonathan Paisley - 11/8/02 */
420     if (tmp_win->mwmhints.flags & MWM_HINTS_DECORATIONS)
421     {
422         if (tmp_win->mwmhints.decorations & MWM_DECOR_ALL)
423             tmp_win->mwmhints.decorations |= (MWM_DECOR_BORDER |
424                         MWM_DECOR_RESIZEH | MWM_DECOR_TITLE |
425                         MWM_DECOR_MENU | MWM_DECOR_MINIMIZE |
426                         MWM_DECOR_MAXIMIZE);
427
428         if (!(tmp_win->mwmhints.decorations & MWM_DECOR_BORDER))
429             tmp_win->frame_bw = tmp_win->frame_bw3D = 0;
430     }
431     if (tmp_win->mwmhints.flags & MWM_HINTS_FUNCTIONS)
432         if (tmp_win->mwmhints.functions & MWM_FUNC_ALL)
433             tmp_win->mwmhints.functions |= (MWM_FUNC_RESIZE |
434                         MWM_FUNC_MOVE | MWM_FUNC_MINIMIZE |
435                         MWM_FUNC_MAXIMIZE | MWM_FUNC_CLOSE);
436
437     bw2 = tmp_win->frame_bw * 2;
438
439     /* moved MakeTitle under NoTitle - djhjr - 10/20/01 */
440     tmp_win->title_height = Scr->TitleHeight + tmp_win->frame_bw;
441
442     /* submitted by Jonathan Paisley 11/8/02 */
443     if (tmp_win->mwmhints.flags & MWM_HINTS_DECORATIONS &&
444                 !(tmp_win->mwmhints.decorations & MWM_DECOR_TITLE))
445         tmp_win->title_height = 0;
446
447     if (Scr->NoTitlebar)
448         tmp_win->title_height = 0;
449     if (LookInList(Scr->NoTitle, tmp_win->full_name, &tmp_win->class))
450         tmp_win->title_height = 0;
451     if (LookInList(Scr->MakeTitle, tmp_win->full_name, &tmp_win->class))
452         tmp_win->title_height = Scr->TitleHeight + tmp_win->frame_bw;
453
454         /* djhjr - 4/7/98 */
455         if (LookInList(Scr->OpaqueMoveL, tmp_win->full_name, &tmp_win->class))
456                 tmp_win->opaque_move = TRUE;
457         else
458             tmp_win->opaque_move = Scr->OpaqueMove &&
459 /* djhjr - 4/22/98
460                 !(short)(int)LookInList(Scr->NoOpaqueMoveL, tmp_win->full_name, &tmp_win->class);
461 */
462                 (LookInList(Scr->NoOpaqueMoveL, tmp_win->full_name,
463                         &tmp_win->class) == (char *)NULL);
464
465         /* djhjr - 9/21/99 */
466         if (tmp_win->opaque_move) tmp_win->attr.save_under = True;
467
468         /* djhjr - 4/7/98 */
469         if (LookInList(Scr->OpaqueResizeL, tmp_win->full_name, &tmp_win->class))
470                 tmp_win->opaque_resize = TRUE;
471         else
472             tmp_win->opaque_resize = Scr->OpaqueResize &&
473 /* djhjr - 4/22/98
474                 !(short)(int)LookInList(Scr->NoOpaqueResizeL, tmp_win->full_name, &tmp_win->class);
475 */
476                 (LookInList(Scr->NoOpaqueResizeL, tmp_win->full_name,
477                         &tmp_win->class) == (char *)NULL);
478
479         /* djhjr - 9/21/99 */
480         if (tmp_win->opaque_resize) tmp_win->attr.save_under = True;
481
482     /* if it is a transient window, don't put a title on it */
483     if (tmp_win->transient && !Scr->DecorateTransients)
484         tmp_win->title_height = 0;
485
486     if (LookInList(Scr->StartIconified, tmp_win->full_name, &tmp_win->class))
487     {
488         if (!tmp_win->wmhints)
489         {
490             tmp_win->wmhints = (XWMHints *)malloc(sizeof(XWMHints));
491             tmp_win->wmhints->flags = 0;
492         }
493         tmp_win->wmhints->initial_state = IconicState;
494         tmp_win->wmhints->flags |= StateHint;
495     }
496
497     GetWindowSizeHints (tmp_win);
498     GetGravityOffsets (tmp_win, &gravx, &gravy);
499
500     /*
501      * Don't bother user if:
502      *
503      *     o  the window is a transient, or
504      *
505      *     o  a USPosition was requested, or
506      *
507      *     o  a PPosition was requested and UsePPosition is ON or
508      *        NON_ZERO if the window is at other than (0,0)
509      */
510
511     /* djhjr - 9/24/02 */
512     if ((ppos_ptr = (int *)LookInList(Scr->UsePPositionL,
513                                       tmp_win->full_name, &tmp_win->class)))
514         ppos_on = *ppos_ptr;
515     else
516         ppos_on = Scr->UsePPosition;
517     if (ppos_on == PPOS_NON_ZERO &&
518                 (tmp_win->attr.x != 0 || tmp_win->attr.y != 0))
519         ppos_on = PPOS_ON;
520
521     ask_user = TRUE;
522     if (tmp_win->transient ||
523                 (tmp_win->hints.flags & USPosition) ||
524                 ((tmp_win->hints.flags & PPosition) && ppos_on == PPOS_ON))
525         ask_user = FALSE;
526
527     /* check for applet regions - djhjr - 4/26/99 */
528     if (PlaceApplet(tmp_win, tmp_win->attr.x, tmp_win->attr.y,
529                     &tmp_win->attr.x, &tmp_win->attr.y))
530         ask_user = FALSE;
531
532     if (LookInList(Scr->NailedDown, tmp_win->full_name, &tmp_win->class))
533             tmp_win->nailed = TRUE;
534     else
535             tmp_win->nailed = FALSE;
536
537     /*
538      * 25/09/90 - Nailed windows should always be on the real screen,
539      * regardless of PPosition or UPosition. If we are dealing with
540      * PPosition, then offset by the current real screen offset on the vd.
541      */
542     if (tmp_win->nailed ||
543         ((tmp_win->hints.flags & PPosition) && (ask_user == FALSE))) {
544             tmp_win->attr.x = R_TO_V_X(tmp_win->attr.x);
545             tmp_win->attr.y = R_TO_V_Y(tmp_win->attr.y);
546     }
547
548 /* moved to after window prep and creation - djhjr - 4/14/98
549         AddMoveAndResize(tmp_win, ask_user);
550 */
551
552     if (!Scr->ClientBorderWidth) {      /* need to adjust for twm borders */
553
554 /* djhjr - 4/19/96
555         int delta = tmp_win->attr.border_width - tmp_win->frame_bw;
556 */
557 /* submitted by Jonathan Paisley - 11/8/02
558         int delta = tmp_win->attr.border_width - tmp_win->frame_bw - tmp_win->frame_bw3D;
559 */
560         int delta = -(tmp_win->frame_bw + tmp_win->frame_bw3D);
561
562         tmp_win->attr.x += gravx * delta;
563         tmp_win->attr.y += gravy * delta;
564     }
565
566     /*
567      * For windows with specified non-northwest gravities.
568      * Submitted by Jonathan Paisley - 11/8/02
569      */
570     if (tmp_win->old_bw) {
571         if (!Scr->ClientBorderWidth) {
572             JunkX = gravx + 1;
573             JunkY = gravy + 1;
574         } else
575             JunkX = JunkY = 1;
576
577         tmp_win->attr.x += JunkX * tmp_win->old_bw;
578         tmp_win->attr.y += JunkY * tmp_win->old_bw;
579     }
580
581     tmp_win->title_width = tmp_win->attr.width;
582
583     if (tmp_win->old_bw) XSetWindowBorderWidth (dpy, tmp_win->w, 0);
584
585 /* djhjr - 9/14/03 */
586 #ifndef NO_I18N_SUPPORT
587     tmp_win->name_width = MyFont_TextWidth(&Scr->TitleBarFont,
588 #else
589     tmp_win->name_width = XTextWidth(Scr->TitleBarFont.font,
590 #endif
591                                      tmp_win->name, namelen);
592
593 /* djhjr - 9/14/03 */
594 #ifndef NO_I18N_SUPPORT
595         if (!I18N_GetIconName(dpy, tmp_win->w, &icon_name))
596 #else
597         /* used to be a simple boolean test for success - djhjr - 1/10/98 */
598         if (XGetWindowProperty (dpy, tmp_win->w, XA_WM_ICON_NAME, 0L, 200L, False,
599                         XA_STRING, &actual_type, &actual_format, &nitems, &bytesafter,
600
601 /* see that the icon name is it's own memory - djhjr - 2/20/99
602                         (unsigned char **)&tmp_win->icon_name) != Success || actual_type == None)
603                 tmp_win->icon_name = tmp_win->name;
604 */
605                         (unsigned char **)&icon_name) != Success || actual_type == None)
606 #endif
607                 tmp_win->icon_name = strdup(tmp_win->name);
608         else
609         {
610                 tmp_win->icon_name = strdup(icon_name);
611 /* djhjr - 9/14/03 */
612 #ifndef NO_I18N_SUPPORT
613                 free(icon_name);
614 #else
615                 XFree(icon_name);
616 #endif
617         }
618
619 /* redundant? - djhjr - 1/10/98
620     if (tmp_win->icon_name == NULL)
621         tmp_win->icon_name = tmp_win->name;
622 */
623
624     tmp_win->iconified = FALSE;
625     tmp_win->icon = FALSE;
626     tmp_win->icon_on = FALSE;
627
628     XGrabServer(dpy);
629
630     /*
631      * Make sure the client window still exists.  We don't want to leave an
632      * orphan frame window if it doesn't.  Since we now have the server
633      * grabbed, the window can't disappear later without having been
634      * reparented, so we'll get a DestroyNotify for it.  We won't have
635      * gotten one for anything up to here, however.
636      */
637     if (XGetGeometry(dpy, tmp_win->w, &JunkRoot, &JunkX, &JunkY,
638                      &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth) == 0)
639     {
640         free((char *)tmp_win);
641         XUngrabServer(dpy);
642         return(NULL);
643     }
644
645     /* add the window into the twm list */
646     tmp_win->next = Scr->TwmRoot.next;
647     if (Scr->TwmRoot.next != NULL)
648         Scr->TwmRoot.next->prev = tmp_win;
649     tmp_win->prev = &Scr->TwmRoot;
650     Scr->TwmRoot.next = tmp_win;
651
652     /* get all the colors for the window */
653
654 /* djhjr - 4/25/96
655     tmp_win->border = Scr->BorderColor;
656 */
657         tmp_win->border.back = Scr->BorderColor;
658
659     tmp_win->icon_border = Scr->IconBorderColor;
660     tmp_win->border_tile.fore = Scr->BorderTileC.fore;
661     tmp_win->border_tile.back = Scr->BorderTileC.back;
662     tmp_win->title.fore = Scr->TitleC.fore;
663     tmp_win->title.back = Scr->TitleC.back;
664     tmp_win->iconc.fore = Scr->IconC.fore;
665     tmp_win->iconc.back = Scr->IconC.back;
666     tmp_win->virtual.fore = Scr->VirtualDesktopDisplayC.fore;
667     tmp_win->virtual.back = Scr->VirtualDesktopDisplayC.back;
668
669 /* djhjr - 4/25/96
670     GetColorFromList(Scr->BorderColorL, tmp_win->full_name, &tmp_win->class,
671         &tmp_win->border);
672 */
673     GetColorFromList(Scr->BorderColorL, tmp_win->full_name, &tmp_win->class,
674         &tmp_win->border.back);
675
676     GetColorFromList(Scr->IconBorderColorL, tmp_win->full_name, &tmp_win->class,
677         &tmp_win->icon_border);
678     GetColorFromList(Scr->BorderTileForegroundL, tmp_win->full_name,
679         &tmp_win->class, &tmp_win->border_tile.fore);
680     GetColorFromList(Scr->BorderTileBackgroundL, tmp_win->full_name,
681         &tmp_win->class, &tmp_win->border_tile.back);
682     GetColorFromList(Scr->TitleForegroundL, tmp_win->full_name, &tmp_win->class,
683         &tmp_win->title.fore);
684     GetColorFromList(Scr->TitleBackgroundL, tmp_win->full_name, &tmp_win->class,
685         &tmp_win->title.back);
686     GetColorFromList(Scr->IconForegroundL, tmp_win->full_name, &tmp_win->class,
687         &tmp_win->iconc.fore);
688     GetColorFromList(Scr->IconBackgroundL, tmp_win->full_name, &tmp_win->class,
689         &tmp_win->iconc.back);
690
691 /* fixed transposed fallback fore and back color lists - djhjr - 9/25/01 */
692     if (!GetColorFromList(Scr->VirtualDesktopColorFL, tmp_win->full_name,
693                      &tmp_win->class, &tmp_win->virtual.fore))
694             GetColorFromList(Scr->TitleForegroundL, tmp_win->full_name,
695                              &tmp_win->class, &tmp_win->virtual.fore);
696     if (!GetColorFromList(Scr->VirtualDesktopColorBL, tmp_win->full_name,
697                      &tmp_win->class, &tmp_win->virtual.back))
698             GetColorFromList(Scr->TitleBackgroundL, tmp_win->full_name,
699                              &tmp_win->class, &tmp_win->virtual.back);
700
701         /* djhjr - 4/19/96 */
702         /* loosened up for titlebar-colored 3D buttons - djhjr - 4/1/98
703         if (Scr->use3Dtitles  && !Scr->BeNiceToColormap)
704         */
705         if (!Scr->BeNiceToColormap)
706                 GetShadeColors (&tmp_win->title);
707         /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
708         /* rearranged the parenthesis - djhjr - 10/30/02 */
709         if ((Scr->ButtonColorIsFrame || Scr->BorderBevelWidth > 0) && !Scr->BeNiceToColormap)
710         {
711                 GetShadeColors (&tmp_win->border);
712                 GetShadeColors (&tmp_win->border_tile);
713     }
714
715     /* create windows */
716
717 /* djhjr - 4/19/96
718     tmp_win->frame_x = tmp_win->attr.x + tmp_win->old_bw - tmp_win->frame_bw;
719     tmp_win->frame_y = tmp_win->attr.y - tmp_win->title_height +
720         tmp_win->old_bw - tmp_win->frame_bw;
721     tmp_win->frame_width = tmp_win->attr.width;
722     tmp_win->frame_height = tmp_win->attr.height + tmp_win->title_height;
723 */
724 /* done in AddMoveAndResize() - djhjr - 4/14/98
725     tmp_win->frame_x = tmp_win->attr.x + tmp_win->old_bw - tmp_win->frame_bw
726                         - tmp_win->frame_bw3D;
727     tmp_win->frame_y = tmp_win->attr.y - tmp_win->title_height +
728         tmp_win->old_bw - tmp_win->frame_bw - tmp_win->frame_bw3D;
729 */
730     tmp_win->frame_width = tmp_win->attr.width + 2 * tmp_win->frame_bw3D;
731     tmp_win->frame_height = tmp_win->attr.height + tmp_win->title_height +
732                                 2 * tmp_win->frame_bw3D;
733 /* done in AddMoveAndResize() - djhjr - 4/14/98
734     ConstrainSize (tmp_win, &tmp_win->frame_width, &tmp_win->frame_height);
735
736     tmp_win->virtual_frame_x = R_TO_V_X(tmp_win->frame_x);
737     tmp_win->virtual_frame_y = R_TO_V_Y(tmp_win->frame_y);
738 */
739
740 /* djhjr - 4/19/96
741     valuemask = CWBackPixmap | CWBorderPixel | CWCursor | CWEventMask;
742     attributes.background_pixmap = None;
743     attributes.border_pixel = tmp_win->border;
744     attributes.cursor = Scr->FrameCursor;
745     attributes.event_mask = (SubstructureRedirectMask |
746                              ButtonPressMask | ButtonReleaseMask |
747                              EnterWindowMask | LeaveWindowMask);
748     if (tmp_win->attr.save_under) {
749         attributes.save_under = True;
750         valuemask |= CWSaveUnder;
751     }
752 */
753 /* djhjr - 9/14/96
754     valuemask = CWBackPixmap | CWBorderPixel | CWCursor | CWEventMask | CWBackPixel;
755     attributes.background_pixmap = None;
756 */
757     valuemask = CWBorderPixel | CWCursor | CWEventMask | CWBackPixel;
758
759     attributes.background_pixel  = tmp_win->border.back;
760     attributes.border_pixel = tmp_win->border.back;
761     attributes.cursor = Scr->FrameCursor;
762     attributes.event_mask = (SubstructureRedirectMask | 
763                              ButtonPressMask | ButtonReleaseMask |
764                              EnterWindowMask | LeaveWindowMask | ExposureMask);
765     if (tmp_win->attr.save_under) {
766         attributes.save_under = True;
767         valuemask |= CWSaveUnder;
768     }
769
770         /* djhjr - 9/17/96 - slows down iconify/delete/destroy too much...
771         if (Scr->BackingStore)
772         {
773                 attributes.backing_store = WhenMapped;
774                 valuemask |= CWBackingStore;
775         }
776         */
777
778     if (tmp_win->hints.flags & PWinGravity) {
779         attributes.win_gravity = tmp_win->hints.win_gravity;
780         valuemask |= CWWinGravity;
781     }
782
783     tmp_win->frame = XCreateWindow (dpy, Scr->Root, tmp_win->frame_x,
784                                     tmp_win->frame_y,
785                                     (unsigned int) tmp_win->frame_width,
786                                     (unsigned int) tmp_win->frame_height,
787                                     (unsigned int) tmp_win->frame_bw,
788                                     Scr->d_depth,
789                                     (unsigned int) CopyFromParent,
790                                     Scr->d_visual, valuemask, &attributes);
791
792     if (tmp_win->title_height)
793     {
794         valuemask = (CWEventMask | CWBorderPixel | CWBackPixel);
795         attributes.event_mask = (KeyPressMask | ButtonPressMask |
796                                  ButtonReleaseMask | ExposureMask);
797 /* djhjr - 4/19/96
798         attributes.border_pixel = tmp_win->border;
799 */
800         attributes.border_pixel = tmp_win->title.back;
801         attributes.background_pixel = tmp_win->title.back;
802
803         /* djhjr - 9/17/96 */
804         if (Scr->BackingStore)
805         {
806                 attributes.backing_store = WhenMapped;
807                 valuemask |= CWBackingStore;
808         }
809
810         tmp_win->title_w = XCreateWindow (dpy, tmp_win->frame,
811 /* djhjr - 4/19/96
812                                           -tmp_win->frame_bw,
813                                           -tmp_win->frame_bw,
814 */
815                                           tmp_win->frame_bw3D - tmp_win->frame_bw,
816                                           tmp_win->frame_bw3D - tmp_win->frame_bw,
817
818                                           (unsigned int) tmp_win->attr.width,
819                                           (unsigned int) Scr->TitleHeight,
820                                           (unsigned int) tmp_win->frame_bw,
821                                           Scr->d_depth,
822                                           (unsigned int) CopyFromParent,
823                                           Scr->d_visual, valuemask,
824                                           &attributes);
825     }
826     else {
827         tmp_win->title_w = 0;
828         tmp_win->squeeze_info = NULL;
829     }
830
831     if (tmp_win->highlight)
832     {
833
834         /* djhjr - 4/19/96 */
835         /* was 'Scr->use3Dtitles' - djhjr - 8/11/98 */
836         if (Scr->TitleBevelWidth > 0 && (Scr->Monochrome != COLOR))
837             tmp_win->gray = XCreatePixmapFromBitmapData(dpy, Scr->Root, 
838                 (char *)black_bits, gray_width, gray_height, 
839                 tmp_win->border_tile.fore, tmp_win->border_tile.back,
840                 Scr->d_depth);
841         else
842
843         tmp_win->gray = XCreatePixmapFromBitmapData(dpy, Scr->Root,
844             gray_bits, gray_width, gray_height,
845             tmp_win->border_tile.fore, tmp_win->border_tile.back,
846             Scr->d_depth);
847
848         SetBorder (tmp_win, False);
849     }
850     else
851         tmp_win->gray = None;
852
853     if (tmp_win->title_w) {
854         CreateWindowTitlebarButtons (tmp_win);
855         ComputeTitleLocation (tmp_win);
856         XMoveWindow (dpy, tmp_win->title_w,
857                      tmp_win->title_x, tmp_win->title_y);
858         XDefineCursor(dpy, tmp_win->title_w, Scr->TitleCursor);
859     }
860
861         /* djhjr - 4/19/96 */
862     else {
863         tmp_win->title_x = tmp_win->frame_bw3D - tmp_win->frame_bw;
864         tmp_win->title_y = tmp_win->frame_bw3D - tmp_win->frame_bw;
865     }
866
867     valuemask = (CWEventMask | CWDontPropagate);
868     attributes.event_mask = (StructureNotifyMask | PropertyChangeMask |
869                              ColormapChangeMask | VisibilityChangeMask |
870                              EnterWindowMask | LeaveWindowMask);
871     attributes.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask;
872     XChangeWindowAttributes (dpy, tmp_win->w, valuemask, &attributes);
873
874     if (HasShape)
875         XShapeSelectInput (dpy, tmp_win->w, ShapeNotifyMask);
876
877     if (tmp_win->title_w) {
878         XMapWindow (dpy, tmp_win->title_w);
879     }
880
881     if (HasShape) {
882         int xws, yws, xbs, ybs;
883         unsigned wws, hws, wbs, hbs;
884         int boundingShaped, clipShaped;
885
886         XShapeSelectInput (dpy, tmp_win->w, ShapeNotifyMask);
887         XShapeQueryExtents (dpy, tmp_win->w,
888                             &boundingShaped, &xws, &yws, &wws, &hws,
889                             &clipShaped, &xbs, &ybs, &wbs, &hbs);
890         tmp_win->wShaped = boundingShaped;
891     }
892
893     if (!tmp_win->iconmgr)
894         XAddToSaveSet(dpy, tmp_win->w);
895
896 /* djhjr - 4/19/96
897     XReparentWindow(dpy, tmp_win->w, tmp_win->frame, 0, tmp_win->title_height);
898 */
899     XReparentWindow(dpy, tmp_win->w, tmp_win->frame, tmp_win->frame_bw3D,
900                 tmp_win->title_height + tmp_win->frame_bw3D);
901
902     /*
903      * Reparenting generates an UnmapNotify event, followed by a MapNotify.
904      * Set the map state to FALSE to prevent a transition back to
905      * WithdrawnState in HandleUnmapNotify.  Map state gets set correctly
906      * again in HandleMapNotify.
907      */
908     tmp_win->mapped = FALSE;
909
910         /*
911          * NOW do the move and resize - windows needed to be created
912          * first to accomodate the opaque resources - djhjr - 4/14/98
913          */
914         AddMoveAndResize(tmp_win, ask_user);
915
916     SetupFrame (tmp_win, tmp_win->frame_x, tmp_win->frame_y,
917                 tmp_win->frame_width, tmp_win->frame_height, -1, True);
918
919     /* wait until the window is iconified and the icon window is mapped
920      * before creating the icon window
921      */
922     tmp_win->icon_w = None;
923
924     if (!tmp_win->iconmgr)
925     {
926         GrabButtons(tmp_win);
927         GrabKeys(tmp_win);
928     }
929
930     (void) AddIconManager(tmp_win);
931     UpdateDesktop(tmp_win);
932
933     XSaveContext(dpy, tmp_win->w, TwmContext, (caddr_t) tmp_win);
934     XSaveContext(dpy, tmp_win->w, ScreenContext, (caddr_t) Scr);
935     XSaveContext(dpy, tmp_win->frame, TwmContext, (caddr_t) tmp_win);
936     XSaveContext(dpy, tmp_win->frame, ScreenContext, (caddr_t) Scr);
937     if (tmp_win->title_height)
938     {
939         int i;
940         int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
941
942         XSaveContext(dpy, tmp_win->title_w, TwmContext, (caddr_t) tmp_win);
943         XSaveContext(dpy, tmp_win->title_w, ScreenContext, (caddr_t) Scr);
944         for (i = 0; i < nb; i++) {
945             XSaveContext(dpy, tmp_win->titlebuttons[i].window, TwmContext,
946                          (caddr_t) tmp_win);
947             XSaveContext(dpy, tmp_win->titlebuttons[i].window, ScreenContext,
948                          (caddr_t) Scr);
949         }
950         if (tmp_win->hilite_w)
951         {
952             XSaveContext(dpy, tmp_win->hilite_w, TwmContext, (caddr_t)tmp_win);
953             XSaveContext(dpy, tmp_win->hilite_w, ScreenContext, (caddr_t)Scr);
954         }
955     }
956
957     XUngrabServer(dpy);
958
959     /* if we were in the middle of a menu activated function, regrab
960      * the pointer
961      */
962     if (RootFunction != F_NOFUNCTION)
963         ReGrab();
964
965         Scr->Newest = tmp_win; /* PF */
966         if (tmp_win->transient && Scr->WarpToTransients) /* PF */
967                 WarpToWindow(tmp_win); /* PF,DSE */
968
969     return (tmp_win);
970 }
971
972
973 /*
974  * AddPaintRealWindows()
975  *
976  * a little helper for AddMoveAndResize() - djhjr - 4/15/98
977  */
978 static void
979 AddPaintRealWindows(tmp_win, x, y)
980 TwmWindow *tmp_win;
981 int x, y;
982 {
983 /* handled in add_window() now - djhjr - 9/21/99
984         XSetWindowAttributes attr;
985
986         attr.save_under = True;
987         XChangeWindowAttributes(dpy, tmp_win->frame, CWSaveUnder, &attr);
988 */
989
990         /* don't need to send a configure notify event */
991         SetupWindow(tmp_win, tmp_win->frame_x, tmp_win->frame_y,
992                 tmp_win->frame_width, tmp_win->frame_height, -1);
993
994         XMoveWindow(dpy, tmp_win->frame, x, y);
995
996         XMapWindow(dpy, tmp_win->frame);
997         XMapSubwindows(dpy, tmp_win->frame);
998         XMapSubwindows(dpy, tmp_win->title_w);
999
1000         PaintBorderAndTitlebar(tmp_win);
1001
1002         /* djhjr - 4/15/98 */
1003         if (!Scr->NoGrabServer)
1004         {
1005                 /* these allow the application window to be drawn */
1006                 XUngrabServer(dpy); XSync(dpy, 0); XGrabServer(dpy);
1007         }
1008 }
1009
1010
1011 /*
1012  * AddMoveAndResize()
1013  *
1014  * was inline in AddWindow() at first call to this function,
1015  * now handles the opaque move and resize resources - djhjr - 4/14/98
1016  */
1017 static void
1018 AddMoveAndResize(tmp_win, ask_user)
1019 TwmWindow *tmp_win;
1020 int ask_user;
1021 {
1022     static int PlaceX = PLACEMENT_START;
1023     static int PlaceY = PLACEMENT_START;
1024     XEvent event;
1025     int stat, gravx, gravy;
1026     int bw2 = tmp_win->frame_bw * 2;
1027     int wd = tmp_win->attr.width + bw2;
1028     int ht = tmp_win->attr.height + tmp_win->title_height + bw2;
1029
1030     /*
1031      * do any prompting for position
1032      */
1033     if (HandlingEvents && ask_user) {
1034       if (Scr->RandomPlacement) {       /* just stick it somewhere */
1035         if (PlaceX + wd > Scr->MyDisplayWidth) {
1036           /* submitted by Seth Robertson <seth@baka.org> - 8/25/02 */
1037           if (PLACEMENT_START + wd < Scr->MyDisplayWidth)
1038             PlaceX = PLACEMENT_START;
1039           else {
1040             PlaceX = tmp_win->frame_bw;
1041             if (wd < Scr->MyDisplayWidth)
1042               PlaceX += (Scr->MyDisplayWidth - wd) / 2;
1043           }
1044         }
1045         if (PlaceY + ht > Scr->MyDisplayHeight) {
1046           /* submitted by Seth Robertson <seth@baka.org> - 8/25/02 */
1047           if (PLACEMENT_START + ht < Scr->MyDisplayHeight)
1048             PlaceY = PLACEMENT_START;
1049           else {
1050             PlaceY = tmp_win->title_height + tmp_win->frame_bw;
1051             if (ht < Scr->MyDisplayHeight)
1052               PlaceY += (Scr->MyDisplayHeight - ht) / 2;
1053           }
1054         }
1055
1056         tmp_win->attr.x = PlaceX;
1057         tmp_win->attr.y = PlaceY;
1058         PlaceX += PLACEMENT_INCR;
1059         PlaceY += PLACEMENT_INCR;
1060       } else if (Scr->PointerPlacement) {
1061           /* find pointer */
1062           if (!XQueryPointer (dpy, Scr->Root, &JunkRoot,
1063                               &JunkChild, &JunkX, &JunkY,
1064                               &AddingX, &AddingY, &JunkMask))
1065               JunkMask = 0;
1066           /* fit window onto screen */
1067           if (Scr->WarpSnug) {
1068               if (JunkX + wd > Scr->MyDisplayWidth)
1069                   JunkX -= (JunkX + wd - Scr->MyDisplayWidth);
1070               if (JunkY + tmp_win->attr.height > Scr->MyDisplayHeight)
1071                   JunkY -= (JunkY + tmp_win->attr.height - Scr->MyDisplayHeight);
1072           }
1073           tmp_win->attr.x = JunkX;
1074           tmp_win->attr.y = JunkY;
1075       } else {                          /* else prompt */
1076         if (!(tmp_win->wmhints && tmp_win->wmhints->flags & StateHint &&
1077               tmp_win->wmhints->initial_state == IconicState))
1078         {
1079             Bool firsttime = True;
1080
1081             /* djhjr - 11/15/01 */
1082             Bool doorismapped = False;
1083             TwmDoor *door = NULL;
1084             XFindContext(dpy, tmp_win->w, DoorContext, (caddr_t *)&door);
1085
1086             /* better wait until all the mouse buttons have been
1087              * released.
1088              */
1089             while (TRUE)
1090             {
1091                 XUngrabServer(dpy);
1092                 XSync(dpy, 0);
1093                 XGrabServer(dpy);
1094
1095                 JunkMask = 0;
1096                 if (!XQueryPointer (dpy, Scr->Root, &JunkRoot,
1097                                     &JunkChild, &JunkX, &JunkY,
1098                                     &AddingX, &AddingY, &JunkMask))
1099                   JunkMask = 0;
1100
1101                 JunkMask &= (Button1Mask | Button2Mask | Button3Mask |
1102                              Button4Mask | Button5Mask);
1103
1104                 /*
1105                  * watch out for changing screens
1106                  */
1107                 if (firsttime) {
1108                     if (JunkRoot != Scr->Root) {
1109                         register int scrnum;
1110
1111                         for (scrnum = 0; scrnum < NumScreens; scrnum++) {
1112                             if (JunkRoot == RootWindow (dpy, scrnum)) break;
1113                         }
1114
1115                         if (scrnum != NumScreens) PreviousScreen = scrnum;
1116                     }
1117                     firsttime = False;
1118                 }
1119
1120                 /*
1121                  * wait for buttons to come up; yuck
1122                  */
1123                 if (JunkMask != 0) continue;
1124
1125                 /*
1126                  * this will cause a warp to the indicated root
1127                  */
1128                 stat = XGrabPointer(dpy, Scr->Root, False,
1129                     ButtonPressMask | ButtonReleaseMask |
1130                     PointerMotionMask | PointerMotionHintMask,
1131                     GrabModeAsync, GrabModeAsync,
1132                     Scr->Root, UpperLeftCursor, CurrentTime);
1133
1134                 if (stat == GrabSuccess)
1135                     break;
1136             }
1137
1138                 /* djhjr - 4/15/98 */
1139                 if (Scr->NoGrabServer) XUngrabServer(dpy);
1140
1141 /* use initialized size... djhjr - 5/9/96
1142 * djhjr - 9/14/03 *
1143 #ifndef NO_I18N_SUPPORT
1144             width = (SIZE_HINDENT + MyFont_TextWidth (&Scr->SizeFont,
1145 #else
1146             width = (SIZE_HINDENT + XTextWidth (Scr->SizeFont.font,
1147 #endif
1148                                                 tmp_win->name, namelen));
1149             height = Scr->SizeFont.height + SIZE_VINDENT * 2;
1150
1151 * djhjr - 4/27/96
1152             XResizeWindow (dpy, Scr->SizeWindow, width + SIZE_HINDENT, height);
1153 *
1154             XResizeWindow (dpy, Scr->SizeWindow, Scr->SizeStringOffset +
1155                                 Scr->SizeStringWidth, height);
1156 */
1157
1158             XMapRaised(dpy, Scr->SizeWindow);
1159             InstallRootColormap();
1160
1161 /* DisplayPosition overwrites it anyway... djhjr - 5/9/96
1162             * font was font.font->fid - djhjr - 9/14/03 *
1163             FBF(Scr->DefaultC.fore, Scr->DefaultC.back, Scr->SizeFont);
1164 * djhjr - 9/14/03 *
1165 #ifndef NO_I18N_SUPPORT
1166             MyFont_DrawImageString (dpy, Scr->SizeWindow, &Scr->SizeFont,
1167 #else
1168             XDrawImageString (dpy, Scr->SizeWindow,
1169 #endif
1170                               Scr->NormalGC, SIZE_HINDENT,
1171 * djhjr - 9/14/03
1172                               SIZE_VINDENT + Scr->SizeFont.font->ascent,
1173 *
1174                               SIZE_VINDENT + Scr->SizeFont.ascent,
1175                               tmp_win->name, namelen);
1176 */
1177
1178 /* djhjr - 4/19/96
1179             AddingW = tmp_win->attr.width + bw2;
1180             AddingH = tmp_win->attr.height + tmp_win->title_height + bw2;
1181
1182                 MoveOutline(Scr->Root, AddingX, AddingY, AddingW, AddingH,
1183                             tmp_win->frame_bw, tmp_win->title_height);
1184 */
1185             AddingW = tmp_win->attr.width + bw2 + 2 * tmp_win->frame_bw3D;
1186             AddingH = tmp_win->attr.height + tmp_win->title_height +
1187                                 bw2 + 2 * tmp_win->frame_bw3D;
1188
1189                 /* added this 'if ... else' - djhjr - 4/14/98 */
1190                 if (tmp_win->opaque_move)
1191                 {
1192                         AddPaintRealWindows(tmp_win, AddingX, AddingY);
1193
1194                         /* djhjr - 11/15/01 */
1195                         if (door && !doorismapped)
1196                         {
1197                                 XMapWindow(dpy, door->w);    
1198                                 RedoDoorName(tmp_win, door);
1199                                 doorismapped = True;
1200                         }
1201                 }
1202                 else
1203                         MoveOutline(Scr->Root, AddingX, AddingY, AddingW, AddingH,
1204                             tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
1205
1206                 /* djhjr - 4/17/98 */
1207                 if (Scr->VirtualReceivesMotionEvents)
1208                 {
1209                         tmp_win->virtual_frame_x = R_TO_V_X(AddingX);
1210                         tmp_win->virtual_frame_y = R_TO_V_Y(AddingY);
1211                         UpdateDesktop(tmp_win);
1212                 }
1213
1214 /* DisplayPosition() overwrites it anyway... djhjr - 5/9/96
1215 * djhjr - 9/14/03 *
1216 #ifndef NO_I18N_SUPPORT
1217             MyFont_DrawImageString (dpy, Scr->SizeWindow, &Scr->SizeFont,
1218 #else
1219                 * djhjr - 4/27/96 *
1220             XDrawImageString (dpy, Scr->SizeWindow,
1221 #endif
1222                                 Scr->NormalGC, width, 
1223 * djhjr - 9/14/03
1224                                 SIZE_VINDENT + Scr->SizeFont.font->ascent, ": ", 2);
1225 *
1226                                 SIZE_VINDENT + Scr->SizeFont.ascent, ": ", 2);
1227 */
1228
1229                 /* djhjr - 4/27/96 */
1230             DisplayPosition (AddingX, AddingY);
1231
1232             while (TRUE)
1233                 {
1234                 XMaskEvent(dpy, ButtonPressMask | PointerMotionMask, &event);
1235
1236                 if (Event.type == MotionNotify) {
1237                     /* discard any extra motion events before a release */
1238                     while(XCheckMaskEvent(dpy,
1239                         ButtonMotionMask | ButtonPressMask, &Event))
1240                         if (Event.type == ButtonPress)
1241                             break;
1242                 }
1243
1244                 if (event.type == ButtonPress) {
1245                   AddingX = event.xbutton.x_root;
1246                   AddingY = event.xbutton.y_root;
1247
1248                   /* DontMoveOff prohibits user form off-screen placement */
1249                   if (Scr->DontMoveOff)
1250                     {
1251                       int AddingR, AddingB;
1252
1253                       AddingR = AddingX + AddingW;
1254                       AddingB = AddingY + AddingH;
1255
1256                       if (AddingX < 0)
1257                         AddingX = 0;
1258                       if (AddingR > Scr->MyDisplayWidth)
1259                         AddingX = Scr->MyDisplayWidth - AddingW;
1260
1261                       if (AddingY < 0)
1262                         AddingY = 0;
1263                       if (AddingB > Scr->MyDisplayHeight)
1264                         AddingY = Scr->MyDisplayHeight - AddingH;
1265
1266                     }
1267                   break;
1268                 }
1269
1270                 if (event.type != MotionNotify) {
1271                     continue;
1272             }
1273
1274                 XQueryPointer(dpy, Scr->Root, &JunkRoot, &JunkChild,
1275                     &JunkX, &JunkY, &AddingX, &AddingY, &JunkMask);
1276
1277                 if (Scr->DontMoveOff)
1278                 {
1279                     int AddingR, AddingB;
1280
1281                     AddingR = AddingX + AddingW;
1282                     AddingB = AddingY + AddingH;
1283
1284                     if (AddingX < 0)
1285                         AddingX = 0;
1286                     if (AddingR > Scr->MyDisplayWidth)
1287                         AddingX = Scr->MyDisplayWidth - AddingW;
1288
1289                     if (AddingY < 0)
1290                         AddingY = 0;
1291                     if (AddingB > Scr->MyDisplayHeight)
1292                         AddingY = Scr->MyDisplayHeight - AddingH;
1293                 }
1294
1295 /* djhjr - 4/19/96
1296                 MoveOutline(Scr->Root, AddingX, AddingY, AddingW, AddingH,
1297                             tmp_win->frame_bw, tmp_win->title_height);
1298 */
1299                 /* added this 'if ... else' - djhjr - 4/14/98 */
1300                 if (tmp_win->opaque_move)
1301                 {
1302                         XMoveWindow(dpy, tmp_win->frame, AddingX, AddingY);
1303                         PaintBorderAndTitlebar(tmp_win);
1304
1305                         /* djhjr - 4/15/98 */
1306                         if (!Scr->NoGrabServer)
1307                         {
1308                                 /* these allow the application window to be drawn */
1309                                 XUngrabServer(dpy); XSync(dpy, 0); XGrabServer(dpy);
1310                         }
1311                 }
1312                 else
1313                         MoveOutline(Scr->Root, AddingX, AddingY, AddingW, AddingH,
1314                             tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
1315
1316                 /* djhjr - 4/17/98 */
1317                 if (Scr->VirtualReceivesMotionEvents)
1318                 {
1319                         tmp_win->virtual_frame_x = R_TO_V_X(AddingX);
1320                         tmp_win->virtual_frame_y = R_TO_V_Y(AddingY);
1321                         MoveResizeDesktop(tmp_win, Scr->NoRaiseResize);
1322                 }
1323
1324                 /* djhjr - 4/27/96 */
1325                 DisplayPosition (AddingX, AddingY);
1326
1327             }
1328
1329             if (event.xbutton.button == Button2) {
1330                 int lastx, lasty;
1331
1332 /* AddStartResize() overwrites it anyway... djhjr - 5/9/96
1333                 Scr->SizeStringOffset = width +
1334 * djhjr - 9/14/03 *
1335 #ifndef NO_I18N_SUPPORT
1336                   MyFont_TextWidth(&Scr->SizeFont, ": ", 2);
1337 #else
1338                   XTextWidth(Scr->SizeFont.font, ": ", 2);
1339 #endif
1340                 XResizeWindow (dpy, Scr->SizeWindow, Scr->SizeStringOffset +
1341                                Scr->SizeStringWidth, height);
1342 * djhjr - 9/14/03 *
1343 #ifndef NO_I18N_SUPPORT
1344                 MyFont_DrawImageString (dpy, Scr->SizeWindow, &Scr->SizeFont,
1345 #else
1346                 XDrawImageString (dpy, Scr->SizeWindow,
1347 #endif
1348                                   Scr->NormalGC, width,
1349 * djhjr - 9/14/03
1350                                   SIZE_VINDENT + Scr->SizeFont.font->ascent,
1351 *
1352                                   SIZE_VINDENT + Scr->SizeFont.ascent,
1353                                   ": ", 2);
1354 */
1355
1356                 /* djhjr - 4/15/98 */
1357                 if (!tmp_win->opaque_move && tmp_win->opaque_resize)
1358                 {
1359                         /* erase the move outline */
1360                     MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
1361
1362                         AddPaintRealWindows(tmp_win, AddingX, AddingY);
1363
1364                         /* djhjr - 11/15/01 */
1365                         if (door && !doorismapped)
1366                         {
1367                                 XMapWindow(dpy, door->w);    
1368                                 RedoDoorName(tmp_win, door);
1369                                 doorismapped = True;
1370                         }
1371                 }
1372
1373 #if 0
1374                 if (0/*Scr->AutoRelativeResize*/)
1375 My R5 vtvwm came with this commented out, always 0.
1376 Why?
1377 #endif
1378                 if (Scr->AutoRelativeResize)
1379                 {
1380                     int dx = (tmp_win->attr.width / 4);
1381                     int dy = (tmp_win->attr.height / 4);
1382
1383 #define HALF_AVE_CURSOR_SIZE 8          /* so that it is visible */
1384                     if (dx < HALF_AVE_CURSOR_SIZE) dx = HALF_AVE_CURSOR_SIZE;
1385                     if (dy < HALF_AVE_CURSOR_SIZE) dy = HALF_AVE_CURSOR_SIZE;
1386 #undef HALF_AVE_CURSOR_SIZE
1387                     dx += (tmp_win->frame_bw + 1);
1388                     dy += (bw2 + tmp_win->title_height + 1);
1389                     if (AddingX + dx >= Scr->MyDisplayWidth)
1390                       dx = Scr->MyDisplayWidth - AddingX - 1;
1391                     if (AddingY + dy >= Scr->MyDisplayHeight)
1392                       dy = Scr->MyDisplayHeight - AddingY - 1;
1393                     if (dx > 0 && dy > 0)
1394                       XWarpPointer (dpy, None, None, 0, 0, 0, 0, dx, dy);
1395                 } else {
1396                     XWarpPointer (dpy, None, Scr->Root, 0, 0, 0, 0,
1397                                   AddingX + AddingW/2, AddingY + AddingH/2);
1398                 }
1399                 AddStartResize(tmp_win, AddingX, AddingY, AddingW, AddingH);
1400
1401                 lastx = -10000;
1402                 lasty = -10000;
1403                 while (TRUE)
1404                 {
1405                     XMaskEvent(dpy,
1406                                ButtonReleaseMask | ButtonMotionMask, &event);
1407
1408                     if (Event.type == MotionNotify) {
1409                         /* discard any extra motion events before a release */
1410                         while(XCheckMaskEvent(dpy,
1411                             ButtonMotionMask | ButtonReleaseMask, &Event))
1412                             if (Event.type == ButtonRelease)
1413                                 break;
1414                     }
1415
1416                     if (event.type == ButtonRelease)
1417                     {
1418                         AddEndResize(tmp_win);
1419
1420                         /* don't need to send a configure notify event - djhjr - 4/15/98 */
1421                         if (tmp_win->opaque_move && !tmp_win->opaque_resize)
1422                                 SetupWindow(tmp_win, AddingX, AddingY, AddingW, AddingH, -1);
1423
1424                         /* djhjr - 11/15/01 */
1425                         if (!tmp_win->opaque_resize && door && doorismapped)
1426                                 RedoDoorName(tmp_win, door);
1427
1428                         break;
1429                     }
1430
1431                     if (event.type != MotionNotify) {
1432                         continue;
1433                     }
1434
1435                     /*
1436                      * XXX - if we are going to do a loop, we ought to consider
1437                      * using multiple GXxor lines so that we don't need to
1438                      * grab the server.
1439                      */
1440                     XQueryPointer(dpy, Scr->Root, &JunkRoot, &JunkChild,
1441                         &JunkX, &JunkY, &AddingX, &AddingY, &JunkMask);
1442
1443                     if (lastx != AddingX || lasty != AddingY)
1444                     {
1445                         DoResize(AddingX, AddingY, tmp_win);
1446
1447                         lastx = AddingX;
1448                         lasty = AddingY;
1449                     }
1450
1451                 }
1452             } /* if (event.xbutton.button == Button2) */
1453             else if (event.xbutton.button == Button3)
1454             {
1455                 int maxw = Scr->MyDisplayWidth - AddingX - bw2;
1456                 int maxh = Scr->MyDisplayHeight - AddingY - bw2;
1457
1458                 /*
1459                  * Make window go to bottom of screen, and clip to right edge.
1460                  * This is useful when popping up large windows and fixed
1461                  * column text windows.
1462                  */
1463                 if (AddingW > maxw) AddingW = maxw;
1464                 AddingH = maxh;
1465
1466                 ConstrainSize (tmp_win, &AddingW, &AddingH);  /* w/o borders */
1467                 AddingW += bw2;
1468                 AddingH += bw2;
1469
1470                 /* don't need to send a configure notify event - djhjr - 4/15/98 */
1471                 SetupWindow(tmp_win, AddingX, AddingY, AddingW, AddingH, -1);
1472
1473                 /* djhjr - 11/15/01 */
1474                 if (!tmp_win->opaque_resize && door && doorismapped)
1475                         RedoDoorName(tmp_win, door);
1476
1477             }
1478             else
1479             {
1480                 XMaskEvent(dpy, ButtonReleaseMask, &event);
1481             }
1482
1483                 /* erase the move outline */
1484             MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
1485
1486             XUnmapWindow(dpy, Scr->SizeWindow);
1487             UninstallRootColormap();
1488             XUngrabPointer(dpy, CurrentTime);
1489
1490 /* djhjr - 4/15/98
1491             tmp_win->attr.x = AddingX;
1492             tmp_win->attr.y = AddingY + tmp_win->title_height;
1493 */
1494                 tmp_win->attr.x = AddingX + tmp_win->frame_bw + tmp_win->frame_bw3D;
1495                 tmp_win->attr.y = AddingY + tmp_win->title_height +
1496                         tmp_win->frame_bw + tmp_win->frame_bw3D;
1497
1498 /* djhjr - 4/19/96
1499             tmp_win->attr.width = AddingW - bw2;
1500             tmp_win->attr.height = AddingH - tmp_win->title_height - bw2;
1501 */
1502             tmp_win->attr.width = AddingW - bw2 - 2 * tmp_win->frame_bw3D;
1503             tmp_win->attr.height = AddingH - tmp_win->title_height -
1504                                 bw2 - 2 * tmp_win->frame_bw3D;
1505
1506 /* un-grabbed in the caller AddWindow() on return - djhjr - 4/15/98
1507             XUngrabServer(dpy);
1508 */
1509         }
1510       }
1511
1512                 /* djhjr - 6/4/98 */
1513                 if (Scr->VirtualReceivesMotionEvents && !tmp_win->opaque_move)
1514                 {
1515                         XUnmapWindow(dpy, Scr->VirtualDesktopDisplay);
1516                         XMapWindow(dpy, Scr->VirtualDesktopDisplay);
1517                 }
1518     } else {                            /* put it where asked, mod title bar */
1519         /* interpret the position specified as a virtual one if asked */
1520
1521 /* added 'FixManagedVirtualGeometries' - djhjr - 1/6/98 */
1522 /* added test for 'PPosition' - submitted by Michael Dales */
1523         if (Scr->GeometriesAreVirtual ||
1524             (!Scr->GeometriesAreVirtual &&
1525                 (tmp_win->nailed ||
1526                     (   ( (Scr->FixManagedVirtualGeometries &&
1527                                 !tmp_win->transient) ||
1528                           (Scr->FixTransientVirtualGeometries &&
1529                                 tmp_win->transient)
1530                         ) && (tmp_win->hints.flags & PPosition)
1531                     )
1532                 )
1533             )
1534         )
1535             /*
1536              * If virtual geometries is set, or virtual geometries
1537              * isn't set and (nailed or (fix virtual geometries and
1538              * preferred position)). This is a bug workaround -- DSE
1539              */
1540             {
1541                 tmp_win->attr.x = V_TO_R_X(tmp_win->attr.x);
1542                 tmp_win->attr.y = V_TO_R_Y(tmp_win->attr.y);
1543             }
1544
1545         GetGravityOffsets (tmp_win, &gravx, &gravy);
1546
1547         /* if the gravity is towards the top, move it by the title height */
1548         if (gravy < 0) tmp_win->attr.y -= gravy * tmp_win->title_height;
1549     }
1550
1551 /* should never have been - djhjr - 9/21/99
1552         if (tmp_win->opaque_move)
1553         {
1554                 XSetWindowAttributes attr;
1555
1556                 attr.save_under = False;
1557                 XChangeWindowAttributes(dpy, tmp_win->frame, CWSaveUnder, &attr);
1558         }
1559 */
1560
1561 /*
1562  * consider client borderwidths based on the ClientBorderWidth and
1563  * RandomPlacement resources, PPosition with the UsePPosition resource,
1564  * and the USPosition spec - djhjr - 6/3/98
1565  *
1566         tmp_win->frame_x = tmp_win->attr.x + tmp_win->old_bw - tmp_win->frame_bw
1567                         - tmp_win->frame_bw3D;
1568         tmp_win->frame_y = tmp_win->attr.y - tmp_win->title_height +
1569                         tmp_win->old_bw - tmp_win->frame_bw - tmp_win->frame_bw3D;
1570 */
1571         tmp_win->frame_x = tmp_win->attr.x -
1572                         tmp_win->frame_bw - tmp_win->frame_bw3D;
1573         tmp_win->frame_y = tmp_win->attr.y - tmp_win->title_height -
1574                         tmp_win->frame_bw - tmp_win->frame_bw3D;
1575 /* Not needed? - submitted by Jonathan Paisley - 11/8/02
1576         if (Scr->ClientBorderWidth || !ask_user)
1577         {
1578                 tmp_win->frame_x += tmp_win->old_bw;
1579                 tmp_win->frame_y += tmp_win->old_bw;
1580         }
1581 */
1582
1583         tmp_win->frame_width = tmp_win->attr.width + 2 * tmp_win->frame_bw3D;
1584         tmp_win->frame_height = tmp_win->attr.height + tmp_win->title_height +
1585                         2 * tmp_win->frame_bw3D;
1586         ConstrainSize (tmp_win, &tmp_win->frame_width, &tmp_win->frame_height);
1587
1588         tmp_win->virtual_frame_x = R_TO_V_X(tmp_win->frame_x);
1589         tmp_win->virtual_frame_y = R_TO_V_Y(tmp_win->frame_y);
1590
1591 #ifdef DEBUG
1592         fprintf(stderr, "  position window  %d, %d  %dx%d\n",
1593             tmp_win->attr.x,
1594             tmp_win->attr.y,
1595             tmp_win->attr.width,
1596             tmp_win->attr.height);
1597 #endif
1598 }
1599
1600
1601 /***********************************************************************
1602  *
1603  *  Procedure:
1604  *      MappedNotOverride - checks to see if we should really
1605  *              put a twm frame on the window
1606  *
1607  *  Returned Value:
1608  *      TRUE    - go ahead and frame the window
1609  *      FALSE   - don't frame the window
1610  *
1611  *  Inputs:
1612  *      w       - the window to check
1613  *
1614  ***********************************************************************
1615  */
1616
1617 int
1618 MappedNotOverride(w)
1619     Window w;
1620 {
1621     XWindowAttributes wa;
1622
1623     XGetWindowAttributes(dpy, w, &wa);
1624     return ((wa.map_state != IsUnmapped) && (wa.override_redirect != True));
1625 }
1626
1627
1628 /***********************************************************************
1629  *
1630  *  Procedure:
1631  *      AddDefaultBindings - attach default bindings so that naive users
1632  *      don't get messed up if they provide a minimal twmrc.
1633  */
1634 static void do_add_binding (button, context, modifier, func)
1635     int button, context, modifier;
1636     int func;
1637 {
1638     MouseButton *mb = &Scr->Mouse[button][context][modifier];
1639
1640     if (mb->func) return;               /* already defined */
1641
1642     mb->func = func;
1643     mb->item = NULL;
1644 }
1645
1646 void AddDefaultBindings ()
1647 {
1648     /*
1649      * The bindings are stored in Scr->Mouse, indexed by
1650      * Mouse[button_number][C_context][modifier].
1651      */
1652
1653 #define NoModifierMask 0
1654
1655     do_add_binding (Button1, C_TITLE, NoModifierMask, F_MOVE);
1656     do_add_binding (Button1, C_ICON, NoModifierMask, F_ICONIFY);
1657     do_add_binding (Button1, C_ICONMGR, NoModifierMask, F_ICONIFY);
1658     do_add_binding (Button1, C_VIRTUAL, NoModifierMask, F_MOVESCREEN);
1659     do_add_binding (Button1, C_VIRTUAL_WIN, NoModifierMask, F_MOVESCREEN);
1660
1661     do_add_binding (Button2, C_TITLE, NoModifierMask, F_RAISELOWER);
1662     do_add_binding (Button2, C_ICON, NoModifierMask, F_ICONIFY);
1663     do_add_binding (Button2, C_ICONMGR, NoModifierMask, F_ICONIFY);
1664     do_add_binding (Button2, C_VIRTUAL, NoModifierMask, F_MOVESCREEN);
1665     do_add_binding (Button2, C_VIRTUAL_WIN, NoModifierMask, F_MOVESCREEN);
1666
1667 #undef NoModifierMask
1668 }
1669
1670
1671
1672
1673 /***********************************************************************
1674  *
1675  *  Procedure:
1676  *      GrabButtons - grab needed buttons for the window
1677  *
1678  *  Inputs:
1679  *      tmp_win - the twm window structure to use
1680  *
1681  ***********************************************************************
1682  */
1683
1684 void
1685 GrabButtons(tmp_win)
1686 TwmWindow *tmp_win;
1687 {
1688     int i, j;
1689
1690     for (i = 0; i < MAX_BUTTONS+1; i++)
1691     {
1692         for (j = 0; j < MOD_SIZE; j++)
1693         {
1694             if (Scr->Mouse[i][C_WINDOW][j].func != F_NOFUNCTION)
1695             {
1696                 /* twm used to do this grab on the application main window,
1697                  * tmp_win->w . This was not ICCCM complient and was changed.
1698                  */
1699                 XGrabButton(dpy, i, j, tmp_win->frame,
1700                             True, ButtonPressMask | ButtonReleaseMask,
1701                             GrabModeAsync, GrabModeAsync, None,
1702                             Scr->FrameCursor);
1703             }
1704         }
1705     }
1706 }
1707
1708 /***********************************************************************
1709  *
1710  *  Procedure:
1711  *      GrabKeys - grab needed keys for the window
1712  *
1713  *  Inputs:
1714  *      tmp_win - the twm window structure to use
1715  *
1716  ***********************************************************************
1717  */
1718
1719 /* djhjr - 9/10/03 */
1720 void
1721 GrabModKeys(w, k)
1722 Window w;
1723 FuncKey *k;
1724 {
1725     int i;
1726
1727     XGrabKey(dpy, k->keycode, k->mods, w, True, GrabModeAsync, GrabModeAsync);
1728
1729     for (i = 1; i <= Scr->IgnoreModifiers; i++)
1730         if ((Scr->IgnoreModifiers & i) == i)
1731             XGrabKey(dpy, k->keycode, k->mods | i, w, True,
1732                         GrabModeAsync, GrabModeAsync);
1733 }
1734
1735 /* djhjr - 9/10/03 */
1736 void
1737 UngrabModKeys(w, k)
1738 Window w;
1739 FuncKey *k;
1740 {
1741     int i;
1742
1743     XUngrabKey(dpy, k->keycode, k->mods, w);
1744
1745     for (i = 1; i <= Scr->IgnoreModifiers; i++)
1746         if ((Scr->IgnoreModifiers & i) == i)
1747             XUngrabKey(dpy, k->keycode, k->mods | i, w);
1748 }
1749
1750 void
1751 GrabKeys(tmp_win)
1752 TwmWindow *tmp_win;
1753 {
1754     FuncKey *tmp;
1755     IconMgr *p;
1756
1757     for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next)
1758     {
1759         switch (tmp->cont)
1760         {
1761         case C_WINDOW:
1762 /* djhjr - 9/10/03
1763             XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->w, True,
1764                 GrabModeAsync, GrabModeAsync);
1765 */
1766             GrabModKeys(tmp_win->w, tmp);
1767             break;
1768
1769         case C_ICON:
1770             if (tmp_win->icon_w)
1771 /* djhjr - 9/10/03
1772                 XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->icon_w, True,
1773                     GrabModeAsync, GrabModeAsync);
1774 */
1775                 GrabModKeys(tmp_win->icon_w, tmp);
1776
1777         case C_TITLE:
1778             if (tmp_win->title_w)
1779 /* djhjr - 9/10/03
1780                 XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->title_w, True,
1781                     GrabModeAsync, GrabModeAsync);
1782 */
1783                 GrabModKeys(tmp_win->title_w, tmp);
1784             break;
1785
1786         case C_NAME:
1787 /* djhjr - 9/10/03
1788             XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->w, True,
1789                 GrabModeAsync, GrabModeAsync);
1790 */
1791             GrabModKeys(tmp_win->w, tmp);
1792             if (tmp_win->icon_w)
1793 /* djhjr - 9/10/03
1794                 XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->icon_w, True,
1795                     GrabModeAsync, GrabModeAsync);
1796 */
1797                 GrabModKeys(tmp_win->icon_w, tmp);
1798             if (tmp_win->title_w)
1799 /* djhjr - 9/10/03
1800                 XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->title_w, True,
1801                     GrabModeAsync, GrabModeAsync);
1802 */
1803                 GrabModKeys(tmp_win->title_w, tmp);
1804             break;
1805
1806         /*
1807         case C_ROOT:
1808 * djhjr - 9/10/03
1809             XGrabKey(dpy, tmp->keycode, tmp->mods, Scr->Root, True,
1810                 GrabModeAsync, GrabModeAsync);
1811 *
1812             GrabModKeys(Scr->Root, tmp);
1813             break;
1814         */
1815         }
1816     }
1817     for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next)
1818     {
1819         if (tmp->cont == C_ICONMGR && !Scr->NoIconManagers)
1820         {
1821             for (p = &Scr->iconmgr; p != NULL; p = p->next)
1822             {
1823 /* djhjr - 9/10/03
1824                 XUngrabKey(dpy, tmp->keycode, tmp->mods, p->twm_win->w);
1825 */
1826                 UngrabModKeys(p->twm_win->w, tmp);
1827             }
1828         }
1829     }
1830 }
1831
1832 static Window CreateHighlightWindow (tmp_win)
1833     TwmWindow *tmp_win;
1834 {
1835     XSetWindowAttributes attributes;    /* attributes for create windows */
1836     Pixmap pm = None;
1837     GC gc;
1838     XGCValues gcv;
1839     unsigned long valuemask;
1840         unsigned int pm_numcolors;
1841     /* added '- 2' - djhjr - 10/18/02 */
1842     int h = (Scr->TitleHeight - 2 * Scr->FramePadding) - 2;
1843     Window w;
1844
1845 /* djhjr - 9/14/03
1846 #ifndef NO_I18N_SUPPORT
1847         int en = MyFont_TextWidth(&Scr->TitleBarFont, "n", 1);
1848 #else
1849         * djhjr - 4/1/98 *
1850         int en = XTextWidth(Scr->TitleBarFont.font, "n", 1);
1851 #endif
1852 */
1853 /* djhjr - 10/18/02
1854         int width = Scr->TBInfo.titlex + tmp_win->name_width + 2 * en;
1855 */
1856
1857     /*
1858      * If a special highlight pixmap was given, use that.  Otherwise,
1859      * use a nice, even gray pattern.  The old horizontal lines look really
1860      * awful on interlaced monitors (as well as resembling other looks a
1861      * little bit too closely), but can be used by putting
1862      *
1863      *                 Pixmaps { TitleHighlight "hline2" }
1864      *
1865      * (or whatever the horizontal line bitmap is named) in the startup
1866      * file.  If all else fails, use the foreground color to look like a
1867      * solid line.
1868      */
1869
1870 /*
1871  * re-written to use an Image structure for XPM support
1872  *
1873  * djhjr - 5/17/98
1874  */
1875 #ifdef ORIGINAL_PIXMAPS
1876     if (!Scr->hilitePm) {
1877
1878         /* djhjr - 4/20/96 */
1879         /* was 'Scr->use3Dtitles' - djhjr - 8/11/98 */
1880         if (Scr->TitleBevelWidth > 0 && (Scr->Monochrome != COLOR))
1881             Scr->hilitePm = XCreateBitmapFromData (dpy, tmp_win->title_w, 
1882                                         (char *)black_bits, gray_width, gray_height);
1883         else
1884             Scr->hilitePm = XCreateBitmapFromData (dpy, tmp_win->title_w, 
1885                                         gray_bits, gray_width, gray_height);
1886
1887         Scr->hilite_pm_width = gray_width;
1888         Scr->hilite_pm_height = gray_height;
1889     }
1890     if (Scr->hilitePm) {
1891         pm = XCreatePixmap (dpy, tmp_win->title_w,
1892                             Scr->hilite_pm_width, Scr->hilite_pm_height,
1893                             Scr->d_depth);
1894         gcv.foreground = tmp_win->title.fore;
1895         gcv.background = tmp_win->title.back;
1896         gcv.graphics_exposures = False;
1897         gc = XCreateGC (dpy, pm,
1898                         (GCForeground|GCBackground|GCGraphicsExposures),
1899                         &gcv);
1900         if (gc) {
1901             XCopyPlane (dpy, Scr->hilitePm, pm, gc, 0, 0,
1902                         Scr->hilite_pm_width, Scr->hilite_pm_height,
1903                         0, 0, 1);
1904             XFreeGC (dpy, gc);
1905         } else {
1906             XFreePixmap (dpy, pm);
1907             pm = None;
1908         }
1909     }
1910     if (pm) {
1911         valuemask = CWBackPixmap;
1912         attributes.background_pixmap = pm;
1913     } else {
1914         valuemask = CWBackPixel;
1915         attributes.background_pixel = tmp_win->title.fore;
1916     }
1917 #else /* ORIGINAL_PIXMAPS */
1918         if (!Scr->hilitePm)
1919         {
1920                 Scr->hilitePm = (Image *)malloc(sizeof(Image));
1921                 if (Scr->hilitePm)
1922                 {
1923                         Scr->hilitePm->width = gray_width;
1924                         Scr->hilitePm->height = gray_height;
1925                         Scr->hilitePm->mask = None;
1926
1927                         /* djhjr - 4/20/96 */
1928                         /* was 'Scr->use3Dtitles' - djhjr - 8/11/98 */
1929                         if (Scr->TitleBevelWidth > 0 && (Scr->Monochrome != COLOR))
1930                                 Scr->hilitePm->pixmap = XCreateBitmapFromData (dpy,
1931                                                 tmp_win->title_w, (char *)black_bits,
1932                                                 Scr->hilitePm->width, Scr->hilitePm->height);
1933                         else
1934                                 Scr->hilitePm->pixmap = XCreateBitmapFromData (dpy,
1935                                                 tmp_win->title_w, gray_bits,
1936                                                 Scr->hilitePm->width, Scr->hilitePm->height);
1937                 }
1938         }
1939
1940         pm_numcolors  = 0;
1941
1942 /* djhjr - 5/23/98 9/2/98 */
1943 #ifndef NO_XPM_SUPPORT
1944 /* removed this for non-transparent pixmaps - djhjr - 5/26/98
1945         if (Scr->hilitePm->mask != None)
1946 */
1947                 pm_numcolors = SetPixmapsBackground(Scr->hilitePm, Scr->Root,
1948                                 tmp_win->title.back);
1949 #endif
1950
1951         /*
1952          * Modified to handle non-transparent pixmaps - Jason Gloudon
1953          */
1954         if (Scr->hilitePm->pixmap)
1955         {
1956                 if (pm_numcolors > 2) /* not a bitmap */
1957                 {
1958                         valuemask = CWBackPixmap;
1959                         attributes.background_pixmap = Scr->hilitePm->pixmap;
1960                 }
1961                 else
1962                 {
1963                         pm = XCreatePixmap (dpy, tmp_win->title_w,
1964                                         Scr->hilitePm->width, Scr->hilitePm->height,
1965                                         Scr->d_depth);
1966
1967                         gcv.foreground = tmp_win->title.fore;
1968                         gcv.background = tmp_win->title.back;
1969                         gcv.graphics_exposures = False;
1970
1971                         gc = XCreateGC (dpy, pm,
1972                                         (GCForeground | GCBackground | GCGraphicsExposures),
1973                                         &gcv);
1974
1975                         if (gc)
1976                         {
1977                                 /* the copy plane works on color ! */
1978                                 XCopyPlane (dpy, Scr->hilitePm->pixmap, pm, gc, 0, 0,
1979                                                 Scr->hilitePm->width, Scr->hilitePm->height,
1980                                                 0, 0, 1);
1981
1982                                 XFreeGC(dpy, gc);
1983
1984                                 valuemask = CWBackPixmap;
1985                                 attributes.background_pixmap = pm;
1986                         }
1987                         else
1988                         {
1989                                 valuemask = CWBackPixel;
1990                                 attributes.background_pixel = tmp_win->title.fore;
1991                         }
1992                 }
1993         }
1994         else
1995         {
1996                 valuemask = CWBackPixel;
1997                 attributes.background_pixel = tmp_win->title.fore;
1998         }
1999 #endif /* ORIGINAL_PIXMAPS */
2000
2001 /* djhjr - 10/18/02 */
2002 #if 0
2003         /* djhjr - 4/19/96 */
2004         /* was 'Scr->use3Dtitles' - djhjr - 8/11/98 */
2005     if (Scr->TitleBevelWidth > 0)
2006 /* djhjr - 4/25/96
2007         w = XCreateWindow (dpy, tmp_win->title_w, 0, Scr->FramePadding + 2,
2008                        (unsigned int) Scr->TBInfo.width, (unsigned int) (h - 4),
2009 */
2010 /* djhjr - 4/1/98
2011         w = XCreateWindow (dpy, tmp_win->title_w, 0, Scr->FramePadding + 3,
2012                        (unsigned int) Scr->TBInfo.width, (unsigned int) (h - 6),
2013 */
2014         w = XCreateWindow (dpy, tmp_win->title_w, width, Scr->FramePadding + 4,
2015                        ComputeHighlightWindowWidth(tmp_win), (unsigned int) (h - 8),
2016
2017                        (unsigned int) 0,
2018                        Scr->d_depth, (unsigned int) CopyFromParent,
2019                        Scr->d_visual, valuemask, &attributes);
2020
2021     else
2022 /* djhjr - 4/1/98
2023     w = XCreateWindow (dpy, tmp_win->title_w, 0, Scr->FramePadding,
2024                        (unsigned int) Scr->TBInfo.width, (unsigned int) h,
2025 */
2026         w = XCreateWindow (dpy, tmp_win->title_w, width, Scr->FramePadding + 2,
2027                        ComputeHighlightWindowWidth(tmp_win), (unsigned int) (h - 4),
2028                        (unsigned int) 0,
2029                        Scr->d_depth, (unsigned int) CopyFromParent,
2030                        Scr->d_visual, valuemask, &attributes);
2031 #else
2032         w = XCreateWindow (dpy, tmp_win->title_w,
2033                        tmp_win->highlightx, Scr->FramePadding + 1,
2034                        ComputeHighlightWindowWidth(tmp_win), (unsigned int) h,
2035                        (unsigned int) 0,
2036                        Scr->d_depth, (unsigned int) CopyFromParent,
2037                        Scr->d_visual, valuemask, &attributes);
2038 #endif
2039
2040     if (pm) XFreePixmap (dpy, pm);
2041
2042     return w;
2043 }
2044
2045
2046 void ComputeCommonTitleOffsets ()
2047 {
2048 /* djhjr - 9/14/03 */
2049 #ifndef NO_I18N_SUPPORT
2050     int en = MyFont_TextWidth(&Scr->TitleBarFont, "n", 1);
2051 #else
2052     /* djhjr - 10/18/02 */
2053     int en = XTextWidth(Scr->TitleBarFont.font, "n", 1);
2054 #endif
2055
2056     int buttonwidth = (Scr->TBInfo.width + Scr->TBInfo.pad);
2057
2058     Scr->TBInfo.leftx = Scr->TBInfo.rightoff = Scr->FramePadding;
2059
2060     if (Scr->TBInfo.nleft > 0)
2061       Scr->TBInfo.leftx += Scr->ButtonIndent;
2062
2063     /* 'en' was 'Scr->TitlePadding' - djhjr - 10/18/02 */
2064     Scr->TBInfo.titlex = (Scr->TBInfo.leftx +
2065                          (Scr->TBInfo.nleft * buttonwidth) - Scr->TBInfo.pad +
2066                          en);
2067
2068     if (Scr->TBInfo.nright > 0)
2069       Scr->TBInfo.rightoff += (Scr->ButtonIndent +
2070                               ((Scr->TBInfo.nright * buttonwidth) -
2071                               Scr->TBInfo.pad));
2072     return;
2073 }
2074
2075 void ComputeWindowTitleOffsets (tmp_win, width, squeeze)
2076     TwmWindow *tmp_win;
2077         int width;
2078     Bool squeeze;
2079 {
2080 /* djhjr - 9/14/03 */
2081 #ifndef NO_I18N_SUPPORT
2082     int en = MyFont_TextWidth(&Scr->TitleBarFont, "n", 1);
2083 #else
2084     /* djhjr - 10/18/02 */
2085     int en = XTextWidth(Scr->TitleBarFont.font, "n", 1);
2086 #endif
2087
2088     /* added 'en' - djhjr - 10/18/02 */
2089     tmp_win->highlightx = Scr->TBInfo.titlex + tmp_win->name_width + en;
2090
2091 /* djhjr - 10/18/02
2092         * djhjr - 4/1/98 *
2093         * was 'Scr->use3Dtitles' - djhjr - 8/11/98 *
2094         if (Scr->TitleBevelWidth > 0)
2095         {
2096 * djhjr - 9/14/03 *
2097 #ifndef NO_I18N_SUPPORT
2098                 int en = MyFont_TextWidth(&Scr->TitleBarFont, "n", 1);
2099 #else
2100                 int en = XTextWidth(Scr->TitleBarFont.font, "n", 1);
2101 #endif
2102                 tmp_win->highlightx += en;
2103
2104                 * rem'd out - djhjr - 4/19/96 *
2105                 * reinstated - djhjr - 4/1/98 *
2106         tmp_win->highlightx += 6;
2107         }
2108
2109     if (tmp_win->hilite_w || Scr->TBInfo.nright > 0)
2110       tmp_win->highlightx += Scr->TitlePadding;
2111 */
2112
2113     tmp_win->rightx = width - Scr->TBInfo.rightoff;
2114
2115         if (squeeze && tmp_win->squeeze_info)
2116         {
2117                 /* djhjr - 3/13/97 8/11/98 */
2118                 /* this used to care about title bevels - djhjr - 10/18/02 */
2119                 int rx = tmp_win->highlightx +
2120                          ((tmp_win->titlehighlight) ? Scr->TitleHeight * 2 : 0);
2121
2122                 if (rx < tmp_win->rightx) tmp_win->rightx = rx;
2123     }
2124
2125     return;
2126 }
2127
2128
2129 /*
2130  * ComputeTitleLocation - calculate the position of the title window.
2131  *
2132  * substantially re-written - djhjr - 1/8/98
2133  */
2134 void ComputeTitleLocation (tmp)
2135     TwmWindow *tmp;
2136 {
2137         tmp->title_x = tmp->frame_bw3D - tmp->frame_bw;
2138         tmp->title_y = tmp->frame_bw3D - tmp->frame_bw;
2139
2140         if (tmp->squeeze_info)
2141         {
2142                 SqueezeInfo *si = tmp->squeeze_info;
2143                 int basex;
2144                 int fw = tmp->frame_bw + tmp->frame_bw3D;
2145
2146                 if (si->denom != 0 && si->num != 0)
2147                         basex = ((tmp->frame_width - tmp->title_width) / si->denom) * si->num + fw;
2148                 else
2149                         if (si->denom == 0 && si->num != 0)
2150                                 basex = si->num + fw;
2151                         else
2152                                 switch (si->justify)
2153                                 {
2154                                         case J_LEFT:
2155                                                 basex = tmp->title_x + fw;
2156                                                 break;
2157                                         case J_CENTER:
2158                                                 basex = tmp->frame_width / 2 - (tmp->title_width / 2 - fw);
2159                                                 break;
2160                                         case J_RIGHT:
2161                                                 basex = tmp->frame_width - tmp->title_width;
2162                                                 break;
2163                                 }
2164
2165                 if (basex > tmp->frame_width - tmp->title_width)
2166                         basex = tmp->frame_width - tmp->title_width;
2167                 if (basex < 0)
2168                         basex = tmp->title_x + fw;
2169
2170                 tmp->title_x = basex - fw;
2171         }
2172 }
2173
2174
2175 static void CreateWindowTitlebarButtons (tmp_win)
2176     TwmWindow *tmp_win;
2177 {
2178     unsigned long valuemask;            /* mask for create windows */
2179     XSetWindowAttributes attributes;    /* attributes for create windows */
2180     TitleButton *tb;
2181     TBWindow *tbw;
2182     int boxwidth = Scr->TBInfo.width + Scr->TBInfo.pad;
2183     unsigned int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
2184     int x, y = Scr->FramePadding + Scr->ButtonIndent;   /* init - djhjr - 10/18/02 */
2185     int nb, leftx, rightx;
2186
2187     if (tmp_win->title_height == 0)
2188     {
2189         tmp_win->hilite_w = 0;
2190         return;
2191     }
2192
2193     /*
2194      * create the title bar windows; let the event handler deal with painting
2195      * so that we don't have to spend two pixmaps (or deal with hashing)
2196      */
2197     ComputeWindowTitleOffsets (tmp_win, tmp_win->attr.width, False);
2198
2199 /* djhjr - 10/18/02
2200     leftx = y = Scr->TBInfo.leftx;
2201 */
2202     leftx = Scr->TBInfo.leftx;
2203     rightx = tmp_win->rightx;
2204
2205     attributes.background_pixel = tmp_win->title.back;
2206     attributes.border_pixel = tmp_win->title.fore;
2207     attributes.event_mask = (ButtonPressMask | ButtonReleaseMask | ExposureMask);
2208     attributes.cursor = Scr->ButtonCursor;
2209
2210     valuemask = (CWWinGravity | CWBackPixel | CWBorderPixel | CWEventMask | CWCursor);
2211
2212     tmp_win->titlebuttons = NULL;
2213     nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
2214     if (nb > 0) {
2215         tmp_win->titlebuttons = (TBWindow *) malloc (nb * sizeof(TBWindow));
2216         if (!tmp_win->titlebuttons) {
2217             fprintf (stderr, "%s:  unable to allocate %d titlebuttons\n",
2218                      ProgramName, nb);
2219         } else {
2220             for (tb = Scr->TBInfo.head, tbw = tmp_win->titlebuttons; tb;
2221                  tb = tb->next, tbw++) {
2222                 if (tb->rightside) {
2223                     x = rightx;
2224                     rightx += boxwidth;
2225                     attributes.win_gravity = NorthEastGravity;
2226                 } else {
2227                     x = leftx;
2228                     leftx += boxwidth;
2229                     attributes.win_gravity = NorthWestGravity;
2230                 }
2231
2232                 tbw->window = XCreateWindow (dpy, tmp_win->title_w, x, y, h, h,
2233                                              (unsigned int) Scr->TBInfo.border,
2234                                              0, (unsigned int) CopyFromParent,
2235                                              (Visual *) CopyFromParent,
2236                                              valuemask, &attributes);
2237
2238                 tbw->info = tb;
2239             } /* end for(...) */
2240         }
2241     }
2242
2243 /* djhjr - 4/5/98
2244     tmp_win->hilite_w = (tmp_win->titlehighlight
2245                          ? CreateHighlightWindow (tmp_win) : None);
2246
2247     XMapSubwindows(dpy, tmp_win->title_w);
2248
2249 * djhjr - 4/25/96
2250     if (tmp_win->hilite_w)
2251       XUnmapWindow(dpy, tmp_win->hilite_w);
2252 *
2253         PaintTitleHighlight(tmp_win, off);
2254 */
2255         /* was '!Scr->SunkFocusWindowTitle' - djhjr - 10/25/02 */
2256         tmp_win->hilite_w =
2257                 (tmp_win->titlehighlight && !Scr->hiliteName) ?
2258                 CreateHighlightWindow(tmp_win) : None;
2259
2260     return;
2261 }
2262
2263
2264 /*
2265  * re-written to use an Image structure for XPM support
2266  *
2267  * djhjr - 5/17/98
2268  */
2269 #ifdef ORIGINAL_PIXMAPS
2270 void SetHighlightPixmap (filename)
2271     char *filename;
2272 {
2273     Pixmap pm = GetBitmap (filename);
2274
2275     if (pm) {
2276         if (Scr->hilitePm) {
2277             XFreePixmap (dpy, Scr->hilitePm);
2278         }
2279         Scr->hilitePm = pm;
2280         Scr->hilite_pm_width = JunkWidth;
2281         Scr->hilite_pm_height = JunkHeight;
2282     }
2283 }
2284 #else /* ORIGINAL_PIXMAPS */
2285 void SetHighlightPixmap (filename)
2286     char *filename;
2287 {
2288         /* added this 'if (...) else' - djhjr - 10/25/02 */
2289         if (filename[0] == ':')
2290                 Scr->hiliteName = filename;
2291         else
2292
2293         if (!Scr->hilitePm) Scr->hilitePm = SetPixmapsPixmap(filename);
2294 }
2295 #endif /* ORIGINAL_PIXMAPS */
2296
2297
2298 void FetchWmProtocols (tmp)
2299     TwmWindow *tmp;
2300 {
2301     unsigned long flags = 0L;
2302     Atom *protocols = NULL;
2303     int n;
2304
2305     if (XGetWMProtocols (dpy, tmp->w, &protocols, &n)) {
2306         register int i;
2307         register Atom *ap;
2308
2309         for (i = 0, ap = protocols; i < n; i++, ap++) {
2310             if (*ap == _XA_WM_TAKE_FOCUS) flags |= DoesWmTakeFocus;
2311             if (*ap == _XA_WM_SAVE_YOURSELF) flags |= DoesWmSaveYourself;
2312             if (*ap == _XA_WM_DELETE_WINDOW) flags |= DoesWmDeleteWindow;
2313         }
2314         if (protocols) XFree ((char *) protocols);
2315     }
2316     tmp->protocols = flags;
2317 }
2318
2319 TwmColormap *
2320 CreateTwmColormap(c)
2321     Colormap c;
2322 {
2323     TwmColormap *cmap;
2324     cmap = (TwmColormap *) malloc(sizeof(TwmColormap));
2325     if (!cmap ||
2326         XSaveContext(dpy, c, ColormapContext, (caddr_t) cmap)) {
2327         if (cmap) free((char *) cmap);
2328         return (NULL);
2329     }
2330     cmap->c = c;
2331     cmap->state = 0;
2332     cmap->install_req = 0;
2333     cmap->w = None;
2334     cmap->refcnt = 1;
2335     return (cmap);
2336 }
2337
2338 ColormapWindow *
2339 CreateColormapWindow(w, creating_parent, property_window)
2340     Window w;
2341     Bool creating_parent;
2342     Bool property_window;
2343 {
2344     ColormapWindow *cwin;
2345     TwmColormap *cmap;
2346     XWindowAttributes attributes;
2347
2348     cwin = (ColormapWindow *) malloc(sizeof(ColormapWindow));
2349     if (cwin) {
2350         if (!XGetWindowAttributes(dpy, w, &attributes) ||
2351             XSaveContext(dpy, w, ColormapContext, (caddr_t) cwin)) {
2352             free((char *) cwin);
2353             return (NULL);
2354         }
2355
2356         if (XFindContext(dpy, attributes.colormap,  ColormapContext,
2357                 (caddr_t *)&cwin->colormap) == XCNOENT) {
2358             cwin->colormap = cmap = CreateTwmColormap(attributes.colormap);
2359             if (!cmap) {
2360                 XDeleteContext(dpy, w, ColormapContext);
2361                 free((char *) cwin);
2362                 return (NULL);
2363             }
2364         } else {
2365             cwin->colormap->refcnt++;
2366         }
2367
2368         cwin->w = w;
2369         /*
2370          * Assume that windows in colormap list are
2371          * obscured if we are creating the parent window.
2372          * Otherwise, we assume they are unobscured.
2373          */
2374         cwin->visibility = creating_parent ?
2375             VisibilityPartiallyObscured : VisibilityUnobscured;
2376         cwin->refcnt = 1;
2377
2378         /*
2379          * If this is a ColormapWindow property window and we
2380          * are not monitoring ColormapNotify or VisibilityNotify
2381          * events, we need to.
2382          */
2383         if (property_window &&
2384             (attributes.your_event_mask &
2385                 (ColormapChangeMask|VisibilityChangeMask)) !=
2386                     (ColormapChangeMask|VisibilityChangeMask)) {
2387             XSelectInput(dpy, w, attributes.your_event_mask |
2388                 (ColormapChangeMask|VisibilityChangeMask));
2389         }
2390     }
2391
2392     return (cwin);
2393 }
2394
2395 void FetchWmColormapWindows (tmp)
2396     TwmWindow *tmp;
2397 {
2398     register int i, j;
2399     Window *cmap_windows = NULL;
2400     Bool can_free_cmap_windows = False;
2401     int number_cmap_windows = 0;
2402     ColormapWindow **cwins = NULL;
2403     int previously_installed;
2404     extern void free_cwins();
2405
2406     number_cmap_windows = 0;
2407
2408     if ((previously_installed =
2409        (Scr->cmapInfo.cmaps == &tmp->cmaps) && tmp->cmaps.number_cwins)) {
2410         cwins = tmp->cmaps.cwins;
2411         for (i = 0; i < tmp->cmaps.number_cwins; i++)
2412             cwins[i]->colormap->state = 0;
2413     }
2414
2415     if (XGetWMColormapWindows (dpy, tmp->w, &cmap_windows,
2416                                &number_cmap_windows) &&
2417         number_cmap_windows > 0) {
2418
2419         can_free_cmap_windows = False;
2420         /*
2421          * check if the top level is in the list, add to front if not
2422          */
2423         for (i = 0; i < number_cmap_windows; i++) {
2424             if (cmap_windows[i] == tmp->w) break;
2425         }
2426         if (i == number_cmap_windows) {  /* not in list */
2427             Window *new_cmap_windows =
2428               (Window *) malloc (sizeof(Window) * (number_cmap_windows + 1));
2429
2430             if (!new_cmap_windows) {
2431                 fprintf (stderr,
2432                          "%s:  unable to allocate %d element colormap window array\n",
2433                         ProgramName, number_cmap_windows+1);
2434                 goto done;
2435             }
2436             new_cmap_windows[0] = tmp->w;  /* add to front */
2437             for (i = 0; i < number_cmap_windows; i++) {  /* append rest */
2438                 new_cmap_windows[i+1] = cmap_windows[i];
2439             }
2440             XFree ((char *) cmap_windows);
2441             can_free_cmap_windows = True;  /* do not use XFree any more */
2442             cmap_windows = new_cmap_windows;
2443             number_cmap_windows++;
2444         }
2445
2446         cwins = (ColormapWindow **) malloc(sizeof(ColormapWindow *) *
2447                 number_cmap_windows);
2448         if (cwins) {
2449             for (i = 0; i < number_cmap_windows; i++) {
2450
2451                 /*
2452                  * Copy any existing entries into new list.
2453                  */
2454                 for (j = 0; j < tmp->cmaps.number_cwins; j++) {
2455                     if (tmp->cmaps.cwins[j]->w == cmap_windows[i]) {
2456                         cwins[i] = tmp->cmaps.cwins[j];
2457                         cwins[i]->refcnt++;
2458                         break;
2459                     }
2460                 }
2461
2462                 /*
2463                  * If the colormap window is not being pointed by
2464                  * some other applications colormap window list,
2465                  * create a new entry.
2466                  */
2467                 if (j == tmp->cmaps.number_cwins) {
2468                     if (XFindContext(dpy, cmap_windows[i], ColormapContext,
2469                                      (caddr_t *)&cwins[i]) == XCNOENT) {
2470                         if ((cwins[i] = CreateColormapWindow(cmap_windows[i],
2471                                     (Bool) tmp->cmaps.number_cwins == 0,
2472                                     True)) == NULL) {
2473                             int k;
2474                             for (k = i + 1; k < number_cmap_windows; k++)
2475                                 cmap_windows[k-1] = cmap_windows[k];
2476                             i--;
2477                             number_cmap_windows--;
2478                         }
2479                     } else
2480                         cwins[i]->refcnt++;
2481                 }
2482             }
2483         }
2484     }
2485
2486     /* No else here, in case we bailed out of clause above.
2487      */
2488     if (number_cmap_windows == 0) {
2489
2490         number_cmap_windows = 1;
2491
2492         cwins = (ColormapWindow **) malloc(sizeof(ColormapWindow *));
2493         if (XFindContext(dpy, tmp->w, ColormapContext, (caddr_t *)&cwins[0]) ==
2494                 XCNOENT)
2495             cwins[0] = CreateColormapWindow(tmp->w,
2496                             (Bool) tmp->cmaps.number_cwins == 0, False);
2497         else
2498             cwins[0]->refcnt++;
2499     }
2500
2501     if (tmp->cmaps.number_cwins)
2502         free_cwins(tmp);
2503
2504     tmp->cmaps.cwins = cwins;
2505     tmp->cmaps.number_cwins = number_cmap_windows;
2506     if (number_cmap_windows > 1)
2507         tmp->cmaps.scoreboard =
2508           (char *) calloc(1, ColormapsScoreboardLength(&tmp->cmaps));
2509
2510     if (previously_installed)
2511         InstallWindowColormaps(PropertyNotify, (TwmWindow *) NULL);
2512
2513   done:
2514     if (cmap_windows) {
2515         if (can_free_cmap_windows)
2516           free ((char *) cmap_windows);
2517         else
2518           XFree ((char *) cmap_windows);
2519     }
2520
2521     return;
2522 }
2523
2524
2525 void GetWindowSizeHints (tmp)
2526     TwmWindow *tmp;
2527 {
2528     long supplied = 0;
2529
2530     if (!XGetWMNormalHints (dpy, tmp->w, &tmp->hints, &supplied))
2531       tmp->hints.flags = 0;
2532
2533     if (tmp->hints.flags & PResizeInc) {
2534         if (tmp->hints.width_inc == 0) tmp->hints.width_inc = 1;
2535         if (tmp->hints.height_inc == 0) tmp->hints.height_inc = 1;
2536     }
2537
2538     if (!(supplied & PWinGravity) && (tmp->hints.flags & USPosition)) {
2539         static int gravs[] = { SouthEastGravity, SouthWestGravity,
2540                                NorthEastGravity, NorthWestGravity };
2541         int right =  tmp->attr.x + tmp->attr.width + 2 * tmp->old_bw;
2542         int bottom = tmp->attr.y + tmp->attr.height + 2 * tmp->old_bw;
2543
2544 /* djhjr - 4/19/96
2545         tmp->hints.win_gravity =
2546           gravs[((Scr->MyDisplayHeight - bottom < tmp->title_height) ? 0 : 2) |
2547                 ((Scr->MyDisplayWidth - right   < tmp->title_height) ? 0 : 1)];
2548 */
2549         tmp->hints.win_gravity = 
2550           gravs[((Scr->MyDisplayHeight - bottom <
2551                 tmp->title_height + 2 * tmp->frame_bw3D) ? 0 : 2) |
2552                 ((Scr->MyDisplayWidth - right   <
2553                 tmp->title_height + 2 * tmp->frame_bw3D) ? 0 : 1)];
2554
2555         tmp->hints.flags |= PWinGravity;
2556     }
2557 }
2558