/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkwinwm.c
ViewVC logotype

Diff of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkwinwm.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 69 by dashley, Sat Nov 5 10:54:17 2016 UTC revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
1  /* $Header$ */  /* $Header$ */
2    
3  /*  /*
4   * tkWinWm.c --   * tkWinWm.c --
5   *   *
6   *      This module takes care of the interactions between a Tk-based   *      This module takes care of the interactions between a Tk-based
7   *      application and the window manager.  Among other things, it   *      application and the window manager.  Among other things, it
8   *      implements the "wm" command and passes geometry information   *      implements the "wm" command and passes geometry information
9   *      to the window manager.   *      to the window manager.
10   *   *
11   * Copyright (c) 1995-1997 Sun Microsystems, Inc.   * Copyright (c) 1995-1997 Sun Microsystems, Inc.
12   * Copyright (c) 1998-2000 by Scriptics Corporation.   * Copyright (c) 1998-2000 by Scriptics Corporation.
13   *   *
14   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
15   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16   *   *
17   * RCS: @(#) $Id: tkwinwm.c,v 1.2 2002/01/28 13:42:22 dtashley Exp $   * RCS: @(#) $Id: tkwinwm.c,v 1.2 2002/01/28 13:42:22 dtashley Exp $
18   */   */
19    
20  #include "resource.h"  #include "resource.h"
21     /* Necessary for LoadIcon() to work after port from Scriptics.     /* Necessary for LoadIcon() to work after port from Scriptics.
22     */     */
23    
24  #include "tkWinInt.h"  #include "tkWinInt.h"
25    
26  /*  /*
27   * Event structure for synthetic activation events.  These events are   * Event structure for synthetic activation events.  These events are
28   * placed on the event queue whenever a toplevel gets a WM_MOUSEACTIVATE   * placed on the event queue whenever a toplevel gets a WM_MOUSEACTIVATE
29   * message.   * message.
30   */   */
31    
32  typedef struct ActivateEvent {  typedef struct ActivateEvent {
33      Tcl_Event ev;      Tcl_Event ev;
34      TkWindow *winPtr;      TkWindow *winPtr;
35  } ActivateEvent;  } ActivateEvent;
36    
37  /*  /*
38   * A data structure of the following type holds information for   * A data structure of the following type holds information for
39   * each window manager protocol (such as WM_DELETE_WINDOW) for   * each window manager protocol (such as WM_DELETE_WINDOW) for
40   * which a handler (i.e. a Tcl command) has been defined for a   * which a handler (i.e. a Tcl command) has been defined for a
41   * particular top-level window.   * particular top-level window.
42   */   */
43    
44  typedef struct ProtocolHandler {  typedef struct ProtocolHandler {
45      Atom protocol;              /* Identifies the protocol. */      Atom protocol;              /* Identifies the protocol. */
46      struct ProtocolHandler *nextPtr;      struct ProtocolHandler *nextPtr;
47                                  /* Next in list of protocol handlers for                                  /* Next in list of protocol handlers for
48                                   * the same top-level window, or NULL for                                   * the same top-level window, or NULL for
49                                   * end of list. */                                   * end of list. */
50      Tcl_Interp *interp;         /* Interpreter in which to invoke command. */      Tcl_Interp *interp;         /* Interpreter in which to invoke command. */
51      char command[4];            /* Tcl command to invoke when a client      char command[4];            /* Tcl command to invoke when a client
52                                   * message for this protocol arrives.                                   * message for this protocol arrives.
53                                   * The actual size of the structure varies                                   * The actual size of the structure varies
54                                   * to accommodate the needs of the actual                                   * to accommodate the needs of the actual
55                                   * command. THIS MUST BE THE LAST FIELD OF                                   * command. THIS MUST BE THE LAST FIELD OF
56                                   * THE STRUCTURE. */                                   * THE STRUCTURE. */
57  } ProtocolHandler;  } ProtocolHandler;
58    
59  #define HANDLER_SIZE(cmdLength) \  #define HANDLER_SIZE(cmdLength) \
60      ((unsigned) (sizeof(ProtocolHandler) - 3 + cmdLength))      ((unsigned) (sizeof(ProtocolHandler) - 3 + cmdLength))
61    
62  /*  /*
63   * A data structure of the following type holds window-manager-related   * A data structure of the following type holds window-manager-related
64   * information for each top-level window in an application.   * information for each top-level window in an application.
65   */   */
66    
67  typedef struct TkWmInfo {  typedef struct TkWmInfo {
68      TkWindow *winPtr;           /* Pointer to main Tk information for      TkWindow *winPtr;           /* Pointer to main Tk information for
69                                   * this window. */                                   * this window. */
70      HWND wrapper;               /* This is the decorative frame window      HWND wrapper;               /* This is the decorative frame window
71                                   * created by the window manager to wrap                                   * created by the window manager to wrap
72                                   * a toplevel window.  This window is                                   * a toplevel window.  This window is
73                                   * a direct child of the root window. */                                   * a direct child of the root window. */
74      Tk_Uid titleUid;            /* Title to display in window caption.  If      Tk_Uid titleUid;            /* Title to display in window caption.  If
75                                   * NULL, use name of widget. */                                   * NULL, use name of widget. */
76      Tk_Uid iconName;            /* Name to display in icon. */      Tk_Uid iconName;            /* Name to display in icon. */
77      TkWindow *masterPtr;        /* Master window for TRANSIENT_FOR property,      TkWindow *masterPtr;        /* Master window for TRANSIENT_FOR property,
78                                   * or NULL. */                                   * or NULL. */
79      XWMHints hints;             /* Various pieces of information for      XWMHints hints;             /* Various pieces of information for
80                                   * window manager. */                                   * window manager. */
81      char *leaderName;           /* Path name of leader of window group      char *leaderName;           /* Path name of leader of window group
82                                   * (corresponds to hints.window_group).                                   * (corresponds to hints.window_group).
83                                   * Malloc-ed. Note:  this field doesn't                                   * Malloc-ed. Note:  this field doesn't
84                                   * get updated if leader is destroyed. */                                   * get updated if leader is destroyed. */
85      Tk_Window icon;             /* Window to use as icon for this window,      Tk_Window icon;             /* Window to use as icon for this window,
86                                   * or NULL. */                                   * or NULL. */
87      Tk_Window iconFor;          /* Window for which this window is icon, or      Tk_Window iconFor;          /* Window for which this window is icon, or
88                                   * NULL if this isn't an icon for anyone. */                                   * NULL if this isn't an icon for anyone. */
89    
90      /*      /*
91       * Information used to construct an XSizeHints structure for       * Information used to construct an XSizeHints structure for
92       * the window manager:       * the window manager:
93       */       */
94    
95      int defMinWidth, defMinHeight, defMaxWidth, defMaxHeight;      int defMinWidth, defMinHeight, defMaxWidth, defMaxHeight;
96                                  /* Default resize limits given by system. */                                  /* Default resize limits given by system. */
97      int sizeHintsFlags;         /* Flags word for XSizeHints structure.      int sizeHintsFlags;         /* Flags word for XSizeHints structure.
98                                   * If the PBaseSize flag is set then the                                   * If the PBaseSize flag is set then the
99                                   * window is gridded;  otherwise it isn't                                   * window is gridded;  otherwise it isn't
100                                   * gridded. */                                   * gridded. */
101      int minWidth, minHeight;    /* Minimum dimensions of window, in      int minWidth, minHeight;    /* Minimum dimensions of window, in
102                                   * grid units, not pixels. */                                   * grid units, not pixels. */
103      int maxWidth, maxHeight;    /* Maximum dimensions of window, in      int maxWidth, maxHeight;    /* Maximum dimensions of window, in
104                                   * grid units, not pixels, or 0 to default. */                                   * grid units, not pixels, or 0 to default. */
105      Tk_Window gridWin;          /* Identifies the window that controls      Tk_Window gridWin;          /* Identifies the window that controls
106                                   * gridding for this top-level, or NULL if                                   * gridding for this top-level, or NULL if
107                                   * the top-level isn't currently gridded. */                                   * the top-level isn't currently gridded. */
108      int widthInc, heightInc;    /* Increments for size changes (# pixels      int widthInc, heightInc;    /* Increments for size changes (# pixels
109                                   * per step). */                                   * per step). */
110      struct {      struct {
111          int x;  /* numerator */          int x;  /* numerator */
112          int y;  /* denominator */          int y;  /* denominator */
113      } minAspect, maxAspect;     /* Min/max aspect ratios for window. */      } minAspect, maxAspect;     /* Min/max aspect ratios for window. */
114      int reqGridWidth, reqGridHeight;      int reqGridWidth, reqGridHeight;
115                                  /* The dimensions of the window (in                                  /* The dimensions of the window (in
116                                   * grid units) requested through                                   * grid units) requested through
117                                   * the geometry manager. */                                   * the geometry manager. */
118      int gravity;                /* Desired window gravity. */      int gravity;                /* Desired window gravity. */
119    
120      /*      /*
121       * Information used to manage the size and location of a window.       * Information used to manage the size and location of a window.
122       */       */
123    
124      int width, height;          /* Desired dimensions of window, specified      int width, height;          /* Desired dimensions of window, specified
125                                   * in grid units.  These values are                                   * in grid units.  These values are
126                                   * set by the "wm geometry" command and by                                   * set by the "wm geometry" command and by
127                                   * ConfigureNotify events (for when wm                                   * ConfigureNotify events (for when wm
128                                   * resizes window).  -1 means user hasn't                                   * resizes window).  -1 means user hasn't
129                                   * requested dimensions. */                                   * requested dimensions. */
130      int x, y;                   /* Desired X and Y coordinates for window.      int x, y;                   /* Desired X and Y coordinates for window.
131                                   * These values are set by "wm geometry",                                   * These values are set by "wm geometry",
132                                   * plus by ConfigureNotify events (when wm                                   * plus by ConfigureNotify events (when wm
133                                   * moves window).  These numbers are                                   * moves window).  These numbers are
134                                   * different than the numbers stored in                                   * different than the numbers stored in
135                                   * winPtr->changes because (a) they could be                                   * winPtr->changes because (a) they could be
136                                   * measured from the right or bottom edge                                   * measured from the right or bottom edge
137                                   * of the screen (see WM_NEGATIVE_X and                                   * of the screen (see WM_NEGATIVE_X and
138                                   * WM_NEGATIVE_Y flags) and (b) if the window                                   * WM_NEGATIVE_Y flags) and (b) if the window
139                                   * has been reparented then they refer to the                                   * has been reparented then they refer to the
140                                   * parent rather than the window itself. */                                   * parent rather than the window itself. */
141      int borderWidth, borderHeight;      int borderWidth, borderHeight;
142                                  /* Width and height of window dressing, in                                  /* Width and height of window dressing, in
143                                   * pixels for the current style/exStyle.  This                                   * pixels for the current style/exStyle.  This
144                                   * includes the border on both sides of the                                   * includes the border on both sides of the
145                                   * window. */                                   * window. */
146      int configWidth, configHeight;      int configWidth, configHeight;
147                                  /* Dimensions passed to last request that we                                  /* Dimensions passed to last request that we
148                                   * issued to change geometry of window.  Used                                   * issued to change geometry of window.  Used
149                                   * to eliminate redundant resize operations. */                                   * to eliminate redundant resize operations. */
150      HMENU hMenu;                /* the hMenu associated with this menu */      HMENU hMenu;                /* the hMenu associated with this menu */
151      DWORD style, exStyle;       /* Style flags for the wrapper window. */      DWORD style, exStyle;       /* Style flags for the wrapper window. */
152    
153      /*      /*
154       * List of children of the toplevel which have private colormaps.       * List of children of the toplevel which have private colormaps.
155       */       */
156    
157      TkWindow **cmapList;        /* Array of window with private colormaps. */      TkWindow **cmapList;        /* Array of window with private colormaps. */
158      int cmapCount;              /* Number of windows in array. */      int cmapCount;              /* Number of windows in array. */
159    
160      /*      /*
161       * Miscellaneous information.       * Miscellaneous information.
162       */       */
163    
164      ProtocolHandler *protPtr;   /* First in list of protocol handlers for      ProtocolHandler *protPtr;   /* First in list of protocol handlers for
165                                   * this window (NULL means none). */                                   * this window (NULL means none). */
166      int cmdArgc;                /* Number of elements in cmdArgv below. */      int cmdArgc;                /* Number of elements in cmdArgv below. */
167      char **cmdArgv;             /* Array of strings to store in the      char **cmdArgv;             /* Array of strings to store in the
168                                   * WM_COMMAND property.  NULL means nothing                                   * WM_COMMAND property.  NULL means nothing
169                                   * available. */                                   * available. */
170      char *clientMachine;        /* String to store in WM_CLIENT_MACHINE      char *clientMachine;        /* String to store in WM_CLIENT_MACHINE
171                                   * property, or NULL. */                                   * property, or NULL. */
172      int flags;                  /* Miscellaneous flags, defined below. */      int flags;                  /* Miscellaneous flags, defined below. */
173      int numTransients;          /* number of transients on this window */      int numTransients;          /* number of transients on this window */
174      struct TkWmInfo *nextPtr;   /* Next in list of all top-level windows. */      struct TkWmInfo *nextPtr;   /* Next in list of all top-level windows. */
175  } WmInfo;  } WmInfo;
176    
177  /*  /*
178   * Flag values for WmInfo structures:   * Flag values for WmInfo structures:
179   *   *
180   * WM_NEVER_MAPPED -            non-zero means window has never been   * WM_NEVER_MAPPED -            non-zero means window has never been
181   *                              mapped;  need to update all info when   *                              mapped;  need to update all info when
182   *                              window is first mapped.   *                              window is first mapped.
183   * WM_UPDATE_PENDING -          non-zero means a call to UpdateGeometryInfo   * WM_UPDATE_PENDING -          non-zero means a call to UpdateGeometryInfo
184   *                              has already been scheduled for this   *                              has already been scheduled for this
185   *                              window;  no need to schedule another one.   *                              window;  no need to schedule another one.
186   * WM_NEGATIVE_X -              non-zero means x-coordinate is measured in   * WM_NEGATIVE_X -              non-zero means x-coordinate is measured in
187   *                              pixels from right edge of screen, rather   *                              pixels from right edge of screen, rather
188   *                              than from left edge.   *                              than from left edge.
189   * WM_NEGATIVE_Y -              non-zero means y-coordinate is measured in   * WM_NEGATIVE_Y -              non-zero means y-coordinate is measured in
190   *                              pixels up from bottom of screen, rather than   *                              pixels up from bottom of screen, rather than
191   *                              down from top.   *                              down from top.
192   * WM_UPDATE_SIZE_HINTS -       non-zero means that new size hints need to be   * WM_UPDATE_SIZE_HINTS -       non-zero means that new size hints need to be
193   *                              propagated to window manager. Not used on Win.   *                              propagated to window manager. Not used on Win.
194   * WM_SYNC_PENDING -            set to non-zero while waiting for the window   * WM_SYNC_PENDING -            set to non-zero while waiting for the window
195   *                              manager to respond to some state change.   *                              manager to respond to some state change.
196   * WM_MOVE_PENDING -            non-zero means the application has requested   * WM_MOVE_PENDING -            non-zero means the application has requested
197   *                              a new position for the window, but it hasn't   *                              a new position for the window, but it hasn't
198   *                              been reflected through the window manager   *                              been reflected through the window manager
199   *                              yet.   *                              yet.
200   * WM_COLORAMPS_EXPLICIT -      non-zero means the colormap windows were   * WM_COLORAMPS_EXPLICIT -      non-zero means the colormap windows were
201   *                              set explicitly via "wm colormapwindows".   *                              set explicitly via "wm colormapwindows".
202   * WM_ADDED_TOPLEVEL_COLORMAP - non-zero means that when "wm colormapwindows"   * WM_ADDED_TOPLEVEL_COLORMAP - non-zero means that when "wm colormapwindows"
203   *                              was called the top-level itself wasn't   *                              was called the top-level itself wasn't
204   *                              specified, so we added it implicitly at   *                              specified, so we added it implicitly at
205   *                              the end of the list.   *                              the end of the list.
206   */   */
207    
208  #define WM_NEVER_MAPPED                 (1<<0)  #define WM_NEVER_MAPPED                 (1<<0)
209  #define WM_UPDATE_PENDING               (1<<1)  #define WM_UPDATE_PENDING               (1<<1)
210  #define WM_NEGATIVE_X                   (1<<2)  #define WM_NEGATIVE_X                   (1<<2)
211  #define WM_NEGATIVE_Y                   (1<<3)  #define WM_NEGATIVE_Y                   (1<<3)
212  #define WM_UPDATE_SIZE_HINTS            (1<<4)  #define WM_UPDATE_SIZE_HINTS            (1<<4)
213  #define WM_SYNC_PENDING                 (1<<5)  #define WM_SYNC_PENDING                 (1<<5)
214  #define WM_CREATE_PENDING               (1<<6)  #define WM_CREATE_PENDING               (1<<6)
215  #define WM_MOVE_PENDING                 (1<<7)  #define WM_MOVE_PENDING                 (1<<7)
216  #define WM_COLORMAPS_EXPLICIT           (1<<8)  #define WM_COLORMAPS_EXPLICIT           (1<<8)
217  #define WM_ADDED_TOPLEVEL_COLORMAP      (1<<9)  #define WM_ADDED_TOPLEVEL_COLORMAP      (1<<9)
218  #define WM_WIDTH_NOT_RESIZABLE          (1<<10)  #define WM_WIDTH_NOT_RESIZABLE          (1<<10)
219  #define WM_HEIGHT_NOT_RESIZABLE         (1<<11)  #define WM_HEIGHT_NOT_RESIZABLE         (1<<11)
220    
221  /*  /*
222   * Window styles for various types of toplevel windows.   * Window styles for various types of toplevel windows.
223   */   */
224    
225  #define WM_OVERRIDE_STYLE (WS_POPUP|WS_CLIPCHILDREN|CS_DBLCLKS)  #define WM_OVERRIDE_STYLE (WS_POPUP|WS_CLIPCHILDREN|CS_DBLCLKS)
226  #define EX_OVERRIDE_STYLE (WS_EX_TOOLWINDOW)  #define EX_OVERRIDE_STYLE (WS_EX_TOOLWINDOW)
227    
228  #define WM_TOPLEVEL_STYLE (WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|CS_DBLCLKS)  #define WM_TOPLEVEL_STYLE (WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|CS_DBLCLKS)
229  #define EX_TOPLEVEL_STYLE (0)  #define EX_TOPLEVEL_STYLE (0)
230    
231  #define WM_TRANSIENT_STYLE \  #define WM_TRANSIENT_STYLE \
232                  (WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS|CS_DBLCLKS)                  (WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS|CS_DBLCLKS)
233  #define EX_TRANSIENT_STYLE \  #define EX_TRANSIENT_STYLE \
234                  (WS_EX_TOOLWINDOW|WS_EX_DLGMODALFRAME)                  (WS_EX_TOOLWINDOW|WS_EX_DLGMODALFRAME)
235    
236  /*  /*
237   * The following structure is the official type record for geometry   * The following structure is the official type record for geometry
238   * management of top-level windows.   * management of top-level windows.
239   */   */
240    
241  static void             TopLevelReqProc(ClientData dummy, Tk_Window tkwin);  static void             TopLevelReqProc(ClientData dummy, Tk_Window tkwin);
242    
243  static Tk_GeomMgr wmMgrType = {  static Tk_GeomMgr wmMgrType = {
244      "wm",                               /* name */      "wm",                               /* name */
245      TopLevelReqProc,                    /* requestProc */      TopLevelReqProc,                    /* requestProc */
246      (Tk_GeomLostSlaveProc *) NULL,      /* lostSlaveProc */      (Tk_GeomLostSlaveProc *) NULL,      /* lostSlaveProc */
247  };  };
248    
249  typedef struct ThreadSpecificData {  typedef struct ThreadSpecificData {
250      HPALETTE systemPalette;      /* System palette; refers to the      HPALETTE systemPalette;      /* System palette; refers to the
251                                    * currently installed foreground logical                                    * currently installed foreground logical
252                                    * palette. */                                    * palette. */
253      TkWindow *createWindow;      /* Window that is being constructed.  This      TkWindow *createWindow;      /* Window that is being constructed.  This
254                                    * value is set immediately before a                                    * value is set immediately before a
255                                    * call to CreateWindowEx, and is used                                    * call to CreateWindowEx, and is used
256                                    * by SetLimits.  This is a gross hack                                    * by SetLimits.  This is a gross hack
257                                    * needed to work around Windows brain                                    * needed to work around Windows brain
258                                    * damage where it sends the                                    * damage where it sends the
259                                    * WM_GETMINMAXINFO message before the                                    * WM_GETMINMAXINFO message before the
260                                    * WM_CREATE window. */                                    * WM_CREATE window. */
261      int initialized;             /* Flag indicating whether thread-      int initialized;             /* Flag indicating whether thread-
262                                    * specific elements of module have                                    * specific elements of module have
263                                    * been initialized. */                                    * been initialized. */
264      int firstWindow;             /* Flag, cleared when the first window      int firstWindow;             /* Flag, cleared when the first window
265                                    * is mapped in a non-iconic state. */                                    * is mapped in a non-iconic state. */
266  } ThreadSpecificData;  } ThreadSpecificData;
267  static Tcl_ThreadDataKey dataKey;  static Tcl_ThreadDataKey dataKey;
268    
269  /*  /*
270   * The following variables cannot be placed in thread local storage   * The following variables cannot be placed in thread local storage
271   * because they must be shared across threads.   * because they must be shared across threads.
272   */   */
273    
274  static WNDCLASS toplevelClass; /* Class for toplevel windows. */  static WNDCLASS toplevelClass; /* Class for toplevel windows. */
275  static int initialized;        /* Flag indicating whether module has  static int initialized;        /* Flag indicating whether module has
276                                  * been initialized. */                                  * been initialized. */
277  TCL_DECLARE_MUTEX(winWmMutex)  TCL_DECLARE_MUTEX(winWmMutex)
278    
279    
280  /*  /*
281   * Forward declarations for procedures defined in this file:   * Forward declarations for procedures defined in this file:
282   */   */
283    
284  static int              ActivateWindow _ANSI_ARGS_((Tcl_Event *evPtr,  static int              ActivateWindow _ANSI_ARGS_((Tcl_Event *evPtr,
285                              int flags));                              int flags));
286  static void             ConfigureEvent _ANSI_ARGS_((TkWindow *winPtr,  static void             ConfigureEvent _ANSI_ARGS_((TkWindow *winPtr,
287                              XConfigureEvent *eventPtr));                              XConfigureEvent *eventPtr));
288  static void             ConfigureTopLevel _ANSI_ARGS_((WINDOWPOS *pos));  static void             ConfigureTopLevel _ANSI_ARGS_((WINDOWPOS *pos));
289  static void             GenerateConfigureNotify _ANSI_ARGS_((  static void             GenerateConfigureNotify _ANSI_ARGS_((
290                              TkWindow *winPtr));                              TkWindow *winPtr));
291  static void             GetMaxSize _ANSI_ARGS_((WmInfo *wmPtr,  static void             GetMaxSize _ANSI_ARGS_((WmInfo *wmPtr,
292                              int *maxWidthPtr, int *maxHeightPtr));                              int *maxWidthPtr, int *maxHeightPtr));
293  static void             GetMinSize _ANSI_ARGS_((WmInfo *wmPtr,  static void             GetMinSize _ANSI_ARGS_((WmInfo *wmPtr,
294                              int *minWidthPtr, int *minHeightPtr));                              int *minWidthPtr, int *minHeightPtr));
295  static TkWindow *       GetTopLevel _ANSI_ARGS_((HWND hwnd));  static TkWindow *       GetTopLevel _ANSI_ARGS_((HWND hwnd));
296  static void             InitWm _ANSI_ARGS_((void));  static void             InitWm _ANSI_ARGS_((void));
297  static int              InstallColormaps _ANSI_ARGS_((HWND hwnd, int message,  static int              InstallColormaps _ANSI_ARGS_((HWND hwnd, int message,
298                              int isForemost));                              int isForemost));
299  static void             InvalidateSubTree _ANSI_ARGS_((TkWindow *winPtr,  static void             InvalidateSubTree _ANSI_ARGS_((TkWindow *winPtr,
300                              Colormap colormap));                              Colormap colormap));
301  static int              ParseGeometry _ANSI_ARGS_((Tcl_Interp *interp,  static int              ParseGeometry _ANSI_ARGS_((Tcl_Interp *interp,
302                              char *string, TkWindow *winPtr));                              char *string, TkWindow *winPtr));
303  static void             RaiseWinWhenIdle _ANSI_ARGS_((  static void             RaiseWinWhenIdle _ANSI_ARGS_((
304                              ClientData clientData));                              ClientData clientData));
305  static void             RefreshColormap _ANSI_ARGS_((Colormap colormap,  static void             RefreshColormap _ANSI_ARGS_((Colormap colormap,
306                              TkDisplay *dispPtr));                              TkDisplay *dispPtr));
307  static void             SetLimits _ANSI_ARGS_((HWND hwnd, MINMAXINFO *info));  static void             SetLimits _ANSI_ARGS_((HWND hwnd, MINMAXINFO *info));
308  static LRESULT CALLBACK TopLevelProc _ANSI_ARGS_((HWND hwnd, UINT message,  static LRESULT CALLBACK TopLevelProc _ANSI_ARGS_((HWND hwnd, UINT message,
309                              WPARAM wParam, LPARAM lParam));                              WPARAM wParam, LPARAM lParam));
310  static void             TopLevelEventProc _ANSI_ARGS_((ClientData clientData,  static void             TopLevelEventProc _ANSI_ARGS_((ClientData clientData,
311                              XEvent *eventPtr));                              XEvent *eventPtr));
312  static void             TopLevelReqProc _ANSI_ARGS_((ClientData dummy,  static void             TopLevelReqProc _ANSI_ARGS_((ClientData dummy,
313                              Tk_Window tkwin));                              Tk_Window tkwin));
314  static void             UpdateGeometryInfo _ANSI_ARGS_((  static void             UpdateGeometryInfo _ANSI_ARGS_((
315                              ClientData clientData));                              ClientData clientData));
316  static void             UpdateWrapper _ANSI_ARGS_((TkWindow *winPtr));  static void             UpdateWrapper _ANSI_ARGS_((TkWindow *winPtr));
317  static LRESULT CALLBACK WmProc _ANSI_ARGS_((HWND hwnd, UINT message,  static LRESULT CALLBACK WmProc _ANSI_ARGS_((HWND hwnd, UINT message,
318                              WPARAM wParam, LPARAM lParam));                              WPARAM wParam, LPARAM lParam));
319  static void             WmWaitVisibilityProc _ANSI_ARGS_((  static void             WmWaitVisibilityProc _ANSI_ARGS_((
320                              ClientData clientData, XEvent *eventPtr));                              ClientData clientData, XEvent *eventPtr));
321    
322  /*  /*
323   *----------------------------------------------------------------------   *----------------------------------------------------------------------
324   *   *
325   * InitWm --   * InitWm --
326   *   *
327   *      This routine creates the Wm toplevel decorative frame class.   *      This routine creates the Wm toplevel decorative frame class.
328   *   *
329   * Results:   * Results:
330   *      None.   *      None.
331   *   *
332   * Side effects:   * Side effects:
333   *      Registers a new window class.   *      Registers a new window class.
334   *   *
335   *----------------------------------------------------------------------   *----------------------------------------------------------------------
336   */   */
337    
338  static void  static void
339  InitWm(void)  InitWm(void)
340  {  {
341      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
342              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
343      WNDCLASS * classPtr;      WNDCLASS * classPtr;
344    
345      if (! tsdPtr->initialized) {      if (! tsdPtr->initialized) {
346          tsdPtr->initialized = 1;          tsdPtr->initialized = 1;
347          tsdPtr->firstWindow = 1;          tsdPtr->firstWindow = 1;
348      }      }
349      if (! initialized) {      if (! initialized) {
350          Tcl_MutexLock(&winWmMutex);          Tcl_MutexLock(&winWmMutex);
351          if (! initialized) {          if (! initialized) {
352              initialized = 1;              initialized = 1;
353              classPtr = &toplevelClass;              classPtr = &toplevelClass;
354    
355      /*      /*
356       * When threads are enabled, we cannot use CLASSDC because       * When threads are enabled, we cannot use CLASSDC because
357       * threads will then write into the same device context.       * threads will then write into the same device context.
358       *       *
359       * This is a hack; we should add a subsystem that manages       * This is a hack; we should add a subsystem that manages
360       * device context on a per-thread basis.  See also tkWinX.c,       * device context on a per-thread basis.  See also tkWinX.c,
361       * which also initializes a WNDCLASS structure.       * which also initializes a WNDCLASS structure.
362       */       */
363    
364  #ifdef TCL_THREADS  #ifdef TCL_THREADS
365              classPtr->style = CS_HREDRAW | CS_VREDRAW;              classPtr->style = CS_HREDRAW | CS_VREDRAW;
366  #else  #else
367              classPtr->style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC;              classPtr->style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC;
368  #endif  #endif
369              classPtr->cbClsExtra = 0;              classPtr->cbClsExtra = 0;
370              classPtr->cbWndExtra = 0;              classPtr->cbWndExtra = 0;
371              classPtr->hInstance = Tk_GetHINSTANCE();              classPtr->hInstance = Tk_GetHINSTANCE();
372              classPtr->hbrBackground = NULL;              classPtr->hbrBackground = NULL;
373              classPtr->lpszMenuName = NULL;              classPtr->lpszMenuName = NULL;
374              classPtr->lpszClassName = TK_WIN_TOPLEVEL_CLASS_NAME;              classPtr->lpszClassName = TK_WIN_TOPLEVEL_CLASS_NAME;
375              classPtr->lpfnWndProc = WmProc;              classPtr->lpfnWndProc = WmProc;
376              classPtr->hIcon = LoadIcon(Tk_GetHINSTANCE(), (const char *)IDI_EGC);              classPtr->hIcon = LoadIcon(Tk_GetHINSTANCE(), (const char *)IDI_EGC);
377            /* Needed to change line above to work reliably with GUI build after            /* Needed to change line above to work reliably with GUI build after
378            ** port from Scriptics code.  Old line was:              ** port from Scriptics code.  Old line was:  
379            ** classPtr->hIcon = LoadIcon(Tk_GetHINSTANCE(), "tk");            ** classPtr->hIcon = LoadIcon(Tk_GetHINSTANCE(), "tk");
380            */            */
381              classPtr->hCursor = LoadCursor(NULL, IDC_ARROW);              classPtr->hCursor = LoadCursor(NULL, IDC_ARROW);
382    
383              if (!RegisterClass(classPtr)) {              if (!RegisterClass(classPtr)) {
384                  panic("Unable to register TkTopLevel class");                  panic("Unable to register TkTopLevel class");
385              }              }
386          }          }
387          Tcl_MutexUnlock(&winWmMutex);          Tcl_MutexUnlock(&winWmMutex);
388      }      }
389  }  }
390    
391  /*  /*
392   *----------------------------------------------------------------------   *----------------------------------------------------------------------
393   *   *
394   * GetTopLevel --   * GetTopLevel --
395   *   *
396   *      This function retrieves the TkWindow associated with the   *      This function retrieves the TkWindow associated with the
397   *      given HWND.   *      given HWND.
398   *   *
399   * Results:   * Results:
400   *      Returns the matching TkWindow.   *      Returns the matching TkWindow.
401   *   *
402   * Side effects:   * Side effects:
403   *      None.   *      None.
404   *   *
405   *----------------------------------------------------------------------   *----------------------------------------------------------------------
406   */   */
407    
408  static TkWindow *  static TkWindow *
409  GetTopLevel(hwnd)  GetTopLevel(hwnd)
410      HWND hwnd;      HWND hwnd;
411  {  {
412      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
413              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
414    
415      /*      /*
416       * If this function is called before the CreateWindowEx call       * If this function is called before the CreateWindowEx call
417       * has completed, then the user data slot will not have been       * has completed, then the user data slot will not have been
418       * set yet, so we use the global createWindow variable.       * set yet, so we use the global createWindow variable.
419       */       */
420    
421      if (tsdPtr->createWindow) {      if (tsdPtr->createWindow) {
422          return tsdPtr->createWindow;          return tsdPtr->createWindow;
423      }      }
424      return (TkWindow *) GetWindowLong(hwnd, GWL_USERDATA);      return (TkWindow *) GetWindowLong(hwnd, GWL_USERDATA);
425  }  }
426    
427  /*  /*
428   *----------------------------------------------------------------------   *----------------------------------------------------------------------
429   *   *
430   * SetLimits --   * SetLimits --
431   *   *
432   *      Updates the minimum and maximum window size constraints.   *      Updates the minimum and maximum window size constraints.
433   *   *
434   * Results:   * Results:
435   *      None.   *      None.
436   *   *
437   * Side effects:   * Side effects:
438   *      Changes the values of the info pointer to reflect the current   *      Changes the values of the info pointer to reflect the current
439   *      minimum and maximum size values.   *      minimum and maximum size values.
440   *   *
441   *----------------------------------------------------------------------   *----------------------------------------------------------------------
442   */   */
443    
444  static void  static void
445  SetLimits(hwnd, info)  SetLimits(hwnd, info)
446      HWND hwnd;      HWND hwnd;
447      MINMAXINFO *info;      MINMAXINFO *info;
448  {  {
449      register WmInfo *wmPtr;      register WmInfo *wmPtr;
450      int maxWidth, maxHeight;      int maxWidth, maxHeight;
451      int minWidth, minHeight;      int minWidth, minHeight;
452      int base;      int base;
453      TkWindow *winPtr = GetTopLevel(hwnd);      TkWindow *winPtr = GetTopLevel(hwnd);
454    
455      if (winPtr == NULL) {      if (winPtr == NULL) {
456          return;          return;
457      }      }
458    
459      wmPtr = winPtr->wmInfoPtr;      wmPtr = winPtr->wmInfoPtr;
460            
461      /*      /*
462       * Copy latest constraint info.       * Copy latest constraint info.
463       */       */
464    
465      wmPtr->defMinWidth = info->ptMinTrackSize.x;      wmPtr->defMinWidth = info->ptMinTrackSize.x;
466      wmPtr->defMinHeight = info->ptMinTrackSize.y;      wmPtr->defMinHeight = info->ptMinTrackSize.y;
467      wmPtr->defMaxWidth = info->ptMaxTrackSize.x;      wmPtr->defMaxWidth = info->ptMaxTrackSize.x;
468      wmPtr->defMaxHeight = info->ptMaxTrackSize.y;      wmPtr->defMaxHeight = info->ptMaxTrackSize.y;
469            
470      GetMaxSize(wmPtr, &maxWidth, &maxHeight);      GetMaxSize(wmPtr, &maxWidth, &maxHeight);
471      GetMinSize(wmPtr, &minWidth, &minHeight);      GetMinSize(wmPtr, &minWidth, &minHeight);
472    
473      if (wmPtr->gridWin != NULL) {      if (wmPtr->gridWin != NULL) {
474          base = winPtr->reqWidth - (wmPtr->reqGridWidth * wmPtr->widthInc);          base = winPtr->reqWidth - (wmPtr->reqGridWidth * wmPtr->widthInc);
475          if (base < 0) {          if (base < 0) {
476              base = 0;              base = 0;
477          }          }
478          base += wmPtr->borderWidth;          base += wmPtr->borderWidth;
479          info->ptMinTrackSize.x = base + (minWidth * wmPtr->widthInc);          info->ptMinTrackSize.x = base + (minWidth * wmPtr->widthInc);
480          info->ptMaxTrackSize.x = base + (maxWidth * wmPtr->widthInc);          info->ptMaxTrackSize.x = base + (maxWidth * wmPtr->widthInc);
481    
482          base = winPtr->reqHeight - (wmPtr->reqGridHeight * wmPtr->heightInc);          base = winPtr->reqHeight - (wmPtr->reqGridHeight * wmPtr->heightInc);
483          if (base < 0) {          if (base < 0) {
484              base = 0;              base = 0;
485          }          }
486          base += wmPtr->borderHeight;          base += wmPtr->borderHeight;
487          info->ptMinTrackSize.y = base + (minHeight * wmPtr->heightInc);          info->ptMinTrackSize.y = base + (minHeight * wmPtr->heightInc);
488          info->ptMaxTrackSize.y = base + (maxHeight * wmPtr->heightInc);          info->ptMaxTrackSize.y = base + (maxHeight * wmPtr->heightInc);
489      } else {      } else {
490          info->ptMaxTrackSize.x = maxWidth + wmPtr->borderWidth;          info->ptMaxTrackSize.x = maxWidth + wmPtr->borderWidth;
491          info->ptMaxTrackSize.y = maxHeight + wmPtr->borderHeight;          info->ptMaxTrackSize.y = maxHeight + wmPtr->borderHeight;
492          info->ptMinTrackSize.x = minWidth + wmPtr->borderWidth;          info->ptMinTrackSize.x = minWidth + wmPtr->borderWidth;
493          info->ptMinTrackSize.y = minHeight + wmPtr->borderHeight;          info->ptMinTrackSize.y = minHeight + wmPtr->borderHeight;
494      }      }
495    
496      /*      /*
497       * If the window isn't supposed to be resizable, then set the       * If the window isn't supposed to be resizable, then set the
498       * minimum and maximum dimensions to be the same as the current size.       * minimum and maximum dimensions to be the same as the current size.
499       */       */
500    
501      if (!(wmPtr->flags & WM_SYNC_PENDING)) {      if (!(wmPtr->flags & WM_SYNC_PENDING)) {
502          if (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) {          if (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) {
503              info->ptMinTrackSize.x = winPtr->changes.width              info->ptMinTrackSize.x = winPtr->changes.width
504                  + wmPtr->borderWidth;                  + wmPtr->borderWidth;
505              info->ptMaxTrackSize.x = info->ptMinTrackSize.x;              info->ptMaxTrackSize.x = info->ptMinTrackSize.x;
506          }          }
507          if (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {          if (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {
508              info->ptMinTrackSize.y = winPtr->changes.height              info->ptMinTrackSize.y = winPtr->changes.height
509                  + wmPtr->borderHeight;                  + wmPtr->borderHeight;
510              info->ptMaxTrackSize.y = info->ptMinTrackSize.y;              info->ptMaxTrackSize.y = info->ptMinTrackSize.y;
511          }          }
512      }      }
513  }  }
514    
515  /*  /*
516   *----------------------------------------------------------------------   *----------------------------------------------------------------------
517   *   *
518   * TkWinWmCleanup --   * TkWinWmCleanup --
519   *   *
520   *      Unregisters classes registered by the window manager. This is   *      Unregisters classes registered by the window manager. This is
521   *      called from the DLL main entry point when the DLL is unloaded.   *      called from the DLL main entry point when the DLL is unloaded.
522   *   *
523   * Results:   * Results:
524   *      None.   *      None.
525   *   *
526   * Side effects:   * Side effects:
527   *      The window classes are discarded.   *      The window classes are discarded.
528   *   *
529   *----------------------------------------------------------------------   *----------------------------------------------------------------------
530   */   */
531    
532  void  void
533  TkWinWmCleanup(hInstance)  TkWinWmCleanup(hInstance)
534      HINSTANCE hInstance;      HINSTANCE hInstance;
535  {  {
536      ThreadSpecificData *tsdPtr;      ThreadSpecificData *tsdPtr;
537    
538      /*      /*
539       * If we're using stubs to access the Tcl library, and they       * If we're using stubs to access the Tcl library, and they
540       * haven't been initialized, we can't call Tcl_GetThreadData.       * haven't been initialized, we can't call Tcl_GetThreadData.
541       */       */
542    
543  #ifdef USE_TCL_STUBS  #ifdef USE_TCL_STUBS
544      if (tclStubsPtr == NULL) {      if (tclStubsPtr == NULL) {
545          return;          return;
546      }      }
547  #endif  #endif
548    
549      tsdPtr = (ThreadSpecificData *)      tsdPtr = (ThreadSpecificData *)
550              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
551    
552      if (!tsdPtr->initialized) {      if (!tsdPtr->initialized) {
553          return;          return;
554      }      }
555      tsdPtr->initialized = 0;      tsdPtr->initialized = 0;
556            
557      UnregisterClass(TK_WIN_TOPLEVEL_CLASS_NAME, hInstance);      UnregisterClass(TK_WIN_TOPLEVEL_CLASS_NAME, hInstance);
558  }  }
559    
560  /*  /*
561   *--------------------------------------------------------------   *--------------------------------------------------------------
562   *   *
563   * TkWmNewWindow --   * TkWmNewWindow --
564   *   *
565   *      This procedure is invoked whenever a new top-level   *      This procedure is invoked whenever a new top-level
566   *      window is created.  Its job is to initialize the WmInfo   *      window is created.  Its job is to initialize the WmInfo
567   *      structure for the window.   *      structure for the window.
568   *   *
569   * Results:   * Results:
570   *      None.   *      None.
571   *   *
572   * Side effects:   * Side effects:
573   *      A WmInfo structure gets allocated and initialized.   *      A WmInfo structure gets allocated and initialized.
574   *   *
575   *--------------------------------------------------------------   *--------------------------------------------------------------
576   */   */
577    
578  void  void
579  TkWmNewWindow(winPtr)  TkWmNewWindow(winPtr)
580      TkWindow *winPtr;           /* Newly-created top-level window. */      TkWindow *winPtr;           /* Newly-created top-level window. */
581  {  {
582      register WmInfo *wmPtr;      register WmInfo *wmPtr;
583    
584      wmPtr = (WmInfo *) ckalloc(sizeof(WmInfo));      wmPtr = (WmInfo *) ckalloc(sizeof(WmInfo));
585      winPtr->wmInfoPtr = wmPtr;      winPtr->wmInfoPtr = wmPtr;
586      wmPtr->winPtr = winPtr;      wmPtr->winPtr = winPtr;
587      wmPtr->wrapper = NULL;      wmPtr->wrapper = NULL;
588      wmPtr->titleUid = NULL;      wmPtr->titleUid = NULL;
589      wmPtr->iconName = NULL;      wmPtr->iconName = NULL;
590      wmPtr->masterPtr = NULL;      wmPtr->masterPtr = NULL;
591      wmPtr->hints.flags = InputHint | StateHint;      wmPtr->hints.flags = InputHint | StateHint;
592      wmPtr->hints.input = True;      wmPtr->hints.input = True;
593      wmPtr->hints.initial_state = NormalState;      wmPtr->hints.initial_state = NormalState;
594      wmPtr->hints.icon_pixmap = None;      wmPtr->hints.icon_pixmap = None;
595      wmPtr->hints.icon_window = None;      wmPtr->hints.icon_window = None;
596      wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;      wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;
597      wmPtr->hints.icon_mask = None;      wmPtr->hints.icon_mask = None;
598      wmPtr->hints.window_group = None;      wmPtr->hints.window_group = None;
599      wmPtr->leaderName = NULL;      wmPtr->leaderName = NULL;
600      wmPtr->icon = NULL;      wmPtr->icon = NULL;
601      wmPtr->iconFor = NULL;      wmPtr->iconFor = NULL;
602      wmPtr->sizeHintsFlags = 0;      wmPtr->sizeHintsFlags = 0;
603    
604      /*      /*
605       * Default the maximum dimensions to the size of the display.       * Default the maximum dimensions to the size of the display.
606       */       */
607    
608      wmPtr->defMinWidth = wmPtr->defMinHeight = 0;      wmPtr->defMinWidth = wmPtr->defMinHeight = 0;
609      wmPtr->defMaxWidth = DisplayWidth(winPtr->display,      wmPtr->defMaxWidth = DisplayWidth(winPtr->display,
610              winPtr->screenNum);              winPtr->screenNum);
611      wmPtr->defMaxHeight = DisplayHeight(winPtr->display,      wmPtr->defMaxHeight = DisplayHeight(winPtr->display,
612              winPtr->screenNum);              winPtr->screenNum);
613      wmPtr->minWidth = wmPtr->minHeight = 1;      wmPtr->minWidth = wmPtr->minHeight = 1;
614      wmPtr->maxWidth = wmPtr->maxHeight = 0;      wmPtr->maxWidth = wmPtr->maxHeight = 0;
615      wmPtr->gridWin = NULL;      wmPtr->gridWin = NULL;
616      wmPtr->widthInc = wmPtr->heightInc = 1;      wmPtr->widthInc = wmPtr->heightInc = 1;
617      wmPtr->minAspect.x = wmPtr->minAspect.y = 1;      wmPtr->minAspect.x = wmPtr->minAspect.y = 1;
618      wmPtr->maxAspect.x = wmPtr->maxAspect.y = 1;      wmPtr->maxAspect.x = wmPtr->maxAspect.y = 1;
619      wmPtr->reqGridWidth = wmPtr->reqGridHeight = -1;      wmPtr->reqGridWidth = wmPtr->reqGridHeight = -1;
620      wmPtr->gravity = NorthWestGravity;      wmPtr->gravity = NorthWestGravity;
621      wmPtr->width = -1;      wmPtr->width = -1;
622      wmPtr->height = -1;      wmPtr->height = -1;
623      wmPtr->hMenu = NULL;      wmPtr->hMenu = NULL;
624      wmPtr->x = winPtr->changes.x;      wmPtr->x = winPtr->changes.x;
625      wmPtr->y = winPtr->changes.y;      wmPtr->y = winPtr->changes.y;
626      wmPtr->borderWidth = 0;      wmPtr->borderWidth = 0;
627      wmPtr->borderHeight = 0;      wmPtr->borderHeight = 0;
628            
629      wmPtr->cmapList = NULL;      wmPtr->cmapList = NULL;
630      wmPtr->cmapCount = 0;      wmPtr->cmapCount = 0;
631      wmPtr->numTransients = 0;      wmPtr->numTransients = 0;
632    
633      wmPtr->configWidth = -1;      wmPtr->configWidth = -1;
634      wmPtr->configHeight = -1;      wmPtr->configHeight = -1;
635      wmPtr->protPtr = NULL;      wmPtr->protPtr = NULL;
636      wmPtr->cmdArgv = NULL;      wmPtr->cmdArgv = NULL;
637      wmPtr->clientMachine = NULL;      wmPtr->clientMachine = NULL;
638      wmPtr->flags = WM_NEVER_MAPPED;      wmPtr->flags = WM_NEVER_MAPPED;
639      wmPtr->nextPtr = winPtr->dispPtr->firstWmPtr;      wmPtr->nextPtr = winPtr->dispPtr->firstWmPtr;
640      winPtr->dispPtr->firstWmPtr = wmPtr;      winPtr->dispPtr->firstWmPtr = wmPtr;
641    
642      /*      /*
643       * Tk must monitor structure events for top-level windows, in order       * Tk must monitor structure events for top-level windows, in order
644       * to detect size and position changes caused by window managers.       * to detect size and position changes caused by window managers.
645       */       */
646    
647      Tk_CreateEventHandler((Tk_Window) winPtr, StructureNotifyMask,      Tk_CreateEventHandler((Tk_Window) winPtr, StructureNotifyMask,
648              TopLevelEventProc, (ClientData) winPtr);              TopLevelEventProc, (ClientData) winPtr);
649    
650      /*      /*
651       * Arrange for geometry requests to be reflected from the window       * Arrange for geometry requests to be reflected from the window
652       * to the window manager.       * to the window manager.
653       */       */
654    
655      Tk_ManageGeometry((Tk_Window) winPtr, &wmMgrType, (ClientData) 0);      Tk_ManageGeometry((Tk_Window) winPtr, &wmMgrType, (ClientData) 0);
656  }  }
657    
658  /*  /*
659   *----------------------------------------------------------------------   *----------------------------------------------------------------------
660   *   *
661   * UpdateWrapper --   * UpdateWrapper --
662   *   *
663   *      This function creates the wrapper window that contains the   *      This function creates the wrapper window that contains the
664   *      window decorations and menus for a toplevel.  This function   *      window decorations and menus for a toplevel.  This function
665   *      may be called after a window is mapped to change the window   *      may be called after a window is mapped to change the window
666   *      style.   *      style.
667   *   *
668   * Results:   * Results:
669   *      None.   *      None.
670   *   *
671   * Side effects:   * Side effects:
672   *      Destroys any old wrapper window and replaces it with a newly   *      Destroys any old wrapper window and replaces it with a newly
673   *      created wrapper.   *      created wrapper.
674   *   *
675   *----------------------------------------------------------------------   *----------------------------------------------------------------------
676   */   */
677    
678  static void  static void
679  UpdateWrapper(winPtr)  UpdateWrapper(winPtr)
680      TkWindow *winPtr;           /* Top-level window to redecorate. */      TkWindow *winPtr;           /* Top-level window to redecorate. */
681  {  {
682      register WmInfo *wmPtr = winPtr->wmInfoPtr;      register WmInfo *wmPtr = winPtr->wmInfoPtr;
683      HWND parentHWND = NULL, oldWrapper;      HWND parentHWND = NULL, oldWrapper;
684      HWND child = TkWinGetHWND(winPtr->window);      HWND child = TkWinGetHWND(winPtr->window);
685      int x, y, width, height, state;      int x, y, width, height, state;
686      WINDOWPLACEMENT place;      WINDOWPLACEMENT place;
687      Tcl_DString titleString;      Tcl_DString titleString;
688      int *childStateInfo = NULL;      int *childStateInfo = NULL;
689      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
690              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
691    
692      parentHWND = NULL;      parentHWND = NULL;
693      child = TkWinGetHWND(winPtr->window);      child = TkWinGetHWND(winPtr->window);
694    
695      if (winPtr->flags & TK_EMBEDDED) {      if (winPtr->flags & TK_EMBEDDED) {
696          wmPtr->wrapper = (HWND) winPtr->privatePtr;          wmPtr->wrapper = (HWND) winPtr->privatePtr;
697          if (wmPtr->wrapper == NULL) {          if (wmPtr->wrapper == NULL) {
698              panic("TkWmMapWindow: Cannot find container window");              panic("TkWmMapWindow: Cannot find container window");
699          }          }
700          if (!IsWindow(wmPtr->wrapper)) {          if (!IsWindow(wmPtr->wrapper)) {
701              panic("TkWmMapWindow: Container was destroyed");              panic("TkWmMapWindow: Container was destroyed");
702          }          }
703    
704      } else {      } else {
705          /*          /*
706           * Pick the decorative frame style.  Override redirect windows get           * Pick the decorative frame style.  Override redirect windows get
707           * created as undecorated popups.  Transient windows get a modal           * created as undecorated popups.  Transient windows get a modal
708           * dialog frame.  Neither override, nor transient windows appear in           * dialog frame.  Neither override, nor transient windows appear in
709           * the Windows taskbar.  Note that a transient window does not resize           * the Windows taskbar.  Note that a transient window does not resize
710           * by default, so we need to explicitly add the WS_THICKFRAME style           * by default, so we need to explicitly add the WS_THICKFRAME style
711           * if we want it to be resizeable.           * if we want it to be resizeable.
712           */           */
713    
714          if (winPtr->atts.override_redirect) {          if (winPtr->atts.override_redirect) {
715              wmPtr->style = WM_OVERRIDE_STYLE;              wmPtr->style = WM_OVERRIDE_STYLE;
716              wmPtr->exStyle = EX_OVERRIDE_STYLE;              wmPtr->exStyle = EX_OVERRIDE_STYLE;
717          } else if (wmPtr->masterPtr) {          } else if (wmPtr->masterPtr) {
718              wmPtr->style = WM_TRANSIENT_STYLE;              wmPtr->style = WM_TRANSIENT_STYLE;
719              wmPtr->exStyle = EX_TRANSIENT_STYLE;              wmPtr->exStyle = EX_TRANSIENT_STYLE;
720              parentHWND = Tk_GetHWND(Tk_WindowId(wmPtr->masterPtr));              parentHWND = Tk_GetHWND(Tk_WindowId(wmPtr->masterPtr));
721              if (! ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) &&              if (! ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) &&
722                      (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE))) {                      (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE))) {
723                  wmPtr->style |= WS_THICKFRAME;                  wmPtr->style |= WS_THICKFRAME;
724              }              }
725          } else {          } else {
726              wmPtr->style = WM_TOPLEVEL_STYLE;              wmPtr->style = WM_TOPLEVEL_STYLE;
727              wmPtr->exStyle = EX_TOPLEVEL_STYLE;              wmPtr->exStyle = EX_TOPLEVEL_STYLE;
728          }          }
729    
730          if ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE)          if ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE)
731                  && (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)) {                  && (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)) {
732              wmPtr->style &= ~ (WS_MAXIMIZEBOX | WS_SIZEBOX);              wmPtr->style &= ~ (WS_MAXIMIZEBOX | WS_SIZEBOX);
733          }          }
734    
735          /*          /*
736           * Compute the geometry of the parent and child windows.           * Compute the geometry of the parent and child windows.
737           */           */
738    
739          wmPtr->flags |= WM_CREATE_PENDING|WM_MOVE_PENDING;          wmPtr->flags |= WM_CREATE_PENDING|WM_MOVE_PENDING;
740          UpdateGeometryInfo((ClientData)winPtr);          UpdateGeometryInfo((ClientData)winPtr);
741          wmPtr->flags &= ~(WM_CREATE_PENDING|WM_MOVE_PENDING);          wmPtr->flags &= ~(WM_CREATE_PENDING|WM_MOVE_PENDING);
742    
743          width = wmPtr->borderWidth + winPtr->changes.width;          width = wmPtr->borderWidth + winPtr->changes.width;
744          height = wmPtr->borderHeight + winPtr->changes.height;          height = wmPtr->borderHeight + winPtr->changes.height;
745    
746          /*          /*
747           * Set the initial position from the user or program specified           * Set the initial position from the user or program specified
748           * location.  If nothing has been specified, then let the system           * location.  If nothing has been specified, then let the system
749           * pick a location.           * pick a location.
750           */           */
751    
752          if (!(wmPtr->sizeHintsFlags & (USPosition | PPosition))          if (!(wmPtr->sizeHintsFlags & (USPosition | PPosition))
753                  && (wmPtr->flags & WM_NEVER_MAPPED)) {                  && (wmPtr->flags & WM_NEVER_MAPPED)) {
754              x = CW_USEDEFAULT;              x = CW_USEDEFAULT;
755              y = CW_USEDEFAULT;              y = CW_USEDEFAULT;
756          } else {          } else {
757              x = winPtr->changes.x;              x = winPtr->changes.x;
758              y = winPtr->changes.y;              y = winPtr->changes.y;
759          }          }
760    
761          /*          /*
762           * Create the containing window, and set the user data to point           * Create the containing window, and set the user data to point
763           * to the TkWindow.           * to the TkWindow.
764           */           */
765    
766          tsdPtr->createWindow = winPtr;          tsdPtr->createWindow = winPtr;
767          Tcl_UtfToExternalDString(NULL, wmPtr->titleUid, -1, &titleString);          Tcl_UtfToExternalDString(NULL, wmPtr->titleUid, -1, &titleString);
768          wmPtr->wrapper = CreateWindowEx(wmPtr->exStyle,          wmPtr->wrapper = CreateWindowEx(wmPtr->exStyle,
769                  TK_WIN_TOPLEVEL_CLASS_NAME,                  TK_WIN_TOPLEVEL_CLASS_NAME,
770                  Tcl_DStringValue(&titleString), wmPtr->style, x, y, width,                  Tcl_DStringValue(&titleString), wmPtr->style, x, y, width,
771                  height, parentHWND, NULL, Tk_GetHINSTANCE(), NULL);                  height, parentHWND, NULL, Tk_GetHINSTANCE(), NULL);
772          Tcl_DStringFree(&titleString);          Tcl_DStringFree(&titleString);
773          SetWindowLong(wmPtr->wrapper, GWL_USERDATA, (LONG) winPtr);          SetWindowLong(wmPtr->wrapper, GWL_USERDATA, (LONG) winPtr);
774          tsdPtr->createWindow = NULL;          tsdPtr->createWindow = NULL;
775    
776          place.length = sizeof(WINDOWPLACEMENT);          place.length = sizeof(WINDOWPLACEMENT);
777          GetWindowPlacement(wmPtr->wrapper, &place);          GetWindowPlacement(wmPtr->wrapper, &place);
778          wmPtr->x = place.rcNormalPosition.left;          wmPtr->x = place.rcNormalPosition.left;
779          wmPtr->y = place.rcNormalPosition.top;          wmPtr->y = place.rcNormalPosition.top;
780    
781          TkInstallFrameMenu((Tk_Window) winPtr);          TkInstallFrameMenu((Tk_Window) winPtr);
782      }      }
783    
784      /*      /*
785       * Now we need to reparent the contained window and set its       * Now we need to reparent the contained window and set its
786       * style appropriately.  Be sure to update the style first so that       * style appropriately.  Be sure to update the style first so that
787       * Windows doesn't try to set the focus to the child window.       * Windows doesn't try to set the focus to the child window.
788       */       */
789    
790      SetWindowLong(child, GWL_STYLE,      SetWindowLong(child, GWL_STYLE,
791              WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);              WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
792      if (winPtr->flags & TK_EMBEDDED) {      if (winPtr->flags & TK_EMBEDDED) {
793          SetWindowLong(child, GWL_WNDPROC, (LONG) TopLevelProc);          SetWindowLong(child, GWL_WNDPROC, (LONG) TopLevelProc);
794      }      }
795      oldWrapper = SetParent(child, wmPtr->wrapper);      oldWrapper = SetParent(child, wmPtr->wrapper);
796      if (oldWrapper && (oldWrapper != wmPtr->wrapper)      if (oldWrapper && (oldWrapper != wmPtr->wrapper)
797              && (oldWrapper != GetDesktopWindow())) {              && (oldWrapper != GetDesktopWindow())) {
798          SetWindowLong(oldWrapper, GWL_USERDATA, (LONG) NULL);          SetWindowLong(oldWrapper, GWL_USERDATA, (LONG) NULL);
799    
800          if (wmPtr->numTransients > 0) {          if (wmPtr->numTransients > 0) {
801              /*              /*
802               * Unset the current wrapper as the parent for all transient               * Unset the current wrapper as the parent for all transient
803               * children for whom this is the master               * children for whom this is the master
804               */               */
805              WmInfo *wmPtr2;              WmInfo *wmPtr2;
806    
807              childStateInfo = (int *)ckalloc((unsigned) wmPtr->numTransients              childStateInfo = (int *)ckalloc((unsigned) wmPtr->numTransients
808                  * sizeof(int));                  * sizeof(int));
809              state = 0;              state = 0;
810              for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;              for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;
811                   wmPtr2 = wmPtr2->nextPtr) {                   wmPtr2 = wmPtr2->nextPtr) {
812                  if (wmPtr2->masterPtr == winPtr) {                  if (wmPtr2->masterPtr == winPtr) {
813                      if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {                      if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
814                          childStateInfo[state++] = wmPtr2->hints.initial_state;                          childStateInfo[state++] = wmPtr2->hints.initial_state;
815                          SetParent(TkWinGetHWND(wmPtr2->winPtr->window), NULL);                          SetParent(TkWinGetHWND(wmPtr2->winPtr->window), NULL);
816                      }                      }
817                  }                  }
818              }              }
819          }          }
820          /*          /*
821           * Remove the menubar before destroying the window so the menubar           * Remove the menubar before destroying the window so the menubar
822           * isn't destroyed.           * isn't destroyed.
823           */           */
824    
825          SetMenu(oldWrapper, NULL);          SetMenu(oldWrapper, NULL);
826          DestroyWindow(oldWrapper);          DestroyWindow(oldWrapper);
827      }      }
828    
829      wmPtr->flags &= ~WM_NEVER_MAPPED;      wmPtr->flags &= ~WM_NEVER_MAPPED;
830      SendMessage(wmPtr->wrapper, TK_ATTACHWINDOW, (WPARAM) child, 0);      SendMessage(wmPtr->wrapper, TK_ATTACHWINDOW, (WPARAM) child, 0);
831    
832      /*      /*
833       * Force an initial transition from withdrawn to the real       * Force an initial transition from withdrawn to the real
834       * initial state.           * initial state.    
835       */       */
836    
837      state = wmPtr->hints.initial_state;      state = wmPtr->hints.initial_state;
838      wmPtr->hints.initial_state = WithdrawnState;      wmPtr->hints.initial_state = WithdrawnState;
839      TkpWmSetState(winPtr, state);      TkpWmSetState(winPtr, state);
840    
841      /*      /*
842       * If we are embedded then force a mapping of the window now,       * If we are embedded then force a mapping of the window now,
843       * because we do not necessarily own the wrapper and may not       * because we do not necessarily own the wrapper and may not
844       * get another opportunity to map ourselves. We should not be       * get another opportunity to map ourselves. We should not be
845       * in either iconified or zoomed states when we get here, so       * in either iconified or zoomed states when we get here, so
846       * it is safe to just check for TK_EMBEDDED without checking       * it is safe to just check for TK_EMBEDDED without checking
847       * what state we are supposed to be in (default to NormalState).       * what state we are supposed to be in (default to NormalState).
848       */       */
849    
850      if (winPtr->flags & TK_EMBEDDED) {      if (winPtr->flags & TK_EMBEDDED) {
851          XMapWindow(winPtr->display, winPtr->window);          XMapWindow(winPtr->display, winPtr->window);
852      }      }
853    
854      /*      /*
855       * Set up menus on the wrapper if required.       * Set up menus on the wrapper if required.
856       */       */
857                    
858      if (wmPtr->hMenu != NULL) {      if (wmPtr->hMenu != NULL) {
859          wmPtr->flags = WM_SYNC_PENDING;          wmPtr->flags = WM_SYNC_PENDING;
860          SetMenu(wmPtr->wrapper, wmPtr->hMenu);          SetMenu(wmPtr->wrapper, wmPtr->hMenu);
861          wmPtr->flags &= ~WM_SYNC_PENDING;          wmPtr->flags &= ~WM_SYNC_PENDING;
862      }      }
863    
864      if (childStateInfo) {      if (childStateInfo) {
865          if (wmPtr->numTransients > 0) {          if (wmPtr->numTransients > 0) {
866              /*              /*
867               * Reset all transient children for whom this is the master               * Reset all transient children for whom this is the master
868               */               */
869              WmInfo *wmPtr2;              WmInfo *wmPtr2;
870    
871              state = 0;              state = 0;
872              for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;              for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;
873                   wmPtr2 = wmPtr2->nextPtr) {                   wmPtr2 = wmPtr2->nextPtr) {
874                  if (wmPtr2->masterPtr == winPtr) {                  if (wmPtr2->masterPtr == winPtr) {
875                      if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {                      if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
876                          UpdateWrapper(wmPtr2->winPtr);                          UpdateWrapper(wmPtr2->winPtr);
877                          TkpWmSetState(wmPtr2->winPtr, childStateInfo[state++]);                          TkpWmSetState(wmPtr2->winPtr, childStateInfo[state++]);
878                      }                      }
879                  }                  }
880              }              }
881          }          }
882    
883          ckfree((char *) childStateInfo);          ckfree((char *) childStateInfo);
884      }      }
885    
886      /*      /*
887       * If this is the first window created by the application, then       * If this is the first window created by the application, then
888       * we should activate the initial window.       * we should activate the initial window.
889       */       */
890    
891      if (tsdPtr->firstWindow) {      if (tsdPtr->firstWindow) {
892          tsdPtr->firstWindow = 0;          tsdPtr->firstWindow = 0;
893          SetActiveWindow(wmPtr->wrapper);          SetActiveWindow(wmPtr->wrapper);
894      }      }
895  }  }
896    
897  /*  /*
898   *--------------------------------------------------------------   *--------------------------------------------------------------
899   *   *
900   * TkWmMapWindow --   * TkWmMapWindow --
901   *   *
902   *      This procedure is invoked to map a top-level window.  This   *      This procedure is invoked to map a top-level window.  This
903   *      module gets a chance to update all window-manager-related   *      module gets a chance to update all window-manager-related
904   *      information in properties before the window manager sees   *      information in properties before the window manager sees
905   *      the map event and checks the properties.  It also gets to   *      the map event and checks the properties.  It also gets to
906   *      decide whether or not to even map the window after all.   *      decide whether or not to even map the window after all.
907   *   *
908   * Results:   * Results:
909   *      None.   *      None.
910   *   *
911   * Side effects:   * Side effects:
912   *      Properties of winPtr may get updated to provide up-to-date   *      Properties of winPtr may get updated to provide up-to-date
913   *      information to the window manager.  The window may also get   *      information to the window manager.  The window may also get
914   *      mapped, but it may not be if this procedure decides that   *      mapped, but it may not be if this procedure decides that
915   *      isn't appropriate (e.g. because the window is withdrawn).   *      isn't appropriate (e.g. because the window is withdrawn).
916   *   *
917   *--------------------------------------------------------------   *--------------------------------------------------------------
918   */   */
919    
920  void  void
921  TkWmMapWindow(winPtr)  TkWmMapWindow(winPtr)
922      TkWindow *winPtr;           /* Top-level window that's about to      TkWindow *winPtr;           /* Top-level window that's about to
923                                   * be mapped. */                                   * be mapped. */
924  {  {
925      register WmInfo *wmPtr = winPtr->wmInfoPtr;      register WmInfo *wmPtr = winPtr->wmInfoPtr;
926      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
927              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
928    
929      if (!tsdPtr->initialized) {      if (!tsdPtr->initialized) {
930          InitWm();          InitWm();
931      }      }
932    
933      if (!(wmPtr->flags & WM_NEVER_MAPPED)) {      if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
934          if (wmPtr->hints.initial_state == WithdrawnState) {          if (wmPtr->hints.initial_state == WithdrawnState) {
935              return;              return;
936          }          }
937    
938          /*          /*
939           * Map the window in either the iconified or normal state.  Note that           * Map the window in either the iconified or normal state.  Note that
940           * we only send a map event if the window is in the normal state.           * we only send a map event if the window is in the normal state.
941           */           */
942    
943          TkpWmSetState(winPtr, wmPtr->hints.initial_state);          TkpWmSetState(winPtr, wmPtr->hints.initial_state);
944      }      }
945    
946      /*      /*
947       * This is the first time this window has ever been mapped.       * This is the first time this window has ever been mapped.
948       * Store all the window-manager-related information for the       * Store all the window-manager-related information for the
949       * window.       * window.
950       */       */
951    
952      if (wmPtr->titleUid == NULL) {      if (wmPtr->titleUid == NULL) {
953          wmPtr->titleUid = winPtr->nameUid;          wmPtr->titleUid = winPtr->nameUid;
954      }      }
955      UpdateWrapper(winPtr);      UpdateWrapper(winPtr);
956  }  }
957    
958  /*  /*
959   *--------------------------------------------------------------   *--------------------------------------------------------------
960   *   *
961   * TkWmUnmapWindow --   * TkWmUnmapWindow --
962   *   *
963   *      This procedure is invoked to unmap a top-level window.  The   *      This procedure is invoked to unmap a top-level window.  The
964   *      only thing it does special is unmap the decorative frame before   *      only thing it does special is unmap the decorative frame before
965   *      unmapping the toplevel window.   *      unmapping the toplevel window.
966   *   *
967   * Results:   * Results:
968   *      None.   *      None.
969   *   *
970   * Side effects:   * Side effects:
971   *      Unmaps the decorative frame and the window.   *      Unmaps the decorative frame and the window.
972   *   *
973   *--------------------------------------------------------------   *--------------------------------------------------------------
974   */   */
975    
976  void  void
977  TkWmUnmapWindow(winPtr)  TkWmUnmapWindow(winPtr)
978      TkWindow *winPtr;           /* Top-level window that's about to      TkWindow *winPtr;           /* Top-level window that's about to
979                                   * be unmapped. */                                   * be unmapped. */
980  {  {
981      TkpWmSetState(winPtr, WithdrawnState);      TkpWmSetState(winPtr, WithdrawnState);
982  }  }
983    
984  /*  /*
985   *----------------------------------------------------------------------   *----------------------------------------------------------------------
986   *   *
987   * TkpWmSetState --   * TkpWmSetState --
988   *   *
989   *      Sets the window manager state for the wrapper window of a   *      Sets the window manager state for the wrapper window of a
990   *      given toplevel window.   *      given toplevel window.
991   *   *
992   * Results:   * Results:
993   *      None.   *      None.
994   *   *
995   * Side effects:   * Side effects:
996   *      May maximize, minimize, restore, or withdraw a window.   *      May maximize, minimize, restore, or withdraw a window.
997   *   *
998   *----------------------------------------------------------------------   *----------------------------------------------------------------------
999   */   */
1000    
1001  void  void
1002  TkpWmSetState(winPtr, state)  TkpWmSetState(winPtr, state)
1003       TkWindow *winPtr;          /* Toplevel window to operate on. */       TkWindow *winPtr;          /* Toplevel window to operate on. */
1004       int state;                 /* One of IconicState, ZoomState, NormalState,       int state;                 /* One of IconicState, ZoomState, NormalState,
1005                                   * or WithdrawnState. */                                   * or WithdrawnState. */
1006  {  {
1007      WmInfo *wmPtr = winPtr->wmInfoPtr;      WmInfo *wmPtr = winPtr->wmInfoPtr;
1008      int cmd;      int cmd;
1009    
1010      if ((wmPtr->flags & WM_NEVER_MAPPED) ||      if ((wmPtr->flags & WM_NEVER_MAPPED) ||
1011              (wmPtr->masterPtr && !Tk_IsMapped(wmPtr->masterPtr))) {              (wmPtr->masterPtr && !Tk_IsMapped(wmPtr->masterPtr))) {
1012          wmPtr->hints.initial_state = state;          wmPtr->hints.initial_state = state;
1013          return;          return;
1014      }      }
1015    
1016      wmPtr->flags |= WM_SYNC_PENDING;      wmPtr->flags |= WM_SYNC_PENDING;
1017      if (state == WithdrawnState) {      if (state == WithdrawnState) {
1018          cmd = SW_HIDE;          cmd = SW_HIDE;
1019      } else if (state == IconicState) {      } else if (state == IconicState) {
1020          cmd = SW_SHOWMINNOACTIVE;          cmd = SW_SHOWMINNOACTIVE;
1021      } else if (state == NormalState) {      } else if (state == NormalState) {
1022          cmd = SW_SHOWNOACTIVATE;          cmd = SW_SHOWNOACTIVATE;
1023      } else if (state == ZoomState) {      } else if (state == ZoomState) {
1024          cmd = SW_SHOWMAXIMIZED;          cmd = SW_SHOWMAXIMIZED;
1025      }      }
1026    
1027      ShowWindow(wmPtr->wrapper, cmd);      ShowWindow(wmPtr->wrapper, cmd);
1028      wmPtr->flags &= ~WM_SYNC_PENDING;      wmPtr->flags &= ~WM_SYNC_PENDING;
1029  }  }
1030    
1031  /*  /*
1032   *--------------------------------------------------------------   *--------------------------------------------------------------
1033   *   *
1034   * TkWmDeadWindow --   * TkWmDeadWindow --
1035   *   *
1036   *      This procedure is invoked when a top-level window is   *      This procedure is invoked when a top-level window is
1037   *      about to be deleted.  It cleans up the wm-related data   *      about to be deleted.  It cleans up the wm-related data
1038   *      structures for the window.   *      structures for the window.
1039   *   *
1040   * Results:   * Results:
1041   *      None.   *      None.
1042   *   *
1043   * Side effects:   * Side effects:
1044   *      The WmInfo structure for winPtr gets freed up.   *      The WmInfo structure for winPtr gets freed up.
1045   *   *
1046   *--------------------------------------------------------------   *--------------------------------------------------------------
1047   */   */
1048    
1049  void  void
1050  TkWmDeadWindow(winPtr)  TkWmDeadWindow(winPtr)
1051      TkWindow *winPtr;           /* Top-level window that's being deleted. */      TkWindow *winPtr;           /* Top-level window that's being deleted. */
1052  {  {
1053      register WmInfo *wmPtr = winPtr->wmInfoPtr;      register WmInfo *wmPtr = winPtr->wmInfoPtr;
1054      WmInfo *wmPtr2;      WmInfo *wmPtr2;
1055    
1056      if (wmPtr == NULL) {      if (wmPtr == NULL) {
1057          return;          return;
1058      }      }
1059    
1060      /*      /*
1061       * Clean up event related window info.       * Clean up event related window info.
1062       */       */
1063    
1064      if (winPtr->dispPtr->firstWmPtr == wmPtr) {      if (winPtr->dispPtr->firstWmPtr == wmPtr) {
1065          winPtr->dispPtr->firstWmPtr = wmPtr->nextPtr;          winPtr->dispPtr->firstWmPtr = wmPtr->nextPtr;
1066      } else {      } else {
1067          register WmInfo *prevPtr;          register WmInfo *prevPtr;
1068          for (prevPtr = winPtr->dispPtr->firstWmPtr; ;          for (prevPtr = winPtr->dispPtr->firstWmPtr; ;
1069               prevPtr = prevPtr->nextPtr) {               prevPtr = prevPtr->nextPtr) {
1070              if (prevPtr == NULL) {              if (prevPtr == NULL) {
1071                  panic("couldn't unlink window in TkWmDeadWindow");                  panic("couldn't unlink window in TkWmDeadWindow");
1072              }              }
1073              if (prevPtr->nextPtr == wmPtr) {              if (prevPtr->nextPtr == wmPtr) {
1074                  prevPtr->nextPtr = wmPtr->nextPtr;                  prevPtr->nextPtr = wmPtr->nextPtr;
1075                  break;                  break;
1076              }              }
1077          }          }
1078      }      }
1079    
1080      /*      /*
1081       * Reset all transient windows whose master is the dead window.       * Reset all transient windows whose master is the dead window.
1082       */       */
1083    
1084      for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;      for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;
1085           wmPtr2 = wmPtr2->nextPtr) {           wmPtr2 = wmPtr2->nextPtr) {
1086          if (wmPtr2->masterPtr == winPtr) {          if (wmPtr2->masterPtr == winPtr) {
1087              wmPtr2->masterPtr = NULL;              wmPtr2->masterPtr = NULL;
1088              if ((wmPtr2->wrapper != None)              if ((wmPtr2->wrapper != None)
1089                      && !(wmPtr2->flags & (WM_NEVER_MAPPED))) {                      && !(wmPtr2->flags & (WM_NEVER_MAPPED))) {
1090                  UpdateWrapper(wmPtr2->winPtr);                  UpdateWrapper(wmPtr2->winPtr);
1091              }              }
1092          }          }
1093      }      }
1094            
1095      if (wmPtr->hints.flags & IconPixmapHint) {      if (wmPtr->hints.flags & IconPixmapHint) {
1096          Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);          Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
1097      }      }
1098      if (wmPtr->hints.flags & IconMaskHint) {      if (wmPtr->hints.flags & IconMaskHint) {
1099          Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);          Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);
1100      }      }
1101      if (wmPtr->leaderName != NULL) {      if (wmPtr->leaderName != NULL) {
1102          ckfree(wmPtr->leaderName);          ckfree(wmPtr->leaderName);
1103      }      }
1104      if (wmPtr->icon != NULL) {      if (wmPtr->icon != NULL) {
1105          wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;          wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
1106          wmPtr2->iconFor = NULL;          wmPtr2->iconFor = NULL;
1107      }      }
1108      if (wmPtr->iconFor != NULL) {      if (wmPtr->iconFor != NULL) {
1109          wmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr;          wmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr;
1110          wmPtr2->icon = NULL;          wmPtr2->icon = NULL;
1111          wmPtr2->hints.flags &= ~IconWindowHint;          wmPtr2->hints.flags &= ~IconWindowHint;
1112      }      }
1113      while (wmPtr->protPtr != NULL) {      while (wmPtr->protPtr != NULL) {
1114          ProtocolHandler *protPtr;          ProtocolHandler *protPtr;
1115    
1116          protPtr = wmPtr->protPtr;          protPtr = wmPtr->protPtr;
1117          wmPtr->protPtr = protPtr->nextPtr;          wmPtr->protPtr = protPtr->nextPtr;
1118          Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC);          Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC);
1119      }      }
1120      if (wmPtr->cmdArgv != NULL) {      if (wmPtr->cmdArgv != NULL) {
1121          ckfree((char *) wmPtr->cmdArgv);          ckfree((char *) wmPtr->cmdArgv);
1122      }      }
1123      if (wmPtr->clientMachine != NULL) {      if (wmPtr->clientMachine != NULL) {
1124          ckfree((char *) wmPtr->clientMachine);          ckfree((char *) wmPtr->clientMachine);
1125      }      }
1126      if (wmPtr->flags & WM_UPDATE_PENDING) {      if (wmPtr->flags & WM_UPDATE_PENDING) {
1127          Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);          Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
1128      }      }
1129      if (wmPtr->masterPtr != NULL) {      if (wmPtr->masterPtr != NULL) {
1130          wmPtr2 = wmPtr->masterPtr->wmInfoPtr;          wmPtr2 = wmPtr->masterPtr->wmInfoPtr;
1131          /*          /*
1132           * If we had a master, tell them that we aren't tied           * If we had a master, tell them that we aren't tied
1133           * to them anymore           * to them anymore
1134           */           */
1135          if (wmPtr2 != NULL) {          if (wmPtr2 != NULL) {
1136              wmPtr2->numTransients--;              wmPtr2->numTransients--;
1137          }          }
1138          Tk_DeleteEventHandler((Tk_Window) wmPtr->masterPtr,          Tk_DeleteEventHandler((Tk_Window) wmPtr->masterPtr,
1139                  VisibilityChangeMask,                  VisibilityChangeMask,
1140                  WmWaitVisibilityProc, (ClientData) winPtr);                  WmWaitVisibilityProc, (ClientData) winPtr);
1141          wmPtr->masterPtr = NULL;          wmPtr->masterPtr = NULL;
1142      }      }
1143    
1144      /*      /*
1145       * Destroy the decorative frame window.       * Destroy the decorative frame window.
1146       */       */
1147    
1148      if (!(winPtr->flags & TK_EMBEDDED)) {      if (!(winPtr->flags & TK_EMBEDDED)) {
1149          if (wmPtr->wrapper != NULL) {          if (wmPtr->wrapper != NULL) {
1150              DestroyWindow(wmPtr->wrapper);              DestroyWindow(wmPtr->wrapper);
1151          } else {          } else {
1152              DestroyWindow(Tk_GetHWND(winPtr->window));              DestroyWindow(Tk_GetHWND(winPtr->window));
1153          }          }
1154      }      }
1155      ckfree((char *) wmPtr);      ckfree((char *) wmPtr);
1156      winPtr->wmInfoPtr = NULL;      winPtr->wmInfoPtr = NULL;
1157  }  }
1158    
1159  /*  /*
1160   *--------------------------------------------------------------   *--------------------------------------------------------------
1161   *   *
1162   * TkWmSetClass --   * TkWmSetClass --
1163   *   *
1164   *      This procedure is invoked whenever a top-level window's   *      This procedure is invoked whenever a top-level window's
1165   *      class is changed.  If the window has been mapped then this   *      class is changed.  If the window has been mapped then this
1166   *      procedure updates the window manager property for the   *      procedure updates the window manager property for the
1167   *      class.  If the window hasn't been mapped, the update is   *      class.  If the window hasn't been mapped, the update is
1168   *      deferred until just before the first mapping.   *      deferred until just before the first mapping.
1169   *   *
1170   * Results:   * Results:
1171   *      None.   *      None.
1172   *   *
1173   * Side effects:   * Side effects:
1174   *      A window property may get updated.   *      A window property may get updated.
1175   *   *
1176   *--------------------------------------------------------------   *--------------------------------------------------------------
1177   */   */
1178    
1179  void  void
1180  TkWmSetClass(winPtr)  TkWmSetClass(winPtr)
1181      TkWindow *winPtr;           /* Newly-created top-level window. */      TkWindow *winPtr;           /* Newly-created top-level window. */
1182  {  {
1183      return;      return;
1184  }  }
1185    
1186  /*  /*
1187   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1188   *   *
1189   * Tk_WmCmd --   * Tk_WmCmd --
1190   *   *
1191   *      This procedure is invoked to process the "wm" Tcl command.   *      This procedure is invoked to process the "wm" Tcl command.
1192   *      See the user documentation for details on what it does.   *      See the user documentation for details on what it does.
1193   *   *
1194   * Results:   * Results:
1195   *      A standard Tcl result.   *      A standard Tcl result.
1196   *   *
1197   * Side effects:   * Side effects:
1198   *      See the user documentation.   *      See the user documentation.
1199   *   *
1200   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1201   */   */
1202    
1203          /* ARGSUSED */          /* ARGSUSED */
1204  int  int
1205  Tk_WmCmd(clientData, interp, argc, argv)  Tk_WmCmd(clientData, interp, argc, argv)
1206      ClientData clientData;      /* Main window associated with      ClientData clientData;      /* Main window associated with
1207                                   * interpreter. */                                   * interpreter. */
1208      Tcl_Interp *interp;         /* Current interpreter. */      Tcl_Interp *interp;         /* Current interpreter. */
1209      int argc;                   /* Number of arguments. */      int argc;                   /* Number of arguments. */
1210      char **argv;                /* Argument strings. */      char **argv;                /* Argument strings. */
1211  {  {
1212      Tk_Window tkwin = (Tk_Window) clientData;      Tk_Window tkwin = (Tk_Window) clientData;
1213      TkWindow *winPtr = NULL;      TkWindow *winPtr = NULL;
1214      register WmInfo *wmPtr;      register WmInfo *wmPtr;
1215      int c;      int c;
1216      size_t length;      size_t length;
1217      TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;      TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
1218    
1219      if (argc < 2) {      if (argc < 2) {
1220          wrongNumArgs:          wrongNumArgs:
1221          Tcl_AppendResult(interp, "wrong # args: should be \"",          Tcl_AppendResult(interp, "wrong # args: should be \"",
1222                  argv[0], " option window ?arg ...?\"", (char *) NULL);                  argv[0], " option window ?arg ...?\"", (char *) NULL);
1223          return TCL_ERROR;          return TCL_ERROR;
1224      }      }
1225      c = argv[1][0];      c = argv[1][0];
1226      length = strlen(argv[1]);      length = strlen(argv[1]);
1227      if ((c == 't') && (strncmp(argv[1], "tracing", length) == 0)      if ((c == 't') && (strncmp(argv[1], "tracing", length) == 0)
1228              && (length >= 3)) {              && (length >= 3)) {
1229          if ((argc != 2) && (argc != 3)) {          if ((argc != 2) && (argc != 3)) {
1230              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1231                      argv[0], " tracing ?boolean?\"", (char *) NULL);                      argv[0], " tracing ?boolean?\"", (char *) NULL);
1232              return TCL_ERROR;              return TCL_ERROR;
1233          }          }
1234          if (argc == 2) {          if (argc == 2) {
1235              Tcl_SetResult(interp, ((dispPtr->wmTracing) ? "on" : "off"),              Tcl_SetResult(interp, ((dispPtr->wmTracing) ? "on" : "off"),
1236                      TCL_STATIC);                      TCL_STATIC);
1237              return TCL_OK;              return TCL_OK;
1238          }          }
1239          return Tcl_GetBoolean(interp, argv[2], &dispPtr->wmTracing);          return Tcl_GetBoolean(interp, argv[2], &dispPtr->wmTracing);
1240      }      }
1241    
1242      if (argc < 3) {      if (argc < 3) {
1243          goto wrongNumArgs;          goto wrongNumArgs;
1244      }      }
1245      winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2], tkwin);      winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2], tkwin);
1246      if (winPtr == NULL) {      if (winPtr == NULL) {
1247          return TCL_ERROR;          return TCL_ERROR;
1248      }      }
1249      if (!(winPtr->flags & TK_TOP_LEVEL)) {      if (!(winPtr->flags & TK_TOP_LEVEL)) {
1250          Tcl_AppendResult(interp, "window \"", winPtr->pathName,          Tcl_AppendResult(interp, "window \"", winPtr->pathName,
1251                  "\" isn't a top-level window", (char *) NULL);                  "\" isn't a top-level window", (char *) NULL);
1252          return TCL_ERROR;          return TCL_ERROR;
1253      }      }
1254      wmPtr = winPtr->wmInfoPtr;      wmPtr = winPtr->wmInfoPtr;
1255      if ((c == 'a') && (strncmp(argv[1], "aspect", length) == 0)) {      if ((c == 'a') && (strncmp(argv[1], "aspect", length) == 0)) {
1256          int numer1, denom1, numer2, denom2;          int numer1, denom1, numer2, denom2;
1257    
1258          if ((argc != 3) && (argc != 7)) {          if ((argc != 3) && (argc != 7)) {
1259              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1260                      argv[0], " aspect window ?minNumer minDenom ",                      argv[0], " aspect window ?minNumer minDenom ",
1261                      "maxNumer maxDenom?\"", (char *) NULL);                      "maxNumer maxDenom?\"", (char *) NULL);
1262              return TCL_ERROR;              return TCL_ERROR;
1263          }          }
1264          if (argc == 3) {          if (argc == 3) {
1265              if (wmPtr->sizeHintsFlags & PAspect) {              if (wmPtr->sizeHintsFlags & PAspect) {
1266                  char buf[TCL_INTEGER_SPACE * 4];                  char buf[TCL_INTEGER_SPACE * 4];
1267                                    
1268                  sprintf(buf, "%d %d %d %d", wmPtr->minAspect.x,                  sprintf(buf, "%d %d %d %d", wmPtr->minAspect.x,
1269                          wmPtr->minAspect.y, wmPtr->maxAspect.x,                          wmPtr->minAspect.y, wmPtr->maxAspect.x,
1270                          wmPtr->maxAspect.y);                          wmPtr->maxAspect.y);
1271                  Tcl_SetResult(interp, buf, TCL_VOLATILE);                  Tcl_SetResult(interp, buf, TCL_VOLATILE);
1272              }              }
1273              return TCL_OK;              return TCL_OK;
1274          }          }
1275          if (*argv[3] == '\0') {          if (*argv[3] == '\0') {
1276              wmPtr->sizeHintsFlags &= ~PAspect;              wmPtr->sizeHintsFlags &= ~PAspect;
1277          } else {          } else {
1278              if ((Tcl_GetInt(interp, argv[3], &numer1) != TCL_OK)              if ((Tcl_GetInt(interp, argv[3], &numer1) != TCL_OK)
1279                      || (Tcl_GetInt(interp, argv[4], &denom1) != TCL_OK)                      || (Tcl_GetInt(interp, argv[4], &denom1) != TCL_OK)
1280                      || (Tcl_GetInt(interp, argv[5], &numer2) != TCL_OK)                      || (Tcl_GetInt(interp, argv[5], &numer2) != TCL_OK)
1281                      || (Tcl_GetInt(interp, argv[6], &denom2) != TCL_OK)) {                      || (Tcl_GetInt(interp, argv[6], &denom2) != TCL_OK)) {
1282                  return TCL_ERROR;                  return TCL_ERROR;
1283              }              }
1284              if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) ||              if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) ||
1285                      (denom2 <= 0)) {                      (denom2 <= 0)) {
1286                  Tcl_SetResult(interp, "aspect number can't be <= 0",                  Tcl_SetResult(interp, "aspect number can't be <= 0",
1287                          TCL_STATIC);                          TCL_STATIC);
1288                  return TCL_ERROR;                  return TCL_ERROR;
1289              }              }
1290              wmPtr->minAspect.x = numer1;              wmPtr->minAspect.x = numer1;
1291              wmPtr->minAspect.y = denom1;              wmPtr->minAspect.y = denom1;
1292              wmPtr->maxAspect.x = numer2;              wmPtr->maxAspect.x = numer2;
1293              wmPtr->maxAspect.y = denom2;              wmPtr->maxAspect.y = denom2;
1294              wmPtr->sizeHintsFlags |= PAspect;              wmPtr->sizeHintsFlags |= PAspect;
1295          }          }
1296          goto updateGeom;          goto updateGeom;
1297      } else if ((c == 'c') && (strncmp(argv[1], "client", length) == 0)      } else if ((c == 'c') && (strncmp(argv[1], "client", length) == 0)
1298              && (length >= 2)) {              && (length >= 2)) {
1299          if ((argc != 3) && (argc != 4)) {          if ((argc != 3) && (argc != 4)) {
1300              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1301                      argv[0], " client window ?name?\"",                      argv[0], " client window ?name?\"",
1302                      (char *) NULL);                      (char *) NULL);
1303              return TCL_ERROR;              return TCL_ERROR;
1304          }          }
1305          if (argc == 3) {          if (argc == 3) {
1306              if (wmPtr->clientMachine != NULL) {              if (wmPtr->clientMachine != NULL) {
1307                  Tcl_SetResult(interp, wmPtr->clientMachine, TCL_STATIC);                  Tcl_SetResult(interp, wmPtr->clientMachine, TCL_STATIC);
1308              }              }
1309              return TCL_OK;              return TCL_OK;
1310          }          }
1311          if (argv[3][0] == 0) {          if (argv[3][0] == 0) {
1312              if (wmPtr->clientMachine != NULL) {              if (wmPtr->clientMachine != NULL) {
1313                  ckfree((char *) wmPtr->clientMachine);                  ckfree((char *) wmPtr->clientMachine);
1314                  wmPtr->clientMachine = NULL;                  wmPtr->clientMachine = NULL;
1315                  if (!(wmPtr->flags & WM_NEVER_MAPPED)) {                  if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
1316                      XDeleteProperty(winPtr->display, winPtr->window,                      XDeleteProperty(winPtr->display, winPtr->window,
1317                              Tk_InternAtom((Tk_Window) winPtr,                              Tk_InternAtom((Tk_Window) winPtr,
1318                              "WM_CLIENT_MACHINE"));                              "WM_CLIENT_MACHINE"));
1319                  }                  }
1320              }              }
1321              return TCL_OK;              return TCL_OK;
1322          }          }
1323          if (wmPtr->clientMachine != NULL) {          if (wmPtr->clientMachine != NULL) {
1324              ckfree((char *) wmPtr->clientMachine);              ckfree((char *) wmPtr->clientMachine);
1325          }          }
1326          wmPtr->clientMachine = (char *)          wmPtr->clientMachine = (char *)
1327                  ckalloc((unsigned) (strlen(argv[3]) + 1));                  ckalloc((unsigned) (strlen(argv[3]) + 1));
1328          strcpy(wmPtr->clientMachine, argv[3]);          strcpy(wmPtr->clientMachine, argv[3]);
1329          if (!(wmPtr->flags & WM_NEVER_MAPPED)) {          if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
1330              XTextProperty textProp;              XTextProperty textProp;
1331              if (XStringListToTextProperty(&wmPtr->clientMachine, 1, &textProp)              if (XStringListToTextProperty(&wmPtr->clientMachine, 1, &textProp)
1332                      != 0) {                      != 0) {
1333                  XSetWMClientMachine(winPtr->display, winPtr->window,                  XSetWMClientMachine(winPtr->display, winPtr->window,
1334                          &textProp);                          &textProp);
1335                  XFree((char *) textProp.value);                  XFree((char *) textProp.value);
1336              }              }
1337          }          }
1338      } else if ((c == 'c') && (strncmp(argv[1], "colormapwindows", length) == 0)      } else if ((c == 'c') && (strncmp(argv[1], "colormapwindows", length) == 0)
1339              && (length >= 3)) {              && (length >= 3)) {
1340          TkWindow **cmapList;          TkWindow **cmapList;
1341          TkWindow *winPtr2;          TkWindow *winPtr2;
1342          int i, windowArgc, gotToplevel;          int i, windowArgc, gotToplevel;
1343          char **windowArgv;          char **windowArgv;
1344    
1345          if ((argc != 3) && (argc != 4)) {          if ((argc != 3) && (argc != 4)) {
1346              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1347                      argv[0], " colormapwindows window ?windowList?\"",                      argv[0], " colormapwindows window ?windowList?\"",
1348                      (char *) NULL);                      (char *) NULL);
1349              return TCL_ERROR;              return TCL_ERROR;
1350          }          }
1351          if (argc == 3) {          if (argc == 3) {
1352              Tk_MakeWindowExist((Tk_Window) winPtr);              Tk_MakeWindowExist((Tk_Window) winPtr);
1353              for (i = 0; i < wmPtr->cmapCount; i++) {              for (i = 0; i < wmPtr->cmapCount; i++) {
1354                  if ((i == (wmPtr->cmapCount-1))                  if ((i == (wmPtr->cmapCount-1))
1355                          && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) {                          && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) {
1356                      break;                      break;
1357                  }                  }
1358                  Tcl_AppendElement(interp, wmPtr->cmapList[i]->pathName);                  Tcl_AppendElement(interp, wmPtr->cmapList[i]->pathName);
1359              }              }
1360              return TCL_OK;              return TCL_OK;
1361          }          }
1362          if (Tcl_SplitList(interp, argv[3], &windowArgc, &windowArgv)          if (Tcl_SplitList(interp, argv[3], &windowArgc, &windowArgv)
1363                  != TCL_OK) {                  != TCL_OK) {
1364              return TCL_ERROR;              return TCL_ERROR;
1365          }          }
1366          cmapList = (TkWindow **) ckalloc((unsigned)          cmapList = (TkWindow **) ckalloc((unsigned)
1367                  ((windowArgc+1)*sizeof(TkWindow*)));                  ((windowArgc+1)*sizeof(TkWindow*)));
1368          for (i = 0; i < windowArgc; i++) {          for (i = 0; i < windowArgc; i++) {
1369              winPtr2 = (TkWindow *) Tk_NameToWindow(interp, windowArgv[i],              winPtr2 = (TkWindow *) Tk_NameToWindow(interp, windowArgv[i],
1370                      tkwin);                      tkwin);
1371              if (winPtr2 == NULL) {              if (winPtr2 == NULL) {
1372                  ckfree((char *) cmapList);                  ckfree((char *) cmapList);
1373                  ckfree((char *) windowArgv);                  ckfree((char *) windowArgv);
1374                  return TCL_ERROR;                  return TCL_ERROR;
1375              }              }
1376              if (winPtr2 == winPtr) {              if (winPtr2 == winPtr) {
1377                  gotToplevel = 1;                  gotToplevel = 1;
1378              }              }
1379              if (winPtr2->window == None) {              if (winPtr2->window == None) {
1380                  Tk_MakeWindowExist((Tk_Window) winPtr2);                  Tk_MakeWindowExist((Tk_Window) winPtr2);
1381              }              }
1382              cmapList[i] = winPtr2;              cmapList[i] = winPtr2;
1383          }          }
1384          if (!gotToplevel) {          if (!gotToplevel) {
1385              wmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP;              wmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP;
1386              cmapList[windowArgc] = winPtr;              cmapList[windowArgc] = winPtr;
1387              windowArgc++;              windowArgc++;
1388          } else {          } else {
1389              wmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP;              wmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP;
1390          }          }
1391          wmPtr->flags |= WM_COLORMAPS_EXPLICIT;          wmPtr->flags |= WM_COLORMAPS_EXPLICIT;
1392          if (wmPtr->cmapList != NULL) {          if (wmPtr->cmapList != NULL) {
1393              ckfree((char *)wmPtr->cmapList);              ckfree((char *)wmPtr->cmapList);
1394          }          }
1395          wmPtr->cmapList = cmapList;          wmPtr->cmapList = cmapList;
1396          wmPtr->cmapCount = windowArgc;          wmPtr->cmapCount = windowArgc;
1397          ckfree((char *) windowArgv);          ckfree((char *) windowArgv);
1398    
1399          /*          /*
1400           * Now we need to force the updated colormaps to be installed.           * Now we need to force the updated colormaps to be installed.
1401           */           */
1402    
1403          if (wmPtr == winPtr->dispPtr->foregroundWmPtr) {          if (wmPtr == winPtr->dispPtr->foregroundWmPtr) {
1404              InstallColormaps(wmPtr->wrapper, WM_QUERYNEWPALETTE, 1);              InstallColormaps(wmPtr->wrapper, WM_QUERYNEWPALETTE, 1);
1405          } else {          } else {
1406              InstallColormaps(wmPtr->wrapper, WM_PALETTECHANGED, 0);              InstallColormaps(wmPtr->wrapper, WM_PALETTECHANGED, 0);
1407          }          }
1408          return TCL_OK;          return TCL_OK;
1409      } else if ((c == 'c') && (strncmp(argv[1], "command", length) == 0)      } else if ((c == 'c') && (strncmp(argv[1], "command", length) == 0)
1410              && (length >= 3)) {              && (length >= 3)) {
1411          int cmdArgc;          int cmdArgc;
1412          char **cmdArgv;          char **cmdArgv;
1413    
1414          if ((argc != 3) && (argc != 4)) {          if ((argc != 3) && (argc != 4)) {
1415              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1416                      argv[0], " command window ?value?\"",                      argv[0], " command window ?value?\"",
1417                      (char *) NULL);                      (char *) NULL);
1418              return TCL_ERROR;              return TCL_ERROR;
1419          }          }
1420          if (argc == 3) {          if (argc == 3) {
1421              if (wmPtr->cmdArgv != NULL) {              if (wmPtr->cmdArgv != NULL) {
1422                  Tcl_SetResult(interp,                  Tcl_SetResult(interp,
1423                          Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv),                          Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv),
1424                          TCL_DYNAMIC);                          TCL_DYNAMIC);
1425              }              }
1426              return TCL_OK;              return TCL_OK;
1427          }          }
1428          if (argv[3][0] == 0) {          if (argv[3][0] == 0) {
1429              if (wmPtr->cmdArgv != NULL) {              if (wmPtr->cmdArgv != NULL) {
1430                  ckfree((char *) wmPtr->cmdArgv);                  ckfree((char *) wmPtr->cmdArgv);
1431                  wmPtr->cmdArgv = NULL;                  wmPtr->cmdArgv = NULL;
1432                  if (!(wmPtr->flags & WM_NEVER_MAPPED)) {                  if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
1433                      XDeleteProperty(winPtr->display, winPtr->window,                      XDeleteProperty(winPtr->display, winPtr->window,
1434                              Tk_InternAtom((Tk_Window) winPtr, "WM_COMMAND"));                              Tk_InternAtom((Tk_Window) winPtr, "WM_COMMAND"));
1435                  }                  }
1436              }              }
1437              return TCL_OK;              return TCL_OK;
1438          }          }
1439          if (Tcl_SplitList(interp, argv[3], &cmdArgc, &cmdArgv) != TCL_OK) {          if (Tcl_SplitList(interp, argv[3], &cmdArgc, &cmdArgv) != TCL_OK) {
1440              return TCL_ERROR;              return TCL_ERROR;
1441          }          }
1442          if (wmPtr->cmdArgv != NULL) {          if (wmPtr->cmdArgv != NULL) {
1443              ckfree((char *) wmPtr->cmdArgv);              ckfree((char *) wmPtr->cmdArgv);
1444          }          }
1445          wmPtr->cmdArgc = cmdArgc;          wmPtr->cmdArgc = cmdArgc;
1446          wmPtr->cmdArgv = cmdArgv;          wmPtr->cmdArgv = cmdArgv;
1447          if (!(wmPtr->flags & WM_NEVER_MAPPED)) {          if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
1448              XSetCommand(winPtr->display, winPtr->window, cmdArgv, cmdArgc);              XSetCommand(winPtr->display, winPtr->window, cmdArgv, cmdArgc);
1449          }          }
1450      } else if ((c == 'd') && (strncmp(argv[1], "deiconify", length) == 0)) {      } else if ((c == 'd') && (strncmp(argv[1], "deiconify", length) == 0)) {
1451          if (argc != 3) {          if (argc != 3) {
1452              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1453                      argv[0], " deiconify window\"", (char *) NULL);                      argv[0], " deiconify window\"", (char *) NULL);
1454              return TCL_ERROR;              return TCL_ERROR;
1455          }          }
1456          if (wmPtr->iconFor != NULL) {          if (wmPtr->iconFor != NULL) {
1457              Tcl_AppendResult(interp, "can't deiconify ", argv[2],              Tcl_AppendResult(interp, "can't deiconify ", argv[2],
1458                      ": it is an icon for ", winPtr->pathName, (char *) NULL);                      ": it is an icon for ", winPtr->pathName, (char *) NULL);
1459              return TCL_ERROR;              return TCL_ERROR;
1460          }          }
1461          if (winPtr->flags & TK_EMBEDDED) {          if (winPtr->flags & TK_EMBEDDED) {
1462              Tcl_AppendResult(interp, "can't deiconify ", winPtr->pathName,              Tcl_AppendResult(interp, "can't deiconify ", winPtr->pathName,
1463                      ": it is an embedded window", (char *) NULL);                      ": it is an embedded window", (char *) NULL);
1464              return TCL_ERROR;              return TCL_ERROR;
1465          }          }
1466          /*          /*
1467           * If WM_UPDATE_PENDING is true, a pending UpdateGeometryInfo may           * If WM_UPDATE_PENDING is true, a pending UpdateGeometryInfo may
1468           * need to be called first to update a withdrew toplevel's geometry           * need to be called first to update a withdrew toplevel's geometry
1469           * before it is deiconified by TkpWmSetState.           * before it is deiconified by TkpWmSetState.
1470           * Don't bother if we've never been mapped.           * Don't bother if we've never been mapped.
1471           */           */
1472          if ((wmPtr->flags & WM_UPDATE_PENDING) &&          if ((wmPtr->flags & WM_UPDATE_PENDING) &&
1473                  !(wmPtr->flags & WM_NEVER_MAPPED)) {                  !(wmPtr->flags & WM_NEVER_MAPPED)) {
1474              Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);              Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
1475              UpdateGeometryInfo((ClientData) winPtr);              UpdateGeometryInfo((ClientData) winPtr);
1476          }          }
1477    
1478          /*          /*
1479           * If we were in the ZoomState (maximized), 'wm deiconify'           * If we were in the ZoomState (maximized), 'wm deiconify'
1480           * should not cause the window to shrink           * should not cause the window to shrink
1481           */           */
1482          if (wmPtr->hints.initial_state == ZoomState) {          if (wmPtr->hints.initial_state == ZoomState) {
1483              TkpWmSetState(winPtr, ZoomState);              TkpWmSetState(winPtr, ZoomState);
1484          } else {          } else {
1485              TkpWmSetState(winPtr, NormalState);              TkpWmSetState(winPtr, NormalState);
1486          }          }
1487    
1488          /*          /*
1489           * Follow Windows-like style here, raising the window to the top.           * Follow Windows-like style here, raising the window to the top.
1490           * Do this when idle, to not cause an unrefreshable window to           * Do this when idle, to not cause an unrefreshable window to
1491           * get mapped.           * get mapped.
1492           */           */
1493          Tcl_DoWhenIdle(RaiseWinWhenIdle, (ClientData) winPtr);          Tcl_DoWhenIdle(RaiseWinWhenIdle, (ClientData) winPtr);
1494      } else if ((c == 'f') && (strncmp(argv[1], "focusmodel", length) == 0)      } else if ((c == 'f') && (strncmp(argv[1], "focusmodel", length) == 0)
1495              && (length >= 2)) {              && (length >= 2)) {
1496          if ((argc != 3) && (argc != 4)) {          if ((argc != 3) && (argc != 4)) {
1497              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1498                      argv[0], " focusmodel window ?active|passive?\"",                      argv[0], " focusmodel window ?active|passive?\"",
1499                      (char *) NULL);                      (char *) NULL);
1500              return TCL_ERROR;              return TCL_ERROR;
1501          }          }
1502          if (argc == 3) {          if (argc == 3) {
1503              Tcl_SetResult(interp, (wmPtr->hints.input ? "passive" : "active"),              Tcl_SetResult(interp, (wmPtr->hints.input ? "passive" : "active"),
1504                      TCL_STATIC);                      TCL_STATIC);
1505              return TCL_OK;              return TCL_OK;
1506          }          }
1507          c = argv[3][0];          c = argv[3][0];
1508          length = strlen(argv[3]);          length = strlen(argv[3]);
1509          if ((c == 'a') && (strncmp(argv[3], "active", length) == 0)) {          if ((c == 'a') && (strncmp(argv[3], "active", length) == 0)) {
1510              wmPtr->hints.input = False;              wmPtr->hints.input = False;
1511          } else if ((c == 'p') && (strncmp(argv[3], "passive", length) == 0)) {          } else if ((c == 'p') && (strncmp(argv[3], "passive", length) == 0)) {
1512              wmPtr->hints.input = True;              wmPtr->hints.input = True;
1513          } else {          } else {
1514              Tcl_AppendResult(interp, "bad argument \"", argv[3],              Tcl_AppendResult(interp, "bad argument \"", argv[3],
1515                      "\": must be active or passive", (char *) NULL);                      "\": must be active or passive", (char *) NULL);
1516              return TCL_ERROR;              return TCL_ERROR;
1517          }          }
1518      } else if ((c == 'f') && (strncmp(argv[1], "frame", length) == 0)      } else if ((c == 'f') && (strncmp(argv[1], "frame", length) == 0)
1519              && (length >= 2)) {              && (length >= 2)) {
1520          HWND hwnd;          HWND hwnd;
1521          char buf[TCL_INTEGER_SPACE];          char buf[TCL_INTEGER_SPACE];
1522    
1523          if (argc != 3) {          if (argc != 3) {
1524              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1525                      argv[0], " frame window\"", (char *) NULL);                      argv[0], " frame window\"", (char *) NULL);
1526              return TCL_ERROR;              return TCL_ERROR;
1527          }          }
1528          if (Tk_WindowId((Tk_Window) winPtr) == None) {          if (Tk_WindowId((Tk_Window) winPtr) == None) {
1529              Tk_MakeWindowExist((Tk_Window) winPtr);              Tk_MakeWindowExist((Tk_Window) winPtr);
1530          }          }
1531          hwnd = wmPtr->wrapper;          hwnd = wmPtr->wrapper;
1532          if (hwnd == NULL) {          if (hwnd == NULL) {
1533              hwnd = Tk_GetHWND(Tk_WindowId((Tk_Window) winPtr));              hwnd = Tk_GetHWND(Tk_WindowId((Tk_Window) winPtr));
1534          }          }
1535          sprintf(buf, "0x%x", (unsigned int) hwnd);          sprintf(buf, "0x%x", (unsigned int) hwnd);
1536          Tcl_SetResult(interp, buf, TCL_VOLATILE);          Tcl_SetResult(interp, buf, TCL_VOLATILE);
1537      } else if ((c == 'g') && (strncmp(argv[1], "geometry", length) == 0)      } else if ((c == 'g') && (strncmp(argv[1], "geometry", length) == 0)
1538              && (length >= 2)) {              && (length >= 2)) {
1539          char xSign, ySign;          char xSign, ySign;
1540          int width, height;          int width, height;
1541    
1542          if ((argc != 3) && (argc != 4)) {          if ((argc != 3) && (argc != 4)) {
1543              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1544                      argv[0], " geometry window ?newGeometry?\"",                      argv[0], " geometry window ?newGeometry?\"",
1545                      (char *) NULL);                      (char *) NULL);
1546              return TCL_ERROR;              return TCL_ERROR;
1547          }          }
1548          if (argc == 3) {          if (argc == 3) {
1549              char buf[16 + TCL_INTEGER_SPACE * 4];              char buf[16 + TCL_INTEGER_SPACE * 4];
1550                            
1551              xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+';              xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+';
1552              ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+';              ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+';
1553              if (wmPtr->gridWin != NULL) {              if (wmPtr->gridWin != NULL) {
1554                  width = wmPtr->reqGridWidth + (winPtr->changes.width                  width = wmPtr->reqGridWidth + (winPtr->changes.width
1555                          - winPtr->reqWidth)/wmPtr->widthInc;                          - winPtr->reqWidth)/wmPtr->widthInc;
1556                  height = wmPtr->reqGridHeight + (winPtr->changes.height                  height = wmPtr->reqGridHeight + (winPtr->changes.height
1557                          - winPtr->reqHeight)/wmPtr->heightInc;                          - winPtr->reqHeight)/wmPtr->heightInc;
1558              } else {              } else {
1559                  width = winPtr->changes.width;                  width = winPtr->changes.width;
1560                  height = winPtr->changes.height;                  height = winPtr->changes.height;
1561              }              }
1562              sprintf(buf, "%dx%d%c%d%c%d", width, height, xSign, wmPtr->x,              sprintf(buf, "%dx%d%c%d%c%d", width, height, xSign, wmPtr->x,
1563                      ySign, wmPtr->y);                      ySign, wmPtr->y);
1564              Tcl_SetResult(interp, buf, TCL_VOLATILE);              Tcl_SetResult(interp, buf, TCL_VOLATILE);
1565              return TCL_OK;              return TCL_OK;
1566          }          }
1567          if (*argv[3] == '\0') {          if (*argv[3] == '\0') {
1568              wmPtr->width = -1;              wmPtr->width = -1;
1569              wmPtr->height = -1;              wmPtr->height = -1;
1570              goto updateGeom;              goto updateGeom;
1571          }          }
1572          return ParseGeometry(interp, argv[3], winPtr);          return ParseGeometry(interp, argv[3], winPtr);
1573      } else if ((c == 'g') && (strncmp(argv[1], "grid", length) == 0)      } else if ((c == 'g') && (strncmp(argv[1], "grid", length) == 0)
1574              && (length >= 3)) {              && (length >= 3)) {
1575          int reqWidth, reqHeight, widthInc, heightInc;          int reqWidth, reqHeight, widthInc, heightInc;
1576    
1577          if ((argc != 3) && (argc != 7)) {          if ((argc != 3) && (argc != 7)) {
1578              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1579                      argv[0], " grid window ?baseWidth baseHeight ",                      argv[0], " grid window ?baseWidth baseHeight ",
1580                      "widthInc heightInc?\"", (char *) NULL);                      "widthInc heightInc?\"", (char *) NULL);
1581              return TCL_ERROR;              return TCL_ERROR;
1582          }          }
1583          if (argc == 3) {          if (argc == 3) {
1584              if (wmPtr->sizeHintsFlags & PBaseSize) {              if (wmPtr->sizeHintsFlags & PBaseSize) {
1585                  char buf[TCL_INTEGER_SPACE * 4];                  char buf[TCL_INTEGER_SPACE * 4];
1586                                    
1587                  sprintf(buf, "%d %d %d %d", wmPtr->reqGridWidth,                  sprintf(buf, "%d %d %d %d", wmPtr->reqGridWidth,
1588                          wmPtr->reqGridHeight, wmPtr->widthInc,                          wmPtr->reqGridHeight, wmPtr->widthInc,
1589                          wmPtr->heightInc);                          wmPtr->heightInc);
1590                  Tcl_SetResult(interp, buf, TCL_VOLATILE);                  Tcl_SetResult(interp, buf, TCL_VOLATILE);
1591              }              }
1592              return TCL_OK;              return TCL_OK;
1593          }          }
1594          if (*argv[3] == '\0') {          if (*argv[3] == '\0') {
1595              /*              /*
1596               * Turn off gridding and reset the width and height               * Turn off gridding and reset the width and height
1597               * to make sense as ungridded numbers.               * to make sense as ungridded numbers.
1598               */               */
1599    
1600              wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc);              wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc);
1601              if (wmPtr->width != -1) {              if (wmPtr->width != -1) {
1602                  wmPtr->width = winPtr->reqWidth + (wmPtr->width                  wmPtr->width = winPtr->reqWidth + (wmPtr->width
1603                          - wmPtr->reqGridWidth)*wmPtr->widthInc;                          - wmPtr->reqGridWidth)*wmPtr->widthInc;
1604                  wmPtr->height = winPtr->reqHeight + (wmPtr->height                  wmPtr->height = winPtr->reqHeight + (wmPtr->height
1605                          - wmPtr->reqGridHeight)*wmPtr->heightInc;                          - wmPtr->reqGridHeight)*wmPtr->heightInc;
1606              }              }
1607              wmPtr->widthInc = 1;              wmPtr->widthInc = 1;
1608              wmPtr->heightInc = 1;              wmPtr->heightInc = 1;
1609          } else {          } else {
1610              if ((Tcl_GetInt(interp, argv[3], &reqWidth) != TCL_OK)              if ((Tcl_GetInt(interp, argv[3], &reqWidth) != TCL_OK)
1611                      || (Tcl_GetInt(interp, argv[4], &reqHeight) != TCL_OK)                      || (Tcl_GetInt(interp, argv[4], &reqHeight) != TCL_OK)
1612                      || (Tcl_GetInt(interp, argv[5], &widthInc) != TCL_OK)                      || (Tcl_GetInt(interp, argv[5], &widthInc) != TCL_OK)
1613                      || (Tcl_GetInt(interp, argv[6], &heightInc) != TCL_OK)) {                      || (Tcl_GetInt(interp, argv[6], &heightInc) != TCL_OK)) {
1614                  return TCL_ERROR;                  return TCL_ERROR;
1615              }              }
1616              if (reqWidth < 0) {              if (reqWidth < 0) {
1617                  Tcl_SetResult(interp, "baseWidth can't be < 0", TCL_STATIC);                  Tcl_SetResult(interp, "baseWidth can't be < 0", TCL_STATIC);
1618                  return TCL_ERROR;                  return TCL_ERROR;
1619              }              }
1620              if (reqHeight < 0) {              if (reqHeight < 0) {
1621                  Tcl_SetResult(interp, "baseHeight can't be < 0", TCL_STATIC);                  Tcl_SetResult(interp, "baseHeight can't be < 0", TCL_STATIC);
1622                  return TCL_ERROR;                  return TCL_ERROR;
1623              }              }
1624              if (widthInc < 0) {              if (widthInc < 0) {
1625                  Tcl_SetResult(interp, "widthInc can't be < 0", TCL_STATIC);                  Tcl_SetResult(interp, "widthInc can't be < 0", TCL_STATIC);
1626                  return TCL_ERROR;                  return TCL_ERROR;
1627              }              }
1628              if (heightInc < 0) {              if (heightInc < 0) {
1629                  Tcl_SetResult(interp, "heightInc can't be < 0", TCL_STATIC);                  Tcl_SetResult(interp, "heightInc can't be < 0", TCL_STATIC);
1630                  return TCL_ERROR;                  return TCL_ERROR;
1631              }              }
1632              Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,              Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,
1633                      heightInc);                      heightInc);
1634          }          }
1635          goto updateGeom;          goto updateGeom;
1636      } else if ((c == 'g') && (strncmp(argv[1], "group", length) == 0)      } else if ((c == 'g') && (strncmp(argv[1], "group", length) == 0)
1637              && (length >= 3)) {              && (length >= 3)) {
1638          Tk_Window tkwin2;          Tk_Window tkwin2;
1639    
1640          if ((argc != 3) && (argc != 4)) {          if ((argc != 3) && (argc != 4)) {
1641              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1642                      argv[0], " group window ?pathName?\"",                      argv[0], " group window ?pathName?\"",
1643                      (char *) NULL);                      (char *) NULL);
1644              return TCL_ERROR;              return TCL_ERROR;
1645          }          }
1646          if (argc == 3) {          if (argc == 3) {
1647              if (wmPtr->hints.flags & WindowGroupHint) {              if (wmPtr->hints.flags & WindowGroupHint) {
1648                  Tcl_SetResult(interp, wmPtr->leaderName, TCL_STATIC);                  Tcl_SetResult(interp, wmPtr->leaderName, TCL_STATIC);
1649              }              }
1650              return TCL_OK;              return TCL_OK;
1651          }          }
1652          if (*argv[3] == '\0') {          if (*argv[3] == '\0') {
1653              wmPtr->hints.flags &= ~WindowGroupHint;              wmPtr->hints.flags &= ~WindowGroupHint;
1654              if (wmPtr->leaderName != NULL) {              if (wmPtr->leaderName != NULL) {
1655                  ckfree(wmPtr->leaderName);                  ckfree(wmPtr->leaderName);
1656              }              }
1657              wmPtr->leaderName = NULL;              wmPtr->leaderName = NULL;
1658          } else {          } else {
1659              tkwin2 = Tk_NameToWindow(interp, argv[3], tkwin);              tkwin2 = Tk_NameToWindow(interp, argv[3], tkwin);
1660              if (tkwin2 == NULL) {              if (tkwin2 == NULL) {
1661                  return TCL_ERROR;                  return TCL_ERROR;
1662              }              }
1663              Tk_MakeWindowExist(tkwin2);              Tk_MakeWindowExist(tkwin2);
1664              wmPtr->hints.window_group = Tk_WindowId(tkwin2);              wmPtr->hints.window_group = Tk_WindowId(tkwin2);
1665              wmPtr->hints.flags |= WindowGroupHint;              wmPtr->hints.flags |= WindowGroupHint;
1666              wmPtr->leaderName = ckalloc((unsigned) (strlen(argv[3])+1));              wmPtr->leaderName = ckalloc((unsigned) (strlen(argv[3])+1));
1667              strcpy(wmPtr->leaderName, argv[3]);              strcpy(wmPtr->leaderName, argv[3]);
1668          }          }
1669      } else if ((c == 'i') && (strncmp(argv[1], "iconbitmap", length) == 0)      } else if ((c == 'i') && (strncmp(argv[1], "iconbitmap", length) == 0)
1670              && (length >= 5)) {              && (length >= 5)) {
1671          Pixmap pixmap;          Pixmap pixmap;
1672    
1673          if ((argc != 3) && (argc != 4)) {          if ((argc != 3) && (argc != 4)) {
1674              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1675                      argv[0], " iconbitmap window ?bitmap?\"",                      argv[0], " iconbitmap window ?bitmap?\"",
1676                      (char *) NULL);                      (char *) NULL);
1677              return TCL_ERROR;              return TCL_ERROR;
1678          }          }
1679          if (argc == 3) {          if (argc == 3) {
1680              if (wmPtr->hints.flags & IconPixmapHint) {              if (wmPtr->hints.flags & IconPixmapHint) {
1681                  Tcl_SetResult(interp,                  Tcl_SetResult(interp,
1682                          Tk_NameOfBitmap(winPtr->display,                          Tk_NameOfBitmap(winPtr->display,
1683                                  wmPtr->hints.icon_pixmap), TCL_STATIC);                                  wmPtr->hints.icon_pixmap), TCL_STATIC);
1684              }              }
1685              return TCL_OK;              return TCL_OK;
1686          }          }
1687          if (*argv[3] == '\0') {          if (*argv[3] == '\0') {
1688              if (wmPtr->hints.icon_pixmap != None) {              if (wmPtr->hints.icon_pixmap != None) {
1689                  Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);                  Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
1690              }              }
1691              wmPtr->hints.flags &= ~IconPixmapHint;              wmPtr->hints.flags &= ~IconPixmapHint;
1692          } else {          } else {
1693              pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr,              pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr,
1694                      Tk_GetUid(argv[3]));                      Tk_GetUid(argv[3]));
1695              if (pixmap == None) {              if (pixmap == None) {
1696                  return TCL_ERROR;                  return TCL_ERROR;
1697              }              }
1698              wmPtr->hints.icon_pixmap = pixmap;              wmPtr->hints.icon_pixmap = pixmap;
1699              wmPtr->hints.flags |= IconPixmapHint;              wmPtr->hints.flags |= IconPixmapHint;
1700          }          }
1701      } else if ((c == 'i') && (strncmp(argv[1], "iconify", length) == 0)      } else if ((c == 'i') && (strncmp(argv[1], "iconify", length) == 0)
1702              && (length >= 5)) {              && (length >= 5)) {
1703          if (argc != 3) {          if (argc != 3) {
1704              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1705                      argv[0], " iconify window\"", (char *) NULL);                      argv[0], " iconify window\"", (char *) NULL);
1706              return TCL_ERROR;              return TCL_ERROR;
1707          }          }
1708          if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {          if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
1709              Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName,              Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName,
1710                      "\": override-redirect flag is set", (char *) NULL);                      "\": override-redirect flag is set", (char *) NULL);
1711              return TCL_ERROR;              return TCL_ERROR;
1712          }          }
1713          if (wmPtr->masterPtr != NULL) {          if (wmPtr->masterPtr != NULL) {
1714              Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName,              Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName,
1715                      "\": it is a transient", (char *) NULL);                      "\": it is a transient", (char *) NULL);
1716              return TCL_ERROR;              return TCL_ERROR;
1717          }          }
1718          if (wmPtr->iconFor != NULL) {          if (wmPtr->iconFor != NULL) {
1719              Tcl_AppendResult(interp, "can't iconify ", argv[2],              Tcl_AppendResult(interp, "can't iconify ", argv[2],
1720                      ": it is an icon for ", winPtr->pathName, (char *) NULL);                      ": it is an icon for ", winPtr->pathName, (char *) NULL);
1721              return TCL_ERROR;              return TCL_ERROR;
1722          }          }
1723          if (winPtr->flags & TK_EMBEDDED) {          if (winPtr->flags & TK_EMBEDDED) {
1724              Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName,              Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName,
1725                      ": it is an embedded window", (char *) NULL);                      ": it is an embedded window", (char *) NULL);
1726              return TCL_ERROR;              return TCL_ERROR;
1727          }          }
1728          TkpWmSetState(winPtr, IconicState);          TkpWmSetState(winPtr, IconicState);
1729      } else if ((c == 'i') && (strncmp(argv[1], "iconmask", length) == 0)      } else if ((c == 'i') && (strncmp(argv[1], "iconmask", length) == 0)
1730              && (length >= 5)) {              && (length >= 5)) {
1731          Pixmap pixmap;          Pixmap pixmap;
1732    
1733          if ((argc != 3) && (argc != 4)) {          if ((argc != 3) && (argc != 4)) {
1734              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1735                      argv[0], " iconmask window ?bitmap?\"",                      argv[0], " iconmask window ?bitmap?\"",
1736                      (char *) NULL);                      (char *) NULL);
1737              return TCL_ERROR;              return TCL_ERROR;
1738          }          }
1739          if (argc == 3) {          if (argc == 3) {
1740              if (wmPtr->hints.flags & IconMaskHint) {              if (wmPtr->hints.flags & IconMaskHint) {
1741                  Tcl_SetResult(interp,                  Tcl_SetResult(interp,
1742                          Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_mask),                          Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_mask),
1743                          TCL_STATIC);                          TCL_STATIC);
1744              }              }
1745              return TCL_OK;              return TCL_OK;
1746          }          }
1747          if (*argv[3] == '\0') {          if (*argv[3] == '\0') {
1748              if (wmPtr->hints.icon_mask != None) {              if (wmPtr->hints.icon_mask != None) {
1749                  Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);                  Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);
1750              }              }
1751              wmPtr->hints.flags &= ~IconMaskHint;              wmPtr->hints.flags &= ~IconMaskHint;
1752          } else {          } else {
1753              pixmap = Tk_GetBitmap(interp, tkwin, Tk_GetUid(argv[3]));              pixmap = Tk_GetBitmap(interp, tkwin, Tk_GetUid(argv[3]));
1754              if (pixmap == None) {              if (pixmap == None) {
1755                  return TCL_ERROR;                  return TCL_ERROR;
1756              }              }
1757              wmPtr->hints.icon_mask = pixmap;              wmPtr->hints.icon_mask = pixmap;
1758              wmPtr->hints.flags |= IconMaskHint;              wmPtr->hints.flags |= IconMaskHint;
1759          }          }
1760      } else if ((c == 'i') && (strncmp(argv[1], "iconname", length) == 0)      } else if ((c == 'i') && (strncmp(argv[1], "iconname", length) == 0)
1761              && (length >= 5)) {              && (length >= 5)) {
1762          if (argc > 4) {          if (argc > 4) {
1763              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1764                      argv[0], " iconname window ?newName?\"", (char *) NULL);                      argv[0], " iconname window ?newName?\"", (char *) NULL);
1765              return TCL_ERROR;              return TCL_ERROR;
1766          }          }
1767          if (argc == 3) {          if (argc == 3) {
1768              Tcl_SetResult(interp,              Tcl_SetResult(interp,
1769                      ((wmPtr->iconName != NULL) ? wmPtr->iconName : ""),                      ((wmPtr->iconName != NULL) ? wmPtr->iconName : ""),
1770                      TCL_STATIC);                      TCL_STATIC);
1771              return TCL_OK;              return TCL_OK;
1772          } else {          } else {
1773              wmPtr->iconName = Tk_GetUid(argv[3]);              wmPtr->iconName = Tk_GetUid(argv[3]);
1774              if (!(wmPtr->flags & WM_NEVER_MAPPED)) {              if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
1775                  XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName);                  XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName);
1776              }              }
1777          }          }
1778      } else if ((c == 'i') && (strncmp(argv[1], "iconposition", length) == 0)      } else if ((c == 'i') && (strncmp(argv[1], "iconposition", length) == 0)
1779              && (length >= 5)) {              && (length >= 5)) {
1780          int x, y;          int x, y;
1781    
1782          if ((argc != 3) && (argc != 5)) {          if ((argc != 3) && (argc != 5)) {
1783              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1784                      argv[0], " iconposition window ?x y?\"",                      argv[0], " iconposition window ?x y?\"",
1785                      (char *) NULL);                      (char *) NULL);
1786              return TCL_ERROR;              return TCL_ERROR;
1787          }          }
1788          if (argc == 3) {          if (argc == 3) {
1789              if (wmPtr->hints.flags & IconPositionHint) {              if (wmPtr->hints.flags & IconPositionHint) {
1790                  char buf[TCL_INTEGER_SPACE * 2];                  char buf[TCL_INTEGER_SPACE * 2];
1791                                    
1792                  sprintf(buf, "%d %d", wmPtr->hints.icon_x,                  sprintf(buf, "%d %d", wmPtr->hints.icon_x,
1793                          wmPtr->hints.icon_y);                          wmPtr->hints.icon_y);
1794                  Tcl_SetResult(interp, buf, TCL_VOLATILE);                  Tcl_SetResult(interp, buf, TCL_VOLATILE);
1795              }              }
1796              return TCL_OK;              return TCL_OK;
1797          }          }
1798          if (*argv[3] == '\0') {          if (*argv[3] == '\0') {
1799              wmPtr->hints.flags &= ~IconPositionHint;              wmPtr->hints.flags &= ~IconPositionHint;
1800          } else {          } else {
1801              if ((Tcl_GetInt(interp, argv[3], &x) != TCL_OK)              if ((Tcl_GetInt(interp, argv[3], &x) != TCL_OK)
1802                      || (Tcl_GetInt(interp, argv[4], &y) != TCL_OK)){                      || (Tcl_GetInt(interp, argv[4], &y) != TCL_OK)){
1803                  return TCL_ERROR;                  return TCL_ERROR;
1804              }              }
1805              wmPtr->hints.icon_x = x;              wmPtr->hints.icon_x = x;
1806              wmPtr->hints.icon_y = y;              wmPtr->hints.icon_y = y;
1807              wmPtr->hints.flags |= IconPositionHint;              wmPtr->hints.flags |= IconPositionHint;
1808          }          }
1809      } else if ((c == 'i') && (strncmp(argv[1], "iconwindow", length) == 0)      } else if ((c == 'i') && (strncmp(argv[1], "iconwindow", length) == 0)
1810              && (length >= 5)) {              && (length >= 5)) {
1811          Tk_Window tkwin2;          Tk_Window tkwin2;
1812          WmInfo *wmPtr2;          WmInfo *wmPtr2;
1813          XSetWindowAttributes atts;          XSetWindowAttributes atts;
1814    
1815          if ((argc != 3) && (argc != 4)) {          if ((argc != 3) && (argc != 4)) {
1816              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1817                      argv[0], " iconwindow window ?pathName?\"",                      argv[0], " iconwindow window ?pathName?\"",
1818                      (char *) NULL);                      (char *) NULL);
1819              return TCL_ERROR;              return TCL_ERROR;
1820          }          }
1821          if (argc == 3) {          if (argc == 3) {
1822              if (wmPtr->icon != NULL) {              if (wmPtr->icon != NULL) {
1823                  Tcl_SetResult(interp, Tk_PathName(wmPtr->icon), TCL_STATIC);                  Tcl_SetResult(interp, Tk_PathName(wmPtr->icon), TCL_STATIC);
1824              }              }
1825              return TCL_OK;              return TCL_OK;
1826          }          }
1827          if (*argv[3] == '\0') {          if (*argv[3] == '\0') {
1828              wmPtr->hints.flags &= ~IconWindowHint;              wmPtr->hints.flags &= ~IconWindowHint;
1829              if (wmPtr->icon != NULL) {              if (wmPtr->icon != NULL) {
1830                  /*                  /*
1831                   * Let the window use button events again, then remove                   * Let the window use button events again, then remove
1832                   * it as icon window.                   * it as icon window.
1833                   */                   */
1834    
1835                  atts.event_mask = Tk_Attributes(wmPtr->icon)->event_mask                  atts.event_mask = Tk_Attributes(wmPtr->icon)->event_mask
1836                          | ButtonPressMask;                          | ButtonPressMask;
1837                  Tk_ChangeWindowAttributes(wmPtr->icon, CWEventMask, &atts);                  Tk_ChangeWindowAttributes(wmPtr->icon, CWEventMask, &atts);
1838                  wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;                  wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
1839                  wmPtr2->iconFor = NULL;                  wmPtr2->iconFor = NULL;
1840                  wmPtr2->hints.initial_state = WithdrawnState;                  wmPtr2->hints.initial_state = WithdrawnState;
1841              }              }
1842              wmPtr->icon = NULL;              wmPtr->icon = NULL;
1843          } else {          } else {
1844              tkwin2 = Tk_NameToWindow(interp, argv[3], tkwin);              tkwin2 = Tk_NameToWindow(interp, argv[3], tkwin);
1845              if (tkwin2 == NULL) {              if (tkwin2 == NULL) {
1846                  return TCL_ERROR;                  return TCL_ERROR;
1847              }              }
1848              if (!Tk_IsTopLevel(tkwin2)) {              if (!Tk_IsTopLevel(tkwin2)) {
1849                  Tcl_AppendResult(interp, "can't use ", argv[3],                  Tcl_AppendResult(interp, "can't use ", argv[3],
1850                          " as icon window: not at top level", (char *) NULL);                          " as icon window: not at top level", (char *) NULL);
1851                  return TCL_ERROR;                  return TCL_ERROR;
1852              }              }
1853              wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;              wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;
1854              if (wmPtr2->iconFor != NULL) {              if (wmPtr2->iconFor != NULL) {
1855                  Tcl_AppendResult(interp, argv[3], " is already an icon for ",                  Tcl_AppendResult(interp, argv[3], " is already an icon for ",
1856                          Tk_PathName(wmPtr2->iconFor), (char *) NULL);                          Tk_PathName(wmPtr2->iconFor), (char *) NULL);
1857                  return TCL_ERROR;                  return TCL_ERROR;
1858              }              }
1859              if (wmPtr->icon != NULL) {              if (wmPtr->icon != NULL) {
1860                  WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;                  WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
1861                  wmPtr3->iconFor = NULL;                  wmPtr3->iconFor = NULL;
1862    
1863                  /*                  /*
1864                   * Let the window use button events again.                   * Let the window use button events again.
1865                   */                   */
1866    
1867                  atts.event_mask = Tk_Attributes(wmPtr->icon)->event_mask                  atts.event_mask = Tk_Attributes(wmPtr->icon)->event_mask
1868                          | ButtonPressMask;                          | ButtonPressMask;
1869                  Tk_ChangeWindowAttributes(wmPtr->icon, CWEventMask, &atts);                  Tk_ChangeWindowAttributes(wmPtr->icon, CWEventMask, &atts);
1870              }              }
1871    
1872              /*              /*
1873               * Disable button events in the icon window:  some window               * Disable button events in the icon window:  some window
1874               * managers (like olvwm) want to get the events themselves,               * managers (like olvwm) want to get the events themselves,
1875               * but X only allows one application at a time to receive               * but X only allows one application at a time to receive
1876               * button events for a window.               * button events for a window.
1877               */               */
1878    
1879              atts.event_mask = Tk_Attributes(tkwin2)->event_mask              atts.event_mask = Tk_Attributes(tkwin2)->event_mask
1880                      & ~ButtonPressMask;                      & ~ButtonPressMask;
1881              Tk_ChangeWindowAttributes(tkwin2, CWEventMask, &atts);              Tk_ChangeWindowAttributes(tkwin2, CWEventMask, &atts);
1882              Tk_MakeWindowExist(tkwin2);              Tk_MakeWindowExist(tkwin2);
1883              wmPtr->hints.icon_window = Tk_WindowId(tkwin2);              wmPtr->hints.icon_window = Tk_WindowId(tkwin2);
1884              wmPtr->hints.flags |= IconWindowHint;              wmPtr->hints.flags |= IconWindowHint;
1885              wmPtr->icon = tkwin2;              wmPtr->icon = tkwin2;
1886              wmPtr2->iconFor = (Tk_Window) winPtr;              wmPtr2->iconFor = (Tk_Window) winPtr;
1887              if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {              if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
1888                  if (XWithdrawWindow(Tk_Display(tkwin2), Tk_WindowId(tkwin2),                  if (XWithdrawWindow(Tk_Display(tkwin2), Tk_WindowId(tkwin2),
1889                          Tk_ScreenNumber(tkwin2)) == 0) {                          Tk_ScreenNumber(tkwin2)) == 0) {
1890                      Tcl_SetResult(interp,                      Tcl_SetResult(interp,
1891                              "couldn't send withdraw message to window manager",                              "couldn't send withdraw message to window manager",
1892                              TCL_STATIC);                              TCL_STATIC);
1893                      return TCL_ERROR;                      return TCL_ERROR;
1894                  }                  }
1895              }              }
1896          }          }
1897      } else if ((c == 'm') && (strncmp(argv[1], "maxsize", length) == 0)      } else if ((c == 'm') && (strncmp(argv[1], "maxsize", length) == 0)
1898              && (length >= 2)) {              && (length >= 2)) {
1899          int width, height;          int width, height;
1900          if ((argc != 3) && (argc != 5)) {          if ((argc != 3) && (argc != 5)) {
1901              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1902                      argv[0], " maxsize window ?width height?\"",                      argv[0], " maxsize window ?width height?\"",
1903                      (char *) NULL);                      (char *) NULL);
1904              return TCL_ERROR;              return TCL_ERROR;
1905          }          }
1906          if (argc == 3) {          if (argc == 3) {
1907              char buf[TCL_INTEGER_SPACE * 2];              char buf[TCL_INTEGER_SPACE * 2];
1908                            
1909              GetMaxSize(wmPtr, &width, &height);              GetMaxSize(wmPtr, &width, &height);
1910              sprintf(buf, "%d %d", width, height);              sprintf(buf, "%d %d", width, height);
1911              Tcl_SetResult(interp, buf, TCL_VOLATILE);              Tcl_SetResult(interp, buf, TCL_VOLATILE);
1912              return TCL_OK;              return TCL_OK;
1913          }          }
1914          if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK)          if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK)
1915                  || (Tcl_GetInt(interp, argv[4], &height) != TCL_OK)) {                  || (Tcl_GetInt(interp, argv[4], &height) != TCL_OK)) {
1916              return TCL_ERROR;              return TCL_ERROR;
1917          }          }
1918          wmPtr->maxWidth = width;          wmPtr->maxWidth = width;
1919          wmPtr->maxHeight = height;          wmPtr->maxHeight = height;
1920          goto updateGeom;          goto updateGeom;
1921      } else if ((c == 'm') && (strncmp(argv[1], "minsize", length) == 0)      } else if ((c == 'm') && (strncmp(argv[1], "minsize", length) == 0)
1922              && (length >= 2)) {              && (length >= 2)) {
1923          int width, height;          int width, height;
1924          if ((argc != 3) && (argc != 5)) {          if ((argc != 3) && (argc != 5)) {
1925              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1926                      argv[0], " minsize window ?width height?\"",                      argv[0], " minsize window ?width height?\"",
1927                      (char *) NULL);                      (char *) NULL);
1928              return TCL_ERROR;              return TCL_ERROR;
1929          }          }
1930          if (argc == 3) {          if (argc == 3) {
1931              char buf[TCL_INTEGER_SPACE * 2];              char buf[TCL_INTEGER_SPACE * 2];
1932                            
1933              GetMinSize(wmPtr, &width, &height);              GetMinSize(wmPtr, &width, &height);
1934              sprintf(buf, "%d %d", width, height);              sprintf(buf, "%d %d", width, height);
1935              Tcl_SetResult(interp, buf, TCL_VOLATILE);              Tcl_SetResult(interp, buf, TCL_VOLATILE);
1936              return TCL_OK;              return TCL_OK;
1937          }          }
1938          if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK)          if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK)
1939                  || (Tcl_GetInt(interp, argv[4], &height) != TCL_OK)) {                  || (Tcl_GetInt(interp, argv[4], &height) != TCL_OK)) {
1940              return TCL_ERROR;              return TCL_ERROR;
1941          }          }
1942          wmPtr->minWidth = width;          wmPtr->minWidth = width;
1943          wmPtr->minHeight = height;          wmPtr->minHeight = height;
1944          goto updateGeom;          goto updateGeom;
1945      } else if ((c == 'o')      } else if ((c == 'o')
1946              && (strncmp(argv[1], "overrideredirect", length) == 0)) {              && (strncmp(argv[1], "overrideredirect", length) == 0)) {
1947          int boolean, curValue;          int boolean, curValue;
1948          XSetWindowAttributes atts;          XSetWindowAttributes atts;
1949    
1950          if ((argc != 3) && (argc != 4)) {          if ((argc != 3) && (argc != 4)) {
1951              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1952                      argv[0], " overrideredirect window ?boolean?\"",                      argv[0], " overrideredirect window ?boolean?\"",
1953                      (char *) NULL);                      (char *) NULL);
1954              return TCL_ERROR;              return TCL_ERROR;
1955          }          }
1956          curValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect;          curValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect;
1957          if (argc == 3) {          if (argc == 3) {
1958              Tcl_SetBooleanObj(Tcl_GetObjResult(interp), curValue);              Tcl_SetBooleanObj(Tcl_GetObjResult(interp), curValue);
1959              return TCL_OK;              return TCL_OK;
1960          }          }
1961          if (Tcl_GetBoolean(interp, argv[3], &boolean) != TCL_OK) {          if (Tcl_GetBoolean(interp, argv[3], &boolean) != TCL_OK) {
1962              return TCL_ERROR;              return TCL_ERROR;
1963          }          }
1964          if (curValue != boolean) {          if (curValue != boolean) {
1965              /*              /*
1966               * Only do this if we are really changing value, because it               * Only do this if we are really changing value, because it
1967               * causes some funky stuff to occur               * causes some funky stuff to occur
1968               */               */
1969              atts.override_redirect = (boolean) ? True : False;              atts.override_redirect = (boolean) ? True : False;
1970              Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect,              Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect,
1971                      &atts);                      &atts);
1972              if (!(wmPtr->flags & (WM_NEVER_MAPPED)              if (!(wmPtr->flags & (WM_NEVER_MAPPED)
1973                      && !(winPtr->flags & TK_EMBEDDED))) {                      && !(winPtr->flags & TK_EMBEDDED))) {
1974                  UpdateWrapper(winPtr);                  UpdateWrapper(winPtr);
1975              }              }
1976          }          }
1977      } else if ((c == 'p') && (strncmp(argv[1], "positionfrom", length) == 0)      } else if ((c == 'p') && (strncmp(argv[1], "positionfrom", length) == 0)
1978              && (length >= 2)) {              && (length >= 2)) {
1979          if ((argc != 3) && (argc != 4)) {          if ((argc != 3) && (argc != 4)) {
1980              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1981                      argv[0], " positionfrom window ?user/program?\"",                      argv[0], " positionfrom window ?user/program?\"",
1982                      (char *) NULL);                      (char *) NULL);
1983              return TCL_ERROR;              return TCL_ERROR;
1984          }          }
1985          if (argc == 3) {          if (argc == 3) {
1986              if (wmPtr->sizeHintsFlags & USPosition) {              if (wmPtr->sizeHintsFlags & USPosition) {
1987                  Tcl_SetResult(interp, "user", TCL_STATIC);                  Tcl_SetResult(interp, "user", TCL_STATIC);
1988              } else if (wmPtr->sizeHintsFlags & PPosition) {              } else if (wmPtr->sizeHintsFlags & PPosition) {
1989                  Tcl_SetResult(interp, "program", TCL_STATIC);                  Tcl_SetResult(interp, "program", TCL_STATIC);
1990              }              }
1991              return TCL_OK;              return TCL_OK;
1992          }          }
1993          if (*argv[3] == '\0') {          if (*argv[3] == '\0') {
1994              wmPtr->sizeHintsFlags &= ~(USPosition|PPosition);              wmPtr->sizeHintsFlags &= ~(USPosition|PPosition);
1995          } else {          } else {
1996              c = argv[3][0];              c = argv[3][0];
1997              length = strlen(argv[3]);              length = strlen(argv[3]);
1998              if ((c == 'u') && (strncmp(argv[3], "user", length) == 0)) {              if ((c == 'u') && (strncmp(argv[3], "user", length) == 0)) {
1999                  wmPtr->sizeHintsFlags &= ~PPosition;                  wmPtr->sizeHintsFlags &= ~PPosition;
2000                  wmPtr->sizeHintsFlags |= USPosition;                  wmPtr->sizeHintsFlags |= USPosition;
2001              } else if ((c == 'p')              } else if ((c == 'p')
2002                      && (strncmp(argv[3], "program", length) == 0)) {                      && (strncmp(argv[3], "program", length) == 0)) {
2003                  wmPtr->sizeHintsFlags &= ~USPosition;                  wmPtr->sizeHintsFlags &= ~USPosition;
2004                  wmPtr->sizeHintsFlags |= PPosition;                  wmPtr->sizeHintsFlags |= PPosition;
2005              } else {              } else {
2006                  Tcl_AppendResult(interp, "bad argument \"", argv[3],                  Tcl_AppendResult(interp, "bad argument \"", argv[3],
2007                          "\": must be program or user", (char *) NULL);                          "\": must be program or user", (char *) NULL);
2008                  return TCL_ERROR;                  return TCL_ERROR;
2009              }              }
2010          }          }
2011          goto updateGeom;          goto updateGeom;
2012      } else if ((c == 'p') && (strncmp(argv[1], "protocol", length) == 0)      } else if ((c == 'p') && (strncmp(argv[1], "protocol", length) == 0)
2013              && (length >= 2)) {              && (length >= 2)) {
2014          register ProtocolHandler *protPtr, *prevPtr;          register ProtocolHandler *protPtr, *prevPtr;
2015          Atom protocol;          Atom protocol;
2016          int cmdLength;          int cmdLength;
2017    
2018          if ((argc < 3) || (argc > 5)) {          if ((argc < 3) || (argc > 5)) {
2019              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
2020                      argv[0], " protocol window ?name? ?command?\"",                      argv[0], " protocol window ?name? ?command?\"",
2021                      (char *) NULL);                      (char *) NULL);
2022              return TCL_ERROR;              return TCL_ERROR;
2023          }          }
2024          if (argc == 3) {          if (argc == 3) {
2025              /*              /*
2026               * Return a list of all defined protocols for the window.               * Return a list of all defined protocols for the window.
2027               */               */
2028              for (protPtr = wmPtr->protPtr; protPtr != NULL;              for (protPtr = wmPtr->protPtr; protPtr != NULL;
2029                      protPtr = protPtr->nextPtr) {                      protPtr = protPtr->nextPtr) {
2030                  Tcl_AppendElement(interp,                  Tcl_AppendElement(interp,
2031                          Tk_GetAtomName((Tk_Window) winPtr, protPtr->protocol));                          Tk_GetAtomName((Tk_Window) winPtr, protPtr->protocol));
2032              }              }
2033              return TCL_OK;              return TCL_OK;
2034          }          }
2035          protocol = Tk_InternAtom((Tk_Window) winPtr, argv[3]);          protocol = Tk_InternAtom((Tk_Window) winPtr, argv[3]);
2036          if (argc == 4) {          if (argc == 4) {
2037              /*              /*
2038               * Return the command to handle a given protocol.               * Return the command to handle a given protocol.
2039               */               */
2040              for (protPtr = wmPtr->protPtr; protPtr != NULL;              for (protPtr = wmPtr->protPtr; protPtr != NULL;
2041                      protPtr = protPtr->nextPtr) {                      protPtr = protPtr->nextPtr) {
2042                  if (protPtr->protocol == protocol) {                  if (protPtr->protocol == protocol) {
2043                      Tcl_SetResult(interp, protPtr->command, TCL_STATIC);                      Tcl_SetResult(interp, protPtr->command, TCL_STATIC);
2044                      return TCL_OK;                      return TCL_OK;
2045                  }                  }
2046              }              }
2047              return TCL_OK;              return TCL_OK;
2048          }          }
2049    
2050          /*          /*
2051           * Delete any current protocol handler, then create a new           * Delete any current protocol handler, then create a new
2052           * one with the specified command, unless the command is           * one with the specified command, unless the command is
2053           * empty.           * empty.
2054           */           */
2055    
2056          for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL;          for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL;
2057                  prevPtr = protPtr, protPtr = protPtr->nextPtr) {                  prevPtr = protPtr, protPtr = protPtr->nextPtr) {
2058              if (protPtr->protocol == protocol) {              if (protPtr->protocol == protocol) {
2059                  if (prevPtr == NULL) {                  if (prevPtr == NULL) {
2060                      wmPtr->protPtr = protPtr->nextPtr;                      wmPtr->protPtr = protPtr->nextPtr;
2061                  } else {                  } else {
2062                      prevPtr->nextPtr = protPtr->nextPtr;                      prevPtr->nextPtr = protPtr->nextPtr;
2063                  }                  }
2064                  Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC);                  Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC);
2065                  break;                  break;
2066              }              }
2067          }          }
2068          cmdLength = strlen(argv[4]);          cmdLength = strlen(argv[4]);
2069          if (cmdLength > 0) {          if (cmdLength > 0) {
2070              protPtr = (ProtocolHandler *) ckalloc(HANDLER_SIZE(cmdLength));              protPtr = (ProtocolHandler *) ckalloc(HANDLER_SIZE(cmdLength));
2071              protPtr->protocol = protocol;              protPtr->protocol = protocol;
2072              protPtr->nextPtr = wmPtr->protPtr;              protPtr->nextPtr = wmPtr->protPtr;
2073              wmPtr->protPtr = protPtr;              wmPtr->protPtr = protPtr;
2074              protPtr->interp = interp;              protPtr->interp = interp;
2075              strcpy(protPtr->command, argv[4]);              strcpy(protPtr->command, argv[4]);
2076          }          }
2077      } else if ((c == 'r') && (strncmp(argv[1], "resizable", length) == 0)) {      } else if ((c == 'r') && (strncmp(argv[1], "resizable", length) == 0)) {
2078          int width, height;          int width, height;
2079    
2080          if ((argc != 3) && (argc != 5)) {          if ((argc != 3) && (argc != 5)) {
2081              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
2082                      argv[0], " resizable window ?width height?\"",                      argv[0], " resizable window ?width height?\"",
2083                      (char *) NULL);                      (char *) NULL);
2084              return TCL_ERROR;              return TCL_ERROR;
2085          }          }
2086          if (argc == 3) {          if (argc == 3) {
2087              char buf[TCL_INTEGER_SPACE * 2];              char buf[TCL_INTEGER_SPACE * 2];
2088                            
2089              sprintf(buf, "%d %d",              sprintf(buf, "%d %d",
2090                      (wmPtr->flags  & WM_WIDTH_NOT_RESIZABLE) ? 0 : 1,                      (wmPtr->flags  & WM_WIDTH_NOT_RESIZABLE) ? 0 : 1,
2091                      (wmPtr->flags  & WM_HEIGHT_NOT_RESIZABLE) ? 0 : 1);                      (wmPtr->flags  & WM_HEIGHT_NOT_RESIZABLE) ? 0 : 1);
2092              Tcl_SetResult(interp, buf, TCL_VOLATILE);              Tcl_SetResult(interp, buf, TCL_VOLATILE);
2093              return TCL_OK;              return TCL_OK;
2094          }          }
2095          if ((Tcl_GetBoolean(interp, argv[3], &width) != TCL_OK)          if ((Tcl_GetBoolean(interp, argv[3], &width) != TCL_OK)
2096                  || (Tcl_GetBoolean(interp, argv[4], &height) != TCL_OK)) {                  || (Tcl_GetBoolean(interp, argv[4], &height) != TCL_OK)) {
2097              return TCL_ERROR;              return TCL_ERROR;
2098          }          }
2099          if (width) {          if (width) {
2100              wmPtr->flags &= ~WM_WIDTH_NOT_RESIZABLE;              wmPtr->flags &= ~WM_WIDTH_NOT_RESIZABLE;
2101          } else {          } else {
2102              wmPtr->flags |= WM_WIDTH_NOT_RESIZABLE;              wmPtr->flags |= WM_WIDTH_NOT_RESIZABLE;
2103          }          }
2104          if (height) {          if (height) {
2105              wmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE;              wmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE;
2106          } else {          } else {
2107              wmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE;              wmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE;
2108          }          }
2109          if (!((wmPtr->flags & WM_NEVER_MAPPED)          if (!((wmPtr->flags & WM_NEVER_MAPPED)
2110                  && !(winPtr->flags & TK_EMBEDDED))) {                  && !(winPtr->flags & TK_EMBEDDED))) {
2111              UpdateWrapper(winPtr);              UpdateWrapper(winPtr);
2112          }          }
2113          goto updateGeom;          goto updateGeom;
2114      } else if ((c == 's') && (strncmp(argv[1], "sizefrom", length) == 0)      } else if ((c == 's') && (strncmp(argv[1], "sizefrom", length) == 0)
2115              && (length >= 2)) {              && (length >= 2)) {
2116          if ((argc != 3) && (argc != 4)) {          if ((argc != 3) && (argc != 4)) {
2117              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
2118                      argv[0], " sizefrom window ?user|program?\"",                      argv[0], " sizefrom window ?user|program?\"",
2119                      (char *) NULL);                      (char *) NULL);
2120              return TCL_ERROR;              return TCL_ERROR;
2121          }          }
2122          if (argc == 3) {          if (argc == 3) {
2123              if (wmPtr->sizeHintsFlags & USSize) {              if (wmPtr->sizeHintsFlags & USSize) {
2124                  Tcl_SetResult(interp, "user", TCL_STATIC);                  Tcl_SetResult(interp, "user", TCL_STATIC);
2125              } else if (wmPtr->sizeHintsFlags & PSize) {              } else if (wmPtr->sizeHintsFlags & PSize) {
2126                  Tcl_SetResult(interp, "program", TCL_STATIC);                  Tcl_SetResult(interp, "program", TCL_STATIC);
2127              }              }
2128              return TCL_OK;              return TCL_OK;
2129          }          }
2130          if (*argv[3] == '\0') {          if (*argv[3] == '\0') {
2131              wmPtr->sizeHintsFlags &= ~(USSize|PSize);              wmPtr->sizeHintsFlags &= ~(USSize|PSize);
2132          } else {          } else {
2133              c = argv[3][0];              c = argv[3][0];
2134              length = strlen(argv[3]);              length = strlen(argv[3]);
2135              if ((c == 'u') && (strncmp(argv[3], "user", length) == 0)) {              if ((c == 'u') && (strncmp(argv[3], "user", length) == 0)) {
2136                  wmPtr->sizeHintsFlags &= ~PSize;                  wmPtr->sizeHintsFlags &= ~PSize;
2137                  wmPtr->sizeHintsFlags |= USSize;                  wmPtr->sizeHintsFlags |= USSize;
2138              } else if ((c == 'p')              } else if ((c == 'p')
2139                      && (strncmp(argv[3], "program", length) == 0)) {                      && (strncmp(argv[3], "program", length) == 0)) {
2140                  wmPtr->sizeHintsFlags &= ~USSize;                  wmPtr->sizeHintsFlags &= ~USSize;
2141                  wmPtr->sizeHintsFlags |= PSize;                  wmPtr->sizeHintsFlags |= PSize;
2142              } else {              } else {
2143                  Tcl_AppendResult(interp, "bad argument \"", argv[3],                  Tcl_AppendResult(interp, "bad argument \"", argv[3],
2144                          "\": must be program or user", (char *) NULL);                          "\": must be program or user", (char *) NULL);
2145                  return TCL_ERROR;                  return TCL_ERROR;
2146              }              }
2147          }          }
2148          goto updateGeom;          goto updateGeom;
2149      } else if ((c == 's') && (strncmp(argv[1], "state", length) == 0)      } else if ((c == 's') && (strncmp(argv[1], "state", length) == 0)
2150              && (length >= 2)) {              && (length >= 2)) {
2151          if ((argc < 3) || (argc > 4)) {          if ((argc < 3) || (argc > 4)) {
2152              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
2153                      argv[0], " state window ?state?\"", (char *) NULL);                      argv[0], " state window ?state?\"", (char *) NULL);
2154              return TCL_ERROR;              return TCL_ERROR;
2155          }          }
2156          if (argc == 4) {          if (argc == 4) {
2157              if (wmPtr->iconFor != NULL) {              if (wmPtr->iconFor != NULL) {
2158                  Tcl_AppendResult(interp, "can't change state of ", argv[2],                  Tcl_AppendResult(interp, "can't change state of ", argv[2],
2159                          ": it is an icon for ", Tk_PathName(wmPtr->iconFor),                          ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
2160                          (char *) NULL);                          (char *) NULL);
2161                  return TCL_ERROR;                  return TCL_ERROR;
2162              }              }
2163              if (winPtr->flags & TK_EMBEDDED) {              if (winPtr->flags & TK_EMBEDDED) {
2164                  Tcl_AppendResult(interp, "can't change state of ",                  Tcl_AppendResult(interp, "can't change state of ",
2165                          winPtr->pathName, ": it is an embedded window",                          winPtr->pathName, ": it is an embedded window",
2166                          (char *) NULL);                          (char *) NULL);
2167                  return TCL_ERROR;                  return TCL_ERROR;
2168              }              }
2169    
2170              c = argv[3][0];              c = argv[3][0];
2171              length = strlen(argv[3]);              length = strlen(argv[3]);
2172    
2173              if ((c == 'n') && (strncmp(argv[3], "normal", length) == 0)) {              if ((c == 'n') && (strncmp(argv[3], "normal", length) == 0)) {
2174                  TkpWmSetState(winPtr, NormalState);                  TkpWmSetState(winPtr, NormalState);
2175                  /*                  /*
2176                   * This varies from 'wm deiconify' because it does not                   * This varies from 'wm deiconify' because it does not
2177                   * force the window to be raised and receive focus                   * force the window to be raised and receive focus
2178                   */                   */
2179              } else if ((c == 'i')              } else if ((c == 'i')
2180                      && (strncmp(argv[3], "iconic", length) == 0)) {                      && (strncmp(argv[3], "iconic", length) == 0)) {
2181                  if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {                  if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
2182                      Tcl_AppendResult(interp, "can't iconify \"",                      Tcl_AppendResult(interp, "can't iconify \"",
2183                              winPtr->pathName,                              winPtr->pathName,
2184                              "\": override-redirect flag is set",                              "\": override-redirect flag is set",
2185                              (char *) NULL);                              (char *) NULL);
2186                      return TCL_ERROR;                      return TCL_ERROR;
2187                  }                  }
2188                  if (wmPtr->masterPtr != NULL) {                  if (wmPtr->masterPtr != NULL) {
2189                      Tcl_AppendResult(interp, "can't iconify \"",                      Tcl_AppendResult(interp, "can't iconify \"",
2190                              winPtr->pathName,                              winPtr->pathName,
2191                              "\": it is a transient", (char *) NULL);                              "\": it is a transient", (char *) NULL);
2192                      return TCL_ERROR;                      return TCL_ERROR;
2193                  }                  }
2194                  TkpWmSetState(winPtr, IconicState);                  TkpWmSetState(winPtr, IconicState);
2195              } else if ((c == 'w')              } else if ((c == 'w')
2196                      && (strncmp(argv[3], "withdrawn", length) == 0)) {                      && (strncmp(argv[3], "withdrawn", length) == 0)) {
2197                  TkpWmSetState(winPtr, WithdrawnState);                  TkpWmSetState(winPtr, WithdrawnState);
2198              } else if ((c == 'z')              } else if ((c == 'z')
2199                      && (strncmp(argv[3], "zoomed", length) == 0)) {                      && (strncmp(argv[3], "zoomed", length) == 0)) {
2200                  TkpWmSetState(winPtr, ZoomState);                  TkpWmSetState(winPtr, ZoomState);
2201              } else {              } else {
2202                  Tcl_AppendResult(interp, "bad argument \"", argv[3],                  Tcl_AppendResult(interp, "bad argument \"", argv[3],
2203                          "\": must be normal, iconic, withdrawn or zoomed",                          "\": must be normal, iconic, withdrawn or zoomed",
2204                          (char *) NULL);                          (char *) NULL);
2205                  return TCL_ERROR;                  return TCL_ERROR;
2206              }              }
2207          } else {          } else {
2208              if (wmPtr->iconFor != NULL) {              if (wmPtr->iconFor != NULL) {
2209                  Tcl_SetResult(interp, "icon", TCL_STATIC);                  Tcl_SetResult(interp, "icon", TCL_STATIC);
2210              } else {              } else {
2211                  switch (wmPtr->hints.initial_state) {                  switch (wmPtr->hints.initial_state) {
2212                      case NormalState:                      case NormalState:
2213                          Tcl_SetResult(interp, "normal", TCL_STATIC);                          Tcl_SetResult(interp, "normal", TCL_STATIC);
2214                          break;                          break;
2215                      case IconicState:                      case IconicState:
2216                          Tcl_SetResult(interp, "iconic", TCL_STATIC);                          Tcl_SetResult(interp, "iconic", TCL_STATIC);
2217                          break;                          break;
2218                      case WithdrawnState:                      case WithdrawnState:
2219                          Tcl_SetResult(interp, "withdrawn", TCL_STATIC);                          Tcl_SetResult(interp, "withdrawn", TCL_STATIC);
2220                          break;                          break;
2221                      case ZoomState:                      case ZoomState:
2222                          Tcl_SetResult(interp, "zoomed", TCL_STATIC);                          Tcl_SetResult(interp, "zoomed", TCL_STATIC);
2223                          break;                          break;
2224                  }                  }
2225              }              }
2226          }          }
2227      } else if ((c == 't') && (strncmp(argv[1], "title", length) == 0)      } else if ((c == 't') && (strncmp(argv[1], "title", length) == 0)
2228              && (length >= 2)) {              && (length >= 2)) {
2229          if (argc > 4) {          if (argc > 4) {
2230              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
2231                      argv[0], " title window ?newTitle?\"", (char *) NULL);                      argv[0], " title window ?newTitle?\"", (char *) NULL);
2232              return TCL_ERROR;              return TCL_ERROR;
2233          }          }
2234          if (argc == 3) {          if (argc == 3) {
2235              Tcl_SetResult(interp, ((wmPtr->titleUid != NULL) ?              Tcl_SetResult(interp, ((wmPtr->titleUid != NULL) ?
2236                      wmPtr->titleUid : winPtr->nameUid), TCL_STATIC);                      wmPtr->titleUid : winPtr->nameUid), TCL_STATIC);
2237              return TCL_OK;              return TCL_OK;
2238          } else {          } else {
2239              wmPtr->titleUid = Tk_GetUid(argv[3]);              wmPtr->titleUid = Tk_GetUid(argv[3]);
2240              if (!(wmPtr->flags & WM_NEVER_MAPPED) && wmPtr->wrapper != NULL) {              if (!(wmPtr->flags & WM_NEVER_MAPPED) && wmPtr->wrapper != NULL) {
2241                  Tcl_DString titleString;                  Tcl_DString titleString;
2242                  Tcl_UtfToExternalDString(NULL, wmPtr->titleUid, -1,                  Tcl_UtfToExternalDString(NULL, wmPtr->titleUid, -1,
2243                          &titleString);                          &titleString);
2244                  SetWindowText(wmPtr->wrapper, Tcl_DStringValue(&titleString));                  SetWindowText(wmPtr->wrapper, Tcl_DStringValue(&titleString));
2245                  Tcl_DStringFree(&titleString);                  Tcl_DStringFree(&titleString);
2246              }              }
2247          }          }
2248      } else if ((c == 't') && (strncmp(argv[1], "transient", length) == 0)      } else if ((c == 't') && (strncmp(argv[1], "transient", length) == 0)
2249              && (length >= 3)) {              && (length >= 3)) {
2250          TkWindow *masterPtr = wmPtr->masterPtr;          TkWindow *masterPtr = wmPtr->masterPtr;
2251    
2252          if ((argc != 3) && (argc != 4)) {          if ((argc != 3) && (argc != 4)) {
2253              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
2254                      argv[0], " transient window ?master?\"", (char *) NULL);                      argv[0], " transient window ?master?\"", (char *) NULL);
2255              return TCL_ERROR;              return TCL_ERROR;
2256          }          }
2257          if (argc == 3) {          if (argc == 3) {
2258              if (masterPtr != NULL) {              if (masterPtr != NULL) {
2259                  Tcl_SetResult(interp, Tk_PathName(masterPtr), TCL_STATIC);                  Tcl_SetResult(interp, Tk_PathName(masterPtr), TCL_STATIC);
2260              }              }
2261              return TCL_OK;              return TCL_OK;
2262          }          }
2263          if (masterPtr != NULL) {          if (masterPtr != NULL) {
2264              /*              /*
2265               * If we had a master, tell them that we aren't tied               * If we had a master, tell them that we aren't tied
2266               * to them anymore               * to them anymore
2267               */               */
2268              masterPtr->wmInfoPtr->numTransients--;              masterPtr->wmInfoPtr->numTransients--;
2269              Tk_DeleteEventHandler((Tk_Window) masterPtr,              Tk_DeleteEventHandler((Tk_Window) masterPtr,
2270                      VisibilityChangeMask,                      VisibilityChangeMask,
2271                      WmWaitVisibilityProc, (ClientData) winPtr);                      WmWaitVisibilityProc, (ClientData) winPtr);
2272          }          }
2273          if (argv[3][0] == '\0') {          if (argv[3][0] == '\0') {
2274              wmPtr->masterPtr = NULL;              wmPtr->masterPtr = NULL;
2275          } else {          } else {
2276              masterPtr = (TkWindow*) Tk_NameToWindow(interp, argv[3], tkwin);              masterPtr = (TkWindow*) Tk_NameToWindow(interp, argv[3], tkwin);
2277              if (masterPtr == NULL) {              if (masterPtr == NULL) {
2278                  return TCL_ERROR;                  return TCL_ERROR;
2279              }              }
2280              if (masterPtr == winPtr) {              if (masterPtr == winPtr) {
2281                  wmPtr->masterPtr = NULL;                  wmPtr->masterPtr = NULL;
2282              } else if (masterPtr != wmPtr->masterPtr) {              } else if (masterPtr != wmPtr->masterPtr) {
2283                  Tk_MakeWindowExist((Tk_Window)masterPtr);                  Tk_MakeWindowExist((Tk_Window)masterPtr);
2284    
2285                  /*                  /*
2286                   * Ensure that the master window is actually a Tk toplevel.                   * Ensure that the master window is actually a Tk toplevel.
2287                   */                   */
2288    
2289                  while (!(masterPtr->flags & TK_TOP_LEVEL)) {                  while (!(masterPtr->flags & TK_TOP_LEVEL)) {
2290                      masterPtr = masterPtr->parentPtr;                      masterPtr = masterPtr->parentPtr;
2291                  }                  }
2292                  wmPtr->masterPtr = masterPtr;                  wmPtr->masterPtr = masterPtr;
2293                  masterPtr->wmInfoPtr->numTransients++;                  masterPtr->wmInfoPtr->numTransients++;
2294    
2295                  /*                  /*
2296                   * Bind a visibility event handler to the master window,                   * Bind a visibility event handler to the master window,
2297                   * to ensure that when it is mapped, the children will                   * to ensure that when it is mapped, the children will
2298                   * have their state set properly.                   * have their state set properly.
2299                   */                   */
2300    
2301                  Tk_CreateEventHandler((Tk_Window) masterPtr,                  Tk_CreateEventHandler((Tk_Window) masterPtr,
2302                          VisibilityChangeMask,                          VisibilityChangeMask,
2303                          WmWaitVisibilityProc, (ClientData) winPtr);                          WmWaitVisibilityProc, (ClientData) winPtr);
2304              }              }
2305          }          }
2306          if (!((wmPtr->flags & WM_NEVER_MAPPED)          if (!((wmPtr->flags & WM_NEVER_MAPPED)
2307                  && !(winPtr->flags & TK_EMBEDDED))) {                  && !(winPtr->flags & TK_EMBEDDED))) {
2308              UpdateWrapper(winPtr);              UpdateWrapper(winPtr);
2309          }          }
2310      } else if ((c == 'w') && (strncmp(argv[1], "withdraw", length) == 0)) {      } else if ((c == 'w') && (strncmp(argv[1], "withdraw", length) == 0)) {
2311          if (argc != 3) {          if (argc != 3) {
2312              Tcl_AppendResult(interp, "wrong # arguments: must be \"",              Tcl_AppendResult(interp, "wrong # arguments: must be \"",
2313                      argv[0], " withdraw window\"", (char *) NULL);                      argv[0], " withdraw window\"", (char *) NULL);
2314              return TCL_ERROR;              return TCL_ERROR;
2315          }          }
2316          if (wmPtr->iconFor != NULL) {          if (wmPtr->iconFor != NULL) {
2317              Tcl_AppendResult(interp, "can't withdraw ", argv[2],              Tcl_AppendResult(interp, "can't withdraw ", argv[2],
2318                      ": it is an icon for ", Tk_PathName(wmPtr->iconFor),                      ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
2319                      (char *) NULL);                      (char *) NULL);
2320              return TCL_ERROR;              return TCL_ERROR;
2321          }          }
2322          TkpWmSetState(winPtr, WithdrawnState);          TkpWmSetState(winPtr, WithdrawnState);
2323      } else {      } else {
2324          Tcl_AppendResult(interp, "unknown or ambiguous option \"", argv[1],          Tcl_AppendResult(interp, "unknown or ambiguous option \"", argv[1],
2325                  "\": must be aspect, client, command, deiconify, ",                  "\": must be aspect, client, command, deiconify, ",
2326                  "focusmodel, frame, geometry, grid, group, iconbitmap, ",                  "focusmodel, frame, geometry, grid, group, iconbitmap, ",
2327                  "iconify, iconmask, iconname, iconposition, ",                  "iconify, iconmask, iconname, iconposition, ",
2328                  "iconwindow, maxsize, minsize, overrideredirect, ",                  "iconwindow, maxsize, minsize, overrideredirect, ",
2329                  "positionfrom, protocol, resizable, sizefrom, state, title, ",                  "positionfrom, protocol, resizable, sizefrom, state, title, ",
2330                  "transient, or withdraw",                  "transient, or withdraw",
2331                  (char *) NULL);                  (char *) NULL);
2332          return TCL_ERROR;          return TCL_ERROR;
2333      }      }
2334      return TCL_OK;      return TCL_OK;
2335    
2336      updateGeom:      updateGeom:
2337      if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {      if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
2338          Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);          Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
2339          wmPtr->flags |= WM_UPDATE_PENDING;          wmPtr->flags |= WM_UPDATE_PENDING;
2340      }      }
2341      return TCL_OK;      return TCL_OK;
2342  }  }
2343          /*ARGSUSED*/          /*ARGSUSED*/
2344  static void  static void
2345  WmWaitVisibilityProc(clientData, eventPtr)  WmWaitVisibilityProc(clientData, eventPtr)
2346      ClientData clientData;      /* Pointer to window. */      ClientData clientData;      /* Pointer to window. */
2347      XEvent *eventPtr;           /* Information about event. */      XEvent *eventPtr;           /* Information about event. */
2348  {  {
2349      TkWindow *winPtr = (TkWindow *) clientData;      TkWindow *winPtr = (TkWindow *) clientData;
2350      TkWindow *masterPtr = winPtr->wmInfoPtr->masterPtr;      TkWindow *masterPtr = winPtr->wmInfoPtr->masterPtr;
2351    
2352      if ((eventPtr->type == VisibilityNotify) && (masterPtr != NULL)) {      if ((eventPtr->type == VisibilityNotify) && (masterPtr != NULL)) {
2353          int state = masterPtr->wmInfoPtr->hints.initial_state;          int state = masterPtr->wmInfoPtr->hints.initial_state;
2354    
2355          if ((state == NormalState) || (state == ZoomState)) {          if ((state == NormalState) || (state == ZoomState)) {
2356              state = winPtr->wmInfoPtr->hints.initial_state;              state = winPtr->wmInfoPtr->hints.initial_state;
2357              if ((state == NormalState) || (state == ZoomState)) {              if ((state == NormalState) || (state == ZoomState)) {
2358                  UpdateWrapper(winPtr);                  UpdateWrapper(winPtr);
2359              }              }
2360          }          }
2361      }      }
2362  }  }
2363    
2364  /*  /*
2365   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2366   *   *
2367   * Tk_SetGrid --   * Tk_SetGrid --
2368   *   *
2369   *      This procedure is invoked by a widget when it wishes to set a grid   *      This procedure is invoked by a widget when it wishes to set a grid
2370   *      coordinate system that controls the size of a top-level window.   *      coordinate system that controls the size of a top-level window.
2371   *      It provides a C interface equivalent to the "wm grid" command and   *      It provides a C interface equivalent to the "wm grid" command and
2372   *      is usually asscoiated with the -setgrid option.   *      is usually asscoiated with the -setgrid option.
2373   *   *
2374   * Results:   * Results:
2375   *      None.   *      None.
2376   *   *
2377   * Side effects:   * Side effects:
2378   *      Grid-related information will be passed to the window manager, so   *      Grid-related information will be passed to the window manager, so
2379   *      that the top-level window associated with tkwin will resize on   *      that the top-level window associated with tkwin will resize on
2380   *      even grid units.  If some other window already controls gridding   *      even grid units.  If some other window already controls gridding
2381   *      for the top-level window then this procedure call has no effect.   *      for the top-level window then this procedure call has no effect.
2382   *   *
2383   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2384   */   */
2385    
2386  void  void
2387  Tk_SetGrid(tkwin, reqWidth, reqHeight, widthInc, heightInc)  Tk_SetGrid(tkwin, reqWidth, reqHeight, widthInc, heightInc)
2388      Tk_Window tkwin;            /* Token for window.  New window mgr info      Tk_Window tkwin;            /* Token for window.  New window mgr info
2389                                   * will be posted for the top-level window                                   * will be posted for the top-level window
2390                                   * associated with this window. */                                   * associated with this window. */
2391      int reqWidth;               /* Width (in grid units) corresponding to      int reqWidth;               /* Width (in grid units) corresponding to
2392                                   * the requested geometry for tkwin. */                                   * the requested geometry for tkwin. */
2393      int reqHeight;              /* Height (in grid units) corresponding to      int reqHeight;              /* Height (in grid units) corresponding to
2394                                   * the requested geometry for tkwin. */                                   * the requested geometry for tkwin. */
2395      int widthInc, heightInc;    /* Pixel increments corresponding to a      int widthInc, heightInc;    /* Pixel increments corresponding to a
2396                                   * change of one grid unit. */                                   * change of one grid unit. */
2397  {  {
2398      TkWindow *winPtr = (TkWindow *) tkwin;      TkWindow *winPtr = (TkWindow *) tkwin;
2399      register WmInfo *wmPtr;      register WmInfo *wmPtr;
2400    
2401      /*      /*
2402       * Find the top-level window for tkwin, plus the window manager       * Find the top-level window for tkwin, plus the window manager
2403       * information.       * information.
2404       */       */
2405    
2406      while (!(winPtr->flags & TK_TOP_LEVEL)) {      while (!(winPtr->flags & TK_TOP_LEVEL)) {
2407          winPtr = winPtr->parentPtr;          winPtr = winPtr->parentPtr;
2408      }      }
2409      wmPtr = winPtr->wmInfoPtr;      wmPtr = winPtr->wmInfoPtr;
2410    
2411      if ((wmPtr->gridWin != NULL) && (wmPtr->gridWin != tkwin)) {      if ((wmPtr->gridWin != NULL) && (wmPtr->gridWin != tkwin)) {
2412          return;          return;
2413      }      }
2414    
2415      if ((wmPtr->reqGridWidth == reqWidth)      if ((wmPtr->reqGridWidth == reqWidth)
2416              && (wmPtr->reqGridHeight == reqHeight)              && (wmPtr->reqGridHeight == reqHeight)
2417              && (wmPtr->widthInc == widthInc)              && (wmPtr->widthInc == widthInc)
2418              && (wmPtr->heightInc == heightInc)              && (wmPtr->heightInc == heightInc)
2419              && ((wmPtr->sizeHintsFlags & (PBaseSize|PResizeInc))              && ((wmPtr->sizeHintsFlags & (PBaseSize|PResizeInc))
2420                      == (PBaseSize|PResizeInc))) {                      == (PBaseSize|PResizeInc))) {
2421          return;          return;
2422      }      }
2423    
2424      /*      /*
2425       * If gridding was previously off, then forget about any window       * If gridding was previously off, then forget about any window
2426       * size requests made by the user or via "wm geometry":  these are       * size requests made by the user or via "wm geometry":  these are
2427       * in pixel units and there's no easy way to translate them to       * in pixel units and there's no easy way to translate them to
2428       * grid units since the new requested size of the top-level window in       * grid units since the new requested size of the top-level window in
2429       * pixels may not yet have been registered yet (it may filter up       * pixels may not yet have been registered yet (it may filter up
2430       * the hierarchy in DoWhenIdle handlers).  However, if the window       * the hierarchy in DoWhenIdle handlers).  However, if the window
2431       * has never been mapped yet then just leave the window size alone:       * has never been mapped yet then just leave the window size alone:
2432       * assume that it is intended to be in grid units but just happened       * assume that it is intended to be in grid units but just happened
2433       * to have been specified before this procedure was called.       * to have been specified before this procedure was called.
2434       */       */
2435    
2436      if ((wmPtr->gridWin == NULL) && !(wmPtr->flags & WM_NEVER_MAPPED)) {      if ((wmPtr->gridWin == NULL) && !(wmPtr->flags & WM_NEVER_MAPPED)) {
2437          wmPtr->width = -1;          wmPtr->width = -1;
2438          wmPtr->height = -1;          wmPtr->height = -1;
2439      }      }
2440    
2441      /*      /*
2442       * Set the new gridding information, and start the process of passing       * Set the new gridding information, and start the process of passing
2443       * all of this information to the window manager.       * all of this information to the window manager.
2444       */       */
2445    
2446      wmPtr->gridWin = tkwin;      wmPtr->gridWin = tkwin;
2447      wmPtr->reqGridWidth = reqWidth;      wmPtr->reqGridWidth = reqWidth;
2448      wmPtr->reqGridHeight = reqHeight;      wmPtr->reqGridHeight = reqHeight;
2449      wmPtr->widthInc = widthInc;      wmPtr->widthInc = widthInc;
2450      wmPtr->heightInc = heightInc;      wmPtr->heightInc = heightInc;
2451      wmPtr->sizeHintsFlags |= PBaseSize|PResizeInc;      wmPtr->sizeHintsFlags |= PBaseSize|PResizeInc;
2452      if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {      if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
2453          Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);          Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
2454          wmPtr->flags |= WM_UPDATE_PENDING;          wmPtr->flags |= WM_UPDATE_PENDING;
2455      }      }
2456  }  }
2457    
2458  /*  /*
2459   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2460   *   *
2461   * Tk_UnsetGrid --   * Tk_UnsetGrid --
2462   *   *
2463   *      This procedure cancels the effect of a previous call   *      This procedure cancels the effect of a previous call
2464   *      to Tk_SetGrid.   *      to Tk_SetGrid.
2465   *   *
2466   * Results:   * Results:
2467   *      None.   *      None.
2468   *   *