home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tkisrc04.zip / tk / os2 / tkWindow.c < prev    next >
C/C++ Source or Header  |  1998-08-07  |  71KB  |  2,426 lines

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