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

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * tkWinWm.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) 1995-1997 Sun Microsystems, Inc.
  10.  * Copyright (c) 1998-2000 by Scriptics Corporation.
  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: tkWinWm.c,v 1.54.2.28 2007/12/05 19:18:09 hobbs Exp $
  16.  */
  17. #include "tkWinInt.h"
  18. #include <shellapi.h>
  19. /*
  20.  * These next two defines are only valid on Win2K/XP+.
  21.  */
  22. #ifndef WS_EX_LAYERED
  23. #define WS_EX_LAYERED 0x00080000
  24. #endif
  25. #ifndef LWA_COLORKEY
  26. #define LWA_COLORKEY 0x00000001
  27. #endif
  28. #ifndef LWA_ALPHA
  29. #define LWA_ALPHA 0x00000002
  30. #endif
  31. /*
  32.  * Event structure for synthetic activation events.  These events are
  33.  * placed on the event queue whenever a toplevel gets a WM_MOUSEACTIVATE
  34.  * message.
  35.  */
  36. typedef struct ActivateEvent {
  37.     Tcl_Event ev;
  38.     TkWindow *winPtr;
  39. } ActivateEvent;
  40. /*
  41.  * A data structure of the following type holds information for
  42.  * each window manager protocol (such as WM_DELETE_WINDOW) for
  43.  * which a handler (i.e. a Tcl command) has been defined for a
  44.  * particular top-level window.
  45.  */
  46. typedef struct ProtocolHandler {
  47.     Atom protocol; /* Identifies the protocol. */
  48.     struct ProtocolHandler *nextPtr;
  49. /* Next in list of protocol handlers for
  50.  * the same top-level window, or NULL for
  51.  * end of list. */
  52.     Tcl_Interp *interp; /* Interpreter in which to invoke command. */
  53.     char command[4]; /* Tcl command to invoke when a client
  54.  * message for this protocol arrives.
  55.  * The actual size of the structure varies
  56.  * to accommodate the needs of the actual
  57.  * command. THIS MUST BE THE LAST FIELD OF
  58.  * THE STRUCTURE. */
  59. } ProtocolHandler;
  60. #define HANDLER_SIZE(cmdLength) 
  61.     ((unsigned) (sizeof(ProtocolHandler) - 3 + cmdLength))
  62. /*
  63.  * Helper type passed via lParam to TkWmStackorderToplevelEnumProc
  64.  */
  65. typedef struct TkWmStackorderToplevelPair {
  66.     Tcl_HashTable *table;
  67.     TkWindow **window_ptr;
  68. } TkWmStackorderToplevelPair;
  69. /*
  70.  * This structure represents the contents of a icon, in terms of its
  71.  * image.  The HICON is an internal Windows format.  Most of these
  72.  * icon-specific-structures originated with the Winico extension.
  73.  * We stripped out unused parts of that code, and integrated the
  74.  * code more naturally with Tcl.
  75.  */
  76. typedef struct {
  77. UINT Width, Height, Colors; /*  Width, Height and bpp */
  78. LPBYTE lpBits;                /*  ptr to DIB bits */
  79. DWORD dwNumBytes;            /*  how many bytes? */
  80. LPBITMAPINFO lpbi;                          /*  ptr to header */
  81. LPBYTE lpXOR;                 /*  ptr to XOR image bits */
  82. LPBYTE lpAND;                 /*  ptr to AND image bits */
  83. HICON hIcon;                 /*  DAS ICON */
  84. } ICONIMAGE, *LPICONIMAGE;
  85. /*
  86.  * This structure is how we represent a block of the above
  87.  * items.  We will reallocate these structures according to
  88.  * how many images they need to contain.
  89.  */
  90. typedef struct {
  91. int nNumImages;                      /*  How many images? */
  92. ICONIMAGE IconImages[1];                   /*  Image entries */
  93. } BlockOfIconImages, *BlockOfIconImagesPtr;
  94. /*
  95.  * These two structures are used to read in icons from an
  96.  * 'icon directory' (i.e. the contents of a .icr file, say).
  97.  * We only use these structures temporarily, since we copy
  98.  * the information we want into a BlockOfIconImages.
  99.  */
  100. typedef struct {
  101. BYTE bWidth;               /*  Width of the image */
  102. BYTE bHeight;              /*  Height of the image (times 2) */
  103. BYTE bColorCount;          /*  Number of colors in image (0 if >=8bpp) */
  104. BYTE bReserved;            /*  Reserved */
  105. WORD wPlanes;              /*  Color Planes */
  106. WORD wBitCount;            /*  Bits per pixel */
  107. DWORD dwBytesInRes;         /*  how many bytes in this resource? */
  108. DWORD dwImageOffset;        /*  where in the file is this image */
  109. } ICONDIRENTRY, *LPICONDIRENTRY;
  110. typedef struct {
  111. WORD idReserved;   /*  Reserved */
  112. WORD idType;       /*  resource type (1 for icons) */
  113. WORD idCount;      /*  how many images? */
  114. ICONDIRENTRY idEntries[1]; /*  the entries for each image */
  115. } ICONDIR, *LPICONDIR;
  116. /*
  117.  * A pointer to one of these strucutures is associated with each
  118.  * toplevel.  This allows us to free up all memory associated with icon
  119.  * resources when a window is deleted or if the window's icon is
  120.  * changed.  They are simply reference counted according to:
  121.  *
  122.  * (i) how many WmInfo structures point to this object
  123.  * (ii) whether the ThreadSpecificData defined in this file contains
  124.  * a pointer to this object.
  125.  *
  126.  * The former count is for windows whose icons are individually
  127.  * set, and the latter is for the global default icon choice.
  128.  *
  129.  * Icons loaded from .icr/.icr use the iconBlock field, icons
  130.  * loaded from .exe/.dll use the hIcon field.
  131.  */
  132. typedef struct WinIconInstance {
  133.     int refCount;  /* Number of instances that share this
  134.   * data structure. */
  135.     BlockOfIconImagesPtr iconBlock;
  136.                                  /* Pointer to icon resource data for
  137.                                   * image. */
  138. } WinIconInstance;
  139. typedef struct WinIconInstance *WinIconPtr;
  140. /*
  141.  * A data structure of the following type holds window-manager-related
  142.  * information for each top-level window in an application.
  143.  */
  144. typedef struct TkWmInfo {
  145.     TkWindow *winPtr; /* Pointer to main Tk information for
  146.  * this window. */
  147.     HWND wrapper; /* This is the decorative frame window
  148.  * created by the window manager to wrap
  149.  * a toplevel window.  This window is
  150.  * a direct child of the root window. */
  151.     char *title; /* Title to display in window caption.  If
  152.  * NULL, use name of widget.  Malloced. */
  153.     char *iconName; /* Name to display in icon.  Malloced. */
  154.     XWMHints hints; /* Various pieces of information for
  155.  * window manager. */
  156.     char *leaderName; /* Path name of leader of window group
  157.  * (corresponds to hints.window_group).
  158.  * Malloc-ed.  Note:  this field doesn't
  159.  * get updated if leader is destroyed. */
  160.     TkWindow *masterPtr; /* Master window for TRANSIENT_FOR property,
  161.  * or NULL. */
  162.     Tk_Window icon; /* Window to use as icon for this window,
  163.  * or NULL. */
  164.     Tk_Window iconFor; /* Window for which this window is icon, or
  165.  * NULL if this isn't an icon for anyone. */
  166.     /*
  167.      * Information used to construct an XSizeHints structure for
  168.      * the window manager:
  169.      */
  170.     int defMinWidth, defMinHeight, defMaxWidth, defMaxHeight;
  171. /* Default resize limits given by system. */
  172.     int sizeHintsFlags; /* Flags word for XSizeHints structure.
  173.  * If the PBaseSize flag is set then the
  174.  * window is gridded;  otherwise it isn't
  175.  * gridded. */
  176.     int minWidth, minHeight; /* Minimum dimensions of window, in
  177.  * pixels or grid units. */
  178.     int maxWidth, maxHeight; /* Maximum dimensions of window, in
  179.  * pixels or grid units. 0 to default. */
  180.     Tk_Window gridWin; /* Identifies the window that controls
  181.  * gridding for this top-level, or NULL if
  182.  * the top-level isn't currently gridded. */
  183.     int widthInc, heightInc; /* Increments for size changes (# pixels
  184.  * per step). */
  185.     struct {
  186. int x; /* numerator */
  187. int y;  /* denominator */
  188.     } minAspect, maxAspect; /* Min/max aspect ratios for window. */
  189.     int reqGridWidth, reqGridHeight;
  190. /* The dimensions of the window (in
  191.  * grid units) requested through
  192.  * the geometry manager. */
  193.     int gravity; /* Desired window gravity. */
  194.     /*
  195.      * Information used to manage the size and location of a window.
  196.      */
  197.     int width, height; /* Desired dimensions of window, specified
  198.  * in pixels or grid units.  These values are
  199.  * set by the "wm geometry" command and by
  200.  * ConfigureNotify events (for when wm
  201.  * resizes window).  -1 means user hasn't
  202.  * requested dimensions. */
  203.     int x, y; /* Desired X and Y coordinates for window.
  204.  * These values are set by "wm geometry",
  205.  * plus by ConfigureNotify events (when wm
  206.  * moves window).  These numbers are
  207.  * different than the numbers stored in
  208.  * winPtr->changes because (a) they could be
  209.  * measured from the right or bottom edge
  210.  * of the screen (see WM_NEGATIVE_X and
  211.  * WM_NEGATIVE_Y flags) and (b) if the window
  212.  * has been reparented then they refer to the
  213.  * parent rather than the window itself. */
  214.     int borderWidth, borderHeight;
  215. /* Width and height of window dressing, in
  216.  * pixels for the current style/exStyle.  This
  217.  * includes the border on both sides of the
  218.  * window. */
  219.     int configWidth, configHeight;
  220. /* Dimensions passed to last request that we
  221.  * issued to change geometry of window.  Used
  222.  * to eliminate redundant resize operations. */
  223.     HMENU hMenu; /* the hMenu associated with this menu */
  224.     DWORD style, exStyle; /* Style flags for the wrapper window. */
  225.     LONG styleConfig; /* Extra user requested style bits */
  226.     LONG exStyleConfig; /* Extra user requested extended style bits */
  227.     Tcl_Obj *crefObj; /* COLORREF object for transparent handling */
  228.     COLORREF colorref; /* COLORREF for transparent handling */
  229.     double alpha; /* Alpha transparency level
  230.  * 0.0 (fully transparent) .. 1.0 (opaque) */
  231.     /*
  232.      * List of children of the toplevel which have private colormaps.
  233.      */
  234.     TkWindow **cmapList; /* Array of window with private colormaps. */
  235.     int cmapCount; /* Number of windows in array. */
  236.     /*
  237.      * Miscellaneous information.
  238.      */
  239.     ProtocolHandler *protPtr; /* First in list of protocol handlers for
  240.  * this window (NULL means none). */
  241.     int cmdArgc; /* Number of elements in cmdArgv below. */
  242.     CONST char **cmdArgv; /* Array of strings to store in the
  243.  * WM_COMMAND property.  NULL means nothing
  244.  * available. */
  245.     char *clientMachine; /* String to store in WM_CLIENT_MACHINE
  246.  * property, or NULL. */
  247.     int flags; /* Miscellaneous flags, defined below. */
  248.     int numTransients; /* number of transients on this window */
  249.     WinIconPtr iconPtr;         /* pointer to titlebar icon structure for
  250.                                  * this window, or NULL. */
  251.     struct TkWmInfo *nextPtr; /* Next in list of all top-level windows. */
  252. } WmInfo;
  253. /*
  254.  * Flag values for WmInfo structures:
  255.  *
  256.  * WM_NEVER_MAPPED - non-zero means window has never been
  257.  * mapped;  need to update all info when
  258.  * window is first mapped.
  259.  * WM_UPDATE_PENDING - non-zero means a call to UpdateGeometryInfo
  260.  * has already been scheduled for this
  261.  * window;  no need to schedule another one.
  262.  * WM_NEGATIVE_X - non-zero means x-coordinate is measured in
  263.  * pixels from right edge of screen, rather
  264.  * than from left edge.
  265.  * WM_NEGATIVE_Y - non-zero means y-coordinate is measured in
  266.  * pixels up from bottom of screen, rather than
  267.  * down from top.
  268.  * WM_UPDATE_SIZE_HINTS - non-zero means that new size hints need to be
  269.  * propagated to window manager. Not used on Win.
  270.  * WM_SYNC_PENDING - set to non-zero while waiting for the window
  271.  * manager to respond to some state change.
  272.  * WM_MOVE_PENDING - non-zero means the application has requested
  273.  * a new position for the window, but it hasn't
  274.  * been reflected through the window manager
  275.  * yet.
  276.  * WM_COLORMAPS_EXPLICIT - non-zero means the colormap windows were
  277.  * set explicitly via "wm colormapwindows".
  278.  * WM_ADDED_TOPLEVEL_COLORMAP - non-zero means that when "wm colormapwindows"
  279.  * was called the top-level itself wasn't
  280.  * specified, so we added it implicitly at
  281.  * the end of the list.
  282.  * WM_WIDTH_NOT_RESIZABLE - non-zero means that we're not supposed to
  283.  * allow the user to change the width of the
  284.  * window (controlled by "wm resizable"
  285.  * command).
  286.  * WM_HEIGHT_NOT_RESIZABLE - non-zero means that we're not supposed to
  287.  * allow the user to change the height of the
  288.  * window (controlled by "wm resizable"
  289.  * command).
  290.  * WM_WITHDRAWN - non-zero means that this window has explicitly
  291.  * been withdrawn. If it's a transient, it should
  292.  * not mirror state changes in the master.
  293.  */
  294. #define WM_NEVER_MAPPED (1<<0)
  295. #define WM_UPDATE_PENDING (1<<1)
  296. #define WM_NEGATIVE_X (1<<2)
  297. #define WM_NEGATIVE_Y (1<<3)
  298. #define WM_UPDATE_SIZE_HINTS (1<<4)
  299. #define WM_SYNC_PENDING (1<<5)
  300. #define WM_CREATE_PENDING (1<<6)
  301. #define WM_MOVE_PENDING (1<<7)
  302. #define WM_COLORMAPS_EXPLICIT (1<<8)
  303. #define WM_ADDED_TOPLEVEL_COLORMAP (1<<9)
  304. #define WM_WIDTH_NOT_RESIZABLE (1<<10)
  305. #define WM_HEIGHT_NOT_RESIZABLE (1<<11)
  306. #define WM_WITHDRAWN (1<<12)
  307. /*
  308.  * Window styles for various types of toplevel windows.
  309.  */
  310. #define WM_OVERRIDE_STYLE (WS_CLIPCHILDREN|WS_CLIPSIBLINGS|CS_DBLCLKS)
  311. #define EX_OVERRIDE_STYLE (WS_EX_TOOLWINDOW)
  312. #define WM_TOPLEVEL_STYLE (WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|CS_DBLCLKS)
  313. #define EX_TOPLEVEL_STYLE (0)
  314. #define WM_TRANSIENT_STYLE 
  315. (WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS|CS_DBLCLKS)
  316. #define EX_TRANSIENT_STYLE (WS_EX_DLGMODALFRAME)
  317. /*
  318.  * The following structure is the official type record for geometry
  319.  * management of top-level windows.
  320.  */
  321. static void TopLevelReqProc(ClientData dummy, Tk_Window tkwin);
  322. static Tk_GeomMgr wmMgrType = {
  323.     "wm", /* name */
  324.     TopLevelReqProc, /* requestProc */
  325.     (Tk_GeomLostSlaveProc *) NULL, /* lostSlaveProc */
  326. };
  327. typedef struct ThreadSpecificData {
  328.     HPALETTE systemPalette;      /* System palette; refers to the
  329.   * currently installed foreground logical
  330.   * palette. */
  331.     TkWindow *createWindow;      /* Window that is being constructed.  This
  332.   * value is set immediately before a
  333.   * call to CreateWindowEx, and is used
  334.   * by SetLimits.  This is a gross hack
  335.   * needed to work around Windows brain
  336.   * damage where it sends the
  337.   * WM_GETMINMAXINFO message before the
  338.   * WM_CREATE window. */
  339.     int initialized;             /* Flag indicating whether thread-
  340.   * specific elements of module have
  341.   * been initialized. */
  342.     int firstWindow;             /* Flag, cleared when the first window
  343.   * is mapped in a non-iconic state. */
  344.     WinIconPtr iconPtr;          /* IconPtr being used as default for all
  345.                                   * toplevels, or NULL. */
  346. } ThreadSpecificData;
  347. static Tcl_ThreadDataKey dataKey;
  348. /*
  349.  * The following variables cannot be placed in thread local storage
  350.  * because they must be shared across threads.
  351.  */
  352. static int initialized;        /* Flag indicating whether module has
  353. * been initialized. */
  354. /* 
  355.  * A pointer to a shell proc which allows us to extract icons from
  356.  * any file.  We just initialize this when we start up (if we can)
  357.  * and then it never changes
  358.  */
  359. DWORD* (WINAPI *shgetfileinfoProc) (LPCTSTR pszPath, DWORD dwFileAttributes,
  360.     SHFILEINFO* psfi, UINT cbFileInfo, UINT uFlags) = NULL;
  361. /*
  362.  * A pointer to SetLayeredWindowAttributes (user32.dll) which we
  363.  * retrieve dynamically because it is only valid on Win2K+.
  364.  */
  365. BOOL (WINAPI *setLayeredWindowAttributesProc) (HWND hwnd, COLORREF crKey,
  366. BYTE bAlpha, DWORD dwFlags) = NULL;
  367. TCL_DECLARE_MUTEX(winWmMutex)
  368. /*
  369.  * Forward declarations for procedures defined in this file:
  370.  */
  371. static int ActivateWindow _ANSI_ARGS_((Tcl_Event *evPtr,
  372.     int flags));
  373. static void ConfigureTopLevel _ANSI_ARGS_((WINDOWPOS *pos));
  374. static void GenerateConfigureNotify _ANSI_ARGS_((
  375.     TkWindow *winPtr));
  376. static void GetMaxSize _ANSI_ARGS_((WmInfo *wmPtr,
  377.     int *maxWidthPtr, int *maxHeightPtr));
  378. static void GetMinSize _ANSI_ARGS_((WmInfo *wmPtr,
  379.     int *minWidthPtr, int *minHeightPtr));
  380. static TkWindow * GetTopLevel _ANSI_ARGS_((HWND hwnd));
  381. static void InitWm _ANSI_ARGS_((void));
  382. static int InstallColormaps _ANSI_ARGS_((HWND hwnd, int message,
  383.     int isForemost));
  384. static void InvalidateSubTree _ANSI_ARGS_((TkWindow *winPtr,
  385.     Colormap colormap));
  386. static void InvalidateSubTreeDepth _ANSI_ARGS_((TkWindow *winPtr));
  387. static int ParseGeometry _ANSI_ARGS_((Tcl_Interp *interp,
  388.     char *string, TkWindow *winPtr));
  389. static void RefreshColormap _ANSI_ARGS_((Colormap colormap,
  390.                     TkDisplay *dispPtr));
  391. static void SetLimits _ANSI_ARGS_((HWND hwnd, MINMAXINFO *info));
  392. static void TkWmStackorderToplevelWrapperMap _ANSI_ARGS_((
  393.     TkWindow *winPtr,
  394.     Display *display,
  395.     Tcl_HashTable *table));
  396. static LRESULT CALLBACK TopLevelProc _ANSI_ARGS_((HWND hwnd, UINT message,
  397.     WPARAM wParam, LPARAM lParam));
  398. static void TopLevelEventProc _ANSI_ARGS_((ClientData clientData,
  399.     XEvent *eventPtr));
  400. static void TopLevelReqProc _ANSI_ARGS_((ClientData dummy,
  401.     Tk_Window tkwin));
  402. static void UpdateGeometryInfo _ANSI_ARGS_((
  403.     ClientData clientData));
  404. static void UpdateWrapper _ANSI_ARGS_((TkWindow *winPtr));
  405. static LRESULT CALLBACK WmProc _ANSI_ARGS_((HWND hwnd, UINT message,
  406.     WPARAM wParam, LPARAM lParam));
  407. static void WmWaitVisibilityOrMapProc _ANSI_ARGS_((
  408.     ClientData clientData, XEvent *eventPtr));
  409. static BlockOfIconImagesPtr   ReadIconOrCursorFromFile _ANSI_ARGS_((
  410.     Tcl_Interp *interp, Tcl_Obj* fileName, BOOL isIcon));
  411. static WinIconPtr       ReadIconFromFile _ANSI_ARGS_((
  412.     Tcl_Interp *interp, Tcl_Obj *fileName));
  413. static WinIconPtr       GetIconFromPixmap _ANSI_ARGS_((Display *dsPtr,
  414.        Pixmap pixmap));
  415. static int      ReadICOHeader _ANSI_ARGS_((Tcl_Channel channel));
  416. static BOOL  AdjustIconImagePointers _ANSI_ARGS_((LPICONIMAGE lpImage));
  417. static HICON  MakeIconOrCursorFromResource 
  418.                             _ANSI_ARGS_((LPICONIMAGE lpIcon, BOOL isIcon));
  419. static HICON  GetIcon _ANSI_ARGS_((WinIconPtr titlebaricon, 
  420.     int icon_size));
  421. static int  WinSetIcon _ANSI_ARGS_((Tcl_Interp *interp,
  422.     WinIconPtr titlebaricon, Tk_Window tkw));
  423. static void  FreeIconBlock _ANSI_ARGS_((BlockOfIconImagesPtr lpIR));
  424. static void     DecrIconRefCount _ANSI_ARGS_((WinIconPtr titlebaricon));
  425. static int  WmAspectCmd _ANSI_ARGS_((Tk_Window tkwin,
  426.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  427.     Tcl_Obj *CONST objv[]));
  428. static int  WmAttributesCmd _ANSI_ARGS_((Tk_Window tkwin,
  429.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  430.     Tcl_Obj *CONST objv[]));
  431. static int  WmClientCmd _ANSI_ARGS_((Tk_Window tkwin,
  432.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  433.     Tcl_Obj *CONST objv[]));
  434. static int  WmColormapwindowsCmd _ANSI_ARGS_((Tk_Window tkwin,
  435.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  436.     Tcl_Obj *CONST objv[]));
  437. static int  WmCommandCmd _ANSI_ARGS_((Tk_Window tkwin,
  438.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  439.     Tcl_Obj *CONST objv[]));
  440. static int  WmDeiconifyCmd _ANSI_ARGS_((Tk_Window tkwin,
  441.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  442.     Tcl_Obj *CONST objv[]));
  443. static int  WmFocusmodelCmd _ANSI_ARGS_((Tk_Window tkwin,
  444.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  445.     Tcl_Obj *CONST objv[]));
  446. static int  WmFrameCmd _ANSI_ARGS_((Tk_Window tkwin,
  447.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  448.     Tcl_Obj *CONST objv[]));
  449. static int  WmGeometryCmd _ANSI_ARGS_((Tk_Window tkwin,
  450.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  451.     Tcl_Obj *CONST objv[]));
  452. static int  WmGridCmd _ANSI_ARGS_((Tk_Window tkwin,
  453.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  454.     Tcl_Obj *CONST objv[]));
  455. static int  WmGroupCmd _ANSI_ARGS_((Tk_Window tkwin,
  456.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  457.     Tcl_Obj *CONST objv[]));
  458. static int  WmIconbitmapCmd _ANSI_ARGS_((Tk_Window tkwin,
  459.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  460.     Tcl_Obj *CONST objv[]));
  461. static int  WmIconifyCmd _ANSI_ARGS_((Tk_Window tkwin,
  462.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  463.     Tcl_Obj *CONST objv[]));
  464. static int  WmIconmaskCmd _ANSI_ARGS_((Tk_Window tkwin,
  465.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  466.     Tcl_Obj *CONST objv[]));
  467. static int  WmIconnameCmd _ANSI_ARGS_((Tk_Window tkwin,
  468.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  469.     Tcl_Obj *CONST objv[]));
  470. static int  WmIconphotoCmd _ANSI_ARGS_((Tk_Window tkwin,
  471.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  472.     Tcl_Obj *CONST objv[]));
  473. static int  WmIconpositionCmd _ANSI_ARGS_((Tk_Window tkwin,
  474.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  475.     Tcl_Obj *CONST objv[]));
  476. static int  WmIconwindowCmd _ANSI_ARGS_((Tk_Window tkwin,
  477.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  478.     Tcl_Obj *CONST objv[]));
  479. static int  WmMaxsizeCmd _ANSI_ARGS_((Tk_Window tkwin,
  480.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  481.     Tcl_Obj *CONST objv[]));
  482. static int  WmMinsizeCmd _ANSI_ARGS_((Tk_Window tkwin,
  483.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  484.     Tcl_Obj *CONST objv[]));
  485. static int  WmOverrideredirectCmd _ANSI_ARGS_((Tk_Window tkwin,
  486.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  487.     Tcl_Obj *CONST objv[]));
  488. static int  WmPositionfromCmd _ANSI_ARGS_((Tk_Window tkwin,
  489.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  490.     Tcl_Obj *CONST objv[]));
  491. static int  WmProtocolCmd _ANSI_ARGS_((Tk_Window tkwin,
  492.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  493.     Tcl_Obj *CONST objv[]));
  494. static int  WmResizableCmd _ANSI_ARGS_((Tk_Window tkwin,
  495.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  496.     Tcl_Obj *CONST objv[]));
  497. static int  WmSizefromCmd _ANSI_ARGS_((Tk_Window tkwin,
  498.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  499.     Tcl_Obj *CONST objv[]));
  500. static int  WmStackorderCmd _ANSI_ARGS_((Tk_Window tkwin,
  501.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  502.     Tcl_Obj *CONST objv[]));
  503. static int  WmStateCmd _ANSI_ARGS_((Tk_Window tkwin,
  504.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  505.     Tcl_Obj *CONST objv[]));
  506. static int  WmTitleCmd _ANSI_ARGS_((Tk_Window tkwin,
  507.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  508.     Tcl_Obj *CONST objv[]));
  509. static int  WmTransientCmd _ANSI_ARGS_((Tk_Window tkwin,
  510.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  511.     Tcl_Obj *CONST objv[]));
  512. static int  WmWithdrawCmd _ANSI_ARGS_((Tk_Window tkwin,
  513.     TkWindow *winPtr, Tcl_Interp *interp, int objc,
  514.     Tcl_Obj *CONST objv[]));
  515. static void WmUpdateGeom _ANSI_ARGS_((WmInfo *wmPtr,
  516.     TkWindow *winPtr));
  517. /* Used in BytesPerLine */
  518. #define WIDTHBYTES(bits)      ((((bits) + 31)>>5)<<2)
  519. /*
  520.  *----------------------------------------------------------------------
  521.  *
  522.  * DIBNumColors --
  523.  *
  524.  * Calculates the number of entries in the color table, given by
  525.  * LPSTR lpbi - pointer to the CF_DIB memory block.  Used by
  526.  * titlebar icon code.
  527.  *
  528.  * Results:
  529.  *
  530.  *      WORD - Number of entries in the color table.
  531.  *
  532.  * Side effects: None.
  533.  *
  534.  *
  535.  *----------------------------------------------------------------------
  536.  */
  537. static WORD 
  538. DIBNumColors( LPSTR lpbi )
  539. {
  540.     WORD wBitCount;
  541.     DWORD dwClrUsed;
  542.     dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;
  543.     if (dwClrUsed)
  544. return (WORD) dwClrUsed;
  545.     wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;
  546.     switch (wBitCount)
  547.     {
  548. case 1: return 2;
  549. case 4: return 16;
  550. case 8: return 256;
  551. default:return 0;
  552.     }
  553. }
  554. /*
  555.  *----------------------------------------------------------------------
  556.  *
  557.  * PaletteSize --
  558.  *
  559.  * Calculates the number of bytes in the color table, as given by
  560.  * LPSTR lpbi - pointer to the CF_DIB memory block.  Used by
  561.  * titlebar icon code.
  562.  *
  563.  * Results:
  564.  * number of bytes in the color table
  565.  *
  566.  * Side effects: None.
  567.  *
  568.  *
  569.  *----------------------------------------------------------------------
  570.  */
  571. static WORD 
  572. PaletteSize( LPSTR lpbi )
  573. {
  574.     return ((WORD)( DIBNumColors( lpbi ) * sizeof( RGBQUAD )) );
  575. }
  576. /*
  577.  *----------------------------------------------------------------------
  578.  *
  579.  * FindDIBits --
  580.  *
  581.  * Locate the image bits in a CF_DIB format DIB, as given by
  582.  * LPSTR lpbi - pointer to the CF_DIB memory block.  Used by
  583.  * titlebar icon code.
  584.  *
  585.  * Results:
  586.  * pointer to the image bits
  587.  *
  588.  * Side effects: None
  589.  *
  590.  *
  591.  *----------------------------------------------------------------------
  592.  */
  593. static LPSTR 
  594. FindDIBBits( LPSTR lpbi )
  595. {
  596.    return ( lpbi + *(LPDWORD)lpbi + PaletteSize( lpbi ) );
  597. }
  598. /*
  599.  *----------------------------------------------------------------------
  600.  *
  601.  * BytesPerLine --
  602.  *
  603.  * Calculates the number of bytes in one scan line, as given by
  604.  * LPBITMAPINFOHEADER lpBMIH - pointer to the BITMAPINFOHEADER
  605.  * that begins the CF_DIB block.  Used by titlebar icon code.
  606.  *
  607.  * Results:
  608.  * number of bytes in one scan line (DWORD aligned)
  609.  *
  610.  * Side effects: None
  611.  *
  612.  *
  613.  *----------------------------------------------------------------------
  614.  */
  615. static DWORD 
  616. BytesPerLine( LPBITMAPINFOHEADER lpBMIH )
  617. {
  618.     return WIDTHBYTES(lpBMIH->biWidth * lpBMIH->biPlanes * lpBMIH->biBitCount);
  619. }
  620. /*
  621.  *----------------------------------------------------------------------
  622.  *
  623.  * AdjustIconImagePointers --
  624.  *
  625.  * Adjusts internal pointers in icon resource struct, as given
  626.  * by LPICONIMAGE lpImage - the resource to handle.  Used by
  627.  * titlebar icon code.
  628.  *
  629.  * Results:
  630.  * BOOL - TRUE for success, FALSE for failure
  631.  *
  632.  * Side effects:
  633.  *
  634.  *
  635.  *----------------------------------------------------------------------
  636.  */
  637. static BOOL 
  638. AdjustIconImagePointers( LPICONIMAGE lpImage )
  639. {
  640.     /*  Sanity check */
  641.     if (lpImage==NULL)
  642. return FALSE;
  643.     /*  BITMAPINFO is at beginning of bits */
  644.     lpImage->lpbi = (LPBITMAPINFO)lpImage->lpBits;
  645.     /*  Width - simple enough */
  646.     lpImage->Width = lpImage->lpbi->bmiHeader.biWidth;
  647.     /* 
  648.      * Icons are stored in funky format where height is doubled 
  649.      * so account for that 
  650.      */
  651.     lpImage->Height = (lpImage->lpbi->bmiHeader.biHeight)/2;
  652.     /*  How many colors? */
  653.     lpImage->Colors = lpImage->lpbi->bmiHeader.biPlanes * 
  654.                             lpImage->lpbi->bmiHeader.biBitCount;
  655.     /*  XOR bits follow the header and color table */
  656.     lpImage->lpXOR = (LPBYTE)FindDIBBits(((LPSTR)lpImage->lpbi));
  657.     /*  AND bits follow the XOR bits */
  658.     lpImage->lpAND = lpImage->lpXOR + (lpImage->Height*
  659. BytesPerLine((LPBITMAPINFOHEADER)(lpImage->lpbi)));
  660.     return TRUE;
  661. }
  662. /*
  663.  *----------------------------------------------------------------------
  664.  *
  665.  * MakeIconOrCursorFromResource --
  666.  *
  667.  * Construct an actual HICON structure from the information
  668.  * in a resource.
  669.  *
  670.  * Results:
  671.  *
  672.  *
  673.  * Side effects:
  674.  *
  675.  *
  676.  *----------------------------------------------------------------------
  677.  */
  678. static HICON 
  679. MakeIconOrCursorFromResource(LPICONIMAGE lpIcon, BOOL isIcon) {
  680.     HICON hIcon ;
  681.     static FARPROC pfnCreateIconFromResourceEx=NULL;
  682.     static int initinfo=0;
  683.     /*  Sanity Check */
  684.     if (lpIcon == NULL)
  685. return NULL;
  686.     if (lpIcon->lpBits == NULL)
  687. return NULL;
  688.     if (!initinfo) {
  689. HMODULE hMod = GetModuleHandleA("USER32.DLL");
  690. initinfo=1;
  691. if (hMod){
  692.     pfnCreateIconFromResourceEx = 
  693.       GetProcAddress(hMod, "CreateIconFromResourceEx");
  694. }
  695.     }
  696.     /*  Let the OS do the real work :) */
  697.     if (pfnCreateIconFromResourceEx!=NULL) {
  698. hIcon = (HICON) (pfnCreateIconFromResourceEx)
  699. (lpIcon->lpBits, lpIcon->dwNumBytes, isIcon, 0x00030000,
  700.  (*(LPBITMAPINFOHEADER)(lpIcon->lpBits)).biWidth,
  701.  (*(LPBITMAPINFOHEADER)(lpIcon->lpBits)).biHeight/2, 0);
  702.     } else {
  703.  hIcon = NULL;
  704.     }
  705.     /*  It failed, odds are good we're on NT so try the non-Ex way */
  706.     if (hIcon == NULL)    {
  707. /*  We would break on NT if we try with a 16bpp image */
  708. if (lpIcon->lpbi->bmiHeader.biBitCount != 16) {
  709.     hIcon = CreateIconFromResource(lpIcon->lpBits, lpIcon->dwNumBytes, 
  710.    isIcon, 0x00030000);
  711. }
  712.     }
  713.     return hIcon;
  714. }
  715. /*
  716.  *----------------------------------------------------------------------
  717.  *
  718.  * ReadICOHeader --
  719.  *
  720.  * Reads the header from an ICO file, as specfied by channel.
  721.  *
  722.  * Results:
  723.  * UINT - Number of images in file, -1 for failure.
  724.  * If this succeeds, there is a decent chance this is a
  725.  * valid icon file.
  726.  *
  727.  * Side effects:
  728.  *
  729.  *
  730.  *----------------------------------------------------------------------
  731.  */
  732. static int 
  733. ReadICOHeader( Tcl_Channel channel )
  734. {
  735.     WORD    Input;
  736.     DWORD dwBytesRead;
  737.     /*  Read the 'reserved' WORD */
  738.     dwBytesRead = Tcl_Read( channel, (char*)&Input, sizeof( WORD ));
  739.     /*  Did we get a WORD? */
  740.     if (dwBytesRead != sizeof( WORD ))
  741. return -1;
  742.     /*  Was it 'reserved' ?   (ie 0) */
  743.     if (Input != 0)
  744. return -1;
  745.     /*  Read the type WORD */
  746.     dwBytesRead = Tcl_Read( channel, (char*)&Input, sizeof( WORD ));
  747.     /*  Did we get a WORD? */
  748.     if (dwBytesRead != sizeof( WORD ))
  749. return -1;
  750.     /*  Was it type 1? */
  751.     if (Input != 1)
  752. return -1;
  753.     /*  Get the count of images */
  754.     dwBytesRead = Tcl_Read( channel, (char*)&Input, sizeof( WORD ));
  755.     /*  Did we get a WORD? */
  756.     if (dwBytesRead != sizeof( WORD ))
  757. return -1;
  758.     /*  Return the count */
  759.     return (int)Input;
  760. }
  761. /*
  762.  *----------------------------------------------------------------------
  763.  *
  764.  * InitWindowClass --
  765.  *
  766.  * This routine creates the Wm toplevel decorative frame class.
  767.  *
  768.  * Results:
  769.  * None.
  770.  *
  771.  * Side effects:
  772.  * Registers a new window class.
  773.  *
  774.  *----------------------------------------------------------------------
  775.  */
  776. static int 
  777. InitWindowClass(WinIconPtr titlebaricon)
  778. {
  779.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  780.     Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  781.     if (! tsdPtr->initialized) {
  782. tsdPtr->initialized = 1;
  783. tsdPtr->firstWindow = 1;
  784. tsdPtr->iconPtr = NULL;
  785.     }
  786.     if (! initialized) {
  787. Tcl_MutexLock(&winWmMutex);
  788. if (! initialized) {
  789.     Tcl_DString classString;
  790.     WNDCLASS class;
  791.     initialized = 1;
  792.     if (shgetfileinfoProc == NULL) {
  793. HINSTANCE hInstance = LoadLibraryA("shell32");
  794. if (hInstance != NULL) {
  795.     shgetfileinfoProc = 
  796.     (DWORD* (WINAPI *) (LPCTSTR pszPath, DWORD dwFileAttributes,
  797.     SHFILEINFO* psfi, UINT cbFileInfo, UINT uFlags)) GetProcAddress(hInstance, 
  798.       "SHGetFileInfo");
  799.     FreeLibrary(hInstance);
  800. }
  801.     }
  802.     if (setLayeredWindowAttributesProc == NULL) {
  803. HINSTANCE hInstance = LoadLibraryA("user32");
  804. if (hInstance != NULL) {
  805.     setLayeredWindowAttributesProc =
  806. (BOOL (WINAPI *) (HWND hwnd, COLORREF crKey,
  807. BYTE bAlpha, DWORD dwFlags))
  808. GetProcAddress(hInstance,
  809. "SetLayeredWindowAttributes");
  810.     FreeLibrary(hInstance);
  811. }
  812.     }
  813.     /*
  814.      * The only difference between WNDCLASSW and WNDCLASSA are
  815.      * in pointers, so we can use the generic structure WNDCLASS.
  816.      */
  817.     ZeroMemory(&class, sizeof(WNDCLASS));
  818.     class.style = CS_HREDRAW | CS_VREDRAW;
  819.     class.hInstance = Tk_GetHINSTANCE();
  820.     Tcl_WinUtfToTChar(TK_WIN_TOPLEVEL_CLASS_NAME, -1, &classString);
  821.     class.lpszClassName = (LPCTSTR) Tcl_DStringValue(&classString);
  822.     class.lpfnWndProc = WmProc;
  823.     if (titlebaricon == NULL) {
  824. class.hIcon = LoadIcon(Tk_GetHINSTANCE(), "tk");
  825.     } else {
  826. class.hIcon = GetIcon(titlebaricon, ICON_BIG);
  827. if (class.hIcon == NULL) {
  828.     return TCL_ERROR;
  829. }
  830. /*
  831.  * Store pointer to default icon so we know when
  832.  * we need to free that information
  833.  */
  834. tsdPtr->iconPtr = titlebaricon;
  835.     }
  836.     class.hCursor = LoadCursor(NULL, IDC_ARROW);
  837.     if (!(*tkWinProcs->registerClass)(&class)) {
  838. Tcl_Panic("Unable to register TkTopLevel class");
  839.     }
  840.     Tcl_DStringFree(&classString);
  841. }
  842. Tcl_MutexUnlock(&winWmMutex);
  843.     }
  844.     return TCL_OK;
  845. }
  846. /*
  847.  *----------------------------------------------------------------------
  848.  *
  849.  * InitWm --
  850.  *
  851.  * This initialises the window manager
  852.  *
  853.  * Results:
  854.  * None.
  855.  *
  856.  * Side effects:
  857.  * Registers a new window class.
  858.  *
  859.  *----------------------------------------------------------------------
  860.  */
  861. static void
  862. InitWm(void)
  863. {
  864.     /* Ignore return result */
  865.     (void) InitWindowClass(NULL);
  866. }
  867. /*
  868.  *----------------------------------------------------------------------
  869.  *
  870.  * WinSetIcon --
  871.  *
  872.  * Sets either the default toplevel titlebar icon, or the icon
  873.  * for a specific toplevel (if tkw is given, then only that
  874.  * window is used).
  875.  *
  876.  * The ref-count of the titlebaricon is NOT changed.  If this
  877.  * function returns successfully, the caller should assume
  878.  * the icon was used (and therefore the ref-count should
  879.  * be adjusted to reflect that fact).  If the function returned
  880.  * an error, the caller should assume the icon was not used
  881.  * (and may wish to free the memory associated with it).
  882.  *
  883.  * Results:
  884.  * A standard Tcl return code.
  885.  *
  886.  * Side effects:
  887.  * One or all windows may have their icon changed.
  888.  * The Tcl result may be modified.
  889.  * The window-manager will be initialised if it wasn't already.
  890.  * The given window will be forced into existence.
  891.  *
  892.  *----------------------------------------------------------------------
  893.  */
  894. static int
  895. WinSetIcon(interp, titlebaricon, tkw)
  896.     Tcl_Interp *interp;
  897.     WinIconPtr titlebaricon;
  898.     Tk_Window tkw;
  899. {
  900.     WmInfo *wmPtr;
  901.     HWND hwnd;
  902.     int application = 0;
  903.     if (tkw == NULL) {
  904.         tkw = Tk_MainWindow(interp);
  905. application = 1;
  906.     }
  907.     if (!(Tk_IsTopLevel(tkw))) {
  908. Tcl_AppendResult(interp, "window "", Tk_PathName(tkw),
  909. "" isn't a top-level window", (char *) NULL);
  910. return TCL_ERROR;
  911.     }
  912.     if (Tk_WindowId(tkw) == None) {
  913. Tk_MakeWindowExist(tkw);
  914.     }
  915.     /* We must get the window's wrapper, not the window itself */
  916.     wmPtr = ((TkWindow*)tkw)->wmInfoPtr;
  917.     hwnd = wmPtr->wrapper;
  918.     if (application) {
  919. if (hwnd == NULL) {
  920.     /*
  921.      * I don't actually think this is ever the correct thing, unless
  922.      * perhaps the window doesn't have a wrapper.  But I believe all
  923.      * windows have wrappers.
  924.      */
  925.     hwnd = Tk_GetHWND(Tk_WindowId(tkw));
  926. }
  927. /*
  928.  * If we aren't initialised, then just initialise with the user's
  929.  * icon.  Otherwise our icon choice will be ignored moments later
  930.  * when Tk finishes initialising.
  931.  */
  932. if (!initialized) {
  933.     if (InitWindowClass(titlebaricon) != TCL_OK) {
  934. Tcl_AppendResult(interp,"Unable to set icon", (char*)NULL);
  935. return TCL_ERROR;
  936.     }
  937. } else {
  938.     ThreadSpecificData *tsdPtr;
  939.     if (
  940. #ifdef _WIN64
  941. !SetClassLongPtr(hwnd, GCLP_HICONSM,
  942. (LPARAM)GetIcon(titlebaricon, ICON_SMALL))
  943. #else
  944. !SetClassLong(hwnd, GCL_HICONSM,
  945. (LPARAM)GetIcon(titlebaricon, ICON_SMALL))
  946. #endif
  947. ) {
  948. /*
  949.  * For some reason this triggers, even though it seems
  950.  * to be successful This is probably related to the
  951.  * WNDCLASS vs WNDCLASSEX difference.  Anyway it seems
  952.  * we have to ignore errors returned here.
  953.  */
  954. /*
  955.  * Tcl_AppendResult(interp,"Unable to set new small icon", (char*)NULL);
  956.  * return TCL_ERROR;
  957.  */
  958.     }
  959.     if (
  960. #ifdef _WIN64
  961. !SetClassLongPtr(hwnd, GCLP_HICON,
  962. (LPARAM)GetIcon(titlebaricon, ICON_BIG))
  963. #else
  964. !SetClassLong(hwnd, GCL_HICON,
  965. (LPARAM)GetIcon(titlebaricon, ICON_BIG))
  966. #endif
  967. ) {
  968. Tcl_AppendResult(interp,"Unable to set new icon", (char*)NULL);
  969. return TCL_ERROR;
  970.     }
  971.     tsdPtr = (ThreadSpecificData *)
  972.     Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  973.     if (tsdPtr->iconPtr != NULL) {
  974. DecrIconRefCount(tsdPtr->iconPtr);
  975.     }
  976.     tsdPtr->iconPtr = titlebaricon;
  977. }
  978.     } else {
  979. if (!initialized) {
  980.     /*
  981.      * Need to initialise the wm otherwise we will fail on
  982.      * code which tries to set a toplevel's icon before that
  983.      * happens.  Ignore return result.
  984.      */
  985.     (void)InitWindowClass(NULL);
  986. }
  987. /*
  988.  * The following code is exercised if you do
  989.  *
  990.  *   toplevel .t ; wm titlebaricon .t foo.icr
  991.  *
  992.  * i.e. the wm hasn't had time to properly create
  993.  * the '.t' window before you set the icon.
  994.  */
  995. if (hwnd == NULL) {
  996.     /*
  997.      * This little snippet is copied from the 'Map' function,
  998.      * and should probably be placed in one proper location
  999.      */
  1000.     UpdateWrapper(wmPtr->winPtr);
  1001.     wmPtr = ((TkWindow*)tkw)->wmInfoPtr;
  1002.     hwnd = wmPtr->wrapper;
  1003.     if (hwnd == NULL) {
  1004. Tcl_AppendResult(interp,
  1005. "Can't set icon; window has no wrapper.", (char*)NULL);
  1006. return TCL_ERROR;
  1007.     }
  1008. }
  1009. SendMessage(hwnd, WM_SETICON, ICON_SMALL,
  1010. (LPARAM) GetIcon(titlebaricon, ICON_SMALL));
  1011. SendMessage(hwnd, WM_SETICON, ICON_BIG,
  1012. (LPARAM) GetIcon(titlebaricon, ICON_BIG));
  1013. /* Update the iconPtr we keep for each WmInfo structure. */
  1014. if (wmPtr->iconPtr != NULL) {
  1015.     /* Free any old icon ptr which is associated with this window. */
  1016.     DecrIconRefCount(wmPtr->iconPtr);
  1017. }
  1018. /*
  1019.  * We do not need to increment the ref count for the
  1020.  * titlebaricon, because it was already incremented when we
  1021.  * retrieved it.
  1022.  */
  1023. wmPtr->iconPtr = titlebaricon;
  1024.     }
  1025.     return TCL_OK;
  1026. }
  1027. /*
  1028.  *----------------------------------------------------------------------
  1029.  *
  1030.  * TkWinGetIcon --
  1031.  *
  1032.  * Gets either the default toplevel titlebar icon, or the icon
  1033.  * for a specific toplevel (ICON_SMALL or ICON_BIG).
  1034.  *
  1035.  * Results:
  1036.  * A Windows HICON.
  1037.  *
  1038.  * Side effects:
  1039.  * The given window will be forced into existence.
  1040.  *
  1041.  *----------------------------------------------------------------------
  1042.  */
  1043. HICON
  1044. TkWinGetIcon(Tk_Window tkwin, DWORD iconsize)
  1045. {
  1046.     WmInfo *wmPtr;
  1047.     HICON icon;
  1048.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  1049.     Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  1050.     if (tsdPtr->iconPtr != NULL) {
  1051. /*
  1052.  * return default toplevel icon
  1053.  */
  1054. return GetIcon(tsdPtr->iconPtr, iconsize);
  1055.     }
  1056.     /* ensure we operate on the toplevel, that has the icon refs */
  1057.     while (!Tk_IsTopLevel(tkwin)) {
  1058. tkwin = Tk_Parent(tkwin);
  1059. if (tkwin == NULL) {
  1060.     return NULL;
  1061. }
  1062.     }
  1063.     if (Tk_WindowId(tkwin) == None) {
  1064. Tk_MakeWindowExist(tkwin);
  1065.     }
  1066.     wmPtr = ((TkWindow *) tkwin)->wmInfoPtr;
  1067.     if (wmPtr->iconPtr != NULL) {
  1068. /*
  1069.  * return window toplevel icon
  1070.  */
  1071. return GetIcon(wmPtr->iconPtr, iconsize);
  1072.     }
  1073.     /*
  1074.      * Find the icon otherwise associated with the toplevel, or
  1075.      * finally with the window class.
  1076.      */
  1077.     icon = (HICON) SendMessage(wmPtr->wrapper, WM_GETICON, iconsize,
  1078.     (LPARAM) NULL);
  1079.     if (icon == (HICON) NULL) {
  1080. #ifdef _WIN64
  1081. icon = (HICON) GetClassLongPtr(wmPtr->wrapper,
  1082. (iconsize == ICON_BIG) ? GCLP_HICON : GCLP_HICONSM);
  1083. #else
  1084. icon = (HICON) GetClassLong(wmPtr->wrapper,
  1085. (iconsize == ICON_BIG) ? GCL_HICON : GCL_HICONSM);
  1086. #endif
  1087.     }
  1088.     return icon;
  1089. }
  1090. /*
  1091.  *----------------------------------------------------------------------
  1092.  *
  1093.  * ReadIconFromFile --
  1094.  *
  1095.  * Read the contents of a file (usually .ico, .icr) and extract an
  1096.  * icon resource, if possible, otherwise check if the shell has an
  1097.  * icon assigned to the given file and use that.  If both of those
  1098.  * fail, then NULL is returned, and an error message will already be
  1099.  * in the interpreter.
  1100.  *
  1101.  * Results:
  1102.  * A WinIconPtr structure containing the icons in the file, with
  1103.  * its ref count already incremented. The calling procedure should
  1104.  * either place this structure inside a WmInfo structure, or it should
  1105.  * pass it on to DecrIconRefCount() to ensure no memory leaks occur.
  1106.  *
  1107.  * If the given fileName did not contain a valid icon structure,
  1108.  * return NULL.
  1109.  *
  1110.  * Side effects:
  1111.  * Memory is allocated for the returned structure and the icons
  1112.  * it contains.  If the structure is not wanted, it should be
  1113.  * passed to DecrIconRefCount, and in any case a valid ref count
  1114.  * should be ensured to avoid memory leaks.
  1115.  *
  1116.  * Currently icon resources are not shared, so the ref count of
  1117.  * one of these structures will always be 0 or 1.  However all we
  1118.  * need do is implement some sort of lookup function between
  1119.  * filenames and WinIconPtr structures and no other code will need
  1120.  * to be changed.  The pseudo-code for this is implemented below
  1121.  * in the 'if (0)' branch.  It did not seem necessary to implement
  1122.  * this optimisation here, since moving to icon<->image
  1123.  * conversions will probably make it obsolete.
  1124.  *
  1125.  *----------------------------------------------------------------------
  1126.  */
  1127. static WinIconPtr
  1128. ReadIconFromFile(interp, fileName)
  1129.     Tcl_Interp *interp;
  1130.     Tcl_Obj *fileName;
  1131. {
  1132.     WinIconPtr titlebaricon = NULL;
  1133.     if (0 /* If we already have an icon for this filename */) {
  1134. titlebaricon = NULL; /* Get the real value from a lookup */
  1135. titlebaricon->refCount++;
  1136. return titlebaricon;
  1137.     } else {
  1138. /* First check if it is a .ico file */
  1139. BlockOfIconImagesPtr lpIR;
  1140. lpIR = ReadIconOrCursorFromFile(interp, fileName, TRUE);
  1141. /*
  1142.  * Then see if we can ask the shell for the icon for this file.
  1143.  * We want both the regular and small icons so that the Alt-Tab
  1144.  * (task-switching) display uses the right icon.
  1145.  */
  1146. if (lpIR == NULL && shgetfileinfoProc != NULL) {
  1147.     SHFILEINFO sfiSM;
  1148.     Tcl_DString ds, ds2;
  1149.     DWORD *res;
  1150.     CONST char *file;
  1151.     file = Tcl_TranslateFileName(interp, Tcl_GetString(fileName), &ds);
  1152.     if (file == NULL) { return NULL; }
  1153.     Tcl_UtfToExternalDString(NULL, file, -1, &ds2);
  1154.     Tcl_DStringFree(&ds);
  1155.     res = (*shgetfileinfoProc)(Tcl_DStringValue(&ds2), 0, &sfiSM,
  1156.     sizeof(SHFILEINFO), SHGFI_SMALLICON|SHGFI_ICON);
  1157.     if (res != 0) {
  1158. SHFILEINFO sfi;
  1159. int size;
  1160. Tcl_ResetResult(interp);
  1161. res = (*shgetfileinfoProc)(Tcl_DStringValue(&ds2), 0, &sfi,
  1162. sizeof(SHFILEINFO), SHGFI_ICON);
  1163. /* Account for extra icon, if necessary */
  1164. size = sizeof(BlockOfIconImages) +
  1165.     ((res != 0) ? sizeof(ICONIMAGE) : 0);
  1166. lpIR = (BlockOfIconImagesPtr) ckalloc(size);
  1167. if (lpIR == NULL) {
  1168.     if (res != 0) {
  1169. DestroyIcon(sfi.hIcon);
  1170.     }
  1171.     DestroyIcon(sfiSM.hIcon);
  1172.     Tcl_DStringFree(&ds2);
  1173.     return NULL;
  1174. }
  1175. ZeroMemory(lpIR, size);
  1176. lpIR->nNumImages               = ((res != 0) ? 2 : 1);
  1177. lpIR->IconImages[0].Width      = 16;
  1178. lpIR->IconImages[0].Height     = 16;
  1179. lpIR->IconImages[0].Colors     = 4;
  1180. lpIR->IconImages[0].hIcon      = sfiSM.hIcon;
  1181. /* All other IconImages fields are ignored */
  1182. if (res != 0) {
  1183.     lpIR->IconImages[1].Width  = 32;
  1184.     lpIR->IconImages[1].Height = 32;
  1185.     lpIR->IconImages[1].Colors = 4;
  1186.     lpIR->IconImages[1].hIcon  = sfi.hIcon;
  1187. }
  1188.     }
  1189.     Tcl_DStringFree(&ds2);
  1190. }
  1191. if (lpIR != NULL) {
  1192.     titlebaricon = (WinIconPtr) ckalloc(sizeof(WinIconInstance));
  1193.     titlebaricon->iconBlock = lpIR;
  1194.     titlebaricon->refCount = 1;
  1195. }
  1196. return titlebaricon;
  1197.     }
  1198. }
  1199. /*
  1200.  *----------------------------------------------------------------------
  1201.  *
  1202.  * GetIconFromPixmap --
  1203.  *
  1204.  * Turn a Tk Pixmap (i.e. a bitmap) into an icon resource, if
  1205.  * possible, otherwise NULL is returned.
  1206.  *
  1207.  * Results:
  1208.  * A WinIconPtr structure containing a conversion of the given
  1209.  * bitmap into an icon, with its ref count already incremented.  The
  1210.  * calling procedure should either place this structure inside a
  1211.  * WmInfo structure, or it should pass it on to DecrIconRefCount()
  1212.  * to ensure no memory leaks occur.
  1213.  *
  1214.  * If the given pixmap did not contain a valid icon structure,
  1215.  * return NULL.
  1216.  *
  1217.  * Side effects:
  1218.  * Memory is allocated for the returned structure and the icons
  1219.  * it contains.  If the structure is not wanted, it should be
  1220.  * passed to DecrIconRefCount, and in any case a valid ref count
  1221.  * should be ensured to avoid memory leaks.
  1222.  *
  1223.  * Currently icon resources are not shared, so the ref count of
  1224.  * one of these structures will always be 0 or 1.  However all we
  1225.  * need do is implement some sort of lookup function between
  1226.  * pixmaps and WinIconPtr structures and no other code will need
  1227.  * to be changed.
  1228.  *
  1229.  *----------------------------------------------------------------------
  1230.  */
  1231. static WinIconPtr       
  1232. GetIconFromPixmap(dsPtr, pixmap)
  1233.     Display *dsPtr;
  1234.     Pixmap pixmap;
  1235. {
  1236.     WinIconPtr titlebaricon = NULL;
  1237.     TkWinDrawable* twdPtr = (TkWinDrawable*) pixmap;
  1238.     
  1239.     if (twdPtr == NULL) {
  1240.         return NULL;
  1241.     }
  1242.     
  1243.     if (0 /* If we already have an icon for this pixmap */) {
  1244. titlebaricon = NULL; /* Get the real value from a lookup */
  1245. titlebaricon->refCount++;
  1246. return titlebaricon;
  1247.     } else {
  1248. BlockOfIconImagesPtr lpIR;
  1249. ICONINFO icon;
  1250. HICON hIcon;
  1251. int width, height;
  1252. Tk_SizeOfBitmap(dsPtr, pixmap, &width, &height);
  1253. icon.fIcon = TRUE;
  1254. icon.xHotspot = 0;
  1255. icon.yHotspot = 0;
  1256. icon.hbmMask = twdPtr->bitmap.handle;
  1257. icon.hbmColor = twdPtr->bitmap.handle;
  1258. hIcon = CreateIconIndirect(&icon);
  1259. if (hIcon == NULL) {
  1260.     return NULL;
  1261. }
  1262. lpIR = (BlockOfIconImagesPtr) ckalloc(sizeof(BlockOfIconImages));
  1263. if (lpIR == NULL) {
  1264.     DestroyIcon(hIcon);
  1265.     return NULL;
  1266. }
  1267. lpIR->nNumImages = 1;
  1268. lpIR->IconImages[0].Width = width;
  1269. lpIR->IconImages[0].Height = height;
  1270. lpIR->IconImages[0].Colors = 1 << twdPtr->bitmap.depth;
  1271. lpIR->IconImages[0].hIcon = hIcon;
  1272. /* These fields are ignored */
  1273. lpIR->IconImages[0].lpBits = 0;
  1274. lpIR->IconImages[0].dwNumBytes = 0;
  1275. lpIR->IconImages[0].lpXOR = 0;
  1276. lpIR->IconImages[0].lpAND = 0;
  1277. titlebaricon = (WinIconPtr) ckalloc(sizeof(WinIconInstance));
  1278. titlebaricon->iconBlock = lpIR;
  1279. titlebaricon->refCount = 1;
  1280. return titlebaricon;
  1281.     }
  1282. }
  1283. /*
  1284.  *----------------------------------------------------------------------
  1285.  *
  1286.  * DecrIconRefCount --
  1287.  *
  1288.  * Reduces the reference count.
  1289.  *
  1290.  * Results:
  1291.  * None.
  1292.  *
  1293.  * Side effects:
  1294.  * If the ref count falls to zero, free the memory associated
  1295.  * with the icon resource structures.  In this case the pointer
  1296.  * passed into this function is no longer valid.
  1297.  *
  1298.  *----------------------------------------------------------------------
  1299.  */
  1300. static void 
  1301. DecrIconRefCount(WinIconPtr titlebaricon) {
  1302.     titlebaricon->refCount--;
  1303.     if (titlebaricon->refCount <= 0) {
  1304. if (titlebaricon->iconBlock != NULL) {
  1305.     FreeIconBlock(titlebaricon->iconBlock);
  1306. }
  1307. titlebaricon->iconBlock = NULL;
  1308. ckfree((char*)titlebaricon);
  1309.     }
  1310. }
  1311. /*
  1312.  *----------------------------------------------------------------------
  1313.  *
  1314.  * FreeIconBlock --
  1315.  *
  1316.  * Frees all memory associated with a previously loaded
  1317.  * titlebaricon.  The icon block pointer is no longer
  1318.  * valid once this function returns.
  1319.  *
  1320.  * Results:
  1321.  * None.
  1322.  *
  1323.  * Side effects:
  1324.  *
  1325.  *
  1326.  *----------------------------------------------------------------------
  1327.  */
  1328. static void 
  1329. FreeIconBlock(BlockOfIconImagesPtr lpIR)
  1330. {
  1331.     int i;
  1332.     /* Free all the bits */
  1333.     for (i=0; i< lpIR->nNumImages; i++) {
  1334. if (lpIR->IconImages[i].lpBits != NULL) {
  1335.     ckfree((char*)lpIR->IconImages[i].lpBits);
  1336. }
  1337. if (lpIR->IconImages[i].hIcon != NULL) {
  1338.     DestroyIcon(lpIR->IconImages[i].hIcon);
  1339. }
  1340.     }
  1341.     ckfree ((char*)lpIR);
  1342. }
  1343. /*
  1344.  *----------------------------------------------------------------------
  1345.  *
  1346.  * GetIcon --
  1347.  *
  1348.  * Extracts an icon of a given size from an icon resource
  1349.  *
  1350.  * Results:
  1351.  * Returns the icon, if found, else NULL.
  1352.  *
  1353.  * Side effects:
  1354.  *
  1355.  *
  1356.  *----------------------------------------------------------------------
  1357.  */
  1358. static HICON 
  1359. GetIcon(WinIconPtr titlebaricon, int icon_size)
  1360. {
  1361.     BlockOfIconImagesPtr lpIR;
  1362.     
  1363.     if (titlebaricon == NULL) {
  1364.         return NULL;
  1365.     }
  1366.     lpIR = titlebaricon->iconBlock;
  1367.     if (lpIR == NULL) {
  1368. return NULL;
  1369.     } else {
  1370. unsigned int size = (icon_size == 0 ? 16 : 32);
  1371. int i;
  1372. for (i = 0; i < lpIR->nNumImages; i++) {
  1373.     /* Take the first or a 32x32 16 color icon*/
  1374.     if ((lpIR->IconImages[i].Height == size)
  1375.        && (lpIR->IconImages[i].Width == size)
  1376.        && (lpIR->IconImages[i].Colors >= 4)) {
  1377. return lpIR->IconImages[i].hIcon;
  1378.     }
  1379. }
  1380. /* 
  1381.  * If we get here, then just return the first one, 
  1382.  * it will have to do!
  1383.  */
  1384. if (lpIR->nNumImages >= 1) {
  1385.     return lpIR->IconImages[0].hIcon;
  1386. }
  1387.     }
  1388.     return NULL;
  1389. }
  1390. static HCURSOR 
  1391. TclWinReadCursorFromFile(Tcl_Interp* interp, Tcl_Obj* fileName)
  1392. {
  1393.     BlockOfIconImagesPtr lpIR;
  1394.     HICON res = NULL;
  1395.     
  1396.     lpIR = ReadIconOrCursorFromFile(interp, fileName, FALSE);
  1397.     if (lpIR == NULL) {
  1398.         return NULL;
  1399.     }
  1400.     if (lpIR->nNumImages >= 1) {
  1401. res = CopyImage(lpIR->IconImages[0].hIcon, IMAGE_CURSOR,0,0,0);
  1402.     }
  1403.     FreeIconBlock(lpIR);
  1404.     return res;
  1405. }
  1406. /*
  1407.  *----------------------------------------------------------------------
  1408.  *
  1409.  * ReadIconOrCursorFromFile --
  1410.  *
  1411.  * Reads an Icon Resource from an ICO file, as given by
  1412.  * char* fileName - Name of the ICO file. This name should
  1413.  * be in Utf format.
  1414.  *
  1415.  * Results:
  1416.  * Returns an icon resource, if found, else NULL.
  1417.  *
  1418.  * Side effects:
  1419.  *      May leave error messages in the Tcl interpreter.
  1420.  *
  1421.  *----------------------------------------------------------------------
  1422.  */
  1423. static BlockOfIconImagesPtr 
  1424. ReadIconOrCursorFromFile(Tcl_Interp* interp, Tcl_Obj* fileName, BOOL isIcon)
  1425. {
  1426.     BlockOfIconImagesPtr lpIR, lpNew;
  1427.     Tcl_Channel          channel;
  1428.     int                  i;
  1429.     DWORD              dwBytesRead;
  1430.     LPICONDIRENTRY      lpIDE;
  1431.     /*  Open the file */
  1432.     channel = Tcl_FSOpenFileChannel(interp, fileName, "r", 0);
  1433.     if (channel == NULL) {
  1434. Tcl_AppendResult(interp,"Error opening file "", 
  1435.  Tcl_GetString(fileName), 
  1436.                  "" for reading",(char*)NULL);
  1437. return NULL;
  1438.     }
  1439.     if (Tcl_SetChannelOption(interp, channel, "-translation", "binary")
  1440.     != TCL_OK) {
  1441. Tcl_Close(NULL, channel);
  1442. return NULL;
  1443.     }
  1444.     if (Tcl_SetChannelOption(interp, channel, "-encoding", "binary")
  1445.     != TCL_OK) {
  1446. Tcl_Close(NULL, channel);
  1447. return NULL;
  1448.     }
  1449.     /*  Allocate memory for the resource structure */
  1450.     lpIR = (BlockOfIconImagesPtr) ckalloc(sizeof(BlockOfIconImages));
  1451.     if (lpIR == NULL)    {
  1452. Tcl_AppendResult(interp,"Error allocating memory",(char*)NULL);
  1453. Tcl_Close(NULL, channel);
  1454. return NULL;
  1455.     }
  1456.     /*  Read in the header */
  1457.     if ((lpIR->nNumImages = ReadICOHeader( channel )) == -1)    {
  1458. Tcl_AppendResult(interp,"Invalid file header",(char*)NULL);
  1459. Tcl_Close(NULL, channel);
  1460. ckfree((char*) lpIR );
  1461. return NULL;
  1462.     }
  1463.     /*  Adjust the size of the struct to account for the images */
  1464.     lpNew = (BlockOfIconImagesPtr) ckrealloc((char*)lpIR, 
  1465. sizeof(BlockOfIconImages) + ((lpIR->nNumImages-1) * sizeof(ICONIMAGE)));
  1466.     if (lpNew == NULL) {
  1467. Tcl_AppendResult(interp,"Error allocating memory",(char*)NULL);
  1468. Tcl_Close(NULL, channel);
  1469. ckfree( (char*)lpIR );
  1470. return NULL;
  1471.     }
  1472.     lpIR = lpNew;
  1473.     /*  Allocate enough memory for the icon directory entries */
  1474.     lpIDE = (LPICONDIRENTRY) ckalloc(lpIR->nNumImages * sizeof(ICONDIRENTRY));
  1475.     if (lpIDE == NULL) {
  1476. Tcl_AppendResult(interp,"Error allocating memory",(char*)NULL);
  1477. Tcl_Close(NULL, channel);
  1478. ckfree( (char*)lpIR );
  1479. return NULL;
  1480.     }
  1481.     /*  Read in the icon directory entries */
  1482.     dwBytesRead = Tcl_Read(channel, (char*)lpIDE, 
  1483.    lpIR->nNumImages * sizeof( ICONDIRENTRY ));
  1484.     if (dwBytesRead != lpIR->nNumImages * sizeof( ICONDIRENTRY ))    {
  1485. Tcl_AppendResult(interp,"Error reading file",(char*)NULL);
  1486. Tcl_Close(NULL, channel);
  1487. ckfree( (char*)lpIR );
  1488. return NULL;
  1489.     }
  1490.     /* NULL-out everything to make memory management easier */
  1491.     for( i = 0; i < lpIR->nNumImages; i++ ) {
  1492. lpIR->IconImages[i].lpBits = NULL;
  1493.     }
  1494.     /*  Loop through and read in each image */
  1495.     for( i = 0; i < lpIR->nNumImages; i++ )    {
  1496. /*  Allocate memory for the resource */
  1497. lpIR->IconImages[i].lpBits = (LPBYTE) ckalloc(lpIDE[i].dwBytesInRes);
  1498. if (lpIR->IconImages[i].lpBits == NULL) {
  1499.     Tcl_AppendResult(interp,"Error allocating memory",(char*)NULL);
  1500.     goto readError;
  1501. }
  1502. lpIR->IconImages[i].dwNumBytes = lpIDE[i].dwBytesInRes;
  1503. /*  Seek to beginning of this image */
  1504. if (Tcl_Seek(channel, lpIDE[i].dwImageOffset, FILE_BEGIN) == -1) {
  1505.     Tcl_AppendResult(interp,"Error seeking in file",(char*)NULL);
  1506.     goto readError;
  1507. }
  1508. /*  Read it in */
  1509. dwBytesRead = Tcl_Read( channel, lpIR->IconImages[i].lpBits, 
  1510.        lpIDE[i].dwBytesInRes);
  1511. if (dwBytesRead != lpIDE[i].dwBytesInRes) {
  1512.     Tcl_AppendResult(interp,"Error reading file",(char*)NULL);
  1513.     goto readError;
  1514. }
  1515. /*  Set the internal pointers appropriately */
  1516. if (!AdjustIconImagePointers( &(lpIR->IconImages[i]))) {
  1517.     Tcl_AppendResult(interp,"Error converting to internal format",
  1518.      (char*)NULL);
  1519.     goto readError;
  1520. }
  1521. lpIR->IconImages[i].hIcon =
  1522.     MakeIconOrCursorFromResource(&(lpIR->IconImages[i]), isIcon);
  1523.     }
  1524.     /*  Clean up */
  1525.     ckfree((char*)lpIDE);
  1526.     Tcl_Close(NULL, channel);
  1527.     if (lpIR == NULL){
  1528. Tcl_AppendResult(interp,"Reading of ", Tcl_GetString(fileName),
  1529.  " failed!",(char*)NULL);
  1530. return NULL;
  1531.     }
  1532.     return lpIR;
  1533.   readError:
  1534.     Tcl_Close(NULL, channel);
  1535.     for( i = 0; i < lpIR->nNumImages; i++ )    {
  1536.      if (lpIR->IconImages[i].lpBits != NULL) {
  1537.     ckfree((char*)lpIR->IconImages[i].lpBits);
  1538. }
  1539.     }
  1540.     ckfree((char*)lpIDE );
  1541.     ckfree((char*)lpIR );
  1542.     return NULL;
  1543. }
  1544. /*
  1545.  *----------------------------------------------------------------------
  1546.  *
  1547.  * GetTopLevel --
  1548.  *
  1549.  * This function retrieves the TkWindow associated with the
  1550.  * given HWND.
  1551.  *
  1552.  * Results:
  1553.  * Returns the matching TkWindow.
  1554.  *
  1555.  * Side effects:
  1556.  * None.
  1557.  *
  1558.  *----------------------------------------------------------------------
  1559.  */
  1560. static TkWindow *
  1561. GetTopLevel(hwnd)
  1562.     HWND hwnd;
  1563. {
  1564.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
  1565.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  1566.     /*
  1567.      * If this function is called before the CreateWindowEx call
  1568.      * has completed, then the user data slot will not have been
  1569.      * set yet, so we use the global createWindow variable.
  1570.      */
  1571.     if (tsdPtr->createWindow) {
  1572. return tsdPtr->createWindow;
  1573.     }
  1574. #ifdef _WIN64
  1575.     return (TkWindow *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1576. #else
  1577.     return (TkWindow *) GetWindowLong(hwnd, GWL_USERDATA);
  1578. #endif
  1579. }
  1580. /*
  1581.  *----------------------------------------------------------------------
  1582.  *
  1583.  * SetLimits --
  1584.  *
  1585.  * Updates the minimum and maximum window size constraints.
  1586.  *
  1587.  * Results:
  1588.  * None.
  1589.  *
  1590.  * Side effects:
  1591.  * Changes the values of the info pointer to reflect the current
  1592.  * minimum and maximum size values.
  1593.  *
  1594.  *----------------------------------------------------------------------
  1595.  */
  1596. static void
  1597. SetLimits(hwnd, info)
  1598.     HWND hwnd;
  1599.     MINMAXINFO *info;
  1600. {
  1601.     register WmInfo *wmPtr;
  1602.     int maxWidth, maxHeight;
  1603.     int minWidth, minHeight;
  1604.     int base;
  1605.     TkWindow *winPtr = GetTopLevel(hwnd);
  1606.     if (winPtr == NULL) {
  1607. return;
  1608.     }
  1609.     wmPtr = winPtr->wmInfoPtr;
  1610.     /*
  1611.      * Copy latest constraint info.
  1612.      */
  1613.     wmPtr->defMinWidth = info->ptMinTrackSize.x;
  1614.     wmPtr->defMinHeight = info->ptMinTrackSize.y;
  1615.     wmPtr->defMaxWidth = info->ptMaxTrackSize.x;
  1616.     wmPtr->defMaxHeight = info->ptMaxTrackSize.y;
  1617.     GetMaxSize(wmPtr, &maxWidth, &maxHeight);
  1618.     GetMinSize(wmPtr, &minWidth, &minHeight);
  1619.     if (wmPtr->gridWin != NULL) {
  1620. base = winPtr->reqWidth - (wmPtr->reqGridWidth * wmPtr->widthInc);
  1621. if (base < 0) {
  1622.     base = 0;
  1623. }
  1624. base += wmPtr->borderWidth;
  1625. info->ptMinTrackSize.x = base + (minWidth * wmPtr->widthInc);
  1626. info->ptMaxTrackSize.x = base + (maxWidth * wmPtr->widthInc);
  1627. base = winPtr->reqHeight - (wmPtr->reqGridHeight * wmPtr->heightInc);
  1628. if (base < 0) {
  1629.     base = 0;
  1630. }
  1631. base += wmPtr->borderHeight;
  1632. info->ptMinTrackSize.y = base + (minHeight * wmPtr->heightInc);
  1633. info->ptMaxTrackSize.y = base + (maxHeight * wmPtr->heightInc);
  1634.     } else {
  1635. info->ptMaxTrackSize.x = maxWidth + wmPtr->borderWidth;
  1636. info->ptMaxTrackSize.y = maxHeight + wmPtr->borderHeight;
  1637. info->ptMinTrackSize.x = minWidth + wmPtr->borderWidth;
  1638. info->ptMinTrackSize.y = minHeight + wmPtr->borderHeight;
  1639.     }
  1640.     /*
  1641.      * If the window isn't supposed to be resizable, then set the
  1642.      * minimum and maximum dimensions to be the same as the current size.
  1643.      */
  1644.     if (!(wmPtr->flags & WM_SYNC_PENDING)) {
  1645. if (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) {
  1646.     info->ptMinTrackSize.x = winPtr->changes.width
  1647. + wmPtr->borderWidth;
  1648.     info->ptMaxTrackSize.x = info->ptMinTrackSize.x;
  1649. }
  1650. if (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {
  1651.     info->ptMinTrackSize.y = winPtr->changes.height
  1652. + wmPtr->borderHeight;
  1653.     info->ptMaxTrackSize.y = info->ptMinTrackSize.y;
  1654. }
  1655.     }
  1656. }
  1657. /*
  1658.  *----------------------------------------------------------------------
  1659.  *
  1660.  * TkWinWmCleanup --
  1661.  *
  1662.  * Unregisters classes registered by the window manager. This is
  1663.  * called from the DLL main entry point when the DLL is unloaded.
  1664.  *
  1665.  * Results:
  1666.  * None.
  1667.  *
  1668.  * Side effects:
  1669.  * The window classes are discarded.
  1670.  *
  1671.  *----------------------------------------------------------------------
  1672.  */
  1673. void
  1674. TkWinWmCleanup(hInstance)
  1675.     HINSTANCE hInstance;
  1676. {
  1677.     ThreadSpecificData *tsdPtr;
  1678.     /*
  1679.      * If we're using stubs to access the Tcl library, and they
  1680.      * haven't been initialized, we can't call Tcl_GetThreadData.
  1681.      */
  1682. #ifdef USE_TCL_STUBS
  1683.     if (tclStubsPtr == NULL) {
  1684.         return;
  1685.     }
  1686. #endif
  1687.     if (!initialized) {
  1688. return;
  1689.     }
  1690.     initialized = 0;
  1691.     tsdPtr = (ThreadSpecificData *)
  1692.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  1693.     if (!tsdPtr->initialized) {
  1694.         return;
  1695.     }
  1696.     tsdPtr->initialized = 0;
  1697.     UnregisterClass(TK_WIN_TOPLEVEL_CLASS_NAME, hInstance);
  1698. }
  1699. /*
  1700.  *--------------------------------------------------------------
  1701.  *
  1702.  * TkWmNewWindow --
  1703.  *
  1704.  * This procedure is invoked whenever a new top-level
  1705.  * window is created.  Its job is to initialize the WmInfo
  1706.  * structure for the window.
  1707.  *
  1708.  * Results:
  1709.  * None.
  1710.  *
  1711.  * Side effects:
  1712.  * A WmInfo structure gets allocated and initialized.
  1713.  *
  1714.  *--------------------------------------------------------------
  1715.  */
  1716. void
  1717. TkWmNewWindow(winPtr)
  1718.     TkWindow *winPtr; /* Newly-created top-level window. */
  1719. {
  1720.     register WmInfo *wmPtr;
  1721.     wmPtr = (WmInfo *) ckalloc(sizeof(WmInfo));
  1722.     /*
  1723.      * Initialize full structure, then set what isn't NULL
  1724.      */
  1725.     ZeroMemory(wmPtr, sizeof(WmInfo));
  1726.     winPtr->wmInfoPtr = wmPtr;
  1727.     wmPtr->winPtr = winPtr;
  1728.     wmPtr->hints.flags = InputHint | StateHint;
  1729.     wmPtr->hints.input = True;
  1730.     wmPtr->hints.initial_state = NormalState;
  1731.     wmPtr->hints.icon_pixmap = None;
  1732.     wmPtr->hints.icon_window = None;
  1733.     wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;
  1734.     wmPtr->hints.icon_mask = None;
  1735.     wmPtr->hints.window_group = None;
  1736.     /*
  1737.      * Default the maximum dimensions to the size of the display.
  1738.      */
  1739.     wmPtr->defMinWidth = wmPtr->defMinHeight = 0;
  1740.     wmPtr->defMaxWidth = DisplayWidth(winPtr->display, winPtr->screenNum);
  1741.     wmPtr->defMaxHeight = DisplayHeight(winPtr->display, winPtr->screenNum);
  1742.     wmPtr->minWidth = wmPtr->minHeight = 1;
  1743.     wmPtr->maxWidth = wmPtr->maxHeight = 0;
  1744.     wmPtr->widthInc = wmPtr->heightInc = 1;
  1745.     wmPtr->minAspect.x = wmPtr->minAspect.y = 1;
  1746.     wmPtr->maxAspect.x = wmPtr->maxAspect.y = 1;
  1747.     wmPtr->reqGridWidth = wmPtr->reqGridHeight = -1;
  1748.     wmPtr->gravity = NorthWestGravity;
  1749.     wmPtr->width = -1;
  1750.     wmPtr->height = -1;
  1751.     wmPtr->x = winPtr->changes.x;
  1752.     wmPtr->y = winPtr->changes.y;
  1753.     wmPtr->crefObj = NULL;
  1754.     wmPtr->colorref = (COLORREF) NULL;
  1755.     wmPtr->alpha = 1.0;
  1756.     wmPtr->configWidth = -1;
  1757.     wmPtr->configHeight = -1;
  1758.     wmPtr->flags = WM_NEVER_MAPPED;
  1759.     wmPtr->nextPtr = winPtr->dispPtr->firstWmPtr;
  1760.     winPtr->dispPtr->firstWmPtr = wmPtr;
  1761.     /*
  1762.      * Tk must monitor structure events for top-level windows, in order
  1763.      * to detect size and position changes caused by window managers.
  1764.      */
  1765.     Tk_CreateEventHandler((Tk_Window) winPtr, StructureNotifyMask,
  1766.     TopLevelEventProc, (ClientData) winPtr);
  1767.     /*
  1768.      * Arrange for geometry requests to be reflected from the window
  1769.      * to the window manager.
  1770.      */
  1771.     Tk_ManageGeometry((Tk_Window) winPtr, &wmMgrType, (ClientData) 0);
  1772. }
  1773. /*
  1774.  *----------------------------------------------------------------------
  1775.  *
  1776.  * UpdateWrapper --
  1777.  *
  1778.  * This function creates the wrapper window that contains the
  1779.  * window decorations and menus for a toplevel.  This function
  1780.  * may be called after a window is mapped to change the window
  1781.  * style.
  1782.  *
  1783.  * Results:
  1784.  * None.
  1785.  *
  1786.  * Side effects:
  1787.  * Destroys any old wrapper window and replaces it with a newly
  1788.  * created wrapper.
  1789.  *
  1790.  *----------------------------------------------------------------------
  1791.  */
  1792. static void
  1793. UpdateWrapper(winPtr)
  1794.     TkWindow *winPtr; /* Top-level window to redecorate. */
  1795. {
  1796.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1797.     HWND parentHWND, oldWrapper = wmPtr->wrapper;
  1798.     HWND child, nextHWND, focusHWND;
  1799.     int x, y, width, height, state;
  1800.     WINDOWPLACEMENT place;
  1801.     HICON hSmallIcon = NULL;
  1802.     HICON hBigIcon = NULL;
  1803.     Tcl_DString titleString, classString;
  1804.     int *childStateInfo = NULL;
  1805.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
  1806.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  1807.     if (winPtr->window == None) {
  1808. /*
  1809.  * Ensure existence of the window to update the wrapper for.
  1810.  */
  1811. Tk_MakeWindowExist((Tk_Window) winPtr);
  1812.     }
  1813.     child = TkWinGetHWND(winPtr->window);
  1814.     parentHWND = NULL;
  1815.     /*
  1816.      * nextHWND will help us maintain Z order.
  1817.      * focusHWND will help us maintain focus, if we had it.
  1818.      */
  1819.     nextHWND = NULL;
  1820.     focusHWND = GetFocus();
  1821.     if ((oldWrapper == NULL) || (oldWrapper != GetForegroundWindow())) {
  1822. focusHWND = NULL;
  1823.     }
  1824.     if (winPtr->flags & TK_EMBEDDED) {
  1825. wmPtr->wrapper = (HWND) winPtr->privatePtr;
  1826. if (wmPtr->wrapper == NULL) {
  1827.     Tcl_Panic("UpdateWrapper: Cannot find container window");
  1828. }
  1829. if (!IsWindow(wmPtr->wrapper)) {
  1830.     Tcl_Panic("UpdateWrapper: Container was destroyed");
  1831. }
  1832.     } else {
  1833. /*
  1834.  * Pick the decorative frame style.  Override redirect windows get
  1835.  * created as undecorated popups if they have no transient parent,
  1836.  * otherwise they are children.  This allows splash screens to operate
  1837.  * as an independent window, while having dropdows (like for a
  1838.  * combobox) not grab focus away from their parent.  Transient windows
  1839.  * get a modal dialog frame.  Neither override, nor transient windows
  1840.  * appear in the Windows taskbar.  Note that a transient window does
  1841.  * not resize by default, so we need to explicitly add the
  1842.  * WS_THICKFRAME style if we want it to be resizeable.
  1843.  */
  1844. if (winPtr->atts.override_redirect) {
  1845.     wmPtr->style = WM_OVERRIDE_STYLE;
  1846.     wmPtr->exStyle = EX_OVERRIDE_STYLE;
  1847.     /* parent must be desktop even if we have a transient parent */
  1848.     parentHWND = GetDesktopWindow();
  1849.     if (wmPtr->masterPtr) {
  1850. wmPtr->style |= WS_CHILD;
  1851.     } else {
  1852. wmPtr->style |= WS_POPUP;
  1853.     }
  1854. } else if (wmPtr->masterPtr) {
  1855.     wmPtr->style = WM_TRANSIENT_STYLE;
  1856.     wmPtr->exStyle = EX_TRANSIENT_STYLE;
  1857.     parentHWND = Tk_GetHWND(Tk_WindowId(wmPtr->masterPtr));
  1858.     if (! ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) &&
  1859.     (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE))) {
  1860. wmPtr->style |= WS_THICKFRAME;
  1861.     }
  1862. } else {
  1863.     wmPtr->style = WM_TOPLEVEL_STYLE;
  1864.     wmPtr->exStyle = EX_TOPLEVEL_STYLE;
  1865. }
  1866. wmPtr->style   |= wmPtr->styleConfig;
  1867. wmPtr->exStyle |= wmPtr->exStyleConfig;
  1868. if ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE)
  1869. && (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)) {
  1870.     wmPtr->style &= ~ (WS_MAXIMIZEBOX | WS_SIZEBOX);
  1871. }
  1872. /*
  1873.  * Compute the geometry of the parent and child windows.
  1874.  */
  1875. if ((wmPtr->flags & WM_UPDATE_PENDING)) {
  1876.     Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
  1877. }
  1878. wmPtr->flags |= WM_CREATE_PENDING|WM_MOVE_PENDING;
  1879. UpdateGeometryInfo((ClientData)winPtr);
  1880. wmPtr->flags &= ~(WM_CREATE_PENDING|WM_MOVE_PENDING);
  1881. width = wmPtr->borderWidth + winPtr->changes.width;
  1882. height = wmPtr->borderHeight + winPtr->changes.height;
  1883. /*
  1884.  * Set the initial position from the user or program specified
  1885.  * location.  If nothing has been specified, then let the system
  1886.  * pick a location.
  1887.  */
  1888. if (!(wmPtr->sizeHintsFlags & (USPosition | PPosition))
  1889. && (wmPtr->flags & WM_NEVER_MAPPED)) {
  1890.     x = CW_USEDEFAULT;
  1891.     y = CW_USEDEFAULT;
  1892. } else {
  1893.     x = winPtr->changes.x;
  1894.     y = winPtr->changes.y;
  1895. }
  1896. /*
  1897.  * Create the containing window, and set the user data to point
  1898.  * to the TkWindow.
  1899.  */
  1900. tsdPtr->createWindow = winPtr;
  1901. Tcl_WinUtfToTChar(((wmPtr->title != NULL) ?
  1902.                            wmPtr->title : winPtr->nameUid), -1, &titleString);
  1903. Tcl_WinUtfToTChar(TK_WIN_TOPLEVEL_CLASS_NAME, -1, &classString);
  1904. wmPtr->wrapper = (*tkWinProcs->createWindowEx)(wmPtr->exStyle,
  1905. (LPCTSTR) Tcl_DStringValue(&classString),
  1906. (LPCTSTR) Tcl_DStringValue(&titleString),
  1907. wmPtr->style, x, y, width, height,
  1908. parentHWND, NULL, Tk_GetHINSTANCE(), NULL);
  1909. Tcl_DStringFree(&classString);
  1910. Tcl_DStringFree(&titleString);
  1911. #ifdef _WIN64
  1912. SetWindowLongPtr(wmPtr->wrapper, GWLP_USERDATA, (LONG_PTR) winPtr);
  1913. #else
  1914. SetWindowLong(wmPtr->wrapper, GWL_USERDATA, (LONG) winPtr);
  1915. #endif
  1916. tsdPtr->createWindow = NULL;
  1917. if ((wmPtr->exStyleConfig & WS_EX_LAYERED)
  1918. && setLayeredWindowAttributesProc != NULL) {
  1919.     /*
  1920.      * The user supplies a double from [0..1], but Windows wants an
  1921.      * int (transparent) 0..255 (opaque), so do the translation.
  1922.      * Add the 0.5 to round the value.
  1923.      */
  1924.     setLayeredWindowAttributesProc((HWND) wmPtr->wrapper,
  1925.     wmPtr->colorref, (BYTE) (wmPtr->alpha * 255 + 0.5),
  1926.     LWA_ALPHA | (wmPtr->crefObj ? LWA_COLORKEY : 0));
  1927. } else {
  1928.     /*
  1929.      * Layering not used or supported.
  1930.      */
  1931.     wmPtr->alpha = 1.0;
  1932.     if (wmPtr->crefObj) {
  1933. Tcl_DecrRefCount(wmPtr->crefObj);
  1934. wmPtr->crefObj = NULL;
  1935.     }
  1936. }
  1937. place.length = sizeof(WINDOWPLACEMENT);
  1938. GetWindowPlacement(wmPtr->wrapper, &place);
  1939. wmPtr->x = place.rcNormalPosition.left;
  1940. wmPtr->y = place.rcNormalPosition.top;
  1941. if (!(winPtr->flags & TK_ALREADY_DEAD)) {
  1942.     TkInstallFrameMenu((Tk_Window) winPtr);
  1943. }
  1944. if (oldWrapper && (oldWrapper != wmPtr->wrapper)
  1945. && !(wmPtr->exStyle & WS_EX_TOPMOST)) {
  1946.     /*
  1947.      * We will adjust wrapper to have the same Z order as oldWrapper
  1948.      * if it isn't a TOPMOST window.
  1949.      */
  1950.     nextHWND = GetNextWindow(oldWrapper, GW_HWNDPREV);
  1951. }
  1952.     }
  1953.     /*
  1954.      * Now we need to reparent the contained window and set its
  1955.      * style appropriately.  Be sure to update the style first so that
  1956.      * Windows doesn't try to set the focus to the child window.
  1957.      */
  1958. #ifdef _WIN64
  1959.     SetWindowLongPtr(child, GWL_STYLE,
  1960.     WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
  1961. #else
  1962.     SetWindowLong(child, GWL_STYLE,
  1963.     WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
  1964. #endif
  1965.     if (winPtr->flags & TK_EMBEDDED) {
  1966. #ifdef _WIN64
  1967. SetWindowLongPtr(child, GWLP_WNDPROC, (LONG_PTR) TopLevelProc);
  1968. #else
  1969. SetWindowLong(child, GWL_WNDPROC, (LONG) TopLevelProc);
  1970. #endif
  1971.     }
  1972.     SetParent(child, wmPtr->wrapper);
  1973.     if (oldWrapper) {
  1974. hSmallIcon = (HICON) SendMessage(oldWrapper, WM_GETICON, ICON_SMALL,
  1975. (LPARAM) NULL);
  1976. hBigIcon = (HICON) SendMessage(oldWrapper, WM_GETICON, ICON_BIG,
  1977. (LPARAM) NULL);
  1978.     }
  1979.     if (oldWrapper && (oldWrapper != wmPtr->wrapper)
  1980.     && (oldWrapper != GetDesktopWindow())) {
  1981. #ifdef _WIN64
  1982. SetWindowLongPtr(oldWrapper, GWLP_USERDATA, (LONG) NULL);
  1983. #else
  1984. SetWindowLong(oldWrapper, GWL_USERDATA, (LONG) NULL);
  1985. #endif
  1986. if (wmPtr->numTransients > 0) {
  1987.     /*
  1988.      * Unset the current wrapper as the parent for all transient
  1989.      * children for whom this is the master
  1990.      */
  1991.     WmInfo *wmPtr2;
  1992.     childStateInfo = (int *)ckalloc((unsigned) wmPtr->numTransients
  1993. * sizeof(int));
  1994.     state = 0;
  1995.     for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;
  1996.  wmPtr2 = wmPtr2->nextPtr) {
  1997. if (wmPtr2->masterPtr == winPtr) {
  1998.     if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
  1999. childStateInfo[state++] = wmPtr2->hints.initial_state;
  2000. SetParent(TkWinGetHWND(wmPtr2->winPtr->window), NULL);
  2001.     }
  2002. }
  2003.     }
  2004. }
  2005. /*
  2006.  * Remove the menubar before destroying the window so the menubar
  2007.  * isn't destroyed.
  2008.  */
  2009. SetMenu(oldWrapper, NULL);
  2010. DestroyWindow(oldWrapper);
  2011.     }
  2012.     wmPtr->flags &= ~WM_NEVER_MAPPED;
  2013.     SendMessage(wmPtr->wrapper, TK_ATTACHWINDOW, (WPARAM) child, 0);
  2014.     /*
  2015.      * Force an initial transition from withdrawn to the real
  2016.      * initial state.  Set the Z order based on previous wrapper
  2017.      * before we set the state.
  2018.      */
  2019.     state = wmPtr->hints.initial_state;
  2020.     wmPtr->hints.initial_state = WithdrawnState;
  2021.     if (nextHWND) {
  2022. SetWindowPos(wmPtr->wrapper, nextHWND, 0, 0, 0, 0,
  2023. SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOSENDCHANGING
  2024. |SWP_NOOWNERZORDER);
  2025.     }
  2026.     TkpWmSetState(winPtr, state);
  2027.     if (hSmallIcon != NULL) {
  2028. SendMessage(wmPtr->wrapper,WM_SETICON,ICON_SMALL,(LPARAM)hSmallIcon);
  2029.     }
  2030.     if (hBigIcon != NULL) {
  2031. SendMessage(wmPtr->wrapper,WM_SETICON,ICON_BIG,(LPARAM)hBigIcon);
  2032.     }
  2033.     /*
  2034.      * If we are embedded then force a mapping of the window now,
  2035.      * because we do not necessarily own the wrapper and may not
  2036.      * get another opportunity to map ourselves. We should not be
  2037.      * in either iconified or zoomed states when we get here, so
  2038.      * it is safe to just check for TK_EMBEDDED without checking
  2039.      * what state we are supposed to be in (default to NormalState).
  2040.      */
  2041.     if (winPtr->flags & TK_EMBEDDED) {
  2042. XMapWindow(winPtr->display, winPtr->window);
  2043.     }
  2044.     /*
  2045.      * Set up menus on the wrapper if required.
  2046.      */
  2047.     if (wmPtr->hMenu != NULL) {
  2048. wmPtr->flags = WM_SYNC_PENDING;
  2049. SetMenu(wmPtr->wrapper, wmPtr->hMenu);
  2050. wmPtr->flags &= ~WM_SYNC_PENDING;
  2051.     }
  2052.     if (childStateInfo) {
  2053. if (wmPtr->numTransients > 0) {
  2054.     /*
  2055.      * Reset all transient children for whom this is the master
  2056.      */
  2057.     WmInfo *wmPtr2;
  2058.     state = 0;
  2059.     for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;
  2060.  wmPtr2 = wmPtr2->nextPtr) {
  2061. if (wmPtr2->masterPtr == winPtr) {
  2062.     if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
  2063. UpdateWrapper(wmPtr2->winPtr);
  2064. TkpWmSetState(wmPtr2->winPtr, childStateInfo[state++]);
  2065.     }
  2066. }
  2067.     }
  2068. }
  2069. ckfree((char *) childStateInfo);
  2070.     }
  2071.     /*
  2072.      * If this is the first window created by the application, then
  2073.      * we should activate the initial window.  Otherwise, if this had
  2074.      * the focus, we need to restore that.
  2075.      * XXX: Rewrapping generates a <FocusOut> and <FocusIn> that would
  2076.      * XXX: best be avoided, if we could safely mask them.
  2077.      */
  2078.     if (tsdPtr->firstWindow) {
  2079. tsdPtr->firstWindow = 0;
  2080. SetActiveWindow(wmPtr->wrapper);
  2081.     } else if (focusHWND) {
  2082. SetFocus(focusHWND);
  2083.     }
  2084. }
  2085. /*
  2086.  *--------------------------------------------------------------
  2087.  *
  2088.  * TkWmMapWindow --
  2089.  *
  2090.  * This procedure is invoked to map a top-level window.  This
  2091.  * module gets a chance to update all window-manager-related
  2092.  * information in properties before the window manager sees
  2093.  * the map event and checks the properties.  It also gets to
  2094.  * decide whether or not to even map the window after all.
  2095.  *
  2096.  * Results:
  2097.  * None.
  2098.  *
  2099.  * Side effects:
  2100.  * Properties of winPtr may get updated to provide up-to-date
  2101.  * information to the window manager.  The window may also get
  2102.  * mapped, but it may not be if this procedure decides that
  2103.  * isn't appropriate (e.g. because the window is withdrawn).
  2104.  *
  2105.  *--------------------------------------------------------------
  2106.  */
  2107. void
  2108. TkWmMapWindow(winPtr)
  2109.     TkWindow *winPtr; /* Top-level window that's about to
  2110.  * be mapped. */
  2111. {
  2112.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2113.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
  2114.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  2115.     if (!tsdPtr->initialized) {
  2116. InitWm();
  2117.     }
  2118.     if (wmPtr->flags & WM_NEVER_MAPPED) {
  2119. /*
  2120.  * Don't map a transient if the master is not mapped.
  2121.  */
  2122. if (wmPtr->masterPtr != NULL &&
  2123.         !Tk_IsMapped(wmPtr->masterPtr)) {
  2124.     wmPtr->hints.initial_state = WithdrawnState;
  2125.     return;
  2126. }
  2127.     } else {
  2128. if (wmPtr->hints.initial_state == WithdrawnState) {
  2129.     return;
  2130. }
  2131. /*
  2132.  * Map the window in either the iconified or normal state.  Note that
  2133.  * we only send a map event if the window is in the normal state.
  2134.  */
  2135. TkpWmSetState(winPtr, wmPtr->hints.initial_state);
  2136.     }
  2137.     /*
  2138.      * This is the first time this window has ever been mapped.
  2139.      * Store all the window-manager-related information for the
  2140.      * window.
  2141.      */
  2142.     UpdateWrapper(winPtr);
  2143. }
  2144. /*
  2145.  *--------------------------------------------------------------
  2146.  *
  2147.  * TkWmUnmapWindow --
  2148.  *
  2149.  * This procedure is invoked to unmap a top-level window.  The
  2150.  * only thing it does special is unmap the decorative frame before
  2151.  * unmapping the toplevel window.
  2152.  *
  2153.  * Results:
  2154.  * None.
  2155.  *
  2156.  * Side effects:
  2157.  * Unmaps the decorative frame and the window.
  2158.  *
  2159.  *--------------------------------------------------------------
  2160.  */
  2161. void
  2162. TkWmUnmapWindow(winPtr)
  2163.     TkWindow *winPtr; /* Top-level window that's about to
  2164.  * be unmapped. */
  2165. {
  2166.     TkpWmSetState(winPtr, WithdrawnState);
  2167. }
  2168. /*
  2169.  *----------------------------------------------------------------------
  2170.  *
  2171.  * TkpWmSetState --
  2172.  *
  2173.  * Sets the window manager state for the wrapper window of a
  2174.  * given toplevel window.
  2175.  *
  2176.  * Results:
  2177.  * None.
  2178.  *
  2179.  * Side effects:
  2180.  * May maximize, minimize, restore, or withdraw a window.
  2181.  *
  2182.  *----------------------------------------------------------------------
  2183.  */
  2184. void
  2185. TkpWmSetState(winPtr, state)
  2186.      TkWindow *winPtr; /* Toplevel window to operate on. */
  2187.      int state; /* One of IconicState, ZoomState, NormalState,
  2188.  * or WithdrawnState. */
  2189. {
  2190.     WmInfo *wmPtr = winPtr->wmInfoPtr;
  2191.     int cmd;
  2192.     if (wmPtr->flags & WM_NEVER_MAPPED) {
  2193. wmPtr->hints.initial_state = state;
  2194. return;
  2195.     }
  2196.     wmPtr->flags |= WM_SYNC_PENDING;
  2197.     if (state == WithdrawnState) {
  2198. cmd = SW_HIDE;
  2199.     } else if (state == IconicState) {
  2200. cmd = SW_SHOWMINNOACTIVE;
  2201.     } else if (state == NormalState) {
  2202. cmd = SW_SHOWNOACTIVATE;
  2203.     } else if (state == ZoomState) {
  2204. cmd = SW_SHOWMAXIMIZED;
  2205.     }
  2206.     ShowWindow(wmPtr->wrapper, cmd);
  2207.     wmPtr->flags &= ~WM_SYNC_PENDING;
  2208. }
  2209. /*
  2210.  *--------------------------------------------------------------
  2211.  *
  2212.  * TkWmDeadWindow --
  2213.  *
  2214.  * This procedure is invoked when a top-level window is
  2215.  * about to be deleted.  It cleans up the wm-related data
  2216.  * structures for the window.
  2217.  *
  2218.  * Results:
  2219.  * None.
  2220.  *
  2221.  * Side effects:
  2222.  * The WmInfo structure for winPtr gets freed up.
  2223.  *
  2224.  *--------------------------------------------------------------
  2225.  */
  2226. void
  2227. TkWmDeadWindow(winPtr)
  2228.     TkWindow *winPtr; /* Top-level window that's being deleted. */
  2229. {
  2230.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2231.     WmInfo *wmPtr2;
  2232.     if (wmPtr == NULL) {
  2233. return;
  2234.     }
  2235.     /*
  2236.      * Clean up event related window info.
  2237.      */
  2238.     if (winPtr->dispPtr->firstWmPtr == wmPtr) {
  2239. winPtr->dispPtr->firstWmPtr = wmPtr->nextPtr;
  2240.     } else {
  2241. register WmInfo *prevPtr;
  2242. for (prevPtr = winPtr->dispPtr->firstWmPtr; ;
  2243.      prevPtr = prevPtr->nextPtr) {
  2244.     if (prevPtr == NULL) {
  2245. Tcl_Panic("couldn't unlink window in TkWmDeadWindow");
  2246.     }
  2247.     if (prevPtr->nextPtr == wmPtr) {
  2248. prevPtr->nextPtr = wmPtr->nextPtr;
  2249. break;
  2250.     }
  2251. }
  2252.     }
  2253.     /*
  2254.      * Reset all transient windows whose master is the dead window.
  2255.      */
  2256.     for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;
  2257.  wmPtr2 = wmPtr2->nextPtr) {
  2258. if (wmPtr2->masterPtr == winPtr) {
  2259.     wmPtr->numTransients--;
  2260.     Tk_DeleteEventHandler((Tk_Window) wmPtr2->masterPtr,
  2261.             VisibilityChangeMask|StructureNotifyMask,
  2262.             WmWaitVisibilityOrMapProc, (ClientData) wmPtr2->winPtr);
  2263.     wmPtr2->masterPtr = NULL;
  2264.     if ((wmPtr2->wrapper != None)
  2265.     && !(wmPtr2->flags & (WM_NEVER_MAPPED))) {
  2266. UpdateWrapper(wmPtr2->winPtr);
  2267.     }
  2268. }
  2269.     }
  2270.     if (wmPtr->numTransients != 0)
  2271.         Tcl_Panic("numTransients should be 0");
  2272.     if (wmPtr->title != NULL) {
  2273. ckfree(wmPtr->title);
  2274.     }
  2275.     if (wmPtr->iconName != NULL) {
  2276. ckfree(wmPtr->iconName);
  2277.     }
  2278.     if (wmPtr->hints.flags & IconPixmapHint) {
  2279. Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
  2280.     }
  2281.     if (wmPtr->hints.flags & IconMaskHint) {
  2282. Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);
  2283.     }
  2284.     if (wmPtr->leaderName != NULL) {
  2285. ckfree(wmPtr->leaderName);
  2286.     }
  2287.     if (wmPtr->icon != NULL) {
  2288. wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
  2289. wmPtr2->iconFor = NULL;
  2290.     }
  2291.     if (wmPtr->iconFor != NULL) {
  2292. wmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr;
  2293. wmPtr2->icon = NULL;
  2294. wmPtr2->hints.flags &= ~IconWindowHint;
  2295.     }
  2296.     while (wmPtr->protPtr != NULL) {
  2297. ProtocolHandler *protPtr;
  2298. protPtr = wmPtr->protPtr;
  2299. wmPtr->protPtr = protPtr->nextPtr;
  2300. Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC);
  2301.     }
  2302.     if (wmPtr->cmdArgv != NULL) {
  2303. ckfree((char *) wmPtr->cmdArgv);
  2304.     }
  2305.     if (wmPtr->clientMachine != NULL) {
  2306. ckfree((char *) wmPtr->clientMachine);
  2307.     }
  2308.     if (wmPtr->flags & WM_UPDATE_PENDING) {
  2309. Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
  2310.     }
  2311.     if (wmPtr->masterPtr != NULL) {
  2312. wmPtr2 = wmPtr->masterPtr->wmInfoPtr;
  2313. /*
  2314.  * If we had a master, tell them that we aren't tied
  2315.  * to them anymore
  2316.  */
  2317. if (wmPtr2 != NULL) {
  2318.     wmPtr2->numTransients--;
  2319. }
  2320. Tk_DeleteEventHandler((Tk_Window) wmPtr->masterPtr,
  2321. VisibilityChangeMask|StructureNotifyMask,
  2322. WmWaitVisibilityOrMapProc, (ClientData) winPtr);
  2323. wmPtr->masterPtr = NULL;
  2324.     }
  2325.     if (wmPtr->crefObj != NULL) {
  2326. Tcl_DecrRefCount(wmPtr->crefObj);
  2327. wmPtr->crefObj = NULL;
  2328.     }
  2329.     /*
  2330.      * Destroy the decorative frame window.
  2331.      */
  2332.     if (!(winPtr->flags & TK_EMBEDDED)) {
  2333. if (wmPtr->wrapper != NULL) {
  2334.     DestroyWindow(wmPtr->wrapper);
  2335. } else {
  2336.     DestroyWindow(Tk_GetHWND(winPtr->window));
  2337. }
  2338.     }
  2339.     if (wmPtr->iconPtr != NULL) {
  2340. /*
  2341.  * This may delete the icon resource data.  I believe we
  2342.  * should do this after destroying the decorative frame,
  2343.  * because the decorative frame is using this icon.
  2344.  */
  2345.         DecrIconRefCount(wmPtr->iconPtr);
  2346.     }
  2347.     ckfree((char *) wmPtr);
  2348.     winPtr->wmInfoPtr = NULL;
  2349. }
  2350. /*
  2351.  *--------------------------------------------------------------
  2352.  *
  2353.  * TkWmSetClass --
  2354.  *
  2355.  * This procedure is invoked whenever a top-level window's
  2356.  * class is changed.  If the window has been mapped then this
  2357.  * procedure updates the window manager property for the
  2358.  * class.  If the window hasn't been mapped, the update is
  2359.  * deferred until just before the first mapping.
  2360.  *
  2361.  * Results:
  2362.  * None.
  2363.  *
  2364.  * Side effects:
  2365.  * A window property may get updated.
  2366.  *
  2367.  *--------------------------------------------------------------
  2368.  */
  2369. void
  2370. TkWmSetClass(winPtr)
  2371.     TkWindow *winPtr; /* Newly-created top-level window. */
  2372. {
  2373.     return;
  2374. }
  2375. /*
  2376.  *----------------------------------------------------------------------
  2377.  *
  2378.  * Tk_WmObjCmd --
  2379.  *
  2380.  * This procedure is invoked to process the "wm" Tcl command.
  2381.  * See the user documentation for details on what it does.
  2382.  *
  2383.  * Results:
  2384.  * A standard Tcl result.
  2385.  *
  2386.  * Side effects:
  2387.  * See the user documentation.
  2388.  *
  2389.  *----------------------------------------------------------------------
  2390.  */
  2391. /* ARGSUSED */
  2392. int
  2393. Tk_WmObjCmd(clientData, interp, objc, objv)
  2394.     ClientData clientData; /* Main window associated with
  2395.  * interpreter. */
  2396.     Tcl_Interp *interp; /* Current interpreter. */
  2397.     int objc; /* Number of arguments. */
  2398.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2399. {
  2400.     Tk_Window tkwin = (Tk_Window) clientData;
  2401.     static CONST char *optionStrings[] = {
  2402. "aspect", "attributes", "client", "colormapwindows",
  2403. "command", "deiconify", "focusmodel", "frame",
  2404. "geometry", "grid", "group", "iconbitmap",
  2405. "iconify", "iconmask", "iconname",
  2406. "iconphoto", "iconposition",
  2407. "iconwindow", "maxsize", "minsize", "overrideredirect",
  2408.         "positionfrom", "protocol", "resizable", "sizefrom",
  2409.         "stackorder", "state", "title", "transient",
  2410. "withdraw", (char *) NULL };
  2411.     enum options {
  2412.         WMOPT_ASPECT, WMOPT_ATTRIBUTES, WMOPT_CLIENT, WMOPT_COLORMAPWINDOWS,
  2413. WMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FRAME,
  2414. WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP, WMOPT_ICONBITMAP,
  2415. WMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME,
  2416. WMOPT_ICONPHOTO, WMOPT_ICONPOSITION,
  2417. WMOPT_ICONWINDOW, WMOPT_MAXSIZE, WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT,
  2418.         WMOPT_POSITIONFROM, WMOPT_PROTOCOL, WMOPT_RESIZABLE, WMOPT_SIZEFROM,
  2419.         WMOPT_STACKORDER, WMOPT_STATE, WMOPT_TITLE, WMOPT_TRANSIENT,
  2420. WMOPT_WITHDRAW };
  2421.     int index, length;
  2422.     char *argv1;
  2423.     TkWindow *winPtr;
  2424.     TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
  2425.     if (objc < 2) {
  2426. wrongNumArgs:
  2427. Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?");
  2428. return TCL_ERROR;
  2429.     }
  2430.     argv1 = Tcl_GetStringFromObj(objv[1], &length);
  2431.     if ((argv1[0] == 't') && (strncmp(argv1, "tracing", length) == 0)
  2432.     && (length >= 3)) {
  2433. int wmTracing;
  2434. if ((objc != 2) && (objc != 3)) {
  2435.     Tcl_WrongNumArgs(interp, 2, objv, "?boolean?");
  2436.     return TCL_ERROR;
  2437. }
  2438. if (objc == 2) {
  2439.     Tcl_SetResult(interp,
  2440.     ((dispPtr->flags & TK_DISPLAY_WM_TRACING) ? "on" : "off"),
  2441.     TCL_STATIC);
  2442.     return TCL_OK;
  2443. }
  2444. if (Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing) != TCL_OK) {
  2445.     return TCL_ERROR;
  2446. }
  2447. if (wmTracing) {
  2448.     dispPtr->flags |= TK_DISPLAY_WM_TRACING;
  2449. } else {
  2450.     dispPtr->flags &= ~TK_DISPLAY_WM_TRACING;
  2451. }
  2452. return TCL_OK;
  2453.     }
  2454.     if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
  2455.     &index) != TCL_OK) {
  2456. return TCL_ERROR;
  2457.     }
  2458.     if (objc < 3) {
  2459. goto wrongNumArgs;
  2460.     }
  2461.     if (TkGetWindowFromObj(interp, tkwin, objv[2], (Tk_Window *) &winPtr)
  2462.     != TCL_OK) {
  2463. return TCL_ERROR;
  2464.     }
  2465.     if (!Tk_IsTopLevel(winPtr)) {
  2466. Tcl_AppendResult(interp, "window "", winPtr->pathName,
  2467. "" isn't a top-level window", (char *) NULL);
  2468. return TCL_ERROR;
  2469.     }
  2470.     switch ((enum options) index) {
  2471.       case WMOPT_ASPECT:
  2472. return WmAspectCmd(tkwin, winPtr, interp, objc, objv);
  2473.       case WMOPT_ATTRIBUTES:
  2474. return WmAttributesCmd(tkwin, winPtr, interp, objc, objv);
  2475.       case WMOPT_CLIENT:
  2476. return WmClientCmd(tkwin, winPtr, interp, objc, objv);
  2477.       case WMOPT_COLORMAPWINDOWS:
  2478. return WmColormapwindowsCmd(tkwin, winPtr, interp, objc, objv);
  2479.       case WMOPT_COMMAND:
  2480. return WmCommandCmd(tkwin, winPtr, interp, objc, objv);
  2481.       case WMOPT_DEICONIFY:
  2482. return WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv);
  2483.       case WMOPT_FOCUSMODEL:
  2484. return WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv);
  2485.       case WMOPT_FRAME:
  2486. return WmFrameCmd(tkwin, winPtr, interp, objc, objv);
  2487.       case WMOPT_GEOMETRY:
  2488. return WmGeometryCmd(tkwin, winPtr, interp, objc, objv);
  2489.       case WMOPT_GRID:
  2490. return WmGridCmd(tkwin, winPtr, interp, objc, objv);
  2491.       case WMOPT_GROUP:
  2492. return WmGroupCmd(tkwin, winPtr, interp, objc, objv);
  2493.       case WMOPT_ICONBITMAP:
  2494. return WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv);
  2495.       case WMOPT_ICONIFY:
  2496. return WmIconifyCmd(tkwin, winPtr, interp, objc, objv);
  2497.       case WMOPT_ICONMASK:
  2498. return WmIconmaskCmd(tkwin, winPtr, interp, objc, objv);
  2499.       case WMOPT_ICONNAME:
  2500. return WmIconnameCmd(tkwin, winPtr, interp, objc, objv);
  2501.       case WMOPT_ICONPHOTO:
  2502.         return WmIconphotoCmd(tkwin, winPtr, interp, objc, objv);
  2503.       case WMOPT_ICONPOSITION:
  2504. return WmIconpositionCmd(tkwin, winPtr, interp, objc, objv);
  2505.       case WMOPT_ICONWINDOW:
  2506. return WmIconwindowCmd(tkwin, winPtr, interp, objc, objv);
  2507.       case WMOPT_MAXSIZE:
  2508. return WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv);
  2509.       case WMOPT_MINSIZE:
  2510. return WmMinsizeCmd(tkwin, winPtr, interp, objc, objv);
  2511.       case WMOPT_OVERRIDEREDIRECT:
  2512. return WmOverrideredirectCmd(tkwin, winPtr, interp, objc, objv);
  2513.       case WMOPT_POSITIONFROM:
  2514. return WmPositionfromCmd(tkwin, winPtr, interp, objc, objv);
  2515.       case WMOPT_PROTOCOL:
  2516. return WmProtocolCmd(tkwin, winPtr, interp, objc, objv);
  2517.       case WMOPT_RESIZABLE:
  2518. return WmResizableCmd(tkwin, winPtr, interp, objc, objv);
  2519.       case WMOPT_SIZEFROM:
  2520. return WmSizefromCmd(tkwin, winPtr, interp, objc, objv);
  2521.       case WMOPT_STACKORDER:
  2522. return WmStackorderCmd(tkwin, winPtr, interp, objc, objv);
  2523.       case WMOPT_STATE:
  2524. return WmStateCmd(tkwin, winPtr, interp, objc, objv);
  2525.       case WMOPT_TITLE:
  2526. return WmTitleCmd(tkwin, winPtr, interp, objc, objv);
  2527.       case WMOPT_TRANSIENT:
  2528. return WmTransientCmd(tkwin, winPtr, interp, objc, objv);
  2529.       case WMOPT_WITHDRAW:
  2530. return WmWithdrawCmd(tkwin, winPtr, interp, objc, objv);
  2531.     }
  2532.     /* This should not happen */
  2533.     return TCL_ERROR;
  2534. }
  2535. /*
  2536.  *----------------------------------------------------------------------
  2537.  *
  2538.  * WmAspectCmd --
  2539.  *
  2540.  * This procedure is invoked to process the "wm aspect" Tcl command.
  2541.  * See the user documentation for details on what it does.
  2542.  *
  2543.  * Results:
  2544.  * A standard Tcl result.
  2545.  *
  2546.  * Side effects:
  2547.  * See the user documentation.
  2548.  *
  2549.  *----------------------------------------------------------------------
  2550.  */
  2551. static int
  2552. WmAspectCmd(tkwin, winPtr, interp, objc, objv)
  2553.     Tk_Window tkwin; /* Main window of the application. */
  2554.     TkWindow *winPtr;           /* Toplevel to work with */
  2555.     Tcl_Interp *interp; /* Current interpreter. */
  2556.     int objc; /* Number of arguments. */
  2557.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2558. {
  2559.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2560.     int numer1, denom1, numer2, denom2;
  2561.     if ((objc != 3) && (objc != 7)) {
  2562. Tcl_WrongNumArgs(interp, 2, objv,
  2563. "window ?minNumer minDenom maxNumer maxDenom?");
  2564. return TCL_ERROR;
  2565.     }
  2566.     if (objc == 3) {
  2567. if (wmPtr->sizeHintsFlags & PAspect) {
  2568.     char buf[TCL_INTEGER_SPACE * 4];
  2569.     sprintf(buf, "%d %d %d %d", wmPtr->minAspect.x,
  2570.     wmPtr->minAspect.y, wmPtr->maxAspect.x,
  2571.     wmPtr->maxAspect.y);
  2572.     Tcl_SetResult(interp, buf, TCL_VOLATILE);
  2573. }
  2574. return TCL_OK;
  2575.     }
  2576.     if (*Tcl_GetString(objv[3]) == '') {
  2577. wmPtr->sizeHintsFlags &= ~PAspect;
  2578.     } else {
  2579. if ((Tcl_GetIntFromObj(interp, objv[3], &numer1) != TCL_OK)
  2580. || (Tcl_GetIntFromObj(interp, objv[4], &denom1) != TCL_OK)
  2581. || (Tcl_GetIntFromObj(interp, objv[5], &numer2) != TCL_OK)
  2582. || (Tcl_GetIntFromObj(interp, objv[6], &denom2) != TCL_OK)) {
  2583.     return TCL_ERROR;
  2584. }
  2585. if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) ||
  2586. (denom2 <= 0)) {
  2587.     Tcl_SetResult(interp, "aspect number can't be <= 0",
  2588.     TCL_STATIC);
  2589.     return TCL_ERROR;
  2590. }
  2591. wmPtr->minAspect.x = numer1;
  2592. wmPtr->minAspect.y = denom1;
  2593. wmPtr->maxAspect.x = numer2;
  2594. wmPtr->maxAspect.y = denom2;
  2595. wmPtr->sizeHintsFlags |= PAspect;
  2596.     }
  2597.     WmUpdateGeom(wmPtr, winPtr);
  2598.     return TCL_OK;
  2599. }
  2600. /*
  2601.  *----------------------------------------------------------------------
  2602.  *
  2603.  * WmAttributesCmd --
  2604.  *
  2605.  * This procedure is invoked to process the "wm attributes" Tcl command.
  2606.  * See the user documentation for details on what it does.
  2607.  *
  2608.  * Results:
  2609.  * A standard Tcl result.
  2610.  *
  2611.  * Side effects:
  2612.  * See the user documentation.
  2613.  *
  2614.  *----------------------------------------------------------------------
  2615.  */
  2616. static int
  2617. WmAttributesCmd(tkwin, winPtr, interp, objc, objv)
  2618.     Tk_Window tkwin; /* Main window of the application. */
  2619.     TkWindow *winPtr;           /* Toplevel to work with */
  2620.     Tcl_Interp *interp; /* Current interpreter. */
  2621.     int objc; /* Number of arguments. */
  2622.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2623. {
  2624.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2625.     LONG style, exStyle, styleBit, *stylePtr;
  2626.     char *string;
  2627.     int i, boolean, length, updatewrapper = 0;
  2628.     if ((objc < 3) || ((objc > 5) && ((objc%2) == 0))) {
  2629.         configArgs:
  2630. Tcl_WrongNumArgs(interp, 2, objv,
  2631. "window"
  2632. " ?-alpha ?double??"
  2633. " ?-transparentcolor ?color??"
  2634. " ?-disabled ?bool??"
  2635. " ?-toolwindow ?bool??"
  2636. " ?-topmost ?bool??");
  2637. return TCL_ERROR;
  2638.     }
  2639.     exStyle = wmPtr->exStyleConfig;
  2640.     style   = wmPtr->styleConfig;
  2641.     if (objc == 3) {
  2642. Tcl_Obj *objPtr = Tcl_NewObj();
  2643. Tcl_ListObjAppendElement(NULL, objPtr,
  2644. Tcl_NewStringObj("-alpha", -1));
  2645. Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewDoubleObj(wmPtr->alpha));
  2646. Tcl_ListObjAppendElement(NULL, objPtr,
  2647. Tcl_NewStringObj("-transparentcolor", -1));
  2648. Tcl_ListObjAppendElement(NULL, objPtr,
  2649. wmPtr->crefObj ? wmPtr->crefObj : Tcl_NewObj());
  2650. Tcl_ListObjAppendElement(NULL, objPtr,
  2651. Tcl_NewStringObj("-disabled", -1));
  2652. Tcl_ListObjAppendElement(NULL, objPtr,
  2653. Tcl_NewBooleanObj((style & WS_DISABLED)));
  2654. Tcl_ListObjAppendElement(NULL, objPtr,
  2655. Tcl_NewStringObj("-toolwindow", -1));
  2656. Tcl_ListObjAppendElement(NULL, objPtr,
  2657. Tcl_NewBooleanObj((exStyle & WS_EX_TOOLWINDOW)));
  2658. Tcl_ListObjAppendElement(NULL, objPtr,
  2659. Tcl_NewStringObj("-topmost", -1));
  2660. Tcl_ListObjAppendElement(NULL, objPtr,
  2661. Tcl_NewBooleanObj((exStyle & WS_EX_TOPMOST)));
  2662. Tcl_SetObjResult(interp, objPtr);
  2663. return TCL_OK;
  2664.     }
  2665.     for (i = 3; i < objc; i += 2) {
  2666. string = Tcl_GetStringFromObj(objv[i], &length);
  2667. if ((length < 2) || (string[0] != '-')) {
  2668.     goto configArgs;
  2669. }
  2670. if (strncmp(string, "-disabled", length) == 0) {
  2671.     stylePtr = &style;
  2672.     styleBit = WS_DISABLED;
  2673. } else if ((strncmp(string, "-alpha", length) == 0)
  2674. || ((length > 2) && (strncmp(string, "-transparentcolor",
  2675.      length) == 0))) {
  2676.     stylePtr = &exStyle;
  2677.     styleBit = WS_EX_LAYERED;
  2678. } else if ((length > 3)
  2679.    && (strncmp(string, "-toolwindow", length) == 0)) {
  2680.     stylePtr = &exStyle;
  2681.     styleBit = WS_EX_TOOLWINDOW;
  2682.     if (objc != 4) {
  2683. /*
  2684.  * Changes to toolwindow style require an update
  2685.  */
  2686. updatewrapper = 1;
  2687.     }
  2688. } else if ((length > 3)
  2689.    && (strncmp(string, "-topmost", length) == 0)) {
  2690.     stylePtr = &exStyle;
  2691.     styleBit = WS_EX_TOPMOST;
  2692.     if ((i < objc-1) && (winPtr->flags & TK_EMBEDDED)) {
  2693. Tcl_AppendResult(interp, "can't set topmost flag on ",
  2694. winPtr->pathName, ": it is an embedded window",
  2695. (char *) NULL);
  2696. return TCL_ERROR;
  2697.     }
  2698. } else {
  2699.     goto configArgs;
  2700. }
  2701. if (styleBit == WS_EX_LAYERED) {
  2702.     if (objc == 4) {
  2703. if (string[1] == 'a') { /* -alpha */
  2704.     Tcl_SetObjResult(interp, Tcl_NewDoubleObj(wmPtr->alpha));
  2705. } else { /* -transparentcolor */
  2706.     Tcl_SetObjResult(interp,
  2707.     wmPtr->crefObj ? wmPtr->crefObj : Tcl_NewObj());
  2708. }
  2709.     } else {
  2710. if (string[1] == 'a') { /* -alpha */
  2711.     double dval;
  2712.     if (Tcl_GetDoubleFromObj(interp, objv[i+1], &dval)
  2713.     != TCL_OK) {
  2714. return TCL_ERROR;
  2715.     }
  2716.     /*
  2717.      * The user should give (transparent) 0 .. 1.0 (opaque),
  2718.      * but we ignore the setting of this (it will always be 1)
  2719.      * in the case that the API is not available.
  2720.      */
  2721.     if (dval < 0.0) {
  2722. dval = 0;
  2723.     } else if (dval > 1.0) {
  2724. dval = 1;
  2725.     }
  2726.     wmPtr->alpha = dval;
  2727. } else { /* -transparentcolor */
  2728.     char *crefstr = Tcl_GetStringFromObj(objv[i+1], &length);
  2729.     if (length == 0) {
  2730. /* reset to no transparent color */
  2731. if (wmPtr->crefObj) {
  2732.     Tcl_DecrRefCount(wmPtr->crefObj);
  2733.     wmPtr->crefObj = NULL;
  2734. }
  2735.     } else {
  2736. XColor *cPtr =
  2737.     Tk_GetColor(interp, tkwin, Tk_GetUid(crefstr));
  2738. if (cPtr == NULL) {
  2739.     return TCL_ERROR;
  2740. }
  2741. if (wmPtr->crefObj) {
  2742.     Tcl_DecrRefCount(wmPtr->crefObj);
  2743. }
  2744. wmPtr->crefObj = objv[i+1];
  2745. Tcl_IncrRefCount(wmPtr->crefObj);
  2746. wmPtr->colorref = RGB((BYTE) (cPtr->red >> 8),
  2747. (BYTE) (cPtr->green >> 8),
  2748. (BYTE) (cPtr->blue >> 8));
  2749. Tk_FreeColor(cPtr);
  2750.     }
  2751. }
  2752. /*
  2753.  * Only ever add the WS_EX_LAYERED bit, as it can cause
  2754.  * flashing to change this window style.  This allows things
  2755.  * like fading tooltips to avoid flash ugliness without
  2756.  * forcing all window to be layered.
  2757.  */
  2758. if ((wmPtr->alpha < 1.0) || (wmPtr->crefObj != NULL)) {
  2759.     *stylePtr |= styleBit;
  2760. }
  2761. if ((setLayeredWindowAttributesProc != NULL)
  2762. && (wmPtr->wrapper != NULL)) {
  2763.     /*
  2764.      * Set the window directly regardless of UpdateWrapper.
  2765.      * The user supplies a double from [0..1], but Windows
  2766.      * wants an int (transparent) 0..255 (opaque), so do the
  2767.      * translation.  Add the 0.5 to round the value.
  2768.      */
  2769.     if (!(wmPtr->exStyleConfig & WS_EX_LAYERED)) {
  2770. SetWindowLongPtr(wmPtr->wrapper, GWL_EXSTYLE,
  2771. *stylePtr);
  2772.     }
  2773.     setLayeredWindowAttributesProc((HWND) wmPtr->wrapper,
  2774.     wmPtr->colorref, (BYTE) (wmPtr->alpha * 255 + 0.5),
  2775.     LWA_ALPHA | (wmPtr->crefObj ? LWA_COLORKEY : 0));
  2776. }
  2777.     }
  2778. } else {
  2779.     if ((i < objc-1) &&
  2780.     (Tcl_GetBooleanFromObj(interp, objv[i+1], &boolean)
  2781.     != TCL_OK)) {
  2782. return TCL_ERROR;
  2783.     }
  2784.     if (objc == 4) {
  2785. Tcl_SetIntObj(Tcl_GetObjResult(interp),
  2786. ((*stylePtr & styleBit) != 0));
  2787.     } else if (boolean) {
  2788. *stylePtr |= styleBit;
  2789.     } else {
  2790. *stylePtr &= ~styleBit;
  2791.     }
  2792. }
  2793. if ((styleBit == WS_EX_TOPMOST) && (wmPtr->wrapper != NULL)) {
  2794.     /*
  2795.      * Force the topmost position aspect to ensure that switching
  2796.      * between (no)topmost reflects properly when rewrapped.
  2797.      */
  2798.     SetWindowPos(wmPtr->wrapper,
  2799.     ((exStyle & WS_EX_TOPMOST) ?
  2800.     HWND_TOPMOST : HWND_NOTOPMOST), 0, 0, 0, 0,
  2801.     SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOSENDCHANGING
  2802.     |SWP_NOOWNERZORDER);
  2803. }
  2804.     }
  2805.     if (wmPtr->styleConfig != style) {
  2806. /*
  2807.  * Currently this means only WS_DISABLED changed, which we can
  2808.  * effect with EnableWindow.
  2809.  */
  2810. wmPtr->styleConfig = style;
  2811. if ((wmPtr->exStyleConfig == exStyle)
  2812. && !(wmPtr->flags & WM_NEVER_MAPPED)) {
  2813.     EnableWindow(wmPtr->wrapper, (style & WS_DISABLED) ? 0 : 1);
  2814. }
  2815.     }
  2816.     if (wmPtr->exStyleConfig != exStyle) {
  2817. wmPtr->exStyleConfig = exStyle;
  2818. if (updatewrapper) {
  2819.     /*
  2820.      * UpdateWrapper ensure that all effects are properly handled,
  2821.      * such as TOOLWINDOW disappearing from the taskbar.
  2822.      */
  2823.     if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  2824. UpdateWrapper(winPtr);
  2825.     }
  2826. }
  2827.     }
  2828.     return TCL_OK;
  2829. }
  2830. /*
  2831.  *----------------------------------------------------------------------
  2832.  *
  2833.  * WmClientCmd --
  2834.  *
  2835.  * This procedure is invoked to process the "wm client" Tcl command.
  2836.  * See the user documentation for details on what it does.
  2837.  *
  2838.  * Results:
  2839.  * A standard Tcl result.
  2840.  *
  2841.  * Side effects:
  2842.  * See the user documentation.
  2843.  *
  2844.  *----------------------------------------------------------------------
  2845.  */
  2846. static int
  2847. WmClientCmd(tkwin, winPtr, interp, objc, objv)
  2848.     Tk_Window tkwin; /* Main window of the application. */
  2849.     TkWindow *winPtr;           /* Toplevel to work with */
  2850.     Tcl_Interp *interp; /* Current interpreter. */
  2851.     int objc; /* Number of arguments. */
  2852.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2853. {
  2854.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2855.     char *argv3;
  2856.     int length;
  2857.     if ((objc != 3) && (objc != 4)) {
  2858. Tcl_WrongNumArgs(interp, 2, objv, "window ?name?");
  2859. return TCL_ERROR;
  2860.     }
  2861.     if (objc == 3) {
  2862. if (wmPtr->clientMachine != NULL) {
  2863.     Tcl_SetResult(interp, wmPtr->clientMachine, TCL_STATIC);
  2864. }
  2865. return TCL_OK;
  2866.     }
  2867.     argv3 = Tcl_GetStringFromObj(objv[3], &length);
  2868.     if (argv3[0] == 0) {
  2869. if (wmPtr->clientMachine != NULL) {
  2870.     ckfree((char *) wmPtr->clientMachine);
  2871.     wmPtr->clientMachine = NULL;
  2872.     if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  2873. XDeleteProperty(winPtr->display, winPtr->window,
  2874. Tk_InternAtom((Tk_Window) winPtr,
  2875. "WM_CLIENT_MACHINE"));
  2876.     }
  2877. }
  2878. return TCL_OK;
  2879.     }
  2880.     if (wmPtr->clientMachine != NULL) {
  2881. ckfree((char *) wmPtr->clientMachine);
  2882.     }
  2883.     wmPtr->clientMachine = (char *)
  2884.     ckalloc((unsigned) (length + 1));
  2885.     strcpy(wmPtr->clientMachine, argv3);
  2886.     if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  2887. XTextProperty textProp;
  2888. if (XStringListToTextProperty(&wmPtr->clientMachine, 1, &textProp)
  2889. != 0) {
  2890.     XSetWMClientMachine(winPtr->display, winPtr->window,
  2891.     &textProp);
  2892.     XFree((char *) textProp.value);
  2893. }
  2894.     }
  2895.     return TCL_OK;
  2896. }
  2897. /*
  2898.  *----------------------------------------------------------------------
  2899.  *
  2900.  * WmColormapwindowsCmd --
  2901.  *
  2902.  * This procedure is invoked to process the "wm colormapwindows"
  2903.  * Tcl command.
  2904.  * See the user documentation for details on what it does.
  2905.  *
  2906.  * Results:
  2907.  * A standard Tcl result.
  2908.  *
  2909.  * Side effects:
  2910.  * See the user documentation.
  2911.  *
  2912.  *----------------------------------------------------------------------
  2913.  */
  2914. static int
  2915. WmColormapwindowsCmd(tkwin, winPtr, interp, objc, objv)
  2916.     Tk_Window tkwin; /* Main window of the application. */
  2917.     TkWindow *winPtr;           /* Toplevel to work with */
  2918.     Tcl_Interp *interp; /* Current interpreter. */
  2919.     int objc; /* Number of arguments. */
  2920.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  2921. {
  2922.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2923.     TkWindow **cmapList;
  2924.     TkWindow *winPtr2;
  2925.     int i, windowObjc, gotToplevel;
  2926.     Tcl_Obj **windowObjv;
  2927.     if ((objc != 3) && (objc != 4)) {
  2928. Tcl_WrongNumArgs(interp, 2, objv, "window ?windowList?");
  2929. return TCL_ERROR;
  2930.     }
  2931.     if (objc == 3) {
  2932. Tk_MakeWindowExist((Tk_Window) winPtr);
  2933. for (i = 0; i < wmPtr->cmapCount; i++) {
  2934.     if ((i == (wmPtr->cmapCount-1))
  2935.     && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) {
  2936. break;
  2937.     }
  2938.     Tcl_AppendElement(interp, wmPtr->cmapList[i]->pathName);
  2939. }
  2940. return TCL_OK;
  2941.     }
  2942.     if (Tcl_ListObjGetElements(interp, objv[3], &windowObjc, &windowObjv)
  2943.     != TCL_OK) {
  2944. return TCL_ERROR;
  2945.     }
  2946.     cmapList = (TkWindow **) ckalloc((unsigned)
  2947.     ((windowObjc+1)*sizeof(TkWindow*)));
  2948.     gotToplevel = 0;
  2949.     for (i = 0; i < windowObjc; i++) {
  2950. if (TkGetWindowFromObj(interp, tkwin, windowObjv[i],
  2951. (Tk_Window *) &winPtr2) != TCL_OK)
  2952. {
  2953.     ckfree((char *) cmapList);
  2954.     return TCL_ERROR;
  2955. }
  2956. if (winPtr2 == winPtr) {
  2957.     gotToplevel = 1;
  2958. }
  2959. if (winPtr2->window == None) {
  2960.     Tk_MakeWindowExist((Tk_Window) winPtr2);
  2961. }
  2962. cmapList[i] = winPtr2;
  2963.     }
  2964.     if (!gotToplevel) {
  2965. wmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP;
  2966. cmapList[windowObjc] = winPtr;
  2967. windowObjc++;
  2968.     } else {
  2969. wmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP;
  2970.     }
  2971.     wmPtr->flags |= WM_COLORMAPS_EXPLICIT;
  2972.     if (wmPtr->cmapList != NULL) {
  2973. ckfree((char *)wmPtr->cmapList);
  2974.     }
  2975.     wmPtr->cmapList = cmapList;
  2976.     wmPtr->cmapCount = windowObjc;
  2977.     /*
  2978.      * Now we need to force the updated colormaps to be installed.
  2979.      */
  2980.     if (wmPtr == winPtr->dispPtr->foregroundWmPtr) {
  2981. InstallColormaps(wmPtr->wrapper, WM_QUERYNEWPALETTE, 1);
  2982.     } else {
  2983. InstallColormaps(wmPtr->wrapper, WM_PALETTECHANGED, 0);
  2984.     }
  2985.     return TCL_OK;
  2986. }
  2987. /*
  2988.  *----------------------------------------------------------------------
  2989.  *
  2990.  * WmCommandCmd --
  2991.  *
  2992.  * This procedure is invoked to process the "wm command" Tcl command.
  2993.  * See the user documentation for details on what it does.
  2994.  *
  2995.  * Results:
  2996.  * A standard Tcl result.
  2997.  *
  2998.  * Side effects:
  2999.  * See the user documentation.
  3000.  *
  3001.  *----------------------------------------------------------------------
  3002.  */
  3003. static int
  3004. WmCommandCmd(tkwin, winPtr, interp, objc, objv)
  3005.     Tk_Window tkwin; /* Main window of the application. */
  3006.     TkWindow *winPtr;           /* Toplevel to work with */
  3007.     Tcl_Interp *interp; /* Current interpreter. */
  3008.     int objc; /* Number of arguments. */
  3009.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  3010. {
  3011.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  3012.     char *argv3;
  3013.     int cmdArgc;
  3014.     CONST char **cmdArgv;
  3015.     if ((objc != 3) && (objc != 4)) {
  3016. Tcl_WrongNumArgs(interp, 2, objv, "window ?value?");
  3017. return TCL_ERROR;
  3018.     }
  3019.     if (objc == 3) {
  3020. if (wmPtr->cmdArgv != NULL) {
  3021.     Tcl_SetResult(interp,
  3022.     Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv),
  3023.     TCL_DYNAMIC);
  3024. }
  3025. return TCL_OK;
  3026.     }
  3027.     argv3 = Tcl_GetString(objv[3]);
  3028.     if (argv3[0] == 0) {
  3029. if (wmPtr->cmdArgv != NULL) {
  3030.     ckfree((char *) wmPtr->cmdArgv);
  3031.     wmPtr->cmdArgv = NULL;
  3032.     if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  3033. XDeleteProperty(winPtr->display, winPtr->window,
  3034. Tk_InternAtom((Tk_Window) winPtr, "WM_COMMAND"));
  3035.     }
  3036. }
  3037. return TCL_OK;
  3038.     }
  3039.     if (Tcl_SplitList(interp, argv3, &cmdArgc, &cmdArgv) != TCL_OK) {
  3040. return TCL_ERROR;
  3041.     }
  3042.     if (wmPtr->cmdArgv != NULL) {
  3043. ckfree((char *) wmPtr->cmdArgv);
  3044.     }
  3045.     wmPtr->cmdArgc = cmdArgc;
  3046.     wmPtr->cmdArgv = cmdArgv;
  3047.     if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  3048. XSetCommand(winPtr->display, winPtr->window, cmdArgv, cmdArgc);
  3049.     }
  3050.     return TCL_OK;
  3051. }
  3052. /*
  3053.  *----------------------------------------------------------------------
  3054.  *
  3055.  * WmDeiconifyCmd --
  3056.  *
  3057.  * This procedure is invoked to process the "wm deiconify" Tcl command.
  3058.  * See the user documentation for details on what it does.
  3059.  *
  3060.  * Results:
  3061.  * A standard Tcl result.
  3062.  *
  3063.  * Side effects:
  3064.  * See the user documentation.
  3065.  *
  3066.  *----------------------------------------------------------------------
  3067.  */
  3068. static int
  3069. WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv)
  3070.     Tk_Window tkwin; /* Main window of the application. */
  3071.     TkWindow *winPtr;           /* Toplevel to work with */
  3072.     Tcl_Interp *interp; /* Current interpreter. */
  3073.     int objc; /* Number of arguments. */
  3074.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  3075. {
  3076.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  3077.     if (objc != 3) {
  3078. Tcl_WrongNumArgs(interp, 2, objv, "window");
  3079. return TCL_ERROR;
  3080.     }
  3081.     if (wmPtr->iconFor != NULL) {
  3082. Tcl_AppendResult(interp, "can't deiconify ", Tcl_GetString(objv[2]),
  3083. ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
  3084. (char *) NULL);
  3085. return TCL_ERROR;
  3086.     }
  3087.     if (winPtr->flags & TK_EMBEDDED) {
  3088. Tcl_AppendResult(interp, "can't deiconify ", winPtr->pathName,
  3089. ": it is an embedded window", (char *) NULL);
  3090. return TCL_ERROR;
  3091.     }
  3092.     wmPtr->flags &= ~WM_WITHDRAWN;
  3093.     /*
  3094.      * If WM_UPDATE_PENDING is true, a pending UpdateGeometryInfo may
  3095.      * need to be called first to update a withdrawn toplevel's geometry
  3096.      * before it is deiconified by TkpWmSetState.
  3097.      * Don't bother if we've never been mapped.
  3098.      */
  3099.     if ((wmPtr->flags & WM_UPDATE_PENDING) &&
  3100.     !(wmPtr->flags & WM_NEVER_MAPPED)) {
  3101. Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
  3102. UpdateGeometryInfo((ClientData) winPtr);
  3103.     }
  3104.     /*
  3105.      * If we were in the ZoomState (maximized), 'wm deiconify'
  3106.      * should not cause the window to shrink
  3107.      */
  3108.     if (wmPtr->hints.initial_state == ZoomState) {
  3109. TkpWmSetState(winPtr, ZoomState);
  3110.     } else {
  3111. TkpWmSetState(winPtr, NormalState);
  3112.     }
  3113.     /*
  3114.      * An unmapped window will be mapped at idle time
  3115.      * by a call to MapFrame. That calls CreateWrapper
  3116.      * which sets the focus and raises the window.
  3117.      */
  3118.     if (wmPtr->flags & WM_NEVER_MAPPED) {
  3119. return TCL_OK;
  3120.     }
  3121.     /*
  3122.      * Follow Windows-like style here, raising the window to the top.
  3123.      */
  3124.     TkWmRestackToplevel(winPtr, Above, NULL);
  3125.     if (!(Tk_Attributes((Tk_Window) winPtr)->override_redirect)) {
  3126. TkSetFocusWin(winPtr, 1);
  3127.     }
  3128.     return TCL_OK;
  3129. }
  3130. /*
  3131.  *----------------------------------------------------------------------
  3132.  *
  3133.  * WmFocusmodelCmd --
  3134.  *
  3135.  * This procedure is invoked to process the "wm focusmodel" Tcl command.
  3136.  * See the user documentation for details on what it does.
  3137.  *
  3138.  * Results:
  3139.  * A standard Tcl result.
  3140.  *
  3141.  * Side effects:
  3142.  * See the user documentation.
  3143.  *
  3144.  *----------------------------------------------------------------------
  3145.  */
  3146. static int
  3147. WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv)
  3148.     Tk_Window tkwin; /* Main window of the application. */
  3149.     TkWindow *winPtr;           /* Toplevel to work with */
  3150.     Tcl_Interp *interp; /* Current interpreter. */
  3151.     int objc; /* Number of arguments. */
  3152.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  3153. {
  3154.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  3155.     static CONST char *optionStrings[] = {
  3156. "active", "passive", (char *) NULL };
  3157.     enum options {
  3158. OPT_ACTIVE, OPT_PASSIVE };
  3159.     int index;
  3160.     if ((objc != 3) && (objc != 4)) {
  3161. Tcl_WrongNumArgs(interp, 2, objv, "window ?active|passive?");
  3162. return TCL_ERROR;
  3163.     }
  3164.     if (objc == 3) {
  3165. Tcl_SetResult(interp, (wmPtr->hints.input ? "passive" : "active"),
  3166. TCL_STATIC);
  3167. return TCL_OK;
  3168.     }
  3169.     if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0,
  3170.     &index) != TCL_OK) {
  3171. return TCL_ERROR;
  3172.     }
  3173.     if (index == OPT_ACTIVE) {
  3174. wmPtr->hints.input = False;
  3175.     } else { /* OPT_PASSIVE */
  3176. wmPtr->hints.input = True;
  3177.     }
  3178.     return TCL_OK;
  3179. }
  3180. /*
  3181.  *----------------------------------------------------------------------
  3182.  *
  3183.  * WmFrameCmd --
  3184.  *
  3185.  * This procedure is invoked to process the "wm frame" Tcl command.
  3186.  * See the user documentation for details on what it does.
  3187.  *
  3188.  * Results:
  3189.  * A standard Tcl result.
  3190.  *
  3191.  * Side effects:
  3192.  * See the user documentation.
  3193.  *
  3194.  *----------------------------------------------------------------------
  3195.  */
  3196. static int
  3197. WmFrameCmd(tkwin, winPtr, interp, objc, objv)
  3198.     Tk_Window tkwin; /* Main window of the application. */
  3199.     TkWindow *winPtr;           /* Toplevel to work with */
  3200.     Tcl_Interp *interp; /* Current interpreter. */
  3201.     int objc; /* Number of arguments. */
  3202.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  3203. {
  3204.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  3205.     HWND hwnd;
  3206.     char buf[TCL_INTEGER_SPACE];
  3207.     if (objc != 3) {
  3208. Tcl_WrongNumArgs(interp, 2, objv, "window");
  3209. return TCL_ERROR;
  3210.     }
  3211.     if (Tk_WindowId((Tk_Window) winPtr) == None) {
  3212. Tk_MakeWindowExist((Tk_Window) winPtr);
  3213.     }
  3214.     hwnd = wmPtr->wrapper;
  3215.     if (hwnd == NULL) {
  3216. hwnd = Tk_GetHWND(Tk_WindowId((Tk_Window) winPtr));
  3217.     }
  3218.     sprintf(buf, "0x%x", (unsigned int) hwnd);
  3219.     Tcl_SetResult(interp, buf, TCL_VOLATILE);
  3220.     return TCL_OK;
  3221. }
  3222. /*
  3223.  *----------------------------------------------------------------------
  3224.  *
  3225.  * WmGeometryCmd --
  3226.  *
  3227.  * This procedure is invoked to process the "wm geometry" Tcl command.
  3228.  * See the user documentation for details on what it does.
  3229.  *
  3230.  * Results:
  3231.  * A standard Tcl result.
  3232.  *
  3233.  * Side effects:
  3234.  * See the user documentation.
  3235.  *
  3236.  *----------------------------------------------------------------------
  3237.  */
  3238. static int
  3239. WmGeometryCmd(tkwin, winPtr, interp, objc, objv)
  3240.     Tk_Window tkwin; /* Main window of the application. */
  3241.     TkWindow *winPtr;           /* Toplevel to work with */
  3242.     Tcl_Interp *interp; /* Current interpreter. */
  3243.     int objc; /* Number of arguments. */
  3244.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  3245. {
  3246.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  3247.     char xSign, ySign;
  3248.     int width, height;
  3249.     char *argv3;
  3250.     if ((objc != 3) && (objc != 4)) {
  3251. Tcl_WrongNumArgs(interp, 2, objv, "window ?newGeometry?");
  3252. return TCL_ERROR;
  3253.     }
  3254.     if (objc == 3) {
  3255. char buf[16 + TCL_INTEGER_SPACE * 4];
  3256. xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+';
  3257. ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+';
  3258. if (wmPtr->gridWin != NULL) {
  3259.     width = wmPtr->reqGridWidth + (winPtr->changes.width
  3260.     - winPtr->reqWidth)/wmPtr->widthInc;
  3261.     height = wmPtr->reqGridHeight + (winPtr->changes.height
  3262.     - winPtr->reqHeight)/wmPtr->heightInc;
  3263. } else {
  3264.     width = winPtr->changes.width;
  3265.     height = winPtr->changes.height;
  3266. }
  3267. sprintf(buf, "%dx%d%c%d%c%d", width, height, xSign, wmPtr->x,
  3268. ySign, wmPtr->y);
  3269. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  3270. return TCL_OK;
  3271.     }
  3272.     argv3 = Tcl_GetString(objv[3]);
  3273.     if (*argv3 == '') {
  3274. wmPtr->width = -1;
  3275. wmPtr->height = -1;
  3276. WmUpdateGeom(wmPtr, winPtr);
  3277. return TCL_OK;
  3278.     }
  3279.     return ParseGeometry(interp, argv3, winPtr);
  3280. }
  3281. /*
  3282.  *----------------------------------------------------------------------
  3283.  *
  3284.  * WmGridCmd --
  3285.  *
  3286.  * This procedure is invoked to process the "wm grid" Tcl command.
  3287.  * See the user documentation for details on what it does.
  3288.  *
  3289.  * Results:
  3290.  * A standard Tcl result.
  3291.  *
  3292.  * Side effects:
  3293.  * See the user documentation.
  3294.  *
  3295.  *----------------------------------------------------------------------
  3296.  */
  3297. static int
  3298. WmGridCmd(tkwin, winPtr, interp, objc, objv)
  3299.     Tk_Window tkwin; /* Main window of the application. */
  3300.     TkWindow *winPtr;           /* Toplevel to work with */
  3301.     Tcl_Interp *interp; /* Current interpreter. */
  3302.     int objc; /* Number of arguments. */
  3303.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  3304. {
  3305.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  3306.     int reqWidth, reqHeight, widthInc, heightInc;
  3307.     if ((objc != 3) && (objc != 7)) {
  3308. Tcl_WrongNumArgs(interp, 2, objv,
  3309. "window ?baseWidth baseHeight widthInc heightInc?");
  3310. return TCL_ERROR;
  3311.     }
  3312.     if (objc == 3) {
  3313. if (wmPtr->sizeHintsFlags & PBaseSize) {
  3314.     char buf[TCL_INTEGER_SPACE * 4];
  3315.     sprintf(buf, "%d %d %d %d", wmPtr->reqGridWidth,
  3316.     wmPtr->reqGridHeight, wmPtr->widthInc,
  3317.     wmPtr->heightInc);
  3318.     Tcl_SetResult(interp, buf, TCL_VOLATILE);
  3319. }
  3320. return TCL_OK;
  3321.     }
  3322.     if (*Tcl_GetString(objv[3]) == '') {
  3323. /*
  3324.  * Turn off gridding and reset the width and height
  3325.  * to make sense as ungridded numbers.
  3326.  */
  3327. wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc);
  3328. if (wmPtr->width != -1) {
  3329.     wmPtr->width = winPtr->reqWidth + (wmPtr->width
  3330.     - wmPtr->reqGridWidth)*wmPtr->widthInc;
  3331.     wmPtr->height = winPtr->reqHeight + (wmPtr->height
  3332.     - wmPtr->reqGridHeight)*wmPtr->heightInc;
  3333. }
  3334. wmPtr->widthInc = 1;
  3335. wmPtr->heightInc = 1;
  3336.     } else {
  3337. if ((Tcl_GetIntFromObj(interp, objv[3], &reqWidth) != TCL_OK)
  3338. || (Tcl_GetIntFromObj(interp, objv[4], &reqHeight) != TCL_OK)
  3339. || (Tcl_GetIntFromObj(interp, objv[5], &widthInc) != TCL_OK)
  3340. || (Tcl_GetIntFromObj(interp, objv[6], &heightInc) != TCL_OK)) {
  3341.     return TCL_ERROR;
  3342. }
  3343. if (reqWidth < 0) {
  3344.     Tcl_SetResult(interp, "baseWidth can't be < 0", TCL_STATIC);
  3345.     return TCL_ERROR;
  3346. }
  3347. if (reqHeight < 0) {
  3348.     Tcl_SetResult(interp, "baseHeight can't be < 0", TCL_STATIC);
  3349.     return TCL_ERROR;
  3350. }
  3351. if (widthInc <= 0) {
  3352.     Tcl_SetResult(interp, "widthInc can't be <= 0", TCL_STATIC);
  3353.     return TCL_ERROR;
  3354. }
  3355. if (heightInc <= 0) {
  3356.     Tcl_SetResult(interp, "heightInc can't be <= 0", TCL_STATIC);
  3357.     return TCL_ERROR;
  3358. }
  3359. Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,
  3360. heightInc);
  3361.     }
  3362.     WmUpdateGeom(wmPtr, winPtr);
  3363.     return TCL_OK;
  3364. }
  3365. /*
  3366.  *----------------------------------------------------------------------
  3367.  *
  3368.  * WmGroupCmd --
  3369.  *
  3370.  * This procedure is invoked to process the "wm group" Tcl command.
  3371.  * See the user documentation for details on what it does.
  3372.  *
  3373.  * Results:
  3374.  * A standard Tcl result.
  3375.  *
  3376.  * Side effects:
  3377.  * See the user documentation.
  3378.  *
  3379.  *----------------------------------------------------------------------
  3380.  */
  3381. static int
  3382. WmGroupCmd(tkwin, winPtr, interp, objc, objv)
  3383.     Tk_Window tkwin; /* Main window of the application. */
  3384.     TkWindow *winPtr;           /* Toplevel to work with */
  3385.     Tcl_Interp *interp; /* Current interpreter. */
  3386.     int objc; /* Number of arguments. */
  3387.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  3388. {
  3389.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  3390.     Tk_Window tkwin2;
  3391.     char *argv3;
  3392.     int length;
  3393.     if ((objc != 3) && (objc != 4)) {
  3394. Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?");
  3395. return TCL_ERROR;
  3396.     }
  3397.     if (objc == 3) {
  3398. if (wmPtr->hints.flags & WindowGroupHint) {
  3399.     Tcl_SetResult(interp, wmPtr->leaderName, TCL_STATIC);
  3400. }
  3401. return TCL_OK;
  3402.     }
  3403.     argv3 = Tcl_GetStringFromObj(objv[3], &length);
  3404.     if (*argv3 == '') {
  3405. wmPtr->hints.flags &= ~WindowGroupHint;
  3406. if (wmPtr->leaderName != NULL) {
  3407.     ckfree(wmPtr->leaderName);
  3408. }
  3409. wmPtr->leaderName = NULL;
  3410.     } else {
  3411. if (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) {
  3412.     return TCL_ERROR;
  3413. }
  3414. Tk_MakeWindowExist(tkwin2);
  3415. if (wmPtr->leaderName != NULL) {
  3416.     ckfree(wmPtr->leaderName);
  3417. }
  3418. wmPtr->hints.window_group = Tk_WindowId(tkwin2);
  3419. wmPtr->hints.flags |= WindowGroupHint;
  3420. wmPtr->leaderName = ckalloc((unsigned) (length + 1));
  3421. strcpy(wmPtr->leaderName, argv3);
  3422.     }
  3423.     return TCL_OK;
  3424. }
  3425. /*
  3426.  *----------------------------------------------------------------------
  3427.  *
  3428.  * WmIconbitmapCmd --
  3429.  *
  3430.  * This procedure is invoked to process the "wm iconbitmap" Tcl command.
  3431.  * See the user documentation for details on what it does.
  3432.  *
  3433.  * Results:
  3434.  * A standard Tcl result.
  3435.  *
  3436.  * Side effects:
  3437.  * See the user documentation.
  3438.  *
  3439.  *----------------------------------------------------------------------
  3440.  */
  3441. static int
  3442. WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv)
  3443.     Tk_Window tkwin; /* Main window of the application. */
  3444.     TkWindow *winPtr;           /* Toplevel to work with */
  3445.     Tcl_Interp *interp; /* Current interpreter. */
  3446.     int objc; /* Number of arguments. */
  3447.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  3448. {
  3449.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  3450.     TkWindow *useWinPtr = winPtr; /* window to apply to (NULL if -default) */
  3451.     char *string;
  3452.     if ((objc < 3) || (objc > 5)) {
  3453. Tcl_WrongNumArgs(interp, 2, objv, "window ?-default? ?image?");
  3454. return TCL_ERROR;
  3455.     } else if (objc == 5) {
  3456. /* If we have 5 arguments, we must have a '-default' flag */
  3457. char *argv3 = Tcl_GetString(objv[3]);
  3458. if (strcmp(argv3, "-default")) {
  3459.     Tcl_AppendResult(interp, "illegal option "",
  3460.     argv3, "" must be "-default"",
  3461.     (char *) NULL);
  3462.     return TCL_ERROR;
  3463. }
  3464. useWinPtr = NULL;
  3465.     } else if (objc == 3) {
  3466. /* No arguments were given */
  3467. if (wmPtr->hints.flags & IconPixmapHint) {
  3468.     Tcl_SetResult(interp, (char *)
  3469.     Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_pixmap),
  3470.     TCL_STATIC);
  3471. }
  3472. return TCL_OK;
  3473.     }
  3474.     string = Tcl_GetString(objv[objc-1]);
  3475.     if (*string == '') {
  3476. if (wmPtr->hints.icon_pixmap != None) {
  3477.     Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
  3478.     wmPtr->hints.icon_pixmap = None;
  3479. }
  3480. wmPtr->hints.flags &= ~IconPixmapHint;
  3481. if (WinSetIcon(interp, NULL, (Tk_Window) useWinPtr) != TCL_OK) {
  3482.     return TCL_ERROR;
  3483. }
  3484.     } else {
  3485. /*
  3486.  * In the future this block of code will use Tk's 'image'
  3487.  * functionality to allow all supported image formats.
  3488.  * However, this will require a change to the way icons are
  3489.  * handled.  We will need to add icon<->image conversions
  3490.  * routines.
  3491.  *
  3492.  * Until that happens we simply try to find an icon in the
  3493.  * given argument, and if that fails, we use the older
  3494.  * bitmap code.  We do things this way round (icon then
  3495.  * bitmap), because the bitmap code actually seems to have
  3496.  * no visible effect, so we want to give the icon code the
  3497.  * first try at doing something.
  3498.  */
  3499. /*
  3500.  * Either return NULL, or return a valid titlebaricon with its
  3501.  * ref count already incremented.
  3502.  */
  3503. WinIconPtr titlebaricon = ReadIconFromFile(interp, objv[objc-1]);
  3504. if (titlebaricon != NULL) {
  3505.     /*
  3506.      * Try to set the icon for the window.  If it is a '-default'
  3507.      * icon, we must pass in NULL
  3508.      */
  3509.     if (WinSetIcon(interp, titlebaricon, (Tk_Window) useWinPtr)
  3510.     != TCL_OK) {
  3511. /* We didn't use the titlebaricon after all */
  3512. DecrIconRefCount(titlebaricon);
  3513. titlebaricon = NULL;
  3514.     }
  3515. }
  3516. if (titlebaricon == NULL) {
  3517.     /*
  3518.      * We didn't manage to handle the argument as a valid
  3519.      * icon.  Try as a bitmap.  First we must clear the
  3520.      * error message which was placed in the interpreter
  3521.      */
  3522.     Pixmap pixmap;
  3523.     Tcl_ResetResult(interp);
  3524.     pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr, string);
  3525.     if (pixmap == None) {
  3526. return TCL_ERROR;
  3527.     }
  3528.     wmPtr->hints.icon_pixmap = pixmap;
  3529.     wmPtr->hints.flags |= IconPixmapHint;
  3530.     titlebaricon = GetIconFromPixmap(Tk_Display(winPtr), pixmap);
  3531.     if (titlebaricon != NULL) {
  3532. if (WinSetIcon(interp, titlebaricon, (Tk_Window) useWinPtr)
  3533. != TCL_OK) {
  3534.     /* We didn't use the titlebaricon after all */
  3535.     DecrIconRefCount(titlebaricon);
  3536.     titlebaricon = NULL;
  3537. }
  3538.     }
  3539. }
  3540.     }
  3541.     return TCL_OK;
  3542. }
  3543. /*
  3544.  *----------------------------------------------------------------------
  3545.  *
  3546.  * WmIconifyCmd --
  3547.  *
  3548.  * This procedure is invoked to process the "wm iconify" Tcl command.
  3549.  * See the user documentation for details on what it does.
  3550.  *
  3551.  * Results:
  3552.  * A standard Tcl result.
  3553.  *
  3554.  * Side effects:
  3555.  * See the user documentation.
  3556.  *
  3557.  *----------------------------------------------------------------------
  3558.  */
  3559. static int
  3560. WmIconifyCmd(tkwin, winPtr, interp, objc, objv)
  3561.     Tk_Window tkwin; /* Main window of the application. */
  3562.     TkWindow *winPtr;           /* Toplevel to work with */
  3563.     Tcl_Interp *interp; /* Current interpreter. */
  3564.     int objc; /* Number of arguments. */
  3565.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  3566. {
  3567.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  3568.     if (objc != 3) {
  3569. Tcl_WrongNumArgs(interp, 2, objv, "window");
  3570. return TCL_ERROR;
  3571.     }
  3572.     if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
  3573. Tcl_AppendResult(interp, "can't iconify "", winPtr->pathName,
  3574. "": override-redirect flag is set", (char *) NULL);
  3575. return TCL_ERROR;
  3576.     }
  3577.     if (wmPtr->masterPtr != NULL) {
  3578. Tcl_AppendResult(interp, "can't iconify "", winPtr->pathName,
  3579. "": it is a transient", (char *) NULL);
  3580. return TCL_ERROR;
  3581.     }
  3582.     if (wmPtr->iconFor != NULL) {
  3583. Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName,
  3584. ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
  3585. (char *) NULL);
  3586. return TCL_ERROR;
  3587.     }
  3588.     if (winPtr->flags & TK_EMBEDDED) {
  3589. Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName,
  3590. ": it is an embedded window", (char *) NULL);
  3591. return TCL_ERROR;
  3592.     }
  3593.     TkpWmSetState(winPtr, IconicState);
  3594.     return TCL_OK;
  3595. }
  3596. /*
  3597.  *----------------------------------------------------------------------
  3598.  *
  3599.  * WmIconmaskCmd --
  3600.  *
  3601.  * This procedure is invoked to process the "wm iconmask" Tcl command.
  3602.  * See the user documentation for details on what it does.