home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mitsch75.zip / scheme-7_5_17-src.zip / scheme-7.5.17 / src / swat / c / tk3.2-custom / tkWindow.c < prev   
C/C++ Source or Header  |  1995-08-02  |  54KB  |  1,803 lines

  1. /**************************
  2.   Changes on April 1, 1993 to support Scheme UITK:
  3.   1) Added Tk_CreateMainWindow_from_display.
  4.   2) Renamed GetScreen to GetScreenByName.  Added GetScreenByDisplay.
  5.   3) Rewrote Tk_CreateMainWindow into Tk_CreateMainWindow_from_data,
  6.      which takes both a lookup procedure for finding a Screen and the
  7.      data necessary for the lookup.  Rewrite Tk_CreateMainWindow in
  8.      terms of this.
  9.   4) Changed the signature of CreateTopLevelWindow to accept a lookup
  10.      procedure and data.
  11.   5) Made NameWindow public for reparenting widgets when mapped by UITK
  12.   6) Added external entry point Tk_DestroyDisplayByNumber.
  13. **************************/
  14.  
  15. /* 
  16.  * tkWindow.c --
  17.  *
  18.  *    This file provides basic window-manipulation procedures,
  19.  *    which are equivalent to procedures in Xlib (and even
  20.  *    invoke them) but also maintain the local Tk_Window
  21.  *    structure.
  22.  *
  23.  * Copyright 1989-1992 Regents of the University of California.
  24.  * Permission to use, copy, modify, and distribute this
  25.  * software and its documentation for any purpose and without
  26.  * fee is hereby granted, provided that the above copyright
  27.  * notice appear in all copies.  The University of California
  28.  * makes no representations about the suitability of this
  29.  * software for any purpose.  It is provided "as is" without
  30.  * express or implied warranty.
  31.  */
  32.  
  33. #ifndef lint
  34. static char rcsid[] = "$Header: /scheme/cvsroot/v7/src/swat/c/tk3.2-custom/tkWindow.c,v 1.1 1995/08/02 21:23:26 adams Exp $ SPRITE (Berkeley)";
  35. #endif
  36.  
  37. #include "tkConfig.h"
  38. #include "tkInt.h"
  39.  
  40. /*
  41.  * Count of number of main windows currently open in this process.
  42.  */
  43.  
  44. int tk_NumMainWindows;
  45.  
  46. /*
  47.  * List of all displays currently in use.
  48.  */
  49.  
  50. TkDisplay *tkDisplayList = NULL;
  51.  
  52. /*
  53.  * Have statics in this module been initialized?
  54.  */
  55.  
  56. static initialized = 0;
  57.  
  58. /*
  59.  * Context information used to map from X window id's to
  60.  * TkWindow structures (during event handling, for example):
  61.  */
  62.  
  63. XContext tkWindowContext;
  64.  
  65. /*
  66.  * The variables below hold several uid's that are used in many places
  67.  * in the toolkit.
  68.  */
  69.  
  70. Tk_Uid tkDisabledUid = NULL;
  71. Tk_Uid tkActiveUid = NULL;
  72. Tk_Uid tkNormalUid = NULL;
  73.  
  74. /*
  75.  * Default values for "changes" and "atts" fields of TkWindows.  Note
  76.  * that Tk always requests all events for all windows, except StructureNotify
  77.  * events on internal windows:  these events are generated internally.
  78.  */
  79.  
  80. static XWindowChanges defChanges = {
  81.     0, 0, 1, 1, 0, 0, Above
  82. };
  83. #define ALL_EVENTS_MASK \
  84.     KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask| \
  85.     EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask| \
  86.     VisibilityChangeMask|SubstructureNotifyMask| \
  87.     FocusChangeMask|PropertyChangeMask|ColormapChangeMask
  88. static XSetWindowAttributes defAtts= {
  89.     None,            /* background_pixmap */
  90.     0,                /* background_pixel */
  91.     CopyFromParent,        /* border_pixmap */
  92.     0,                /* border_pixel */
  93.     ForgetGravity,        /* bit_gravity */
  94.     NorthWestGravity,        /* win_gravity */
  95.     NotUseful,            /* backing_store */
  96.     ~0,                /* backing_planes */
  97.     0,                /* backing_pixel */
  98.     False,            /* save_under */
  99.     ALL_EVENTS_MASK,        /* event_mask */
  100.     0,                /* do_not_propagate_mask */
  101.     False,            /* override_redirect */
  102.     CopyFromParent,        /* colormap */
  103.     None            /* cursor */
  104. };
  105.  
  106. /*
  107.  * The following structure defines all of the commands supported by
  108.  * Tk, and the C procedures that execute them.
  109.  */
  110.  
  111. typedef struct {
  112.     char *name;            /* Name of command. */
  113.     int (*cmdProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
  114.         int argc, char **argv));
  115.                 /* Command procedure. */
  116. } TkCmd;
  117.  
  118. TkCmd commands[] = {
  119.     /*
  120.      * Commands that are part of the intrinsics:
  121.      */
  122.  
  123.     {"after",        Tk_AfterCmd},
  124.     {"bind",        Tk_BindCmd},
  125.     {"destroy",        Tk_DestroyCmd},
  126.     {"focus",        Tk_FocusCmd},
  127.     {"grab",        Tk_GrabCmd},
  128.     {"option",        Tk_OptionCmd},
  129.     {"pack",        Tk_PackCmd},
  130.     {"place",        Tk_PlaceCmd},
  131.     {"selection",    Tk_SelectionCmd},
  132.     {"tk",        Tk_TkCmd},
  133.     {"tkwait",        Tk_TkwaitCmd},
  134.     {"update",        Tk_UpdateCmd},
  135.     {"winfo",        Tk_WinfoCmd},
  136.     {"wm",        Tk_WmCmd},
  137.  
  138.     /*
  139.      * Widget-creation commands.
  140.      */
  141.     {"button",        Tk_ButtonCmd},
  142.     {"canvas",        Tk_CanvasCmd},
  143.     {"checkbutton",    Tk_ButtonCmd},
  144.     {"entry",        Tk_EntryCmd},
  145.     {"frame",        Tk_FrameCmd},
  146.     {"label",        Tk_ButtonCmd},
  147.     {"listbox",        Tk_ListboxCmd},
  148.     {"menu",        Tk_MenuCmd},
  149.     {"menubutton",    Tk_MenubuttonCmd},
  150.     {"message",        Tk_MessageCmd},
  151.     {"radiobutton",    Tk_ButtonCmd},
  152.     {"scale",        Tk_ScaleCmd},
  153.     {"scrollbar",    Tk_ScrollbarCmd},
  154.     {"text",        Tk_TextCmd},
  155.     {"toplevel",    Tk_FrameCmd},
  156.     {(char *) NULL,    (int (*)()) NULL}
  157. };
  158.  
  159. /*
  160.  * Forward declarations to procedures defined later in this file:
  161.  */
  162.  
  163. static Tk_Window    CreateTopLevelWindow
  164.   _ANSI_ARGS_((Tcl_Interp *interp,
  165.            Tk_Window parent,
  166.            char *name,
  167.            TkDisplay *LookupProcedure(Tcl_Interp *interp,
  168.                       char *data,
  169.                       int *screenPtr),
  170.            char *data));
  171. static void        DoConfigureNotify _ANSI_ARGS_((TkWindow *winPtr));
  172. static TkDisplay *    GetScreenByName _ANSI_ARGS_((Tcl_Interp *interp,
  173.                              char *screenName,
  174.                              int *screenPtr));
  175. static TkDisplay *    GetScreenByDisplay _ANSI_ARGS_((Tcl_Interp *interp,
  176.                             char /*Display*/ *disp,
  177.                             int *screenPtr));
  178. extern int        NameWindow _ANSI_ARGS_((Tcl_Interp *interp,
  179.                 TkWindow *winPtr, TkWindow *parentPtr,
  180.                 char *name));
  181. static TkWindow    *    NewWindow _ANSI_ARGS_((TkDisplay *dispPtr,
  182.                 int screenNum, TkWindow *parentPtr));
  183.  
  184. extern void             Tk_DestroyDisplayByNumber _ANSI_ARGS_ ((Display *disp));
  185.  
  186. /*
  187.  *----------------------------------------------------------------------
  188.  *
  189.  * CreateTopLevelWindow --
  190.  *
  191.  *    Make a new window that will be at top-level (its parent will
  192.  *    be the root window of a screen).
  193.  *
  194.  * Results:
  195.  *    The return value is a token for the new window, or NULL if
  196.  *    an error prevented the new window from being created.  If
  197.  *    NULL is returned, an error message will be left in
  198.  *    interp->result.
  199.  *
  200.  * Side effects:
  201.  *    A new window structure is allocated locally.  An X
  202.  *    window is NOT initially created, but will be created
  203.  *    the first time the window is mapped.
  204.  *
  205.  *----------------------------------------------------------------------
  206.  */
  207.  
  208. static Tk_Window
  209. CreateTopLevelWindow(interp, parent, name, LookupProcedure, data)
  210.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  211.     Tk_Window parent;        /* Token for logical parent of new window
  212.                  * (used for naming, options, etc.).  May
  213.                  * be NULL. */
  214.     char *name;            /* Name for new window;  if parent is
  215.                  * non-NULL, must be unique among parent's
  216.                  * children. */
  217.     TkDisplay *(*LookupProcedure) _ANSI_ARGS_ ((Tcl_Interp *interp, char *data, int *screenPtr));
  218.                 /* Lookup a display structure, either */
  219.                 /* by name or by display connection */
  220.     char *data;            /* Data supplied to LookupProcedure: */
  221.                 /* either a screen name or a display */
  222.                 /* connection */
  223. {
  224.     register TkWindow *winPtr;
  225.     register TkDisplay *dispPtr;
  226.     int screenId;
  227.  
  228.     if (!initialized) {
  229.     initialized = 1;
  230.     tkWindowContext = XUniqueContext();
  231.     tkActiveUid = Tk_GetUid("active");
  232.     tkDisabledUid = Tk_GetUid("disabled");
  233.     tkNormalUid = Tk_GetUid("normal");
  234.     }
  235.  
  236.     if ((LookupProcedure==GetScreenByName) && (parent != NULL) &&
  237.     (data != NULL) && (data[0] == '\0'))
  238.     { dispPtr = ((TkWindow *) parent)->dispPtr;
  239.       screenId = Tk_ScreenNumber(parent);
  240.     }
  241.     else
  242.     { dispPtr = LookupProcedure(interp, data, &screenId);
  243.       if (dispPtr == NULL) return (Tk_Window) NULL;
  244.     }
  245.  
  246.     winPtr = NewWindow(dispPtr, screenId, (TkWindow *) parent);
  247.  
  248.     /*
  249.      * Internal windows don't normally ask for StructureNotify events,
  250.      * since we can generate them internally.  However, for top-level
  251.      * windows we need to as for the events because the window could
  252.      * be manipulated externally.
  253.      */
  254.  
  255.     winPtr->atts.event_mask |= StructureNotifyMask;
  256.  
  257.     /*
  258.      * (Need to set the TK_TOP_LEVEL flag immediately here;  otherwise
  259.      * Tk_DestroyWindow will core dump if it is called before the flag
  260.      * has been set.)
  261.      */
  262.  
  263.     winPtr->flags |= TK_TOP_LEVEL;
  264.     if (parent != NULL) {
  265.     if (NameWindow(interp, winPtr, (TkWindow *) parent, name) != TCL_OK) {
  266.         Tk_DestroyWindow((Tk_Window) winPtr);
  267.         return (Tk_Window) NULL;
  268.     }
  269.     }
  270.     TkWmNewWindow(winPtr);
  271.     return (Tk_Window) winPtr;
  272. }
  273.  
  274. TkDisplay * MakeTkDisplay(display, NameLength, screenName)
  275.      Display *display;
  276.      int NameLength;
  277.      char* screenName;
  278. {
  279.   register TkDisplay *dispPtr = (TkDisplay *) ckalloc(sizeof(TkDisplay));
  280.   register long i;
  281.  
  282.   dispPtr->display = display;
  283.   dispPtr->nextPtr = tkDisplayList;
  284.   dispPtr->name = (char *) ckalloc((unsigned) (NameLength+1));
  285.   dispPtr->lastEventTime = CurrentTime;
  286.   strncpy(dispPtr->name, screenName, NameLength);
  287.   dispPtr->focusTopLevelPtr = NULL;
  288.   dispPtr->focussedOnEnter = 0;
  289.   dispPtr->name[NameLength] = '\0';
  290.   dispPtr->bindInfoStale = 1;
  291.   dispPtr->errorPtr = NULL;
  292.   dispPtr->deleteCount = 0;
  293.   dispPtr->commWindow = NULL;
  294.   dispPtr->selectionOwner = NULL;
  295.   dispPtr->selectionSerial = 0;
  296.   dispPtr->multipleAtom = None;
  297.   dispPtr->atomInit = 0;
  298.   dispPtr->cursorFont = None;
  299.   dispPtr->grabWinPtr = NULL;
  300.   dispPtr->eventualGrabWinPtr = NULL;
  301.   dispPtr->buttonWinPtr = NULL;
  302.   dispPtr->serverWinPtr = NULL;
  303.   dispPtr->firstGrabEventPtr = NULL;
  304.   dispPtr->lastGrabEventPtr = NULL;
  305.   dispPtr->grabFlags = 0;
  306.   dispPtr->colorModels =
  307.     (Tk_ColorModel *) ckalloc((unsigned)
  308.                   (ScreenCount(display)*
  309.                    sizeof(Tk_ColorModel)));
  310.   for (i = ScreenCount(display)-1; i >= 0; i--) {
  311.     if (DisplayPlanes(display, i) <= 4) {
  312.       dispPtr->colorModels[i] = TK_MONO;
  313.     } else {
  314.       dispPtr->colorModels[i] = TK_COLOR;
  315.     }
  316.   }
  317.   tkDisplayList = dispPtr;
  318.   Tk_CreateFileHandler(ConnectionNumber(display),
  319.                TK_READABLE, (void (*)()) NULL,
  320.                (ClientData) display);
  321.   return dispPtr;
  322. }
  323.  
  324. /*
  325.  *----------------------------------------------------------------------
  326.  *
  327.  * GetScreenByName --
  328.  *
  329.  *    Given a string name for a display-plus-screen, find the
  330.  *    TkDisplay structure for the display and return the screen
  331.  *    number too.
  332.  *
  333.  * Results:
  334.  *    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
  336.  *    error message is left in interp->result.  The location at
  337.  *    *screenPtr is overwritten with the screen number parsed from
  338.  *    screenName.
  339.  *
  340.  * Side effects:
  341.  *    A new connection is opened to the display if there is no
  342.  *    connection already.  A new TkDisplay data structure is also
  343.  *    setup, if necessary.
  344.  *
  345.  *----------------------------------------------------------------------
  346.  */
  347.  
  348. static TkDisplay *
  349. GetScreenByName(interp, screenName, screenPtr)
  350.     Tcl_Interp *interp;        /* Place to leave error message. */
  351.     char *screenName;        /* Name for screen.  NULL or empty means
  352.                  * use DISPLAY envariable. */
  353.     int *screenPtr;        /* Where to store screen number. */
  354. {
  355.     register TkDisplay *dispPtr;
  356.     char *p;
  357.     int length, screenId, i;
  358.  
  359.     /*
  360.      * Separate the screen number from the rest of the display
  361.      * name.  ScreenName is assumed to have the syntax
  362.      * <display>.<screen> with the dot and the screen being
  363.      * optional.
  364.      */
  365.  
  366.     if ((screenName == NULL) || (screenName[0] == '\0')) {
  367.     screenName = getenv("DISPLAY");
  368.     if (screenName == NULL) {
  369.         interp->result =
  370.             "no display name and no $DISPLAY environment variable";
  371.         return (TkDisplay *) NULL;
  372.     }
  373.     }
  374.     length = strlen(screenName);
  375.     screenId = 0;
  376.     p = screenName+length-1;
  377.     while (isdigit(*p) && (p != screenName)) {
  378.     p--;
  379.     }
  380.     if ((*p == '.') && (p[1] != '\0')) {
  381.     length = p - screenName;
  382.     screenId = strtoul(p+1, (char **) NULL, 10);
  383.     }
  384.  
  385.     /*
  386.      * See if we already have a connection to this display.  If not,
  387.      * then open a new connection.
  388.      */
  389.  
  390.     for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr)
  391.     { if (dispPtr == NULL)
  392.       { Display *display;
  393.     /* block and unblock added by Hal  -- 7/22/95 in an attempt to fix a problem
  394.            with making this work over PPP (i.e. slow) connections */
  395.         block_signals ();
  396.     display = XOpenDisplay(screenName);
  397.         unblock_signals ();
  398.     if (display == NULL)
  399.     { Tcl_AppendResult(interp, "couldn't connect to display \"",
  400.                screenName, "\"", (char *) NULL);
  401.       return (TkDisplay *) NULL;
  402.     }
  403.     dispPtr = MakeTkDisplay(display, length, screenName);
  404.     break;
  405.       }
  406.       if ((strncmp(dispPtr->name, screenName, length) == 0)
  407.       && (dispPtr->name[length] == '\0'))
  408.       {
  409.     break;
  410.       }
  411.     }
  412.     if (screenId >= ScreenCount(dispPtr->display)) {
  413.     sprintf(interp->result, "bad screen number \"%d\"", screenId);
  414.     return (TkDisplay *) NULL;
  415.     }
  416.     *screenPtr = screenId;
  417.     return dispPtr;
  418. }
  419.  
  420. static TkDisplay *GetScreenByDisplay(interp, disp, screenPtr)
  421.      Tcl_Interp *interp;
  422.      char *disp;
  423.      int *screenPtr;
  424. /* GetScreenByDisplay assumes screen 0! */
  425. { Display *Disp = (Display *) disp;
  426.   register TkDisplay *dispPtr;
  427.  
  428.   for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr)
  429.   { if (dispPtr == NULL)
  430.     { dispPtr = MakeTkDisplay(Disp, 0, "");
  431.       break;
  432.     }
  433.     if (Disp==(dispPtr->display)) break;
  434.   }
  435.   *screenPtr = 0;
  436.   return dispPtr;
  437. }
  438.  
  439. void Tk_DestroyDisplayByNumber(Disp)
  440.      Display *Disp;
  441. /* Tk_DestroyDisplayByNumber assumes screen 0! */
  442. { register TkDisplay *dispPtr, *Prev=(TkDisplay *) NULL;
  443.  
  444.   for (dispPtr = tkDisplayList; dispPtr != NULL;
  445.        Prev=dispPtr, dispPtr = dispPtr->nextPtr)
  446.   { if (Disp==(dispPtr->display))
  447.     { if (Prev==(TkDisplay *) NULL)
  448.     tkDisplayList = dispPtr->nextPtr;
  449.       else Prev->nextPtr = dispPtr->nextPtr;
  450.       ckfree(dispPtr->name);
  451.       ckfree(dispPtr->colorModels);
  452.       ckfree(dispPtr);
  453.       Tk_DeleteFileHandler(ConnectionNumber(Disp));
  454.       return;
  455.     }
  456.   }
  457.   return;
  458. }
  459.  
  460. /*
  461.  *--------------------------------------------------------------
  462.  *
  463.  * NewWindow --
  464.  *
  465.  *    This procedure creates and initializes a TkWindow structure.
  466.  *
  467.  * Results:
  468.  *    The return value is a pointer to the new window.
  469.  *
  470.  * Side effects:
  471.  *    A new window structure is allocated and all its fields are
  472.  *    initialized.
  473.  *
  474.  *--------------------------------------------------------------
  475.  */
  476.  
  477. static TkWindow *
  478. NewWindow(dispPtr, screenNum, parentPtr)
  479.     TkDisplay *dispPtr;        /* Display associated with new window. */
  480.     int screenNum;        /* Index of screen for new window. */
  481.     TkWindow *parentPtr;    /* Parent from which this window should
  482.                  * inherit visual inforamtion.  NULL means
  483.                  * use screen defaults instead of
  484.                  * inheriting. */
  485. {
  486.     register TkWindow *winPtr;
  487.  
  488.     winPtr = (TkWindow *) ckalloc(sizeof(TkWindow));
  489.     winPtr->display = dispPtr->display;
  490.     winPtr->dispPtr = dispPtr;
  491.     winPtr->screenNum = screenNum;
  492.     if (parentPtr != NULL) {
  493.     winPtr->visual = parentPtr->visual;
  494.     winPtr->depth = parentPtr->depth;
  495.     } else {
  496.     winPtr->visual = DefaultVisual(dispPtr->display, screenNum);
  497.     winPtr->depth = DefaultDepth(dispPtr->display, screenNum);
  498.     }
  499.     winPtr->window = None;
  500.     winPtr->childList = NULL;
  501.     winPtr->parentPtr = NULL;
  502.     winPtr->nextPtr = NULL;
  503.     winPtr->mainPtr = NULL;
  504.     winPtr->pathName = NULL;
  505.     winPtr->nameUid = NULL;
  506.     winPtr->classUid = NULL;
  507.     winPtr->changes = defChanges;
  508.     winPtr->dirtyChanges = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;
  509.     winPtr->atts = defAtts;
  510.     if (parentPtr != NULL) {
  511.     winPtr->atts.colormap = parentPtr->atts.colormap;
  512.     } else {
  513.     winPtr->atts.colormap = DefaultColormap(dispPtr->display, screenNum);
  514.     }
  515.     winPtr->dirtyAtts = CWEventMask|CWColormap;
  516.     winPtr->flags = 0;
  517.     winPtr->handlerList = NULL;
  518.     winPtr->focusProc = NULL;
  519.     winPtr->focusData = NULL;
  520.     winPtr->optionLevel = -1;
  521.     winPtr->selHandlerList = NULL;
  522.     winPtr->selClearProc = NULL;
  523.     winPtr->selClearData = NULL;
  524.     winPtr->geomProc = NULL;
  525.     winPtr->geomData = NULL;
  526.     winPtr->reqWidth = winPtr->reqHeight = 0;
  527.     winPtr->internalBorderWidth = 0;
  528.     winPtr->wmInfoPtr = NULL;
  529.  
  530.     return winPtr;
  531. }
  532.  
  533. /*
  534.  *----------------------------------------------------------------------
  535.  *
  536.  * NameWindow --
  537.  *
  538.  *    This procedure is invoked to give a window a name and insert
  539.  *    the window into the hierarchy associated with a particular
  540.  *    application.
  541.  *
  542.  * Results:
  543.  *    A standard Tcl return value.
  544.  *
  545.  * Side effects:
  546.  *      See above.
  547.  *
  548.  *----------------------------------------------------------------------
  549.  */
  550.  
  551. int
  552. NameWindow(interp, winPtr, parentPtr, name)
  553.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  554.     register TkWindow *winPtr;    /* Window that is to be named and inserted. */
  555.     TkWindow *parentPtr;    /* Pointer to logical parent for winPtr
  556.                  * (used for naming, options, etc.). */
  557.     char *name;            /* Name for winPtr;   must be unique among
  558.                  * parentPtr's children. */
  559. {
  560. #define FIXED_SIZE 200
  561.     char staticSpace[FIXED_SIZE];
  562.     char *pathName;
  563.     int new;
  564.     Tcl_HashEntry *hPtr;
  565.     int length1, length2;
  566.  
  567.     /*
  568.      * Setup all the stuff except name right away, then do the name stuff
  569.      * last.  This is so that if the name stuff fails, everything else
  570.      * will be properly initialized (needed to destroy the window cleanly
  571.      * after the naming failure).
  572.      */
  573.     winPtr->parentPtr = parentPtr;
  574.     winPtr->nextPtr = parentPtr->childList;
  575.     parentPtr->childList = winPtr;
  576.     winPtr->mainPtr = parentPtr->mainPtr;
  577.     winPtr->nameUid = Tk_GetUid(name);
  578.  
  579.     /*
  580.      * Don't permit names that start with an upper-case letter:  this
  581.      * will just cause confusion with class names in the option database.
  582.      */
  583.  
  584.     if (isupper(name[0])) {
  585.     Tcl_AppendResult(interp,
  586.         "window name starts with an upper-case letter: \"",
  587.         name, "\"", (char *) NULL);
  588.     return TCL_ERROR;
  589.     }
  590.  
  591.     /*
  592.      * To permit names of arbitrary length, must be prepared to malloc
  593.      * a buffer to hold the new path name.  To run fast in the common
  594.      * case where names are short, use a fixed-size buffer on the
  595.      * stack.
  596.      */
  597.  
  598.     length1 = strlen(parentPtr->pathName);
  599.     length2 = strlen(name);
  600.     if ((length1+length2+2) <= FIXED_SIZE) {
  601.     pathName = staticSpace;
  602.     } else {
  603.     pathName = (char *) ckalloc((unsigned) (length1+length2+2));
  604.     }
  605.     if (length1 == 1) {
  606.     pathName[0] = '.';
  607.     strcpy(pathName+1, name);
  608.     } else {
  609.     strcpy(pathName, parentPtr->pathName);
  610.     pathName[length1] = '.';
  611.     strcpy(pathName+length1+1, name);
  612.     }
  613.     hPtr = Tcl_CreateHashEntry(&parentPtr->mainPtr->nameTable, pathName, &new);
  614.     if (pathName != staticSpace) {
  615.     ckfree(pathName);
  616.     }
  617.     if (!new) {
  618.     Tcl_AppendResult(interp, "window name \"", name,
  619.         "\" already exists in parent", (char *) NULL);
  620.     return TCL_ERROR;
  621.     }
  622.     Tcl_SetHashValue(hPtr, winPtr);
  623.     winPtr->pathName = Tcl_GetHashKey(&parentPtr->mainPtr->nameTable, hPtr);
  624.     return TCL_OK;
  625. }
  626.  
  627. /*
  628.  *----------------------------------------------------------------------
  629.  *
  630.  * Tk_CreateMainWindow --
  631.  *
  632.  *    Make a new main window.  A main window is a special kind of
  633.  *    top-level window used as the outermost window in an
  634.  *    application.
  635.  *
  636.  * Results:
  637.  *    The return value is a token for the new window, or NULL if
  638.  *    an error prevented the new window from being created.  If
  639.  *    NULL is returned, an error message will be left in
  640.  *    interp->result.
  641.  *
  642.  * Side effects:
  643.  *    A new window structure is allocated locally;  "interp" is
  644.  *    associated with the window and registered for "send" commands
  645.  *    under "baseName".  BaseName may be extended with an instance
  646.  *    number in the form "#2" if necessary to make it globally
  647.  *    unique.  Tk-related commands are bound into interp.  An X
  648.  *    window is NOT initially created, but will be created the
  649.  *    first time the window is mapped.
  650.  *
  651.  *----------------------------------------------------------------------
  652.  */
  653.  
  654. Tk_Window
  655. Tk_CreateMainWindow_from_data(interp, baseName, LookupProcedure, data)
  656.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  657.     char *baseName;        /* Base name for application;  usually of the
  658.                  * form "prog instance". */
  659.     TkDisplay *(*LookupProcedure) _ANSI_ARGS_ ((Tcl_Interp *interp, char *data, int *screenPtr));
  660.                 /* Lookup a display structure, either */
  661.                 /* by name or by display connection */
  662.     char *data;            /* Data supplied to LookupProcedure */
  663. {
  664.     Tk_Window tkwin;
  665.     int result, dummy;
  666.     Tcl_HashEntry *hPtr;
  667.     register TkMainInfo *mainPtr;
  668.     register TkWindow *winPtr;
  669.     register TkCmd *cmdPtr;
  670.     char *libDir;
  671.  
  672.     /*
  673.      * Create the basic TkWindow structure.
  674.      */
  675.  
  676.     tkwin = CreateTopLevelWindow(interp, (Tk_Window) NULL, baseName,
  677.                  LookupProcedure, data);
  678.     if (tkwin == NULL) {
  679.     return NULL;
  680.     }
  681.  
  682.     /*
  683.      * Create the TkMainInfo structure for this application, and set
  684.      * up name-related information for the new window.
  685.      */
  686.  
  687.     winPtr = (TkWindow *) tkwin;
  688.     mainPtr = (TkMainInfo *) ckalloc(sizeof(TkMainInfo));
  689.     mainPtr->winPtr = winPtr;
  690.     mainPtr->interp = interp;
  691.     Tcl_InitHashTable(&mainPtr->nameTable, TCL_STRING_KEYS);
  692.     mainPtr->bindingTable = Tk_CreateBindingTable(interp);
  693.     mainPtr->focusPtr = winPtr;
  694.     mainPtr->focusDefaultPtr = NULL;
  695.     mainPtr->optionRootPtr = NULL;
  696.     winPtr->mainPtr = mainPtr;
  697.     hPtr = Tcl_CreateHashEntry(&mainPtr->nameTable, ".", &dummy);
  698.     Tcl_SetHashValue(hPtr, winPtr);
  699.     winPtr->pathName = Tcl_GetHashKey(&mainPtr->nameTable, hPtr);
  700.  
  701.     /*
  702.      * Register the interpreter for "send" purposes.  If baseName isn't
  703.      * already unique, find a unique suffix to add to it to make it
  704.      * unique.  Change the window's name to contain the suffix.
  705.      */
  706.  
  707.     result = Tk_RegisterInterp(interp, baseName, tkwin);
  708.     if (result == TCL_OK) {
  709.     winPtr->nameUid = Tk_GetUid(baseName);
  710.     } else {
  711.     char newName[110];
  712.     int i;
  713.  
  714.     for (i = 2; ; i++) {
  715.         sprintf(newName, "%.100s #%d", baseName, i);
  716.         Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
  717.         result = Tk_RegisterInterp(interp, newName, tkwin);
  718.         if (result == TCL_OK) {
  719.         break;
  720.         }
  721.         if (i >= 100) {
  722.         Tcl_SetResult(interp,
  723.             "couldn't generate unique name to register application",
  724.             TCL_STATIC);
  725.         Tk_DestroyWindow(tkwin);
  726.         }
  727.     }
  728.     winPtr->nameUid = Tk_GetUid(newName);
  729.     }
  730.  
  731.     /*
  732.      * Bind in Tk's commands.
  733.      */
  734.  
  735.     for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
  736.     Tcl_CreateCommand(interp, cmdPtr->name, cmdPtr->cmdProc,
  737.         (ClientData) tkwin, (void (*)()) NULL);
  738.     }
  739.  
  740.     /*
  741.      * Set variables for the intepreter.
  742.      */
  743.  
  744.     libDir = getenv("TK_LIBRARY");
  745.     if (libDir == NULL) {
  746.     libDir = TK_LIBRARY;
  747.     }
  748.     Tcl_SetVar(interp, "tk_library", libDir, TCL_GLOBAL_ONLY);
  749.     Tcl_SetVar(interp, "tk_version", TK_VERSION, TCL_GLOBAL_ONLY);
  750.     Tcl_SetVar(interp, "tkVersion", TK_VERSION, TCL_GLOBAL_ONLY);
  751.  
  752.     tk_NumMainWindows++;
  753.     return tkwin;
  754. }
  755.  
  756. Tk_Window
  757.   Tk_CreateMainWindow(interp, screenName, baseName)
  758.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  759.     char *screenName;        /* Name of screen on which to create
  760.                  * window.  Empty or NULL string means
  761.                  * use DISPLAY environment variable. */
  762.     char *baseName;        /* Base name for application;  usually of the
  763.                  * form "prog instance". */
  764. { return Tk_CreateMainWindow_from_data(interp, baseName,
  765.                        GetScreenByName, screenName);
  766. }
  767.  
  768. Tk_Window
  769. Tk_CreateMainWindow_from_display(interp, display, baseName)
  770.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  771.     Display *display;        /* X Display connection */
  772.     char *baseName;        /* Base name for application;  usually of the
  773.                  * form "prog instance". */
  774. { return Tk_CreateMainWindow_from_data(interp, baseName,
  775.                        GetScreenByDisplay,
  776.                        (char *) display);
  777. }
  778.  
  779. /*
  780.  *--------------------------------------------------------------
  781.  *
  782.  * Tk_CreateWindow --
  783.  *
  784.  *    Create a new internal or top-level window as a child of an
  785.  *    existing window.
  786.  *
  787.  * Results:
  788.  *    The return value is a token for the new window.  This
  789.  *    is not the same as X's token for the window.  If an error
  790.  *    occurred in creating the window (e.g. no such display or
  791.  *    screen), then an error message is left in interp->result and
  792.  *    NULL is returned.
  793.  *
  794.  * Side effects:
  795.  *    A new window structure is allocated locally.  An X
  796.  *    window is not initially created, but will be created
  797.  *    the first time the window is mapped.
  798.  *
  799.  *--------------------------------------------------------------
  800.  */
  801.  
  802. Tk_Window
  803. Tk_CreateWindow(interp, parent, name, screenName)
  804.     Tcl_Interp *interp;        /* Interpreter to use for error reporting.
  805.                  * Interp->result is assumed to be
  806.                  * initialized by the caller. */
  807.     Tk_Window parent;        /* Token for parent of new window. */
  808.     char *name;            /* Name for new window.  Must be unique
  809.                  * among parent's children. */
  810.     char *screenName;        /* If NULL, new window will be internal on
  811.                  * same screen as its parent.  If non-NULL,
  812.                  * gives name of screen on which to create
  813.                  * new window;  window will be a top-level
  814.                  * window. */
  815. {
  816.     TkWindow *parentPtr = (TkWindow *) parent;
  817.     TkWindow *winPtr;
  818.  
  819.     if (screenName == NULL)
  820.     { winPtr = NewWindow(parentPtr->dispPtr, parentPtr->screenNum,
  821.              parentPtr);
  822.       if (NameWindow(interp, winPtr, parentPtr, name) != TCL_OK)
  823.       { Tk_DestroyWindow((Tk_Window) winPtr);
  824.     return NULL;
  825.       }
  826.       else
  827.       { return (Tk_Window) winPtr;
  828.       }
  829.     }
  830.     else
  831.     { return CreateTopLevelWindow(interp, parent, name,
  832.                   GetScreenByName, screenName);
  833.     }
  834. }
  835.  
  836. /*
  837.  *----------------------------------------------------------------------
  838.  *
  839.  * Tk_CreateWindowFromPath --
  840.  *
  841.  *    This procedure is similar to Tk_CreateInternalWindow except
  842.  *    that it uses a path name to create the window, rather than
  843.  *    a parent and a child name.
  844.  *
  845.  * Results:
  846.  *    The return value is a token for the new window.  This
  847.  *    is not the same as X's token for the window.  If an error
  848.  *    occurred in creating the window (e.g. no such display or
  849.  *    screen), then an error message is left in interp->result and
  850.  *    NULL is returned.
  851.  *
  852.  * Side effects:
  853.  *    A new window structure is allocated locally.  An X
  854.  *    window is not initially created, but will be created
  855.  *    the first time the window is mapped.
  856.  *
  857.  *----------------------------------------------------------------------
  858.  */
  859.  
  860. Tk_Window
  861. Tk_CreateWindowFromPath(interp, tkwin, pathName, screenName)
  862.     Tcl_Interp *interp;        /* Interpreter to use for error reporting.
  863.                  * Interp->result is assumed to be
  864.                  * initialized by the caller. */
  865.     Tk_Window tkwin;        /* Token for any window in application
  866.                  * that is to contain new window. */
  867.     char *pathName;        /* Path name for new window within the
  868.                  * application of tkwin.  The parent of
  869.                  * this window must already exist, but
  870.                  * the window itself must not exist. */
  871.     char *screenName;        /* If NULL, new window will be on same
  872.                  * screen as its parent.  If non-NULL,
  873.                  * gives name of screen on which to create
  874.                  * new window;  window will be a top-level
  875.                  * window. */
  876. {
  877. #define FIXED_SPACE 5
  878.     char fixedSpace[FIXED_SPACE+1];
  879.     char *p;
  880.     Tk_Window parent;
  881.     int numChars;
  882.  
  883.     /*
  884.      * Strip the parent's name out of pathName (it's everything up
  885.      * to the last dot).  There are two tricky parts: (a) must
  886.      * copy the parent's name somewhere else to avoid modifying
  887.      * the pathName string (for large names, space for the copy
  888.      * will have to be malloc'ed);  (b) must special-case the
  889.      * situation where the parent is ".".
  890.      */
  891.  
  892.     p = strrchr(pathName, '.');
  893.     if (p == NULL) {
  894.     Tcl_AppendResult(interp, "bad window path name \"", pathName,
  895.         "\"", (char *) NULL);
  896.     return NULL;
  897.     }
  898.     numChars = p-pathName;
  899.     if (numChars > FIXED_SPACE) {
  900.     p = (char *) ckalloc((unsigned) (numChars+1));
  901.     } else {
  902.     p = fixedSpace;
  903.     }
  904.     if (numChars == 0) {
  905.     *p = '.';
  906.     p[1] = '\0';
  907.     } else {
  908.     strncpy(p, pathName, numChars);
  909.     p[numChars] = '\0';
  910.     }
  911.  
  912.     /*
  913.      * Find the parent window.
  914.      */
  915.  
  916.     parent = Tk_NameToWindow(interp, p, tkwin);
  917.     if (p != fixedSpace) {
  918.     ckfree(p);
  919.     }
  920.     if (parent == NULL) {
  921.     return NULL;
  922.     }
  923.  
  924.     /*
  925.      * Create the window.
  926.      */
  927.  
  928.     if (screenName == NULL) {
  929.     TkWindow *parentPtr = (TkWindow *) parent;
  930.     TkWindow *winPtr;
  931.  
  932.     winPtr = NewWindow(parentPtr->dispPtr, parentPtr->screenNum,
  933.                parentPtr);
  934.     if (NameWindow(interp, winPtr, parentPtr, pathName+numChars+1)
  935.         != TCL_OK) {
  936.         Tk_DestroyWindow((Tk_Window) winPtr);
  937.         return NULL;
  938.     } else
  939.     { return (Tk_Window) winPtr;
  940.     }
  941.     } else {
  942.     return CreateTopLevelWindow(interp, parent, pathName+numChars+1,
  943.                     GetScreenByName, screenName);
  944.     }
  945. }
  946.  
  947. /*
  948.  *--------------------------------------------------------------
  949.  *
  950.  * Tk_DestroyWindow --
  951.  *
  952.  *    Destroy an existing window.  After this call, the caller
  953.  *    should never again use the token.
  954.  *
  955.  * Results:
  956.  *    None.
  957.  *
  958.  * Side effects:
  959.  *    The window is deleted, along with all of its children.
  960.  *    Relevant callback procedures are invoked.
  961.  *
  962.  *--------------------------------------------------------------
  963.  */
  964.  
  965. void
  966. Tk_DestroyWindow(tkwin)
  967.     Tk_Window tkwin;        /* Window to destroy. */
  968. {
  969.     register TkWindow *winPtr = (TkWindow *) tkwin;
  970.     XEvent event;
  971.  
  972.     if (winPtr->flags & TK_ALREADY_DEAD) {
  973.     /*
  974.      * An destroy event binding caused the window to be destroyed
  975.      * again.  Ignore the request.
  976.      */
  977.  
  978.     return;
  979.     }
  980.  
  981.     /*
  982.      * Recursively destroy children.  The TK_RECURSIVE_DESTROY
  983.      * flags means that the child's window needn't be explicitly
  984.      * destroyed (the destroy of the parent already did it), nor
  985.      * does it need to be removed from its parent's child list,
  986.      * since the parent is being destroyed too.
  987.      */
  988.  
  989.     while (winPtr->childList != NULL) {
  990.     winPtr->childList->flags |= TK_RECURSIVE_DESTROY;
  991.     Tk_DestroyWindow((Tk_Window) winPtr->childList);
  992.     }
  993.  
  994.     /*
  995.      * Generate a DestroyNotify event.  In order for the DestroyNotify
  996.      * event to be processed correctly, need to make sure the window
  997.      * exists.  This is a bit of a kludge, and may be unnecessarily
  998.      * expensive, but without it no event handlers will get called for
  999.      * windows that don't exist yet.
  1000.      */
  1001.  
  1002.     if (winPtr->window == None) {
  1003.     Tk_MakeWindowExist(tkwin);
  1004.     }
  1005.     winPtr->flags |= TK_ALREADY_DEAD;
  1006.     event.type = DestroyNotify;
  1007.     event.xdestroywindow.serial =
  1008.         LastKnownRequestProcessed(winPtr->display);
  1009.     event.xdestroywindow.send_event = False;
  1010.     event.xdestroywindow.display = winPtr->display;
  1011.     event.xdestroywindow.event = winPtr->window;
  1012.     event.xdestroywindow.window = winPtr->window;
  1013.     Tk_HandleEvent(&event);
  1014.  
  1015.     /*
  1016.      * Cleanup the data structures associated with this window.
  1017.      * No need to destroy windows during recursive destroys, since
  1018.      * that will happen automatically when the parent window is
  1019.      * destroyed (not true for top-level windows:  must destroy
  1020.      * them explicitly).
  1021.      */
  1022.  
  1023.     if (winPtr->window != None) {
  1024.     if (!(winPtr->flags & TK_RECURSIVE_DESTROY)
  1025.         || (winPtr->flags & TK_TOP_LEVEL)) {
  1026.         XDestroyWindow(winPtr->display, winPtr->window);
  1027.     }
  1028.     XDeleteContext(winPtr->display, winPtr->window, tkWindowContext);
  1029.     winPtr->window = None;
  1030.     }
  1031.     if (winPtr->parentPtr != NULL) {
  1032.     if (winPtr->parentPtr->childList == winPtr) {
  1033.         winPtr->parentPtr->childList = winPtr->nextPtr;
  1034.     } else {
  1035.         register TkWindow *winPtr2;
  1036.     
  1037.         for (winPtr2 = winPtr->parentPtr->childList; ;
  1038.             winPtr2 = winPtr2->nextPtr) {
  1039.         if (winPtr2 == NULL) {
  1040.             panic("Tk_DestroyWindow couldn't find child in parent (deleted twice?)");
  1041.             break;
  1042.         }
  1043.         if (winPtr2->nextPtr == winPtr) {
  1044.             winPtr2->nextPtr = winPtr->nextPtr;
  1045.             break;
  1046.         }
  1047.         }
  1048.     }
  1049.     }
  1050.     TkEventDeadWindow(winPtr);
  1051.     TkFocusDeadWindow(winPtr);
  1052.     TkOptionDeadWindow(winPtr);
  1053.     TkSelDeadWindow(winPtr);
  1054.     if (winPtr->flags & TK_TOP_LEVEL) {
  1055.     TkWmDeadWindow(winPtr);
  1056.     }
  1057.     TkGrabDeadWindow(winPtr);
  1058.     if (winPtr->mainPtr != NULL) {
  1059.     Tk_DeleteAllBindings(winPtr->mainPtr->bindingTable,
  1060.         (ClientData) winPtr->pathName);
  1061.     if (winPtr->pathName != NULL) {
  1062.         Tcl_DeleteHashEntry(Tcl_FindHashEntry(&winPtr->mainPtr->nameTable,
  1063.             winPtr->pathName));
  1064.     }
  1065.     if (winPtr->mainPtr->winPtr == winPtr) {
  1066.         register TkCmd *cmdPtr;
  1067.  
  1068.         /*
  1069.          * Deleting a main window.  Delete the TkMainInfo structure too
  1070.          * and replace all of Tk's commands with dummy commands that
  1071.          * return errors.  Also delete the "send" command to unregister
  1072.          * the interpreter.
  1073.          */
  1074.  
  1075.         for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
  1076.         Tcl_CreateCommand(winPtr->mainPtr->interp, cmdPtr->name,
  1077.             TkDeadAppCmd, (ClientData) NULL, (void (*)()) NULL);
  1078.         }
  1079.         Tcl_CreateCommand(winPtr->mainPtr->interp, "send",
  1080.             TkDeadAppCmd, (ClientData) NULL, (void (*)()) NULL);
  1081.         Tcl_DeleteHashTable(&winPtr->mainPtr->nameTable);
  1082.         Tk_DeleteBindingTable(winPtr->mainPtr->bindingTable);
  1083.         ckfree((char *) winPtr->mainPtr);
  1084.         tk_NumMainWindows--;
  1085.     }
  1086.     }
  1087.     ckfree((char *) winPtr);
  1088. }
  1089.  
  1090. /*
  1091.  *--------------------------------------------------------------
  1092.  *
  1093.  * Tk_MapWindow --
  1094.  *
  1095.  *    Map a window within its parent.  This may require the
  1096.  *    window and/or its parents to actually be created.
  1097.  *
  1098.  * Results:
  1099.  *    None.
  1100.  *
  1101.  * Side effects:
  1102.  *    The given window will be mapped.  Windows may also
  1103.  *    be created.
  1104.  *
  1105.  *--------------------------------------------------------------
  1106.  */
  1107.  
  1108. void
  1109. Tk_MapWindow(tkwin)
  1110.     Tk_Window tkwin;        /* Token for window to map. */
  1111. {
  1112.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1113.     XEvent event;
  1114.  
  1115.     if (winPtr->flags & TK_MAPPED) {
  1116.     return;
  1117.     }
  1118.     if (winPtr->window == None) {
  1119.     Tk_MakeWindowExist(tkwin);
  1120.     }
  1121.     if (winPtr->flags & TK_TOP_LEVEL) {
  1122.     /*
  1123.      * Lots of special processing has to be done for top-level
  1124.      * windows.  Let tkWm.c handle everything itself.
  1125.      */
  1126.  
  1127.     TkWmMapWindow(winPtr);
  1128.     return;
  1129.     }
  1130.     winPtr->flags |= TK_MAPPED;
  1131.     XMapWindow(winPtr->display, winPtr->window);
  1132.     event.type = MapNotify;
  1133.     event.xmap.serial = LastKnownRequestProcessed(winPtr->display);
  1134.     event.xmap.send_event = False;
  1135.     event.xmap.display = winPtr->display;
  1136.     event.xmap.event = winPtr->window;
  1137.     event.xmap.window = winPtr->window;
  1138.     event.xmap.override_redirect = winPtr->atts.override_redirect;
  1139.     Tk_HandleEvent(&event);
  1140. }
  1141.  
  1142. /*
  1143.  *--------------------------------------------------------------
  1144.  *
  1145.  * Tk_MakeWindowExist --
  1146.  *
  1147.  *    Ensure that a particular window actually exists.  This
  1148.  *    procedure shouldn't normally need to be invoked from
  1149.  *    outside the Tk package, but may be needed if someone
  1150.  *    wants to manipulate a window before mapping it.
  1151.  *
  1152.  * Results:
  1153.  *    None.
  1154.  *
  1155.  * Side effects:
  1156.  *    When the procedure returns, the X window associated with
  1157.  *    tkwin is guaranteed to exist.  This may require the
  1158.  *    window's ancestors to be created also.
  1159.  *
  1160.  *--------------------------------------------------------------
  1161.  */
  1162.  
  1163. void
  1164. Tk_MakeWindowExist(tkwin)
  1165.     Tk_Window tkwin;        /* Token for window. */
  1166. {
  1167.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1168.     Window parent;
  1169.  
  1170.     if (winPtr->window != None) {
  1171.     return;
  1172.     }
  1173.  
  1174.     if (winPtr->flags & TK_TOP_LEVEL) {
  1175.     parent = XRootWindow(winPtr->display, winPtr->screenNum);
  1176.     } else {
  1177.     if (winPtr->parentPtr->window == None) {
  1178.         Tk_MakeWindowExist((Tk_Window) winPtr->parentPtr);
  1179.     }
  1180.     parent = winPtr->parentPtr->window;
  1181.     }
  1182.  
  1183.     winPtr->window = XCreateWindow(winPtr->display, parent,
  1184.         winPtr->changes.x, winPtr->changes.y,
  1185.         winPtr->changes.width, winPtr->changes.height,
  1186.         winPtr->changes.border_width, winPtr->depth,
  1187.         InputOutput, winPtr->visual, winPtr->dirtyAtts,
  1188.         &winPtr->atts);
  1189.     XSaveContext(winPtr->display, winPtr->window, tkWindowContext,
  1190.         (caddr_t) winPtr);
  1191.     winPtr->dirtyAtts = 0;
  1192.     winPtr->dirtyChanges &= ~(CWX|CWY|CWWidth|CWHeight|CWBorderWidth);
  1193.     if (winPtr->dirtyChanges != 0) {
  1194.     XConfigureWindow(winPtr->display, winPtr->window,
  1195.         winPtr->dirtyChanges, &winPtr->changes);
  1196.     winPtr->dirtyChanges = 0;
  1197.     }
  1198.  
  1199.     /*
  1200.      * Issue a ConfigureNotify event if there were deferred configuration
  1201.      * changes.
  1202.      */
  1203.  
  1204.     if (winPtr->flags & TK_NEED_CONFIG_NOTIFY) {
  1205.     winPtr->flags &= ~TK_NEED_CONFIG_NOTIFY;
  1206.     DoConfigureNotify(winPtr);
  1207.     }
  1208. }
  1209.  
  1210. /*
  1211.  *--------------------------------------------------------------
  1212.  *
  1213.  * Tk_UnmapWindow, etc. --
  1214.  *
  1215.  *    There are several procedures under here, each of which
  1216.  *    mirrors an existing X procedure.  In addition to performing
  1217.  *    the functions of the corresponding procedure, each
  1218.  *    procedure also updates the local window structure and
  1219.  *    synthesizes an X event (if the window's structure is being
  1220.  *    managed internally).
  1221.  *
  1222.  * Results:
  1223.  *    See the manual entries.
  1224.  *
  1225.  * Side effects:
  1226.  *    See the manual entries.
  1227.  *
  1228.  *--------------------------------------------------------------
  1229.  */
  1230.  
  1231. void
  1232. Tk_UnmapWindow(tkwin)
  1233.     Tk_Window tkwin;        /* Token for window to unmap. */
  1234. {
  1235.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1236.  
  1237.     if (!(winPtr->flags & TK_MAPPED)) {
  1238.     return;
  1239.     }
  1240.     winPtr->flags &= ~TK_MAPPED;
  1241.     XUnmapWindow(winPtr->display, winPtr->window);
  1242.     if (!(winPtr->flags & TK_TOP_LEVEL)) {
  1243.     XEvent event;
  1244.  
  1245.     event.type = UnmapNotify;
  1246.     event.xunmap.serial = LastKnownRequestProcessed(winPtr->display);
  1247.     event.xunmap.send_event = False;
  1248.     event.xunmap.display = winPtr->display;
  1249.     event.xunmap.event = winPtr->window;
  1250.     event.xunmap.window = winPtr->window;
  1251.     event.xunmap.from_configure = False;
  1252.     Tk_HandleEvent(&event);
  1253.     }
  1254. }
  1255.  
  1256. void
  1257. Tk_ConfigureWindow(tkwin, valueMask, valuePtr)
  1258.     Tk_Window tkwin;        /* Window to re-configure. */
  1259.     unsigned int valueMask;    /* Mask indicating which parts of
  1260.                  * *valuePtr are to be used. */
  1261.     XWindowChanges *valuePtr;    /* New values. */
  1262. {
  1263.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1264.  
  1265.     if (valueMask & CWX) {
  1266.     winPtr->changes.x = valuePtr->x;
  1267.     }
  1268.     if (valueMask & CWY) {
  1269.     winPtr->changes.y = valuePtr->y;
  1270.     }
  1271.     if (valueMask & CWWidth) {
  1272.     winPtr->changes.width = valuePtr->width;
  1273.     }
  1274.     if (valueMask & CWHeight) {
  1275.     winPtr->changes.height = valuePtr->height;
  1276.     }
  1277.     if (valueMask & CWBorderWidth) {
  1278.     winPtr->changes.border_width = valuePtr->border_width;
  1279.     }
  1280.     if (valueMask & CWSibling) {
  1281.     winPtr->changes.sibling = valuePtr->sibling;
  1282.     }
  1283.     if (valueMask & CWStackMode) {
  1284.     winPtr->changes.stack_mode = valuePtr->stack_mode;
  1285.     }
  1286.  
  1287.     if (winPtr->window != None) {
  1288.     XConfigureWindow(winPtr->display, winPtr->window,
  1289.         valueMask, valuePtr);
  1290.     if (!(winPtr->flags & TK_TOP_LEVEL)) {
  1291.         DoConfigureNotify(winPtr);
  1292.     }
  1293.     } else {
  1294.     winPtr->dirtyChanges |= valueMask;
  1295.     winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
  1296.     }
  1297. }
  1298.  
  1299. void
  1300. Tk_MoveWindow(tkwin, x, y)
  1301.     Tk_Window tkwin;        /* Window to move. */
  1302.     int x, y;            /* New location for window (within
  1303.                  * parent). */
  1304. {
  1305.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1306.  
  1307.     winPtr->changes.x = x;
  1308.     winPtr->changes.y = y;
  1309.     if (winPtr->window != None) {
  1310.     XMoveWindow(winPtr->display, winPtr->window, x, y);
  1311.     if (!(winPtr->flags & TK_TOP_LEVEL)) {
  1312.         DoConfigureNotify(winPtr);
  1313.     }
  1314.     } else {
  1315.     winPtr->dirtyChanges |= CWX|CWY;
  1316.     winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
  1317.     }
  1318. }
  1319.  
  1320. void
  1321. Tk_ResizeWindow(tkwin, width, height)
  1322.     Tk_Window tkwin;        /* Window to resize. */
  1323.     unsigned int width, height;    /* New dimensions for window. */
  1324. {
  1325.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1326.  
  1327.     winPtr->changes.width = width;
  1328.     winPtr->changes.height = height;
  1329.     if (winPtr->window != None) {
  1330.     XResizeWindow(winPtr->display, winPtr->window, width, height);
  1331.     if (!(winPtr->flags & TK_TOP_LEVEL)) {
  1332.         DoConfigureNotify(winPtr);
  1333.     }
  1334.     } else {
  1335.     winPtr->dirtyChanges |= CWWidth|CWHeight;
  1336.     winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
  1337.     }
  1338. }
  1339.  
  1340. void
  1341. Tk_MoveResizeWindow(tkwin, x, y, width, height)
  1342.     Tk_Window tkwin;        /* Window to move and resize. */
  1343.     int x, y;            /* New location for window (within
  1344.                  * parent). */
  1345.     unsigned int width, height;    /* New dimensions for window. */
  1346. {
  1347.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1348.  
  1349.     winPtr->changes.x = x;
  1350.     winPtr->changes.y = y;
  1351.     winPtr->changes.width = width;
  1352.     winPtr->changes.height = height;
  1353.     if (winPtr->window != None) {
  1354.     XMoveResizeWindow(winPtr->display, winPtr->window,
  1355.         x, y, width, height);
  1356.     if (!(winPtr->flags & TK_TOP_LEVEL)) {
  1357.         DoConfigureNotify(winPtr);
  1358.     }
  1359.     } else {
  1360.     winPtr->dirtyChanges |= CWX|CWY|CWWidth|CWHeight;
  1361.     winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
  1362.     }
  1363. }
  1364.  
  1365. void
  1366. Tk_SetWindowBorderWidth(tkwin, width)
  1367.     Tk_Window tkwin;        /* Window to modify. */
  1368.     int width;            /* New border width for window. */
  1369. {
  1370.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1371.  
  1372.     winPtr->changes.border_width = width;
  1373.     if (winPtr->window != None) {
  1374.     XSetWindowBorderWidth(winPtr->display, winPtr->window, width);
  1375.     if (!(winPtr->flags & TK_TOP_LEVEL)) {
  1376.         DoConfigureNotify(winPtr);
  1377.     }
  1378.     } else {
  1379.     winPtr->dirtyChanges |= CWBorderWidth;
  1380.     winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
  1381.     }
  1382. }
  1383.  
  1384. void
  1385. Tk_ChangeWindowAttributes(tkwin, valueMask, attsPtr)
  1386.     Tk_Window tkwin;        /* Window to manipulate. */
  1387.     unsigned long valueMask;    /* OR'ed combination of bits,
  1388.                  * indicating which fields of
  1389.                  * *attsPtr are to be used. */
  1390.     register XSetWindowAttributes *attsPtr;
  1391.                 /* New values for some attributes. */
  1392. {
  1393.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1394.  
  1395.     if (valueMask & CWBackPixmap) {
  1396.     winPtr->atts.background_pixmap = attsPtr->background_pixmap;
  1397.     }
  1398.     if (valueMask & CWBackPixel) {
  1399.     winPtr->atts.background_pixel = attsPtr->background_pixel;
  1400.     }
  1401.     if (valueMask & CWBorderPixmap) {
  1402.     winPtr->atts.border_pixmap = attsPtr->border_pixmap;
  1403.     }
  1404.     if (valueMask & CWBorderPixel) {
  1405.     winPtr->atts.border_pixel = attsPtr->border_pixel;
  1406.     }
  1407.     if (valueMask & CWBitGravity) {
  1408.     winPtr->atts.bit_gravity = attsPtr->bit_gravity;
  1409.     }
  1410.     if (valueMask & CWWinGravity) {
  1411.     winPtr->atts.win_gravity = attsPtr->win_gravity;
  1412.     }
  1413.     if (valueMask & CWBackingStore) {
  1414.     winPtr->atts.backing_store = attsPtr->backing_store;
  1415.     }
  1416.     if (valueMask & CWBackingPlanes) {
  1417.     winPtr->atts.backing_planes = attsPtr->backing_planes;
  1418.     }
  1419.     if (valueMask & CWBackingPixel) {
  1420.     winPtr->atts.backing_pixel = attsPtr->backing_pixel;
  1421.     }
  1422.     if (valueMask & CWOverrideRedirect) {
  1423.     winPtr->atts.override_redirect = attsPtr->override_redirect;
  1424.     }
  1425.     if (valueMask & CWSaveUnder) {
  1426.     winPtr->atts.save_under = attsPtr->save_under;
  1427.     }
  1428.     if (valueMask & CWEventMask) {
  1429.     winPtr->atts.event_mask = attsPtr->event_mask;
  1430.     }
  1431.     if (valueMask & CWDontPropagate) {
  1432.     winPtr->atts.do_not_propagate_mask
  1433.         = attsPtr->do_not_propagate_mask;
  1434.     }
  1435.     if (valueMask & CWColormap) {
  1436.     winPtr->atts.colormap = attsPtr->colormap;
  1437.     }
  1438.     if (valueMask & CWCursor) {
  1439.     winPtr->atts.cursor = attsPtr->cursor;
  1440.     }
  1441.  
  1442.     if (winPtr->window != None) {
  1443.     XChangeWindowAttributes(winPtr->display, winPtr->window,
  1444.         valueMask, attsPtr);
  1445.     } else {
  1446.     winPtr->dirtyAtts |= valueMask;
  1447.     }
  1448. }
  1449.  
  1450. void
  1451. Tk_SetWindowBackground(tkwin, pixel)
  1452.     Tk_Window tkwin;        /* Window to manipulate. */
  1453.     unsigned long pixel;    /* Pixel value to use for
  1454.                  * window's background. */
  1455. {
  1456.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1457.  
  1458.     winPtr->atts.background_pixel = pixel;
  1459.  
  1460.     if (winPtr->window != None) {
  1461.     XSetWindowBackground(winPtr->display, winPtr->window, pixel);
  1462.     } else {
  1463.     winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBackPixmap)
  1464.         | CWBackPixel;
  1465.     }
  1466. }
  1467.  
  1468. void
  1469. Tk_SetWindowBackgroundPixmap(tkwin, pixmap)
  1470.     Tk_Window tkwin;        /* Window to manipulate. */
  1471.     Pixmap pixmap;        /* Pixmap to use for window's
  1472.                  * background. */
  1473. {
  1474.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1475.  
  1476.     winPtr->atts.background_pixmap = pixmap;
  1477.  
  1478.     if (winPtr->window != None) {
  1479.     XSetWindowBackgroundPixmap(winPtr->display,
  1480.         winPtr->window, pixmap);
  1481.     } else {
  1482.     winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBackPixel)
  1483.         | CWBackPixmap;
  1484.     }
  1485. }
  1486.  
  1487. void
  1488. Tk_SetWindowBorder(tkwin, pixel)
  1489.     Tk_Window tkwin;        /* Window to manipulate. */
  1490.     unsigned long pixel;    /* Pixel value to use for
  1491.                  * window's border. */
  1492. {
  1493.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1494.  
  1495.     winPtr->atts.border_pixel = pixel;
  1496.  
  1497.     if (winPtr->window != None) {
  1498.     XSetWindowBorder(winPtr->display, winPtr->window, pixel);
  1499.     } else {
  1500.     winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBorderPixmap)
  1501.         | CWBorderPixel;
  1502.     }
  1503. }
  1504.  
  1505. void
  1506. Tk_SetWindowBorderPixmap(tkwin, pixmap)
  1507.     Tk_Window tkwin;        /* Window to manipulate. */
  1508.     Pixmap pixmap;        /* Pixmap to use for window's
  1509.                  * border. */
  1510. {
  1511.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1512.  
  1513.     winPtr->atts.border_pixmap = pixmap;
  1514.  
  1515.     if (winPtr->window != None) {
  1516.     XSetWindowBorderPixmap(winPtr->display,
  1517.         winPtr->window, pixmap);
  1518.     } else {
  1519.     winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBorderPixel)
  1520.         | CWBorderPixmap;
  1521.     }
  1522. }
  1523.  
  1524. void
  1525. Tk_DefineCursor(tkwin, cursor)
  1526.     Tk_Window tkwin;        /* Window to manipulate. */
  1527.     Cursor cursor;        /* Cursor to use for window (may be None). */
  1528. {
  1529.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1530.  
  1531.     winPtr->atts.cursor = cursor;
  1532.  
  1533.     if (winPtr->window != None) {
  1534.     XDefineCursor(winPtr->display, winPtr->window, cursor);
  1535.     } else {
  1536.     winPtr->dirtyAtts = winPtr->dirtyAtts | CWCursor;
  1537.     }
  1538. }
  1539.  
  1540. void
  1541. Tk_UndefineCursor(tkwin)
  1542.     Tk_Window tkwin;        /* Window to manipulate. */
  1543. {
  1544.     Tk_DefineCursor(tkwin, None);
  1545. }
  1546.  
  1547. void
  1548. Tk_SetWindowColormap(tkwin, colormap)
  1549.     Tk_Window tkwin;        /* Window to manipulate. */
  1550.     Colormap colormap;        /* Colormap to use for window. */
  1551. {
  1552.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1553.  
  1554.     winPtr->atts.colormap = colormap;
  1555.  
  1556.     if (winPtr->window != None) {
  1557.     XSetWindowColormap(winPtr->display, winPtr->window, colormap);
  1558.     } else {
  1559.     winPtr->dirtyAtts |= CWColormap;
  1560.     }
  1561. }
  1562.  
  1563. /*
  1564.  *----------------------------------------------------------------------
  1565.  *
  1566.  * Tk_SetWindowVisual --
  1567.  *
  1568.  *    This procedure is called to specify a visual to be used
  1569.  *    for a Tk window when it is created.  This procedure, if
  1570.  *    called at all, must be called before the X window is created
  1571.  *    (i.e. before Tk_MakeWindowExist is called).
  1572.  *
  1573.  * Results:
  1574.  *    The return value is 1 if successful, or 0 if the X window has
  1575.  *    been already created.
  1576.  *
  1577.  * Side effects:
  1578.  *    The information given is stored for when the window is created.
  1579.  *
  1580.  *----------------------------------------------------------------------
  1581.  */
  1582.  
  1583. int
  1584. Tk_SetWindowVisual(tkwin, visual, depth, colormap)
  1585.     Tk_Window tkwin;        /* Window to manipulate. */
  1586.     Visual *visual;        /* New visual for window. */
  1587.     unsigned int depth;        /* New depth for window. */
  1588.     Colormap colormap;        /* An appropriate colormap for the visual. */
  1589. {
  1590.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1591.  
  1592.     if( winPtr->window != None ){
  1593.     /* Too late! */
  1594.     return 0;
  1595.     }
  1596.  
  1597.     winPtr->visual = visual;
  1598.     winPtr->depth = depth;
  1599.     winPtr->atts.colormap = colormap;
  1600.  
  1601.     /*
  1602.      * The following code is needed to make sure that the window doesn't
  1603.      * inherit the parent's border pixmap, which would result in a BadMatch
  1604.      * error.
  1605.      */
  1606.  
  1607.     if (!(winPtr->dirtyAtts & CWBorderPixmap)) {
  1608.     winPtr->dirtyAtts |= CWBorderPixel;
  1609.     }
  1610.     return 1;
  1611. }
  1612.  
  1613. /*
  1614.  *----------------------------------------------------------------------
  1615.  *
  1616.  * DoConfigureNotify --
  1617.  *
  1618.  *    Generate a ConfigureNotify event describing the current
  1619.  *    configuration of a window.
  1620.  *
  1621.  * Results:
  1622.  *    None.
  1623.  *
  1624.  * Side effects:
  1625.  *    An event is generated and processed by Tk_HandleEvent.
  1626.  *
  1627.  *----------------------------------------------------------------------
  1628.  */
  1629.  
  1630. static void
  1631. DoConfigureNotify(winPtr)
  1632.     register TkWindow *winPtr;        /* Window whose configuration
  1633.                      * was just changed. */
  1634. {
  1635.     XEvent event;
  1636.  
  1637.     event.type = ConfigureNotify;
  1638.     event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display);
  1639.     event.xconfigure.send_event = False;
  1640.     event.xconfigure.display = winPtr->display;
  1641.     event.xconfigure.event = winPtr->window;
  1642.     event.xconfigure.window = winPtr->window;
  1643.     event.xconfigure.x = winPtr->changes.x;
  1644.     event.xconfigure.y = winPtr->changes.y;
  1645.     event.xconfigure.width = winPtr->changes.width;
  1646.     event.xconfigure.height = winPtr->changes.height;
  1647.     event.xconfigure.border_width = winPtr->changes.border_width;
  1648.     if (winPtr->changes.stack_mode == Above) {
  1649.     event.xconfigure.above = winPtr->changes.sibling;
  1650.     } else {
  1651.     event.xconfigure.above = None;
  1652.     }
  1653.     event.xconfigure.override_redirect = winPtr->atts.override_redirect;
  1654.     Tk_HandleEvent(&event);
  1655. }
  1656.  
  1657. /*
  1658.  *----------------------------------------------------------------------
  1659.  *
  1660.  * Tk_SetClass --
  1661.  *
  1662.  *    This procedure is used to give a window a class.
  1663.  *
  1664.  * Results:
  1665.  *    None.
  1666.  *
  1667.  * Side effects:
  1668.  *    A new class is stored for tkwin, replacing any existing
  1669.  *    class for it.
  1670.  *
  1671.  *----------------------------------------------------------------------
  1672.  */
  1673.  
  1674. void
  1675. Tk_SetClass(tkwin, className)
  1676.     Tk_Window tkwin;        /* Token for window to assign class. */
  1677.     char *className;        /* New class for tkwin. */
  1678. {
  1679.     register TkWindow *winPtr = (TkWindow *) tkwin;
  1680.  
  1681.     winPtr->classUid = Tk_GetUid(className);
  1682.     if (winPtr->flags & TK_TOP_LEVEL) {
  1683.     TkWmSetClass(winPtr);
  1684.     }
  1685. }
  1686.  
  1687. /*
  1688.  *----------------------------------------------------------------------
  1689.  *
  1690.  * Tk_NameToWindow --
  1691.  *
  1692.  *    Given a string name for a window, this procedure
  1693.  *    returns the token for the window, if there exists a
  1694.  *    window corresponding to the given name.
  1695.  *
  1696.  * Results:
  1697.  *    The return result is either a token for the window corresponding
  1698.  *    to "name", or else NULL to indicate that there is no such
  1699.  *    window.  In this case, an error message is left in interp->result.
  1700.  *
  1701.  * Side effects:
  1702.  *    None.
  1703.  *
  1704.  *----------------------------------------------------------------------
  1705.  */
  1706.  
  1707. Tk_Window
  1708. Tk_NameToWindow(interp, pathName, tkwin)
  1709.     Tcl_Interp *interp;        /* Where to report errors. */
  1710.     char *pathName;        /* Path name of window. */
  1711.     Tk_Window tkwin;        /* Token for window:  name is assumed to
  1712.                  * belong to the same main window as tkwin. */
  1713. {
  1714.     Tcl_HashEntry *hPtr;
  1715.  
  1716.     hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->nameTable,
  1717.         pathName);
  1718.     if (hPtr == NULL) {
  1719.     Tcl_AppendResult(interp, "bad window path name \"",
  1720.         pathName, "\"", (char *) NULL);
  1721.     return NULL;
  1722.     }
  1723.     return (Tk_Window) Tcl_GetHashValue(hPtr);
  1724. }
  1725.  
  1726. /*
  1727.  *----------------------------------------------------------------------
  1728.  *
  1729.  * Tk_DisplayName --
  1730.  *
  1731.  *    Return the textual name of a window's display.
  1732.  *
  1733.  * Results:
  1734.  *    The return value is the string name of the display associated
  1735.  *    with tkwin.
  1736.  *
  1737.  * Side effects:
  1738.  *    None.
  1739.  *
  1740.  *----------------------------------------------------------------------
  1741.  */
  1742.  
  1743. char *
  1744. Tk_DisplayName(tkwin)
  1745.     Tk_Window tkwin;        /* Window whose display name is desired. */
  1746. {
  1747.     return ((TkWindow *) tkwin)->dispPtr->name;
  1748. }
  1749.  
  1750. /*
  1751.  *----------------------------------------------------------------------
  1752.  *
  1753.  * Tk_SetColorModel --
  1754.  *
  1755.  *    This procedure changes the current color model for a window
  1756.  *    (actually, for the window's screen).
  1757.  *
  1758.  * Results:
  1759.  *    None.
  1760.  *
  1761.  * Side effects:
  1762.  *    The color model for tkwin's screen is set to "model".
  1763.  *
  1764.  *----------------------------------------------------------------------
  1765.  */
  1766.  
  1767. void
  1768. Tk_SetColorModel(tkwin, model)
  1769.     Tk_Window tkwin;        /* Token for window;  this selects a screen
  1770.                  * whose color model is to be modified. */
  1771.     Tk_ColorModel model;    /* New model for tkwin's screen. */
  1772. {
  1773.     TkWindow *winPtr = (TkWindow *) tkwin;
  1774.     winPtr->dispPtr->colorModels[winPtr->screenNum] = model;
  1775. }
  1776.  
  1777. /*
  1778.  *----------------------------------------------------------------------
  1779.  *
  1780.  * Tk_GetColorModel --
  1781.  *
  1782.  *    This procedure returns the current color model for a window
  1783.  *    (actually, for the window's screen).
  1784.  *
  1785.  * Results:
  1786.  *    A color model.
  1787.  *
  1788.  * Side effects:
  1789.  *    None.
  1790.  *
  1791.  *----------------------------------------------------------------------
  1792.  */
  1793.  
  1794. Tk_ColorModel
  1795. Tk_GetColorModel(tkwin)
  1796.     Tk_Window tkwin;        /* Token for window;  this selects a screen
  1797.                  * whose color model is returned. */
  1798. {
  1799.     TkWindow *winPtr = (TkWindow *) tkwin;
  1800.     return winPtr->dispPtr->colorModels[winPtr->screenNum];
  1801.  
  1802. }
  1803.