tkUnixWm.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:195k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * tkUnixWm.c --
  3.  *
  4.  * This module takes care of the interactions between a Tk-based
  5.  * application and the window manager.  Among other things, it
  6.  * implements the "wm" command and passes geometry information
  7.  * to the window manager.
  8.  *
  9.  * Copyright (c) 1991-1994 The Regents of the University of California.
  10.  * Copyright (c) 1994-1997 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.  * RCS: @(#) $Id: tkUnixWm.c,v 1.36.2.7 2006/04/11 20:23:45 hobbs Exp $
  16.  */
  17. #include "tkPort.h"
  18. #include "tkInt.h"
  19. #include "tkUnixInt.h"
  20. /*
  21.  * A data structure of the following type holds information for
  22.  * each window manager protocol (such as WM_DELETE_WINDOW) for
  23.  * which a handler (i.e. a Tcl command) has been defined for a
  24.  * particular top-level window.
  25.  */
  26. typedef struct ProtocolHandler {
  27.     Atom protocol; /* Identifies the protocol. */
  28.     struct ProtocolHandler *nextPtr;
  29. /* Next in list of protocol handlers for
  30.  * the same top-level window, or NULL for
  31.  * end of list. */
  32.     Tcl_Interp *interp; /* Interpreter in which to invoke command. */
  33.     char command[4]; /* Tcl command to invoke when a client
  34.  * message for this protocol arrives.
  35.  * The actual size of the structure varies
  36.  * to accommodate the needs of the actual
  37.  * command. THIS MUST BE THE LAST FIELD OF
  38.  * THE STRUCTURE. */
  39. } ProtocolHandler;
  40. #define HANDLER_SIZE(cmdLength) 
  41.     ((unsigned) (sizeof(ProtocolHandler) - 3 + cmdLength))
  42. /*
  43.  * A data structure of the following type holds window-manager-related
  44.  * information for each top-level window in an application.
  45.  */
  46. typedef struct TkWmInfo {
  47.     TkWindow *winPtr; /* Pointer to main Tk information for
  48.  * this window. */
  49.     Window reparent; /* If the window has been reparented, this
  50.  * gives the ID of the ancestor of the window
  51.  * that is a child of the root window (may
  52.  * not be window's immediate parent).  If
  53.  * the window isn't reparented, this has the
  54.  * value None. */
  55.     char *title; /* Title to display in window caption.  If
  56.  * NULL, use name of widget.  Malloced. */
  57.     char *iconName; /* Name to display in icon.  Malloced. */
  58.     XWMHints hints; /* Various pieces of information for
  59.  * window manager. */
  60.     char *leaderName; /* Path name of leader of window group
  61.  * (corresponds to hints.window_group).
  62.  * Malloc-ed.  Note:  this field doesn't
  63.  * get updated if leader is destroyed. */
  64.     TkWindow *masterPtr; /* Master window for TRANSIENT_FOR property,
  65.  * or NULL. */
  66.     Tk_Window icon; /* Window to use as icon for this window,
  67.  * or NULL. */
  68.     Tk_Window iconFor; /* Window for which this window is icon, or
  69.  * NULL if this isn't an icon for anyone. */
  70.     int withdrawn; /* Non-zero means window has been withdrawn. */
  71.     /*
  72.      * In order to support menubars transparently under X, each toplevel
  73.      * window is encased in an additional window, called the wrapper,
  74.      * that holds the toplevel and the menubar, if any.  The information
  75.      * below is used to keep track of the wrapper and the menubar.
  76.      */
  77.     TkWindow *wrapperPtr; /* Pointer to information about the wrapper.
  78.  * This is the "real" toplevel window as
  79.  * seen by the window manager. Although
  80.  * this is an official Tk window, it
  81.  * doesn't appear in the application's
  82.  * window hierarchy.  NULL means that
  83.  * the wrapper hasn't been created yet. */
  84.     Tk_Window menubar; /* Pointer to information about the
  85.  * menubar, or NULL if there is no
  86.  * menubar for this toplevel. */
  87.     int menuHeight; /* Amount of vertical space needed for
  88.  * menubar, measured in pixels.  If
  89.  * menubar is non-NULL, this is >= 1 (X
  90.  * servers don't like dimensions of 0). */
  91.     /*
  92.      * Information used to construct an XSizeHints structure for
  93.      * the window manager:
  94.      */
  95.     int sizeHintsFlags; /* Flags word for XSizeHints structure.
  96.  * If the PBaseSize flag is set then the
  97.  * window is gridded;  otherwise it isn't
  98.  * gridded. */
  99.     int minWidth, minHeight; /* Minimum dimensions of window, in
  100.  * pixels or grid units. */
  101.     int maxWidth, maxHeight; /* Maximum dimensions of window, in
  102.  * pixels or grid units. 0 to default.*/
  103.     Tk_Window gridWin; /* Identifies the window that controls
  104.  * gridding for this top-level, or NULL if
  105.  * the top-level isn't currently gridded. */
  106.     int widthInc, heightInc; /* Increments for size changes (# pixels
  107.  * per step). */
  108.     struct {
  109. int x; /* numerator */
  110. int y;  /* denominator */
  111.     } minAspect, maxAspect; /* Min/max aspect ratios for window. */
  112.     int reqGridWidth, reqGridHeight;
  113. /* The dimensions of the window (in
  114.  * grid units) requested through
  115.  * the geometry manager. */
  116.     int gravity; /* Desired window gravity. */
  117.     /*
  118.      * Information used to manage the size and location of a window.
  119.      */
  120.     int width, height; /* Desired dimensions of window, specified
  121.  * in pixels or grid units.  These values are
  122.  * set by the "wm geometry" command and by
  123.  * ConfigureNotify events (for when wm
  124.  * resizes window).  -1 means user hasn't
  125.  * requested dimensions. */
  126.     int x, y; /* Desired X and Y coordinates for window.
  127.  * These values are set by "wm geometry",
  128.  * plus by ConfigureNotify events (when wm
  129.  * moves window).  These numbers are
  130.  * different than the numbers stored in
  131.  * winPtr->changes because (a) they could be
  132.  * measured from the right or bottom edge
  133.  * of the screen (see WM_NEGATIVE_X and
  134.  * WM_NEGATIVE_Y flags) and (b) if the window
  135.  * has been reparented then they refer to the
  136.  * parent rather than the window itself. */
  137.     int parentWidth, parentHeight;
  138. /* Width and height of reparent, in pixels
  139.  * *including border*.  If window hasn't been
  140.  * reparented then these will be the outer
  141.  * dimensions of the window, including
  142.  * border. */
  143.     int xInParent, yInParent; /* Offset of wrapperPtr within reparent,
  144.  * measured in pixels from upper-left outer
  145.  * corner of reparent's border to upper-left
  146.  * outer corner of wrapperPtr's border.  If
  147.  * not reparented then these are zero. */
  148.     int configWidth, configHeight;
  149. /* Dimensions passed to last request that we
  150.  * issued to change geometry of the wrapper.
  151.  * Used to eliminate redundant resize
  152.  * operations. */
  153.     /*
  154.      * Information about the virtual root window for this top-level,
  155.      * if there is one.
  156.      */
  157.     Window vRoot; /* Virtual root window for this top-level,
  158.  * or None if there is no virtual root
  159.  * window (i.e. just use the screen's root). */
  160.     int vRootX, vRootY; /* Position of the virtual root inside the
  161.  * root window.  If the WM_VROOT_OFFSET_STALE
  162.  * flag is set then this information may be
  163.  * incorrect and needs to be refreshed from
  164.  * the X server.  If vRoot is None then these
  165.  * values are both 0. */
  166.     int vRootWidth, vRootHeight;/* Dimensions of the virtual root window.
  167.  * If vRoot is None, gives the dimensions
  168.  * of the containing screen.  This information
  169.  * is never stale, even though vRootX and
  170.  * vRootY can be. */
  171.     /*
  172.      * Miscellaneous information.
  173.      */
  174.     ProtocolHandler *protPtr; /* First in list of protocol handlers for
  175.  * this window (NULL means none). */
  176.     int cmdArgc; /* Number of elements in cmdArgv below. */
  177.     CONST char **cmdArgv; /* Array of strings to store in the
  178.  * WM_COMMAND property.  NULL means nothing
  179.  * available. */
  180.     char *clientMachine; /* String to store in WM_CLIENT_MACHINE
  181.  * property, or NULL. */
  182.     int flags; /* Miscellaneous flags, defined below. */
  183.     int numTransients; /* number of transients on this window */
  184.     int iconDataSize; /* size of iconphoto image data */
  185.     unsigned char *iconDataPtr; /* iconphoto image data, if set */
  186.     struct TkWmInfo *nextPtr; /* Next in list of all top-level windows. */
  187. } WmInfo;
  188. /*
  189.  * Flag values for WmInfo structures:
  190.  *
  191.  * WM_NEVER_MAPPED - non-zero means window has never been
  192.  * mapped;  need to update all info when
  193.  * window is first mapped.
  194.  * WM_UPDATE_PENDING - non-zero means a call to UpdateGeometryInfo
  195.  * has already been scheduled for this
  196.  * window;  no need to schedule another one.
  197.  * WM_NEGATIVE_X - non-zero means x-coordinate is measured in
  198.  * pixels from right edge of screen, rather
  199.  * than from left edge.
  200.  * WM_NEGATIVE_Y - non-zero means y-coordinate is measured in
  201.  * pixels up from bottom of screen, rather than
  202.  * down from top.
  203.  * WM_UPDATE_SIZE_HINTS - non-zero means that new size hints need to be
  204.  * propagated to window manager.
  205.  * WM_SYNC_PENDING - set to non-zero while waiting for the window
  206.  * manager to respond to some state change.
  207.  * WM_VROOT_OFFSET_STALE - non-zero means that (x,y) offset information
  208.  * about the virtual root window is stale and
  209.  * needs to be fetched fresh from the X server.
  210.  * WM_ABOUT_TO_MAP - non-zero means that the window is about to
  211.  * be mapped by TkWmMapWindow.  This is used
  212.  * by UpdateGeometryInfo to modify its behavior.
  213.  * WM_MOVE_PENDING - non-zero means the application has requested
  214.  * a new position for the window, but it hasn't
  215.  * been reflected through the window manager
  216.  * yet.
  217.  * WM_COLORMAPS_EXPLICIT - non-zero means the colormap windows were
  218.  * set explicitly via "wm colormapwindows".
  219.  * WM_ADDED_TOPLEVEL_COLORMAP - non-zero means that when "wm colormapwindows"
  220.  * was called the top-level itself wasn't
  221.  * specified, so we added it implicitly at
  222.  * the end of the list.
  223.  * WM_WIDTH_NOT_RESIZABLE - non-zero means that we're not supposed to
  224.  * allow the user to change the width of the
  225.  * window (controlled by "wm resizable"
  226.  * command).
  227.  * WM_HEIGHT_NOT_RESIZABLE - non-zero means that we're not supposed to
  228.  * allow the user to change the height of the
  229.  * window (controlled by "wm resizable"
  230.  * command).
  231.  * WM_WITHDRAWN - non-zero means that this window has explicitly
  232.  * been withdrawn. If it's a transient, it should
  233.  * not mirror state changes in the master.
  234.  */
  235. #define WM_NEVER_MAPPED 1
  236. #define WM_UPDATE_PENDING 2
  237. #define WM_NEGATIVE_X 4
  238. #define WM_NEGATIVE_Y 8
  239. #define WM_UPDATE_SIZE_HINTS 0x10
  240. #define WM_SYNC_PENDING 0x20
  241. #define WM_VROOT_OFFSET_STALE 0x40
  242. #define WM_ABOUT_TO_MAP 0x100
  243. #define WM_MOVE_PENDING 0x200
  244. #define WM_COLORMAPS_EXPLICIT 0x400
  245. #define WM_ADDED_TOPLEVEL_COLORMAP 0x800
  246. #define WM_WIDTH_NOT_RESIZABLE 0x1000
  247. #define WM_HEIGHT_NOT_RESIZABLE 0x2000
  248. #define WM_WITHDRAWN         0x4000
  249. /*
  250.  * This module keeps a list of all top-level windows, primarily to
  251.  * simplify the job of Tk_CoordsToWindow.  The list is called
  252.  * firstWmPtr and is stored in the TkDisplay structure.
  253.  */
  254. /*
  255.  * The following structures are the official type records for geometry
  256.  * management of top-level and menubar windows.
  257.  */
  258. static void TopLevelReqProc _ANSI_ARGS_((ClientData dummy,
  259.     Tk_Window tkwin));
  260. static Tk_GeomMgr wmMgrType = {
  261.     "wm", /* name */
  262.     TopLevelReqProc, /* requestProc */
  263.     (Tk_GeomLostSlaveProc *) NULL, /* lostSlaveProc */
  264. };
  265. static void MenubarReqProc _ANSI_ARGS_((ClientData clientData,
  266.     Tk_Window tkwin));
  267. static Tk_GeomMgr menubarMgrType = {
  268.     "menubar", /* name */
  269.     MenubarReqProc, /* requestProc */
  270.     (Tk_GeomLostSlaveProc *) NULL, /* lostSlaveProc */
  271. };
  272. /*
  273.  * Structures of the following type are used for communication between
  274.  * WaitForEvent, WaitRestrictProc, and WaitTimeoutProc.
  275.  */
  276. typedef struct WaitRestrictInfo {
  277.     Display *display; /* Window belongs to this display. */
  278.     WmInfo *wmInfoPtr;
  279.     int type; /* We only care about this type of event. */
  280.     XEvent *eventPtr; /* Where to store the event when it's found. */
  281.     int foundEvent; /* Non-zero means that an event of the
  282.  * desired type has been found. */
  283. } WaitRestrictInfo;
  284. /*
  285.  * Forward declarations for procedures defined in this file:
  286.  */
  287. static int ComputeReparentGeometry _ANSI_ARGS_((WmInfo *wmPtr));
  288. static void ConfigureEvent _ANSI_ARGS_((WmInfo *wmPtr,
  289.     XConfigureEvent *eventPtr));
  290. static void CreateWrapper _ANSI_ARGS_((WmInfo *wmPtr));
  291. static void GetMaxSize _ANSI_ARGS_((WmInfo *wmPtr,
  292.     int *maxWidthPtr, int *maxHeightPtr));
  293. static void MenubarDestroyProc _ANSI_ARGS_((ClientData clientData,
  294.     XEvent *eventPtr));
  295. static int ParseGeometry _ANSI_ARGS_((Tcl_Interp *interp,
  296.     char *string, TkWindow *winPtr));
  297. static void ReparentEvent _ANSI_ARGS_((WmInfo *wmPtr,
  298.     XReparentEvent *eventPtr));
  299. static void TkWmStackorderToplevelWrapperMap _ANSI_ARGS_((
  300.     TkWindow *winPtr,
  301.     Display *display,
  302.     Tcl_HashTable *reparentTable));
  303. static void TopLevelReqProc _ANSI_ARGS_((ClientData dummy,
  304.     Tk_Window tkwin));
  305. static void UpdateCommand _ANSI_ARGS_((TkWindow *winPtr));
  306. static void UpdateGeometryInfo _ANSI_ARGS_((
  307.     ClientData clientData));
  308. static void UpdateHints _ANSI_ARGS_((TkWindow *winPtr));
  309. static void UpdateSizeHints _ANSI_ARGS_((TkWindow *winPtr,
  310.     int newWidth, int newHeight));
  311. static void UpdateTitle _ANSI_ARGS_((TkWindow *winPtr));
  312. static void UpdatePhotoIcon _ANSI_ARGS_((TkWindow *winPtr));
  313. static void UpdateVRootGeometry _ANSI_ARGS_((WmInfo *wmPtr));
  314. static void UpdateWmProtocols _ANSI_ARGS_((WmInfo *wmPtr));
  315. static void WaitForConfigureNotify _ANSI_ARGS_((TkWindow *winPtr,
  316.     unsigned long serial));
  317. static int WaitForEvent _ANSI_ARGS_((Display *display,
  318.     WmInfo *wmInfoPtr, int type, XEvent *eventPtr));
  319. static void WaitForMapNotify _ANSI_ARGS_((TkWindow *winPtr,
  320.     int mapped));
  321. static Tk_RestrictAction
  322. WaitRestrictProc _ANSI_ARGS_((ClientData clientData,
  323.     XEvent *eventPtr));
  324. static void WrapperEventProc _ANSI_ARGS_((ClientData clientData,
  325.     XEvent *eventPtr));
  326. static void WmWaitMapProc _ANSI_ARGS_((
  327.     ClientData clientData, XEvent *eventPtr));
  328. static int  WmAspectCmd _ANSI_ARGS_((Tk_Window tkwin,
  329.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  330.     Tcl_Obj *CONST objv[]));
  331. static int  WmAttributesCmd _ANSI_ARGS_((Tk_Window tkwin,
  332.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  333.     Tcl_Obj *CONST objv[]));
  334. static int  WmClientCmd _ANSI_ARGS_((Tk_Window tkwin,
  335.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  336.     Tcl_Obj *CONST objv[]));
  337. static int  WmColormapwindowsCmd _ANSI_ARGS_((Tk_Window tkwin,
  338.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  339.     Tcl_Obj *CONST objv[]));
  340. static int  WmCommandCmd _ANSI_ARGS_((Tk_Window tkwin,
  341.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  342.     Tcl_Obj *CONST objv[]));
  343. static int  WmDeiconifyCmd _ANSI_ARGS_((Tk_Window tkwin,
  344.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  345.     Tcl_Obj *CONST objv[]));
  346. static int  WmFocusmodelCmd _ANSI_ARGS_((Tk_Window tkwin,
  347.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  348.     Tcl_Obj *CONST objv[]));
  349. static int  WmFrameCmd _ANSI_ARGS_((Tk_Window tkwin,
  350.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  351.     Tcl_Obj *CONST objv[]));
  352. static int  WmGeometryCmd _ANSI_ARGS_((Tk_Window tkwin,
  353.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  354.     Tcl_Obj *CONST objv[]));
  355. static int  WmGridCmd _ANSI_ARGS_((Tk_Window tkwin,
  356.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  357.     Tcl_Obj *CONST objv[]));
  358. static int  WmGroupCmd _ANSI_ARGS_((Tk_Window tkwin,
  359.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  360.     Tcl_Obj *CONST objv[]));
  361. static int  WmIconbitmapCmd _ANSI_ARGS_((Tk_Window tkwin,
  362.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  363.     Tcl_Obj *CONST objv[]));
  364. static int  WmIconifyCmd _ANSI_ARGS_((Tk_Window tkwin,
  365.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  366.     Tcl_Obj *CONST objv[]));
  367. static int  WmIconmaskCmd _ANSI_ARGS_((Tk_Window tkwin,
  368.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  369.     Tcl_Obj *CONST objv[]));
  370. static int  WmIconnameCmd _ANSI_ARGS_((Tk_Window tkwin,
  371.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  372.     Tcl_Obj *CONST objv[]));
  373. static int  WmIconphotoCmd _ANSI_ARGS_((Tk_Window tkwin,
  374.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  375.     Tcl_Obj *CONST objv[]));
  376. static int  WmIconpositionCmd _ANSI_ARGS_((Tk_Window tkwin,
  377.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  378.     Tcl_Obj *CONST objv[]));
  379. static int  WmIconwindowCmd _ANSI_ARGS_((Tk_Window tkwin,
  380.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  381.     Tcl_Obj *CONST objv[]));
  382. static int  WmMaxsizeCmd _ANSI_ARGS_((Tk_Window tkwin,
  383.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  384.     Tcl_Obj *CONST objv[]));
  385. static int  WmMinsizeCmd _ANSI_ARGS_((Tk_Window tkwin,
  386.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  387.     Tcl_Obj *CONST objv[]));
  388. static int  WmOverrideredirectCmd _ANSI_ARGS_((Tk_Window tkwin,
  389.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  390.     Tcl_Obj *CONST objv[]));
  391. static int  WmPositionfromCmd _ANSI_ARGS_((Tk_Window tkwin,
  392.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  393.     Tcl_Obj *CONST objv[]));
  394. static int  WmProtocolCmd _ANSI_ARGS_((Tk_Window tkwin,
  395.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  396.     Tcl_Obj *CONST objv[]));
  397. static int  WmResizableCmd _ANSI_ARGS_((Tk_Window tkwin,
  398.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  399.     Tcl_Obj *CONST objv[]));
  400. static int  WmSizefromCmd _ANSI_ARGS_((Tk_Window tkwin,
  401.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  402.     Tcl_Obj *CONST objv[]));
  403. static int  WmStackorderCmd _ANSI_ARGS_((Tk_Window tkwin,
  404.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  405.     Tcl_Obj *CONST objv[]));
  406. static int  WmStateCmd _ANSI_ARGS_((Tk_Window tkwin,
  407.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  408.     Tcl_Obj *CONST objv[]));
  409. static int  WmTitleCmd _ANSI_ARGS_((Tk_Window tkwin,
  410.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  411.     Tcl_Obj *CONST objv[]));
  412. static int  WmTransientCmd _ANSI_ARGS_((Tk_Window tkwin,
  413.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  414.     Tcl_Obj *CONST objv[]));
  415. static int  WmWithdrawCmd _ANSI_ARGS_((Tk_Window tkwin,
  416.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  417.     Tcl_Obj *CONST objv[]));
  418. static void WmUpdateGeom _ANSI_ARGS_((WmInfo *wmPtr,
  419.     TkWindow *winPtr));
  420. /*
  421.  *--------------------------------------------------------------
  422.  *
  423.  * TkWmCleanup --
  424.  *
  425.  * This procedure is invoked to cleanup remaining wm resources
  426.  * associated with a display.
  427.  *
  428.  * Results:
  429.  * None.
  430.  *
  431.  * Side effects:
  432.  * All WmInfo structure resources are freed and invalidated.
  433.  *
  434.  *--------------------------------------------------------------
  435.  */
  436. void TkWmCleanup(dispPtr)
  437.     TkDisplay *dispPtr;
  438. {
  439.     WmInfo *wmPtr, *nextPtr;
  440.     for (wmPtr = dispPtr->firstWmPtr; wmPtr != NULL; wmPtr = nextPtr) {
  441. /*
  442.  * We can't assume we have access to winPtr's anymore, so some
  443.  * cleanup requiring winPtr data is avoided.
  444.  */
  445. nextPtr = wmPtr->nextPtr;
  446. if (wmPtr->title != NULL) {
  447.     ckfree(wmPtr->title);
  448. }
  449. if (wmPtr->iconName != NULL) {
  450.     ckfree(wmPtr->iconName);
  451. }
  452. if (wmPtr->iconDataPtr != NULL) {
  453.     ckfree((char *)wmPtr->iconDataPtr);
  454. }
  455. if (wmPtr->leaderName != NULL) {
  456.     ckfree(wmPtr->leaderName);
  457. }
  458. if (wmPtr->menubar != NULL) {
  459.     Tk_DestroyWindow(wmPtr->menubar);
  460. }
  461. if (wmPtr->wrapperPtr != NULL) {
  462.     Tk_DestroyWindow((Tk_Window) wmPtr->wrapperPtr);
  463. }
  464. while (wmPtr->protPtr != NULL) {
  465.     ProtocolHandler *protPtr;
  466.     protPtr = wmPtr->protPtr;
  467.     wmPtr->protPtr = protPtr->nextPtr;
  468.     Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC);
  469. }
  470. if (wmPtr->cmdArgv != NULL) {
  471.     ckfree((char *) wmPtr->cmdArgv);
  472. }
  473. if (wmPtr->clientMachine != NULL) {
  474.     ckfree((char *) wmPtr->clientMachine);
  475. }
  476. ckfree((char *) wmPtr);
  477.     }
  478.     if (dispPtr->iconDataPtr != NULL) {
  479. ckfree((char *)dispPtr->iconDataPtr);
  480. dispPtr->iconDataPtr = NULL;
  481.     }
  482. }
  483. /*
  484.  *--------------------------------------------------------------
  485.  *
  486.  * TkWmNewWindow --
  487.  *
  488.  * This procedure is invoked whenever a new top-level
  489.  * window is created.  Its job is to initialize the WmInfo
  490.  * structure for the window.
  491.  *
  492.  * Results:
  493.  * None.
  494.  *
  495.  * Side effects:
  496.  * A WmInfo structure gets allocated and initialized.
  497.  *
  498.  *--------------------------------------------------------------
  499.  */
  500. void
  501. TkWmNewWindow(winPtr)
  502.     TkWindow *winPtr; /* Newly-created top-level window. */
  503. {
  504.     register WmInfo *wmPtr;
  505.     TkDisplay *dispPtr = winPtr->dispPtr;
  506.     wmPtr = (WmInfo *) ckalloc(sizeof(WmInfo));
  507.     memset(wmPtr, 0, sizeof(WmInfo));
  508.     wmPtr->winPtr = winPtr;
  509.     wmPtr->reparent = None;
  510.     wmPtr->masterPtr = NULL;
  511.     wmPtr->numTransients = 0;
  512.     wmPtr->hints.flags = InputHint | StateHint;
  513.     wmPtr->hints.input = True;
  514.     wmPtr->hints.initial_state = NormalState;
  515.     wmPtr->hints.icon_pixmap = None;
  516.     wmPtr->hints.icon_window = None;
  517.     wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;
  518.     wmPtr->hints.icon_mask = None;
  519.     wmPtr->hints.window_group = None;
  520.     /*
  521.      * Default the maximum dimensions to the size of the display, minus
  522.      * a guess about how space is needed for window manager decorations.
  523.      */
  524.     wmPtr->gridWin = NULL;
  525.     wmPtr->minWidth = wmPtr->minHeight = 1;
  526.     wmPtr->maxWidth = wmPtr->maxHeight = 0;
  527.     wmPtr->widthInc = wmPtr->heightInc = 1;
  528.     wmPtr->minAspect.x = wmPtr->minAspect.y = 1;
  529.     wmPtr->maxAspect.x = wmPtr->maxAspect.y = 1;
  530.     wmPtr->reqGridWidth = wmPtr->reqGridHeight = -1;
  531.     wmPtr->gravity = NorthWestGravity;
  532.     wmPtr->width = -1;
  533.     wmPtr->height = -1;
  534.     wmPtr->x = winPtr->changes.x;
  535.     wmPtr->y = winPtr->changes.y;
  536.     wmPtr->parentWidth = winPtr->changes.width
  537.     + 2*winPtr->changes.border_width;
  538.     wmPtr->parentHeight = winPtr->changes.height
  539.     + 2*winPtr->changes.border_width;
  540.     wmPtr->configWidth = -1;
  541.     wmPtr->configHeight = -1;
  542.     wmPtr->vRoot = None;
  543.     wmPtr->flags = WM_NEVER_MAPPED;
  544.     wmPtr->nextPtr = (WmInfo *) dispPtr->firstWmPtr;
  545.     dispPtr->firstWmPtr = wmPtr;
  546.     winPtr->wmInfoPtr = wmPtr;
  547.     UpdateVRootGeometry(wmPtr);
  548.     /*
  549.      * Arrange for geometry requests to be reflected from the window
  550.      * to the window manager.
  551.      */
  552.     Tk_ManageGeometry((Tk_Window) winPtr, &wmMgrType, (ClientData) 0);
  553. }
  554. /*
  555.  *--------------------------------------------------------------
  556.  *
  557.  * TkWmMapWindow --
  558.  *
  559.  * This procedure is invoked to map a top-level window.  This
  560.  * module gets a chance to update all window-manager-related
  561.  * information in properties before the window manager sees
  562.  * the map event and checks the properties.  It also gets to
  563.  * decide whether or not to even map the window after all.
  564.  *
  565.  * Results:
  566.  * None.
  567.  *
  568.  * Side effects:
  569.  * Properties of winPtr may get updated to provide up-to-date
  570.  * information to the window manager.  The window may also get
  571.  * mapped, but it may not be if this procedure decides that
  572.  * isn't appropriate (e.g. because the window is withdrawn).
  573.  *
  574.  *--------------------------------------------------------------
  575.  */
  576. void
  577. TkWmMapWindow(winPtr)
  578.     TkWindow *winPtr; /* Top-level window that's about to
  579.  * be mapped. */
  580. {
  581.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  582.     XTextProperty textProp;
  583.     if (wmPtr->flags & WM_NEVER_MAPPED) {
  584. Tcl_DString ds;
  585. wmPtr->flags &= ~WM_NEVER_MAPPED;
  586. /*
  587.  * This is the first time this window has ever been mapped.
  588.  * First create the wrapper window that provides space for a
  589.  * menubar.
  590.  */
  591. if (wmPtr->wrapperPtr == NULL) {
  592.     CreateWrapper(wmPtr);
  593. }
  594. /*
  595.  * Store all the window-manager-related information for the
  596.  * window.
  597.  */
  598. TkWmSetClass(winPtr);
  599. UpdateTitle(winPtr);
  600. UpdatePhotoIcon(winPtr);
  601. if (wmPtr->masterPtr != NULL) {
  602.     /*
  603.      * Don't map a transient if the master is not mapped.
  604.      */
  605.     if (!Tk_IsMapped(wmPtr->masterPtr)) {
  606.         wmPtr->withdrawn = 1;
  607.         wmPtr->hints.initial_state = WithdrawnState;
  608.     } else {
  609.         XSetTransientForHint(winPtr->display, wmPtr->wrapperPtr->window,
  610.         wmPtr->masterPtr->wmInfoPtr->wrapperPtr->window);
  611.     }
  612. }
  613. wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
  614. UpdateHints(winPtr);
  615. UpdateWmProtocols(wmPtr);
  616. if (wmPtr->cmdArgv != NULL) {
  617.     UpdateCommand(winPtr);
  618. }
  619. if (wmPtr->clientMachine != NULL) {
  620.     Tcl_UtfToExternalDString(NULL, wmPtr->clientMachine, -1, &ds);
  621.     if (XStringListToTextProperty(&(Tcl_DStringValue(&ds)), 1,
  622.     &textProp) != 0) {
  623. XSetWMClientMachine(winPtr->display, wmPtr->wrapperPtr->window,
  624. &textProp);
  625. XFree((char *) textProp.value);
  626.     }
  627.     Tcl_DStringFree(&ds);
  628. }
  629.     }
  630.     if (wmPtr->hints.initial_state == WithdrawnState) {
  631. return;
  632.     }
  633.     if (wmPtr->iconFor != NULL) {
  634. /*
  635.  * This window is an icon for somebody else.  Make sure that
  636.  * the geometry is up-to-date, then return without mapping
  637.  * the window.
  638.  */
  639. if (wmPtr->flags & WM_UPDATE_PENDING) {
  640.     Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
  641. }
  642. UpdateGeometryInfo((ClientData) winPtr);
  643. return;
  644.     }
  645.     wmPtr->flags |= WM_ABOUT_TO_MAP;
  646.     if (wmPtr->flags & WM_UPDATE_PENDING) {
  647. Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
  648.     }
  649.     UpdateGeometryInfo((ClientData) winPtr);
  650.     wmPtr->flags &= ~WM_ABOUT_TO_MAP;
  651.     /*
  652.      * Map the window, then wait to be sure that the window manager has
  653.      * processed the map operation.
  654.      */
  655.     XMapWindow(winPtr->display, wmPtr->wrapperPtr->window);
  656.     if (wmPtr->hints.initial_state == NormalState) {
  657. WaitForMapNotify(winPtr, 1);
  658.     }
  659. }
  660. /*
  661.  *--------------------------------------------------------------
  662.  *
  663.  * TkWmUnmapWindow --
  664.  *
  665.  * This procedure is invoked to unmap a top-level window.  The
  666.  * only thing it does special is to wait for the window actually
  667.  * to be unmapped.
  668.  *
  669.  * Results:
  670.  * None.
  671.  *
  672.  * Side effects:
  673.  * Unmaps the window.
  674.  *
  675.  *--------------------------------------------------------------
  676.  */
  677. void
  678. TkWmUnmapWindow(winPtr)
  679.     TkWindow *winPtr; /* Top-level window that's about to
  680.  * be mapped. */
  681. {
  682.     /*
  683.      * It seems to be important to wait after unmapping a top-level
  684.      * window until the window really gets unmapped.  I don't completely
  685.      * understand all the interactions with the window manager, but if
  686.      * we go on without waiting, and if the window is then mapped again
  687.      * quickly, events seem to get lost so that we think the window isn't
  688.      * mapped when in fact it is mapped.  I suspect that this has something
  689.      * to do with the window manager filtering Map events (and possily not
  690.      * filtering Unmap events?).
  691.      */
  692.     XUnmapWindow(winPtr->display, winPtr->wmInfoPtr->wrapperPtr->window);
  693.     WaitForMapNotify(winPtr, 0);
  694. }
  695. /*
  696.  *--------------------------------------------------------------
  697.  *
  698.  * TkWmDeadWindow --
  699.  *
  700.  * This procedure is invoked when a top-level window is
  701.  * about to be deleted.  It cleans up the wm-related data
  702.  * structures for the window.
  703.  *
  704.  * Results:
  705.  * None.
  706.  *
  707.  * Side effects:
  708.  * The WmInfo structure for winPtr gets freed up.
  709.  *
  710.  *--------------------------------------------------------------
  711.  */
  712. void
  713. TkWmDeadWindow(winPtr)
  714.     TkWindow *winPtr; /* Top-level window that's being deleted. */
  715. {
  716.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  717.     WmInfo *wmPtr2;
  718.     if (wmPtr == NULL) {
  719. return;
  720.     }
  721.     if ((WmInfo *) winPtr->dispPtr->firstWmPtr == wmPtr) {
  722. winPtr->dispPtr->firstWmPtr = wmPtr->nextPtr;
  723.     } else {
  724. register WmInfo *prevPtr;
  725. for (prevPtr = (WmInfo *) winPtr->dispPtr->firstWmPtr; ;
  726.                 prevPtr = prevPtr->nextPtr) {
  727.     if (prevPtr == NULL) {
  728. Tcl_Panic("couldn't unlink window in TkWmDeadWindow");
  729.     }
  730.     if (prevPtr->nextPtr == wmPtr) {
  731. prevPtr->nextPtr = wmPtr->nextPtr;
  732. break;
  733.     }
  734. }
  735.     }
  736.     if (wmPtr->title != NULL) {
  737. ckfree(wmPtr->title);
  738.     }
  739.     if (wmPtr->iconName != NULL) {
  740. ckfree(wmPtr->iconName);
  741.     }
  742.     if (wmPtr->iconDataPtr != NULL) {
  743. ckfree((char *)wmPtr->iconDataPtr);
  744.     }
  745.     if (wmPtr->hints.flags & IconPixmapHint) {
  746. Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
  747.     }
  748.     if (wmPtr->hints.flags & IconMaskHint) {
  749. Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);
  750.     }
  751.     if (wmPtr->leaderName != NULL) {
  752. ckfree(wmPtr->leaderName);
  753.     }
  754.     if (wmPtr->icon != NULL) {
  755. wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
  756. wmPtr2->iconFor = NULL;
  757. wmPtr2->withdrawn = 1;
  758.     }
  759.     if (wmPtr->iconFor != NULL) {
  760. wmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr;
  761. wmPtr2->icon = NULL;
  762. wmPtr2->hints.flags &= ~IconWindowHint;
  763. UpdateHints((TkWindow *) wmPtr->iconFor);
  764.     }
  765.     if (wmPtr->menubar != NULL) {
  766. Tk_DestroyWindow(wmPtr->menubar);
  767.     }
  768.     if (wmPtr->wrapperPtr != NULL) {
  769. /*
  770.  * The rest of Tk doesn't know that we reparent the toplevel
  771.  * inside the wrapper, so reparent it back out again before
  772.  * deleting the wrapper; otherwise the toplevel will get deleted
  773.  * twice (once implicitly by the deletion of the wrapper).
  774.  */
  775. XUnmapWindow(winPtr->display, winPtr->window);
  776. XReparentWindow(winPtr->display, winPtr->window,
  777. XRootWindow(winPtr->display, winPtr->screenNum), 0, 0);
  778. Tk_DestroyWindow((Tk_Window) wmPtr->wrapperPtr);
  779.     }
  780.     while (wmPtr->protPtr != NULL) {
  781. ProtocolHandler *protPtr;
  782. protPtr = wmPtr->protPtr;
  783. wmPtr->protPtr = protPtr->nextPtr;
  784. Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC);
  785.     }
  786.     if (wmPtr->cmdArgv != NULL) {
  787. ckfree((char *) wmPtr->cmdArgv);
  788.     }
  789.     if (wmPtr->clientMachine != NULL) {
  790. ckfree((char *) wmPtr->clientMachine);
  791.     }
  792.     if (wmPtr->flags & WM_UPDATE_PENDING) {
  793. Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
  794.     }
  795.     /*
  796.      * Reset all transient windows whose master is the dead window.
  797.      */
  798.     for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;
  799.  wmPtr2 = wmPtr2->nextPtr) {
  800. if (wmPtr2->masterPtr == winPtr) {
  801.     wmPtr->numTransients--;
  802.     Tk_DeleteEventHandler((Tk_Window) wmPtr2->masterPtr,
  803.             StructureNotifyMask,
  804.             WmWaitMapProc, (ClientData) wmPtr2->winPtr);
  805.     wmPtr2->masterPtr = NULL;
  806.     if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
  807. XDeleteProperty(winPtr->display, wmPtr2->wrapperPtr->window,
  808. Tk_InternAtom((Tk_Window) winPtr, "WM_TRANSIENT_FOR"));
  809. /* FIXME: Need a call like Win32's UpdateWrapper() so
  810.    we can recreate the wrapper and get rid of the
  811.    transient window decorations. */
  812.     }
  813. }
  814.     }
  815.     if (wmPtr->numTransients != 0)
  816.         Tcl_Panic("numTransients should be 0");
  817.     if (wmPtr->masterPtr != NULL) {
  818. wmPtr2 = wmPtr->masterPtr->wmInfoPtr;
  819. /*
  820.  * If we had a master, tell them that we aren't tied
  821.  * to them anymore
  822.  */
  823. if (wmPtr2 != NULL) {
  824.     wmPtr2->numTransients--;
  825. }
  826. Tk_DeleteEventHandler((Tk_Window) wmPtr->masterPtr,
  827. StructureNotifyMask,
  828. WmWaitMapProc, (ClientData) winPtr);
  829. wmPtr->masterPtr = NULL;
  830.     }
  831.     ckfree((char *) wmPtr);
  832.     winPtr->wmInfoPtr = NULL;
  833. }
  834. /*
  835.  *--------------------------------------------------------------
  836.  *
  837.  * TkWmSetClass --
  838.  *
  839.  * This procedure is invoked whenever a top-level window's
  840.  * class is changed.  If the window has been mapped then this
  841.  * procedure updates the window manager property for the
  842.  * class.  If the window hasn't been mapped, the update is
  843.  * deferred until just before the first mapping.
  844.  *
  845.  * Results:
  846.  * None.
  847.  *
  848.  * Side effects:
  849.  * A window property may get updated.
  850.  *
  851.  *--------------------------------------------------------------
  852.  */
  853. void
  854. TkWmSetClass(winPtr)
  855.     TkWindow *winPtr; /* Newly-created top-level window. */
  856. {
  857.     if (winPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {
  858. return;
  859.     }
  860.     if (winPtr->classUid != NULL) {
  861. XClassHint *classPtr;
  862. Tcl_DString name, class;
  863. Tcl_UtfToExternalDString(NULL, winPtr->nameUid, -1, &name);
  864. Tcl_UtfToExternalDString(NULL, winPtr->classUid, -1, &class);
  865. classPtr = XAllocClassHint();
  866. classPtr->res_name = Tcl_DStringValue(&name);
  867. classPtr->res_class = Tcl_DStringValue(&class);
  868. XSetClassHint(winPtr->display, winPtr->wmInfoPtr->wrapperPtr->window,
  869. classPtr);
  870. XFree((char *) classPtr);
  871. Tcl_DStringFree(&name);
  872. Tcl_DStringFree(&class);
  873.     }
  874. }
  875. /*
  876.  *----------------------------------------------------------------------
  877.  *
  878.  * Tk_WmObjCmd --
  879.  *
  880.  * This procedure is invoked to process the "wm" Tcl command.
  881.  * See the user documentation for details on what it does.
  882.  *
  883.  * Results:
  884.  * A standard Tcl result.
  885.  *
  886.  * Side effects:
  887.  * See the user documentation.
  888.  *
  889.  *----------------------------------------------------------------------
  890.  */
  891. /* ARGSUSED */
  892. int
  893. Tk_WmObjCmd(clientData, interp, objc, objv)
  894.     ClientData clientData; /* Main window associated with
  895.  * interpreter. */
  896.     Tcl_Interp *interp; /* Current interpreter. */
  897.     int objc; /* Number of arguments. */
  898.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  899. {
  900.     Tk_Window tkwin = (Tk_Window) clientData;
  901.     static CONST char *optionStrings[] = {
  902. "aspect", "attributes", "client", "colormapwindows",
  903. "command", "deiconify", "focusmodel", "frame",
  904. "geometry", "grid", "group", "iconbitmap",
  905. "iconify", "iconmask", "iconname",
  906. "iconphoto", "iconposition",
  907. "iconwindow", "maxsize", "minsize", "overrideredirect",
  908.         "positionfrom", "protocol", "resizable", "sizefrom",
  909.         "stackorder", "state", "title", "transient",
  910. "withdraw", (char *) NULL };
  911.     enum options {
  912.         WMOPT_ASPECT, WMOPT_ATTRIBUTES, WMOPT_CLIENT, WMOPT_COLORMAPWINDOWS,
  913. WMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FRAME,
  914. WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP, WMOPT_ICONBITMAP,
  915. WMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME,
  916. WMOPT_ICONPHOTO, WMOPT_ICONPOSITION,
  917. WMOPT_ICONWINDOW, WMOPT_MAXSIZE, WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT,
  918.         WMOPT_POSITIONFROM, WMOPT_PROTOCOL, WMOPT_RESIZABLE, WMOPT_SIZEFROM,
  919.         WMOPT_STACKORDER, WMOPT_STATE, WMOPT_TITLE, WMOPT_TRANSIENT,
  920. WMOPT_WITHDRAW };
  921.     int index; 
  922.     int length;
  923.     char *argv1;
  924.     TkWindow *winPtr;
  925.     TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
  926.     if (objc < 2) {
  927. wrongNumArgs:
  928. Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?");
  929. return TCL_ERROR;
  930.     }
  931.     argv1 = Tcl_GetStringFromObj(objv[1], &length);
  932.     if ((argv1[0] == 't') && (strncmp(argv1, "tracing", (size_t) length) == 0)
  933.     && (length >= 3)) {
  934. int wmTracing;
  935. if ((objc != 2) && (objc != 3)) {
  936.     Tcl_WrongNumArgs(interp, 2, objv, "?boolean?");
  937.     return TCL_ERROR;
  938. }
  939. if (objc == 2) {
  940.     Tcl_SetResult(interp,
  941.     ((dispPtr->flags & TK_DISPLAY_WM_TRACING) ? "on" : "off"),
  942.     TCL_STATIC);
  943.     return TCL_OK;
  944. }
  945. if (Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing) != TCL_OK) {
  946.     return TCL_ERROR;
  947. }
  948. if (wmTracing) {
  949.     dispPtr->flags |= TK_DISPLAY_WM_TRACING;
  950. } else {
  951.     dispPtr->flags &= ~TK_DISPLAY_WM_TRACING;
  952. }
  953. return TCL_OK;
  954.     }
  955.     if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
  956.     &index) != TCL_OK) {
  957. return TCL_ERROR;
  958.     }
  959.     if (objc < 3) {
  960. goto wrongNumArgs;
  961.     }
  962.     if (TkGetWindowFromObj(interp, tkwin, objv[2], (Tk_Window *) &winPtr)
  963.     != TCL_OK) {
  964. return TCL_ERROR;
  965.     }
  966.     if (!Tk_IsTopLevel(winPtr)) {
  967. Tcl_AppendResult(interp, "window "", winPtr->pathName,
  968. "" isn't a top-level window", (char *) NULL);
  969. return TCL_ERROR;
  970.     }
  971.     switch ((enum options) index) {
  972.       case WMOPT_ASPECT:
  973. return WmAspectCmd(tkwin, winPtr, interp, objc, objv);
  974.       case WMOPT_ATTRIBUTES:
  975. return WmAttributesCmd(tkwin, winPtr, interp, objc, objv);
  976.       case WMOPT_CLIENT:
  977. return WmClientCmd(tkwin, winPtr, interp, objc, objv);
  978.       case WMOPT_COLORMAPWINDOWS:
  979. return WmColormapwindowsCmd(tkwin, winPtr, interp, objc, objv);
  980.       case WMOPT_COMMAND:
  981. return WmCommandCmd(tkwin, winPtr, interp, objc, objv);
  982.       case WMOPT_DEICONIFY:
  983. return WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv);
  984.       case WMOPT_FOCUSMODEL:
  985. return WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv);
  986.       case WMOPT_FRAME:
  987. return WmFrameCmd(tkwin, winPtr, interp, objc, objv);
  988.       case WMOPT_GEOMETRY:
  989. return WmGeometryCmd(tkwin, winPtr, interp, objc, objv);
  990.       case WMOPT_GRID:
  991. return WmGridCmd(tkwin, winPtr, interp, objc, objv);
  992.       case WMOPT_GROUP:
  993. return WmGroupCmd(tkwin, winPtr, interp, objc, objv);
  994.       case WMOPT_ICONBITMAP:
  995. return WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv);
  996.       case WMOPT_ICONIFY:
  997. return WmIconifyCmd(tkwin, winPtr, interp, objc, objv);
  998.       case WMOPT_ICONMASK:
  999. return WmIconmaskCmd(tkwin, winPtr, interp, objc, objv);
  1000.       case WMOPT_ICONNAME:
  1001. return WmIconnameCmd(tkwin, winPtr, interp, objc, objv);
  1002.       case WMOPT_ICONPHOTO:
  1003.         return WmIconphotoCmd(tkwin, winPtr, interp, objc, objv);
  1004.       case WMOPT_ICONPOSITION:
  1005. return WmIconpositionCmd(tkwin, winPtr, interp, objc, objv);
  1006.       case WMOPT_ICONWINDOW:
  1007. return WmIconwindowCmd(tkwin, winPtr, interp, objc, objv);
  1008.       case WMOPT_MAXSIZE:
  1009. return WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv);
  1010.       case WMOPT_MINSIZE:
  1011. return WmMinsizeCmd(tkwin, winPtr, interp, objc, objv);
  1012.       case WMOPT_OVERRIDEREDIRECT:
  1013. return WmOverrideredirectCmd(tkwin, winPtr, interp, objc, objv);
  1014.       case WMOPT_POSITIONFROM:
  1015. return WmPositionfromCmd(tkwin, winPtr, interp, objc, objv);
  1016.       case WMOPT_PROTOCOL:
  1017. return WmProtocolCmd(tkwin, winPtr, interp, objc, objv);
  1018.       case WMOPT_RESIZABLE:
  1019. return WmResizableCmd(tkwin, winPtr, interp, objc, objv);
  1020.       case WMOPT_SIZEFROM:
  1021. return WmSizefromCmd(tkwin, winPtr, interp, objc, objv);
  1022.       case WMOPT_STACKORDER:
  1023. return WmStackorderCmd(tkwin, winPtr, interp, objc, objv);
  1024.       case WMOPT_STATE:
  1025. return WmStateCmd(tkwin, winPtr, interp, objc, objv);
  1026.       case WMOPT_TITLE:
  1027. return WmTitleCmd(tkwin, winPtr, interp, objc, objv);
  1028.       case WMOPT_TRANSIENT:
  1029. return WmTransientCmd(tkwin, winPtr, interp, objc, objv);
  1030.       case WMOPT_WITHDRAW:
  1031. return WmWithdrawCmd(tkwin, winPtr, interp, objc, objv);
  1032.     }
  1033.     /* This should not happen */
  1034.     return TCL_ERROR;
  1035. }
  1036. /*
  1037.  *----------------------------------------------------------------------
  1038.  *
  1039.  * WmAspectCmd --
  1040.  *
  1041.  * This procedure is invoked to process the "wm aspect" Tcl command.
  1042.  * See the user documentation for details on what it does.
  1043.  *
  1044.  * Results:
  1045.  * A standard Tcl result.
  1046.  *
  1047.  * Side effects:
  1048.  * See the user documentation.
  1049.  *
  1050.  *----------------------------------------------------------------------
  1051.  */
  1052. static int
  1053. WmAspectCmd(tkwin, winPtr, interp, objc, objv)
  1054.     Tk_Window tkwin; /* Main window of the application. */
  1055.     TkWindow *winPtr;           /* Toplevel to work with */
  1056.     Tcl_Interp *interp; /* Current interpreter. */
  1057.     int objc; /* Number of arguments. */
  1058.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1059. {
  1060.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1061.     int numer1, denom1, numer2, denom2;
  1062.     if ((objc != 3) && (objc != 7)) {
  1063. Tcl_WrongNumArgs(interp, 2, objv,
  1064. "window ?minNumer minDenom maxNumer maxDenom?");
  1065. return TCL_ERROR;
  1066.     }
  1067.     if (objc == 3) {
  1068. if (wmPtr->sizeHintsFlags & PAspect) {
  1069.     char buf[TCL_INTEGER_SPACE * 4];
  1070.     sprintf(buf, "%d %d %d %d", wmPtr->minAspect.x,
  1071.     wmPtr->minAspect.y, wmPtr->maxAspect.x,
  1072.     wmPtr->maxAspect.y);
  1073.     Tcl_SetResult(interp, buf, TCL_VOLATILE);
  1074. }
  1075. return TCL_OK;
  1076.     }
  1077.     if (*Tcl_GetString(objv[3]) == '') {
  1078. wmPtr->sizeHintsFlags &= ~PAspect;
  1079.     } else {
  1080. if ((Tcl_GetIntFromObj(interp, objv[3], &numer1) != TCL_OK)
  1081. || (Tcl_GetIntFromObj(interp, objv[4], &denom1) != TCL_OK)
  1082. || (Tcl_GetIntFromObj(interp, objv[5], &numer2) != TCL_OK)
  1083. || (Tcl_GetIntFromObj(interp, objv[6], &denom2) != TCL_OK)) {
  1084.     return TCL_ERROR;
  1085. }
  1086. if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) ||
  1087. (denom2 <= 0)) {
  1088.     Tcl_SetResult(interp, "aspect number can't be <= 0",
  1089.     TCL_STATIC);
  1090.     return TCL_ERROR;
  1091. }
  1092. wmPtr->minAspect.x = numer1;
  1093. wmPtr->minAspect.y = denom1;
  1094. wmPtr->maxAspect.x = numer2;
  1095. wmPtr->maxAspect.y = denom2;
  1096. wmPtr->sizeHintsFlags |= PAspect;
  1097.     }
  1098.     wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
  1099.     WmUpdateGeom(wmPtr, winPtr);
  1100.     return TCL_OK;
  1101. }
  1102. /*
  1103.  *----------------------------------------------------------------------
  1104.  *
  1105.  * WmAttributesCmd --
  1106.  *
  1107.  * This procedure is invoked to process the "wm attributes" Tcl command.
  1108.  * See the user documentation for details on what it does.
  1109.  *
  1110.  * Results:
  1111.  * A standard Tcl result.
  1112.  *
  1113.  * Side effects:
  1114.  * See the user documentation.
  1115.  *
  1116.  *----------------------------------------------------------------------
  1117.  */
  1118. static int
  1119. WmAttributesCmd(tkwin, winPtr, interp, objc, objv)
  1120.     Tk_Window tkwin; /* Main window of the application. */
  1121.     TkWindow *winPtr;           /* Toplevel to work with */
  1122.     Tcl_Interp *interp; /* Current interpreter. */
  1123.     int objc; /* Number of arguments. */
  1124.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1125. {
  1126.     if (objc != 3) {
  1127. Tcl_WrongNumArgs(interp, 2, objv, "window");
  1128. return TCL_ERROR;
  1129.     }
  1130.     return TCL_OK;
  1131. }
  1132. /*
  1133.  *----------------------------------------------------------------------
  1134.  *
  1135.  * WmClientCmd --
  1136.  *
  1137.  * This procedure is invoked to process the "wm client" Tcl command.
  1138.  * See the user documentation for details on what it does.
  1139.  *
  1140.  * Results:
  1141.  * A standard Tcl result.
  1142.  *
  1143.  * Side effects:
  1144.  * See the user documentation.
  1145.  *
  1146.  *----------------------------------------------------------------------
  1147.  */
  1148. static int
  1149. WmClientCmd(tkwin, winPtr, interp, objc, objv)
  1150.     Tk_Window tkwin; /* Main window of the application. */
  1151.     TkWindow *winPtr;           /* Toplevel to work with */
  1152.     Tcl_Interp *interp; /* Current interpreter. */
  1153.     int objc; /* Number of arguments. */
  1154.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1155. {
  1156.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1157.     char *argv3;
  1158.     int length;
  1159.     if ((objc != 3) && (objc != 4)) {
  1160. Tcl_WrongNumArgs(interp, 2, objv, "window ?name?");
  1161. return TCL_ERROR;
  1162.     }
  1163.     if (objc == 3) {
  1164. if (wmPtr->clientMachine != NULL) {
  1165.     Tcl_SetResult(interp, wmPtr->clientMachine, TCL_STATIC);
  1166. }
  1167. return TCL_OK;
  1168.     }
  1169.     argv3 = Tcl_GetStringFromObj(objv[3], &length);
  1170.     if (argv3[0] == 0) {
  1171. if (wmPtr->clientMachine != NULL) {
  1172.     ckfree((char *) wmPtr->clientMachine);
  1173.     wmPtr->clientMachine = NULL;
  1174.     if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  1175. XDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window,
  1176. Tk_InternAtom((Tk_Window) winPtr,
  1177. "WM_CLIENT_MACHINE"));
  1178.     }
  1179. }
  1180. return TCL_OK;
  1181.     }
  1182.     if (wmPtr->clientMachine != NULL) {
  1183. ckfree((char *) wmPtr->clientMachine);
  1184.     }
  1185.     wmPtr->clientMachine = (char *)
  1186.     ckalloc((unsigned) (length + 1));
  1187.     strcpy(wmPtr->clientMachine, argv3);
  1188.     if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  1189. XTextProperty textProp;
  1190. Tcl_DString ds;
  1191. Tcl_UtfToExternalDString(NULL, wmPtr->clientMachine, -1, &ds);
  1192. if (XStringListToTextProperty(&(Tcl_DStringValue(&ds)), 1,
  1193. &textProp) != 0) {
  1194.     XSetWMClientMachine(winPtr->display, wmPtr->wrapperPtr->window,
  1195.     &textProp);
  1196.     XFree((char *) textProp.value);
  1197. }
  1198. Tcl_DStringFree(&ds);
  1199.     }
  1200.     return TCL_OK;
  1201. }
  1202. /*
  1203.  *----------------------------------------------------------------------
  1204.  *
  1205.  * WmColormapwindowsCmd --
  1206.  *
  1207.  * This procedure is invoked to process the "wm colormapwindows"
  1208.  * Tcl command.
  1209.  * See the user documentation for details on what it does.
  1210.  *
  1211.  * Results:
  1212.  * A standard Tcl result.
  1213.  *
  1214.  * Side effects:
  1215.  * See the user documentation.
  1216.  *
  1217.  *----------------------------------------------------------------------
  1218.  */
  1219. static int
  1220. WmColormapwindowsCmd(tkwin, winPtr, interp, objc, objv)
  1221.     Tk_Window tkwin; /* Main window of the application. */
  1222.     TkWindow *winPtr;           /* Toplevel to work with */
  1223.     Tcl_Interp *interp; /* Current interpreter. */
  1224.     int objc; /* Number of arguments. */
  1225.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1226. {
  1227.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1228.     Window *cmapList;
  1229.     TkWindow *winPtr2;
  1230.     int count, i, windowObjc, gotToplevel;
  1231.     Tcl_Obj **windowObjv;
  1232.     char buffer[20];
  1233.     if ((objc != 3) && (objc != 4)) {
  1234. Tcl_WrongNumArgs(interp, 2, objv, "window ?windowList?");
  1235. return TCL_ERROR;
  1236.     }
  1237.     Tk_MakeWindowExist((Tk_Window) winPtr);
  1238.     if (wmPtr->wrapperPtr == NULL) {
  1239. CreateWrapper(wmPtr);
  1240.     }
  1241.     if (objc == 3) {
  1242. if (XGetWMColormapWindows(winPtr->display,
  1243. wmPtr->wrapperPtr->window, &cmapList, &count) == 0) {
  1244.     return TCL_OK;
  1245. }
  1246. for (i = 0; i < count; i++) {
  1247.     if ((i == (count-1))
  1248.     && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) {
  1249. break;
  1250.     }
  1251.     winPtr2  = (TkWindow *) Tk_IdToWindow(winPtr->display,
  1252.     cmapList[i]);
  1253.     if (winPtr2 == NULL) {
  1254. sprintf(buffer, "0x%lx", cmapList[i]);
  1255. Tcl_AppendElement(interp, buffer);
  1256.     } else {
  1257. Tcl_AppendElement(interp, winPtr2->pathName);
  1258.     }
  1259. }
  1260. XFree((char *) cmapList);
  1261. return TCL_OK;
  1262.     }
  1263.     if (Tcl_ListObjGetElements(interp, objv[3], &windowObjc, &windowObjv)
  1264.     != TCL_OK) {
  1265. return TCL_ERROR;
  1266.     }
  1267.     cmapList = (Window *) ckalloc((unsigned)
  1268.     ((windowObjc+1)*sizeof(Window)));
  1269.     gotToplevel = 0;
  1270.     for (i = 0; i < windowObjc; i++) {
  1271. if (TkGetWindowFromObj(interp, tkwin, windowObjv[i],
  1272. (Tk_Window *) &winPtr2) != TCL_OK)
  1273. {
  1274.     ckfree((char *) cmapList);
  1275.     return TCL_ERROR;
  1276. }
  1277. if (winPtr2 == winPtr) {
  1278.     gotToplevel = 1;
  1279. }
  1280. if (winPtr2->window == None) {
  1281.     Tk_MakeWindowExist((Tk_Window) winPtr2);
  1282. }
  1283. cmapList[i] = winPtr2->window;
  1284.     }
  1285.     if (!gotToplevel) {
  1286. wmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP;
  1287. cmapList[windowObjc] = wmPtr->wrapperPtr->window;
  1288. windowObjc++;
  1289.     } else {
  1290. wmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP;
  1291.     }
  1292.     wmPtr->flags |= WM_COLORMAPS_EXPLICIT;
  1293.     XSetWMColormapWindows(winPtr->display, wmPtr->wrapperPtr->window,
  1294.     cmapList, windowObjc);
  1295.     ckfree((char *) cmapList);
  1296.     return TCL_OK;
  1297. }
  1298. /*
  1299.  *----------------------------------------------------------------------
  1300.  *
  1301.  * WmCommandCmd --
  1302.  *
  1303.  * This procedure is invoked to process the "wm command" Tcl command.
  1304.  * See the user documentation for details on what it does.
  1305.  *
  1306.  * Results:
  1307.  * A standard Tcl result.
  1308.  *
  1309.  * Side effects:
  1310.  * See the user documentation.
  1311.  *
  1312.  *----------------------------------------------------------------------
  1313.  */
  1314. static int
  1315. WmCommandCmd(tkwin, winPtr, interp, objc, objv)
  1316.     Tk_Window tkwin; /* Main window of the application. */
  1317.     TkWindow *winPtr;           /* Toplevel to work with */
  1318.     Tcl_Interp *interp; /* Current interpreter. */
  1319.     int objc; /* Number of arguments. */
  1320.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1321. {
  1322.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1323.     char *argv3;
  1324.     int cmdArgc;
  1325.     CONST char **cmdArgv;
  1326.     if ((objc != 3) && (objc != 4)) {
  1327. Tcl_WrongNumArgs(interp, 2, objv, "window ?value?");
  1328. return TCL_ERROR;
  1329.     }
  1330.     if (objc == 3) {
  1331. if (wmPtr->cmdArgv != NULL) {
  1332.     Tcl_SetResult(interp,
  1333.     Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv),
  1334.     TCL_DYNAMIC);
  1335. }
  1336. return TCL_OK;
  1337.     }
  1338.     argv3 = Tcl_GetString(objv[3]);
  1339.     if (argv3[0] == 0) {
  1340. if (wmPtr->cmdArgv != NULL) {
  1341.     ckfree((char *) wmPtr->cmdArgv);
  1342.     wmPtr->cmdArgv = NULL;
  1343.     if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  1344. XDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window,
  1345. Tk_InternAtom((Tk_Window) winPtr, "WM_COMMAND"));
  1346.     }
  1347. }
  1348. return TCL_OK;
  1349.     }
  1350.     if (Tcl_SplitList(interp, argv3, &cmdArgc, &cmdArgv) != TCL_OK) {
  1351. return TCL_ERROR;
  1352.     }
  1353.     if (wmPtr->cmdArgv != NULL) {
  1354. ckfree((char *) wmPtr->cmdArgv);
  1355.     }
  1356.     wmPtr->cmdArgc = cmdArgc;
  1357.     wmPtr->cmdArgv = cmdArgv;
  1358.     if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  1359. UpdateCommand(winPtr);
  1360.     }
  1361.     return TCL_OK;
  1362. }
  1363. /*
  1364.  *----------------------------------------------------------------------
  1365.  *
  1366.  * WmDeiconifyCmd --
  1367.  *
  1368.  * This procedure is invoked to process the "wm deiconify" Tcl command.
  1369.  * See the user documentation for details on what it does.
  1370.  *
  1371.  * Results:
  1372.  * A standard Tcl result.
  1373.  *
  1374.  * Side effects:
  1375.  * See the user documentation.
  1376.  *
  1377.  *----------------------------------------------------------------------
  1378.  */
  1379. static int
  1380. WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv)
  1381.     Tk_Window tkwin; /* Main window of the application. */
  1382.     TkWindow *winPtr;           /* Toplevel to work with */
  1383.     Tcl_Interp *interp; /* Current interpreter. */
  1384.     int objc; /* Number of arguments. */
  1385.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1386. {
  1387.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1388.     if (objc != 3) {
  1389. Tcl_WrongNumArgs(interp, 2, objv, "window");
  1390. return TCL_ERROR;
  1391.     }
  1392.     if (wmPtr->iconFor != NULL) {
  1393. Tcl_AppendResult(interp, "can't deiconify ", Tcl_GetString(objv[2]),
  1394. ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
  1395. (char *) NULL);
  1396. return TCL_ERROR;
  1397.     }
  1398.     if (winPtr->flags & TK_EMBEDDED) {
  1399. Tcl_AppendResult(interp, "can't deiconify ", winPtr->pathName,
  1400. ": it is an embedded window", (char *) NULL);
  1401. return TCL_ERROR;
  1402.     }
  1403.     wmPtr->flags &= ~WM_WITHDRAWN;
  1404.     TkpWmSetState(winPtr, NormalState);
  1405.     return TCL_OK;
  1406. }
  1407. /*
  1408.  *----------------------------------------------------------------------
  1409.  *
  1410.  * WmFocusmodelCmd --
  1411.  *
  1412.  * This procedure is invoked to process the "wm focusmodel" Tcl command.
  1413.  * See the user documentation for details on what it does.
  1414.  *
  1415.  * Results:
  1416.  * A standard Tcl result.
  1417.  *
  1418.  * Side effects:
  1419.  * See the user documentation.
  1420.  *
  1421.  *----------------------------------------------------------------------
  1422.  */
  1423. static int
  1424. WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv)
  1425.     Tk_Window tkwin; /* Main window of the application. */
  1426.     TkWindow *winPtr;           /* Toplevel to work with */
  1427.     Tcl_Interp *interp; /* Current interpreter. */
  1428.     int objc; /* Number of arguments. */
  1429.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1430. {
  1431.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1432.     static CONST char *optionStrings[] = {
  1433. "active", "passive", (char *) NULL };
  1434.     enum options {
  1435. OPT_ACTIVE, OPT_PASSIVE };
  1436.     int index;
  1437.     if ((objc != 3) && (objc != 4)) {
  1438. Tcl_WrongNumArgs(interp, 2, objv, "window ?active|passive?");
  1439. return TCL_ERROR;
  1440.     }
  1441.     if (objc == 3) {
  1442. Tcl_SetResult(interp, (wmPtr->hints.input ? "passive" : "active"),
  1443. TCL_STATIC);
  1444. return TCL_OK;
  1445.     }
  1446.     if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0,
  1447.     &index) != TCL_OK) {
  1448. return TCL_ERROR;
  1449.     }
  1450.     if (index == OPT_ACTIVE) {
  1451. wmPtr->hints.input = False;
  1452.     } else { /* OPT_PASSIVE */
  1453. wmPtr->hints.input = True;
  1454.     }
  1455.     UpdateHints(winPtr);
  1456.     return TCL_OK;
  1457. }
  1458. /*
  1459.  *----------------------------------------------------------------------
  1460.  *
  1461.  * WmFrameCmd --
  1462.  *
  1463.  * This procedure is invoked to process the "wm frame" Tcl command.
  1464.  * See the user documentation for details on what it does.
  1465.  *
  1466.  * Results:
  1467.  * A standard Tcl result.
  1468.  *
  1469.  * Side effects:
  1470.  * See the user documentation.
  1471.  *
  1472.  *----------------------------------------------------------------------
  1473.  */
  1474. static int
  1475. WmFrameCmd(tkwin, winPtr, interp, objc, objv)
  1476.     Tk_Window tkwin; /* Main window of the application. */
  1477.     TkWindow *winPtr;           /* Toplevel to work with */
  1478.     Tcl_Interp *interp; /* Current interpreter. */
  1479.     int objc; /* Number of arguments. */
  1480.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1481. {
  1482.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1483.     Window window;
  1484.     char buf[TCL_INTEGER_SPACE];
  1485.     if (objc != 3) {
  1486. Tcl_WrongNumArgs(interp, 2, objv, "window");
  1487. return TCL_ERROR;
  1488.     }
  1489.     window = wmPtr->reparent;
  1490.     if (window == None) {
  1491. window = Tk_WindowId((Tk_Window) winPtr);
  1492.     }
  1493.     sprintf(buf, "0x%x", (unsigned int) window);
  1494.     Tcl_SetResult(interp, buf, TCL_VOLATILE);
  1495.     return TCL_OK;
  1496. }
  1497. /*
  1498.  *----------------------------------------------------------------------
  1499.  *
  1500.  * WmGeometryCmd --
  1501.  *
  1502.  * This procedure is invoked to process the "wm geometry" Tcl command.
  1503.  * See the user documentation for details on what it does.
  1504.  *
  1505.  * Results:
  1506.  * A standard Tcl result.
  1507.  *
  1508.  * Side effects:
  1509.  * See the user documentation.
  1510.  *
  1511.  *----------------------------------------------------------------------
  1512.  */
  1513. static int
  1514. WmGeometryCmd(tkwin, winPtr, interp, objc, objv)
  1515.     Tk_Window tkwin; /* Main window of the application. */
  1516.     TkWindow *winPtr;           /* Toplevel to work with */
  1517.     Tcl_Interp *interp; /* Current interpreter. */
  1518.     int objc; /* Number of arguments. */
  1519.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1520. {
  1521.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1522.     char xSign, ySign;
  1523.     int width, height;
  1524.     char *argv3;
  1525.     if ((objc != 3) && (objc != 4)) {
  1526. Tcl_WrongNumArgs(interp, 2, objv, "window ?newGeometry?");
  1527. return TCL_ERROR;
  1528.     }
  1529.     if (objc == 3) {
  1530. char buf[16 + TCL_INTEGER_SPACE * 4];
  1531. xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+';
  1532. ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+';
  1533. if (wmPtr->gridWin != NULL) {
  1534.     width = wmPtr->reqGridWidth + (winPtr->changes.width
  1535.     - winPtr->reqWidth)/wmPtr->widthInc;
  1536.     height = wmPtr->reqGridHeight + (winPtr->changes.height
  1537.     - winPtr->reqHeight)/wmPtr->heightInc;
  1538. } else {
  1539.     width = winPtr->changes.width;
  1540.     height = winPtr->changes.height;
  1541. }
  1542. sprintf(buf, "%dx%d%c%d%c%d", width, height, xSign, wmPtr->x,
  1543. ySign, wmPtr->y);
  1544. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  1545. return TCL_OK;
  1546.     }
  1547.     argv3 = Tcl_GetString(objv[3]);
  1548.     if (*argv3 == '') {
  1549. wmPtr->width = -1;
  1550. wmPtr->height = -1;
  1551. WmUpdateGeom(wmPtr, winPtr);
  1552. return TCL_OK;
  1553.     }
  1554.     return ParseGeometry(interp, argv3, winPtr);
  1555. }
  1556. /*
  1557.  *----------------------------------------------------------------------
  1558.  *
  1559.  * WmGridCmd --
  1560.  *
  1561.  * This procedure is invoked to process the "wm grid" Tcl command.
  1562.  * See the user documentation for details on what it does.
  1563.  *
  1564.  * Results:
  1565.  * A standard Tcl result.
  1566.  *
  1567.  * Side effects:
  1568.  * See the user documentation.
  1569.  *
  1570.  *----------------------------------------------------------------------
  1571.  */
  1572. static int
  1573. WmGridCmd(tkwin, winPtr, interp, objc, objv)
  1574.     Tk_Window tkwin; /* Main window of the application. */
  1575.     TkWindow *winPtr;           /* Toplevel to work with */
  1576.     Tcl_Interp *interp; /* Current interpreter. */
  1577.     int objc; /* Number of arguments. */
  1578.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1579. {
  1580.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1581.     int reqWidth, reqHeight, widthInc, heightInc;
  1582.     if ((objc != 3) && (objc != 7)) {
  1583. Tcl_WrongNumArgs(interp, 2, objv,
  1584. "window ?baseWidth baseHeight widthInc heightInc?");
  1585. return TCL_ERROR;
  1586.     }
  1587.     if (objc == 3) {
  1588. if (wmPtr->sizeHintsFlags & PBaseSize) {
  1589.     char buf[TCL_INTEGER_SPACE * 4];
  1590.     sprintf(buf, "%d %d %d %d", wmPtr->reqGridWidth,
  1591.     wmPtr->reqGridHeight, wmPtr->widthInc,
  1592.     wmPtr->heightInc);
  1593.     Tcl_SetResult(interp, buf, TCL_VOLATILE);
  1594. }
  1595. return TCL_OK;
  1596.     }
  1597.     if (*Tcl_GetString(objv[3]) == '') {
  1598. /*
  1599.  * Turn off gridding and reset the width and height
  1600.  * to make sense as ungridded numbers.
  1601.  */
  1602. wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc);
  1603. if (wmPtr->width != -1) {
  1604.     wmPtr->width = winPtr->reqWidth + (wmPtr->width
  1605.     - wmPtr->reqGridWidth)*wmPtr->widthInc;
  1606.     wmPtr->height = winPtr->reqHeight + (wmPtr->height
  1607.     - wmPtr->reqGridHeight)*wmPtr->heightInc;
  1608. }
  1609. wmPtr->widthInc = 1;
  1610. wmPtr->heightInc = 1;
  1611.     } else {
  1612. if ((Tcl_GetIntFromObj(interp, objv[3], &reqWidth) != TCL_OK)
  1613. || (Tcl_GetIntFromObj(interp, objv[4], &reqHeight) != TCL_OK)
  1614. || (Tcl_GetIntFromObj(interp, objv[5], &widthInc) != TCL_OK)
  1615. || (Tcl_GetIntFromObj(interp, objv[6], &heightInc) != TCL_OK)) {
  1616.     return TCL_ERROR;
  1617. }
  1618. if (reqWidth < 0) {
  1619.     Tcl_SetResult(interp, "baseWidth can't be < 0", TCL_STATIC);
  1620.     return TCL_ERROR;
  1621. }
  1622. if (reqHeight < 0) {
  1623.     Tcl_SetResult(interp, "baseHeight can't be < 0", TCL_STATIC);
  1624.     return TCL_ERROR;
  1625. }
  1626. if (widthInc <= 0) {
  1627.     Tcl_SetResult(interp, "widthInc can't be <= 0", TCL_STATIC);
  1628.     return TCL_ERROR;
  1629. }
  1630. if (heightInc <= 0) {
  1631.     Tcl_SetResult(interp, "heightInc can't be <= 0", TCL_STATIC);
  1632.     return TCL_ERROR;
  1633. }
  1634. Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,
  1635. heightInc);
  1636.     }
  1637.     wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
  1638.     WmUpdateGeom(wmPtr, winPtr);
  1639.     return TCL_OK;
  1640. }
  1641. /*
  1642.  *----------------------------------------------------------------------
  1643.  *
  1644.  * WmGroupCmd --
  1645.  *
  1646.  * This procedure is invoked to process the "wm group" Tcl command.
  1647.  * See the user documentation for details on what it does.
  1648.  *
  1649.  * Results:
  1650.  * A standard Tcl result.
  1651.  *
  1652.  * Side effects:
  1653.  * See the user documentation.
  1654.  *
  1655.  *----------------------------------------------------------------------
  1656.  */
  1657. static int
  1658. WmGroupCmd(tkwin, winPtr, interp, objc, objv)
  1659.     Tk_Window tkwin; /* Main window of the application. */
  1660.     TkWindow *winPtr;           /* Toplevel to work with */
  1661.     Tcl_Interp *interp; /* Current interpreter. */
  1662.     int objc; /* Number of arguments. */
  1663.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1664. {
  1665.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1666.     Tk_Window tkwin2;
  1667.     WmInfo *wmPtr2;
  1668.     char *argv3;
  1669.     int length;
  1670.     if ((objc != 3) && (objc != 4)) {
  1671. Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?");
  1672. return TCL_ERROR;
  1673.     }
  1674.     if (objc == 3) {
  1675. if (wmPtr->hints.flags & WindowGroupHint) {
  1676.     Tcl_SetResult(interp, wmPtr->leaderName, TCL_STATIC);
  1677. }
  1678. return TCL_OK;
  1679.     }
  1680.     argv3 = Tcl_GetStringFromObj(objv[3], &length);
  1681.     if (*argv3 == '') {
  1682. wmPtr->hints.flags &= ~WindowGroupHint;
  1683. if (wmPtr->leaderName != NULL) {
  1684.     ckfree(wmPtr->leaderName);
  1685. }
  1686. wmPtr->leaderName = NULL;
  1687.     } else {
  1688. if (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) {
  1689.     return TCL_ERROR;
  1690. }
  1691. while (!Tk_TopWinHierarchy(tkwin2)) {
  1692.     /*
  1693.      * Ensure that the group leader is actually a Tk toplevel.
  1694.      */
  1695.     tkwin2 = Tk_Parent(tkwin2);
  1696. }
  1697. Tk_MakeWindowExist(tkwin2);
  1698. wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;
  1699. if (wmPtr2->wrapperPtr == NULL) {
  1700.     CreateWrapper(wmPtr2);
  1701. }
  1702. if (wmPtr->leaderName != NULL) {
  1703.     ckfree(wmPtr->leaderName);
  1704. }
  1705. wmPtr->hints.window_group = Tk_WindowId(wmPtr2->wrapperPtr);
  1706. wmPtr->hints.flags |= WindowGroupHint;
  1707. wmPtr->leaderName = ckalloc((unsigned) (length + 1));
  1708. strcpy(wmPtr->leaderName, argv3);
  1709.     }
  1710.     UpdateHints(winPtr);
  1711.     return TCL_OK;
  1712. }
  1713. /*
  1714.  *----------------------------------------------------------------------
  1715.  *
  1716.  * WmIconbitmapCmd --
  1717.  *
  1718.  * This procedure is invoked to process the "wm iconbitmap" Tcl command.
  1719.  * See the user documentation for details on what it does.
  1720.  *
  1721.  * Results:
  1722.  * A standard Tcl result.
  1723.  *
  1724.  * Side effects:
  1725.  * See the user documentation.
  1726.  *
  1727.  *----------------------------------------------------------------------
  1728.  */
  1729. static int
  1730. WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv)
  1731.     Tk_Window tkwin; /* Main window of the application. */
  1732.     TkWindow *winPtr;           /* Toplevel to work with */
  1733.     Tcl_Interp *interp; /* Current interpreter. */
  1734.     int objc; /* Number of arguments. */
  1735.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1736. {
  1737.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1738.     Pixmap pixmap;
  1739.     char *argv3;
  1740.     if ((objc < 3) || (objc > 4)) {
  1741. Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?");
  1742. return TCL_ERROR;
  1743.     }
  1744.     if (objc == 3) {
  1745. if (wmPtr->hints.flags & IconPixmapHint) {
  1746.     Tcl_SetResult(interp, (char *)
  1747.     Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_pixmap),
  1748.     TCL_STATIC);
  1749. }
  1750. return TCL_OK;
  1751.     }
  1752.     argv3 = Tcl_GetString(objv[3]);
  1753.     if (*argv3 == '') {
  1754. if (wmPtr->hints.icon_pixmap != None) {
  1755.     Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
  1756.     wmPtr->hints.icon_pixmap = None;
  1757. }
  1758. wmPtr->hints.flags &= ~IconPixmapHint;
  1759.     } else {
  1760. pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr, argv3);
  1761. if (pixmap == None) {
  1762.     return TCL_ERROR;
  1763. }
  1764. wmPtr->hints.icon_pixmap = pixmap;
  1765. wmPtr->hints.flags |= IconPixmapHint;
  1766.     }
  1767.     UpdateHints(winPtr);
  1768.     return TCL_OK;
  1769. }
  1770. /*
  1771.  *----------------------------------------------------------------------
  1772.  *
  1773.  * WmIconifyCmd --
  1774.  *
  1775.  * This procedure is invoked to process the "wm iconify" Tcl command.
  1776.  * See the user documentation for details on what it does.
  1777.  *
  1778.  * Results:
  1779.  * A standard Tcl result.
  1780.  *
  1781.  * Side effects:
  1782.  * See the user documentation.
  1783.  *
  1784.  *----------------------------------------------------------------------
  1785.  */
  1786. static int
  1787. WmIconifyCmd(tkwin, winPtr, interp, objc, objv)
  1788.     Tk_Window tkwin; /* Main window of the application. */
  1789.     TkWindow *winPtr;           /* Toplevel to work with */
  1790.     Tcl_Interp *interp; /* Current interpreter. */
  1791.     int objc; /* Number of arguments. */
  1792.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1793. {
  1794.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1795.     if (objc != 3) {
  1796. Tcl_WrongNumArgs(interp, 2, objv, "window");
  1797. return TCL_ERROR;
  1798.     }
  1799.     if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
  1800. Tcl_AppendResult(interp, "can't iconify "", winPtr->pathName,
  1801. "": override-redirect flag is set", (char *) NULL);
  1802. return TCL_ERROR;
  1803.     }
  1804.     if (wmPtr->masterPtr != NULL) {
  1805. Tcl_AppendResult(interp, "can't iconify "", winPtr->pathName,
  1806. "": it is a transient", (char *) NULL);
  1807. return TCL_ERROR;
  1808.     }
  1809.     if (wmPtr->iconFor != NULL) {
  1810. Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName,
  1811. ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
  1812. (char *) NULL);
  1813. return TCL_ERROR;
  1814.     }
  1815.     if (winPtr->flags & TK_EMBEDDED) {
  1816. Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName,
  1817. ": it is an embedded window", (char *) NULL);
  1818. return TCL_ERROR;
  1819.     }
  1820.     if (TkpWmSetState(winPtr, IconicState) == 0) {
  1821. Tcl_SetResult(interp,
  1822. "couldn't send iconify message to window manager",
  1823. TCL_STATIC);
  1824. return TCL_ERROR;
  1825.     }
  1826.     return TCL_OK;
  1827. }
  1828. /*
  1829.  *----------------------------------------------------------------------
  1830.  *
  1831.  * WmIconmaskCmd --
  1832.  *
  1833.  * This procedure is invoked to process the "wm iconmask" Tcl command.
  1834.  * See the user documentation for details on what it does.
  1835.  *
  1836.  * Results:
  1837.  * A standard Tcl result.
  1838.  *
  1839.  * Side effects:
  1840.  * See the user documentation.
  1841.  *
  1842.  *----------------------------------------------------------------------
  1843.  */
  1844. static int
  1845. WmIconmaskCmd(tkwin, winPtr, interp, objc, objv)
  1846.     Tk_Window tkwin; /* Main window of the application. */
  1847.     TkWindow *winPtr;           /* Toplevel to work with */
  1848.     Tcl_Interp *interp; /* Current interpreter. */
  1849.     int objc; /* Number of arguments. */
  1850.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1851. {
  1852.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1853.     Pixmap pixmap;
  1854.     char *argv3;
  1855.     if ((objc != 3) && (objc != 4)) {
  1856. Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?");
  1857. return TCL_ERROR;
  1858.     }
  1859.     if (objc == 3) {
  1860. if (wmPtr->hints.flags & IconMaskHint) {
  1861.     Tcl_SetResult(interp, (char *)
  1862.     Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_mask),
  1863.     TCL_STATIC);
  1864. }
  1865. return TCL_OK;
  1866.     }
  1867.     argv3 = Tcl_GetString(objv[3]);
  1868.     if (*argv3 == '') {
  1869. if (wmPtr->hints.icon_mask != None) {
  1870.     Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);
  1871. }
  1872. wmPtr->hints.flags &= ~IconMaskHint;
  1873.     } else {
  1874. pixmap = Tk_GetBitmap(interp, tkwin, argv3);
  1875. if (pixmap == None) {
  1876.     return TCL_ERROR;
  1877. }
  1878. wmPtr->hints.icon_mask = pixmap;
  1879. wmPtr->hints.flags |= IconMaskHint;
  1880.     }
  1881.     UpdateHints(winPtr);
  1882.     return TCL_OK;
  1883. }
  1884. /*
  1885.  *----------------------------------------------------------------------
  1886.  *
  1887.  * WmIconnameCmd --
  1888.  *
  1889.  * This procedure is invoked to process the "wm iconname" Tcl command.
  1890.  * See the user documentation for details on what it does.
  1891.  *
  1892.  * Results:
  1893.  * A standard Tcl result.
  1894.  *
  1895.  * Side effects:
  1896.  * See the user documentation.
  1897.  *
  1898.  *----------------------------------------------------------------------
  1899.  */
  1900. static int
  1901. WmIconnameCmd(tkwin, winPtr, interp, objc, objv)
  1902.     Tk_Window tkwin; /* Main window of the application. */
  1903.     TkWindow *winPtr;           /* Toplevel to work with */
  1904.     Tcl_Interp *interp; /* Current interpreter. */
  1905.     int objc; /* Number of arguments. */
  1906.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1907. {
  1908.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1909.     char *argv3;
  1910.     int length;
  1911.     if (objc > 4) {
  1912. Tcl_WrongNumArgs(interp, 2, objv, "window ?newName?");
  1913. return TCL_ERROR;
  1914.     }
  1915.     if (objc == 3) {
  1916. Tcl_SetResult(interp,
  1917. ((wmPtr->iconName != NULL) ? wmPtr->iconName : ""),
  1918. TCL_STATIC);
  1919. return TCL_OK;
  1920.     } else {
  1921. if (wmPtr->iconName != NULL) {
  1922.     ckfree((char *) wmPtr->iconName);
  1923. }
  1924. argv3 = Tcl_GetStringFromObj(objv[3], &length);
  1925. wmPtr->iconName = ckalloc((unsigned) (length + 1));
  1926. strcpy(wmPtr->iconName, argv3);
  1927. if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  1928.     UpdateTitle(winPtr);
  1929. }
  1930.     }
  1931.     return TCL_OK;
  1932. }
  1933. /*
  1934.  *----------------------------------------------------------------------
  1935.  *
  1936.  * WmIconphotoCmd --
  1937.  *
  1938.  * This procedure is invoked to process the "wm iconphoto"
  1939.  * Tcl command.
  1940.  * See the user documentation for details on what it does.
  1941.  *
  1942.  * Results:
  1943.  * A standard Tcl result.
  1944.  *
  1945.  * Side effects:
  1946.  * See the user documentation.
  1947.  *
  1948.  *----------------------------------------------------------------------
  1949.  */
  1950. static int
  1951. WmIconphotoCmd(tkwin, winPtr, interp, objc, objv)
  1952.     Tk_Window tkwin; /* Main window of the application. */
  1953.     TkWindow *winPtr;           /* Toplevel to work with */
  1954.     Tcl_Interp *interp; /* Current interpreter. */
  1955.     int objc; /* Number of arguments. */
  1956.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1957. {
  1958.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1959.     Tk_PhotoHandle photo;
  1960.     Tk_PhotoImageBlock block;
  1961.     int i, size = 0, width, height, index = 0, x, y, isDefault = 0;
  1962.     long R, G, B, A;
  1963.     long *iconPropertyData;
  1964.     unsigned char *pixelByte;
  1965.     if (objc < 4) {
  1966. Tcl_WrongNumArgs(interp, 2, objv,
  1967. "window ?-default? image1 ?image2 ...?");
  1968. return TCL_ERROR;
  1969.     }
  1970.     if (strcmp(Tcl_GetString(objv[3]), "-default") == 0) {
  1971. isDefault = 1;
  1972. if (objc == 4) {
  1973.     Tcl_WrongNumArgs(interp, 2, objv,
  1974.     "window ?-default? image1 ?image2 ...?");
  1975.     return TCL_ERROR;
  1976. }
  1977.     }
  1978.     /*
  1979.      * Iterate over all images to retrieve their sizes, in order to allocate a
  1980.      * buffer large enough to hold all images.
  1981.      */
  1982.     for (i = 3 + isDefault; i < objc; i++) {
  1983. photo = Tk_FindPhoto(interp, Tcl_GetString(objv[i]));
  1984. if (photo == NULL) {
  1985.     Tcl_AppendResult(interp, "can't use "", Tcl_GetString(objv[i]),
  1986.     "" as iconphoto: not a photo image", (char *) NULL);
  1987.     return TCL_ERROR;
  1988. }
  1989. Tk_PhotoGetSize(photo, &width, &height);
  1990. /* We need to cardinals for width & height and one cardinal for each
  1991.  * image pixel. */
  1992. size += 2 + width * height;
  1993.     }
  1994.     /* We have calculated the size of the data. Try to allocate the needed
  1995.      * memory space. */
  1996.     iconPropertyData = (long *) Tcl_AttemptAlloc(sizeof(long)*size);
  1997.     if (iconPropertyData == NULL) {
  1998. return TCL_ERROR;
  1999.     }
  2000.     memset(iconPropertyData, 0, sizeof(long)*size);
  2001.     for (i = 3 + isDefault; i < objc; i++) {
  2002. photo = Tk_FindPhoto(interp, Tcl_GetString(objv[i]));
  2003. if (photo == NULL) {
  2004.     Tcl_Free((char *) iconPropertyData);
  2005.     return TCL_ERROR;
  2006. }
  2007. Tk_PhotoGetSize(photo, &width, &height);
  2008. Tk_PhotoGetImage(photo, &block);
  2009. /*
  2010.  * Each image data will be placed as an array of 32bit packed
  2011.  * CARDINAL, in a window property named "_NET_WM_ICON":
  2012.  * _NET_WM_ICON
  2013.  *
  2014.  * _NET_WM_ICON CARDINAL[][2+n]/32
  2015.  *
  2016.  * This is an array of possible icons for the client.
  2017.  * This specification does not stipulate what size these icons should
  2018.  * be, but individual desktop environments or toolkits may do so.
  2019.  * The Window Manager MAY scale any of these icons to an appropriate
  2020.  * size.
  2021.  *
  2022.  * This is an array of 32bit packed CARDINAL ARGB with high byte being
  2023.  * A, low byte being B. The first two cardinals are width, height.
  2024.  * Data is in rows, left to right and top to bottom.
  2025.  */
  2026. /*
  2027.  * Encode the image data in the iconPropertyData array.
  2028.  */
  2029. iconPropertyData[index++] = width;
  2030. iconPropertyData[index++] = height;
  2031. for (y = 0; y < height; y++) {
  2032.     for (x = 0; x < width; x++) {
  2033. R = *(block.pixelPtr + x*block.pixelSize +
  2034. y*block.pitch + block.offset[0]);
  2035. G = *(block.pixelPtr + x*block.pixelSize +
  2036. y*block.pitch + block.offset[1]);
  2037. B = *(block.pixelPtr + x*block.pixelSize +
  2038. y*block.pitch + block.offset[2]);
  2039. A = *(block.pixelPtr + x*block.pixelSize +
  2040. y*block.pitch + block.offset[3]);
  2041. pixelByte = (unsigned char *) &iconPropertyData[index];
  2042. pixelByte[3] = A;
  2043. pixelByte[2] = R;
  2044. pixelByte[1] = G;
  2045. pixelByte[0] = B;
  2046. index++;
  2047.     }
  2048. }
  2049.     }
  2050.     if (wmPtr->iconDataPtr != NULL) {
  2051. ckfree((char *)wmPtr->iconDataPtr);
  2052. wmPtr->iconDataPtr = NULL;
  2053.     }
  2054.     if (isDefault) {
  2055. if (winPtr->dispPtr->iconDataPtr != NULL) {
  2056.     ckfree((char *) winPtr->dispPtr->iconDataPtr);
  2057. }
  2058. winPtr->dispPtr->iconDataPtr  = (unsigned char *) iconPropertyData;
  2059. winPtr->dispPtr->iconDataSize = size;
  2060.     } else {
  2061. wmPtr->iconDataPtr  = (unsigned char *) iconPropertyData;
  2062. wmPtr->iconDataSize = size;
  2063.     }
  2064.     if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  2065. UpdatePhotoIcon(winPtr);
  2066.     }
  2067.     return TCL_OK;
  2068. }
  2069. /*
  2070.  *----------------------------------------------------------------------
  2071.  *
  2072.  * WmIconpositionCmd --
  2073.  *
  2074.  * This procedure is invoked to process the "wm iconposition"
  2075.  * Tcl command.
  2076.  * See the user documentation for details on what it does.
  2077.  *
  2078.  * Results:
  2079.  * A standard Tcl result.
  2080.  *
  2081.  * Side effects:
  2082.  * See the user documentation.
  2083.  *
  2084.  *----------------------------------------------------------------------
  2085.  */
  2086. static int
  2087. WmIconpositionCmd(tkwin, winPtr, interp, objc, objv)
  2088.     Tk_Window tkwin; /* Main window of the application. */
  2089.     TkWindow *winPtr;           /* Toplevel to work with */
  2090.     Tcl_Interp *interp; /* Current interpreter. */
  2091.     int objc; /* Number of arguments. */
  2092.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2093. {
  2094.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2095.     int x, y;
  2096.     if ((objc != 3) && (objc != 5)) {
  2097. Tcl_WrongNumArgs(interp, 2, objv, "window ?x y?");
  2098. return TCL_ERROR;
  2099.     }
  2100.     if (objc == 3) {
  2101. if (wmPtr->hints.flags & IconPositionHint) {
  2102.     char buf[TCL_INTEGER_SPACE * 2];
  2103.     sprintf(buf, "%d %d", wmPtr->hints.icon_x,
  2104.     wmPtr->hints.icon_y);
  2105.     Tcl_SetResult(interp, buf, TCL_VOLATILE);
  2106. }
  2107. return TCL_OK;
  2108.     }
  2109.     if (*Tcl_GetString(objv[3]) == '') {
  2110. wmPtr->hints.flags &= ~IconPositionHint;
  2111.     } else {
  2112. if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)
  2113. || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)){
  2114.     return TCL_ERROR;
  2115. }
  2116. wmPtr->hints.icon_x = x;
  2117. wmPtr->hints.icon_y = y;
  2118. wmPtr->hints.flags |= IconPositionHint;
  2119.     }
  2120.     UpdateHints(winPtr);
  2121.     return TCL_OK;
  2122. }
  2123. /*
  2124.  *----------------------------------------------------------------------
  2125.  *
  2126.  * WmIconwindowCmd --
  2127.  *
  2128.  * This procedure is invoked to process the "wm iconwindow" Tcl command.
  2129.  * See the user documentation for details on what it does.
  2130.  *
  2131.  * Results:
  2132.  * A standard Tcl result.
  2133.  *
  2134.  * Side effects:
  2135.  * See the user documentation.
  2136.  *
  2137.  *----------------------------------------------------------------------
  2138.  */
  2139. static int
  2140. WmIconwindowCmd(tkwin, winPtr, interp, objc, objv)
  2141.     Tk_Window tkwin; /* Main window of the application. */
  2142.     TkWindow *winPtr;           /* Toplevel to work with */
  2143.     Tcl_Interp *interp; /* Current interpreter. */
  2144.     int objc; /* Number of arguments. */
  2145.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2146. {
  2147.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2148.     Tk_Window tkwin2;
  2149.     WmInfo *wmPtr2;
  2150.     XSetWindowAttributes atts;
  2151.     if ((objc != 3) && (objc != 4)) {
  2152. Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?");
  2153. return TCL_ERROR;
  2154.     }
  2155.     if (objc == 3) {
  2156. if (wmPtr->icon != NULL) {
  2157.     Tcl_SetResult(interp, Tk_PathName(wmPtr->icon), TCL_STATIC);
  2158. }
  2159. return TCL_OK;
  2160.     }
  2161.     if (*Tcl_GetString(objv[3]) == '') {
  2162. wmPtr->hints.flags &= ~IconWindowHint;
  2163. if (wmPtr->icon != NULL) {
  2164.     /*
  2165.      * Remove the icon window relationship.  In principle we
  2166.      * should also re-enable button events for the window, but
  2167.      * this doesn't work in general because the window manager
  2168.      * is probably selecting on them (we'll get an error if
  2169.      * we try to re-enable the events).  So, just leave the
  2170.      * icon window event-challenged;  the user will have to
  2171.      * recreate it if they want button events.
  2172.      */
  2173.     wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
  2174.     wmPtr2->iconFor = NULL;
  2175.     wmPtr2->withdrawn = 1;
  2176.     wmPtr2->hints.initial_state = WithdrawnState;
  2177. }
  2178. wmPtr->icon = NULL;
  2179.     } else {
  2180. if (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) {
  2181.     return TCL_ERROR;
  2182. }
  2183. if (!Tk_IsTopLevel(tkwin2)) {
  2184.     Tcl_AppendResult(interp, "can't use ", Tcl_GetString(objv[3]),
  2185.     " as icon window: not at top level", (char *) NULL);
  2186.     return TCL_ERROR;
  2187. }
  2188. wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;
  2189. if (wmPtr2->iconFor != NULL) {
  2190.     Tcl_AppendResult(interp, Tcl_GetString(objv[3]),
  2191.     " is already an icon for ",
  2192.     Tk_PathName(wmPtr2->iconFor), (char *) NULL);
  2193.     return TCL_ERROR;
  2194. }
  2195. if (wmPtr->icon != NULL) {
  2196.     WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
  2197.     wmPtr3->iconFor = NULL;
  2198.     wmPtr3->withdrawn = 1;
  2199.     wmPtr3->hints.initial_state = WithdrawnState;
  2200. }
  2201. /*
  2202.  * Disable button events in the icon window:  some window
  2203.  * managers (like olvwm) want to get the events themselves,
  2204.  * but X only allows one application at a time to receive
  2205.  * button events for a window.
  2206.  */
  2207. atts.event_mask = Tk_Attributes(tkwin2)->event_mask
  2208. & ~ButtonPressMask;
  2209. Tk_ChangeWindowAttributes(tkwin2, CWEventMask, &atts);
  2210. Tk_MakeWindowExist(tkwin2);
  2211. if (wmPtr2->wrapperPtr == NULL) {
  2212.     CreateWrapper(wmPtr2);
  2213. }
  2214. wmPtr->hints.icon_window = Tk_WindowId(wmPtr2->wrapperPtr);
  2215. wmPtr->hints.flags |= IconWindowHint;
  2216. wmPtr->icon = tkwin2;
  2217. wmPtr2->iconFor = (Tk_Window) winPtr;
  2218. if (!wmPtr2->withdrawn && !(wmPtr2->flags & WM_NEVER_MAPPED)) {
  2219.     wmPtr2->withdrawn = 0;
  2220.     if (XWithdrawWindow(Tk_Display(tkwin2),
  2221.     Tk_WindowId(wmPtr2->wrapperPtr),
  2222.     Tk_ScreenNumber(tkwin2)) == 0) {
  2223. Tcl_SetResult(interp,
  2224. "couldn't send withdraw message to window manager",
  2225. TCL_STATIC);
  2226. return TCL_ERROR;
  2227.     }
  2228.     WaitForMapNotify((TkWindow *) tkwin2, 0);
  2229. }
  2230.     }
  2231.     UpdateHints(winPtr);
  2232.     return TCL_OK;
  2233. }
  2234. /*
  2235.  *----------------------------------------------------------------------
  2236.  *
  2237.  * WmMaxsizeCmd --
  2238.  *
  2239.  * This procedure is invoked to process the "wm maxsize" Tcl command.
  2240.  * See the user documentation for details on what it does.
  2241.  *
  2242.  * Results:
  2243.  * A standard Tcl result.
  2244.  *
  2245.  * Side effects:
  2246.  * See the user documentation.
  2247.  *
  2248.  *----------------------------------------------------------------------
  2249.  */
  2250. static int
  2251. WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv)
  2252.     Tk_Window tkwin; /* Main window of the application. */
  2253.     TkWindow *winPtr;           /* Toplevel to work with */
  2254.     Tcl_Interp *interp; /* Current interpreter. */
  2255.     int objc; /* Number of arguments. */
  2256.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2257. {
  2258.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2259.     int width, height;
  2260.     if ((objc != 3) && (objc != 5)) {
  2261. Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
  2262. return TCL_ERROR;
  2263.     }
  2264.     if (objc == 3) {
  2265. char buf[TCL_INTEGER_SPACE * 2];
  2266. GetMaxSize(wmPtr, &width, &height);
  2267. sprintf(buf, "%d %d", width, height);
  2268. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  2269. return TCL_OK;
  2270.     }
  2271.     if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK)
  2272.     || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) {
  2273. return TCL_ERROR;
  2274.     }
  2275.     wmPtr->maxWidth = width;
  2276.     wmPtr->maxHeight = height;
  2277.     wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
  2278.     if (width <= 0 && height <= 0) {
  2279. wmPtr->sizeHintsFlags &= ~PMaxSize;
  2280.     } else {
  2281. wmPtr->sizeHintsFlags |= PMaxSize;
  2282.     }
  2283.     WmUpdateGeom(wmPtr, winPtr);
  2284.     return TCL_OK;
  2285. }
  2286. /*
  2287.  *----------------------------------------------------------------------
  2288.  *
  2289.  * WmMinsizeCmd --
  2290.  *
  2291.  * This procedure is invoked to process the "wm minsize" Tcl command.
  2292.  * See the user documentation for details on what it does.
  2293.  *
  2294.  * Results:
  2295.  * A standard Tcl result.
  2296.  *
  2297.  * Side effects:
  2298.  * See the user documentation.
  2299.  *
  2300.  *----------------------------------------------------------------------
  2301.  */
  2302. static int
  2303. WmMinsizeCmd(tkwin, winPtr, interp, objc, objv)
  2304.     Tk_Window tkwin; /* Main window of the application. */
  2305.     TkWindow *winPtr;           /* Toplevel to work with */
  2306.     Tcl_Interp *interp; /* Current interpreter. */
  2307.     int objc; /* Number of arguments. */
  2308.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2309. {
  2310.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2311.     int width, height;
  2312.     if ((objc != 3) && (objc != 5)) {
  2313. Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
  2314. return TCL_ERROR;
  2315.     }
  2316.     if (objc == 3) {
  2317. char buf[TCL_INTEGER_SPACE * 2];
  2318. sprintf(buf, "%d %d", wmPtr->minWidth, wmPtr->minHeight);
  2319. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  2320. return TCL_OK;
  2321.     }
  2322.     if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK)
  2323.     || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) {
  2324. return TCL_ERROR;
  2325.     }
  2326.     wmPtr->minWidth = width;
  2327.     wmPtr->minHeight = height;
  2328.     wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
  2329.     WmUpdateGeom(wmPtr, winPtr);
  2330.     return TCL_OK;
  2331. }
  2332. /*
  2333.  *----------------------------------------------------------------------
  2334.  *
  2335.  * WmOverrideredirectCmd --
  2336.  *
  2337.  * This procedure is invoked to process the "wm overrideredirect"
  2338.  * Tcl command.
  2339.  * See the user documentation for details on what it does.
  2340.  *
  2341.  * Results:
  2342.  * A standard Tcl result.
  2343.  *
  2344.  * Side effects:
  2345.  * See the user documentation.
  2346.  *
  2347.  *----------------------------------------------------------------------
  2348.  */
  2349. static int
  2350. WmOverrideredirectCmd(tkwin, winPtr, interp, objc, objv)
  2351.     Tk_Window tkwin; /* Main window of the application. */
  2352.     TkWindow *winPtr;           /* Toplevel to work with */
  2353.     Tcl_Interp *interp; /* Current interpreter. */
  2354.     int objc; /* Number of arguments. */
  2355.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2356. {
  2357.     int boolean, curValue;
  2358.     XSetWindowAttributes atts;
  2359.     if ((objc != 3) && (objc != 4)) {
  2360. Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?");
  2361. return TCL_ERROR;
  2362.     }
  2363.     curValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect;
  2364.     if (objc == 3) {
  2365. Tcl_SetBooleanObj(Tcl_GetObjResult(interp), curValue);
  2366. return TCL_OK;
  2367.     }
  2368.     if (Tcl_GetBooleanFromObj(interp, objv[3], &boolean) != TCL_OK) {
  2369. return TCL_ERROR;
  2370.     }
  2371.     if (curValue != boolean) {
  2372. /*
  2373.  * Only do this if we are really changing value, because it
  2374.  * causes some funky stuff to occur
  2375.  */
  2376. atts.override_redirect = (boolean) ? True : False;
  2377. Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect,
  2378. &atts);
  2379. if (winPtr->wmInfoPtr->wrapperPtr != NULL) {
  2380.     Tk_ChangeWindowAttributes(
  2381.     (Tk_Window) winPtr->wmInfoPtr->wrapperPtr,
  2382.     CWOverrideRedirect, &atts);
  2383. }
  2384.     }
  2385.     return TCL_OK;
  2386. }
  2387. /*
  2388.  *----------------------------------------------------------------------
  2389.  *
  2390.  * WmPositionfromCmd --
  2391.  *
  2392.  * This procedure is invoked to process the "wm positionfrom"
  2393.  * Tcl command.
  2394.  * See the user documentation for details on what it does.
  2395.  *
  2396.  * Results:
  2397.  * A standard Tcl result.
  2398.  *
  2399.  * Side effects:
  2400.  * See the user documentation.
  2401.  *
  2402.  *----------------------------------------------------------------------
  2403.  */
  2404. static int
  2405. WmPositionfromCmd(tkwin, winPtr, interp, objc, objv)
  2406.     Tk_Window tkwin; /* Main window of the application. */
  2407.     TkWindow *winPtr;           /* Toplevel to work with */
  2408.     Tcl_Interp *interp; /* Current interpreter. */
  2409.     int objc; /* Number of arguments. */
  2410.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2411. {
  2412.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2413.     static CONST char *optionStrings[] = {
  2414. "program", "user", (char *) NULL };
  2415.     enum options {
  2416. OPT_PROGRAM, OPT_USER };
  2417.     int index;
  2418.     if ((objc != 3) && (objc != 4)) {
  2419. Tcl_WrongNumArgs(interp, 2, objv, "window ?user/program?");
  2420. return TCL_ERROR;
  2421.     }
  2422.     if (objc == 3) {
  2423. if (wmPtr->sizeHintsFlags & USPosition) {
  2424.     Tcl_SetResult(interp, "user", TCL_STATIC);
  2425. } else if (wmPtr->sizeHintsFlags & PPosition) {
  2426.     Tcl_SetResult(interp, "program", TCL_STATIC);
  2427. }
  2428. return TCL_OK;
  2429.     }
  2430.     if (*Tcl_GetString(objv[3]) == '') {
  2431. wmPtr->sizeHintsFlags &= ~(USPosition|PPosition);
  2432.     } else {
  2433. if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0,
  2434. &index) != TCL_OK) {
  2435.     return TCL_ERROR;
  2436. }
  2437. if (index == OPT_USER) {
  2438.     wmPtr->sizeHintsFlags &= ~PPosition;
  2439.     wmPtr->sizeHintsFlags |= USPosition;
  2440. } else {
  2441.     wmPtr->sizeHintsFlags &= ~USPosition;
  2442.     wmPtr->sizeHintsFlags |= PPosition;
  2443. }
  2444.     }
  2445.     wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
  2446.     WmUpdateGeom(wmPtr, winPtr);
  2447.     return TCL_OK;
  2448. }
  2449. /*
  2450.  *----------------------------------------------------------------------
  2451.  *
  2452.  * WmProtocolCmd --
  2453.  *
  2454.  * This procedure is invoked to process the "wm protocol" Tcl command.
  2455.  * See the user documentation for details on what it does.
  2456.  *
  2457.  * Results:
  2458.  * A standard Tcl result.
  2459.  *
  2460.  * Side effects:
  2461.  * See the user documentation.
  2462.  *
  2463.  *----------------------------------------------------------------------
  2464.  */
  2465. static int
  2466. WmProtocolCmd(tkwin, winPtr, interp, objc, objv)
  2467.     Tk_Window tkwin; /* Main window of the application. */
  2468.     TkWindow *winPtr;           /* Toplevel to work with */
  2469.     Tcl_Interp *interp; /* Current interpreter. */
  2470.     int objc; /* Number of arguments. */
  2471.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2472. {
  2473.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2474.     register ProtocolHandler *protPtr, *prevPtr;
  2475.     Atom protocol;
  2476.     char *cmd;
  2477.     int cmdLength;
  2478.     if ((objc < 3) || (objc > 5)) {
  2479. Tcl_WrongNumArgs(interp, 2, objv, "window ?name? ?command?");
  2480. return TCL_ERROR;
  2481.     }
  2482.     if (objc == 3) {
  2483. /*
  2484.  * Return a list of all defined protocols for the window.
  2485.  */
  2486. for (protPtr = wmPtr->protPtr; protPtr != NULL;
  2487.      protPtr = protPtr->nextPtr) {
  2488.     Tcl_AppendElement(interp,
  2489.     Tk_GetAtomName((Tk_Window) winPtr, protPtr->protocol));
  2490. }
  2491. return TCL_OK;
  2492.     }
  2493.     protocol = Tk_InternAtom((Tk_Window) winPtr, Tcl_GetString(objv[3]));
  2494.     if (objc == 4) {
  2495. /*
  2496.  * Return the command to handle a given protocol.
  2497.  */
  2498. for (protPtr = wmPtr->protPtr; protPtr != NULL;
  2499.      protPtr = protPtr->nextPtr) {
  2500.     if (protPtr->protocol == protocol) {
  2501. Tcl_SetResult(interp, protPtr->command, TCL_STATIC);
  2502. return TCL_OK;
  2503.     }
  2504. }
  2505. return TCL_OK;
  2506.     }
  2507.     /*
  2508.      * Delete any current protocol handler, then create a new
  2509.      * one with the specified command, unless the command is
  2510.      * empty.
  2511.      */
  2512.     for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL;
  2513.  prevPtr = protPtr, protPtr = protPtr->nextPtr) {
  2514. if (protPtr->protocol == protocol) {
  2515.     if (prevPtr == NULL) {
  2516. wmPtr->protPtr = protPtr->nextPtr;
  2517.     } else {
  2518. prevPtr->nextPtr = protPtr->nextPtr;
  2519.     }
  2520.     Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC);
  2521.     break;
  2522. }
  2523.     }
  2524.     cmd = Tcl_GetStringFromObj(objv[4], &cmdLength);
  2525.     if (cmdLength > 0) {
  2526. protPtr = (ProtocolHandler *) ckalloc(HANDLER_SIZE(cmdLength));
  2527. protPtr->protocol = protocol;
  2528. protPtr->nextPtr = wmPtr->protPtr;
  2529. wmPtr->protPtr = protPtr;
  2530. protPtr->interp = interp;
  2531. strcpy(protPtr->command, cmd);
  2532.     }
  2533.     if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  2534. UpdateWmProtocols(wmPtr);
  2535.     }
  2536.     return TCL_OK;
  2537. }
  2538. /*
  2539.  *----------------------------------------------------------------------
  2540.  *
  2541.  * WmResizableCmd --
  2542.  *
  2543.  * This procedure is invoked to process the "wm resizable" Tcl command.
  2544.  * See the user documentation for details on what it does.
  2545.  *
  2546.  * Results:
  2547.  * A standard Tcl result.
  2548.  *
  2549.  * Side effects:
  2550.  * See the user documentation.
  2551.  *
  2552.  *----------------------------------------------------------------------
  2553.  */
  2554. static int
  2555. WmResizableCmd(tkwin, winPtr, interp, objc, objv)
  2556.     Tk_Window tkwin; /* Main window of the application. */
  2557.     TkWindow *winPtr;           /* Toplevel to work with */
  2558.     Tcl_Interp *interp; /* Current interpreter. */
  2559.     int objc; /* Number of arguments. */
  2560.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2561. {
  2562.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2563.     int width, height;
  2564.     if ((objc != 3) && (objc != 5)) {
  2565. Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
  2566. return TCL_ERROR;
  2567.     }
  2568.     if (objc == 3) {
  2569. char buf[TCL_INTEGER_SPACE * 2];
  2570. sprintf(buf, "%d %d",
  2571. (wmPtr->flags  & WM_WIDTH_NOT_RESIZABLE) ? 0 : 1,
  2572. (wmPtr->flags  & WM_HEIGHT_NOT_RESIZABLE) ? 0 : 1);
  2573. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  2574. return TCL_OK;
  2575.     }
  2576.     if ((Tcl_GetBooleanFromObj(interp, objv[3], &width) != TCL_OK)
  2577.     || (Tcl_GetBooleanFromObj(interp, objv[4], &height) != TCL_OK)) {
  2578. return TCL_ERROR;
  2579.     }
  2580.     if (width) {
  2581. wmPtr->flags &= ~WM_WIDTH_NOT_RESIZABLE;
  2582.     } else {
  2583. wmPtr->flags |= WM_WIDTH_NOT_RESIZABLE;
  2584.     }
  2585.     if (height) {
  2586. wmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE;
  2587.     } else {
  2588. wmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE;
  2589.     }
  2590.     wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
  2591.     WmUpdateGeom(wmPtr, winPtr);
  2592.     return TCL_OK;
  2593. }
  2594. /*
  2595.  *----------------------------------------------------------------------
  2596.  *
  2597.  * WmSizefromCmd --
  2598.  *
  2599.  * This procedure is invoked to process the "wm sizefrom" Tcl command.
  2600.  * See the user documentation for details on what it does.
  2601.  *
  2602.  * Results:
  2603.  * A standard Tcl result.
  2604.  *
  2605.  * Side effects:
  2606.  * See the user documentation.
  2607.  *
  2608.  *----------------------------------------------------------------------
  2609.  */
  2610. static int
  2611. WmSizefromCmd(tkwin, winPtr, interp, objc, objv)
  2612.     Tk_Window tkwin; /* Main window of the application. */
  2613.     TkWindow *winPtr;           /* Toplevel to work with */
  2614.     Tcl_Interp *interp; /* Current interpreter. */
  2615.     int objc; /* Number of arguments. */
  2616.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2617. {
  2618.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2619.     static CONST char *optionStrings[] = {
  2620. "program", "user", (char *) NULL };
  2621.     enum options {
  2622. OPT_PROGRAM, OPT_USER };
  2623.     int index;
  2624.     if ((objc != 3) && (objc != 4)) {
  2625. Tcl_WrongNumArgs(interp, 2, objv, "window ?user|program?");
  2626. return TCL_ERROR;
  2627.     }
  2628.     if (objc == 3) {
  2629. if (wmPtr->sizeHintsFlags & USSize) {
  2630.     Tcl_SetResult(interp, "user", TCL_STATIC);
  2631. } else if (wmPtr->sizeHintsFlags & PSize) {
  2632.     Tcl_SetResult(interp, "program", TCL_STATIC);
  2633. }
  2634. return TCL_OK;
  2635.     }
  2636.     if (*Tcl_GetString(objv[3]) == '') {
  2637. wmPtr->sizeHintsFlags &= ~(USSize|PSize);
  2638.     } else {
  2639. if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0,
  2640. &index) != TCL_OK) {
  2641.     return TCL_ERROR;
  2642. }
  2643. if (index == OPT_USER) {
  2644.     wmPtr->sizeHintsFlags &= ~PSize;
  2645.     wmPtr->sizeHintsFlags |= USSize;
  2646. } else { /* OPT_PROGRAM */
  2647.     wmPtr->sizeHintsFlags &= ~USSize;
  2648.     wmPtr->sizeHintsFlags |= PSize;
  2649. }
  2650.     }
  2651.     wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
  2652.     WmUpdateGeom(wmPtr, winPtr);
  2653.     return TCL_OK;
  2654. }
  2655. /*
  2656.  *----------------------------------------------------------------------
  2657.  *
  2658.  * WmStackorderCmd --
  2659.  *
  2660.  * This procedure is invoked to process the "wm stackorder" Tcl command.
  2661.  * See the user documentation for details on what it does.
  2662.  *
  2663.  * Results:
  2664.  * A standard Tcl result.
  2665.  *
  2666.  * Side effects:
  2667.  * See the user documentation.
  2668.  *
  2669.  *----------------------------------------------------------------------
  2670.  */
  2671. static int
  2672. WmStackorderCmd(tkwin, winPtr, interp, objc, objv)
  2673.     Tk_Window tkwin; /* Main window of the application. */
  2674.     TkWindow *winPtr;           /* Toplevel to work with */
  2675.     Tcl_Interp *interp; /* Current interpreter. */
  2676.     int objc; /* Number of arguments. */
  2677.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2678. {
  2679.     TkWindow **windows, **window_ptr;
  2680.     static CONST char *optionStrings[] = {
  2681. "isabove", "isbelow", (char *) NULL };
  2682.     enum options {
  2683. OPT_ISABOVE, OPT_ISBELOW };
  2684.     int index;
  2685.     if ((objc != 3) && (objc != 5)) {
  2686. Tcl_WrongNumArgs(interp, 2, objv, "window ?isabove|isbelow window?");
  2687. return TCL_ERROR;
  2688.     }
  2689.     if (objc == 3) {
  2690. windows = TkWmStackorderToplevel(winPtr);
  2691. if (windows == NULL) {
  2692.     Tcl_Panic("TkWmStackorderToplevel failed");
  2693. } else {
  2694.     for (window_ptr = windows; *window_ptr ; window_ptr++) {
  2695. Tcl_AppendElement(interp, (*window_ptr)->pathName);
  2696.     }
  2697.     ckfree((char *) windows);
  2698.     return TCL_OK;
  2699. }
  2700.     } else {
  2701. TkWindow *winPtr2;
  2702. int index1=-1, index2=-1, result;
  2703. if (TkGetWindowFromObj(interp, tkwin, objv[4], (Tk_Window *) &winPtr2)
  2704. != TCL_OK) {
  2705.     return TCL_ERROR;
  2706. }
  2707. if (!Tk_IsTopLevel(winPtr2)) {
  2708.     Tcl_AppendResult(interp, "window "", winPtr2->pathName,
  2709.     "" isn't a top-level window", (char *) NULL);
  2710.     return TCL_ERROR;
  2711. }
  2712. if (!Tk_IsMapped(winPtr)) {
  2713.     Tcl_AppendResult(interp, "window "", winPtr->pathName,
  2714.     "" isn't mapped", (char *) NULL);
  2715.     return TCL_ERROR;
  2716. }
  2717. if (!Tk_IsMapped(winPtr2)) {
  2718.     Tcl_AppendResult(interp, "window "", winPtr2->pathName,
  2719.     "" isn't mapped", (char *) NULL);
  2720.     return TCL_ERROR;
  2721. }
  2722. /*
  2723.  * Lookup stacking order of all toplevels that are children
  2724.  * of "." and find the position of winPtr and winPtr2
  2725.  * in the stacking order.
  2726.  */
  2727. windows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr);
  2728. if (windows == NULL) {
  2729.     Tcl_AppendResult(interp, "TkWmStackorderToplevel failed",
  2730.                     (char *) NULL);
  2731.     return TCL_ERROR;
  2732. } else {
  2733.     for (window_ptr = windows; *window_ptr ; window_ptr++) {
  2734. if (*window_ptr == winPtr)
  2735.     index1 = (window_ptr - windows);
  2736. if (*window_ptr == winPtr2)
  2737.     index2 = (window_ptr - windows);
  2738.     }
  2739.     if (index1 == -1)
  2740. Tcl_Panic("winPtr window not found");
  2741.     if (index2 == -1)
  2742. Tcl_Panic("winPtr2 window not found");
  2743.     ckfree((char *) windows);
  2744. }
  2745. if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0,
  2746. &index) != TCL_OK) {
  2747.     return TCL_ERROR;
  2748. }
  2749. if (index == OPT_ISABOVE) {
  2750.     result = index1 > index2;
  2751. } else { /* OPT_ISBELOW */
  2752.     result = index1 < index2;
  2753. }
  2754. Tcl_SetIntObj(Tcl_GetObjResult(interp), result);
  2755. return TCL_OK;
  2756.     }
  2757.     return TCL_OK;
  2758. }
  2759. /*
  2760.  *----------------------------------------------------------------------
  2761.  *
  2762.  * WmStateCmd --
  2763.  *
  2764.  * This procedure is invoked to process the "wm state" Tcl command.
  2765.  * See the user documentation for details on what it does.
  2766.  *
  2767.  * Results:
  2768.  * A standard Tcl result.
  2769.  *
  2770.  * Side effects:
  2771.  * See the user documentation.
  2772.  *
  2773.  *----------------------------------------------------------------------
  2774.  */
  2775. static int
  2776. WmStateCmd(tkwin, winPtr, interp, objc, objv)
  2777.     Tk_Window tkwin; /* Main window of the application. */
  2778.     TkWindow *winPtr;           /* Toplevel to work with */
  2779.     Tcl_Interp *interp; /* Current interpreter. */
  2780.     int objc; /* Number of arguments. */
  2781.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2782. {
  2783.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2784.     static CONST char *optionStrings[] = {
  2785. "normal", "iconic", "withdrawn", (char *) NULL };
  2786.     enum options {
  2787. OPT_NORMAL, OPT_ICONIC, OPT_WITHDRAWN };
  2788.     int index;
  2789.     if ((objc < 3) || (objc > 4)) {
  2790. Tcl_WrongNumArgs(interp, 2, objv, "window ?state?");
  2791. return TCL_ERROR;
  2792.     }
  2793.     if (objc == 4) {
  2794. if (wmPtr->iconFor != NULL) {
  2795.     Tcl_AppendResult(interp, "can't change state of ",
  2796.     Tcl_GetString(objv[2]),
  2797.     ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
  2798.     (char *) NULL);
  2799.     return TCL_ERROR;
  2800. }
  2801. if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0,
  2802. &index) != TCL_OK) {
  2803.     return TCL_ERROR;
  2804. }
  2805. if (index == OPT_NORMAL) {
  2806.     wmPtr->flags &= ~WM_WITHDRAWN;
  2807.     (void) TkpWmSetState(winPtr, NormalState);
  2808. } else if (index == OPT_ICONIC) {
  2809.     if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
  2810. Tcl_AppendResult(interp, "can't iconify "",
  2811. winPtr->pathName,
  2812. "": override-redirect flag is set",
  2813. (char *) NULL);
  2814. return TCL_ERROR;
  2815.     }
  2816.     if (wmPtr->masterPtr != NULL) {
  2817. Tcl_AppendResult(interp, "can't iconify "",
  2818. winPtr->pathName,
  2819. "": it is a transient", (char *) NULL);
  2820. return TCL_ERROR;
  2821.     }
  2822.     if (TkpWmSetState(winPtr, IconicState) == 0) {
  2823. Tcl_SetResult(interp,
  2824. "couldn't send iconify message to window manager",
  2825. TCL_STATIC);
  2826. return TCL_ERROR;
  2827.     }
  2828. } else { /* OPT_WITHDRAWN */
  2829.     wmPtr->flags |= WM_WITHDRAWN;
  2830.     if (TkpWmSetState(winPtr, WithdrawnState) == 0) {
  2831. Tcl_SetResult(interp,
  2832. "couldn't send withdraw message to window manager",
  2833. TCL_STATIC);
  2834. return TCL_ERROR;
  2835.     }
  2836. }
  2837.     } else {
  2838. if (wmPtr->iconFor != NULL) {
  2839.     Tcl_SetResult(interp, "icon", TCL_STATIC);
  2840. } else if (wmPtr->withdrawn) {
  2841.     Tcl_SetResult(interp, "withdrawn", TCL_STATIC);
  2842. } else if (Tk_IsMapped((Tk_Window) winPtr)
  2843. || ((wmPtr->flags & WM_NEVER_MAPPED)
  2844. && (wmPtr->hints.initial_state == NormalState))) {
  2845.     Tcl_SetResult(interp, "normal", TCL_STATIC);
  2846. } else {
  2847.     Tcl_SetResult(interp, "iconic", TCL_STATIC);
  2848. }
  2849.     }
  2850.     return TCL_OK;
  2851. }
  2852. /*
  2853.  *----------------------------------------------------------------------
  2854.  *
  2855.  * WmTitleCmd --
  2856.  *
  2857.  * This procedure is invoked to process the "wm title" Tcl command.
  2858.  * See the user documentation for details on what it does.
  2859.  *
  2860.  * Results:
  2861.  * A standard Tcl result.
  2862.  *
  2863.  * Side effects:
  2864.  * See the user documentation.
  2865.  *
  2866.  *----------------------------------------------------------------------
  2867.  */
  2868. static int
  2869. WmTitleCmd(tkwin, winPtr, interp, objc, objv)
  2870.     Tk_Window tkwin; /* Main window of the application. */
  2871.     TkWindow *winPtr;           /* Toplevel to work with */
  2872.     Tcl_Interp *interp; /* Current interpreter. */
  2873.     int objc; /* Number of arguments. */
  2874.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2875. {
  2876.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2877.     char *argv3;
  2878.     int length;
  2879.     if (objc > 4) {
  2880. Tcl_WrongNumArgs(interp, 2, objv, "window ?newTitle?");
  2881. return TCL_ERROR;
  2882.     }
  2883.     if (objc == 3) {
  2884. Tcl_SetResult(interp, (char *)
  2885. ((wmPtr->title != NULL) ? wmPtr->title : winPtr->nameUid),
  2886. TCL_STATIC);
  2887. return TCL_OK;
  2888.     } else {
  2889. if (wmPtr->title != NULL) {
  2890.     ckfree((char *) wmPtr->title);
  2891. }
  2892. argv3 = Tcl_GetStringFromObj(objv[3], &length);
  2893. wmPtr->title = ckalloc((unsigned) (length + 1));
  2894. strcpy(wmPtr->title, argv3);
  2895. if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  2896.     UpdateTitle(winPtr);
  2897. }
  2898.     }
  2899.     return TCL_OK;
  2900. }
  2901. /*
  2902.  *----------------------------------------------------------------------
  2903.  *
  2904.  * WmTransientCmd --
  2905.  *
  2906.  * This procedure is invoked to process the "wm transient" Tcl command.
  2907.  * See the user documentation for details on what it does.
  2908.  *
  2909.  * Results:
  2910.  * A standard Tcl result.
  2911.  *
  2912.  * Side effects:
  2913.  * See the user documentation.
  2914.  *
  2915.  *----------------------------------------------------------------------
  2916.  */
  2917. static int
  2918. WmTransientCmd(tkwin, winPtr, interp, objc, objv)
  2919.     Tk_Window tkwin; /* Main window of the application. */
  2920.     TkWindow *winPtr;           /* Toplevel to work with */
  2921.     Tcl_Interp *interp; /* Current interpreter. */
  2922.     int objc; /* Number of arguments. */
  2923.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2924. {
  2925.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2926.     TkWindow *masterPtr = wmPtr->masterPtr;
  2927.     WmInfo *wmPtr2;
  2928.     if ((objc != 3) && (objc != 4)) {
  2929. Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
  2930. return TCL_ERROR;
  2931.     }
  2932.     if (objc == 3) {
  2933. if (masterPtr != NULL) {
  2934.     Tcl_SetResult(interp, Tk_PathName(masterPtr), TCL_STATIC);
  2935. }
  2936. return TCL_OK;
  2937.     }
  2938.     if (Tcl_GetString(objv[3])[0] == '') {
  2939. if (masterPtr != NULL) {
  2940.     /*
  2941.      * If we had a master, tell them that we aren't tied
  2942.      * to them anymore
  2943.      */
  2944.     masterPtr->wmInfoPtr->numTransients--;
  2945.     Tk_DeleteEventHandler((Tk_Window) masterPtr,
  2946.     StructureNotifyMask,
  2947.     WmWaitMapProc, (ClientData) winPtr);
  2948.     /* FIXME: Need a call like Win32's UpdateWrapper() so
  2949.        we can recreate the wrapper and get rid of the
  2950.        transient window decorations. */
  2951. }
  2952. wmPtr->masterPtr = NULL;
  2953.     } else {
  2954. if (TkGetWindowFromObj(interp, tkwin, objv[3],
  2955. (Tk_Window *) &masterPtr) != TCL_OK) {
  2956.     return TCL_ERROR;
  2957. }
  2958. while (!Tk_TopWinHierarchy(masterPtr)) {
  2959.     /*
  2960.      * Ensure that the master window is actually a Tk toplevel.
  2961.      */
  2962.     masterPtr = masterPtr->parentPtr;
  2963. }
  2964. Tk_MakeWindowExist((Tk_Window) masterPtr);
  2965. if (wmPtr->iconFor != NULL) {
  2966.     Tcl_AppendResult(interp, "can't make "",
  2967.     Tcl_GetString(objv[2]),
  2968.     "" a transient: it is an icon for ",
  2969.     Tk_PathName(wmPtr->iconFor),
  2970.     (char *) NULL);
  2971.     return TCL_ERROR;
  2972. }
  2973. wmPtr2 = masterPtr->wmInfoPtr;
  2974. if (wmPtr2->wrapperPtr == NULL) {
  2975.     CreateWrapper(wmPtr2);
  2976. }
  2977. if (wmPtr2->iconFor != NULL) {
  2978.     Tcl_AppendResult(interp, "can't make "",
  2979.     Tcl_GetString(objv[3]),
  2980.     "" a master: it is an icon for ",
  2981.     Tk_PathName(wmPtr2->iconFor),
  2982.     (char *) NULL);
  2983.     return TCL_ERROR;
  2984. }
  2985. if (masterPtr == winPtr) {
  2986.     Tcl_AppendResult(interp, "can't make "", Tk_PathName(winPtr),
  2987.     "" its own master",
  2988.     (char *) NULL);
  2989.     return TCL_ERROR;
  2990. } else if (masterPtr != wmPtr->masterPtr) {
  2991.     /*
  2992.      * Remove old master map/unmap binding before setting
  2993.      * the new master. The event handler will ensure that
  2994.      * transient states reflect the state of the master.
  2995.      */
  2996.     if (wmPtr->masterPtr != NULL) {
  2997. wmPtr->masterPtr->wmInfoPtr->numTransients--;
  2998. Tk_DeleteEventHandler((Tk_Window) wmPtr->masterPtr,
  2999. StructureNotifyMask,
  3000. WmWaitMapProc, (ClientData) winPtr);
  3001.     }
  3002.     masterPtr->wmInfoPtr->numTransients++;
  3003.     Tk_CreateEventHandler((Tk_Window) masterPtr,
  3004.     StructureNotifyMask,
  3005.     WmWaitMapProc, (ClientData) winPtr);
  3006.     wmPtr->masterPtr = masterPtr;
  3007. }
  3008.     }
  3009.     if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  3010. if (wmPtr->masterPtr != NULL && !Tk_IsMapped(wmPtr->masterPtr)) {
  3011.     if (TkpWmSetState(winPtr, WithdrawnState) == 0) {
  3012. Tcl_SetResult(interp,
  3013. "couldn't send withdraw message to window manager",
  3014. TCL_STATIC);
  3015. return TCL_ERROR;
  3016.     }
  3017. } else {
  3018.     if (wmPtr->masterPtr != NULL) {
  3019. XSetTransientForHint(winPtr->display, wmPtr->wrapperPtr->window,
  3020. wmPtr->masterPtr->wmInfoPtr->wrapperPtr->window);
  3021.     } else {
  3022. XDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window,
  3023. Tk_InternAtom((Tk_Window)winPtr, "WM_TRANSIENT_FOR"));
  3024.     }
  3025. }
  3026.     }
  3027.     return TCL_OK;
  3028. }
  3029. /*
  3030.  *----------------------------------------------------------------------
  3031.  *
  3032.  * WmWithdrawCmd --
  3033.  *
  3034.  * This procedure is invoked to process the "wm withdraw" Tcl command.
  3035.  * See the user documentation for details on what it does.
  3036.  *
  3037.  * Results:
  3038.  * A standard Tcl result.
  3039.  *
  3040.  * Side effects:
  3041.  * See the user documentation.
  3042.  *
  3043.  *----------------------------------------------------------------------
  3044.  */
  3045. static int
  3046. WmWithdrawCmd(tkwin, winPtr, interp, objc, objv)
  3047.     Tk_Window tkwin; /* Main window of the application. */
  3048.     TkWindow *winPtr;           /* Toplevel to work with */
  3049.     Tcl_Interp *interp; /* Current interpreter. */
  3050.     int objc; /* Number of arguments. */
  3051.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  3052. {
  3053.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  3054.     if (objc != 3) {
  3055. Tcl_WrongNumArgs(interp, 2, objv, "window");
  3056. return TCL_ERROR;
  3057.     }
  3058.     if (wmPtr->iconFor != NULL) {
  3059. Tcl_AppendResult(interp, "can't withdraw ", Tcl_GetString(objv[2]),
  3060. ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
  3061. (char *) NULL);
  3062. return TCL_ERROR;
  3063.     }
  3064.     wmPtr->flags |= WM_WITHDRAWN;
  3065.     if (TkpWmSetState(winPtr, WithdrawnState) == 0) {
  3066. Tcl_SetResult(interp,
  3067. "couldn't send withdraw message to window manager",
  3068. TCL_STATIC);
  3069. return TCL_ERROR;
  3070.     }
  3071.     return TCL_OK;
  3072. }
  3073. /*
  3074.  * Invoked by those wm subcommands that affect geometry.
  3075.  * Schedules a geometry update.
  3076.  */
  3077. static void
  3078. WmUpdateGeom(wmPtr, winPtr)
  3079.     WmInfo *wmPtr;
  3080.     TkWindow *winPtr;
  3081. {
  3082.     if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
  3083. Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
  3084. wmPtr->flags |= WM_UPDATE_PENDING;
  3085.     }
  3086. }
  3087. /*
  3088.  * Invoked when a MapNotify or UnmapNotify event is delivered for a
  3089.  * toplevel that is the master of a transient toplevel.
  3090.  */
  3091. static void
  3092. WmWaitMapProc(clientData, eventPtr)
  3093.     ClientData clientData; /* Pointer to window. */
  3094.     XEvent *eventPtr; /* Information about event. */
  3095. {
  3096.     TkWindow *winPtr = (TkWindow *) clientData;
  3097.     TkWindow *masterPtr = winPtr->wmInfoPtr->masterPtr;
  3098.     if (masterPtr == NULL)
  3099.         return;
  3100.     if (eventPtr->type == MapNotify) {
  3101.         if (!(winPtr->wmInfoPtr->flags & WM_WITHDRAWN))
  3102.             (void) TkpWmSetState(winPtr, NormalState);