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

Diff of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkwindow.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   * tkWindow.c --   * tkWindow.c --
5   *   *
6   *      This file provides basic window-manipulation procedures,   *      This file provides basic window-manipulation procedures,
7   *      which are equivalent to procedures in Xlib (and even   *      which are equivalent to procedures in Xlib (and even
8   *      invoke them) but also maintain the local Tk_Window   *      invoke them) but also maintain the local Tk_Window
9   *      structure.   *      structure.
10   *   *
11   * Copyright (c) 1989-1994 The Regents of the University of California.   * Copyright (c) 1989-1994 The Regents of the University of California.
12   * Copyright (c) 1994-1997 Sun Microsystems, Inc.   * Copyright (c) 1994-1997 Sun Microsystems, Inc.
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: tkwindow.c,v 1.1.1.1 2001/06/13 05:12:54 dtashley Exp $   * RCS: @(#) $Id: tkwindow.c,v 1.1.1.1 2001/06/13 05:12:54 dtashley Exp $
18   */   */
19    
20  #include "tkPort.h"  #include "tkPort.h"
21  #include "tkInt.h"  #include "tkInt.h"
22    
23  #if !defined(__WIN32__) && !defined(MAC_TCL)  #if !defined(__WIN32__) && !defined(MAC_TCL)
24  #include "tkUnixInt.h"  #include "tkUnixInt.h"
25  #endif  #endif
26    
27    
28  typedef struct ThreadSpecificData {  typedef struct ThreadSpecificData {
29      int numMainWindows;    /* Count of numver of main windows currently      int numMainWindows;    /* Count of numver of main windows currently
30                              * open in this thread. */                              * open in this thread. */
31      TkMainInfo *mainWindowList;      TkMainInfo *mainWindowList;
32                             /* First in list of all main windows managed                             /* First in list of all main windows managed
33                              * by this thread. */                              * by this thread. */
34      TkDisplay *displayList;      TkDisplay *displayList;
35                             /* List of all displays currently in use by                             /* List of all displays currently in use by
36                              * the current thread. */                              * the current thread. */
37      int initialized;       /* 0 means the structures above need      int initialized;       /* 0 means the structures above need
38                              * initializing. */                              * initializing. */
39  } ThreadSpecificData;  } ThreadSpecificData;
40  static Tcl_ThreadDataKey dataKey;  static Tcl_ThreadDataKey dataKey;
41    
42  /*  /*
43   * The Mutex below is used to lock access to the Tk_Uid structs above.   * The Mutex below is used to lock access to the Tk_Uid structs above.
44   */   */
45    
46  TCL_DECLARE_MUTEX(windowMutex)  TCL_DECLARE_MUTEX(windowMutex)
47    
48  /*  /*
49   * Default values for "changes" and "atts" fields of TkWindows.  Note   * Default values for "changes" and "atts" fields of TkWindows.  Note
50   * that Tk always requests all events for all windows, except StructureNotify   * that Tk always requests all events for all windows, except StructureNotify
51   * events on internal windows:  these events are generated internally.   * events on internal windows:  these events are generated internally.
52   */   */
53    
54  static XWindowChanges defChanges = {  static XWindowChanges defChanges = {
55      0, 0, 1, 1, 0, 0, Above      0, 0, 1, 1, 0, 0, Above
56  };  };
57  #define ALL_EVENTS_MASK \  #define ALL_EVENTS_MASK \
58      KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask| \      KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask| \
59      EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask| \      EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask| \
60      VisibilityChangeMask|PropertyChangeMask|ColormapChangeMask      VisibilityChangeMask|PropertyChangeMask|ColormapChangeMask
61  static XSetWindowAttributes defAtts= {  static XSetWindowAttributes defAtts= {
62      None,                       /* background_pixmap */      None,                       /* background_pixmap */
63      0,                          /* background_pixel */      0,                          /* background_pixel */
64      CopyFromParent,             /* border_pixmap */      CopyFromParent,             /* border_pixmap */
65      0,                          /* border_pixel */      0,                          /* border_pixel */
66      NorthWestGravity,           /* bit_gravity */      NorthWestGravity,           /* bit_gravity */
67      NorthWestGravity,           /* win_gravity */      NorthWestGravity,           /* win_gravity */
68      NotUseful,                  /* backing_store */      NotUseful,                  /* backing_store */
69      (unsigned) ~0,              /* backing_planes */      (unsigned) ~0,              /* backing_planes */
70      0,                          /* backing_pixel */      0,                          /* backing_pixel */
71      False,                      /* save_under */      False,                      /* save_under */
72      ALL_EVENTS_MASK,            /* event_mask */      ALL_EVENTS_MASK,            /* event_mask */
73      0,                          /* do_not_propagate_mask */      0,                          /* do_not_propagate_mask */
74      False,                      /* override_redirect */      False,                      /* override_redirect */
75      CopyFromParent,             /* colormap */      CopyFromParent,             /* colormap */
76      None                        /* cursor */      None                        /* cursor */
77  };  };
78    
79  /*  /*
80   * The following structure defines all of the commands supported by   * The following structure defines all of the commands supported by
81   * Tk, and the C procedures that execute them.   * Tk, and the C procedures that execute them.
82   */   */
83    
84  typedef struct {  typedef struct {
85      char *name;                 /* Name of command. */      char *name;                 /* Name of command. */
86      Tcl_CmdProc *cmdProc;       /* Command's string-based procedure. */      Tcl_CmdProc *cmdProc;       /* Command's string-based procedure. */
87      Tcl_ObjCmdProc *objProc;    /* Command's object-based procedure. */      Tcl_ObjCmdProc *objProc;    /* Command's object-based procedure. */
88      int isSafe;                 /* If !0, this command will be exposed in      int isSafe;                 /* If !0, this command will be exposed in
89                                   * a safe interpreter. Otherwise it will be                                   * a safe interpreter. Otherwise it will be
90                                   * hidden in a safe interpreter. */                                   * hidden in a safe interpreter. */
91      int passMainWindow;         /* 0 means provide NULL clientData to      int passMainWindow;         /* 0 means provide NULL clientData to
92                                   * command procedure; 1 means pass main                                   * command procedure; 1 means pass main
93                                   * window as clientData to command                                   * window as clientData to command
94                                   * procedure. */                                   * procedure. */
95  } TkCmd;  } TkCmd;
96    
97  static TkCmd commands[] = {  static TkCmd commands[] = {
98      /*      /*
99       * Commands that are part of the intrinsics:       * Commands that are part of the intrinsics:
100       */       */
101    
102      {"bell",            NULL,                   Tk_BellObjCmd,          0, 1},      {"bell",            NULL,                   Tk_BellObjCmd,          0, 1},
103      {"bind",            Tk_BindCmd,             NULL,                   1, 1},      {"bind",            Tk_BindCmd,             NULL,                   1, 1},
104      {"bindtags",        Tk_BindtagsCmd,         NULL,                   1, 1},      {"bindtags",        Tk_BindtagsCmd,         NULL,                   1, 1},
105      {"clipboard",       Tk_ClipboardCmd,        NULL,                   0, 1},      {"clipboard",       Tk_ClipboardCmd,        NULL,                   0, 1},
106      {"destroy",         NULL,                   Tk_DestroyObjCmd,       1, 1},      {"destroy",         NULL,                   Tk_DestroyObjCmd,       1, 1},
107      {"event",           NULL,                   Tk_EventObjCmd,         1, 1},      {"event",           NULL,                   Tk_EventObjCmd,         1, 1},
108      {"focus",           NULL,                   Tk_FocusObjCmd,         1, 1},      {"focus",           NULL,                   Tk_FocusObjCmd,         1, 1},
109      {"font",            NULL,                   Tk_FontObjCmd,          1, 1},      {"font",            NULL,                   Tk_FontObjCmd,          1, 1},
110      {"grab",            Tk_GrabCmd,             NULL,                   0, 1},      {"grab",            Tk_GrabCmd,             NULL,                   0, 1},
111      {"grid",            Tk_GridCmd,             NULL,                   1, 1},      {"grid",            Tk_GridCmd,             NULL,                   1, 1},
112      {"image",           NULL,                   Tk_ImageObjCmd,         1, 1},      {"image",           NULL,                   Tk_ImageObjCmd,         1, 1},
113      {"lower",           NULL,                   Tk_LowerObjCmd,         1, 1},      {"lower",           NULL,                   Tk_LowerObjCmd,         1, 1},
114      {"option",          NULL,                   Tk_OptionObjCmd,        1, 1},      {"option",          NULL,                   Tk_OptionObjCmd,        1, 1},
115      {"pack",            Tk_PackCmd,             NULL,                   1, 1},      {"pack",            Tk_PackCmd,             NULL,                   1, 1},
116      {"place",           Tk_PlaceCmd,            NULL,                   1, 1},      {"place",           Tk_PlaceCmd,            NULL,                   1, 1},
117      {"raise",           NULL,                   Tk_RaiseObjCmd,         1, 1},      {"raise",           NULL,                   Tk_RaiseObjCmd,         1, 1},
118      {"selection",       Tk_SelectionCmd,        NULL,                   0, 1},      {"selection",       Tk_SelectionCmd,        NULL,                   0, 1},
119      {"tk",              NULL,                   Tk_TkObjCmd,            0, 1},      {"tk",              NULL,                   Tk_TkObjCmd,            0, 1},
120      {"tkwait",          Tk_TkwaitCmd,           NULL,                   1, 1},      {"tkwait",          Tk_TkwaitCmd,           NULL,                   1, 1},
121  #if defined(__WIN32__) || defined(MAC_TCL)  #if defined(__WIN32__) || defined(MAC_TCL)
122      {"tk_chooseColor",  NULL,                   Tk_ChooseColorObjCmd,   0, 1},      {"tk_chooseColor",  NULL,                   Tk_ChooseColorObjCmd,   0, 1},
123      {"tk_chooseDirectory", NULL,                Tk_ChooseDirectoryObjCmd, 0, 1},      {"tk_chooseDirectory", NULL,                Tk_ChooseDirectoryObjCmd, 0, 1},
124      {"tk_getOpenFile",  NULL,                   Tk_GetOpenFileObjCmd,   0, 1},      {"tk_getOpenFile",  NULL,                   Tk_GetOpenFileObjCmd,   0, 1},
125      {"tk_getSaveFile",  NULL,                   Tk_GetSaveFileObjCmd,   0, 1},      {"tk_getSaveFile",  NULL,                   Tk_GetSaveFileObjCmd,   0, 1},
126  #endif  #endif
127  #ifdef __WIN32__  #ifdef __WIN32__
128      {"tk_messageBox",   NULL,                   Tk_MessageBoxObjCmd,    0, 1},      {"tk_messageBox",   NULL,                   Tk_MessageBoxObjCmd,    0, 1},
129  #endif  #endif
130      {"update",          NULL,                   Tk_UpdateObjCmd,        1, 1},      {"update",          NULL,                   Tk_UpdateObjCmd,        1, 1},
131      {"winfo",           NULL,                   Tk_WinfoObjCmd,         1, 1},      {"winfo",           NULL,                   Tk_WinfoObjCmd,         1, 1},
132      {"wm",              Tk_WmCmd,               NULL,                   0, 1},      {"wm",              Tk_WmCmd,               NULL,                   0, 1},
133    
134      /*      /*
135       * Widget class commands.       * Widget class commands.
136       */       */
137    
138      {"button",          NULL,                   Tk_ButtonObjCmd,        1, 0},      {"button",          NULL,                   Tk_ButtonObjCmd,        1, 0},
139      {"canvas",          NULL,                   Tk_CanvasObjCmd,        1, 1},      {"canvas",          NULL,                   Tk_CanvasObjCmd,        1, 1},
140      {"checkbutton",     NULL,                   Tk_CheckbuttonObjCmd,   1, 0},      {"checkbutton",     NULL,                   Tk_CheckbuttonObjCmd,   1, 0},
141      {"entry",           NULL,                   Tk_EntryObjCmd,         1, 0},      {"entry",           NULL,                   Tk_EntryObjCmd,         1, 0},
142      {"frame",           NULL,                   Tk_FrameObjCmd,         1, 1},      {"frame",           NULL,                   Tk_FrameObjCmd,         1, 1},
143      {"label",           NULL,                   Tk_LabelObjCmd,         1, 0},      {"label",           NULL,                   Tk_LabelObjCmd,         1, 0},
144      {"listbox",         NULL,                   Tk_ListboxObjCmd,       1, 0},      {"listbox",         NULL,                   Tk_ListboxObjCmd,       1, 0},
145      {"menubutton",      NULL,                   Tk_MenubuttonObjCmd,    1, 0},      {"menubutton",      NULL,                   Tk_MenubuttonObjCmd,    1, 0},
146      {"message",         Tk_MessageCmd,          NULL,                   1, 1},      {"message",         Tk_MessageCmd,          NULL,                   1, 1},
147      {"radiobutton",     NULL,                   Tk_RadiobuttonObjCmd,   1, 0},      {"radiobutton",     NULL,                   Tk_RadiobuttonObjCmd,   1, 0},
148      {"scale",           NULL,                   Tk_ScaleObjCmd,         1, 0},      {"scale",           NULL,                   Tk_ScaleObjCmd,         1, 0},
149      {"scrollbar",       Tk_ScrollbarCmd,        NULL,                   1, 1},      {"scrollbar",       Tk_ScrollbarCmd,        NULL,                   1, 1},
150      {"text",            Tk_TextCmd,             NULL,                   1, 1},      {"text",            Tk_TextCmd,             NULL,                   1, 1},
151      {"toplevel",        NULL,                   Tk_ToplevelObjCmd,      0, 1},      {"toplevel",        NULL,                   Tk_ToplevelObjCmd,      0, 1},
152    
153      /*      /*
154       * Misc.       * Misc.
155       */       */
156    
157  #ifdef MAC_TCL  #ifdef MAC_TCL
158      {"unsupported1",    TkUnsupported1Cmd,      NULL,                   1, 1},      {"unsupported1",    TkUnsupported1Cmd,      NULL,                   1, 1},
159  #endif  #endif
160      {(char *) NULL,     (int (*) _ANSI_ARGS_((ClientData, Tcl_Interp *, int, char **))) NULL, NULL, 0}      {(char *) NULL,     (int (*) _ANSI_ARGS_((ClientData, Tcl_Interp *, int, char **))) NULL, NULL, 0}
161  };  };
162    
163  /*  /*
164   * The variables and table below are used to parse arguments from   * The variables and table below are used to parse arguments from
165   * the "argv" variable in Tk_Init.   * the "argv" variable in Tk_Init.
166   */   */
167    
168  static int synchronize = 0;  static int synchronize = 0;
169  static char *name = NULL;  static char *name = NULL;
170  static char *display = NULL;  static char *display = NULL;
171  static char *geometry = NULL;  static char *geometry = NULL;
172  static char *colormap = NULL;  static char *colormap = NULL;
173  static char *use = NULL;  static char *use = NULL;
174  static char *visual = NULL;  static char *visual = NULL;
175  static int rest = 0;  static int rest = 0;
176    
177  static Tk_ArgvInfo argTable[] = {  static Tk_ArgvInfo argTable[] = {
178      {"-colormap", TK_ARGV_STRING, (char *) NULL, (char *) &colormap,      {"-colormap", TK_ARGV_STRING, (char *) NULL, (char *) &colormap,
179          "Colormap for main window"},          "Colormap for main window"},
180      {"-display", TK_ARGV_STRING, (char *) NULL, (char *) &display,      {"-display", TK_ARGV_STRING, (char *) NULL, (char *) &display,
181          "Display to use"},          "Display to use"},
182      {"-geometry", TK_ARGV_STRING, (char *) NULL, (char *) &geometry,      {"-geometry", TK_ARGV_STRING, (char *) NULL, (char *) &geometry,
183          "Initial geometry for window"},          "Initial geometry for window"},
184      {"-name", TK_ARGV_STRING, (char *) NULL, (char *) &name,      {"-name", TK_ARGV_STRING, (char *) NULL, (char *) &name,
185          "Name to use for application"},          "Name to use for application"},
186      {"-sync", TK_ARGV_CONSTANT, (char *) 1, (char *) &synchronize,      {"-sync", TK_ARGV_CONSTANT, (char *) 1, (char *) &synchronize,
187          "Use synchronous mode for display server"},          "Use synchronous mode for display server"},
188      {"-visual", TK_ARGV_STRING, (char *) NULL, (char *) &visual,      {"-visual", TK_ARGV_STRING, (char *) NULL, (char *) &visual,
189          "Visual for main window"},          "Visual for main window"},
190      {"-use", TK_ARGV_STRING, (char *) NULL, (char *) &use,      {"-use", TK_ARGV_STRING, (char *) NULL, (char *) &use,
191          "Id of window in which to embed application"},          "Id of window in which to embed application"},
192      {"--", TK_ARGV_REST, (char *) 1, (char *) &rest,      {"--", TK_ARGV_REST, (char *) 1, (char *) &rest,
193          "Pass all remaining arguments through to script"},          "Pass all remaining arguments through to script"},
194      {(char *) NULL, TK_ARGV_END, (char *) NULL, (char *) NULL,      {(char *) NULL, TK_ARGV_END, (char *) NULL, (char *) NULL,
195          (char *) NULL}          (char *) NULL}
196  };  };
197    
198  /*  /*
199   * Forward declarations to procedures defined later in this file:   * Forward declarations to procedures defined later in this file:
200   */   */
201    
202  static Tk_Window        CreateTopLevelWindow _ANSI_ARGS_((Tcl_Interp *interp,  static Tk_Window        CreateTopLevelWindow _ANSI_ARGS_((Tcl_Interp *interp,
203                              Tk_Window parent, char *name, char *screenName));                              Tk_Window parent, char *name, char *screenName));
204  static void             DeleteWindowsExitProc _ANSI_ARGS_((  static void             DeleteWindowsExitProc _ANSI_ARGS_((
205                              ClientData clientData));                              ClientData clientData));
206  static TkDisplay *      GetScreen _ANSI_ARGS_((Tcl_Interp *interp,  static TkDisplay *      GetScreen _ANSI_ARGS_((Tcl_Interp *interp,
207                              char *screenName, int *screenPtr));                              char *screenName, int *screenPtr));
208  static int              Initialize _ANSI_ARGS_((Tcl_Interp *interp));  static int              Initialize _ANSI_ARGS_((Tcl_Interp *interp));
209  static int              NameWindow _ANSI_ARGS_((Tcl_Interp *interp,  static int              NameWindow _ANSI_ARGS_((Tcl_Interp *interp,
210                              TkWindow *winPtr, TkWindow *parentPtr,                              TkWindow *winPtr, TkWindow *parentPtr,
211                              char *name));                              char *name));
212  static void             OpenIM _ANSI_ARGS_((TkDisplay *dispPtr));  static void             OpenIM _ANSI_ARGS_((TkDisplay *dispPtr));
213  static void             UnlinkWindow _ANSI_ARGS_((TkWindow *winPtr));  static void             UnlinkWindow _ANSI_ARGS_((TkWindow *winPtr));
214    
215  /*  /*
216   *----------------------------------------------------------------------   *----------------------------------------------------------------------
217   *   *
218   * CreateTopLevelWindow --   * CreateTopLevelWindow --
219   *   *
220   *      Make a new window that will be at top-level (its parent will   *      Make a new window that will be at top-level (its parent will
221   *      be the root window of a screen).   *      be the root window of a screen).
222   *   *
223   * Results:   * Results:
224   *      The return value is a token for the new window, or NULL if   *      The return value is a token for the new window, or NULL if
225   *      an error prevented the new window from being created.  If   *      an error prevented the new window from being created.  If
226   *      NULL is returned, an error message will be left in   *      NULL is returned, an error message will be left in
227   *      the interp's result.   *      the interp's result.
228   *   *
229   * Side effects:   * Side effects:
230   *      A new window structure is allocated locally.  An X   *      A new window structure is allocated locally.  An X
231   *      window is NOT initially created, but will be created   *      window is NOT initially created, but will be created
232   *      the first time the window is mapped.   *      the first time the window is mapped.
233   *   *
234   *----------------------------------------------------------------------   *----------------------------------------------------------------------
235   */   */
236    
237  static Tk_Window  static Tk_Window
238  CreateTopLevelWindow(interp, parent, name, screenName)  CreateTopLevelWindow(interp, parent, name, screenName)
239      Tcl_Interp *interp;         /* Interpreter to use for error reporting. */      Tcl_Interp *interp;         /* Interpreter to use for error reporting. */
240      Tk_Window parent;           /* Token for logical parent of new window      Tk_Window parent;           /* Token for logical parent of new window
241                                   * (used for naming, options, etc.).  May                                   * (used for naming, options, etc.).  May
242                                   * be NULL. */                                   * be NULL. */
243      char *name;                 /* Name for new window;  if parent is      char *name;                 /* Name for new window;  if parent is
244                                   * non-NULL, must be unique among parent's                                   * non-NULL, must be unique among parent's
245                                   * children. */                                   * children. */
246      char *screenName;           /* Name of screen on which to create      char *screenName;           /* Name of screen on which to create
247                                   * window.  NULL means use DISPLAY environment                                   * window.  NULL means use DISPLAY environment
248                                   * variable to determine.  Empty string means                                   * variable to determine.  Empty string means
249                                   * use parent's screen, or DISPLAY if no                                   * use parent's screen, or DISPLAY if no
250                                   * parent. */                                   * parent. */
251  {  {
252      register TkWindow *winPtr;      register TkWindow *winPtr;
253      register TkDisplay *dispPtr;      register TkDisplay *dispPtr;
254      int screenId;      int screenId;
255      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
256              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
257    
258      if (!tsdPtr->initialized) {      if (!tsdPtr->initialized) {
259          tsdPtr->initialized = 1;          tsdPtr->initialized = 1;
260    
261          /*          /*
262           * Create built-in image types.           * Create built-in image types.
263           */           */
264            
265          Tk_CreateImageType(&tkBitmapImageType);          Tk_CreateImageType(&tkBitmapImageType);
266          Tk_CreateImageType(&tkPhotoImageType);          Tk_CreateImageType(&tkPhotoImageType);
267            
268          /*          /*
269           * Create built-in photo image formats.           * Create built-in photo image formats.
270           */           */
271            
272          Tk_CreatePhotoImageFormat(&tkImgFmtGIF);          Tk_CreatePhotoImageFormat(&tkImgFmtGIF);
273          Tk_CreateOldPhotoImageFormat(&tkImgFmtPPM);          Tk_CreateOldPhotoImageFormat(&tkImgFmtPPM);
274    
275          /*          /*
276           * Create exit handler to delete all windows when the application           * Create exit handler to delete all windows when the application
277           * exits.           * exits.
278           */           */
279    
280          Tcl_CreateExitHandler(DeleteWindowsExitProc, (ClientData) NULL);          Tcl_CreateExitHandler(DeleteWindowsExitProc, (ClientData) NULL);
281      }      }
282    
283      if ((parent != NULL) && (screenName != NULL) && (screenName[0] == '\0')) {      if ((parent != NULL) && (screenName != NULL) && (screenName[0] == '\0')) {
284          dispPtr = ((TkWindow *) parent)->dispPtr;          dispPtr = ((TkWindow *) parent)->dispPtr;
285          screenId = Tk_ScreenNumber(parent);          screenId = Tk_ScreenNumber(parent);
286      } else {      } else {
287          dispPtr = GetScreen(interp, screenName, &screenId);          dispPtr = GetScreen(interp, screenName, &screenId);
288          if (dispPtr == NULL) {          if (dispPtr == NULL) {
289              return (Tk_Window) NULL;              return (Tk_Window) NULL;
290          }          }
291      }      }
292    
293      winPtr = TkAllocWindow(dispPtr, screenId, (TkWindow *) parent);      winPtr = TkAllocWindow(dispPtr, screenId, (TkWindow *) parent);
294    
295      /*      /*
296       * Force the window to use a border pixel instead of border pixmap.       * Force the window to use a border pixel instead of border pixmap.
297       * This is needed for the case where the window doesn't use the       * This is needed for the case where the window doesn't use the
298       * default visual.  In this case, the default border is a pixmap       * default visual.  In this case, the default border is a pixmap
299       * inherited from the root window, which won't work because it will       * inherited from the root window, which won't work because it will
300       * have the wrong visual.       * have the wrong visual.
301       */       */
302    
303      winPtr->dirtyAtts |= CWBorderPixel;      winPtr->dirtyAtts |= CWBorderPixel;
304    
305      /*      /*
306       * (Need to set the TK_TOP_LEVEL flag immediately here;  otherwise       * (Need to set the TK_TOP_LEVEL flag immediately here;  otherwise
307       * Tk_DestroyWindow will core dump if it is called before the flag       * Tk_DestroyWindow will core dump if it is called before the flag
308       * has been set.)       * has been set.)
309       */       */
310    
311      winPtr->flags |= TK_TOP_LEVEL;      winPtr->flags |= TK_TOP_LEVEL;
312    
313      if (parent != NULL) {      if (parent != NULL) {
314          if (NameWindow(interp, winPtr, (TkWindow *) parent, name) != TCL_OK) {          if (NameWindow(interp, winPtr, (TkWindow *) parent, name) != TCL_OK) {
315              Tk_DestroyWindow((Tk_Window) winPtr);              Tk_DestroyWindow((Tk_Window) winPtr);
316              return (Tk_Window) NULL;              return (Tk_Window) NULL;
317          }          }
318      }      }
319      TkWmNewWindow(winPtr);      TkWmNewWindow(winPtr);
320    
321      return (Tk_Window) winPtr;      return (Tk_Window) winPtr;
322  }  }
323    
324  /*  /*
325   *----------------------------------------------------------------------   *----------------------------------------------------------------------
326   *   *
327   * GetScreen --   * GetScreen --
328   *   *
329   *      Given a string name for a display-plus-screen, find the   *      Given a string name for a display-plus-screen, find the
330   *      TkDisplay structure for the display and return the screen   *      TkDisplay structure for the display and return the screen
331   *      number too.   *      number too.
332   *   *
333   * Results:   * Results:
334   *      The return value is a pointer to information about the display,   *      The return value is a pointer to information about the display,
335   *      or NULL if the display couldn't be opened.  In this case, an   *      or NULL if the display couldn't be opened.  In this case, an
336   *      error message is left in the interp's result.  The location at   *      error message is left in the interp's result.  The location at
337   *      *screenPtr is overwritten with the screen number parsed from   *      *screenPtr is overwritten with the screen number parsed from
338   *      screenName.   *      screenName.
339   *   *
340   * Side effects:   * Side effects:
341   *      A new connection is opened to the display if there is no   *      A new connection is opened to the display if there is no
342   *      connection already.  A new TkDisplay data structure is also   *      connection already.  A new TkDisplay data structure is also
343   *      setup, if necessary.   *      setup, if necessary.
344   *   *
345   *----------------------------------------------------------------------   *----------------------------------------------------------------------
346   */   */
347    
348  static TkDisplay *  static TkDisplay *
349  GetScreen(interp, screenName, screenPtr)  GetScreen(interp, screenName, screenPtr)
350      Tcl_Interp *interp;         /* Place to leave error message. */      Tcl_Interp *interp;         /* Place to leave error message. */
351      char *screenName;           /* Name for screen.  NULL or empty means      char *screenName;           /* Name for screen.  NULL or empty means
352                                   * use DISPLAY envariable. */                                   * use DISPLAY envariable. */
353      int *screenPtr;             /* Where to store screen number. */      int *screenPtr;             /* Where to store screen number. */
354  {  {
355      register TkDisplay *dispPtr;      register TkDisplay *dispPtr;
356      char *p;      char *p;
357      int screenId;      int screenId;
358      size_t length;      size_t length;
359      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
360              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
361    
362      /*      /*
363       * Separate the screen number from the rest of the display       * Separate the screen number from the rest of the display
364       * name.  ScreenName is assumed to have the syntax       * name.  ScreenName is assumed to have the syntax
365       * <display>.<screen> with the dot and the screen being       * <display>.<screen> with the dot and the screen being
366       * optional.       * optional.
367       */       */
368    
369      screenName = TkGetDefaultScreenName(interp, screenName);      screenName = TkGetDefaultScreenName(interp, screenName);
370      if (screenName == NULL) {      if (screenName == NULL) {
371          Tcl_SetResult(interp,          Tcl_SetResult(interp,
372                  "no display name and no $DISPLAY environment variable",                  "no display name and no $DISPLAY environment variable",
373                  TCL_STATIC);                  TCL_STATIC);
374          return (TkDisplay *) NULL;          return (TkDisplay *) NULL;
375      }      }
376      length = strlen(screenName);      length = strlen(screenName);
377      screenId = 0;      screenId = 0;
378      p = screenName+length-1;      p = screenName+length-1;
379      while (isdigit(UCHAR(*p)) && (p != screenName)) {      while (isdigit(UCHAR(*p)) && (p != screenName)) {
380          p--;          p--;
381      }      }
382      if ((*p == '.') && (p[1] != '\0')) {      if ((*p == '.') && (p[1] != '\0')) {
383          length = p - screenName;          length = p - screenName;
384          screenId = strtoul(p+1, (char **) NULL, 10);          screenId = strtoul(p+1, (char **) NULL, 10);
385      }      }
386    
387      /*      /*
388       * See if we already have a connection to this display.  If not,       * See if we already have a connection to this display.  If not,
389       * then open a new connection.       * then open a new connection.
390       */       */
391    
392      for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) {      for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) {
393          if (dispPtr == NULL) {          if (dispPtr == NULL) {
394              dispPtr = TkpOpenDisplay(screenName);              dispPtr = TkpOpenDisplay(screenName);
395              if (dispPtr == NULL) {              if (dispPtr == NULL) {
396                  Tcl_AppendResult(interp, "couldn't connect to display \"",                  Tcl_AppendResult(interp, "couldn't connect to display \"",
397                          screenName, "\"", (char *) NULL);                          screenName, "\"", (char *) NULL);
398                  return (TkDisplay *) NULL;                  return (TkDisplay *) NULL;
399              }              }
400              dispPtr->nextPtr = TkGetDisplayList();              dispPtr->nextPtr = TkGetDisplayList();
401              dispPtr->name = (char *) ckalloc((unsigned) (length+1));              dispPtr->name = (char *) ckalloc((unsigned) (length+1));
402              dispPtr->lastEventTime = CurrentTime;              dispPtr->lastEventTime = CurrentTime;
403              dispPtr->borderInit = 0;              dispPtr->borderInit = 0;
404              dispPtr->atomInit = 0;              dispPtr->atomInit = 0;
405              dispPtr->bindInfoStale = 1;              dispPtr->bindInfoStale = 1;
406              dispPtr->modeModMask = 0;              dispPtr->modeModMask = 0;
407              dispPtr->metaModMask = 0;              dispPtr->metaModMask = 0;
408              dispPtr->altModMask = 0;              dispPtr->altModMask = 0;
409              dispPtr->numModKeyCodes = 0;              dispPtr->numModKeyCodes = 0;
410              dispPtr->modKeyCodes = NULL;              dispPtr->modKeyCodes = NULL;
411              dispPtr->bitmapInit = 0;              dispPtr->bitmapInit = 0;
412              dispPtr->bitmapAutoNumber = 0;              dispPtr->bitmapAutoNumber = 0;
413              dispPtr->numIdSearches = 0;              dispPtr->numIdSearches = 0;
414              dispPtr->numSlowSearches = 0;              dispPtr->numSlowSearches = 0;
415              dispPtr->colorInit = 0;              dispPtr->colorInit = 0;
416              dispPtr->stressPtr = NULL;              dispPtr->stressPtr = NULL;
417              dispPtr->cursorInit = 0;              dispPtr->cursorInit = 0;
418              dispPtr->cursorString[0] = '\0';              dispPtr->cursorString[0] = '\0';
419              dispPtr->cursorFont = None;              dispPtr->cursorFont = None;
420              dispPtr->errorPtr = NULL;              dispPtr->errorPtr = NULL;
421              dispPtr->deleteCount = 0;              dispPtr->deleteCount = 0;
422              dispPtr->delayedMotionPtr = NULL;              dispPtr->delayedMotionPtr = NULL;
423              dispPtr->focusDebug = 0;              dispPtr->focusDebug = 0;
424              dispPtr->implicitWinPtr = NULL;              dispPtr->implicitWinPtr = NULL;
425              dispPtr->focusPtr = NULL;              dispPtr->focusPtr = NULL;
426              dispPtr->gcInit = 0;              dispPtr->gcInit = 0;
427              dispPtr->geomInit = 0;              dispPtr->geomInit = 0;
428              dispPtr->uidInit = 0;              dispPtr->uidInit = 0;
429              dispPtr->grabWinPtr = NULL;              dispPtr->grabWinPtr = NULL;
430              dispPtr->eventualGrabWinPtr = NULL;              dispPtr->eventualGrabWinPtr = NULL;
431              dispPtr->buttonWinPtr = NULL;              dispPtr->buttonWinPtr = NULL;
432              dispPtr->serverWinPtr = NULL;              dispPtr->serverWinPtr = NULL;
433              dispPtr->firstGrabEventPtr = NULL;              dispPtr->firstGrabEventPtr = NULL;
434              dispPtr->lastGrabEventPtr = NULL;              dispPtr->lastGrabEventPtr = NULL;
435              dispPtr->grabFlags = 0;              dispPtr->grabFlags = 0;
436              dispPtr->mouseButtonState = 0;              dispPtr->mouseButtonState = 0;
437              dispPtr->warpInProgress = 0;              dispPtr->warpInProgress = 0;
438              dispPtr->warpWindow = None;              dispPtr->warpWindow = None;
439              dispPtr->warpX = 0;              dispPtr->warpX = 0;
440              dispPtr->warpY = 0;              dispPtr->warpY = 0;
441              dispPtr->gridInit = 0;              dispPtr->gridInit = 0;
442              dispPtr->imageId = 0;              dispPtr->imageId = 0;
443              dispPtr->packInit = 0;              dispPtr->packInit = 0;
444              dispPtr->placeInit = 0;              dispPtr->placeInit = 0;
445              dispPtr->selectionInfoPtr = NULL;              dispPtr->selectionInfoPtr = NULL;
446              dispPtr->multipleAtom = None;              dispPtr->multipleAtom = None;
447              dispPtr->clipWindow = NULL;              dispPtr->clipWindow = NULL;
448              dispPtr->clipboardActive = 0;              dispPtr->clipboardActive = 0;
449              dispPtr->clipboardAppPtr = NULL;              dispPtr->clipboardAppPtr = NULL;
450              dispPtr->clipTargetPtr = NULL;              dispPtr->clipTargetPtr = NULL;
451              dispPtr->commTkwin = NULL;              dispPtr->commTkwin = NULL;
452              dispPtr->wmTracing = 0;              dispPtr->wmTracing = 0;
453              dispPtr->firstWmPtr = NULL;              dispPtr->firstWmPtr = NULL;
454              dispPtr->foregroundWmPtr = NULL;              dispPtr->foregroundWmPtr = NULL;
455              dispPtr->destroyCount = 0;              dispPtr->destroyCount = 0;
456              dispPtr->lastDestroyRequest = 0;              dispPtr->lastDestroyRequest = 0;
457              dispPtr->cmapPtr = NULL;              dispPtr->cmapPtr = NULL;
458              Tcl_InitHashTable(&dispPtr->winTable, TCL_ONE_WORD_KEYS);              Tcl_InitHashTable(&dispPtr->winTable, TCL_ONE_WORD_KEYS);
459    
460              dispPtr->refCount = 0;              dispPtr->refCount = 0;
461              strncpy(dispPtr->name, screenName, length);              strncpy(dispPtr->name, screenName, length);
462              dispPtr->name[length] = '\0';              dispPtr->name[length] = '\0';
463              dispPtr->useInputMethods = 0;              dispPtr->useInputMethods = 0;
464              OpenIM(dispPtr);              OpenIM(dispPtr);
465              TkInitXId(dispPtr);              TkInitXId(dispPtr);
466    
467              tsdPtr->displayList = dispPtr;              tsdPtr->displayList = dispPtr;
468              break;              break;
469          }          }
470          if ((strncmp(dispPtr->name, screenName, length) == 0)          if ((strncmp(dispPtr->name, screenName, length) == 0)
471                  && (dispPtr->name[length] == '\0')) {                  && (dispPtr->name[length] == '\0')) {
472              break;              break;
473          }          }
474      }      }
475      if (screenId >= ScreenCount(dispPtr->display)) {      if (screenId >= ScreenCount(dispPtr->display)) {
476          char buf[32 + TCL_INTEGER_SPACE];          char buf[32 + TCL_INTEGER_SPACE];
477                    
478          sprintf(buf, "bad screen number \"%d\"", screenId);          sprintf(buf, "bad screen number \"%d\"", screenId);
479          Tcl_SetResult(interp, buf, TCL_VOLATILE);          Tcl_SetResult(interp, buf, TCL_VOLATILE);
480          return (TkDisplay *) NULL;          return (TkDisplay *) NULL;
481      }      }
482      *screenPtr = screenId;      *screenPtr = screenId;
483      return dispPtr;      return dispPtr;
484  }  }
485    
486  /*  /*
487   *----------------------------------------------------------------------   *----------------------------------------------------------------------
488   *   *
489   * TkGetDisplay --   * TkGetDisplay --
490   *   *
491   *      Given an X display, TkGetDisplay returns the TkDisplay   *      Given an X display, TkGetDisplay returns the TkDisplay
492   *      structure for the display.   *      structure for the display.
493   *   *
494   * Results:   * Results:
495   *      The return value is a pointer to information about the display,   *      The return value is a pointer to information about the display,
496   *      or NULL if the display did not have a TkDisplay structure.   *      or NULL if the display did not have a TkDisplay structure.
497   *   *
498   * Side effects:   * Side effects:
499   *      None.   *      None.
500   *   *
501   *----------------------------------------------------------------------   *----------------------------------------------------------------------
502   */   */
503    
504  TkDisplay *  TkDisplay *
505  TkGetDisplay(display)  TkGetDisplay(display)
506       Display *display;          /* X's display pointer */       Display *display;          /* X's display pointer */
507  {  {
508      TkDisplay *dispPtr;      TkDisplay *dispPtr;
509      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
510              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
511    
512      for (dispPtr = tsdPtr->displayList; dispPtr != NULL;      for (dispPtr = tsdPtr->displayList; dispPtr != NULL;
513              dispPtr = dispPtr->nextPtr) {              dispPtr = dispPtr->nextPtr) {
514          if (dispPtr->display == display) {          if (dispPtr->display == display) {
515              break;              break;
516          }          }
517      }      }
518      return dispPtr;      return dispPtr;
519  }  }
520    
521  /*  /*
522   *--------------------------------------------------------------   *--------------------------------------------------------------
523   *   *
524   * TkGetDisplayList --   * TkGetDisplayList --
525   *   *
526   *      This procedure returns a pointer to the thread-local   *      This procedure returns a pointer to the thread-local
527   *      list of TkDisplays corresponding to the open displays.   *      list of TkDisplays corresponding to the open displays.
528   *   *
529   * Results:   * Results:
530   *      The return value is a pointer to the first TkDisplay   *      The return value is a pointer to the first TkDisplay
531   *      structure in thread-local-storage.   *      structure in thread-local-storage.
532   *   *
533   * Side effects:   * Side effects:
534   *      None.   *      None.
535   *   *
536   *--------------------------------------------------------------   *--------------------------------------------------------------
537   */   */
538  TkDisplay *  TkDisplay *
539  TkGetDisplayList()  TkGetDisplayList()
540  {  {
541      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
542              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
543            
544      return tsdPtr->displayList;      return tsdPtr->displayList;
545  }  }
546    
547  /*  /*
548   *--------------------------------------------------------------   *--------------------------------------------------------------
549   *   *
550   * TkGetMainInfoList --   * TkGetMainInfoList --
551   *   *
552   *      This procedure returns a pointer to the list of structures   *      This procedure returns a pointer to the list of structures
553   *      containing information about all main windows for the   *      containing information about all main windows for the
554   *      current thread.   *      current thread.
555   *   *
556   * Results:   * Results:
557   *      The return value is a pointer to the first TkMainInfo   *      The return value is a pointer to the first TkMainInfo
558   *      structure in thread local storage.   *      structure in thread local storage.
559   *   *
560   * Side effects:   * Side effects:
561   *      None.   *      None.
562   *   *
563   *--------------------------------------------------------------   *--------------------------------------------------------------
564   */   */
565  TkMainInfo *  TkMainInfo *
566  TkGetMainInfoList()  TkGetMainInfoList()
567  {  {
568      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
569              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
570            
571      return tsdPtr->mainWindowList;      return tsdPtr->mainWindowList;
572  }  }
573  /*  /*
574   *--------------------------------------------------------------   *--------------------------------------------------------------
575   *   *
576   * TkAllocWindow --   * TkAllocWindow --
577   *   *
578   *      This procedure creates and initializes a TkWindow structure.   *      This procedure creates and initializes a TkWindow structure.
579   *   *
580   * Results:   * Results:
581   *      The return value is a pointer to the new window.   *      The return value is a pointer to the new window.
582   *   *
583   * Side effects:   * Side effects:
584   *      A new window structure is allocated and all its fields are   *      A new window structure is allocated and all its fields are
585   *      initialized.   *      initialized.
586   *   *
587   *--------------------------------------------------------------   *--------------------------------------------------------------
588   */   */
589    
590  TkWindow *  TkWindow *
591  TkAllocWindow(dispPtr, screenNum, parentPtr)  TkAllocWindow(dispPtr, screenNum, parentPtr)
592      TkDisplay *dispPtr;         /* Display associated with new window. */      TkDisplay *dispPtr;         /* Display associated with new window. */
593      int screenNum;              /* Index of screen for new window. */      int screenNum;              /* Index of screen for new window. */
594      TkWindow *parentPtr;        /* Parent from which this window should      TkWindow *parentPtr;        /* Parent from which this window should
595                                   * inherit visual information.  NULL means                                   * inherit visual information.  NULL means
596                                   * use screen defaults instead of                                   * use screen defaults instead of
597                                   * inheriting. */                                   * inheriting. */
598  {  {
599      register TkWindow *winPtr;      register TkWindow *winPtr;
600    
601      winPtr = (TkWindow *) ckalloc(sizeof(TkWindow));      winPtr = (TkWindow *) ckalloc(sizeof(TkWindow));
602      winPtr->display = dispPtr->display;      winPtr->display = dispPtr->display;
603      winPtr->dispPtr = dispPtr;      winPtr->dispPtr = dispPtr;
604      winPtr->screenNum = screenNum;      winPtr->screenNum = screenNum;
605      if ((parentPtr != NULL) && (parentPtr->display == winPtr->display)      if ((parentPtr != NULL) && (parentPtr->display == winPtr->display)
606              && (parentPtr->screenNum == winPtr->screenNum)) {              && (parentPtr->screenNum == winPtr->screenNum)) {
607          winPtr->visual = parentPtr->visual;          winPtr->visual = parentPtr->visual;
608          winPtr->depth = parentPtr->depth;          winPtr->depth = parentPtr->depth;
609      } else {      } else {
610          winPtr->visual = DefaultVisual(dispPtr->display, screenNum);          winPtr->visual = DefaultVisual(dispPtr->display, screenNum);
611          winPtr->depth = DefaultDepth(dispPtr->display, screenNum);          winPtr->depth = DefaultDepth(dispPtr->display, screenNum);
612      }      }
613      winPtr->window = None;      winPtr->window = None;
614      winPtr->childList = NULL;      winPtr->childList = NULL;
615      winPtr->lastChildPtr = NULL;      winPtr->lastChildPtr = NULL;
616      winPtr->parentPtr = NULL;      winPtr->parentPtr = NULL;
617      winPtr->nextPtr = NULL;      winPtr->nextPtr = NULL;
618      winPtr->mainPtr = NULL;      winPtr->mainPtr = NULL;
619      winPtr->pathName = NULL;      winPtr->pathName = NULL;
620      winPtr->nameUid = NULL;      winPtr->nameUid = NULL;
621      winPtr->classUid = NULL;      winPtr->classUid = NULL;
622      winPtr->changes = defChanges;      winPtr->changes = defChanges;
623      winPtr->dirtyChanges = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;      winPtr->dirtyChanges = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;
624      winPtr->atts = defAtts;      winPtr->atts = defAtts;
625      if ((parentPtr != NULL) && (parentPtr->display == winPtr->display)      if ((parentPtr != NULL) && (parentPtr->display == winPtr->display)
626              && (parentPtr->screenNum == winPtr->screenNum)) {              && (parentPtr->screenNum == winPtr->screenNum)) {
627          winPtr->atts.colormap = parentPtr->atts.colormap;          winPtr->atts.colormap = parentPtr->atts.colormap;
628      } else {      } else {
629          winPtr->atts.colormap = DefaultColormap(dispPtr->display, screenNum);          winPtr->atts.colormap = DefaultColormap(dispPtr->display, screenNum);
630      }      }
631      winPtr->dirtyAtts = CWEventMask|CWColormap|CWBitGravity;      winPtr->dirtyAtts = CWEventMask|CWColormap|CWBitGravity;
632      winPtr->flags = 0;      winPtr->flags = 0;
633      winPtr->handlerList = NULL;      winPtr->handlerList = NULL;
634  #ifdef TK_USE_INPUT_METHODS  #ifdef TK_USE_INPUT_METHODS
635      winPtr->inputContext = NULL;      winPtr->inputContext = NULL;
636  #endif /* TK_USE_INPUT_METHODS */  #endif /* TK_USE_INPUT_METHODS */
637      winPtr->tagPtr = NULL;      winPtr->tagPtr = NULL;
638      winPtr->numTags = 0;      winPtr->numTags = 0;
639      winPtr->optionLevel = -1;      winPtr->optionLevel = -1;
640      winPtr->selHandlerList = NULL;      winPtr->selHandlerList = NULL;
641      winPtr->geomMgrPtr = NULL;      winPtr->geomMgrPtr = NULL;
642      winPtr->geomData = NULL;      winPtr->geomData = NULL;
643      winPtr->reqWidth = winPtr->reqHeight = 1;      winPtr->reqWidth = winPtr->reqHeight = 1;
644      winPtr->internalBorderWidth = 0;      winPtr->internalBorderWidth = 0;
645      winPtr->wmInfoPtr = NULL;      winPtr->wmInfoPtr = NULL;
646      winPtr->classProcsPtr = NULL;      winPtr->classProcsPtr = NULL;
647      winPtr->instanceData = NULL;      winPtr->instanceData = NULL;
648      winPtr->privatePtr = NULL;      winPtr->privatePtr = NULL;
649    
650      return winPtr;      return winPtr;
651  }  }
652    
653  /*  /*
654   *----------------------------------------------------------------------   *----------------------------------------------------------------------
655   *   *
656   * NameWindow --   * NameWindow --
657   *   *
658   *      This procedure is invoked to give a window a name and insert   *      This procedure is invoked to give a window a name and insert
659   *      the window into the hierarchy associated with a particular   *      the window into the hierarchy associated with a particular
660   *      application.   *      application.
661   *   *
662   * Results:   * Results:
663   *      A standard Tcl return value.   *      A standard Tcl return value.
664   *   *
665   * Side effects:   * Side effects:
666   *      See above.   *      See above.
667   *   *
668   *----------------------------------------------------------------------   *----------------------------------------------------------------------
669   */   */
670    
671  static int  static int
672  NameWindow(interp, winPtr, parentPtr, name)  NameWindow(interp, winPtr, parentPtr, name)
673      Tcl_Interp *interp;         /* Interpreter to use for error reporting. */      Tcl_Interp *interp;         /* Interpreter to use for error reporting. */
674      register TkWindow *winPtr;  /* Window that is to be named and inserted. */      register TkWindow *winPtr;  /* Window that is to be named and inserted. */
675      TkWindow *parentPtr;        /* Pointer to logical parent for winPtr      TkWindow *parentPtr;        /* Pointer to logical parent for winPtr
676                                   * (used for naming, options, etc.). */                                   * (used for naming, options, etc.). */
677      char *name;                 /* Name for winPtr;   must be unique among      char *name;                 /* Name for winPtr;   must be unique among
678                                   * parentPtr's children. */                                   * parentPtr's children. */
679  {  {
680  #define FIXED_SIZE 200  #define FIXED_SIZE 200
681      char staticSpace[FIXED_SIZE];      char staticSpace[FIXED_SIZE];
682      char *pathName;      char *pathName;
683      int new;      int new;
684      Tcl_HashEntry *hPtr;      Tcl_HashEntry *hPtr;
685      int length1, length2;      int length1, length2;
686    
687      /*      /*
688       * Setup all the stuff except name right away, then do the name stuff       * Setup all the stuff except name right away, then do the name stuff
689       * last.  This is so that if the name stuff fails, everything else       * last.  This is so that if the name stuff fails, everything else
690       * will be properly initialized (needed to destroy the window cleanly       * will be properly initialized (needed to destroy the window cleanly
691       * after the naming failure).       * after the naming failure).
692       */       */
693      winPtr->parentPtr = parentPtr;      winPtr->parentPtr = parentPtr;
694      winPtr->nextPtr = NULL;      winPtr->nextPtr = NULL;
695      if (parentPtr->childList == NULL) {      if (parentPtr->childList == NULL) {
696          parentPtr->childList = winPtr;          parentPtr->childList = winPtr;
697      } else {      } else {
698          parentPtr->lastChildPtr->nextPtr = winPtr;          parentPtr->lastChildPtr->nextPtr = winPtr;
699      }      }
700      parentPtr->lastChildPtr = winPtr;      parentPtr->lastChildPtr = winPtr;
701      winPtr->mainPtr = parentPtr->mainPtr;      winPtr->mainPtr = parentPtr->mainPtr;
702      winPtr->mainPtr->refCount++;      winPtr->mainPtr->refCount++;
703      winPtr->nameUid = Tk_GetUid(name);      winPtr->nameUid = Tk_GetUid(name);
704    
705      /*      /*
706       * Don't permit names that start with an upper-case letter:  this       * Don't permit names that start with an upper-case letter:  this
707       * will just cause confusion with class names in the option database.       * will just cause confusion with class names in the option database.
708       */       */
709    
710      if (isupper(UCHAR(name[0]))) {      if (isupper(UCHAR(name[0]))) {
711          Tcl_AppendResult(interp,          Tcl_AppendResult(interp,
712                  "window name starts with an upper-case letter: \"",                  "window name starts with an upper-case letter: \"",
713                  name, "\"", (char *) NULL);                  name, "\"", (char *) NULL);
714          return TCL_ERROR;          return TCL_ERROR;
715      }      }
716    
717      /*      /*
718       * To permit names of arbitrary length, must be prepared to malloc       * To permit names of arbitrary length, must be prepared to malloc
719       * a buffer to hold the new path name.  To run fast in the common       * a buffer to hold the new path name.  To run fast in the common
720       * case where names are short, use a fixed-size buffer on the       * case where names are short, use a fixed-size buffer on the
721       * stack.       * stack.
722       */       */
723    
724      length1 = strlen(parentPtr->pathName);      length1 = strlen(parentPtr->pathName);
725      length2 = strlen(name);      length2 = strlen(name);
726      if ((length1+length2+2) <= FIXED_SIZE) {      if ((length1+length2+2) <= FIXED_SIZE) {
727          pathName = staticSpace;          pathName = staticSpace;
728      } else {      } else {
729          pathName = (char *) ckalloc((unsigned) (length1+length2+2));          pathName = (char *) ckalloc((unsigned) (length1+length2+2));
730      }      }
731      if (length1 == 1) {      if (length1 == 1) {
732          pathName[0] = '.';          pathName[0] = '.';
733          strcpy(pathName+1, name);          strcpy(pathName+1, name);
734      } else {      } else {
735          strcpy(pathName, parentPtr->pathName);          strcpy(pathName, parentPtr->pathName);
736          pathName[length1] = '.';          pathName[length1] = '.';
737          strcpy(pathName+length1+1, name);          strcpy(pathName+length1+1, name);
738      }      }
739      hPtr = Tcl_CreateHashEntry(&parentPtr->mainPtr->nameTable, pathName, &new);      hPtr = Tcl_CreateHashEntry(&parentPtr->mainPtr->nameTable, pathName, &new);
740      if (pathName != staticSpace) {      if (pathName != staticSpace) {
741          ckfree(pathName);          ckfree(pathName);
742      }      }
743      if (!new) {      if (!new) {
744          Tcl_AppendResult(interp, "window name \"", name,          Tcl_AppendResult(interp, "window name \"", name,
745                  "\" already exists in parent", (char *) NULL);                  "\" already exists in parent", (char *) NULL);
746          return TCL_ERROR;          return TCL_ERROR;
747      }      }
748      Tcl_SetHashValue(hPtr, winPtr);      Tcl_SetHashValue(hPtr, winPtr);
749      winPtr->pathName = Tcl_GetHashKey(&parentPtr->mainPtr->nameTable, hPtr);      winPtr->pathName = Tcl_GetHashKey(&parentPtr->mainPtr->nameTable, hPtr);
750      return TCL_OK;      return TCL_OK;
751  }  }
752    
753  /*  /*
754   *----------------------------------------------------------------------   *----------------------------------------------------------------------
755   *   *
756   * TkCreateMainWindow --   * TkCreateMainWindow --
757   *   *
758   *      Make a new main window.  A main window is a special kind of   *      Make a new main window.  A main window is a special kind of
759   *      top-level window used as the outermost window in an   *      top-level window used as the outermost window in an
760   *      application.   *      application.
761   *   *
762   * Results:   * Results:
763   *      The return value is a token for the new window, or NULL if   *      The return value is a token for the new window, or NULL if
764   *      an error prevented the new window from being created.  If   *      an error prevented the new window from being created.  If
765   *      NULL is returned, an error message will be left in   *      NULL is returned, an error message will be left in
766   *      the interp's result.   *      the interp's result.
767   *   *
768   * Side effects:   * Side effects:
769   *      A new window structure is allocated locally;  "interp" is   *      A new window structure is allocated locally;  "interp" is
770   *      associated with the window and registered for "send" commands   *      associated with the window and registered for "send" commands
771   *      under "baseName".  BaseName may be extended with an instance   *      under "baseName".  BaseName may be extended with an instance
772   *      number in the form "#2" if necessary to make it globally   *      number in the form "#2" if necessary to make it globally
773   *      unique.  Tk-related commands are bound into interp.   *      unique.  Tk-related commands are bound into interp.
774   *   *
775   *----------------------------------------------------------------------   *----------------------------------------------------------------------
776   */   */
777    
778  Tk_Window  Tk_Window
779  TkCreateMainWindow(interp, screenName, baseName)  TkCreateMainWindow(interp, screenName, baseName)
780      Tcl_Interp *interp;         /* Interpreter to use for error reporting. */      Tcl_Interp *interp;         /* Interpreter to use for error reporting. */
781      char *screenName;           /* Name of screen on which to create      char *screenName;           /* Name of screen on which to create
782                                   * window.  Empty or NULL string means                                   * window.  Empty or NULL string means
783                                   * use DISPLAY environment variable. */                                   * use DISPLAY environment variable. */
784      char *baseName;             /* Base name for application;  usually of the      char *baseName;             /* Base name for application;  usually of the
785                                   * form "prog instance". */                                   * form "prog instance". */
786  {  {
787      Tk_Window tkwin;      Tk_Window tkwin;
788      int dummy;      int dummy;
789      int isSafe;      int isSafe;
790      Tcl_HashEntry *hPtr;      Tcl_HashEntry *hPtr;
791      register TkMainInfo *mainPtr;      register TkMainInfo *mainPtr;
792      register TkWindow *winPtr;      register TkWindow *winPtr;
793      register TkCmd *cmdPtr;      register TkCmd *cmdPtr;
794      ClientData clientData;      ClientData clientData;
795      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
796              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
797            
798      /*      /*
799       * Panic if someone updated the TkWindow structure without       * Panic if someone updated the TkWindow structure without
800       * also updating the Tk_FakeWin structure (or vice versa).       * also updating the Tk_FakeWin structure (or vice versa).
801       */       */
802    
803      if (sizeof(TkWindow) != sizeof(Tk_FakeWin)) {      if (sizeof(TkWindow) != sizeof(Tk_FakeWin)) {
804          panic("TkWindow and Tk_FakeWin are not the same size");          panic("TkWindow and Tk_FakeWin are not the same size");
805      }      }
806    
807      /*      /*
808       * Create the basic TkWindow structure.       * Create the basic TkWindow structure.
809       */       */
810    
811      tkwin = CreateTopLevelWindow(interp, (Tk_Window) NULL, baseName,      tkwin = CreateTopLevelWindow(interp, (Tk_Window) NULL, baseName,
812              screenName);              screenName);
813      if (tkwin == NULL) {      if (tkwin == NULL) {
814          return NULL;          return NULL;
815      }      }
816            
817      /*      /*
818       * Create the TkMainInfo structure for this application, and set       * Create the TkMainInfo structure for this application, and set
819       * up name-related information for the new window.       * up name-related information for the new window.
820       */       */
821    
822      winPtr = (TkWindow *) tkwin;      winPtr = (TkWindow *) tkwin;
823      mainPtr = (TkMainInfo *) ckalloc(sizeof(TkMainInfo));      mainPtr = (TkMainInfo *) ckalloc(sizeof(TkMainInfo));
824      mainPtr->winPtr = winPtr;      mainPtr->winPtr = winPtr;
825      mainPtr->refCount = 1;      mainPtr->refCount = 1;
826      mainPtr->interp = interp;      mainPtr->interp = interp;
827      Tcl_InitHashTable(&mainPtr->nameTable, TCL_STRING_KEYS);      Tcl_InitHashTable(&mainPtr->nameTable, TCL_STRING_KEYS);
828      TkEventInit();      TkEventInit();
829      TkBindInit(mainPtr);      TkBindInit(mainPtr);
830      TkFontPkgInit(mainPtr);      TkFontPkgInit(mainPtr);
831      mainPtr->tlFocusPtr = NULL;      mainPtr->tlFocusPtr = NULL;
832      mainPtr->displayFocusPtr = NULL;      mainPtr->displayFocusPtr = NULL;
833      mainPtr->optionRootPtr = NULL;      mainPtr->optionRootPtr = NULL;
834      Tcl_InitHashTable(&mainPtr->imageTable, TCL_STRING_KEYS);      Tcl_InitHashTable(&mainPtr->imageTable, TCL_STRING_KEYS);
835      mainPtr->strictMotif = 0;      mainPtr->strictMotif = 0;
836      if (Tcl_LinkVar(interp, "tk_strictMotif", (char *) &mainPtr->strictMotif,      if (Tcl_LinkVar(interp, "tk_strictMotif", (char *) &mainPtr->strictMotif,
837              TCL_LINK_BOOLEAN) != TCL_OK) {              TCL_LINK_BOOLEAN) != TCL_OK) {
838          Tcl_ResetResult(interp);          Tcl_ResetResult(interp);
839      }      }
840      mainPtr->nextPtr = tsdPtr->mainWindowList;      mainPtr->nextPtr = tsdPtr->mainWindowList;
841      tsdPtr->mainWindowList = mainPtr;      tsdPtr->mainWindowList = mainPtr;
842      winPtr->mainPtr = mainPtr;      winPtr->mainPtr = mainPtr;
843      hPtr = Tcl_CreateHashEntry(&mainPtr->nameTable, ".", &dummy);      hPtr = Tcl_CreateHashEntry(&mainPtr->nameTable, ".", &dummy);
844      Tcl_SetHashValue(hPtr, winPtr);      Tcl_SetHashValue(hPtr, winPtr);
845      winPtr->pathName = Tcl_GetHashKey(&mainPtr->nameTable, hPtr);      winPtr->pathName = Tcl_GetHashKey(&mainPtr->nameTable, hPtr);
846    
847      /*      /*
848       * We have just created another Tk application; increment the refcount       * We have just created another Tk application; increment the refcount
849       * on the display pointer.       * on the display pointer.
850       */       */
851    
852      winPtr->dispPtr->refCount++;      winPtr->dispPtr->refCount++;
853    
854      /*      /*
855       * Register the interpreter for "send" purposes.       * Register the interpreter for "send" purposes.
856       */       */
857    
858      winPtr->nameUid = Tk_GetUid(Tk_SetAppName(tkwin, baseName));      winPtr->nameUid = Tk_GetUid(Tk_SetAppName(tkwin, baseName));
859    
860      /*      /*
861       * Bind in Tk's commands.       * Bind in Tk's commands.
862       */       */
863    
864      isSafe = Tcl_IsSafe(interp);      isSafe = Tcl_IsSafe(interp);
865      for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {      for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
866          if ((cmdPtr->cmdProc == NULL) && (cmdPtr->objProc == NULL)) {          if ((cmdPtr->cmdProc == NULL) && (cmdPtr->objProc == NULL)) {
867              panic("TkCreateMainWindow: builtin command with NULL string and object procs");              panic("TkCreateMainWindow: builtin command with NULL string and object procs");
868          }          }
869          if (cmdPtr->passMainWindow) {          if (cmdPtr->passMainWindow) {
870              clientData = (ClientData) tkwin;              clientData = (ClientData) tkwin;
871          } else {          } else {
872              clientData = (ClientData) NULL;              clientData = (ClientData) NULL;
873          }          }
874          if (cmdPtr->cmdProc != NULL) {          if (cmdPtr->cmdProc != NULL) {
875              Tcl_CreateCommand(interp, cmdPtr->name, cmdPtr->cmdProc,              Tcl_CreateCommand(interp, cmdPtr->name, cmdPtr->cmdProc,
876                      clientData, (void (*) _ANSI_ARGS_((ClientData))) NULL);                      clientData, (void (*) _ANSI_ARGS_((ClientData))) NULL);
877          } else {          } else {
878              Tcl_CreateObjCommand(interp, cmdPtr->name, cmdPtr->objProc,              Tcl_CreateObjCommand(interp, cmdPtr->name, cmdPtr->objProc,
879                      clientData, NULL);                      clientData, NULL);
880          }          }
881          if (isSafe) {          if (isSafe) {
882              if (!(cmdPtr->isSafe)) {              if (!(cmdPtr->isSafe)) {
883                  Tcl_HideCommand(interp, cmdPtr->name, cmdPtr->name);                  Tcl_HideCommand(interp, cmdPtr->name, cmdPtr->name);
884              }              }
885          }          }
886      }      }
887    
888      TkCreateMenuCmd(interp);      TkCreateMenuCmd(interp);
889    
890      /*      /*
891       * Set variables for the intepreter.       * Set variables for the intepreter.
892       */       */
893    
894      Tcl_SetVar(interp, "tk_patchLevel", TK_PATCH_LEVEL, TCL_GLOBAL_ONLY);      Tcl_SetVar(interp, "tk_patchLevel", TK_PATCH_LEVEL, TCL_GLOBAL_ONLY);
895      Tcl_SetVar(interp, "tk_version", TK_VERSION, TCL_GLOBAL_ONLY);      Tcl_SetVar(interp, "tk_version", TK_VERSION, TCL_GLOBAL_ONLY);
896    
897      tsdPtr->numMainWindows++;      tsdPtr->numMainWindows++;
898      return tkwin;      return tkwin;
899  }  }
900    
901  /*  /*
902   *--------------------------------------------------------------   *--------------------------------------------------------------
903   *   *
904   * Tk_CreateWindow --   * Tk_CreateWindow --
905   *   *
906   *      Create a new internal or top-level window as a child of an   *      Create a new internal or top-level window as a child of an
907   *      existing window.   *      existing window.
908   *   *
909   * Results:   * Results:
910   *      The return value is a token for the new window.  This   *      The return value is a token for the new window.  This
911   *      is not the same as X's token for the window.  If an error   *      is not the same as X's token for the window.  If an error
912   *      occurred in creating the window (e.g. no such display or   *      occurred in creating the window (e.g. no such display or
913   *      screen), then an error message is left in the interp's result and   *      screen), then an error message is left in the interp's result and
914   *      NULL is returned.   *      NULL is returned.
915   *   *
916   * Side effects:   * Side effects:
917   *      A new window structure is allocated locally.  An X   *      A new window structure is allocated locally.  An X
918   *      window is not initially created, but will be created   *      window is not initially created, but will be created
919   *      the first time the window is mapped.   *      the first time the window is mapped.
920   *   *
921   *--------------------------------------------------------------   *--------------------------------------------------------------
922   */   */
923    
924  Tk_Window  Tk_Window
925  Tk_CreateWindow(interp, parent, name, screenName)  Tk_CreateWindow(interp, parent, name, screenName)
926      Tcl_Interp *interp;         /* Interpreter to use for error reporting.      Tcl_Interp *interp;         /* Interpreter to use for error reporting.
927                                   * the interp's result is assumed to be                                   * the interp's result is assumed to be
928                                   * initialized by the caller. */                                   * initialized by the caller. */
929      Tk_Window parent;           /* Token for parent of new window. */      Tk_Window parent;           /* Token for parent of new window. */
930      char *name;                 /* Name for new window.  Must be unique      char *name;                 /* Name for new window.  Must be unique
931                                   * among parent's children. */                                   * among parent's children. */
932      char *screenName;           /* If NULL, new window will be internal on      char *screenName;           /* If NULL, new window will be internal on
933                                   * same screen as its parent.  If non-NULL,                                   * same screen as its parent.  If non-NULL,
934                                   * gives name of screen on which to create                                   * gives name of screen on which to create
935                                   * new window;  window will be a top-level                                   * new window;  window will be a top-level
936                                   * window. */                                   * window. */
937  {  {
938      TkWindow *parentPtr = (TkWindow *) parent;      TkWindow *parentPtr = (TkWindow *) parent;
939      TkWindow *winPtr;      TkWindow *winPtr;
940    
941      if ((parentPtr != NULL) && (parentPtr->flags & TK_ALREADY_DEAD)) {      if ((parentPtr != NULL) && (parentPtr->flags & TK_ALREADY_DEAD)) {
942          Tcl_AppendResult(interp,          Tcl_AppendResult(interp,
943                  "can't create window: parent has been destroyed",                  "can't create window: parent has been destroyed",
944                  (char *) NULL);                  (char *) NULL);
945          return NULL;          return NULL;
946      } else if ((parentPtr != NULL) &&      } else if ((parentPtr != NULL) &&
947              (parentPtr->flags & TK_CONTAINER)) {              (parentPtr->flags & TK_CONTAINER)) {
948          Tcl_AppendResult(interp,          Tcl_AppendResult(interp,
949                  "can't create window: its parent has -container = yes",                  "can't create window: its parent has -container = yes",
950                  (char *) NULL);                  (char *) NULL);
951          return NULL;          return NULL;
952      }      }
953      if (screenName == NULL) {      if (screenName == NULL) {
954          winPtr = TkAllocWindow(parentPtr->dispPtr, parentPtr->screenNum,          winPtr = TkAllocWindow(parentPtr->dispPtr, parentPtr->screenNum,
955                  parentPtr);                  parentPtr);
956          if (NameWindow(interp, winPtr, parentPtr, name) != TCL_OK) {          if (NameWindow(interp, winPtr, parentPtr, name) != TCL_OK) {
957              Tk_DestroyWindow((Tk_Window) winPtr);              Tk_DestroyWindow((Tk_Window) winPtr);
958              return NULL;              return NULL;
959          } else {          } else {
960              return (Tk_Window) winPtr;              return (Tk_Window) winPtr;
961          }          }
962      } else {      } else {
963          return CreateTopLevelWindow(interp, parent, name, screenName);          return CreateTopLevelWindow(interp, parent, name, screenName);
964      }      }
965  }  }
966    
967  /*  /*
968   *----------------------------------------------------------------------   *----------------------------------------------------------------------
969   *   *
970   * Tk_CreateWindowFromPath --   * Tk_CreateWindowFromPath --
971   *   *
972   *      This procedure is similar to Tk_CreateWindow except that   *      This procedure is similar to Tk_CreateWindow except that
973   *      it uses a path name to create the window, rather than a   *      it uses a path name to create the window, rather than a
974   *      parent and a child name.   *      parent and a child name.
975   *   *
976   * Results:   * Results:
977   *      The return value is a token for the new window.  This   *      The return value is a token for the new window.  This
978   *      is not the same as X's token for the window.  If an error   *      is not the same as X's token for the window.  If an error
979   *      occurred in creating the window (e.g. no such display or   *      occurred in creating the window (e.g. no such display or
980   *      screen), then an error message is left in the interp's result and   *      screen), then an error message is left in the interp's result and
981   *      NULL is returned.   *      NULL is returned.
982   *   *
983   * Side effects:   * Side effects:
984   *      A new window structure is allocated locally.  An X   *      A new window structure is allocated locally.  An X
985   *      window is not initially created, but will be created   *      window is not initially created, but will be created
986   *      the first time the window is mapped.   *      the first time the window is mapped.
987   *   *
988   *----------------------------------------------------------------------   *----------------------------------------------------------------------
989   */   */
990    
991  Tk_Window  Tk_Window
992  Tk_CreateWindowFromPath(interp, tkwin, pathName, screenName)  Tk_CreateWindowFromPath(interp, tkwin, pathName, screenName)
993      Tcl_Interp *interp;         /* Interpreter to use for error reporting.      Tcl_Interp *interp;         /* Interpreter to use for error reporting.
994                                   * the interp's result is assumed to be                                   * the interp's result is assumed to be
995                                   * initialized by the caller. */                                   * initialized by the caller. */
996      Tk_Window tkwin;            /* Token for any window in application      Tk_Window tkwin;            /* Token for any window in application
997                                   * that is to contain new window. */                                   * that is to contain new window. */
998      char *pathName;             /* Path name for new window within the      char *pathName;             /* Path name for new window within the
999                                   * application of tkwin.  The parent of                                   * application of tkwin.  The parent of
1000                                   * this window must already exist, but                                   * this window must already exist, but
1001                                   * the window itself must not exist. */                                   * the window itself must not exist. */
1002      char *screenName;           /* If NULL, new window will be on same      char *screenName;           /* If NULL, new window will be on same
1003                                   * screen as its parent.  If non-NULL,                                   * screen as its parent.  If non-NULL,
1004                                   * gives name of screen on which to create                                   * gives name of screen on which to create
1005                                   * new window;  window will be a top-level                                   * new window;  window will be a top-level
1006                                   * window. */                                   * window. */
1007  {  {
1008  #define FIXED_SPACE 5  #define FIXED_SPACE 5
1009      char fixedSpace[FIXED_SPACE+1];      char fixedSpace[FIXED_SPACE+1];
1010      char *p;      char *p;
1011      Tk_Window parent;      Tk_Window parent;
1012      int numChars;      int numChars;
1013    
1014      /*      /*
1015       * Strip the parent's name out of pathName (it's everything up       * Strip the parent's name out of pathName (it's everything up
1016       * to the last dot).  There are two tricky parts: (a) must       * to the last dot).  There are two tricky parts: (a) must
1017       * copy the parent's name somewhere else to avoid modifying       * copy the parent's name somewhere else to avoid modifying
1018       * the pathName string (for large names, space for the copy       * the pathName string (for large names, space for the copy
1019       * will have to be malloc'ed);  (b) must special-case the       * will have to be malloc'ed);  (b) must special-case the
1020       * situation where the parent is ".".       * situation where the parent is ".".
1021       */       */
1022    
1023      p = strrchr(pathName, '.');      p = strrchr(pathName, '.');
1024      if (p == NULL) {      if (p == NULL) {
1025          Tcl_AppendResult(interp, "bad window path name \"", pathName,          Tcl_AppendResult(interp, "bad window path name \"", pathName,
1026                  "\"", (char *) NULL);                  "\"", (char *) NULL);
1027          return NULL;          return NULL;
1028      }      }
1029      numChars = p-pathName;      numChars = p-pathName;
1030      if (numChars > FIXED_SPACE) {      if (numChars > FIXED_SPACE) {
1031          p = (char *) ckalloc((unsigned) (numChars+1));          p = (char *) ckalloc((unsigned) (numChars+1));
1032      } else {      } else {
1033          p = fixedSpace;          p = fixedSpace;
1034      }      }
1035      if (numChars == 0) {      if (numChars == 0) {
1036          *p = '.';          *p = '.';
1037          p[1] = '\0';          p[1] = '\0';
1038      } else {      } else {
1039          strncpy(p, pathName, (size_t) numChars);          strncpy(p, pathName, (size_t) numChars);
1040          p[numChars] = '\0';          p[numChars] = '\0';
1041      }      }
1042    
1043      /*      /*
1044       * Find the parent window.       * Find the parent window.
1045       */       */
1046    
1047      parent = Tk_NameToWindow(interp, p, tkwin);      parent = Tk_NameToWindow(interp, p, tkwin);
1048      if (p != fixedSpace) {      if (p != fixedSpace) {
1049          ckfree(p);          ckfree(p);
1050      }      }
1051      if (parent == NULL) {      if (parent == NULL) {
1052          return NULL;          return NULL;
1053      }      }
1054      if (((TkWindow *) parent)->flags & TK_ALREADY_DEAD) {      if (((TkWindow *) parent)->flags & TK_ALREADY_DEAD) {
1055          Tcl_AppendResult(interp,          Tcl_AppendResult(interp,
1056              "can't create window: parent has been destroyed", (char *) NULL);              "can't create window: parent has been destroyed", (char *) NULL);
1057          return NULL;          return NULL;
1058      } else if (((TkWindow *) parent)->flags & TK_CONTAINER) {      } else if (((TkWindow *) parent)->flags & TK_CONTAINER) {
1059          Tcl_AppendResult(interp,          Tcl_AppendResult(interp,
1060              "can't create window: its parent has -container = yes",              "can't create window: its parent has -container = yes",
1061                  (char *) NULL);                  (char *) NULL);
1062          return NULL;          return NULL;
1063      }      }
1064    
1065      /*      /*
1066       * Create the window.       * Create the window.
1067       */       */
1068    
1069      if (screenName == NULL) {      if (screenName == NULL) {
1070          TkWindow *parentPtr = (TkWindow *) parent;          TkWindow *parentPtr = (TkWindow *) parent;
1071          TkWindow *winPtr;          TkWindow *winPtr;
1072    
1073          winPtr = TkAllocWindow(parentPtr->dispPtr, parentPtr->screenNum,          winPtr = TkAllocWindow(parentPtr->dispPtr, parentPtr->screenNum,
1074                  parentPtr);                  parentPtr);
1075          if (NameWindow(interp, winPtr, parentPtr, pathName+numChars+1)          if (NameWindow(interp, winPtr, parentPtr, pathName+numChars+1)
1076                  != TCL_OK) {                  != TCL_OK) {
1077              Tk_DestroyWindow((Tk_Window) winPtr);              Tk_DestroyWindow((Tk_Window) winPtr);
1078              return NULL;              return NULL;
1079          } else {          } else {
1080              return (Tk_Window) winPtr;              return (Tk_Window) winPtr;
1081          }          }
1082      } else {      } else {
1083          return CreateTopLevelWindow(interp, parent, pathName+numChars+1,          return CreateTopLevelWindow(interp, parent, pathName+numChars+1,
1084                  screenName);                  screenName);
1085      }      }
1086  }  }
1087    
1088  /*  /*
1089   *--------------------------------------------------------------   *--------------------------------------------------------------
1090   *   *
1091   * Tk_DestroyWindow --   * Tk_DestroyWindow --
1092   *   *
1093   *      Destroy an existing window.  After this call, the caller   *      Destroy an existing window.  After this call, the caller
1094   *      should never again use the token.   *      should never again use the token.
1095   *   *
1096   * Results:   * Results:
1097   *      None.   *      None.
1098   *   *
1099   * Side effects:   * Side effects:
1100   *      The window is deleted, along with all of its children.   *      The window is deleted, along with all of its children.
1101   *      Relevant callback procedures are invoked.   *      Relevant callback procedures are invoked.
1102   *   *
1103   *--------------------------------------------------------------   *--------------------------------------------------------------
1104   */   */
1105    
1106  void  void
1107  Tk_DestroyWindow(tkwin)  Tk_DestroyWindow(tkwin)
1108      Tk_Window tkwin;            /* Window to destroy. */      Tk_Window tkwin;            /* Window to destroy. */
1109  {  {
1110      TkWindow *winPtr = (TkWindow *) tkwin;      TkWindow *winPtr = (TkWindow *) tkwin;
1111      TkDisplay *dispPtr = winPtr->dispPtr;      TkDisplay *dispPtr = winPtr->dispPtr;
1112      XEvent event;      XEvent event;
1113      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
1114              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
1115    
1116      if (winPtr->flags & TK_ALREADY_DEAD) {      if (winPtr->flags & TK_ALREADY_DEAD) {
1117          /*          /*
1118           * A destroy event binding caused the window to be destroyed           * A destroy event binding caused the window to be destroyed
1119           * again.  Ignore the request.           * again.  Ignore the request.
1120           */           */
1121    
1122          return;          return;
1123      }      }
1124      winPtr->flags |= TK_ALREADY_DEAD;      winPtr->flags |= TK_ALREADY_DEAD;
1125    
1126      /*      /*
1127       * Some cleanup needs to be done immediately, rather than later,       * Some cleanup needs to be done immediately, rather than later,
1128       * because it needs information that will be destoyed before we       * because it needs information that will be destoyed before we
1129       * get to the main cleanup point.  For example, TkFocusDeadWindow       * get to the main cleanup point.  For example, TkFocusDeadWindow
1130       * needs to access the parentPtr field from a window, but if       * needs to access the parentPtr field from a window, but if
1131       * a Destroy event handler deletes the window's parent this       * a Destroy event handler deletes the window's parent this
1132       * field will be NULL before the main cleanup point is reached.       * field will be NULL before the main cleanup point is reached.
1133       */       */
1134    
1135      TkFocusDeadWindow(winPtr);      TkFocusDeadWindow(winPtr);
1136    
1137      /*      /*
1138       * If this is a main window, remove it from the list of main       * If this is a main window, remove it from the list of main
1139       * windows.  This needs to be done now (rather than later with       * windows.  This needs to be done now (rather than later with
1140       * all the other main window cleanup) to handle situations where       * all the other main window cleanup) to handle situations where
1141       * a destroy binding for a window calls "exit".  In this case       * a destroy binding for a window calls "exit".  In this case
1142       * the child window cleanup isn't complete when exit is called,       * the child window cleanup isn't complete when exit is called,
1143       * so the reference count of its application doesn't go to zero       * so the reference count of its application doesn't go to zero
1144       * when exit calls Tk_DestroyWindow on ".", so the main window       * when exit calls Tk_DestroyWindow on ".", so the main window
1145       * doesn't get removed from the list and exit loops infinitely.       * doesn't get removed from the list and exit loops infinitely.
1146       * Even worse, if "destroy ." is called by the destroy binding       * Even worse, if "destroy ." is called by the destroy binding
1147       * before calling "exit", "exit" will attempt to destroy       * before calling "exit", "exit" will attempt to destroy
1148       * mainPtr->winPtr, which no longer exists, and there may be a       * mainPtr->winPtr, which no longer exists, and there may be a
1149       * core dump.       * core dump.
1150       *       *
1151       * Also decrement the display refcount so that if this is the       * Also decrement the display refcount so that if this is the
1152       * last Tk application in this process on this display, the display       * last Tk application in this process on this display, the display
1153       * can be closed and its data structures deleted.       * can be closed and its data structures deleted.
1154       */       */
1155    
1156      if (winPtr->mainPtr->winPtr == winPtr) {      if (winPtr->mainPtr->winPtr == winPtr) {
1157          dispPtr->refCount--;          dispPtr->refCount--;
1158          if (tsdPtr->mainWindowList == winPtr->mainPtr) {          if (tsdPtr->mainWindowList == winPtr->mainPtr) {
1159              tsdPtr->mainWindowList = winPtr->mainPtr->nextPtr;              tsdPtr->mainWindowList = winPtr->mainPtr->nextPtr;
1160          } else {          } else {
1161              TkMainInfo *prevPtr;              TkMainInfo *prevPtr;
1162    
1163              for (prevPtr = tsdPtr->mainWindowList;              for (prevPtr = tsdPtr->mainWindowList;
1164                      prevPtr->nextPtr != winPtr->mainPtr;                      prevPtr->nextPtr != winPtr->mainPtr;
1165                      prevPtr = prevPtr->nextPtr) {                      prevPtr = prevPtr->nextPtr) {
1166                  /* Empty loop body. */                  /* Empty loop body. */
1167              }              }
1168              prevPtr->nextPtr = winPtr->mainPtr->nextPtr;              prevPtr->nextPtr = winPtr->mainPtr->nextPtr;
1169          }          }
1170          tsdPtr->numMainWindows--;          tsdPtr->numMainWindows--;
1171      }      }
1172    
1173      /*      /*
1174       * Recursively destroy children.       * Recursively destroy children.
1175       */       */
1176    
1177      dispPtr->destroyCount++;      dispPtr->destroyCount++;
1178      while (winPtr->childList != NULL) {      while (winPtr->childList != NULL) {
1179          TkWindow *childPtr;          TkWindow *childPtr;
1180          childPtr = winPtr->childList;          childPtr = winPtr->childList;
1181          childPtr->flags |= TK_DONT_DESTROY_WINDOW;          childPtr->flags |= TK_DONT_DESTROY_WINDOW;
1182          Tk_DestroyWindow((Tk_Window) childPtr);          Tk_DestroyWindow((Tk_Window) childPtr);
1183          if (winPtr->childList == childPtr) {          if (winPtr->childList == childPtr) {
1184              /*              /*
1185               * The child didn't remove itself from the child list, so               * The child didn't remove itself from the child list, so
1186               * let's remove it here.  This can happen in some strange               * let's remove it here.  This can happen in some strange
1187               * conditions, such as when a Delete event handler for a               * conditions, such as when a Delete event handler for a
1188               * window deletes the window's parent.               * window deletes the window's parent.
1189               */               */
1190    
1191              winPtr->childList = childPtr->nextPtr;              winPtr->childList = childPtr->nextPtr;
1192              childPtr->parentPtr = NULL;              childPtr->parentPtr = NULL;
1193          }          }
1194      }      }
1195      if ((winPtr->flags & (TK_CONTAINER|TK_BOTH_HALVES))      if ((winPtr->flags & (TK_CONTAINER|TK_BOTH_HALVES))
1196              == (TK_CONTAINER|TK_BOTH_HALVES)) {              == (TK_CONTAINER|TK_BOTH_HALVES)) {
1197          /*          /*
1198           * This is the container for an embedded application, and           * This is the container for an embedded application, and
1199           * the embedded application is also in this process.  Delete           * the embedded application is also in this process.  Delete
1200           * the embedded window in-line here, for the same reasons we           * the embedded window in-line here, for the same reasons we
1201           * delete children in-line (otherwise, for example, the Tk           * delete children in-line (otherwise, for example, the Tk
1202           * window may appear to exist even though its X window is           * window may appear to exist even though its X window is
1203           * gone; this could cause errors).  Special note: it's possible           * gone; this could cause errors).  Special note: it's possible
1204           * that the embedded window has already been deleted, in which           * that the embedded window has already been deleted, in which
1205           * case TkpGetOtherWindow will return NULL.           * case TkpGetOtherWindow will return NULL.
1206           */           */
1207    
1208          TkWindow *childPtr;          TkWindow *childPtr;
1209          childPtr = TkpGetOtherWindow(winPtr);          childPtr = TkpGetOtherWindow(winPtr);
1210          if (childPtr != NULL) {          if (childPtr != NULL) {
1211              childPtr->flags |= TK_DONT_DESTROY_WINDOW;              childPtr->flags |= TK_DONT_DESTROY_WINDOW;
1212              Tk_DestroyWindow((Tk_Window) childPtr);              Tk_DestroyWindow((Tk_Window) childPtr);
1213          }          }
1214      }      }
1215    
1216      /*      /*
1217       * Generate a DestroyNotify event.  In order for the DestroyNotify       * Generate a DestroyNotify event.  In order for the DestroyNotify
1218       * event to be processed correctly, need to make sure the window       * event to be processed correctly, need to make sure the window
1219       * exists.  This is a bit of a kludge, and may be unnecessarily       * exists.  This is a bit of a kludge, and may be unnecessarily
1220       * expensive, but without it no event handlers will get called for       * expensive, but without it no event handlers will get called for
1221       * windows that don't exist yet.       * windows that don't exist yet.
1222       *       *
1223       * Note: if the window's pathName is NULL it means that the window       * Note: if the window's pathName is NULL it means that the window
1224       * was not successfully initialized in the first place, so we should       * was not successfully initialized in the first place, so we should
1225       * not make the window exist or generate the event.       * not make the window exist or generate the event.
1226       */       */
1227    
1228      if (winPtr->pathName != NULL) {      if (winPtr->pathName != NULL) {
1229          if (winPtr->window == None) {          if (winPtr->window == None) {
1230              Tk_MakeWindowExist(tkwin);              Tk_MakeWindowExist(tkwin);
1231          }          }
1232          event.type = DestroyNotify;          event.type = DestroyNotify;
1233          event.xdestroywindow.serial =          event.xdestroywindow.serial =
1234                  LastKnownRequestProcessed(winPtr->display);                  LastKnownRequestProcessed(winPtr->display);
1235          event.xdestroywindow.send_event = False;          event.xdestroywindow.send_event = False;
1236          event.xdestroywindow.display = winPtr->display;          event.xdestroywindow.display = winPtr->display;
1237          event.xdestroywindow.event = winPtr->window;          event.xdestroywindow.event = winPtr->window;
1238          event.xdestroywindow.window = winPtr->window;          event.xdestroywindow.window = winPtr->window;
1239          Tk_HandleEvent(&event);          Tk_HandleEvent(&event);
1240      }      }
1241    
1242      /*      /*
1243       * Cleanup the data structures associated with this window.       * Cleanup the data structures associated with this window.
1244       */       */
1245    
1246      if (winPtr->flags & TK_TOP_LEVEL) {      if (winPtr->flags & TK_TOP_LEVEL) {
1247          TkWmDeadWindow(winPtr);          TkWmDeadWindow(winPtr);
1248      } else if (winPtr->flags & TK_WM_COLORMAP_WINDOW) {      } else if (winPtr->flags & TK_WM_COLORMAP_WINDOW) {
1249          TkWmRemoveFromColormapWindows(winPtr);          TkWmRemoveFromColormapWindows(winPtr);
1250      }      }
1251      if (winPtr->window != None) {      if (winPtr->window != None) {
1252  #if defined(MAC_TCL) || defined(__WIN32__)  #if defined(MAC_TCL) || defined(__WIN32__)
1253          XDestroyWindow(winPtr->display, winPtr->window);          XDestroyWindow(winPtr->display, winPtr->window);
1254  #else  #else
1255          if ((winPtr->flags & TK_TOP_LEVEL)          if ((winPtr->flags & TK_TOP_LEVEL)
1256                  || !(winPtr->flags & TK_DONT_DESTROY_WINDOW)) {                  || !(winPtr->flags & TK_DONT_DESTROY_WINDOW)) {
1257              /*              /*
1258               * The parent has already been destroyed and this isn't               * The parent has already been destroyed and this isn't
1259               * a top-level window, so this window will be destroyed               * a top-level window, so this window will be destroyed
1260               * implicitly when the parent's X window is destroyed;               * implicitly when the parent's X window is destroyed;
1261               * it's much faster not to do an explicit destroy of this               * it's much faster not to do an explicit destroy of this
1262               * X window.               * X window.
1263               */               */
1264    
1265              dispPtr->lastDestroyRequest = NextRequest(winPtr->display);              dispPtr->lastDestroyRequest = NextRequest(winPtr->display);
1266              XDestroyWindow(winPtr->display, winPtr->window);              XDestroyWindow(winPtr->display, winPtr->window);
1267          }          }
1268  #endif  #endif
1269          TkFreeWindowId(dispPtr, winPtr->window);          TkFreeWindowId(dispPtr, winPtr->window);
1270          Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->winTable,          Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->winTable,
1271                  (char *) winPtr->window));                  (char *) winPtr->window));
1272          winPtr->window = None;          winPtr->window = None;
1273      }      }
1274      dispPtr->destroyCount--;      dispPtr->destroyCount--;
1275      UnlinkWindow(winPtr);      UnlinkWindow(winPtr);
1276      TkEventDeadWindow(winPtr);      TkEventDeadWindow(winPtr);
1277      TkBindDeadWindow(winPtr);      TkBindDeadWindow(winPtr);
1278  #ifdef TK_USE_INPUT_METHODS  #ifdef TK_USE_INPUT_METHODS
1279      if (winPtr->inputContext != NULL) {      if (winPtr->inputContext != NULL) {
1280          XDestroyIC(winPtr->inputContext);          XDestroyIC(winPtr->inputContext);
1281      }      }
1282  #endif /* TK_USE_INPUT_METHODS */  #endif /* TK_USE_INPUT_METHODS */
1283      if (winPtr->tagPtr != NULL) {      if (winPtr->tagPtr != NULL) {
1284          TkFreeBindingTags(winPtr);          TkFreeBindingTags(winPtr);
1285      }      }
1286      TkOptionDeadWindow(winPtr);      TkOptionDeadWindow(winPtr);
1287      TkSelDeadWindow(winPtr);      TkSelDeadWindow(winPtr);
1288      TkGrabDeadWindow(winPtr);      TkGrabDeadWindow(winPtr);
1289      if (winPtr->mainPtr != NULL) {      if (winPtr->mainPtr != NULL) {
1290          if (winPtr->pathName != NULL) {          if (winPtr->pathName != NULL) {
1291              Tk_DeleteAllBindings(winPtr->mainPtr->bindingTable,              Tk_DeleteAllBindings(winPtr->mainPtr->bindingTable,
1292                      (ClientData) winPtr->pathName);                      (ClientData) winPtr->pathName);
1293              Tcl_DeleteHashEntry(Tcl_FindHashEntry(&winPtr->mainPtr->nameTable,              Tcl_DeleteHashEntry(Tcl_FindHashEntry(&winPtr->mainPtr->nameTable,
1294                      winPtr->pathName));                      winPtr->pathName));
1295          }          }
1296          winPtr->mainPtr->refCount--;          winPtr->mainPtr->refCount--;
1297          if (winPtr->mainPtr->refCount == 0) {          if (winPtr->mainPtr->refCount == 0) {
1298              register TkCmd *cmdPtr;              register TkCmd *cmdPtr;
1299    
1300              /*              /*
1301               * We just deleted the last window in the application.  Delete               * We just deleted the last window in the application.  Delete
1302               * the TkMainInfo structure too and replace all of Tk's commands               * the TkMainInfo structure too and replace all of Tk's commands
1303               * with dummy commands that return errors.  Also delete the               * with dummy commands that return errors.  Also delete the
1304               * "send" command to unregister the interpreter.               * "send" command to unregister the interpreter.
1305               *               *
1306               * NOTE: Only replace the commands it if the interpreter is               * NOTE: Only replace the commands it if the interpreter is
1307               * not being deleted. If it *is*, the interpreter cleanup will               * not being deleted. If it *is*, the interpreter cleanup will
1308               * do all the needed work.               * do all the needed work.
1309               */               */
1310    
1311              if ((winPtr->mainPtr->interp != NULL) &&              if ((winPtr->mainPtr->interp != NULL) &&
1312                      (!Tcl_InterpDeleted(winPtr->mainPtr->interp))) {                      (!Tcl_InterpDeleted(winPtr->mainPtr->interp))) {
1313                  for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {                  for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
1314                      Tcl_CreateCommand(winPtr->mainPtr->interp, cmdPtr->name,                      Tcl_CreateCommand(winPtr->mainPtr->interp, cmdPtr->name,
1315                              TkDeadAppCmd, (ClientData) NULL,                              TkDeadAppCmd, (ClientData) NULL,
1316                              (void (*) _ANSI_ARGS_((ClientData))) NULL);                              (void (*) _ANSI_ARGS_((ClientData))) NULL);
1317                  }                  }
1318                  Tcl_CreateCommand(winPtr->mainPtr->interp, "send",                  Tcl_CreateCommand(winPtr->mainPtr->interp, "send",
1319                          TkDeadAppCmd, (ClientData) NULL,                          TkDeadAppCmd, (ClientData) NULL,
1320                          (void (*) _ANSI_ARGS_((ClientData))) NULL);                          (void (*) _ANSI_ARGS_((ClientData))) NULL);
1321                  Tcl_UnlinkVar(winPtr->mainPtr->interp, "tk_strictMotif");                  Tcl_UnlinkVar(winPtr->mainPtr->interp, "tk_strictMotif");
1322              }              }
1323                                    
1324              Tcl_DeleteHashTable(&winPtr->mainPtr->nameTable);              Tcl_DeleteHashTable(&winPtr->mainPtr->nameTable);
1325              TkBindFree(winPtr->mainPtr);              TkBindFree(winPtr->mainPtr);
1326              TkDeleteAllImages(winPtr->mainPtr);              TkDeleteAllImages(winPtr->mainPtr);
1327              TkFontPkgFree(winPtr->mainPtr);              TkFontPkgFree(winPtr->mainPtr);
1328    
1329              /*              /*
1330               * When embedding Tk into other applications, make sure               * When embedding Tk into other applications, make sure
1331               * that all destroy events reach the server. Otherwise               * that all destroy events reach the server. Otherwise
1332               * the embedding application may also attempt to destroy               * the embedding application may also attempt to destroy
1333               * the windows, resulting in an X error               * the windows, resulting in an X error
1334               */               */
1335    
1336              if (winPtr->flags & TK_EMBEDDED) {              if (winPtr->flags & TK_EMBEDDED) {
1337                  XSync(winPtr->display,False) ;                  XSync(winPtr->display,False) ;
1338              }              }
1339              ckfree((char *) winPtr->mainPtr);              ckfree((char *) winPtr->mainPtr);
1340    
1341              /*              /*
1342               * If no other applications are using the display, close the               * If no other applications are using the display, close the
1343               * display now and relinquish its data structures.               * display now and relinquish its data structures.
1344               */               */
1345                            
1346              if (dispPtr->refCount <= 0) {              if (dispPtr->refCount <= 0) {
1347  #ifdef  NOT_YET  #ifdef  NOT_YET
1348                  /*                  /*
1349                   * I have disabled this code because on Windows there are                   * I have disabled this code because on Windows there are
1350                   * still order dependencies in close-down. All displays                   * still order dependencies in close-down. All displays
1351                   * and resources will get closed down properly anyway at                   * and resources will get closed down properly anyway at
1352                   * exit, through the exit handler.                   * exit, through the exit handler.
1353                   */                   */
1354                                    
1355                  TkDisplay *theDispPtr, *backDispPtr;                  TkDisplay *theDispPtr, *backDispPtr;
1356                                    
1357                  /*                  /*
1358                   * Splice this display out of the list of displays.                   * Splice this display out of the list of displays.
1359                   */                   */
1360                                    
1361                  for (theDispPtr = displayList, backDispPtr = NULL;                  for (theDispPtr = displayList, backDispPtr = NULL;
1362                           (theDispPtr != winPtr->dispPtr) &&                           (theDispPtr != winPtr->dispPtr) &&
1363                               (theDispPtr != NULL);                               (theDispPtr != NULL);
1364                           theDispPtr = theDispPtr->nextPtr) {                           theDispPtr = theDispPtr->nextPtr) {
1365                      backDispPtr = theDispPtr;                      backDispPtr = theDispPtr;
1366                  }                  }
1367                  if (theDispPtr == NULL) {                  if (theDispPtr == NULL) {
1368                      panic("could not find display to close!");                      panic("could not find display to close!");
1369                  }                  }
1370                  if (backDispPtr == NULL) {                  if (backDispPtr == NULL) {
1371                      displayList = theDispPtr->nextPtr;                      displayList = theDispPtr->nextPtr;
1372                  } else {                  } else {
1373                      backDispPtr->nextPtr = theDispPtr->nextPtr;                      backDispPtr->nextPtr = theDispPtr->nextPtr;
1374                  }                  }
1375                                    
1376                  /*                  /*
1377                   * Found and spliced it out, now actually do the cleanup.                   * Found and spliced it out, now actually do the cleanup.
1378                   */                   */
1379                                    
1380                  if (dispPtr->name != NULL) {                  if (dispPtr->name != NULL) {
1381                      ckfree(dispPtr->name);                      ckfree(dispPtr->name);
1382                  }                  }
1383                                    
1384                  Tcl_DeleteHashTable(&(dispPtr->winTable));                  Tcl_DeleteHashTable(&(dispPtr->winTable));
1385    
1386                  /*                  /*
1387                   * Cannot yet close the display because we still have                   * Cannot yet close the display because we still have
1388                   * order of deletion problems. Defer until exit handling                   * order of deletion problems. Defer until exit handling
1389                   * instead. At that time, the display will cleanly shut                   * instead. At that time, the display will cleanly shut
1390                   * down (hopefully..). (JYL)                   * down (hopefully..). (JYL)
1391                   */                   */
1392    
1393                  TkpCloseDisplay(dispPtr);                  TkpCloseDisplay(dispPtr);
1394    
1395                  /*                  /*
1396                   * There is lots more to clean up, we leave it at this for                   * There is lots more to clean up, we leave it at this for
1397                   * the time being.                   * the time being.
1398                   */                   */
1399  #endif  #endif
1400              }              }
1401          }          }
1402      }      }
1403      ckfree((char *) winPtr);      ckfree((char *) winPtr);
1404  }  }
1405    
1406  /*  /*
1407   *--------------------------------------------------------------   *--------------------------------------------------------------
1408   *   *
1409   * Tk_MapWindow --   * Tk_MapWindow --
1410   *   *
1411   *      Map a window within its parent.  This may require the   *      Map a window within its parent.  This may require the
1412   *      window and/or its parents to actually be created.   *      window and/or its parents to actually be created.
1413   *   *
1414   * Results:   * Results:
1415   *      None.   *      None.
1416   *   *
1417   * Side effects:   * Side effects:
1418   *      The given window will be mapped.  Windows may also   *      The given window will be mapped.  Windows may also
1419   *      be created.   *      be created.
1420   *   *
1421   *--------------------------------------------------------------   *--------------------------------------------------------------
1422   */   */
1423    
1424  void  void
1425  Tk_MapWindow(tkwin)  Tk_MapWindow(tkwin)
1426      Tk_Window tkwin;            /* Token for window to map. */      Tk_Window tkwin;            /* Token for window to map. */
1427  {  {
1428      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1429      XEvent event;      XEvent event;
1430    
1431      if (winPtr->flags & TK_MAPPED) {      if (winPtr->flags & TK_MAPPED) {
1432          return;          return;
1433      }      }
1434      if (winPtr->window == None) {      if (winPtr->window == None) {
1435          Tk_MakeWindowExist(tkwin);          Tk_MakeWindowExist(tkwin);
1436      }      }
1437      if (winPtr->flags & TK_TOP_LEVEL) {      if (winPtr->flags & TK_TOP_LEVEL) {
1438          /*          /*
1439           * Lots of special processing has to be done for top-level           * Lots of special processing has to be done for top-level
1440           * windows.  Let tkWm.c handle everything itself.           * windows.  Let tkWm.c handle everything itself.
1441           */           */
1442    
1443          TkWmMapWindow(winPtr);          TkWmMapWindow(winPtr);
1444          return;          return;
1445      }      }
1446      winPtr->flags |= TK_MAPPED;      winPtr->flags |= TK_MAPPED;
1447      XMapWindow(winPtr->display, winPtr->window);      XMapWindow(winPtr->display, winPtr->window);
1448      event.type = MapNotify;      event.type = MapNotify;
1449      event.xmap.serial = LastKnownRequestProcessed(winPtr->display);      event.xmap.serial = LastKnownRequestProcessed(winPtr->display);
1450      event.xmap.send_event = False;      event.xmap.send_event = False;
1451      event.xmap.display = winPtr->display;      event.xmap.display = winPtr->display;
1452      event.xmap.event = winPtr->window;      event.xmap.event = winPtr->window;
1453      event.xmap.window = winPtr->window;      event.xmap.window = winPtr->window;
1454      event.xmap.override_redirect = winPtr->atts.override_redirect;      event.xmap.override_redirect = winPtr->atts.override_redirect;
1455      Tk_HandleEvent(&event);      Tk_HandleEvent(&event);
1456  }  }
1457    
1458  /*  /*
1459   *--------------------------------------------------------------   *--------------------------------------------------------------
1460   *   *
1461   * Tk_MakeWindowExist --   * Tk_MakeWindowExist --
1462   *   *
1463   *      Ensure that a particular window actually exists.  This   *      Ensure that a particular window actually exists.  This
1464   *      procedure shouldn't normally need to be invoked from   *      procedure shouldn't normally need to be invoked from
1465   *      outside the Tk package, but may be needed if someone   *      outside the Tk package, but may be needed if someone
1466   *      wants to manipulate a window before mapping it.   *      wants to manipulate a window before mapping it.
1467   *   *
1468   * Results:   * Results:
1469   *      None.   *      None.
1470   *   *
1471   * Side effects:   * Side effects:
1472   *      When the procedure returns, the X window associated with   *      When the procedure returns, the X window associated with
1473   *      tkwin is guaranteed to exist.  This may require the   *      tkwin is guaranteed to exist.  This may require the
1474   *      window's ancestors to be created also.   *      window's ancestors to be created also.
1475   *   *
1476   *--------------------------------------------------------------   *--------------------------------------------------------------
1477   */   */
1478    
1479  void  void
1480  Tk_MakeWindowExist(tkwin)  Tk_MakeWindowExist(tkwin)
1481      Tk_Window tkwin;            /* Token for window. */      Tk_Window tkwin;            /* Token for window. */
1482  {  {
1483      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1484      TkWindow *winPtr2;      TkWindow *winPtr2;
1485      Window parent;      Window parent;
1486      Tcl_HashEntry *hPtr;      Tcl_HashEntry *hPtr;
1487      int new;      int new;
1488    
1489      if (winPtr->window != None) {      if (winPtr->window != None) {
1490          return;          return;
1491      }      }
1492    
1493      if ((winPtr->parentPtr == NULL) || (winPtr->flags & TK_TOP_LEVEL)) {      if ((winPtr->parentPtr == NULL) || (winPtr->flags & TK_TOP_LEVEL)) {
1494          parent = XRootWindow(winPtr->display, winPtr->screenNum);          parent = XRootWindow(winPtr->display, winPtr->screenNum);
1495      } else {      } else {
1496          if (winPtr->parentPtr->window == None) {          if (winPtr->parentPtr->window == None) {
1497              Tk_MakeWindowExist((Tk_Window) winPtr->parentPtr);              Tk_MakeWindowExist((Tk_Window) winPtr->parentPtr);
1498          }          }
1499          parent = winPtr->parentPtr->window;          parent = winPtr->parentPtr->window;
1500      }      }
1501    
1502      if (winPtr->classProcsPtr != NULL      if (winPtr->classProcsPtr != NULL
1503              && winPtr->classProcsPtr->createProc != NULL) {              && winPtr->classProcsPtr->createProc != NULL) {
1504          winPtr->window = (*winPtr->classProcsPtr->createProc)(tkwin, parent,          winPtr->window = (*winPtr->classProcsPtr->createProc)(tkwin, parent,
1505                  winPtr->instanceData);                  winPtr->instanceData);
1506      } else {      } else {
1507          winPtr->window = TkpMakeWindow(winPtr, parent);          winPtr->window = TkpMakeWindow(winPtr, parent);
1508      }      }
1509    
1510      hPtr = Tcl_CreateHashEntry(&winPtr->dispPtr->winTable,      hPtr = Tcl_CreateHashEntry(&winPtr->dispPtr->winTable,
1511              (char *) winPtr->window, &new);              (char *) winPtr->window, &new);
1512      Tcl_SetHashValue(hPtr, winPtr);      Tcl_SetHashValue(hPtr, winPtr);
1513      winPtr->dirtyAtts = 0;      winPtr->dirtyAtts = 0;
1514      winPtr->dirtyChanges = 0;      winPtr->dirtyChanges = 0;
1515  #ifdef TK_USE_INPUT_METHODS  #ifdef TK_USE_INPUT_METHODS
1516      winPtr->inputContext = NULL;      winPtr->inputContext = NULL;
1517  #endif /* TK_USE_INPUT_METHODS */  #endif /* TK_USE_INPUT_METHODS */
1518    
1519      if (!(winPtr->flags & TK_TOP_LEVEL)) {      if (!(winPtr->flags & TK_TOP_LEVEL)) {
1520          /*          /*
1521           * If any siblings higher up in the stacking order have already           * If any siblings higher up in the stacking order have already
1522           * been created then move this window to its rightful position           * been created then move this window to its rightful position
1523           * in the stacking order.           * in the stacking order.
1524           *           *
1525           * NOTE: this code ignores any changes anyone might have made           * NOTE: this code ignores any changes anyone might have made
1526           * to the sibling and stack_mode field of the window's attributes,           * to the sibling and stack_mode field of the window's attributes,
1527           * so it really isn't safe for these to be manipulated except           * so it really isn't safe for these to be manipulated except
1528           * by calling Tk_RestackWindow.           * by calling Tk_RestackWindow.
1529           */           */
1530    
1531          for (winPtr2 = winPtr->nextPtr; winPtr2 != NULL;          for (winPtr2 = winPtr->nextPtr; winPtr2 != NULL;
1532                  winPtr2 = winPtr2->nextPtr) {                  winPtr2 = winPtr2->nextPtr) {
1533              if ((winPtr2->window != None)              if ((winPtr2->window != None)
1534                      && !(winPtr2->flags & (TK_TOP_LEVEL|TK_REPARENTED))) {                      && !(winPtr2->flags & (TK_TOP_LEVEL|TK_REPARENTED))) {
1535                  XWindowChanges changes;                  XWindowChanges changes;
1536                  changes.sibling = winPtr2->window;                  changes.sibling = winPtr2->window;
1537                  changes.stack_mode = Below;                  changes.stack_mode = Below;
1538                  XConfigureWindow(winPtr->display, winPtr->window,                  XConfigureWindow(winPtr->display, winPtr->window,
1539                          CWSibling|CWStackMode, &changes);                          CWSibling|CWStackMode, &changes);
1540                  break;                  break;
1541              }              }
1542          }          }
1543    
1544          /*          /*
1545           * If this window has a different colormap than its parent, add           * If this window has a different colormap than its parent, add
1546           * the window to the WM_COLORMAP_WINDOWS property for its top-level.           * the window to the WM_COLORMAP_WINDOWS property for its top-level.
1547           */           */
1548    
1549          if ((winPtr->parentPtr != NULL) &&          if ((winPtr->parentPtr != NULL) &&
1550                  (winPtr->atts.colormap != winPtr->parentPtr->atts.colormap)) {                  (winPtr->atts.colormap != winPtr->parentPtr->atts.colormap)) {
1551              TkWmAddToColormapWindows(winPtr);              TkWmAddToColormapWindows(winPtr);
1552              winPtr->flags |= TK_WM_COLORMAP_WINDOW;              winPtr->flags |= TK_WM_COLORMAP_WINDOW;
1553          }          }
1554      }      }
1555    
1556      /*      /*
1557       * Issue a ConfigureNotify event if there were deferred configuration       * Issue a ConfigureNotify event if there were deferred configuration
1558       * changes (but skip it if the window is being deleted;  the       * changes (but skip it if the window is being deleted;  the
1559       * ConfigureNotify event could cause problems if we're being called       * ConfigureNotify event could cause problems if we're being called
1560       * from Tk_DestroyWindow under some conditions).       * from Tk_DestroyWindow under some conditions).
1561       */       */
1562    
1563      if ((winPtr->flags & TK_NEED_CONFIG_NOTIFY)      if ((winPtr->flags & TK_NEED_CONFIG_NOTIFY)
1564              && !(winPtr->flags & TK_ALREADY_DEAD)){              && !(winPtr->flags & TK_ALREADY_DEAD)){
1565          winPtr->flags &= ~TK_NEED_CONFIG_NOTIFY;          winPtr->flags &= ~TK_NEED_CONFIG_NOTIFY;
1566          TkDoConfigureNotify(winPtr);          TkDoConfigureNotify(winPtr);
1567      }      }
1568  }  }
1569    
1570  /*  /*
1571   *--------------------------------------------------------------   *--------------------------------------------------------------
1572   *   *
1573   * Tk_UnmapWindow, etc. --   * Tk_UnmapWindow, etc. --
1574   *   *
1575   *      There are several procedures under here, each of which   *      There are several procedures under here, each of which
1576   *      mirrors an existing X procedure.  In addition to performing   *      mirrors an existing X procedure.  In addition to performing
1577   *      the functions of the corresponding procedure, each   *      the functions of the corresponding procedure, each
1578   *      procedure also updates the local window structure and   *      procedure also updates the local window structure and
1579   *      synthesizes an X event (if the window's structure is being   *      synthesizes an X event (if the window's structure is being
1580   *      managed internally).   *      managed internally).
1581   *   *
1582   * Results:   * Results:
1583   *      See the manual entries.   *      See the manual entries.
1584   *   *
1585   * Side effects:   * Side effects:
1586   *      See the manual entries.   *      See the manual entries.
1587   *   *
1588   *--------------------------------------------------------------   *--------------------------------------------------------------
1589   */   */
1590    
1591  void  void
1592  Tk_UnmapWindow(tkwin)  Tk_UnmapWindow(tkwin)
1593      Tk_Window tkwin;            /* Token for window to unmap. */      Tk_Window tkwin;            /* Token for window to unmap. */
1594  {  {
1595      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1596    
1597      if (!(winPtr->flags & TK_MAPPED) || (winPtr->flags & TK_ALREADY_DEAD)) {      if (!(winPtr->flags & TK_MAPPED) || (winPtr->flags & TK_ALREADY_DEAD)) {
1598          return;          return;
1599      }      }
1600      if (winPtr->flags & TK_TOP_LEVEL) {      if (winPtr->flags & TK_TOP_LEVEL) {
1601          /*          /*
1602           * Special processing has to be done for top-level windows.  Let           * Special processing has to be done for top-level windows.  Let
1603           * tkWm.c handle everything itself.           * tkWm.c handle everything itself.
1604           */           */
1605    
1606          TkWmUnmapWindow(winPtr);          TkWmUnmapWindow(winPtr);
1607          return;          return;
1608      }      }
1609      winPtr->flags &= ~TK_MAPPED;      winPtr->flags &= ~TK_MAPPED;
1610      XUnmapWindow(winPtr->display, winPtr->window);      XUnmapWindow(winPtr->display, winPtr->window);
1611      if (!(winPtr->flags & TK_TOP_LEVEL)) {      if (!(winPtr->flags & TK_TOP_LEVEL)) {
1612          XEvent event;          XEvent event;
1613    
1614          event.type = UnmapNotify;          event.type = UnmapNotify;
1615          event.xunmap.serial = LastKnownRequestProcessed(winPtr->display);          event.xunmap.serial = LastKnownRequestProcessed(winPtr->display);
1616          event.xunmap.send_event = False;          event.xunmap.send_event = False;
1617          event.xunmap.display = winPtr->display;          event.xunmap.display = winPtr->display;
1618          event.xunmap.event = winPtr->window;          event.xunmap.event = winPtr->window;
1619          event.xunmap.window = winPtr->window;          event.xunmap.window = winPtr->window;
1620          event.xunmap.from_configure = False;          event.xunmap.from_configure = False;
1621          Tk_HandleEvent(&event);          Tk_HandleEvent(&event);
1622      }      }
1623  }  }
1624    
1625  void  void
1626  Tk_ConfigureWindow(tkwin, valueMask, valuePtr)  Tk_ConfigureWindow(tkwin, valueMask, valuePtr)
1627      Tk_Window tkwin;            /* Window to re-configure. */      Tk_Window tkwin;            /* Window to re-configure. */
1628      unsigned int valueMask;     /* Mask indicating which parts of      unsigned int valueMask;     /* Mask indicating which parts of
1629                                   * *valuePtr are to be used. */                                   * *valuePtr are to be used. */
1630      XWindowChanges *valuePtr;   /* New values. */      XWindowChanges *valuePtr;   /* New values. */
1631  {  {
1632      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1633    
1634      if (valueMask & CWX) {      if (valueMask & CWX) {
1635          winPtr->changes.x = valuePtr->x;          winPtr->changes.x = valuePtr->x;
1636      }      }
1637      if (valueMask & CWY) {      if (valueMask & CWY) {
1638          winPtr->changes.y = valuePtr->y;          winPtr->changes.y = valuePtr->y;
1639      }      }
1640      if (valueMask & CWWidth) {      if (valueMask & CWWidth) {
1641          winPtr->changes.width = valuePtr->width;          winPtr->changes.width = valuePtr->width;
1642      }      }
1643      if (valueMask & CWHeight) {      if (valueMask & CWHeight) {
1644          winPtr->changes.height = valuePtr->height;          winPtr->changes.height = valuePtr->height;
1645      }      }
1646      if (valueMask & CWBorderWidth) {      if (valueMask & CWBorderWidth) {
1647          winPtr->changes.border_width = valuePtr->border_width;          winPtr->changes.border_width = valuePtr->border_width;
1648      }      }
1649      if (valueMask & (CWSibling|CWStackMode)) {      if (valueMask & (CWSibling|CWStackMode)) {
1650          panic("Can't set sibling or stack mode from Tk_ConfigureWindow.");          panic("Can't set sibling or stack mode from Tk_ConfigureWindow.");
1651      }      }
1652    
1653      if (winPtr->window != None) {      if (winPtr->window != None) {
1654          XConfigureWindow(winPtr->display, winPtr->window,          XConfigureWindow(winPtr->display, winPtr->window,
1655                  valueMask, valuePtr);                  valueMask, valuePtr);
1656          TkDoConfigureNotify(winPtr);          TkDoConfigureNotify(winPtr);
1657      } else {      } else {
1658          winPtr->dirtyChanges |= valueMask;          winPtr->dirtyChanges |= valueMask;
1659          winPtr->flags |= TK_NEED_CONFIG_NOTIFY;          winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1660      }      }
1661  }  }
1662    
1663  void  void
1664  Tk_MoveWindow(tkwin, x, y)  Tk_MoveWindow(tkwin, x, y)
1665      Tk_Window tkwin;            /* Window to move. */      Tk_Window tkwin;            /* Window to move. */
1666      int x, y;                   /* New location for window (within      int x, y;                   /* New location for window (within
1667                                   * parent). */                                   * parent). */
1668  {  {
1669      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1670    
1671      winPtr->changes.x = x;      winPtr->changes.x = x;
1672      winPtr->changes.y = y;      winPtr->changes.y = y;
1673      if (winPtr->window != None) {      if (winPtr->window != None) {
1674          XMoveWindow(winPtr->display, winPtr->window, x, y);          XMoveWindow(winPtr->display, winPtr->window, x, y);
1675          TkDoConfigureNotify(winPtr);          TkDoConfigureNotify(winPtr);
1676      } else {      } else {
1677          winPtr->dirtyChanges |= CWX|CWY;          winPtr->dirtyChanges |= CWX|CWY;
1678          winPtr->flags |= TK_NEED_CONFIG_NOTIFY;          winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1679      }      }
1680  }  }
1681    
1682  void  void
1683  Tk_ResizeWindow(tkwin, width, height)  Tk_ResizeWindow(tkwin, width, height)
1684      Tk_Window tkwin;            /* Window to resize. */      Tk_Window tkwin;            /* Window to resize. */
1685      int width, height;          /* New dimensions for window. */      int width, height;          /* New dimensions for window. */
1686  {  {
1687      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1688    
1689      winPtr->changes.width = (unsigned) width;      winPtr->changes.width = (unsigned) width;
1690      winPtr->changes.height = (unsigned) height;      winPtr->changes.height = (unsigned) height;
1691      if (winPtr->window != None) {      if (winPtr->window != None) {
1692          XResizeWindow(winPtr->display, winPtr->window, (unsigned) width,          XResizeWindow(winPtr->display, winPtr->window, (unsigned) width,
1693                  (unsigned) height);                  (unsigned) height);
1694          TkDoConfigureNotify(winPtr);          TkDoConfigureNotify(winPtr);
1695      } else {      } else {
1696          winPtr->dirtyChanges |= CWWidth|CWHeight;          winPtr->dirtyChanges |= CWWidth|CWHeight;
1697          winPtr->flags |= TK_NEED_CONFIG_NOTIFY;          winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1698      }      }
1699  }  }
1700    
1701  void  void
1702  Tk_MoveResizeWindow(tkwin, x, y, width, height)  Tk_MoveResizeWindow(tkwin, x, y, width, height)
1703      Tk_Window tkwin;            /* Window to move and resize. */      Tk_Window tkwin;            /* Window to move and resize. */
1704      int x, y;                   /* New location for window (within      int x, y;                   /* New location for window (within
1705                                   * parent). */                                   * parent). */
1706      int width, height;          /* New dimensions for window. */      int width, height;          /* New dimensions for window. */
1707  {  {
1708      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1709    
1710      winPtr->changes.x = x;      winPtr->changes.x = x;
1711      winPtr->changes.y = y;      winPtr->changes.y = y;
1712      winPtr->changes.width = (unsigned) width;      winPtr->changes.width = (unsigned) width;
1713      winPtr->changes.height = (unsigned) height;      winPtr->changes.height = (unsigned) height;
1714      if (winPtr->window != None) {      if (winPtr->window != None) {
1715          XMoveResizeWindow(winPtr->display, winPtr->window, x, y,          XMoveResizeWindow(winPtr->display, winPtr->window, x, y,
1716                  (unsigned) width, (unsigned) height);                  (unsigned) width, (unsigned) height);
1717          TkDoConfigureNotify(winPtr);          TkDoConfigureNotify(winPtr);
1718      } else {      } else {
1719          winPtr->dirtyChanges |= CWX|CWY|CWWidth|CWHeight;          winPtr->dirtyChanges |= CWX|CWY|CWWidth|CWHeight;
1720          winPtr->flags |= TK_NEED_CONFIG_NOTIFY;          winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1721      }      }
1722  }  }
1723    
1724  void  void
1725  Tk_SetWindowBorderWidth(tkwin, width)  Tk_SetWindowBorderWidth(tkwin, width)
1726      Tk_Window tkwin;            /* Window to modify. */      Tk_Window tkwin;            /* Window to modify. */
1727      int width;                  /* New border width for window. */      int width;                  /* New border width for window. */
1728  {  {
1729      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1730    
1731      winPtr->changes.border_width = width;      winPtr->changes.border_width = width;
1732      if (winPtr->window != None) {      if (winPtr->window != None) {
1733          XSetWindowBorderWidth(winPtr->display, winPtr->window,          XSetWindowBorderWidth(winPtr->display, winPtr->window,
1734                  (unsigned) width);                  (unsigned) width);
1735          TkDoConfigureNotify(winPtr);          TkDoConfigureNotify(winPtr);
1736      } else {      } else {
1737          winPtr->dirtyChanges |= CWBorderWidth;          winPtr->dirtyChanges |= CWBorderWidth;
1738          winPtr->flags |= TK_NEED_CONFIG_NOTIFY;          winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1739      }      }
1740  }  }
1741    
1742  void  void
1743  Tk_ChangeWindowAttributes(tkwin, valueMask, attsPtr)  Tk_ChangeWindowAttributes(tkwin, valueMask, attsPtr)
1744      Tk_Window tkwin;            /* Window to manipulate. */      Tk_Window tkwin;            /* Window to manipulate. */
1745      unsigned long valueMask;    /* OR'ed combination of bits,      unsigned long valueMask;    /* OR'ed combination of bits,
1746                                   * indicating which fields of                                   * indicating which fields of
1747                                   * *attsPtr are to be used. */                                   * *attsPtr are to be used. */
1748      register XSetWindowAttributes *attsPtr;      register XSetWindowAttributes *attsPtr;
1749                                  /* New values for some attributes. */                                  /* New values for some attributes. */
1750  {  {
1751      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1752    
1753      if (valueMask & CWBackPixmap) {      if (valueMask & CWBackPixmap) {
1754          winPtr->atts.background_pixmap = attsPtr->background_pixmap;          winPtr->atts.background_pixmap = attsPtr->background_pixmap;
1755      }      }
1756      if (valueMask & CWBackPixel) {      if (valueMask & CWBackPixel) {
1757          winPtr->atts.background_pixel = attsPtr->background_pixel;          winPtr->atts.background_pixel = attsPtr->background_pixel;
1758      }      }
1759      if (valueMask & CWBorderPixmap) {      if (valueMask & CWBorderPixmap) {
1760          winPtr->atts.border_pixmap = attsPtr->border_pixmap;          winPtr->atts.border_pixmap = attsPtr->border_pixmap;
1761      }      }
1762      if (valueMask & CWBorderPixel) {      if (valueMask & CWBorderPixel) {
1763          winPtr->atts.border_pixel = attsPtr->border_pixel;          winPtr->atts.border_pixel = attsPtr->border_pixel;
1764      }      }
1765      if (valueMask & CWBitGravity) {      if (valueMask & CWBitGravity) {
1766          winPtr->atts.bit_gravity = attsPtr->bit_gravity;          winPtr->atts.bit_gravity = attsPtr->bit_gravity;
1767      }      }
1768      if (valueMask & CWWinGravity) {      if (valueMask & CWWinGravity) {
1769          winPtr->atts.win_gravity = attsPtr->win_gravity;          winPtr->atts.win_gravity = attsPtr->win_gravity;
1770      }      }
1771      if (valueMask & CWBackingStore) {      if (valueMask & CWBackingStore) {
1772          winPtr->atts.backing_store = attsPtr->backing_store;          winPtr->atts.backing_store = attsPtr->backing_store;
1773      }      }
1774      if (valueMask & CWBackingPlanes) {      if (valueMask & CWBackingPlanes) {
1775          winPtr->atts.backing_planes = attsPtr->backing_planes;          winPtr->atts.backing_planes = attsPtr->backing_planes;
1776      }      }
1777      if (valueMask & CWBackingPixel) {      if (valueMask & CWBackingPixel) {
1778          winPtr->atts.backing_pixel = attsPtr->backing_pixel;          winPtr->atts.backing_pixel = attsPtr->backing_pixel;
1779      }      }
1780      if (valueMask & CWOverrideRedirect) {      if (valueMask & CWOverrideRedirect) {
1781          winPtr->atts.override_redirect = attsPtr->override_redirect;          winPtr->atts.override_redirect = attsPtr->override_redirect;
1782      }      }
1783      if (valueMask & CWSaveUnder) {      if (valueMask & CWSaveUnder) {
1784          winPtr->atts.save_under = attsPtr->save_under;          winPtr->atts.save_under = attsPtr->save_under;
1785      }      }
1786      if (valueMask & CWEventMask) {      if (valueMask & CWEventMask) {
1787          winPtr->atts.event_mask = attsPtr->event_mask;          winPtr->atts.event_mask = attsPtr->event_mask;
1788      }      }
1789      if (valueMask & CWDontPropagate) {      if (valueMask & CWDontPropagate) {
1790          winPtr->atts.do_not_propagate_mask          winPtr->atts.do_not_propagate_mask
1791                  = attsPtr->do_not_propagate_mask;                  = attsPtr->do_not_propagate_mask;
1792      }      }
1793      if (valueMask & CWColormap) {      if (valueMask & CWColormap) {
1794          winPtr->atts.colormap = attsPtr->colormap;          winPtr->atts.colormap = attsPtr->colormap;
1795      }      }
1796      if (valueMask & CWCursor) {      if (valueMask & CWCursor) {
1797          winPtr->atts.cursor = attsPtr->cursor;          winPtr->atts.cursor = attsPtr->cursor;
1798      }      }
1799    
1800      if (winPtr->window != None) {      if (winPtr->window != None) {
1801          XChangeWindowAttributes(winPtr->display, winPtr->window,          XChangeWindowAttributes(winPtr->display, winPtr->window,
1802                  valueMask, attsPtr);                  valueMask, attsPtr);
1803      } else {      } else {
1804          winPtr->dirtyAtts |= valueMask;          winPtr->dirtyAtts |= valueMask;
1805      }      }
1806  }  }
1807    
1808  void  void
1809  Tk_SetWindowBackground(tkwin, pixel)  Tk_SetWindowBackground(tkwin, pixel)
1810      Tk_Window tkwin;            /* Window to manipulate. */      Tk_Window tkwin;            /* Window to manipulate. */
1811      unsigned long pixel;        /* Pixel value to use for      unsigned long pixel;        /* Pixel value to use for
1812                                   * window's background. */                                   * window's background. */
1813  {  {
1814      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1815    
1816      winPtr->atts.background_pixel = pixel;      winPtr->atts.background_pixel = pixel;
1817    
1818      if (winPtr->window != None) {      if (winPtr->window != None) {
1819          XSetWindowBackground(winPtr->display, winPtr->window, pixel);          XSetWindowBackground(winPtr->display, winPtr->window, pixel);
1820      } else {      } else {
1821          winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBackPixmap)          winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBackPixmap)
1822                  | CWBackPixel;                  | CWBackPixel;
1823      }      }
1824  }  }
1825    
1826  void  void
1827  Tk_SetWindowBackgroundPixmap(tkwin, pixmap)  Tk_SetWindowBackgroundPixmap(tkwin, pixmap)
1828      Tk_Window tkwin;            /* Window to manipulate. */      Tk_Window tkwin;            /* Window to manipulate. */
1829      Pixmap pixmap;              /* Pixmap to use for window's      Pixmap pixmap;              /* Pixmap to use for window's
1830                                   * background. */                                   * background. */
1831  {  {
1832      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1833    
1834      winPtr->atts.background_pixmap = pixmap;      winPtr->atts.background_pixmap = pixmap;
1835    
1836      if (winPtr->window != None) {      if (winPtr->window != None) {
1837          XSetWindowBackgroundPixmap(winPtr->display,          XSetWindowBackgroundPixmap(winPtr->display,
1838                  winPtr->window, pixmap);                  winPtr->window, pixmap);
1839      } else {      } else {
1840          winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBackPixel)          winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBackPixel)
1841                  | CWBackPixmap;                  | CWBackPixmap;
1842      }      }
1843  }  }
1844    
1845  void  void
1846  Tk_SetWindowBorder(tkwin, pixel)  Tk_SetWindowBorder(tkwin, pixel)
1847      Tk_Window tkwin;            /* Window to manipulate. */      Tk_Window tkwin;            /* Window to manipulate. */
1848      unsigned long pixel;        /* Pixel value to use for      unsigned long pixel;        /* Pixel value to use for
1849                                   * window's border. */                                   * window's border. */
1850  {  {
1851      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1852    
1853      winPtr->atts.border_pixel = pixel;      winPtr->atts.border_pixel = pixel;
1854    
1855      if (winPtr->window != None) {      if (winPtr->window != None) {
1856          XSetWindowBorder(winPtr->display, winPtr->window, pixel);          XSetWindowBorder(winPtr->display, winPtr->window, pixel);
1857      } else {      } else {
1858          winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBorderPixmap)          winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBorderPixmap)
1859                  | CWBorderPixel;                  | CWBorderPixel;
1860      }      }
1861  }  }
1862    
1863  void  void
1864  Tk_SetWindowBorderPixmap(tkwin, pixmap)  Tk_SetWindowBorderPixmap(tkwin, pixmap)
1865      Tk_Window tkwin;            /* Window to manipulate. */      Tk_Window tkwin;            /* Window to manipulate. */
1866      Pixmap pixmap;              /* Pixmap to use for window's      Pixmap pixmap;              /* Pixmap to use for window's
1867                                   * border. */                                   * border. */
1868  {  {
1869      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1870    
1871      winPtr->atts.border_pixmap = pixmap;      winPtr->atts.border_pixmap = pixmap;
1872    
1873      if (winPtr->window != None) {      if (winPtr->window != None) {
1874          XSetWindowBorderPixmap(winPtr->display,          XSetWindowBorderPixmap(winPtr->display,
1875                  winPtr->window, pixmap);                  winPtr->window, pixmap);
1876      } else {      } else {
1877          winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBorderPixel)          winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBorderPixel)
1878                  | CWBorderPixmap;                  | CWBorderPixmap;
1879      }      }
1880  }  }
1881    
1882  void  void
1883  Tk_DefineCursor(tkwin, cursor)  Tk_DefineCursor(tkwin, cursor)
1884      Tk_Window tkwin;            /* Window to manipulate. */      Tk_Window tkwin;            /* Window to manipulate. */
1885      Tk_Cursor cursor;           /* Cursor to use for window (may be None). */      Tk_Cursor cursor;           /* Cursor to use for window (may be None). */
1886  {  {
1887      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1888    
1889  #ifdef MAC_TCL  #ifdef MAC_TCL
1890      winPtr->atts.cursor = (XCursor) cursor;      winPtr->atts.cursor = (XCursor) cursor;
1891  #else  #else
1892      winPtr->atts.cursor = (Cursor) cursor;      winPtr->atts.cursor = (Cursor) cursor;
1893  #endif  #endif
1894            
1895      if (winPtr->window != None) {      if (winPtr->window != None) {
1896          XDefineCursor(winPtr->display, winPtr->window, winPtr->atts.cursor);          XDefineCursor(winPtr->display, winPtr->window, winPtr->atts.cursor);
1897      } else {      } else {
1898          winPtr->dirtyAtts = winPtr->dirtyAtts | CWCursor;          winPtr->dirtyAtts = winPtr->dirtyAtts | CWCursor;
1899      }      }
1900  }  }
1901    
1902  void  void
1903  Tk_UndefineCursor(tkwin)  Tk_UndefineCursor(tkwin)
1904      Tk_Window tkwin;            /* Window to manipulate. */      Tk_Window tkwin;            /* Window to manipulate. */
1905  {  {
1906      Tk_DefineCursor(tkwin, None);      Tk_DefineCursor(tkwin, None);
1907  }  }
1908    
1909  void  void
1910  Tk_SetWindowColormap(tkwin, colormap)  Tk_SetWindowColormap(tkwin, colormap)
1911      Tk_Window tkwin;            /* Window to manipulate. */      Tk_Window tkwin;            /* Window to manipulate. */
1912      Colormap colormap;          /* Colormap to use for window. */      Colormap colormap;          /* Colormap to use for window. */
1913  {  {
1914      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1915    
1916      winPtr->atts.colormap = colormap;      winPtr->atts.colormap = colormap;
1917    
1918      if (winPtr->window != None) {      if (winPtr->window != None) {
1919          XSetWindowColormap(winPtr->display, winPtr->window, colormap);          XSetWindowColormap(winPtr->display, winPtr->window, colormap);
1920          if (!(winPtr->flags & TK_TOP_LEVEL)) {          if (!(winPtr->flags & TK_TOP_LEVEL)) {
1921              TkWmAddToColormapWindows(winPtr);              TkWmAddToColormapWindows(winPtr);
1922              winPtr->flags |= TK_WM_COLORMAP_WINDOW;              winPtr->flags |= TK_WM_COLORMAP_WINDOW;
1923          }          }
1924      } else {      } else {
1925          winPtr->dirtyAtts |= CWColormap;          winPtr->dirtyAtts |= CWColormap;
1926      }      }
1927  }  }
1928    
1929  /*  /*
1930   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1931   *   *
1932   * Tk_SetWindowVisual --   * Tk_SetWindowVisual --
1933   *   *
1934   *      This procedure is called to specify a visual to be used   *      This procedure is called to specify a visual to be used
1935   *      for a Tk window when it is created.  This procedure, if   *      for a Tk window when it is created.  This procedure, if
1936   *      called at all, must be called before the X window is created   *      called at all, must be called before the X window is created
1937   *      (i.e. before Tk_MakeWindowExist is called).   *      (i.e. before Tk_MakeWindowExist is called).
1938   *   *
1939   * Results:   * Results:
1940   *      The return value is 1 if successful, or 0 if the X window has   *      The return value is 1 if successful, or 0 if the X window has
1941   *      been already created.   *      been already created.
1942   *   *
1943   * Side effects:   * Side effects:
1944   *      The information given is stored for when the window is created.   *      The information given is stored for when the window is created.
1945   *   *
1946   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1947   */   */
1948    
1949  int  int
1950  Tk_SetWindowVisual(tkwin, visual, depth, colormap)  Tk_SetWindowVisual(tkwin, visual, depth, colormap)
1951      Tk_Window tkwin;            /* Window to manipulate. */      Tk_Window tkwin;            /* Window to manipulate. */
1952      Visual *visual;             /* New visual for window. */      Visual *visual;             /* New visual for window. */
1953      int depth;                  /* New depth for window. */      int depth;                  /* New depth for window. */
1954      Colormap colormap;          /* An appropriate colormap for the visual. */      Colormap colormap;          /* An appropriate colormap for the visual. */
1955  {  {
1956      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
1957    
1958      if( winPtr->window != None ){      if( winPtr->window != None ){
1959          /* Too late! */          /* Too late! */
1960          return 0;          return 0;
1961      }      }
1962    
1963      winPtr->visual = visual;      winPtr->visual = visual;
1964      winPtr->depth = depth;      winPtr->depth = depth;
1965      winPtr->atts.colormap = colormap;      winPtr->atts.colormap = colormap;
1966      winPtr->dirtyAtts |= CWColormap;      winPtr->dirtyAtts |= CWColormap;
1967    
1968      /*      /*
1969       * The following code is needed to make sure that the window doesn't       * The following code is needed to make sure that the window doesn't
1970       * inherit the parent's border pixmap, which would result in a BadMatch       * inherit the parent's border pixmap, which would result in a BadMatch
1971       * error.       * error.
1972       */       */
1973    
1974      if (!(winPtr->dirtyAtts & CWBorderPixmap)) {      if (!(winPtr->dirtyAtts & CWBorderPixmap)) {
1975          winPtr->dirtyAtts |= CWBorderPixel;          winPtr->dirtyAtts |= CWBorderPixel;
1976      }      }
1977      return 1;      return 1;
1978  }  }
1979    
1980  /*  /*
1981   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1982   *   *
1983   * TkDoConfigureNotify --   * TkDoConfigureNotify --
1984   *   *
1985   *      Generate a ConfigureNotify event describing the current   *      Generate a ConfigureNotify event describing the current
1986   *      configuration of a window.   *      configuration of a window.
1987   *   *
1988   * Results:   * Results:
1989   *      None.   *      None.
1990   *   *
1991   * Side effects:   * Side effects:
1992   *      An event is generated and processed by Tk_HandleEvent.   *      An event is generated and processed by Tk_HandleEvent.
1993   *   *
1994   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1995   */   */
1996    
1997  void  void
1998  TkDoConfigureNotify(winPtr)  TkDoConfigureNotify(winPtr)
1999      register TkWindow *winPtr;          /* Window whose configuration      register TkWindow *winPtr;          /* Window whose configuration
2000                                           * was just changed. */                                           * was just changed. */
2001  {  {
2002      XEvent event;      XEvent event;
2003    
2004      event.type = ConfigureNotify;      event.type = ConfigureNotify;
2005      event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display);      event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display);
2006      event.xconfigure.send_event = False;      event.xconfigure.send_event = False;
2007      event.xconfigure.display = winPtr->display;      event.xconfigure.display = winPtr->display;
2008      event.xconfigure.event = winPtr->window;      event.xconfigure.event = winPtr->window;
2009      event.xconfigure.window = winPtr->window;      event.xconfigure.window = winPtr->window;
2010      event.xconfigure.x = winPtr->changes.x;      event.xconfigure.x = winPtr->changes.x;
2011      event.xconfigure.y = winPtr->changes.y;      event.xconfigure.y = winPtr->changes.y;
2012      event.xconfigure.width = winPtr->changes.width;      event.xconfigure.width = winPtr->changes.width;
2013      event.xconfigure.height = winPtr->changes.height;      event.xconfigure.height = winPtr->changes.height;
2014      event.xconfigure.border_width = winPtr->changes.border_width;      event.xconfigure.border_width = winPtr->changes.border_width;
2015      if (winPtr->changes.stack_mode == Above) {      if (winPtr->changes.stack_mode == Above) {
2016          event.xconfigure.above = winPtr->changes.sibling;          event.xconfigure.above = winPtr->changes.sibling;
2017      } else {      } else {
2018          event.xconfigure.above = None;          event.xconfigure.above = None;
2019      }      }
2020      event.xconfigure.override_redirect = winPtr->atts.override_redirect;      event.xconfigure.override_redirect = winPtr->atts.override_redirect;
2021      Tk_HandleEvent(&event);      Tk_HandleEvent(&event);
2022  }  }
2023    
2024  /*  /*
2025   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2026   *   *
2027   * Tk_SetClass --   * Tk_SetClass --
2028   *   *
2029   *      This procedure is used to give a window a class.   *      This procedure is used to give a window a class.
2030   *   *
2031   * Results:   * Results:
2032   *      None.   *      None.
2033   *   *
2034   * Side effects:   * Side effects:
2035   *      A new class is stored for tkwin, replacing any existing   *      A new class is stored for tkwin, replacing any existing
2036   *      class for it.   *      class for it.
2037   *   *
2038   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2039   */   */
2040    
2041  void  void
2042  Tk_SetClass(tkwin, className)  Tk_SetClass(tkwin, className)
2043      Tk_Window tkwin;            /* Token for window to assign class. */      Tk_Window tkwin;            /* Token for window to assign class. */
2044      char *className;            /* New class for tkwin. */      char *className;            /* New class for tkwin. */
2045  {  {
2046      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
2047    
2048      winPtr->classUid = Tk_GetUid(className);      winPtr->classUid = Tk_GetUid(className);
2049      if (winPtr->flags & TK_TOP_LEVEL) {      if (winPtr->flags & TK_TOP_LEVEL) {
2050          TkWmSetClass(winPtr);          TkWmSetClass(winPtr);
2051      }      }
2052      TkOptionClassChanged(winPtr);      TkOptionClassChanged(winPtr);
2053  }  }
2054    
2055  /*  /*
2056   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2057   *   *
2058   * TkSetClassProcs --   * TkSetClassProcs --
2059   *   *
2060   *      This procedure is used to set the class procedures and   *      This procedure is used to set the class procedures and
2061   *      instance data for a window.   *      instance data for a window.
2062   *   *
2063   * Results:   * Results:
2064   *      None.   *      None.
2065   *   *
2066   * Side effects:   * Side effects:
2067   *      A new set of class procedures and instance data is stored   *      A new set of class procedures and instance data is stored
2068   *      for tkwin, replacing any existing values.   *      for tkwin, replacing any existing values.
2069   *   *
2070   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2071   */   */
2072    
2073  void  void
2074  TkSetClassProcs(tkwin, procs, instanceData)  TkSetClassProcs(tkwin, procs, instanceData)
2075      Tk_Window tkwin;            /* Token for window to modify. */      Tk_Window tkwin;            /* Token for window to modify. */
2076      TkClassProcs *procs;        /* Class procs structure. */      TkClassProcs *procs;        /* Class procs structure. */
2077      ClientData instanceData;    /* Data to be passed to class procedures. */      ClientData instanceData;    /* Data to be passed to class procedures. */
2078  {  {
2079      register TkWindow *winPtr = (TkWindow *) tkwin;      register TkWindow *winPtr = (TkWindow *) tkwin;
2080    
2081      winPtr->classProcsPtr = procs;      winPtr->classProcsPtr = procs;
2082      winPtr->instanceData = instanceData;      winPtr->instanceData = instanceData;
2083  }  }
2084    
2085  /*  /*
2086   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2087   *   *
2088   * Tk_NameToWindow --   * Tk_NameToWindow --
2089   *   *
2090   *      Given a string name for a window, this procedure   *      Given a string name for a window, this procedure
2091   *      returns the token for the window, if there exists a   *      returns the token for the window, if there exists a
2092   *      window corresponding to the given name.   *      window corresponding to the given name.
2093   *   *
2094   * Results:   * Results:
2095   *      The return result is either a token for the window corresponding   *      The return result is either a token for the window corresponding
2096   *      to "name", or else NULL to indicate that there is no such   *      to "name", or else NULL to indicate that there is no such
2097   *      window.  In this case, an error message is left in the interp's result.   *      window.  In this case, an error message is left in the interp's result.
2098   *   *
2099   * Side effects:   * Side effects:
2100   *      None.   *      None.
2101   *   *
2102   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2103   */   */
2104    
2105  Tk_Window  Tk_Window
2106  Tk_NameToWindow(interp, pathName, tkwin)  Tk_NameToWindow(interp, pathName, tkwin)
2107      Tcl_Interp *interp;         /* Where to report errors. */      Tcl_Interp *interp;         /* Where to report errors. */
2108      char *pathName;             /* Path name of window. */      char *pathName;             /* Path name of window. */
2109      Tk_Window tkwin;            /* Token for window:  name is assumed to      Tk_Window tkwin;            /* Token for window:  name is assumed to
2110                                   * belong to the same main window as tkwin. */                                   * belong to the same main window as tkwin. */
2111  {  {
2112      Tcl_HashEntry *hPtr;      Tcl_HashEntry *hPtr;
2113    
2114      if (tkwin == NULL) {      if (tkwin == NULL) {
2115          /*          /*
2116           * Either we're not really in Tk, or the main window was destroyed and           * Either we're not really in Tk, or the main window was destroyed and
2117           * we're on our way out of the application           * we're on our way out of the application
2118           */           */
2119          Tcl_AppendResult(interp, "NULL main window", (char *)NULL);          Tcl_AppendResult(interp, "NULL main window", (char *)NULL);
2120          return NULL;          return NULL;
2121      }      }
2122            
2123      hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->nameTable,      hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->nameTable,
2124              pathName);              pathName);
2125      if (hPtr == NULL) {      if (hPtr == NULL) {
2126          Tcl_AppendResult(interp, "bad window path name \"",          Tcl_AppendResult(interp, "bad window path name \"",
2127                  pathName, "\"", (char *) NULL);                  pathName, "\"", (char *) NULL);
2128          return NULL;          return NULL;
2129      }      }
2130      return (Tk_Window) Tcl_GetHashValue(hPtr);      return (Tk_Window) Tcl_GetHashValue(hPtr);
2131  }  }
2132    
2133  /*  /*
2134   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2135   *   *
2136   * Tk_IdToWindow --   * Tk_IdToWindow --
2137   *   *
2138   *      Given an X display and window ID, this procedure returns the   *      Given an X display and window ID, this procedure returns the
2139   *      Tk token for the window, if there exists a Tk window corresponding   *      Tk token for the window, if there exists a Tk window corresponding
2140   *      to the given ID.   *      to the given ID.
2141   *   *
2142   * Results:   * Results:
2143   *      The return result is either a token for the window corresponding   *      The return result is either a token for the window corresponding
2144   *      to the given X id, or else NULL to indicate that there is no such   *      to the given X id, or else NULL to indicate that there is no such
2145   *      window.   *      window.
2146   *   *
2147   * Side effects:   * Side effects:
2148   *      None.   *      None.
2149   *   *
2150   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2151   */   */
2152    
2153  Tk_Window  Tk_Window
2154  Tk_IdToWindow(display, window)  Tk_IdToWindow(display, window)
2155      Display *display;           /* X display containing the window. */      Display *display;           /* X display containing the window. */
2156      Window window;              /* X window window id. */      Window window;              /* X window window id. */
2157  {  {
2158      TkDisplay *dispPtr;      TkDisplay *dispPtr;
2159      Tcl_HashEntry *hPtr;      Tcl_HashEntry *hPtr;
2160    
2161      for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) {      for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) {
2162          if (dispPtr == NULL) {          if (dispPtr == NULL) {
2163              return NULL;              return NULL;
2164          }          }
2165          if (dispPtr->display == display) {          if (dispPtr->display == display) {
2166              break;              break;
2167          }          }
2168      }      }
2169    
2170      hPtr = Tcl_FindHashEntry(&dispPtr->winTable, (char *) window);      hPtr = Tcl_FindHashEntry(&dispPtr->winTable, (char *) window);
2171      if (hPtr == NULL) {      if (hPtr == NULL) {
2172          return NULL;          return NULL;
2173      }      }
2174      return (Tk_Window) Tcl_GetHashValue(hPtr);      return (Tk_Window) Tcl_GetHashValue(hPtr);
2175  }  }
2176    
2177  /*  /*
2178   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2179   *   *
2180   * Tk_DisplayName --   * Tk_DisplayName --
2181   *   *
2182   *      Return the textual name of a window's display.   *      Return the textual name of a window's display.
2183   *   *
2184   * Results:   * Results:
2185   *      The return value is the string name of the display associated   *      The return value is the string name of the display associated
2186   *      with tkwin.   *      with tkwin.
2187   *   *
2188   * Side effects:   * Side effects:
2189   *      None.   *      None.
2190   *   *
2191   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2192   */   */
2193    
2194  char *  char *
2195  Tk_DisplayName(tkwin)  Tk_DisplayName(tkwin)
2196      Tk_Window tkwin;            /* Window whose display name is desired. */      Tk_Window tkwin;            /* Window whose display name is desired. */
2197  {  {
2198      return ((TkWindow *) tkwin)->dispPtr->name;      return ((TkWindow *) tkwin)->dispPtr->name;
2199  }  }
2200    
2201  /*  /*
2202   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2203   *   *
2204   * UnlinkWindow --   * UnlinkWindow --
2205   *   *
2206   *      This procedure removes a window from the childList of its   *      This procedure removes a window from the childList of its
2207   *      parent.   *      parent.
2208   *   *
2209   * Results:   * Results:
2210   *      None.   *      None.
2211   *   *
2212   * Side effects:   * Side effects:
2213   *      The window is unlinked from its childList.   *      The window is unlinked from its childList.
2214   *   *
2215   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2216   */   */
2217    
2218  static void  static void
2219  UnlinkWindow(winPtr)  UnlinkWindow(winPtr)
2220      TkWindow *winPtr;                   /* Child window to be unlinked. */      TkWindow *winPtr;                   /* Child window to be unlinked. */
2221  {  {
2222      TkWindow *prevPtr;      TkWindow *prevPtr;
2223    
2224      if (winPtr->parentPtr == NULL) {      if (winPtr->parentPtr == NULL) {
2225          return;          return;
2226      }      }
2227      prevPtr = winPtr->parentPtr->childList;      prevPtr = winPtr->parentPtr->childList;
2228      if (prevPtr == winPtr) {      if (prevPtr == winPtr) {
2229          winPtr->parentPtr->childList = winPtr->nextPtr;          winPtr->parentPtr->childList = winPtr->nextPtr;
2230          if (winPtr->nextPtr == NULL) {          if (winPtr->nextPtr == NULL) {
2231              winPtr->parentPtr->lastChildPtr = NULL;              winPtr->parentPtr->lastChildPtr = NULL;
2232          }          }
2233      } else {      } else {
2234          while (prevPtr->nextPtr != winPtr) {          while (prevPtr->nextPtr != winPtr) {
2235              prevPtr = prevPtr->nextPtr;              prevPtr = prevPtr->nextPtr;
2236              if (prevPtr == NULL) {              if (prevPtr == NULL) {
2237                  panic("UnlinkWindow couldn't find child in parent");                  panic("UnlinkWindow couldn't find child in parent");
2238              }              }
2239          }          }
2240          prevPtr->nextPtr = winPtr->nextPtr;          prevPtr->nextPtr = winPtr->nextPtr;
2241          if (winPtr->nextPtr == NULL) {          if (winPtr->nextPtr == NULL) {
2242              winPtr->parentPtr->lastChildPtr = prevPtr;              winPtr->parentPtr->lastChildPtr = prevPtr;
2243          }          }
2244      }      }
2245  }  }
2246    
2247  /*  /*
2248   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2249   *   *
2250   * Tk_RestackWindow --   * Tk_RestackWindow --
2251   *   *
2252   *      Change a window's position in the stacking order.   *      Change a window's position in the stacking order.
2253   *   *
2254   * Results:   * Results:
2255   *      TCL_OK is normally returned.  If other is not a descendant   *      TCL_OK is normally returned.  If other is not a descendant
2256   *      of tkwin's parent then TCL_ERROR is returned and tkwin is   *      of tkwin's parent then TCL_ERROR is returned and tkwin is
2257   *      not repositioned.   *      not repositioned.
2258   *   *
2259   * Side effects:   * Side effects:
2260   *      Tkwin is repositioned in the stacking order.   *      Tkwin is repositioned in the stacking order.
2261   *   *
2262   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2263   */   */
2264    
2265  int  int
2266  Tk_RestackWindow(tkwin, aboveBelow, other)  Tk_RestackWindow(tkwin, aboveBelow, other)
2267      Tk_Window tkwin;            /* Token for window whose position in      Tk_Window tkwin;            /* Token for window whose position in
2268                                   * the stacking order is to change. */                                   * the stacking order is to change. */
2269      int aboveBelow;             /* Indicates new position of tkwin relative      int aboveBelow;             /* Indicates new position of tkwin relative
2270                                   * to other;  must be Above or Below. */                                   * to other;  must be Above or Below. */
2271      Tk_Window other;            /* Tkwin will be moved to a position that      Tk_Window other;            /* Tkwin will be moved to a position that
2272                                   * puts it just above or below this window.                                   * puts it just above or below this window.
2273                                   * If NULL then tkwin goes above or below                                   * If NULL then tkwin goes above or below
2274                                   * all windows in the same parent. */                                   * all windows in the same parent. */
2275  {  {
2276      TkWindow *winPtr = (TkWindow *) tkwin;      TkWindow *winPtr = (TkWindow *) tkwin;
2277      TkWindow *otherPtr = (TkWindow *) other;      TkWindow *otherPtr = (TkWindow *) other;
2278    
2279      /*      /*
2280       * Special case:  if winPtr is a top-level window then just find       * Special case:  if winPtr is a top-level window then just find
2281       * the top-level ancestor of otherPtr and restack winPtr above       * the top-level ancestor of otherPtr and restack winPtr above
2282       * otherPtr without changing any of Tk's childLists.       * otherPtr without changing any of Tk's childLists.
2283       */       */
2284    
2285      if (winPtr->flags & TK_TOP_LEVEL) {      if (winPtr->flags & TK_TOP_LEVEL) {
2286          while ((otherPtr != NULL) && !(otherPtr->flags & TK_TOP_LEVEL)) {          while ((otherPtr != NULL) && !(otherPtr->flags & TK_TOP_LEVEL)) {
2287              otherPtr = otherPtr->parentPtr;              otherPtr = otherPtr->parentPtr;
2288          }          }
2289          TkWmRestackToplevel(winPtr, aboveBelow, otherPtr);          TkWmRestackToplevel(winPtr, aboveBelow, otherPtr);
2290          return TCL_OK;          return TCL_OK;
2291      }      }
2292    
2293      /*      /*
2294       * Find an ancestor of otherPtr that is a sibling of winPtr.       * Find an ancestor of otherPtr that is a sibling of winPtr.
2295       */       */
2296    
2297      if (winPtr->parentPtr == NULL) {      if (winPtr->parentPtr == NULL) {
2298          /*          /*
2299           * Window is going to be deleted shortly;  don't do anything.           * Window is going to be deleted shortly;  don't do anything.
2300           */           */
2301    
2302          return TCL_OK;          return TCL_OK;
2303      }      }
2304      if (otherPtr == NULL) {      if (otherPtr == NULL) {
2305          if (aboveBelow == Above) {          if (aboveBelow == Above) {
2306              otherPtr = winPtr->parentPtr->lastChildPtr;              otherPtr = winPtr->parentPtr->lastChildPtr;
2307          } else {          } else {
2308              otherPtr = winPtr->parentPtr->childList;              otherPtr = winPtr->parentPtr->childList;
2309          }          }
2310      } else {      } else {
2311          while (winPtr->parentPtr != otherPtr->parentPtr) {          while (winPtr->parentPtr != otherPtr->parentPtr) {
2312              if ((otherPtr == NULL) || (otherPtr->flags & TK_TOP_LEVEL)) {              if ((otherPtr == NULL) || (otherPtr->flags & TK_TOP_LEVEL)) {
2313                  return TCL_ERROR;                  return TCL_ERROR;
2314              }              }
2315              otherPtr = otherPtr->parentPtr;              otherPtr = otherPtr->parentPtr;
2316          }          }
2317      }      }
2318      if (otherPtr == winPtr) {      if (otherPtr == winPtr) {
2319          return TCL_OK;          return TCL_OK;
2320      }      }
2321    
2322      /*      /*
2323       * Reposition winPtr in the stacking order.       * Reposition winPtr in the stacking order.
2324       */       */
2325    
2326      UnlinkWindow(winPtr);      UnlinkWindow(winPtr);
2327      if (aboveBelow == Above) {      if (aboveBelow == Above) {
2328          winPtr->nextPtr = otherPtr->nextPtr;          winPtr->nextPtr = otherPtr->nextPtr;
2329          if (winPtr->nextPtr == NULL) {          if (winPtr->nextPtr == NULL) {
2330              winPtr->parentPtr->lastChildPtr = winPtr;              winPtr->parentPtr->lastChildPtr = winPtr;
2331          }          }
2332          otherPtr->nextPtr = winPtr;          otherPtr->nextPtr = winPtr;
2333      } else {      } else {
2334          TkWindow *prevPtr;          TkWindow *prevPtr;
2335    
2336          prevPtr = winPtr->parentPtr->childList;          prevPtr = winPtr->parentPtr->childList;
2337          if (prevPtr == otherPtr) {          if (prevPtr == otherPtr) {
2338              winPtr->parentPtr->childList = winPtr;              winPtr->parentPtr->childList = winPtr;
2339          } else {          } else {
2340              while (prevPtr->nextPtr != otherPtr) {              while (prevPtr->nextPtr != otherPtr) {
2341                  prevPtr = prevPtr->nextPtr;                  prevPtr = prevPtr->nextPtr;
2342              }              }
2343              prevPtr->nextPtr = winPtr;              prevPtr->nextPtr = winPtr;
2344          }          }
2345          winPtr->nextPtr = otherPtr;          winPtr->nextPtr = otherPtr;
2346      }      }
2347    
2348      /*      /*
2349       * Notify the X server of the change.  If winPtr hasn't yet been       * Notify the X server of the change.  If winPtr hasn't yet been
2350       * created then there's no need to tell the X server now, since       * created then there's no need to tell the X server now, since
2351       * the stacking order will be handled properly when the window       * the stacking order will be handled properly when the window
2352       * is finally created.       * is finally created.
2353       */       */
2354    
2355      if (winPtr->window != None) {      if (winPtr->window != None) {
2356          XWindowChanges changes;          XWindowChanges changes;
2357          unsigned int mask;          unsigned int mask;
2358    
2359          mask = CWStackMode;          mask = CWStackMode;
2360          changes.stack_mode = Above;          changes.stack_mode = Above;
2361          for (otherPtr = winPtr->nextPtr; otherPtr != NULL;          for (otherPtr = winPtr->nextPtr; otherPtr != NULL;
2362                  otherPtr = otherPtr->nextPtr) {                  otherPtr = otherPtr->nextPtr) {
2363              if ((otherPtr->window != None)              if ((otherPtr->window != None)
2364                      && !(otherPtr->flags & (TK_TOP_LEVEL|TK_REPARENTED))){                      && !(otherPtr->flags & (TK_TOP_LEVEL|TK_REPARENTED))){
2365                  changes.sibling = otherPtr->window;                  changes.sibling = otherPtr->window;
2366                  changes.stack_mode = Below;                  changes.stack_mode = Below;
2367                  mask = CWStackMode|CWSibling;                  mask = CWStackMode|CWSibling;
2368                  break;                  break;
2369              }              }
2370          }          }
2371          XConfigureWindow(winPtr->display, winPtr->window, mask, &changes);          XConfigureWindow(winPtr->display, winPtr->window, mask, &changes);
2372      }      }
2373      return TCL_OK;      return TCL_OK;
2374  }  }
2375    
2376  /*  /*
2377   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2378   *   *
2379   * Tk_MainWindow --   * Tk_MainWindow --
2380   *   *
2381   *      Returns the main window for an application.   *      Returns the main window for an application.
2382   *   *
2383   * Results:   * Results:
2384   *      If interp has a Tk application associated with it, the main   *      If interp has a Tk application associated with it, the main
2385   *      window for the application is returned.  Otherwise NULL is   *      window for the application is returned.  Otherwise NULL is
2386   *      returned and an error message is left in the interp's result.   *      returned and an error message is left in the interp's result.
2387   *   *
2388   * Side effects:   * Side effects:
2389   *      None.   *      None.
2390   *   *
2391   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2392   */   */
2393    
2394  Tk_Window  Tk_Window
2395  Tk_MainWindow(interp)  Tk_MainWindow(interp)
2396      Tcl_Interp *interp;                 /* Interpreter that embodies the      Tcl_Interp *interp;                 /* Interpreter that embodies the
2397                                           * application.  Used for error                                           * application.  Used for error
2398                                           * reporting also. */                                           * reporting also. */
2399  {  {
2400      TkMainInfo *mainPtr;      TkMainInfo *mainPtr;
2401      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
2402              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
2403    
2404      for (mainPtr = tsdPtr->mainWindowList; mainPtr != NULL;      for (mainPtr = tsdPtr->mainWindowList; mainPtr != NULL;
2405              mainPtr = mainPtr->nextPtr) {              mainPtr = mainPtr->nextPtr) {
2406          if (mainPtr->interp == interp) {          if (mainPtr->interp == interp) {
2407              return (Tk_Window) mainPtr->winPtr;              return (Tk_Window) mainPtr->winPtr;
2408          }          }
2409      }      }
2410      Tcl_SetResult(interp, "this isn't a Tk application", TCL_STATIC);      Tcl_SetResult(interp, "this isn't a Tk application", TCL_STATIC);
2411      return NULL;      return NULL;
2412  }  }
2413    
2414  /*  /*
2415   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2416   *   *
2417   * Tk_StrictMotif --   * Tk_StrictMotif --
2418   *   *
2419   *      Indicates whether strict Motif compliance has been specified   *      Indicates whether strict Motif compliance has been specified
2420   *      for the given window.   *      for the given window.
2421   *   *
2422   * Results:   * Results:
2423   *      The return value is 1 if strict Motif compliance has been   *      The return value is 1 if strict Motif compliance has been
2424   *      requested for tkwin's application by setting the tk_strictMotif   *      requested for tkwin's application by setting the tk_strictMotif
2425   *      variable in its interpreter to a true value.  0 is returned   *      variable in its interpreter to a true value.  0 is returned
2426   *      if tk_strictMotif has a false value.   *      if tk_strictMotif has a false value.
2427   *   *
2428   * Side effects:   * Side effects:
2429   *      None.   *      None.
2430   *   *
2431   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2432   */   */
2433    
2434  int  int
2435  Tk_StrictMotif(tkwin)  Tk_StrictMotif(tkwin)
2436      Tk_Window tkwin;                    /* Window whose application is      Tk_Window tkwin;                    /* Window whose application is
2437                                           * to be checked. */                                           * to be checked. */
2438  {  {
2439      return ((TkWindow *) tkwin)->mainPtr->strictMotif;      return ((TkWindow *) tkwin)->mainPtr->strictMotif;
2440  }  }
2441    
2442  /*  /*
2443   *--------------------------------------------------------------   *--------------------------------------------------------------
2444   *   *
2445   * OpenIM --   * OpenIM --
2446   *   *
2447   *      Tries to open an X input method, associated with the   *      Tries to open an X input method, associated with the
2448   *      given display.  Right now we can only deal with a bare-bones   *      given display.  Right now we can only deal with a bare-bones
2449   *      input style:  no preedit, and no status.   *      input style:  no preedit, and no status.
2450   *   *
2451   * Results:   * Results:
2452   *      Stores the input method in dispPtr->inputMethod;  if there isn't   *      Stores the input method in dispPtr->inputMethod;  if there isn't
2453   *      a suitable input method, then NULL is stored in dispPtr->inputMethod.   *      a suitable input method, then NULL is stored in dispPtr->inputMethod.
2454   *   *
2455   * Side effects:   * Side effects:
2456   *      An input method gets opened.   *      An input method gets opened.
2457   *   *
2458   *--------------------------------------------------------------   *--------------------------------------------------------------
2459   */   */
2460    
2461  static void  static void
2462  OpenIM(dispPtr)  OpenIM(dispPtr)
2463      TkDisplay *dispPtr;         /* Tk's structure for the display. */      TkDisplay *dispPtr;         /* Tk's structure for the display. */
2464  {  {
2465  #ifndef TK_USE_INPUT_METHODS  #ifndef TK_USE_INPUT_METHODS
2466      return;      return;
2467  #else  #else
2468      unsigned short i;      unsigned short i;
2469      XIMStyles *stylePtr;      XIMStyles *stylePtr;
2470    
2471      dispPtr->inputMethod = XOpenIM(dispPtr->display, NULL, NULL, NULL);      dispPtr->inputMethod = XOpenIM(dispPtr->display, NULL, NULL, NULL);
2472      if (dispPtr->inputMethod == NULL) {      if (dispPtr->inputMethod == NULL) {
2473          return;          return;
2474      }      }
2475    
2476      if ((XGetIMValues(dispPtr->inputMethod, XNQueryInputStyle, &stylePtr,      if ((XGetIMValues(dispPtr->inputMethod, XNQueryInputStyle, &stylePtr,
2477              NULL) != NULL) || (stylePtr == NULL)) {              NULL) != NULL) || (stylePtr == NULL)) {
2478          goto error;          goto error;
2479      }      }
2480      for (i = 0; i < stylePtr->count_styles; i++) {      for (i = 0; i < stylePtr->count_styles; i++) {
2481          if (stylePtr->supported_styles[i]          if (stylePtr->supported_styles[i]
2482                  == (XIMPreeditNothing|XIMStatusNothing)) {                  == (XIMPreeditNothing|XIMStatusNothing)) {
2483              XFree(stylePtr);              XFree(stylePtr);
2484              return;              return;
2485          }          }
2486      }      }
2487      XFree(stylePtr);      XFree(stylePtr);
2488    
2489      error:      error:
2490    
2491      /*      /*
2492       * Should close the input method, but this causes core dumps on some       * Should close the input method, but this causes core dumps on some
2493       * systems (e.g. Solaris 2.3 as of 1/6/95).       * systems (e.g. Solaris 2.3 as of 1/6/95).
2494       * XCloseIM(dispPtr->inputMethod);       * XCloseIM(dispPtr->inputMethod);
2495       */       */
2496      dispPtr->inputMethod = NULL;      dispPtr->inputMethod = NULL;
2497      return;      return;
2498  #endif /* TK_USE_INPUT_METHODS */  #endif /* TK_USE_INPUT_METHODS */
2499  }  }
2500    
2501  /*  /*
2502   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2503   *   *
2504   * Tk_GetNumMainWindows --   * Tk_GetNumMainWindows --
2505   *   *
2506   *      This procedure returns the number of main windows currently   *      This procedure returns the number of main windows currently
2507   *      open in this process.   *      open in this process.
2508   *   *
2509   * Results:   * Results:
2510   *      The number of main windows open in this process.   *      The number of main windows open in this process.
2511   *   *
2512   * Side effects:   * Side effects:
2513   *      None.   *      None.
2514   *   *
2515   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2516   */   */
2517    
2518  int  int
2519  Tk_GetNumMainWindows()  Tk_GetNumMainWindows()
2520  {  {
2521      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
2522              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
2523    
2524      return tsdPtr->numMainWindows;      return tsdPtr->numMainWindows;
2525  }  }
2526    
2527  /*  /*
2528   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2529   *   *
2530   * DeleteWindowsExitProc --   * DeleteWindowsExitProc --
2531   *   *
2532   *      This procedure is invoked as an exit handler.  It deletes all   *      This procedure is invoked as an exit handler.  It deletes all
2533   *      of the main windows in the process.   *      of the main windows in the process.
2534   *   *
2535   * Results:   * Results:
2536   *      None.   *      None.
2537   *   *
2538   * Side effects:   * Side effects:
2539   *      None.   *      None.
2540   *   *
2541   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2542   */   */
2543    
2544  static void  static void
2545  DeleteWindowsExitProc(clientData)  DeleteWindowsExitProc(clientData)
2546      ClientData clientData;              /* Not used. */      ClientData clientData;              /* Not used. */
2547  {  {
2548      TkDisplay *displayPtr, *nextPtr;      TkDisplay *displayPtr, *nextPtr;
2549      Tcl_Interp *interp;      Tcl_Interp *interp;
2550      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
2551              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
2552            
2553      while (tsdPtr->mainWindowList != NULL) {      while (tsdPtr->mainWindowList != NULL) {
2554          /*          /*
2555           * We must protect the interpreter while deleting the window,           * We must protect the interpreter while deleting the window,
2556           * because of <Destroy> bindings which could destroy the interpreter           * because of <Destroy> bindings which could destroy the interpreter
2557           * while the window is being deleted. This would leave frames on           * while the window is being deleted. This would leave frames on
2558           * the call stack pointing at deleted memory, causing core dumps.           * the call stack pointing at deleted memory, causing core dumps.
2559           */           */
2560                    
2561          interp = tsdPtr->mainWindowList->winPtr->mainPtr->interp;          interp = tsdPtr->mainWindowList->winPtr->mainPtr->interp;
2562          Tcl_Preserve((ClientData) interp);          Tcl_Preserve((ClientData) interp);
2563          Tk_DestroyWindow((Tk_Window) tsdPtr->mainWindowList->winPtr);          Tk_DestroyWindow((Tk_Window) tsdPtr->mainWindowList->winPtr);
2564          Tcl_Release((ClientData) interp);          Tcl_Release((ClientData) interp);
2565      }      }
2566            
2567      displayPtr = tsdPtr->displayList;      displayPtr = tsdPtr->displayList;
2568      tsdPtr->displayList = NULL;      tsdPtr->displayList = NULL;
2569            
2570      /*      /*
2571       * Iterate destroying the displays until no more displays remain.       * Iterate destroying the displays until no more displays remain.
2572       * It is possible for displays to get recreated during exit by any       * It is possible for displays to get recreated during exit by any
2573       * code that calls GetScreen, so we must destroy these new displays       * code that calls GetScreen, so we must destroy these new displays
2574       * as well as the old ones.       * as well as the old ones.
2575       */       */
2576            
2577      for (displayPtr = tsdPtr->displayList;      for (displayPtr = tsdPtr->displayList;
2578           displayPtr != NULL;           displayPtr != NULL;
2579           displayPtr = tsdPtr->displayList) {           displayPtr = tsdPtr->displayList) {
2580    
2581          /*          /*
2582           * Now iterate over the current list of open displays, and first           * Now iterate over the current list of open displays, and first
2583           * set the global pointer to NULL so we will be able to notice if           * set the global pointer to NULL so we will be able to notice if
2584           * any new displays got created during deletion of the current set.           * any new displays got created during deletion of the current set.
2585           * We must also do this to ensure that Tk_IdToWindow does not find           * We must also do this to ensure that Tk_IdToWindow does not find
2586           * the old display as it is being destroyed, when it wants to see           * the old display as it is being destroyed, when it wants to see
2587           * if it needs to dispatch a message.           * if it needs to dispatch a message.
2588           */           */
2589                    
2590          for (tsdPtr->displayList = NULL; displayPtr != NULL;          for (tsdPtr->displayList = NULL; displayPtr != NULL;
2591                  displayPtr = nextPtr) {                  displayPtr = nextPtr) {
2592              nextPtr = displayPtr->nextPtr;              nextPtr = displayPtr->nextPtr;
2593              if (displayPtr->name != (char *) NULL) {              if (displayPtr->name != (char *) NULL) {
2594                  ckfree(displayPtr->name);                  ckfree(displayPtr->name);
2595              }              }
2596              Tcl_DeleteHashTable(&(displayPtr->winTable));              Tcl_DeleteHashTable(&(displayPtr->winTable));
2597              TkpCloseDisplay(displayPtr);              TkpCloseDisplay(displayPtr);
2598          }          }
2599      }      }
2600            
2601      tsdPtr->numMainWindows = 0;      tsdPtr->numMainWindows = 0;
2602      tsdPtr->mainWindowList = NULL;      tsdPtr->mainWindowList = NULL;
2603      tsdPtr->initialized = 0;      tsdPtr->initialized = 0;
2604  }  }
2605    
2606  /*  /*
2607   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2608   *   *