diff options
Diffstat (limited to 'tk/win/tkWinWm.c')
-rw-r--r-- | tk/win/tkWinWm.c | 4743 |
1 files changed, 3660 insertions, 1083 deletions
diff --git a/tk/win/tkWinWm.c b/tk/win/tkWinWm.c index 8f7ba87d999..db1e540693c 100644 --- a/tk/win/tkWinWm.c +++ b/tk/win/tkWinWm.c @@ -1,4 +1,4 @@ -/* +/* * tkWinWm.c -- * * This module takes care of the interactions between a Tk-based @@ -16,6 +16,7 @@ */ #include "tkWinInt.h" +#include <shellapi.h> /* * Event structure for synthetic activation events. These events are @@ -43,7 +44,7 @@ typedef struct ProtocolHandler { * end of list. */ Tcl_Interp *interp; /* Interpreter in which to invoke command. */ char command[4]; /* Tcl command to invoke when a client - * message for this protocol arrives. + * message for this protocol arrives. * The actual size of the structure varies * to accommodate the needs of the actual * command. THIS MUST BE THE LAST FIELD OF @@ -54,6 +55,88 @@ typedef struct ProtocolHandler { ((unsigned) (sizeof(ProtocolHandler) - 3 + cmdLength)) /* + * Helper type passed via lParam to TkWmStackorderToplevelEnumProc + */ +typedef struct TkWmStackorderToplevelPair { + Tcl_HashTable *table; + TkWindow **window_ptr; +} TkWmStackorderToplevelPair; + +/* + * This structure represents the contents of a icon, in terms of its + * image. The HICON is an internal Windows format. Most of these + * icon-specific-structures originated with the Winico extension. + * We stripped out unused parts of that code, and integrated the + * code more naturally with Tcl. + */ +typedef struct { + UINT Width, Height, Colors; /* Width, Height and bpp */ + LPBYTE lpBits; /* ptr to DIB bits */ + DWORD dwNumBytes; /* how many bytes? */ + LPBITMAPINFO lpbi; /* ptr to header */ + LPBYTE lpXOR; /* ptr to XOR image bits */ + LPBYTE lpAND; /* ptr to AND image bits */ + HICON hIcon; /* DAS ICON */ +} ICONIMAGE, *LPICONIMAGE; +/* + * This structure is how we represent a block of the above + * items. We will reallocate these structures according to + * how many images they need to contain. + */ +typedef struct { + int nNumImages; /* How many images? */ + ICONIMAGE IconImages[1]; /* Image entries */ +} BlockOfIconImages, *BlockOfIconImagesPtr; +/* + * These two structures are used to read in icons from an + * 'icon directory' (i.e. the contents of a .icr file, say). + * We only use these structures temporarily, since we copy + * the information we want into a BlockOfIconImages. + */ +typedef struct { + BYTE bWidth; /* Width of the image */ + BYTE bHeight; /* Height of the image (times 2) */ + BYTE bColorCount; /* Number of colors in image (0 if >=8bpp) */ + BYTE bReserved; /* Reserved */ + WORD wPlanes; /* Color Planes */ + WORD wBitCount; /* Bits per pixel */ + DWORD dwBytesInRes; /* how many bytes in this resource? */ + DWORD dwImageOffset; /* where in the file is this image */ +} ICONDIRENTRY, *LPICONDIRENTRY; +typedef struct { + WORD idReserved; /* Reserved */ + WORD idType; /* resource type (1 for icons) */ + WORD idCount; /* how many images? */ + ICONDIRENTRY idEntries[1]; /* the entries for each image */ +} ICONDIR, *LPICONDIR; + +/* + * A pointer to one of these strucutures is associated with each + * toplevel. This allows us to free up all memory associated with icon + * resources when a window is deleted or if the window's icon is + * changed. They are simply reference counted according to: + * + * (i) how many WmInfo structures point to this object + * (ii) whether the ThreadSpecificData defined in this file contains + * a pointer to this object. + * + * The former count is for windows whose icons are individually + * set, and the latter is for the global default icon choice. + * + * Icons loaded from .icr/.icr use the iconBlock field, icons + * loaded from .exe/.dll use the hIcon field. + */ +typedef struct WinIconInstance { + int refCount; /* Number of instances that share this + * data structure. */ + BlockOfIconImagesPtr iconBlock; + /* Pointer to icon resource data for + * image. */ +} WinIconInstance; + +typedef struct WinIconInstance *WinIconPtr; + +/* * A data structure of the following type holds window-manager-related * information for each top-level window in an application. */ @@ -65,17 +148,17 @@ typedef struct TkWmInfo { * created by the window manager to wrap * a toplevel window. This window is * a direct child of the root window. */ - Tk_Uid titleUid; /* Title to display in window caption. If - * NULL, use name of widget. */ - Tk_Uid iconName; /* Name to display in icon. */ - TkWindow *masterPtr; /* Master window for TRANSIENT_FOR property, - * or NULL. */ + char *title; /* Title to display in window caption. If + * NULL, use name of widget. Malloced. */ + char *iconName; /* Name to display in icon. Malloced. */ XWMHints hints; /* Various pieces of information for * window manager. */ char *leaderName; /* Path name of leader of window group * (corresponds to hints.window_group). - * Malloc-ed. Note: this field doesn't + * Malloc-ed. Note: this field doesn't * get updated if leader is destroyed. */ + TkWindow *masterPtr; /* Master window for TRANSIENT_FOR property, + * or NULL. */ Tk_Window icon; /* Window to use as icon for this window, * or NULL. */ Tk_Window iconFor; /* Window for which this window is icon, or @@ -143,6 +226,8 @@ typedef struct TkWmInfo { * to eliminate redundant resize operations. */ HMENU hMenu; /* the hMenu associated with this menu */ DWORD style, exStyle; /* Style flags for the wrapper window. */ + LONG styleConfig; /* Extra user requested style bits */ + LONG exStyleConfig; /* Extra user requested extended style bits */ /* * List of children of the toplevel which have private colormaps. @@ -158,13 +243,15 @@ typedef struct TkWmInfo { ProtocolHandler *protPtr; /* First in list of protocol handlers for * this window (NULL means none). */ int cmdArgc; /* Number of elements in cmdArgv below. */ - char **cmdArgv; /* Array of strings to store in the + CONST char **cmdArgv; /* Array of strings to store in the * WM_COMMAND property. NULL means nothing * available. */ char *clientMachine; /* String to store in WM_CLIENT_MACHINE * property, or NULL. */ int flags; /* Miscellaneous flags, defined below. */ int numTransients; /* number of transients on this window */ + WinIconPtr iconPtr; /* pointer to titlebar icon structure for + * this window, or NULL. */ struct TkWmInfo *nextPtr; /* Next in list of all top-level windows. */ } WmInfo; @@ -191,12 +278,23 @@ typedef struct TkWmInfo { * a new position for the window, but it hasn't * been reflected through the window manager * yet. - * WM_COLORAMPS_EXPLICIT - non-zero means the colormap windows were + * WM_COLORMAPS_EXPLICIT - non-zero means the colormap windows were * set explicitly via "wm colormapwindows". * WM_ADDED_TOPLEVEL_COLORMAP - non-zero means that when "wm colormapwindows" * was called the top-level itself wasn't * specified, so we added it implicitly at * the end of the list. + * WM_WIDTH_NOT_RESIZABLE - non-zero means that we're not supposed to + * allow the user to change the width of the + * window (controlled by "wm resizable" + * command). + * WM_HEIGHT_NOT_RESIZABLE - non-zero means that we're not supposed to + * allow the user to change the height of the + * window (controlled by "wm resizable" + * command). + * WM_TRANSIENT_WITHDRAWN - non-zero means that this is a transient window + * that has explicitly been withdrawn. It should + * not mirror state changes in the master. */ #define WM_NEVER_MAPPED (1<<0) @@ -211,6 +309,7 @@ typedef struct TkWmInfo { #define WM_ADDED_TOPLEVEL_COLORMAP (1<<9) #define WM_WIDTH_NOT_RESIZABLE (1<<10) #define WM_HEIGHT_NOT_RESIZABLE (1<<11) +#define WM_TRANSIENT_WITHDRAWN (1<<12) /* * Window styles for various types of toplevel windows. @@ -224,8 +323,7 @@ typedef struct TkWmInfo { #define WM_TRANSIENT_STYLE \ (WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS|CS_DBLCLKS) -#define EX_TRANSIENT_STYLE \ - (WS_EX_TOOLWINDOW|WS_EX_DLGMODALFRAME) +#define EX_TRANSIENT_STYLE (WS_EX_DLGMODALFRAME) /* * The following structure is the official type record for geometry @@ -241,7 +339,7 @@ static Tk_GeomMgr wmMgrType = { }; typedef struct ThreadSpecificData { - HPALETTE systemPalette; /* System palette; refers to the + HPALETTE systemPalette; /* System palette; refers to the * currently installed foreground logical * palette. */ TkWindow *createWindow; /* Window that is being constructed. This @@ -253,10 +351,12 @@ typedef struct ThreadSpecificData { * WM_GETMINMAXINFO message before the * WM_CREATE window. */ int initialized; /* Flag indicating whether thread- - * specific elements of module have + * specific elements of module have * been initialized. */ int firstWindow; /* Flag, cleared when the first window * is mapped in a non-iconic state. */ + WinIconPtr iconPtr; /* IconPtr being used as default for all + * toplevels, or NULL. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -265,11 +365,18 @@ static Tcl_ThreadDataKey dataKey; * because they must be shared across threads. */ -static WNDCLASS toplevelClass; /* Class for toplevel windows. */ static int initialized; /* Flag indicating whether module has * been initialized. */ -TCL_DECLARE_MUTEX(winWmMutex) +/* + * A pointer to a shell proc which allows us to extract icons from + * any file. We just initialize this when we start up (if we can) + * and then it never changes + */ +DWORD* (WINAPI *shgetfileinfoProc) (LPCTSTR pszPath, DWORD dwFileAttributes, + SHFILEINFO* psfi, UINT cbFileInfo, UINT uFlags) = NULL; + +TCL_DECLARE_MUTEX(winWmMutex) /* * Forward declarations for procedures defined in this file: @@ -277,8 +384,6 @@ TCL_DECLARE_MUTEX(winWmMutex) static int ActivateWindow _ANSI_ARGS_((Tcl_Event *evPtr, int flags)); -static void ConfigureEvent _ANSI_ARGS_((TkWindow *winPtr, - XConfigureEvent *eventPtr)); static void ConfigureTopLevel _ANSI_ARGS_((WINDOWPOS *pos)); static void GenerateConfigureNotify _ANSI_ARGS_(( TkWindow *winPtr)); @@ -297,6 +402,9 @@ static int ParseGeometry _ANSI_ARGS_((Tcl_Interp *interp, static void RefreshColormap _ANSI_ARGS_((Colormap colormap, TkDisplay *dispPtr)); static void SetLimits _ANSI_ARGS_((HWND hwnd, MINMAXINFO *info)); +static void TkWmStackorderToplevelWrapperMap _ANSI_ARGS_(( + TkWindow *winPtr, + Tcl_HashTable *table)); static LRESULT CALLBACK TopLevelProc _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)); static void TopLevelEventProc _ANSI_ARGS_((ClientData clientData, @@ -308,13 +416,376 @@ static void UpdateGeometryInfo _ANSI_ARGS_(( static void UpdateWrapper _ANSI_ARGS_((TkWindow *winPtr)); static LRESULT CALLBACK WmProc _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)); -static void WmWaitVisibilityProc _ANSI_ARGS_(( +static void WmWaitVisibilityOrMapProc _ANSI_ARGS_(( ClientData clientData, XEvent *eventPtr)); +static BlockOfIconImagesPtr ReadIconOrCursorFromFile _ANSI_ARGS_(( + Tcl_Interp *interp, Tcl_Obj* fileName, BOOL isIcon)); +static WinIconPtr ReadIconFromFile _ANSI_ARGS_(( + Tcl_Interp *interp, Tcl_Obj *fileName)); +static WinIconPtr GetIconFromPixmap _ANSI_ARGS_((Display *dsPtr, + Pixmap pixmap)); +static int ReadICOHeader _ANSI_ARGS_((Tcl_Channel channel)); +static BOOL AdjustIconImagePointers _ANSI_ARGS_((LPICONIMAGE lpImage)); +static HICON MakeIconOrCursorFromResource + _ANSI_ARGS_((LPICONIMAGE lpIcon, BOOL isIcon)); +static HICON GetIcon _ANSI_ARGS_((WinIconPtr titlebaricon, + int icon_size)); +static int WinSetIcon _ANSI_ARGS_((Tcl_Interp *interp, + WinIconPtr titlebaricon, Tk_Window tkw)); +static void FreeIconBlock _ANSI_ARGS_((BlockOfIconImagesPtr lpIR)); +static void DecrIconRefCount _ANSI_ARGS_((WinIconPtr titlebaricon)); + +static int WmAspectCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmAttributesCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmClientCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmColormapwindowsCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmCommandCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmDeiconifyCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmFocusmodelCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmFrameCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmGeometryCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmGridCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmGroupCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmIconbitmapCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmIconifyCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmIconmaskCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmIconnameCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmIconpositionCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmIconwindowCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmMaxsizeCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmMinsizeCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmOverrideredirectCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmPositionfromCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmProtocolCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmResizableCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmSizefromCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmStackorderCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmStateCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmTitleCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmTransientCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmWithdrawCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static void WmUpdateGeom _ANSI_ARGS_((WmInfo *wmPtr, + TkWindow *winPtr)); + +/* Used in BytesPerLine */ +#define WIDTHBYTES(bits) ((((bits) + 31)>>5)<<2) + +/* + *---------------------------------------------------------------------- + * + * DIBNumColors -- + * + * Calculates the number of entries in the color table, given by + * LPSTR lpbi - pointer to the CF_DIB memory block. Used by + * titlebar icon code. + * + * Results: + * + * WORD - Number of entries in the color table. + * + * Side effects: None. + * + * + *---------------------------------------------------------------------- + */ +static WORD +DIBNumColors( LPSTR lpbi ) +{ + WORD wBitCount; + DWORD dwClrUsed; + + dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed; + + if (dwClrUsed) + return (WORD) dwClrUsed; + + wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount; + + switch (wBitCount) + { + case 1: return 2; + case 4: return 16; + case 8: return 256; + default:return 0; + } +} /* *---------------------------------------------------------------------- * - * InitWm -- + * PaletteSize -- + * + * Calculates the number of bytes in the color table, as given by + * LPSTR lpbi - pointer to the CF_DIB memory block. Used by + * titlebar icon code. + * + * Results: + * number of bytes in the color table + * + * Side effects: None. + * + * + *---------------------------------------------------------------------- + */ +static WORD +PaletteSize( LPSTR lpbi ) +{ + return ((WORD)( DIBNumColors( lpbi ) * sizeof( RGBQUAD )) ); +} + +/* + *---------------------------------------------------------------------- + * + * FindDIBits -- + * + * Locate the image bits in a CF_DIB format DIB, as given by + * LPSTR lpbi - pointer to the CF_DIB memory block. Used by + * titlebar icon code. + * + * Results: + * pointer to the image bits + * + * Side effects: None + * + * + *---------------------------------------------------------------------- + */ +static LPSTR +FindDIBBits( LPSTR lpbi ) +{ + return ( lpbi + *(LPDWORD)lpbi + PaletteSize( lpbi ) ); +} + +/* + *---------------------------------------------------------------------- + * + * BytesPerLine -- + * + * Calculates the number of bytes in one scan line, as given by + * LPBITMAPINFOHEADER lpBMIH - pointer to the BITMAPINFOHEADER + * that begins the CF_DIB block. Used by titlebar icon code. + * + * Results: + * number of bytes in one scan line (DWORD aligned) + * + * Side effects: None + * + * + *---------------------------------------------------------------------- + */ +static DWORD +BytesPerLine( LPBITMAPINFOHEADER lpBMIH ) +{ + return WIDTHBYTES(lpBMIH->biWidth * lpBMIH->biPlanes * lpBMIH->biBitCount); +} + +/* + *---------------------------------------------------------------------- + * + * AdjustIconImagePointers -- + * + * Adjusts internal pointers in icon resource struct, as given + * by LPICONIMAGE lpImage - the resource to handle. Used by + * titlebar icon code. + * + * Results: + * BOOL - TRUE for success, FALSE for failure + * + * Side effects: + * + * + *---------------------------------------------------------------------- + */ +static BOOL +AdjustIconImagePointers( LPICONIMAGE lpImage ) +{ + /* Sanity check */ + if (lpImage==NULL) + return FALSE; + /* BITMAPINFO is at beginning of bits */ + lpImage->lpbi = (LPBITMAPINFO)lpImage->lpBits; + /* Width - simple enough */ + lpImage->Width = lpImage->lpbi->bmiHeader.biWidth; + /* + * Icons are stored in funky format where height is doubled + * so account for that + */ + lpImage->Height = (lpImage->lpbi->bmiHeader.biHeight)/2; + /* How many colors? */ + lpImage->Colors = lpImage->lpbi->bmiHeader.biPlanes * + lpImage->lpbi->bmiHeader.biBitCount; + /* XOR bits follow the header and color table */ + lpImage->lpXOR = (LPBYTE)FindDIBBits(((LPSTR)lpImage->lpbi)); + /* AND bits follow the XOR bits */ + lpImage->lpAND = lpImage->lpXOR + (lpImage->Height* + BytesPerLine((LPBITMAPINFOHEADER)(lpImage->lpbi))); + return TRUE; +} + +/* + *---------------------------------------------------------------------- + * + * MakeIconOrCursorFromResource -- + * + * Construct an actual HICON structure from the information + * in a resource. + * + * Results: + * + * + * Side effects: + * + * + *---------------------------------------------------------------------- + */ +static HICON +MakeIconOrCursorFromResource(LPICONIMAGE lpIcon, BOOL isIcon) { + HICON hIcon ; + static FARPROC pfnCreateIconFromResourceEx=NULL; + static int initinfo=0; + /* Sanity Check */ + if (lpIcon == NULL) + return NULL; + if (lpIcon->lpBits == NULL) + return NULL; + if (!initinfo) { + HMODULE hMod = GetModuleHandleA("USER32.DLL"); + initinfo=1; + if (hMod){ + pfnCreateIconFromResourceEx = + GetProcAddress(hMod, "CreateIconFromResourceEx"); + } + } + /* Let the OS do the real work :) */ + if (pfnCreateIconFromResourceEx!=NULL) { + hIcon = (HICON) (pfnCreateIconFromResourceEx) + (lpIcon->lpBits, lpIcon->dwNumBytes, isIcon, 0x00030000, + (*(LPBITMAPINFOHEADER)(lpIcon->lpBits)).biWidth, + (*(LPBITMAPINFOHEADER)(lpIcon->lpBits)).biHeight/2, 0); + } else { + hIcon = NULL; + } + /* It failed, odds are good we're on NT so try the non-Ex way */ + if (hIcon == NULL) { + /* We would break on NT if we try with a 16bpp image */ + if (lpIcon->lpbi->bmiHeader.biBitCount != 16) { + hIcon = CreateIconFromResource(lpIcon->lpBits, lpIcon->dwNumBytes, + isIcon, 0x00030000); + } + } + return hIcon; +} + +/* + *---------------------------------------------------------------------- + * + * ReadICOHeader -- + * + * Reads the header from an ICO file, as specfied by channel. + * + * Results: + * UINT - Number of images in file, -1 for failure. + * If this succeeds, there is a decent chance this is a + * valid icon file. + * + * Side effects: + * + * + *---------------------------------------------------------------------- + */ +static int +ReadICOHeader( Tcl_Channel channel ) +{ + WORD Input; + DWORD dwBytesRead; + + /* Read the 'reserved' WORD */ + dwBytesRead = Tcl_Read( channel, (char*)&Input, sizeof( WORD )); + /* Did we get a WORD? */ + if (dwBytesRead != sizeof( WORD )) + return -1; + /* Was it 'reserved' ? (ie 0) */ + if (Input != 0) + return -1; + /* Read the type WORD */ + dwBytesRead = Tcl_Read( channel, (char*)&Input, sizeof( WORD )); + /* Did we get a WORD? */ + if (dwBytesRead != sizeof( WORD )) + return -1; + /* Was it type 1? */ + if (Input != 1) + return -1; + /* Get the count of images */ + dwBytesRead = Tcl_Read( channel, (char*)&Input, sizeof( WORD )); + /* Did we get a WORD? */ + if (dwBytesRead != sizeof( WORD )) + return -1; + /* Return the count */ + return (int)Input; +} + +/* + *---------------------------------------------------------------------- + * + * InitWindowClass -- * * This routine creates the Wm toplevel decorative frame class. * @@ -326,54 +797,726 @@ static void WmWaitVisibilityProc _ANSI_ARGS_(( * *---------------------------------------------------------------------- */ - -static void -InitWm(void) -{ +static int +InitWindowClass(WinIconPtr titlebaricon) { ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - WNDCLASS * classPtr; + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (! tsdPtr->initialized) { tsdPtr->initialized = 1; tsdPtr->firstWindow = 1; + tsdPtr->iconPtr = NULL; } if (! initialized) { Tcl_MutexLock(&winWmMutex); if (! initialized) { + Tcl_DString classString; + WNDCLASS class; initialized = 1; - classPtr = &toplevelClass; - /* - * When threads are enabled, we cannot use CLASSDC because - * threads will then write into the same device context. - * - * This is a hack; we should add a subsystem that manages - * device context on a per-thread basis. See also tkWinX.c, - * which also initializes a WNDCLASS structure. - */ + if (shgetfileinfoProc == NULL) { + HINSTANCE hInstance = LoadLibraryA("shell32"); + if (hInstance != NULL) { + shgetfileinfoProc = + (DWORD* (WINAPI *) (LPCTSTR pszPath, DWORD dwFileAttributes, + SHFILEINFO* psfi, UINT cbFileInfo, UINT uFlags)) GetProcAddress(hInstance, + "SHGetFileInfo"); + FreeLibrary(hInstance); + } + } + /* + * The only difference between WNDCLASSW and WNDCLASSA are + * in pointers, so we can use the generic structure WNDCLASS. + */ + ZeroMemory(&class, sizeof(WNDCLASS)); + + /* + * When threads are enabled, we cannot use CLASSDC because + * threads will then write into the same device context. + * + * This is a hack; we should add a subsystem that manages + * device context on a per-thread basis. See also tkWinX.c, + * which also initializes a WNDCLASS structure. + */ #ifdef TCL_THREADS - classPtr->style = CS_HREDRAW | CS_VREDRAW; + class.style = CS_HREDRAW | CS_VREDRAW; #else - classPtr->style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC; + class.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC; #endif - classPtr->cbClsExtra = 0; - classPtr->cbWndExtra = 0; - classPtr->hInstance = Tk_GetHINSTANCE(); - classPtr->hbrBackground = NULL; - classPtr->lpszMenuName = NULL; - classPtr->lpszClassName = TK_WIN_TOPLEVEL_CLASS_NAME; - classPtr->lpfnWndProc = WmProc; - classPtr->hIcon = LoadIcon(Tk_GetHINSTANCE(), "tk"); - classPtr->hCursor = LoadCursor(NULL, IDC_ARROW); - - if (!RegisterClass(classPtr)) { + class.hInstance = Tk_GetHINSTANCE(); + Tcl_WinUtfToTChar(TK_WIN_TOPLEVEL_CLASS_NAME, -1, &classString); + class.lpszClassName = (LPCTSTR) Tcl_DStringValue(&classString); + class.lpfnWndProc = WmProc; + if (titlebaricon == NULL) { + class.hIcon = LoadIcon(Tk_GetHINSTANCE(), "tk"); + } else { + class.hIcon = GetIcon(titlebaricon, ICON_BIG); + if (class.hIcon == NULL) { + return TCL_ERROR; + } + /* + * Store pointer to default icon so we know when + * we need to free that information + */ + tsdPtr->iconPtr = titlebaricon; + } + class.hCursor = LoadCursor(NULL, IDC_ARROW); + + if (!(*tkWinProcs->registerClass)(&class)) { panic("Unable to register TkTopLevel class"); } + Tcl_DStringFree(&classString); } Tcl_MutexUnlock(&winWmMutex); } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * InitWm -- + * + * This initialises the window manager + * + * Results: + * None. + * + * Side effects: + * Registers a new window class. + * + *---------------------------------------------------------------------- + */ +static void +InitWm(void) +{ + /* Ignore return result */ + (void) InitWindowClass(NULL); +} + +/* + *---------------------------------------------------------------------- + * + * WinSetIcon -- + * + * Sets either the default toplevel titlebar icon, or the icon + * for a specific toplevel (if tkw is given, then only that + * window is used). + * + * The ref-count of the titlebaricon is NOT changed. If this + * function returns successfully, the caller should assume + * the icon was used (and therefore the ref-count should + * be adjusted to reflect that fact). If the function returned + * an error, the caller should assume the icon was not used + * (and may wish to free the memory associated with it). + * + * Results: + * A standard Tcl return code. + * + * Side effects: + * One or all windows may have their icon changed. + * The Tcl result may be modified. + * The window-manager will be initialised if it wasn't already. + * The given window will be forced into existence. + * + *---------------------------------------------------------------------- + */ +static int +WinSetIcon(interp, titlebaricon, tkw) + Tcl_Interp *interp; + WinIconPtr titlebaricon; + Tk_Window tkw; +{ + WmInfo *wmPtr; + HWND hwnd; + int application = 0; + + if (tkw == NULL) { + tkw = Tk_MainWindow(interp); + application = 1; + } + + if (!(Tk_IsTopLevel(tkw))) { + Tcl_AppendResult(interp, "window \"", Tk_PathName(tkw), + "\" isn't a top-level window", (char *) NULL); + return TCL_ERROR; + } + if (Tk_WindowId(tkw) == None) { + Tk_MakeWindowExist(tkw); + } + /* We must get the window's wrapper, not the window itself */ + wmPtr = ((TkWindow*)tkw)->wmInfoPtr; + hwnd = wmPtr->wrapper; + + if (application) { + if (hwnd == NULL) { + /* + * I don't actually think this is ever the correct thing, unless + * perhaps the window doesn't have a wrapper. But I believe all + * windows have wrappers. + */ + hwnd = Tk_GetHWND(Tk_WindowId(tkw)); + } + /* + * If we aren't initialised, then just initialise with the user's + * icon. Otherwise our icon choice will be ignored moments later + * when Tk finishes initialising. + */ + if (!initialized) { + if (InitWindowClass(titlebaricon) != TCL_OK) { + Tcl_AppendResult(interp,"Unable to set icon", (char*)NULL); + return TCL_ERROR; + } + } else { + ThreadSpecificData *tsdPtr; + if ( +#ifdef _WIN64 + !SetClassLongPtr(hwnd, GCLP_HICONSM, + (LPARAM)GetIcon(titlebaricon, ICON_SMALL)) +#else + !SetClassLong(hwnd, GCL_HICONSM, + (LPARAM)GetIcon(titlebaricon, ICON_SMALL)) +#endif + ) { + /* + * For some reason this triggers, even though it seems + * to be successful This is probably related to the + * WNDCLASS vs WNDCLASSEX difference. Anyway it seems + * we have to ignore errors returned here. + */ + + /* + * Tcl_AppendResult(interp,"Unable to set new small icon", (char*)NULL); + * return TCL_ERROR; + */ + } + if ( +#ifdef _WIN64 + !SetClassLongPtr(hwnd, GCLP_HICON, + (LPARAM)GetIcon(titlebaricon, ICON_BIG)) +#else + !SetClassLong(hwnd, GCL_HICON, + (LPARAM)GetIcon(titlebaricon, ICON_BIG)) +#endif + ) { + Tcl_AppendResult(interp,"Unable to set new icon", (char*)NULL); + return TCL_ERROR; + } + tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + if (tsdPtr->iconPtr != NULL) { + DecrIconRefCount(tsdPtr->iconPtr); + } + tsdPtr->iconPtr = titlebaricon; + } + } else { + if (!initialized) { + /* + * Need to initialise the wm otherwise we will fail on + * code which tries to set a toplevel's icon before that + * happens. Ignore return result. + */ + (void)InitWindowClass(NULL); + } + /* + * The following code is exercised if you do + * + * toplevel .t ; wm titlebaricon .t foo.icr + * + * i.e. the wm hasn't had time to properly create + * the '.t' window before you set the icon. + */ + if (hwnd == NULL) { + /* + * This little snippet is copied from the 'Map' function, + * and should probably be placed in one proper location + */ + UpdateWrapper(wmPtr->winPtr); + wmPtr = ((TkWindow*)tkw)->wmInfoPtr; + hwnd = wmPtr->wrapper; + if (hwnd == NULL) { + Tcl_AppendResult(interp, + "Can't set icon; window has no wrapper.", (char*)NULL); + return TCL_ERROR; + } + } + SendMessage(hwnd, WM_SETICON, ICON_SMALL, + (LPARAM) GetIcon(titlebaricon, ICON_SMALL)); + SendMessage(hwnd, WM_SETICON, ICON_BIG, + (LPARAM) GetIcon(titlebaricon, ICON_BIG)); + + /* Update the iconPtr we keep for each WmInfo structure. */ + if (wmPtr->iconPtr != NULL) { + /* Free any old icon ptr which is associated with this window. */ + DecrIconRefCount(wmPtr->iconPtr); + } + /* + * We do not need to increment the ref count for the + * titlebaricon, because it was already incremented when we + * retrieved it. + */ + wmPtr->iconPtr = titlebaricon; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ReadIconFromFile -- + * + * Read the contents of a file (usually .ico, .icr) and extract an + * icon resource, if possible, otherwise check if the shell has an + * icon assigned to the given file and use that. If both of those + * fail, then NULL is returned, and an error message will already be + * in the interpreter. + * + * Results: + * A WinIconPtr structure containing the icons in the file, with + * its ref count already incremented. The calling procedure should + * either place this structure inside a WmInfo structure, or it should + * pass it on to DecrIconRefCount() to ensure no memory leaks occur. + * + * If the given fileName did not contain a valid icon structure, + * return NULL. + * + * Side effects: + * Memory is allocated for the returned structure and the icons + * it contains. If the structure is not wanted, it should be + * passed to DecrIconRefCount, and in any case a valid ref count + * should be ensured to avoid memory leaks. + * + * Currently icon resources are not shared, so the ref count of + * one of these structures will always be 0 or 1. However all we + * need do is implement some sort of lookup function between + * filenames and WinIconPtr structures and no other code will need + * to be changed. The pseudo-code for this is implemented below + * in the 'if (0)' branch. It did not seem necessary to implement + * this optimisation here, since moving to icon<->image + * conversions will probably make it obsolete. + * + *---------------------------------------------------------------------- + */ +static WinIconPtr +ReadIconFromFile(interp, fileName) + Tcl_Interp *interp; + Tcl_Obj *fileName; +{ + WinIconPtr titlebaricon = NULL; + + if (0 /* If we already have an icon for this filename */) { + titlebaricon = NULL; /* Get the real value from a lookup */ + titlebaricon->refCount++; + return titlebaricon; + } else { + /* First check if it is a .ico file */ + BlockOfIconImagesPtr lpIR; + lpIR = ReadIconOrCursorFromFile(interp, fileName, TRUE); + + /* Then see if we can ask the shell for the icon for this file */ + if (lpIR == NULL && shgetfileinfoProc != NULL) { + SHFILEINFO sfi; + Tcl_DString ds, ds2; + DWORD *res; + CONST char *file; + + file = Tcl_TranslateFileName(interp, Tcl_GetString(fileName), &ds); + if (file == NULL) { return NULL; } + Tcl_UtfToExternalDString(NULL, file, -1, &ds2); + Tcl_DStringFree(&ds); + + res = (*shgetfileinfoProc)(Tcl_DStringValue(&ds2), 0, &sfi, + sizeof(SHFILEINFO), SHGFI_SMALLICON|SHGFI_ICON); + + Tcl_DStringFree(&ds2); + + if (res != 0) { + Tcl_ResetResult(interp); + + lpIR = (BlockOfIconImagesPtr) ckalloc(sizeof(BlockOfIconImages)); + if (lpIR == NULL) { + DestroyIcon(sfi.hIcon); + return NULL; + } + + lpIR->nNumImages = 1; + lpIR->IconImages[0].Width = 16; + lpIR->IconImages[0].Height = 16; + lpIR->IconImages[0].Colors = 4; + lpIR->IconImages[0].hIcon = sfi.hIcon; + /* These fields are ignored */ + lpIR->IconImages[0].lpBits = 0; + lpIR->IconImages[0].dwNumBytes = 0; + lpIR->IconImages[0].lpXOR = 0; + lpIR->IconImages[0].lpAND = 0; + } + } + if (lpIR != NULL) { + titlebaricon = (WinIconPtr) ckalloc(sizeof(WinIconInstance)); + titlebaricon->iconBlock = lpIR; + titlebaricon->refCount = 1; + } + return titlebaricon; + } +} + +/* + *---------------------------------------------------------------------- + * + * GetIconFromPixmap -- + * + * Turn a Tk Pixmap (i.e. a bitmap) into an icon resource, if + * possible, otherwise NULL is returned. + * + * Results: + * A WinIconPtr structure containing a conversion of the given + * bitmap into an icon, with its ref count already incremented. The + * calling procedure should either place this structure inside a + * WmInfo structure, or it should pass it on to DecrIconRefCount() + * to ensure no memory leaks occur. + * + * If the given pixmap did not contain a valid icon structure, + * return NULL. + * + * Side effects: + * Memory is allocated for the returned structure and the icons + * it contains. If the structure is not wanted, it should be + * passed to DecrIconRefCount, and in any case a valid ref count + * should be ensured to avoid memory leaks. + * + * Currently icon resources are not shared, so the ref count of + * one of these structures will always be 0 or 1. However all we + * need do is implement some sort of lookup function between + * pixmaps and WinIconPtr structures and no other code will need + * to be changed. + * + *---------------------------------------------------------------------- + */ +static WinIconPtr +GetIconFromPixmap(dsPtr, pixmap) + Display *dsPtr; + Pixmap pixmap; +{ + WinIconPtr titlebaricon = NULL; + TkWinDrawable* twdPtr = (TkWinDrawable*) pixmap; + + if (twdPtr == NULL) { + return NULL; + } + + if (0 /* If we already have an icon for this pixmap */) { + titlebaricon = NULL; /* Get the real value from a lookup */ + titlebaricon->refCount++; + return titlebaricon; + } else { + BlockOfIconImagesPtr lpIR; + ICONINFO icon; + HICON hIcon; + int width, height; + + Tk_SizeOfBitmap(dsPtr, pixmap, &width, &height); + + icon.fIcon = TRUE; + icon.xHotspot = 0; + icon.yHotspot = 0; + icon.hbmMask = twdPtr->bitmap.handle; + icon.hbmColor = twdPtr->bitmap.handle; + + hIcon = CreateIconIndirect(&icon); + if (hIcon == NULL) { + return NULL; + } + + lpIR = (BlockOfIconImagesPtr) ckalloc(sizeof(BlockOfIconImages)); + if (lpIR == NULL) { + DestroyIcon(hIcon); + return NULL; + } + + lpIR->nNumImages = 1; + lpIR->IconImages[0].Width = width; + lpIR->IconImages[0].Height = height; + lpIR->IconImages[0].Colors = 1 << twdPtr->bitmap.depth; + lpIR->IconImages[0].hIcon = hIcon; + /* These fields are ignored */ + lpIR->IconImages[0].lpBits = 0; + lpIR->IconImages[0].dwNumBytes = 0; + lpIR->IconImages[0].lpXOR = 0; + lpIR->IconImages[0].lpAND = 0; + + titlebaricon = (WinIconPtr) ckalloc(sizeof(WinIconInstance)); + titlebaricon->iconBlock = lpIR; + titlebaricon->refCount = 1; + return titlebaricon; + } +} + +/* + *---------------------------------------------------------------------- + * + * DecrIconRefCount -- + * + * Reduces the reference count. + * + * Results: + * None. + * + * Side effects: + * If the ref count falls to zero, free the memory associated + * with the icon resource structures. In this case the pointer + * passed into this function is no longer valid. + * + *---------------------------------------------------------------------- + */ +static void +DecrIconRefCount(WinIconPtr titlebaricon) { + titlebaricon->refCount--; + + if (titlebaricon->refCount <= 0) { + if (titlebaricon->iconBlock != NULL) { + FreeIconBlock(titlebaricon->iconBlock); + } + titlebaricon->iconBlock = NULL; + + ckfree((char*)titlebaricon); + } +} + +/* + *---------------------------------------------------------------------- + * + * FreeIconBlock -- + * + * Frees all memory associated with a previously loaded + * titlebaricon. The icon block pointer is no longer + * valid once this function returns. + * + * Results: + * None. + * + * Side effects: + * + * + *---------------------------------------------------------------------- + */ +static void +FreeIconBlock(BlockOfIconImagesPtr lpIR) { + int i; + + /* Free all the bits */ + for (i=0; i< lpIR->nNumImages; i++) { + if (lpIR->IconImages[i].lpBits != NULL) { + ckfree((char*)lpIR->IconImages[i].lpBits); + } + if (lpIR->IconImages[i].hIcon != NULL) { + DestroyIcon(lpIR->IconImages[i].hIcon); + } + } + ckfree ((char*)lpIR); +} + +/* + *---------------------------------------------------------------------- + * + * GetIcon -- + * + * Extracts an icon of a given size from an icon resource + * + * Results: + * Returns the icon, if found, else NULL. + * + * Side effects: + * + * + *---------------------------------------------------------------------- + */ +static HICON +GetIcon(WinIconPtr titlebaricon, int icon_size) { + BlockOfIconImagesPtr lpIR; + + if (titlebaricon == NULL) { + return NULL; + } + + lpIR = titlebaricon->iconBlock; + if (lpIR == NULL) { + return NULL; + } else { + unsigned int size = (icon_size == 0 ? 16 : 32); + int i; + + for (i = 0; i < lpIR->nNumImages; i++) { + /* Take the first or a 32x32 16 color icon*/ + if ((lpIR->IconImages[i].Height == size) + && (lpIR->IconImages[i].Width == size) + && (lpIR->IconImages[i].Colors >= 4)) { + return lpIR->IconImages[i].hIcon; + } + } + + /* + * If we get here, then just return the first one, + * it will have to do! + */ + if (lpIR->nNumImages >= 1) { + return lpIR->IconImages[0].hIcon; + } + } + return NULL; +} + +static HCURSOR +TclWinReadCursorFromFile(Tcl_Interp* interp, Tcl_Obj* fileName) { + BlockOfIconImagesPtr lpIR; + HICON res = NULL; + + lpIR = ReadIconOrCursorFromFile(interp, fileName, FALSE); + if (lpIR == NULL) { + return NULL; + } + if (lpIR->nNumImages >= 1) { + res = CopyImage(lpIR->IconImages[0].hIcon, IMAGE_CURSOR,0,0,0); + } + FreeIconBlock(lpIR); + return res; +} + +/* + *---------------------------------------------------------------------- + * + * ReadIconOrCursorFromFile -- + * + * Reads an Icon Resource from an ICO file, as given by + * char* fileName - Name of the ICO file. This name should + * be in Utf format. + * + * Results: + * Returns an icon resource, if found, else NULL. + * + * Side effects: + * May leave error messages in the Tcl interpreter. + * + *---------------------------------------------------------------------- + */ +static BlockOfIconImagesPtr +ReadIconOrCursorFromFile(Tcl_Interp* interp, Tcl_Obj* fileName, BOOL isIcon) { + BlockOfIconImagesPtr lpIR, lpNew; + Tcl_Channel channel; + int i; + DWORD dwBytesRead; + LPICONDIRENTRY lpIDE; + + /* Open the file */ + channel = Tcl_FSOpenFileChannel(interp, fileName, "r", 0); + if (channel == NULL) { + Tcl_AppendResult(interp,"Error opening file \"", + Tcl_GetString(fileName), + "\" for reading",(char*)NULL); + return NULL; + } + if (Tcl_SetChannelOption(interp, channel, "-translation", "binary") + != TCL_OK) { + Tcl_Close(NULL, channel); + return NULL; + } + if (Tcl_SetChannelOption(interp, channel, "-encoding", "binary") + != TCL_OK) { + Tcl_Close(NULL, channel); + return NULL; + } + /* Allocate memory for the resource structure */ + lpIR = (BlockOfIconImagesPtr) ckalloc(sizeof(BlockOfIconImages)); + if (lpIR == NULL) { + Tcl_AppendResult(interp,"Error allocating memory",(char*)NULL); + Tcl_Close(NULL, channel); + return NULL; + } + /* Read in the header */ + if ((lpIR->nNumImages = ReadICOHeader( channel )) == -1) { + Tcl_AppendResult(interp,"Invalid file header",(char*)NULL); + Tcl_Close(NULL, channel); + ckfree((char*) lpIR ); + return NULL; + } + /* Adjust the size of the struct to account for the images */ + lpNew = (BlockOfIconImagesPtr) ckrealloc((char*)lpIR, + sizeof(BlockOfIconImages) + ((lpIR->nNumImages-1) * sizeof(ICONIMAGE))); + if (lpNew == NULL) { + Tcl_AppendResult(interp,"Error allocating memory",(char*)NULL); + Tcl_Close(NULL, channel); + ckfree( (char*)lpIR ); + return NULL; + } + lpIR = lpNew; + /* Allocate enough memory for the icon directory entries */ + lpIDE = (LPICONDIRENTRY) ckalloc(lpIR->nNumImages * sizeof(ICONDIRENTRY)); + if (lpIDE == NULL) { + Tcl_AppendResult(interp,"Error allocating memory",(char*)NULL); + Tcl_Close(NULL, channel); + ckfree( (char*)lpIR ); + return NULL; + } + /* Read in the icon directory entries */ + dwBytesRead = Tcl_Read(channel, (char*)lpIDE, + lpIR->nNumImages * sizeof( ICONDIRENTRY )); + if (dwBytesRead != lpIR->nNumImages * sizeof( ICONDIRENTRY )) { + Tcl_AppendResult(interp,"Error reading file",(char*)NULL); + Tcl_Close(NULL, channel); + ckfree( (char*)lpIR ); + return NULL; + } + /* Loop through and read in each image */ + for( i = 0; i < lpIR->nNumImages; i++ ) { + /* Allocate memory for the resource */ + lpIR->IconImages[i].lpBits = (LPBYTE) ckalloc(lpIDE[i].dwBytesInRes); + if (lpIR->IconImages[i].lpBits == NULL) { + Tcl_AppendResult(interp,"Error allocating memory",(char*)NULL); + Tcl_Close(NULL, channel); + ckfree( (char*)lpIR ); + ckfree( (char*)lpIDE ); + return NULL; + } + lpIR->IconImages[i].dwNumBytes = lpIDE[i].dwBytesInRes; + /* Seek to beginning of this image */ + if (Tcl_Seek(channel, lpIDE[i].dwImageOffset, FILE_BEGIN) == -1) { + Tcl_AppendResult(interp,"Error seeking in file",(char*)NULL); + Tcl_Close(NULL, channel); + ckfree( (char*)lpIR ); + ckfree( (char*)lpIDE ); + return NULL; + } + /* Read it in */ + dwBytesRead = Tcl_Read( channel, lpIR->IconImages[i].lpBits, + lpIDE[i].dwBytesInRes); + if (dwBytesRead != lpIDE[i].dwBytesInRes) { + Tcl_AppendResult(interp,"Error reading file",(char*)NULL); + Tcl_Close(NULL, channel); + ckfree( (char*)lpIDE ); + ckfree( (char*)lpIR ); + return NULL; + } + /* Set the internal pointers appropriately */ + if (!AdjustIconImagePointers( &(lpIR->IconImages[i]))) { + Tcl_AppendResult(interp,"Error converting to internal format", + (char*)NULL); + Tcl_Close(NULL, channel); + ckfree( (char*)lpIDE ); + ckfree( (char*)lpIR ); + return NULL; + } + lpIR->IconImages[i].hIcon = + MakeIconOrCursorFromResource(&(lpIR->IconImages[i]), isIcon); + } + /* Clean up */ + ckfree((char*)lpIDE); + Tcl_Close(NULL, channel); + if (lpIR == NULL){ + Tcl_AppendResult(interp,"Reading of ", Tcl_GetString(fileName), + " failed!",(char*)NULL); + return NULL; + } + return lpIR; } /* @@ -392,12 +1535,11 @@ InitWm(void) * *---------------------------------------------------------------------- */ - static TkWindow * GetTopLevel(hwnd) HWND hwnd; { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* @@ -409,7 +1551,11 @@ GetTopLevel(hwnd) if (tsdPtr->createWindow) { return tsdPtr->createWindow; } +#ifdef _WIN64 + return (TkWindow *) GetWindowLongPtr(hwnd, GWLP_USERDATA); +#else return (TkWindow *) GetWindowLong(hwnd, GWL_USERDATA); +#endif } /* @@ -445,7 +1591,7 @@ SetLimits(hwnd, info) } wmPtr = winPtr->wmInfoPtr; - + /* * Copy latest constraint info. */ @@ -454,7 +1600,7 @@ SetLimits(hwnd, info) wmPtr->defMinHeight = info->ptMinTrackSize.y; wmPtr->defMaxWidth = info->ptMaxTrackSize.x; wmPtr->defMaxHeight = info->ptMaxTrackSize.y; - + GetMaxSize(wmPtr, &maxWidth, &maxHeight); GetMinSize(wmPtr, &minWidth, &minHeight); @@ -493,7 +1639,7 @@ SetLimits(hwnd, info) info->ptMaxTrackSize.x = info->ptMinTrackSize.x; } if (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) { - info->ptMinTrackSize.y = winPtr->changes.height + info->ptMinTrackSize.y = winPtr->changes.height + wmPtr->borderHeight; info->ptMaxTrackSize.y = info->ptMinTrackSize.y; } @@ -534,14 +1680,14 @@ TkWinWmCleanup(hInstance) } #endif - tsdPtr = (ThreadSpecificData *) + tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (!tsdPtr->initialized) { return; } tsdPtr->initialized = 0; - + UnregisterClass(TK_WIN_TOPLEVEL_CLASS_NAME, hInstance); } @@ -570,12 +1716,13 @@ TkWmNewWindow(winPtr) register WmInfo *wmPtr; wmPtr = (WmInfo *) ckalloc(sizeof(WmInfo)); + + /* + * Initialize full structure, then set what isn't NULL + */ + ZeroMemory(wmPtr, sizeof(WmInfo)); winPtr->wmInfoPtr = wmPtr; wmPtr->winPtr = winPtr; - wmPtr->wrapper = NULL; - wmPtr->titleUid = NULL; - wmPtr->iconName = NULL; - wmPtr->masterPtr = NULL; wmPtr->hints.flags = InputHint | StateHint; wmPtr->hints.input = True; wmPtr->hints.initial_state = NormalState; @@ -584,23 +1731,16 @@ TkWmNewWindow(winPtr) wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0; wmPtr->hints.icon_mask = None; wmPtr->hints.window_group = None; - wmPtr->leaderName = NULL; - wmPtr->icon = NULL; - wmPtr->iconFor = NULL; - wmPtr->sizeHintsFlags = 0; /* * Default the maximum dimensions to the size of the display. */ wmPtr->defMinWidth = wmPtr->defMinHeight = 0; - wmPtr->defMaxWidth = DisplayWidth(winPtr->display, - winPtr->screenNum); - wmPtr->defMaxHeight = DisplayHeight(winPtr->display, - winPtr->screenNum); + wmPtr->defMaxWidth = DisplayWidth(winPtr->display, winPtr->screenNum); + wmPtr->defMaxHeight = DisplayHeight(winPtr->display, winPtr->screenNum); wmPtr->minWidth = wmPtr->minHeight = 1; wmPtr->maxWidth = wmPtr->maxHeight = 0; - wmPtr->gridWin = NULL; wmPtr->widthInc = wmPtr->heightInc = 1; wmPtr->minAspect.x = wmPtr->minAspect.y = 1; wmPtr->maxAspect.x = wmPtr->maxAspect.y = 1; @@ -608,21 +1748,11 @@ TkWmNewWindow(winPtr) wmPtr->gravity = NorthWestGravity; wmPtr->width = -1; wmPtr->height = -1; - wmPtr->hMenu = NULL; wmPtr->x = winPtr->changes.x; wmPtr->y = winPtr->changes.y; - wmPtr->borderWidth = 0; - wmPtr->borderHeight = 0; - - wmPtr->cmapList = NULL; - wmPtr->cmapCount = 0; - wmPtr->numTransients = 0; wmPtr->configWidth = -1; wmPtr->configHeight = -1; - wmPtr->protPtr = NULL; - wmPtr->cmdArgv = NULL; - wmPtr->clientMachine = NULL; wmPtr->flags = WM_NEVER_MAPPED; wmPtr->nextPtr = winPtr->dispPtr->firstWmPtr; winPtr->dispPtr->firstWmPtr = wmPtr; @@ -668,25 +1798,34 @@ UpdateWrapper(winPtr) TkWindow *winPtr; /* Top-level window to redecorate. */ { register WmInfo *wmPtr = winPtr->wmInfoPtr; - HWND parentHWND = NULL, oldWrapper; - HWND child = TkWinGetHWND(winPtr->window); + HWND parentHWND, oldWrapper; + HWND child; int x, y, width, height, state; WINDOWPLACEMENT place; - Tcl_DString titleString; + HICON hSmallIcon = NULL; + HICON hBigIcon = NULL; + Tcl_DString titleString, classString; int *childStateInfo = NULL; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - parentHWND = NULL; + if (winPtr->window == None) { + /* + * Ensure existence of the window to update the wrapper for. + */ + Tk_MakeWindowExist((Tk_Window) winPtr); + } + child = TkWinGetHWND(winPtr->window); + parentHWND = NULL; if (winPtr->flags & TK_EMBEDDED) { wmPtr->wrapper = (HWND) winPtr->privatePtr; if (wmPtr->wrapper == NULL) { - panic("TkWmMapWindow: Cannot find container window"); + panic("UpdateWrapper: Cannot find container window"); } if (!IsWindow(wmPtr->wrapper)) { - panic("TkWmMapWindow: Container was destroyed"); + panic("UpdateWrapper: Container was destroyed"); } } else { @@ -706,7 +1845,7 @@ UpdateWrapper(winPtr) wmPtr->style = WM_TRANSIENT_STYLE; wmPtr->exStyle = EX_TRANSIENT_STYLE; parentHWND = Tk_GetHWND(Tk_WindowId(wmPtr->masterPtr)); - if (! ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) && + if (! ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) && (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE))) { wmPtr->style |= WS_THICKFRAME; } @@ -715,6 +1854,9 @@ UpdateWrapper(winPtr) wmPtr->exStyle = EX_TOPLEVEL_STYLE; } + wmPtr->style |= wmPtr->styleConfig; + wmPtr->exStyle |= wmPtr->exStyleConfig; + if ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) && (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)) { wmPtr->style &= ~ (WS_MAXIMIZEBOX | WS_SIZEBOX); @@ -752,13 +1894,21 @@ UpdateWrapper(winPtr) */ tsdPtr->createWindow = winPtr; - Tcl_UtfToExternalDString(NULL, wmPtr->titleUid, -1, &titleString); - wmPtr->wrapper = CreateWindowEx(wmPtr->exStyle, - TK_WIN_TOPLEVEL_CLASS_NAME, - Tcl_DStringValue(&titleString), wmPtr->style, x, y, width, - height, parentHWND, NULL, Tk_GetHINSTANCE(), NULL); + Tcl_WinUtfToTChar(((wmPtr->title != NULL) ? + wmPtr->title : winPtr->nameUid), -1, &titleString); + Tcl_WinUtfToTChar(TK_WIN_TOPLEVEL_CLASS_NAME, -1, &classString); + wmPtr->wrapper = (*tkWinProcs->createWindowEx)(wmPtr->exStyle, + (LPCTSTR) Tcl_DStringValue(&classString), + (LPCTSTR) Tcl_DStringValue(&titleString), + wmPtr->style, x, y, width, height, + parentHWND, NULL, Tk_GetHINSTANCE(), NULL); + Tcl_DStringFree(&classString); Tcl_DStringFree(&titleString); +#ifdef _WIN64 + SetWindowLongPtr(wmPtr->wrapper, GWLP_USERDATA, (LONG_PTR) winPtr); +#else SetWindowLong(wmPtr->wrapper, GWL_USERDATA, (LONG) winPtr); +#endif tsdPtr->createWindow = NULL; place.length = sizeof(WINDOWPLACEMENT); @@ -775,15 +1925,35 @@ UpdateWrapper(winPtr) * Windows doesn't try to set the focus to the child window. */ +#ifdef _WIN64 + SetWindowLongPtr(child, GWL_STYLE, + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); +#else SetWindowLong(child, GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); +#endif if (winPtr->flags & TK_EMBEDDED) { +#ifdef _WIN64 + SetWindowLongPtr(child, GWLP_WNDPROC, (LONG_PTR) TopLevelProc); +#else SetWindowLong(child, GWL_WNDPROC, (LONG) TopLevelProc); +#endif } oldWrapper = SetParent(child, wmPtr->wrapper); - if (oldWrapper && (oldWrapper != wmPtr->wrapper) + if (oldWrapper) { + hSmallIcon = (HICON) SendMessage(oldWrapper, WM_GETICON, ICON_SMALL, + (LPARAM) NULL); + hBigIcon = (HICON) SendMessage(oldWrapper, WM_GETICON, ICON_BIG, + (LPARAM) NULL); + } + + if (oldWrapper && (oldWrapper != wmPtr->wrapper) && (oldWrapper != GetDesktopWindow())) { +#ifdef _WIN64 + SetWindowLongPtr(oldWrapper, GWLP_USERDATA, (LONG) NULL); +#else SetWindowLong(oldWrapper, GWL_USERDATA, (LONG) NULL); +#endif if (wmPtr->numTransients > 0) { /* @@ -819,13 +1989,20 @@ UpdateWrapper(winPtr) /* * Force an initial transition from withdrawn to the real - * initial state. + * initial state. */ state = wmPtr->hints.initial_state; wmPtr->hints.initial_state = WithdrawnState; TkpWmSetState(winPtr, state); + if (hSmallIcon != NULL) { + SendMessage(wmPtr->wrapper,WM_SETICON,ICON_SMALL,(LPARAM)hSmallIcon); + } + if (hBigIcon != NULL) { + SendMessage(wmPtr->wrapper,WM_SETICON,ICON_BIG,(LPARAM)hBigIcon); + } + /* * If we are embedded then force a mapping of the window now, * because we do not necessarily own the wrapper and may not @@ -842,7 +2019,7 @@ UpdateWrapper(winPtr) /* * Set up menus on the wrapper if required. */ - + if (wmPtr->hMenu != NULL) { wmPtr->flags = WM_SYNC_PENDING; SetMenu(wmPtr->wrapper, wmPtr->hMenu); @@ -911,14 +2088,24 @@ TkWmMapWindow(winPtr) * be mapped. */ { register WmInfo *wmPtr = winPtr->wmInfoPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (!tsdPtr->initialized) { InitWm(); } - if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + if (wmPtr->flags & WM_NEVER_MAPPED) { + /* + * Don't map a transient if the master is not mapped. + */ + + if (wmPtr->masterPtr != NULL && + !Tk_IsMapped(wmPtr->masterPtr)) { + wmPtr->hints.initial_state = WithdrawnState; + return; + } + } else { if (wmPtr->hints.initial_state == WithdrawnState) { return; } @@ -937,9 +2124,6 @@ TkWmMapWindow(winPtr) * window. */ - if (wmPtr->titleUid == NULL) { - wmPtr->titleUid = winPtr->nameUid; - } UpdateWrapper(winPtr); } @@ -995,8 +2179,7 @@ TkpWmSetState(winPtr, state) WmInfo *wmPtr = winPtr->wmInfoPtr; int cmd; - if ((wmPtr->flags & WM_NEVER_MAPPED) || - (wmPtr->masterPtr && !Tk_IsMapped(wmPtr->masterPtr))) { + if (wmPtr->flags & WM_NEVER_MAPPED) { wmPtr->hints.initial_state = state; return; } @@ -1072,6 +2255,10 @@ TkWmDeadWindow(winPtr) for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL; wmPtr2 = wmPtr2->nextPtr) { if (wmPtr2->masterPtr == winPtr) { + wmPtr->numTransients--; + Tk_DeleteEventHandler((Tk_Window) wmPtr2->masterPtr, + VisibilityChangeMask|StructureNotifyMask, + WmWaitVisibilityOrMapProc, (ClientData) wmPtr2->winPtr); wmPtr2->masterPtr = NULL; if ((wmPtr2->wrapper != None) && !(wmPtr2->flags & (WM_NEVER_MAPPED))) { @@ -1079,7 +2266,15 @@ TkWmDeadWindow(winPtr) } } } - + if (wmPtr->numTransients != 0) + panic("numTransients should be 0"); + + if (wmPtr->title != NULL) { + ckfree(wmPtr->title); + } + if (wmPtr->iconName != NULL) { + ckfree(wmPtr->iconName); + } if (wmPtr->hints.flags & IconPixmapHint) { Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap); } @@ -1124,8 +2319,8 @@ TkWmDeadWindow(winPtr) wmPtr2->numTransients--; } Tk_DeleteEventHandler((Tk_Window) wmPtr->masterPtr, - VisibilityChangeMask, - WmWaitVisibilityProc, (ClientData) winPtr); + VisibilityChangeMask|StructureNotifyMask, + WmWaitVisibilityOrMapProc, (ClientData) winPtr); wmPtr->masterPtr = NULL; } @@ -1140,6 +2335,15 @@ TkWmDeadWindow(winPtr) DestroyWindow(Tk_GetHWND(winPtr->window)); } } + if (wmPtr->iconPtr != NULL) { + /* + * This may delete the icon resource data. I believe we + * should do this after destroying the decorative frame, + * because the decorative frame is using this icon. + */ + DecrIconRefCount(wmPtr->iconPtr); + } + ckfree((char *) wmPtr); winPtr->wmInfoPtr = NULL; } @@ -1174,7 +2378,7 @@ TkWmSetClass(winPtr) /* *---------------------------------------------------------------------- * - * Tk_WmCmd -- + * Tk_WmObjCmd -- * * This procedure is invoked to process the "wm" Tcl command. * See the user documentation for details on what it does. @@ -1190,1154 +2394,2343 @@ TkWmSetClass(winPtr) /* ARGSUSED */ int -Tk_WmCmd(clientData, interp, argc, argv) +Tk_WmObjCmd(clientData, interp, objc, objv) ClientData clientData; /* Main window associated with * interpreter. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { Tk_Window tkwin = (Tk_Window) clientData; - TkWindow *winPtr = NULL; - register WmInfo *wmPtr; - int c; - size_t length; + static CONST char *optionStrings[] = { + "aspect", "attributes", "client", "colormapwindows", + "command", "deiconify", "focusmodel", "frame", + "geometry", "grid", "group", "iconbitmap", + "iconify", "iconmask", "iconname", "iconposition", + "iconwindow", "maxsize", "minsize", "overrideredirect", + "positionfrom", "protocol", "resizable", "sizefrom", + "stackorder", "state", "title", "transient", + "withdraw", (char *) NULL }; + enum options { + WMOPT_ASPECT, WMOPT_ATTRIBUTES, WMOPT_CLIENT, WMOPT_COLORMAPWINDOWS, + WMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FRAME, + WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP, WMOPT_ICONBITMAP, + WMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME, WMOPT_ICONPOSITION, + WMOPT_ICONWINDOW, WMOPT_MAXSIZE, WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT, + WMOPT_POSITIONFROM, WMOPT_PROTOCOL, WMOPT_RESIZABLE, WMOPT_SIZEFROM, + WMOPT_STACKORDER, WMOPT_STATE, WMOPT_TITLE, WMOPT_TRANSIENT, + WMOPT_WITHDRAW }; + int index, length; + char *argv1; + TkWindow *winPtr; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; - if (argc < 2) { + if (objc < 2) { wrongNumArgs: - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " option window ?arg ...?\"", (char *) NULL); + Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?"); return TCL_ERROR; } - c = argv[1][0]; - length = strlen(argv[1]); - if ((c == 't') && (strncmp(argv[1], "tracing", length) == 0) + + argv1 = Tcl_GetStringFromObj(objv[1], &length); + if ((argv1[0] == 't') && (strncmp(argv1, "tracing", length) == 0) && (length >= 3)) { - if ((argc != 2) && (argc != 3)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " tracing ?boolean?\"", (char *) NULL); + int wmTracing; + if ((objc != 2) && (objc != 3)) { + Tcl_WrongNumArgs(interp, 2, objv, "?boolean?"); return TCL_ERROR; } - if (argc == 2) { - Tcl_SetResult(interp, ((dispPtr->wmTracing) ? "on" : "off"), + if (objc == 2) { + Tcl_SetResult(interp, + ((dispPtr->flags & TK_DISPLAY_WM_TRACING) ? "on" : "off"), TCL_STATIC); return TCL_OK; } - return Tcl_GetBoolean(interp, argv[2], &dispPtr->wmTracing); + if (Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing) != TCL_OK) { + return TCL_ERROR; + } + if (wmTracing) { + dispPtr->flags |= TK_DISPLAY_WM_TRACING; + } else { + dispPtr->flags &= ~TK_DISPLAY_WM_TRACING; + } + return TCL_OK; + } + + if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, + &index) != TCL_OK) { + return TCL_ERROR; } - if (argc < 3) { + if (objc < 3) { goto wrongNumArgs; } - winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2], tkwin); - if (winPtr == NULL) { + + if (TkGetWindowFromObj(interp, tkwin, objv[2], (Tk_Window *) &winPtr) + != TCL_OK) { return TCL_ERROR; } - if (!(winPtr->flags & TK_TOP_LEVEL)) { + if (!Tk_IsTopLevel(winPtr)) { Tcl_AppendResult(interp, "window \"", winPtr->pathName, "\" isn't a top-level window", (char *) NULL); return TCL_ERROR; } - wmPtr = winPtr->wmInfoPtr; - if ((c == 'a') && (strncmp(argv[1], "aspect", length) == 0)) { - int numer1, denom1, numer2, denom2; - if ((argc != 3) && (argc != 7)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " aspect window ?minNumer minDenom ", - "maxNumer maxDenom?\"", (char *) NULL); + switch ((enum options) index) { + case WMOPT_ASPECT: + return WmAspectCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ATTRIBUTES: + return WmAttributesCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_CLIENT: + return WmClientCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_COLORMAPWINDOWS: + return WmColormapwindowsCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_COMMAND: + return WmCommandCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_DEICONIFY: + return WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_FOCUSMODEL: + return WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_FRAME: + return WmFrameCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_GEOMETRY: + return WmGeometryCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_GRID: + return WmGridCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_GROUP: + return WmGroupCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONBITMAP: + return WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONIFY: + return WmIconifyCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONMASK: + return WmIconmaskCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONNAME: + return WmIconnameCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONPOSITION: + return WmIconpositionCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONWINDOW: + return WmIconwindowCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_MAXSIZE: + return WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_MINSIZE: + return WmMinsizeCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_OVERRIDEREDIRECT: + return WmOverrideredirectCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_POSITIONFROM: + return WmPositionfromCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_PROTOCOL: + return WmProtocolCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_RESIZABLE: + return WmResizableCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_SIZEFROM: + return WmSizefromCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_STACKORDER: + return WmStackorderCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_STATE: + return WmStateCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_TITLE: + return WmTitleCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_TRANSIENT: + return WmTransientCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_WITHDRAW: + return WmWithdrawCmd(tkwin, winPtr, interp, objc, objv); + } + + /* This should not happen */ + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * WmAspectCmd -- + * + * This procedure is invoked to process the "wm aspect" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmAspectCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int numer1, denom1, numer2, denom2; + + if ((objc != 3) && (objc != 7)) { + Tcl_WrongNumArgs(interp, 2, objv, + "window ?minNumer minDenom maxNumer maxDenom?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->sizeHintsFlags & PAspect) { + char buf[TCL_INTEGER_SPACE * 4]; + + sprintf(buf, "%d %d %d %d", wmPtr->minAspect.x, + wmPtr->minAspect.y, wmPtr->maxAspect.x, + wmPtr->maxAspect.y); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + } + return TCL_OK; + } + if (*Tcl_GetString(objv[3]) == '\0') { + wmPtr->sizeHintsFlags &= ~PAspect; + } else { + if ((Tcl_GetIntFromObj(interp, objv[3], &numer1) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &denom1) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[5], &numer2) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[6], &denom2) != TCL_OK)) { return TCL_ERROR; } - if (argc == 3) { - if (wmPtr->sizeHintsFlags & PAspect) { - char buf[TCL_INTEGER_SPACE * 4]; - - sprintf(buf, "%d %d %d %d", wmPtr->minAspect.x, - wmPtr->minAspect.y, wmPtr->maxAspect.x, - wmPtr->maxAspect.y); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } - return TCL_OK; + if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) || + (denom2 <= 0)) { + Tcl_SetResult(interp, "aspect number can't be <= 0", + TCL_STATIC); + return TCL_ERROR; } - if (*argv[3] == '\0') { - wmPtr->sizeHintsFlags &= ~PAspect; - } else { - if ((Tcl_GetInt(interp, argv[3], &numer1) != TCL_OK) - || (Tcl_GetInt(interp, argv[4], &denom1) != TCL_OK) - || (Tcl_GetInt(interp, argv[5], &numer2) != TCL_OK) - || (Tcl_GetInt(interp, argv[6], &denom2) != TCL_OK)) { - return TCL_ERROR; - } - if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) || - (denom2 <= 0)) { - Tcl_SetResult(interp, "aspect number can't be <= 0", - TCL_STATIC); - return TCL_ERROR; - } - wmPtr->minAspect.x = numer1; - wmPtr->minAspect.y = denom1; - wmPtr->maxAspect.x = numer2; - wmPtr->maxAspect.y = denom2; - wmPtr->sizeHintsFlags |= PAspect; - } - goto updateGeom; - } else if ((c == 'c') && (strncmp(argv[1], "client", length) == 0) - && (length >= 2)) { - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " client window ?name?\"", - (char *) NULL); + wmPtr->minAspect.x = numer1; + wmPtr->minAspect.y = denom1; + wmPtr->maxAspect.x = numer2; + wmPtr->maxAspect.y = denom2; + wmPtr->sizeHintsFlags |= PAspect; + } + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmAttributesCmd -- + * + * This procedure is invoked to process the "wm attributes" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmAttributesCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + LONG style, exStyle, styleBit, *stylePtr; + char buf[TCL_INTEGER_SPACE], *string; + int i, boolean, length; + + if (objc < 3) { + configArgs: + Tcl_WrongNumArgs(interp, 2, objv, + "window" + " ?-disabled ?bool??" + " ?-toolwindow ?bool??" + " ?-topmost ?bool??"); + return TCL_ERROR; + } + exStyle = wmPtr->exStyleConfig; + style = wmPtr->styleConfig; + if (objc == 3) { + sprintf(buf, "%d", ((style & WS_DISABLED) != 0)); + Tcl_AppendResult(interp, "-disabled ", buf, (char *) NULL); + sprintf(buf, "%d", ((exStyle & WS_EX_TOOLWINDOW) != 0)); + Tcl_AppendResult(interp, " -toolwindow ", buf, (char *) NULL); + sprintf(buf, "%d", ((exStyle & WS_EX_TOPMOST) != 0)); + Tcl_AppendResult(interp, " -topmost ", buf, (char *) NULL); + return TCL_OK; + } + for (i = 3; i < objc; i += 2) { + string = Tcl_GetStringFromObj(objv[i], &length); + if ((length < 2) || (string[0] != '-')) { + goto configArgs; + } + if ((i < objc-1) && + (Tcl_GetBooleanFromObj(interp, objv[i+1], &boolean) != TCL_OK)) { return TCL_ERROR; } - if (argc == 3) { - if (wmPtr->clientMachine != NULL) { - Tcl_SetResult(interp, wmPtr->clientMachine, TCL_STATIC); + if (strncmp(string, "-disabled", length) == 0) { + stylePtr = &style; + styleBit = WS_DISABLED; + } else if ((strncmp(string, "-toolwindow", length) == 0) + && (length >= 3)) { + stylePtr = &exStyle; + styleBit = WS_EX_TOOLWINDOW; + } else if ((strncmp(string, "-topmost", length) == 0) + && (length >= 3)) { + stylePtr = &exStyle; + styleBit = WS_EX_TOPMOST; + if ((i < objc-1) && (winPtr->flags & TK_EMBEDDED)) { + Tcl_AppendResult(interp, "can't set topmost flag on ", + winPtr->pathName, ": it is an embedded window", + (char *) NULL); + return TCL_ERROR; } - return TCL_OK; + } else { + goto configArgs; } - if (argv[3][0] == 0) { - if (wmPtr->clientMachine != NULL) { - ckfree((char *) wmPtr->clientMachine); - wmPtr->clientMachine = NULL; - if (!(wmPtr->flags & WM_NEVER_MAPPED)) { - XDeleteProperty(winPtr->display, winPtr->window, - Tk_InternAtom((Tk_Window) winPtr, - "WM_CLIENT_MACHINE")); - } - } - return TCL_OK; + if (i == objc-1) { + Tcl_SetIntObj(Tcl_GetObjResult(interp), + ((*stylePtr & styleBit) != 0)); + } else if (boolean) { + *stylePtr |= styleBit; + } else { + *stylePtr &= ~styleBit; } + } + if ((wmPtr->styleConfig != style) || + (wmPtr->exStyleConfig != exStyle)) { + wmPtr->styleConfig = style; + wmPtr->exStyleConfig = exStyle; + UpdateWrapper(winPtr); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmClientCmd -- + * + * This procedure is invoked to process the "wm client" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmClientCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + char *argv3; + int length; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?name?"); + return TCL_ERROR; + } + if (objc == 3) { if (wmPtr->clientMachine != NULL) { - ckfree((char *) wmPtr->clientMachine); + Tcl_SetResult(interp, wmPtr->clientMachine, TCL_STATIC); } - wmPtr->clientMachine = (char *) - ckalloc((unsigned) (strlen(argv[3]) + 1)); - strcpy(wmPtr->clientMachine, argv[3]); - if (!(wmPtr->flags & WM_NEVER_MAPPED)) { - XTextProperty textProp; - if (XStringListToTextProperty(&wmPtr->clientMachine, 1, &textProp) - != 0) { - XSetWMClientMachine(winPtr->display, winPtr->window, - &textProp); - XFree((char *) textProp.value); + return TCL_OK; + } + argv3 = Tcl_GetStringFromObj(objv[3], &length); + if (argv3[0] == 0) { + if (wmPtr->clientMachine != NULL) { + ckfree((char *) wmPtr->clientMachine); + wmPtr->clientMachine = NULL; + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + XDeleteProperty(winPtr->display, winPtr->window, + Tk_InternAtom((Tk_Window) winPtr, + "WM_CLIENT_MACHINE")); } } - } else if ((c == 'c') && (strncmp(argv[1], "colormapwindows", length) == 0) - && (length >= 3)) { - TkWindow **cmapList; - TkWindow *winPtr2; - int i, windowArgc, gotToplevel; - char **windowArgv; - - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " colormapwindows window ?windowList?\"", - (char *) NULL); - return TCL_ERROR; + return TCL_OK; + } + if (wmPtr->clientMachine != NULL) { + ckfree((char *) wmPtr->clientMachine); + } + wmPtr->clientMachine = (char *) + ckalloc((unsigned) (length + 1)); + strcpy(wmPtr->clientMachine, argv3); + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + XTextProperty textProp; + if (XStringListToTextProperty(&wmPtr->clientMachine, 1, &textProp) + != 0) { + XSetWMClientMachine(winPtr->display, winPtr->window, + &textProp); + XFree((char *) textProp.value); } - if (argc == 3) { - Tk_MakeWindowExist((Tk_Window) winPtr); - for (i = 0; i < wmPtr->cmapCount; i++) { - if ((i == (wmPtr->cmapCount-1)) - && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) { - break; - } - Tcl_AppendElement(interp, wmPtr->cmapList[i]->pathName); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmColormapwindowsCmd -- + * + * This procedure is invoked to process the "wm colormapwindows" + * Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmColormapwindowsCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + TkWindow **cmapList; + TkWindow *winPtr2; + int i, windowObjc, gotToplevel; + Tcl_Obj **windowObjv; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?windowList?"); + return TCL_ERROR; + } + if (objc == 3) { + Tk_MakeWindowExist((Tk_Window) winPtr); + for (i = 0; i < wmPtr->cmapCount; i++) { + if ((i == (wmPtr->cmapCount-1)) + && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) { + break; } - return TCL_OK; + Tcl_AppendElement(interp, wmPtr->cmapList[i]->pathName); } - if (Tcl_SplitList(interp, argv[3], &windowArgc, &windowArgv) - != TCL_OK) { + return TCL_OK; + } + if (Tcl_ListObjGetElements(interp, objv[3], &windowObjc, &windowObjv) + != TCL_OK) { + return TCL_ERROR; + } + cmapList = (TkWindow **) ckalloc((unsigned) + ((windowObjc+1)*sizeof(TkWindow*))); + gotToplevel = 0; + for (i = 0; i < windowObjc; i++) { + if (TkGetWindowFromObj(interp, tkwin, windowObjv[i], + (Tk_Window *) &winPtr2) != TCL_OK) + { + ckfree((char *) cmapList); return TCL_ERROR; } - cmapList = (TkWindow **) ckalloc((unsigned) - ((windowArgc+1)*sizeof(TkWindow*))); - for (i = 0; i < windowArgc; i++) { - winPtr2 = (TkWindow *) Tk_NameToWindow(interp, windowArgv[i], - tkwin); - if (winPtr2 == NULL) { - ckfree((char *) cmapList); - ckfree((char *) windowArgv); - return TCL_ERROR; - } - if (winPtr2 == winPtr) { - gotToplevel = 1; - } - if (winPtr2->window == None) { - Tk_MakeWindowExist((Tk_Window) winPtr2); - } - cmapList[i] = winPtr2; + if (winPtr2 == winPtr) { + gotToplevel = 1; } - if (!gotToplevel) { - wmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP; - cmapList[windowArgc] = winPtr; - windowArgc++; - } else { - wmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP; + if (winPtr2->window == None) { + Tk_MakeWindowExist((Tk_Window) winPtr2); + } + cmapList[i] = winPtr2; + } + if (!gotToplevel) { + wmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP; + cmapList[windowObjc] = winPtr; + windowObjc++; + } else { + wmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP; + } + wmPtr->flags |= WM_COLORMAPS_EXPLICIT; + if (wmPtr->cmapList != NULL) { + ckfree((char *)wmPtr->cmapList); + } + wmPtr->cmapList = cmapList; + wmPtr->cmapCount = windowObjc; + + /* + * Now we need to force the updated colormaps to be installed. + */ + + if (wmPtr == winPtr->dispPtr->foregroundWmPtr) { + InstallColormaps(wmPtr->wrapper, WM_QUERYNEWPALETTE, 1); + } else { + InstallColormaps(wmPtr->wrapper, WM_PALETTECHANGED, 0); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmCommandCmd -- + * + * This procedure is invoked to process the "wm command" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmCommandCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + char *argv3; + int cmdArgc; + CONST char **cmdArgv; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?value?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->cmdArgv != NULL) { + Tcl_SetResult(interp, + Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv), + TCL_DYNAMIC); } - wmPtr->flags |= WM_COLORMAPS_EXPLICIT; - if (wmPtr->cmapList != NULL) { - ckfree((char *)wmPtr->cmapList); + return TCL_OK; + } + argv3 = Tcl_GetString(objv[3]); + if (argv3[0] == 0) { + if (wmPtr->cmdArgv != NULL) { + ckfree((char *) wmPtr->cmdArgv); + wmPtr->cmdArgv = NULL; + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + XDeleteProperty(winPtr->display, winPtr->window, + Tk_InternAtom((Tk_Window) winPtr, "WM_COMMAND")); + } } - wmPtr->cmapList = cmapList; - wmPtr->cmapCount = windowArgc; - ckfree((char *) windowArgv); + return TCL_OK; + } + if (Tcl_SplitList(interp, argv3, &cmdArgc, &cmdArgv) != TCL_OK) { + return TCL_ERROR; + } + if (wmPtr->cmdArgv != NULL) { + ckfree((char *) wmPtr->cmdArgv); + } + wmPtr->cmdArgc = cmdArgc; + wmPtr->cmdArgv = cmdArgv; + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + XSetCommand(winPtr->display, winPtr->window, cmdArgv, cmdArgc); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmDeiconifyCmd -- + * + * This procedure is invoked to process the "wm deiconify" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ - /* - * Now we need to force the updated colormaps to be installed. - */ +static int +WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + if (wmPtr->iconFor != NULL) { + Tcl_AppendResult(interp, "can't deiconify ", Tcl_GetString(objv[2]), + ": it is an icon for ", Tk_PathName(wmPtr->iconFor), + (char *) NULL); + return TCL_ERROR; + } + if (winPtr->flags & TK_EMBEDDED) { + Tcl_AppendResult(interp, "can't deiconify ", winPtr->pathName, + ": it is an embedded window", (char *) NULL); + return TCL_ERROR; + } + + if (wmPtr->flags & WM_TRANSIENT_WITHDRAWN) { + wmPtr->flags &= ~WM_TRANSIENT_WITHDRAWN; + } + + /* + * If WM_UPDATE_PENDING is true, a pending UpdateGeometryInfo may + * need to be called first to update a withdrawn toplevel's geometry + * before it is deiconified by TkpWmSetState. + * Don't bother if we've never been mapped. + */ + if ((wmPtr->flags & WM_UPDATE_PENDING) && + !(wmPtr->flags & WM_NEVER_MAPPED)) { + Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr); + UpdateGeometryInfo((ClientData) winPtr); + } + + /* + * If we were in the ZoomState (maximized), 'wm deiconify' + * should not cause the window to shrink + */ + if (wmPtr->hints.initial_state == ZoomState) { + TkpWmSetState(winPtr, ZoomState); + } else { + TkpWmSetState(winPtr, NormalState); + } + + /* + * An unmapped window will be mapped at idle time + * by a call to MapFrame. That calls CreateWrapper + * which sets the focus and raises the window. + */ + if (wmPtr->flags & WM_NEVER_MAPPED) { + return TCL_OK; + } + + /* + * Follow Windows-like style here, raising the window to the top. + */ + TkWmRestackToplevel(winPtr, Above, NULL); + if (!(Tk_Attributes((Tk_Window) winPtr)->override_redirect)) { + TkSetFocusWin(winPtr, 1); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmFocusmodelCmd -- + * + * This procedure is invoked to process the "wm focusmodel" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + static CONST char *optionStrings[] = { + "active", "passive", (char *) NULL }; + enum options { + OPT_ACTIVE, OPT_PASSIVE }; + int index; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?active|passive?"); + return TCL_ERROR; + } + if (objc == 3) { + Tcl_SetResult(interp, (wmPtr->hints.input ? "passive" : "active"), + TCL_STATIC); + return TCL_OK; + } + + if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == OPT_ACTIVE) { + wmPtr->hints.input = False; + } else { /* OPT_PASSIVE */ + wmPtr->hints.input = True; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmFrameCmd -- + * + * This procedure is invoked to process the "wm frame" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmFrameCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + HWND hwnd; + char buf[TCL_INTEGER_SPACE]; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + if (Tk_WindowId((Tk_Window) winPtr) == None) { + Tk_MakeWindowExist((Tk_Window) winPtr); + } + hwnd = wmPtr->wrapper; + if (hwnd == NULL) { + hwnd = Tk_GetHWND(Tk_WindowId((Tk_Window) winPtr)); + } + sprintf(buf, "0x%x", (unsigned int) hwnd); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmGeometryCmd -- + * + * This procedure is invoked to process the "wm geometry" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ - if (wmPtr == winPtr->dispPtr->foregroundWmPtr) { - InstallColormaps(wmPtr->wrapper, WM_QUERYNEWPALETTE, 1); +static int +WmGeometryCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + char xSign, ySign; + int width, height; + char *argv3; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?newGeometry?"); + return TCL_ERROR; + } + if (objc == 3) { + char buf[16 + TCL_INTEGER_SPACE * 4]; + + xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+'; + ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+'; + if (wmPtr->gridWin != NULL) { + width = wmPtr->reqGridWidth + (winPtr->changes.width + - winPtr->reqWidth)/wmPtr->widthInc; + height = wmPtr->reqGridHeight + (winPtr->changes.height + - winPtr->reqHeight)/wmPtr->heightInc; } else { - InstallColormaps(wmPtr->wrapper, WM_PALETTECHANGED, 0); + width = winPtr->changes.width; + height = winPtr->changes.height; } + sprintf(buf, "%dx%d%c%d%c%d", width, height, xSign, wmPtr->x, + ySign, wmPtr->y); + Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_OK; - } else if ((c == 'c') && (strncmp(argv[1], "command", length) == 0) - && (length >= 3)) { - int cmdArgc; - char **cmdArgv; + } + argv3 = Tcl_GetString(objv[3]); + if (*argv3 == '\0') { + wmPtr->width = -1; + wmPtr->height = -1; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; + } + return ParseGeometry(interp, argv3, winPtr); +} + +/* + *---------------------------------------------------------------------- + * + * WmGridCmd -- + * + * This procedure is invoked to process the "wm grid" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " command window ?value?\"", - (char *) NULL); - return TCL_ERROR; - } - if (argc == 3) { - if (wmPtr->cmdArgv != NULL) { - Tcl_SetResult(interp, - Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv), - TCL_DYNAMIC); - } - return TCL_OK; +static int +WmGridCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int reqWidth, reqHeight, widthInc, heightInc; + + if ((objc != 3) && (objc != 7)) { + Tcl_WrongNumArgs(interp, 2, objv, + "window ?baseWidth baseHeight widthInc heightInc?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->sizeHintsFlags & PBaseSize) { + char buf[TCL_INTEGER_SPACE * 4]; + + sprintf(buf, "%d %d %d %d", wmPtr->reqGridWidth, + wmPtr->reqGridHeight, wmPtr->widthInc, + wmPtr->heightInc); + Tcl_SetResult(interp, buf, TCL_VOLATILE); } - if (argv[3][0] == 0) { - if (wmPtr->cmdArgv != NULL) { - ckfree((char *) wmPtr->cmdArgv); - wmPtr->cmdArgv = NULL; - if (!(wmPtr->flags & WM_NEVER_MAPPED)) { - XDeleteProperty(winPtr->display, winPtr->window, - Tk_InternAtom((Tk_Window) winPtr, "WM_COMMAND")); - } - } - return TCL_OK; + return TCL_OK; + } + if (*Tcl_GetString(objv[3]) == '\0') { + /* + * Turn off gridding and reset the width and height + * to make sense as ungridded numbers. + */ + + wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc); + if (wmPtr->width != -1) { + wmPtr->width = winPtr->reqWidth + (wmPtr->width + - wmPtr->reqGridWidth)*wmPtr->widthInc; + wmPtr->height = winPtr->reqHeight + (wmPtr->height + - wmPtr->reqGridHeight)*wmPtr->heightInc; } - if (Tcl_SplitList(interp, argv[3], &cmdArgc, &cmdArgv) != TCL_OK) { + wmPtr->widthInc = 1; + wmPtr->heightInc = 1; + } else { + if ((Tcl_GetIntFromObj(interp, objv[3], &reqWidth) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &reqHeight) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[5], &widthInc) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[6], &heightInc) != TCL_OK)) { return TCL_ERROR; } - if (wmPtr->cmdArgv != NULL) { - ckfree((char *) wmPtr->cmdArgv); - } - wmPtr->cmdArgc = cmdArgc; - wmPtr->cmdArgv = cmdArgv; - if (!(wmPtr->flags & WM_NEVER_MAPPED)) { - XSetCommand(winPtr->display, winPtr->window, cmdArgv, cmdArgc); + if (reqWidth < 0) { + Tcl_SetResult(interp, "baseWidth can't be < 0", TCL_STATIC); + return TCL_ERROR; } - } else if ((c == 'd') && (strncmp(argv[1], "deiconify", length) == 0)) { - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " deiconify window\"", (char *) NULL); + if (reqHeight < 0) { + Tcl_SetResult(interp, "baseHeight can't be < 0", TCL_STATIC); return TCL_ERROR; } - if (wmPtr->iconFor != NULL) { - Tcl_AppendResult(interp, "can't deiconify ", argv[2], - ": it is an icon for ", winPtr->pathName, (char *) NULL); + if (widthInc < 0) { + Tcl_SetResult(interp, "widthInc can't be < 0", TCL_STATIC); return TCL_ERROR; } - if (winPtr->flags & TK_EMBEDDED) { - Tcl_AppendResult(interp, "can't deiconify ", winPtr->pathName, - ": it is an embedded window", (char *) NULL); - return TCL_ERROR; - } - /* - * If WM_UPDATE_PENDING is true, a pending UpdateGeometryInfo may - * need to be called first to update a withdrew toplevel's geometry - * before it is deiconified by TkpWmSetState. - * Don't bother if we've never been mapped. - */ - if (wmPtr->flags & WM_UPDATE_PENDING) { - Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr); - UpdateGeometryInfo((ClientData) winPtr); + if (heightInc < 0) { + Tcl_SetResult(interp, "heightInc can't be < 0", TCL_STATIC); + return TCL_ERROR; } + Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc, + heightInc); + } + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmGroupCmd -- + * + * This procedure is invoked to process the "wm group" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ - /* - * If we were in the ZoomState (maximized), 'wm deiconify' - * should not cause the window to shrink - */ - if (wmPtr->hints.initial_state == ZoomState) { - TkpWmSetState(winPtr, ZoomState); - } else { - TkpWmSetState(winPtr, NormalState); - } +static int +WmGroupCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Tk_Window tkwin2; + char *argv3; + int length; - /* - * Follow Windows-like style here, raising the window to the top. - */ - TkWmRestackToplevel(winPtr, Above, NULL); - if (!(Tk_Attributes((Tk_Window) winPtr)->override_redirect)) { - TkSetFocusWin(winPtr, 1); - } - } else if ((c == 'f') && (strncmp(argv[1], "focusmodel", length) == 0) - && (length >= 2)) { - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " focusmodel window ?active|passive?\"", - (char *) NULL); - return TCL_ERROR; - } - if (argc == 3) { - Tcl_SetResult(interp, (wmPtr->hints.input ? "passive" : "active"), - TCL_STATIC); - return TCL_OK; + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->hints.flags & WindowGroupHint) { + Tcl_SetResult(interp, wmPtr->leaderName, TCL_STATIC); } - c = argv[3][0]; - length = strlen(argv[3]); - if ((c == 'a') && (strncmp(argv[3], "active", length) == 0)) { - wmPtr->hints.input = False; - } else if ((c == 'p') && (strncmp(argv[3], "passive", length) == 0)) { - wmPtr->hints.input = True; - } else { - Tcl_AppendResult(interp, "bad argument \"", argv[3], - "\": must be active or passive", (char *) NULL); - return TCL_ERROR; + return TCL_OK; + } + argv3 = Tcl_GetStringFromObj(objv[3], &length); + if (*argv3 == '\0') { + wmPtr->hints.flags &= ~WindowGroupHint; + if (wmPtr->leaderName != NULL) { + ckfree(wmPtr->leaderName); } - } else if ((c == 'f') && (strncmp(argv[1], "frame", length) == 0) - && (length >= 2)) { - HWND hwnd; - char buf[TCL_INTEGER_SPACE]; - - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " frame window\"", (char *) NULL); + wmPtr->leaderName = NULL; + } else { + if (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) { return TCL_ERROR; } - if (Tk_WindowId((Tk_Window) winPtr) == None) { - Tk_MakeWindowExist((Tk_Window) winPtr); - } - hwnd = wmPtr->wrapper; - if (hwnd == NULL) { - hwnd = Tk_GetHWND(Tk_WindowId((Tk_Window) winPtr)); + Tk_MakeWindowExist(tkwin2); + if (wmPtr->leaderName != NULL) { + ckfree(wmPtr->leaderName); } - sprintf(buf, "0x%x", (unsigned int) hwnd); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } else if ((c == 'g') && (strncmp(argv[1], "geometry", length) == 0) - && (length >= 2)) { - char xSign, ySign; - int width, height; + wmPtr->hints.window_group = Tk_WindowId(tkwin2); + wmPtr->hints.flags |= WindowGroupHint; + wmPtr->leaderName = ckalloc((unsigned) (length + 1)); + strcpy(wmPtr->leaderName, argv3); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconbitmapCmd -- + * + * This procedure is invoked to process the "wm iconbitmap" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " geometry window ?newGeometry?\"", +static int +WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + /* If true, then set for all windows. */ + int isDefault = 0; + char *string; + + if ((objc < 3) || (objc > 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?-default? ?image?"); + return TCL_ERROR; + } else if (objc == 5) { + /* If we have 5 arguments, we must have a '-default' flag */ + char *argv3 = Tcl_GetString(objv[3]); + if (strcmp(argv3, "-default")) { + Tcl_AppendResult(interp, "illegal option \"", + argv3, "\" must be \"-default\"", (char *) NULL); return TCL_ERROR; } - if (argc == 3) { - char buf[16 + TCL_INTEGER_SPACE * 4]; - - xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+'; - ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+'; - if (wmPtr->gridWin != NULL) { - width = wmPtr->reqGridWidth + (winPtr->changes.width - - winPtr->reqWidth)/wmPtr->widthInc; - height = wmPtr->reqGridHeight + (winPtr->changes.height - - winPtr->reqHeight)/wmPtr->heightInc; - } else { - width = winPtr->changes.width; - height = winPtr->changes.height; - } - sprintf(buf, "%dx%d%c%d%c%d", width, height, xSign, wmPtr->x, - ySign, wmPtr->y); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - return TCL_OK; - } - if (*argv[3] == '\0') { - wmPtr->width = -1; - wmPtr->height = -1; - goto updateGeom; + isDefault = 1; + } else if (objc == 3) { + /* No arguments were given */ + if (wmPtr->hints.flags & IconPixmapHint) { + Tcl_SetResult(interp, (char *) + Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_pixmap), + TCL_STATIC); } - return ParseGeometry(interp, argv[3], winPtr); - } else if ((c == 'g') && (strncmp(argv[1], "grid", length) == 0) - && (length >= 3)) { - int reqWidth, reqHeight, widthInc, heightInc; + return TCL_OK; + } - if ((argc != 3) && (argc != 7)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " grid window ?baseWidth baseHeight ", - "widthInc heightInc?\"", (char *) NULL); + string = Tcl_GetString(objv[objc-1]); + if (*string == '\0') { + if (wmPtr->hints.icon_pixmap != None) { + Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap); + wmPtr->hints.icon_pixmap = None; + } + wmPtr->hints.flags &= ~IconPixmapHint; + if (WinSetIcon(interp, NULL, + (isDefault ? NULL : (Tk_Window) winPtr)) != TCL_OK) { return TCL_ERROR; } - if (argc == 3) { - if (wmPtr->sizeHintsFlags & PBaseSize) { - char buf[TCL_INTEGER_SPACE * 4]; - - sprintf(buf, "%d %d %d %d", wmPtr->reqGridWidth, - wmPtr->reqGridHeight, wmPtr->widthInc, - wmPtr->heightInc); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + } else { + /* + * In the future this block of code will use Tk's 'image' + * functionality to allow all supported image formats. + * However, this will require a change to the way icons are + * handled. We will need to add icon<->image conversions + * routines. + * + * Until that happens we simply try to find an icon in the + * given argument, and if that fails, we use the older + * bitmap code. We do things this way round (icon then + * bitmap), because the bitmap code actually seems to have + * no visible effect, so we want to give the icon code the + * first try at doing something. + */ + + /* + * Either return NULL, or return a valid titlebaricon with its + * ref count already incremented. + */ + WinIconPtr titlebaricon = ReadIconFromFile(interp, objv[objc-1]); + if (titlebaricon != NULL) { + /* + * Try to set the icon for the window. If it is a '-default' + * icon, we must pass in NULL + */ + if (WinSetIcon(interp, titlebaricon, + (isDefault ? NULL : (Tk_Window) winPtr)) != TCL_OK) { + /* We didn't use the titlebaricon after all */ + DecrIconRefCount(titlebaricon); + titlebaricon = NULL; } - return TCL_OK; } - if (*argv[3] == '\0') { + if (titlebaricon == NULL) { /* - * Turn off gridding and reset the width and height - * to make sense as ungridded numbers. + * We didn't manage to handle the argument as a valid + * icon. Try as a bitmap. First we must clear the + * error message which was placed in the interpreter */ - - wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc); - if (wmPtr->width != -1) { - wmPtr->width = winPtr->reqWidth + (wmPtr->width - - wmPtr->reqGridWidth)*wmPtr->widthInc; - wmPtr->height = winPtr->reqHeight + (wmPtr->height - - wmPtr->reqGridHeight)*wmPtr->heightInc; - } - wmPtr->widthInc = 1; - wmPtr->heightInc = 1; - } else { - if ((Tcl_GetInt(interp, argv[3], &reqWidth) != TCL_OK) - || (Tcl_GetInt(interp, argv[4], &reqHeight) != TCL_OK) - || (Tcl_GetInt(interp, argv[5], &widthInc) != TCL_OK) - || (Tcl_GetInt(interp, argv[6], &heightInc) != TCL_OK)) { - return TCL_ERROR; - } - if (reqWidth < 0) { - Tcl_SetResult(interp, "baseWidth can't be < 0", TCL_STATIC); - return TCL_ERROR; - } - if (reqHeight < 0) { - Tcl_SetResult(interp, "baseHeight can't be < 0", TCL_STATIC); - return TCL_ERROR; - } - if (widthInc < 0) { - Tcl_SetResult(interp, "widthInc can't be < 0", TCL_STATIC); + Pixmap pixmap; + Tcl_ResetResult(interp); + pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr, string); + if (pixmap == None) { return TCL_ERROR; } - if (heightInc < 0) { - Tcl_SetResult(interp, "heightInc can't be < 0", TCL_STATIC); - return TCL_ERROR; + wmPtr->hints.icon_pixmap = pixmap; + wmPtr->hints.flags |= IconPixmapHint; + titlebaricon = GetIconFromPixmap(Tk_Display(winPtr), pixmap); + if (titlebaricon != NULL) { + if (WinSetIcon(interp, titlebaricon, + (isDefault ? NULL : (Tk_Window) winPtr)) != TCL_OK) { + /* We didn't use the titlebaricon after all */ + DecrIconRefCount(titlebaricon); + titlebaricon = NULL; + } } - Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc, - heightInc); } - goto updateGeom; - } else if ((c == 'g') && (strncmp(argv[1], "group", length) == 0) - && (length >= 3)) { - Tk_Window tkwin2; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconifyCmd -- + * + * This procedure is invoked to process the "wm iconify" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " group window ?pathName?\"", - (char *) NULL); - return TCL_ERROR; +static int +WmIconifyCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) { + Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName, + "\": override-redirect flag is set", (char *) NULL); + return TCL_ERROR; + } + if (wmPtr->masterPtr != NULL) { + Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName, + "\": it is a transient", (char *) NULL); + return TCL_ERROR; + } + if (wmPtr->iconFor != NULL) { + Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName, + ": it is an icon for ", Tk_PathName(wmPtr->iconFor), + (char *) NULL); + return TCL_ERROR; + } + if (winPtr->flags & TK_EMBEDDED) { + Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName, + ": it is an embedded window", (char *) NULL); + return TCL_ERROR; + } + TkpWmSetState(winPtr, IconicState); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconmaskCmd -- + * + * This procedure is invoked to process the "wm iconmask" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconmaskCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Pixmap pixmap; + char *argv3; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->hints.flags & IconMaskHint) { + Tcl_SetResult(interp, (char *) + Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_mask), + TCL_STATIC); } - if (argc == 3) { - if (wmPtr->hints.flags & WindowGroupHint) { - Tcl_SetResult(interp, wmPtr->leaderName, TCL_STATIC); - } - return TCL_OK; + return TCL_OK; + } + argv3 = Tcl_GetString(objv[3]); + if (*argv3 == '\0') { + if (wmPtr->hints.icon_mask != None) { + Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask); } - if (*argv[3] == '\0') { - wmPtr->hints.flags &= ~WindowGroupHint; - if (wmPtr->leaderName != NULL) { - ckfree(wmPtr->leaderName); - } - wmPtr->leaderName = NULL; - } else { - tkwin2 = Tk_NameToWindow(interp, argv[3], tkwin); - if (tkwin2 == NULL) { - return TCL_ERROR; - } - Tk_MakeWindowExist(tkwin2); - wmPtr->hints.window_group = Tk_WindowId(tkwin2); - wmPtr->hints.flags |= WindowGroupHint; - wmPtr->leaderName = ckalloc((unsigned) (strlen(argv[3])+1)); - strcpy(wmPtr->leaderName, argv[3]); - } - } else if ((c == 'i') && (strncmp(argv[1], "iconbitmap", length) == 0) - && (length >= 5)) { - Pixmap pixmap; - - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " iconbitmap window ?bitmap?\"", - (char *) NULL); + wmPtr->hints.flags &= ~IconMaskHint; + } else { + pixmap = Tk_GetBitmap(interp, tkwin, argv3); + if (pixmap == None) { return TCL_ERROR; } - if (argc == 3) { - if (wmPtr->hints.flags & IconPixmapHint) { - Tcl_SetResult(interp, - Tk_NameOfBitmap(winPtr->display, - wmPtr->hints.icon_pixmap), TCL_STATIC); - } - return TCL_OK; + wmPtr->hints.icon_mask = pixmap; + wmPtr->hints.flags |= IconMaskHint; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconnameCmd -- + * + * This procedure is invoked to process the "wm iconname" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconnameCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + char *argv3; + int length; + + if (objc > 4) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?newName?"); + return TCL_ERROR; + } + if (objc == 3) { + Tcl_SetResult(interp, + ((wmPtr->iconName != NULL) ? wmPtr->iconName : ""), + TCL_STATIC); + return TCL_OK; + } else { + if (wmPtr->iconName != NULL) { + ckfree((char *) wmPtr->iconName); } - if (*argv[3] == '\0') { - if (wmPtr->hints.icon_pixmap != None) { - Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap); - } - wmPtr->hints.flags &= ~IconPixmapHint; - } else { - pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr, - Tk_GetUid(argv[3])); - if (pixmap == None) { - return TCL_ERROR; - } - wmPtr->hints.icon_pixmap = pixmap; - wmPtr->hints.flags |= IconPixmapHint; + argv3 = Tcl_GetStringFromObj(objv[3], &length); + wmPtr->iconName = ckalloc((unsigned) (length + 1)); + strcpy(wmPtr->iconName, argv3); + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName); } - } else if ((c == 'i') && (strncmp(argv[1], "iconify", length) == 0) - && (length >= 5)) { - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " iconify window\"", (char *) NULL); - return TCL_ERROR; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconpositionCmd -- + * + * This procedure is invoked to process the "wm iconposition" + * Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconpositionCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int x, y; + + if ((objc != 3) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?x y?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->hints.flags & IconPositionHint) { + char buf[TCL_INTEGER_SPACE * 2]; + + sprintf(buf, "%d %d", wmPtr->hints.icon_x, + wmPtr->hints.icon_y); + Tcl_SetResult(interp, buf, TCL_VOLATILE); } - if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) { - Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName, - "\": override-redirect flag is set", (char *) NULL); + return TCL_OK; + } + if (*Tcl_GetString(objv[3]) == '\0') { + wmPtr->hints.flags &= ~IconPositionHint; + } else { + if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)){ return TCL_ERROR; } - if (wmPtr->masterPtr != NULL) { - Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName, - "\": it is a transient", (char *) NULL); + wmPtr->hints.icon_x = x; + wmPtr->hints.icon_y = y; + wmPtr->hints.flags |= IconPositionHint; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconwindowCmd -- + * + * This procedure is invoked to process the "wm iconwindow" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconwindowCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Tk_Window tkwin2; + WmInfo *wmPtr2; + XSetWindowAttributes atts; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->icon != NULL) { + Tcl_SetResult(interp, Tk_PathName(wmPtr->icon), TCL_STATIC); + } + return TCL_OK; + } + if (*Tcl_GetString(objv[3]) == '\0') { + wmPtr->hints.flags &= ~IconWindowHint; + if (wmPtr->icon != NULL) { + /* + * Let the window use button events again, then remove + * it as icon window. + */ + + atts.event_mask = Tk_Attributes(wmPtr->icon)->event_mask + | ButtonPressMask; + Tk_ChangeWindowAttributes(wmPtr->icon, CWEventMask, &atts); + wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr; + wmPtr2->iconFor = NULL; + wmPtr2->hints.initial_state = WithdrawnState; + } + wmPtr->icon = NULL; + } else { + if (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) { return TCL_ERROR; } - if (wmPtr->iconFor != NULL) { - Tcl_AppendResult(interp, "can't iconify ", argv[2], - ": it is an icon for ", winPtr->pathName, (char *) NULL); + if (!Tk_IsTopLevel(tkwin2)) { + Tcl_AppendResult(interp, "can't use ", Tcl_GetString(objv[3]), + " as icon window: not at top level", (char *) NULL); return TCL_ERROR; } - if (winPtr->flags & TK_EMBEDDED) { - Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName, - ": it is an embedded window", (char *) NULL); - return TCL_ERROR; - } - TkpWmSetState(winPtr, IconicState); - } else if ((c == 'i') && (strncmp(argv[1], "iconmask", length) == 0) - && (length >= 5)) { - Pixmap pixmap; - - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " iconmask window ?bitmap?\"", - (char *) NULL); + wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr; + if (wmPtr2->iconFor != NULL) { + Tcl_AppendResult(interp, Tcl_GetString(objv[3]), + " is already an icon for ", + Tk_PathName(wmPtr2->iconFor), (char *) NULL); return TCL_ERROR; } - if (argc == 3) { - if (wmPtr->hints.flags & IconMaskHint) { + if (wmPtr->icon != NULL) { + WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr; + wmPtr3->iconFor = NULL; + + /* + * Let the window use button events again. + */ + + atts.event_mask = Tk_Attributes(wmPtr->icon)->event_mask + | ButtonPressMask; + Tk_ChangeWindowAttributes(wmPtr->icon, CWEventMask, &atts); + } + + /* + * Disable button events in the icon window: some window + * managers (like olvwm) want to get the events themselves, + * but X only allows one application at a time to receive + * button events for a window. + */ + + atts.event_mask = Tk_Attributes(tkwin2)->event_mask + & ~ButtonPressMask; + Tk_ChangeWindowAttributes(tkwin2, CWEventMask, &atts); + Tk_MakeWindowExist(tkwin2); + wmPtr->hints.icon_window = Tk_WindowId(tkwin2); + wmPtr->hints.flags |= IconWindowHint; + wmPtr->icon = tkwin2; + wmPtr2->iconFor = (Tk_Window) winPtr; + if (!(wmPtr2->flags & WM_NEVER_MAPPED)) { + if (XWithdrawWindow(Tk_Display(tkwin2), Tk_WindowId(tkwin2), + Tk_ScreenNumber(tkwin2)) == 0) { Tcl_SetResult(interp, - Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_mask), + "couldn't send withdraw message to window manager", TCL_STATIC); - } - return TCL_OK; - } - if (*argv[3] == '\0') { - if (wmPtr->hints.icon_mask != None) { - Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask); - } - wmPtr->hints.flags &= ~IconMaskHint; - } else { - pixmap = Tk_GetBitmap(interp, tkwin, Tk_GetUid(argv[3])); - if (pixmap == None) { return TCL_ERROR; } - wmPtr->hints.icon_mask = pixmap; - wmPtr->hints.flags |= IconMaskHint; - } - } else if ((c == 'i') && (strncmp(argv[1], "iconname", length) == 0) - && (length >= 5)) { - if (argc > 4) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " iconname window ?newName?\"", (char *) NULL); - return TCL_ERROR; } - if (argc == 3) { - Tcl_SetResult(interp, - ((wmPtr->iconName != NULL) ? wmPtr->iconName : ""), - TCL_STATIC); - return TCL_OK; - } else { - wmPtr->iconName = Tk_GetUid(argv[3]); - if (!(wmPtr->flags & WM_NEVER_MAPPED)) { - XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName); - } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmMaxsizeCmd -- + * + * This procedure is invoked to process the "wm maxsize" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int width, height; + + if ((objc != 3) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?"); + return TCL_ERROR; + } + if (objc == 3) { + char buf[TCL_INTEGER_SPACE * 2]; + + GetMaxSize(wmPtr, &width, &height); + sprintf(buf, "%d %d", width, height); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + return TCL_OK; + } + if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) { + return TCL_ERROR; + } + wmPtr->maxWidth = width; + wmPtr->maxHeight = height; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmMinsizeCmd -- + * + * This procedure is invoked to process the "wm minsize" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmMinsizeCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int width, height; + + if ((objc != 3) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?"); + return TCL_ERROR; + } + if (objc == 3) { + char buf[TCL_INTEGER_SPACE * 2]; + + GetMinSize(wmPtr, &width, &height); + sprintf(buf, "%d %d", width, height); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + return TCL_OK; + } + if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) { + return TCL_ERROR; + } + wmPtr->minWidth = width; + wmPtr->minHeight = height; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmOverrideredirectCmd -- + * + * This procedure is invoked to process the "wm overrideredirect" + * Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmOverrideredirectCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int boolean, curValue; + XSetWindowAttributes atts; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?"); + return TCL_ERROR; + } + curValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect; + if (objc == 3) { + Tcl_SetBooleanObj(Tcl_GetObjResult(interp), curValue); + return TCL_OK; + } + if (Tcl_GetBooleanFromObj(interp, objv[3], &boolean) != TCL_OK) { + return TCL_ERROR; + } + if (curValue != boolean) { + /* + * Only do this if we are really changing value, because it + * causes some funky stuff to occur + */ + atts.override_redirect = (boolean) ? True : False; + Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, + &atts); + if (!(wmPtr->flags & (WM_NEVER_MAPPED) + && !(winPtr->flags & TK_EMBEDDED))) { + UpdateWrapper(winPtr); } - } else if ((c == 'i') && (strncmp(argv[1], "iconposition", length) == 0) - && (length >= 5)) { - int x, y; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmPositionfromCmd -- + * + * This procedure is invoked to process the "wm positionfrom" + * Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ - if ((argc != 3) && (argc != 5)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " iconposition window ?x y?\"", - (char *) NULL); - return TCL_ERROR; +static int +WmPositionfromCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + static CONST char *optionStrings[] = { + "program", "user", (char *) NULL }; + enum options { + OPT_PROGRAM, OPT_USER }; + int index; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?user/program?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->sizeHintsFlags & USPosition) { + Tcl_SetResult(interp, "user", TCL_STATIC); + } else if (wmPtr->sizeHintsFlags & PPosition) { + Tcl_SetResult(interp, "program", TCL_STATIC); } - if (argc == 3) { - if (wmPtr->hints.flags & IconPositionHint) { - char buf[TCL_INTEGER_SPACE * 2]; - - sprintf(buf, "%d %d", wmPtr->hints.icon_x, - wmPtr->hints.icon_y); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } - return TCL_OK; + return TCL_OK; + } + if (*Tcl_GetString(objv[3]) == '\0') { + wmPtr->sizeHintsFlags &= ~(USPosition|PPosition); + } else { + if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, + &index) != TCL_OK) { + return TCL_ERROR; } - if (*argv[3] == '\0') { - wmPtr->hints.flags &= ~IconPositionHint; + if (index == OPT_USER) { + wmPtr->sizeHintsFlags &= ~PPosition; + wmPtr->sizeHintsFlags |= USPosition; } else { - if ((Tcl_GetInt(interp, argv[3], &x) != TCL_OK) - || (Tcl_GetInt(interp, argv[4], &y) != TCL_OK)){ - return TCL_ERROR; - } - wmPtr->hints.icon_x = x; - wmPtr->hints.icon_y = y; - wmPtr->hints.flags |= IconPositionHint; - } - } else if ((c == 'i') && (strncmp(argv[1], "iconwindow", length) == 0) - && (length >= 5)) { - Tk_Window tkwin2; - WmInfo *wmPtr2; - XSetWindowAttributes atts; - - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " iconwindow window ?pathName?\"", - (char *) NULL); - return TCL_ERROR; + wmPtr->sizeHintsFlags &= ~USPosition; + wmPtr->sizeHintsFlags |= PPosition; + } + } + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmProtocolCmd -- + * + * This procedure is invoked to process the "wm protocol" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmProtocolCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + register ProtocolHandler *protPtr, *prevPtr; + Atom protocol; + char *cmd; + int cmdLength; + + if ((objc < 3) || (objc > 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?name? ?command?"); + return TCL_ERROR; + } + if (objc == 3) { + /* + * Return a list of all defined protocols for the window. + */ + for (protPtr = wmPtr->protPtr; protPtr != NULL; + protPtr = protPtr->nextPtr) { + Tcl_AppendElement(interp, + Tk_GetAtomName((Tk_Window) winPtr, protPtr->protocol)); } - if (argc == 3) { - if (wmPtr->icon != NULL) { - Tcl_SetResult(interp, Tk_PathName(wmPtr->icon), TCL_STATIC); + return TCL_OK; + } + protocol = Tk_InternAtom((Tk_Window) winPtr, Tcl_GetString(objv[3])); + if (objc == 4) { + /* + * Return the command to handle a given protocol. + */ + for (protPtr = wmPtr->protPtr; protPtr != NULL; + protPtr = protPtr->nextPtr) { + if (protPtr->protocol == protocol) { + Tcl_SetResult(interp, protPtr->command, TCL_STATIC); + return TCL_OK; } - return TCL_OK; } - if (*argv[3] == '\0') { - wmPtr->hints.flags &= ~IconWindowHint; - if (wmPtr->icon != NULL) { - /* - * Let the window use button events again, then remove - * it as icon window. - */ + return TCL_OK; + } - atts.event_mask = Tk_Attributes(wmPtr->icon)->event_mask - | ButtonPressMask; - Tk_ChangeWindowAttributes(wmPtr->icon, CWEventMask, &atts); - wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr; - wmPtr2->iconFor = NULL; - wmPtr2->hints.initial_state = WithdrawnState; - } - wmPtr->icon = NULL; - } else { - tkwin2 = Tk_NameToWindow(interp, argv[3], tkwin); - if (tkwin2 == NULL) { - return TCL_ERROR; - } - if (!Tk_IsTopLevel(tkwin2)) { - Tcl_AppendResult(interp, "can't use ", argv[3], - " as icon window: not at top level", (char *) NULL); - return TCL_ERROR; - } - wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr; - if (wmPtr2->iconFor != NULL) { - Tcl_AppendResult(interp, argv[3], " is already an icon for ", - Tk_PathName(wmPtr2->iconFor), (char *) NULL); - return TCL_ERROR; + /* + * Delete any current protocol handler, then create a new + * one with the specified command, unless the command is + * empty. + */ + + for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL; + prevPtr = protPtr, protPtr = protPtr->nextPtr) { + if (protPtr->protocol == protocol) { + if (prevPtr == NULL) { + wmPtr->protPtr = protPtr->nextPtr; + } else { + prevPtr->nextPtr = protPtr->nextPtr; } - if (wmPtr->icon != NULL) { - WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr; - wmPtr3->iconFor = NULL; + Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC); + break; + } + } + cmd = Tcl_GetStringFromObj(objv[4], &cmdLength); + if (cmdLength > 0) { + protPtr = (ProtocolHandler *) ckalloc(HANDLER_SIZE(cmdLength)); + protPtr->protocol = protocol; + protPtr->nextPtr = wmPtr->protPtr; + wmPtr->protPtr = protPtr; + protPtr->interp = interp; + strcpy(protPtr->command, cmd); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmResizableCmd -- + * + * This procedure is invoked to process the "wm resizable" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ - /* - * Let the window use button events again. - */ +static int +WmResizableCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int width, height; - atts.event_mask = Tk_Attributes(wmPtr->icon)->event_mask - | ButtonPressMask; - Tk_ChangeWindowAttributes(wmPtr->icon, CWEventMask, &atts); - } + if ((objc != 3) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?"); + return TCL_ERROR; + } + if (objc == 3) { + char buf[TCL_INTEGER_SPACE * 2]; - /* - * Disable button events in the icon window: some window - * managers (like olvwm) want to get the events themselves, - * but X only allows one application at a time to receive - * button events for a window. - */ + sprintf(buf, "%d %d", + (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) ? 0 : 1, + (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) ? 0 : 1); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + return TCL_OK; + } + if ((Tcl_GetBooleanFromObj(interp, objv[3], &width) != TCL_OK) + || (Tcl_GetBooleanFromObj(interp, objv[4], &height) != TCL_OK)) { + return TCL_ERROR; + } + if (width) { + wmPtr->flags &= ~WM_WIDTH_NOT_RESIZABLE; + } else { + wmPtr->flags |= WM_WIDTH_NOT_RESIZABLE; + } + if (height) { + wmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE; + } else { + wmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE; + } + if (!((wmPtr->flags & WM_NEVER_MAPPED) + && !(winPtr->flags & TK_EMBEDDED))) { + UpdateWrapper(winPtr); + } + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmSizefromCmd -- + * + * This procedure is invoked to process the "wm sizefrom" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ - atts.event_mask = Tk_Attributes(tkwin2)->event_mask - & ~ButtonPressMask; - Tk_ChangeWindowAttributes(tkwin2, CWEventMask, &atts); - Tk_MakeWindowExist(tkwin2); - wmPtr->hints.icon_window = Tk_WindowId(tkwin2); - wmPtr->hints.flags |= IconWindowHint; - wmPtr->icon = tkwin2; - wmPtr2->iconFor = (Tk_Window) winPtr; - if (!(wmPtr2->flags & WM_NEVER_MAPPED)) { - if (XWithdrawWindow(Tk_Display(tkwin2), Tk_WindowId(tkwin2), - Tk_ScreenNumber(tkwin2)) == 0) { - Tcl_SetResult(interp, - "couldn't send withdraw message to window manager", - TCL_STATIC); - return TCL_ERROR; - } - } - } - } else if ((c == 'm') && (strncmp(argv[1], "maxsize", length) == 0) - && (length >= 2)) { - int width, height; - if ((argc != 3) && (argc != 5)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " maxsize window ?width height?\"", - (char *) NULL); - return TCL_ERROR; - } - if (argc == 3) { - char buf[TCL_INTEGER_SPACE * 2]; - - GetMaxSize(wmPtr, &width, &height); - sprintf(buf, "%d %d", width, height); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - return TCL_OK; +static int +WmSizefromCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + static CONST char *optionStrings[] = { + "program", "user", (char *) NULL }; + enum options { + OPT_PROGRAM, OPT_USER }; + int index; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?user|program?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->sizeHintsFlags & USSize) { + Tcl_SetResult(interp, "user", TCL_STATIC); + } else if (wmPtr->sizeHintsFlags & PSize) { + Tcl_SetResult(interp, "program", TCL_STATIC); } - if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK) - || (Tcl_GetInt(interp, argv[4], &height) != TCL_OK)) { + return TCL_OK; + } + + if (*Tcl_GetString(objv[3]) == '\0') { + wmPtr->sizeHintsFlags &= ~(USSize|PSize); + } else { + if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, + &index) != TCL_OK) { return TCL_ERROR; } - wmPtr->maxWidth = width; - wmPtr->maxHeight = height; - goto updateGeom; - } else if ((c == 'm') && (strncmp(argv[1], "minsize", length) == 0) - && (length >= 2)) { - int width, height; - if ((argc != 3) && (argc != 5)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " minsize window ?width height?\"", - (char *) NULL); - return TCL_ERROR; + if (index == OPT_USER) { + wmPtr->sizeHintsFlags &= ~PSize; + wmPtr->sizeHintsFlags |= USSize; + } else { /* OPT_PROGRAM */ + wmPtr->sizeHintsFlags &= ~USSize; + wmPtr->sizeHintsFlags |= PSize; } - if (argc == 3) { - char buf[TCL_INTEGER_SPACE * 2]; - - GetMinSize(wmPtr, &width, &height); - sprintf(buf, "%d %d", width, height); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + } + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmStackorderCmd -- + * + * This procedure is invoked to process the "wm stackorder" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmStackorderCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + TkWindow **windows, **window_ptr; + static CONST char *optionStrings[] = { + "isabove", "isbelow", (char *) NULL }; + enum options { + OPT_ISABOVE, OPT_ISBELOW }; + int index; + + if ((objc != 3) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?isabove|isbelow window?"); + return TCL_ERROR; + } + + if (objc == 3) { + windows = TkWmStackorderToplevel(winPtr); + if (windows == NULL) { + panic("TkWmStackorderToplevel failed"); + } else { + for (window_ptr = windows; *window_ptr ; window_ptr++) { + Tcl_AppendElement(interp, (*window_ptr)->pathName); + } + ckfree((char *) windows); return TCL_OK; } - if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK) - || (Tcl_GetInt(interp, argv[4], &height) != TCL_OK)) { - return TCL_ERROR; - } - wmPtr->minWidth = width; - wmPtr->minHeight = height; - goto updateGeom; - } else if ((c == 'o') - && (strncmp(argv[1], "overrideredirect", length) == 0)) { - int boolean, curValue; - XSetWindowAttributes atts; - - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " overrideredirect window ?boolean?\"", - (char *) NULL); + } else { + TkWindow *winPtr2; + int index1=-1, index2=-1, result; + + if (TkGetWindowFromObj(interp, tkwin, objv[4], (Tk_Window *) &winPtr2) + != TCL_OK) { return TCL_ERROR; } - curValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect; - if (argc == 3) { - Tcl_SetBooleanObj(Tcl_GetObjResult(interp), curValue); - return TCL_OK; - } - if (Tcl_GetBoolean(interp, argv[3], &boolean) != TCL_OK) { + + if (!Tk_IsTopLevel(winPtr2)) { + Tcl_AppendResult(interp, "window \"", winPtr2->pathName, + "\" isn't a top-level window", (char *) NULL); return TCL_ERROR; } - if (curValue != boolean) { - /* - * Only do this if we are really changing value, because it - * causes some funky stuff to occur - */ - atts.override_redirect = (boolean) ? True : False; - Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, - &atts); - if (!(wmPtr->flags & (WM_NEVER_MAPPED) - && !(winPtr->flags & TK_EMBEDDED))) { - UpdateWrapper(winPtr); - } - } - } else if ((c == 'p') && (strncmp(argv[1], "positionfrom", length) == 0) - && (length >= 2)) { - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " positionfrom window ?user/program?\"", - (char *) NULL); + + if (!Tk_IsMapped(winPtr)) { + Tcl_AppendResult(interp, "window \"", winPtr->pathName, + "\" isn't mapped", (char *) NULL); return TCL_ERROR; } - if (argc == 3) { - if (wmPtr->sizeHintsFlags & USPosition) { - Tcl_SetResult(interp, "user", TCL_STATIC); - } else if (wmPtr->sizeHintsFlags & PPosition) { - Tcl_SetResult(interp, "program", TCL_STATIC); - } - return TCL_OK; - } - if (*argv[3] == '\0') { - wmPtr->sizeHintsFlags &= ~(USPosition|PPosition); - } else { - c = argv[3][0]; - length = strlen(argv[3]); - if ((c == 'u') && (strncmp(argv[3], "user", length) == 0)) { - wmPtr->sizeHintsFlags &= ~PPosition; - wmPtr->sizeHintsFlags |= USPosition; - } else if ((c == 'p') - && (strncmp(argv[3], "program", length) == 0)) { - wmPtr->sizeHintsFlags &= ~USPosition; - wmPtr->sizeHintsFlags |= PPosition; - } else { - Tcl_AppendResult(interp, "bad argument \"", argv[3], - "\": must be program or user", (char *) NULL); - return TCL_ERROR; - } - } - goto updateGeom; - } else if ((c == 'p') && (strncmp(argv[1], "protocol", length) == 0) - && (length >= 2)) { - register ProtocolHandler *protPtr, *prevPtr; - Atom protocol; - int cmdLength; - if ((argc < 3) || (argc > 5)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " protocol window ?name? ?command?\"", - (char *) NULL); + if (!Tk_IsMapped(winPtr2)) { + Tcl_AppendResult(interp, "window \"", winPtr2->pathName, + "\" isn't mapped", (char *) NULL); return TCL_ERROR; } - if (argc == 3) { - /* - * Return a list of all defined protocols for the window. - */ - for (protPtr = wmPtr->protPtr; protPtr != NULL; - protPtr = protPtr->nextPtr) { - Tcl_AppendElement(interp, - Tk_GetAtomName((Tk_Window) winPtr, protPtr->protocol)); - } - return TCL_OK; - } - protocol = Tk_InternAtom((Tk_Window) winPtr, argv[3]); - if (argc == 4) { - /* - * Return the command to handle a given protocol. - */ - for (protPtr = wmPtr->protPtr; protPtr != NULL; - protPtr = protPtr->nextPtr) { - if (protPtr->protocol == protocol) { - Tcl_SetResult(interp, protPtr->command, TCL_STATIC); - return TCL_OK; - } - } - return TCL_OK; - } /* - * Delete any current protocol handler, then create a new - * one with the specified command, unless the command is - * empty. + * Lookup stacking order of all toplevels that are children + * of "." and find the position of winPtr and winPtr2 + * in the stacking order. */ - for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL; - prevPtr = protPtr, protPtr = protPtr->nextPtr) { - if (protPtr->protocol == protocol) { - if (prevPtr == NULL) { - wmPtr->protPtr = protPtr->nextPtr; - } else { - prevPtr->nextPtr = protPtr->nextPtr; - } - Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC); - break; + windows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr); + + if (windows == NULL) { + Tcl_AppendResult(interp, "TkWmStackorderToplevel failed", + (char *) NULL); + return TCL_ERROR; + } else { + for (window_ptr = windows; *window_ptr ; window_ptr++) { + if (*window_ptr == winPtr) + index1 = (window_ptr - windows); + if (*window_ptr == winPtr2) + index2 = (window_ptr - windows); } + if (index1 == -1) + panic("winPtr window not found"); + if (index2 == -1) + panic("winPtr2 window not found"); + + ckfree((char *) windows); } - cmdLength = strlen(argv[4]); - if (cmdLength > 0) { - protPtr = (ProtocolHandler *) ckalloc(HANDLER_SIZE(cmdLength)); - protPtr->protocol = protocol; - protPtr->nextPtr = wmPtr->protPtr; - wmPtr->protPtr = protPtr; - protPtr->interp = interp; - strcpy(protPtr->command, argv[4]); - } - } else if ((c == 'r') && (strncmp(argv[1], "resizable", length) == 0)) { - int width, height; - if ((argc != 3) && (argc != 5)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " resizable window ?width height?\"", - (char *) NULL); + if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, + &index) != TCL_OK) { return TCL_ERROR; } - if (argc == 3) { - char buf[TCL_INTEGER_SPACE * 2]; - - sprintf(buf, "%d %d", - (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) ? 0 : 1, - (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) ? 0 : 1); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - return TCL_OK; + if (index == OPT_ISABOVE) { + result = index1 > index2; + } else { /* OPT_ISBELOW */ + result = index1 < index2; } - if ((Tcl_GetBoolean(interp, argv[3], &width) != TCL_OK) - || (Tcl_GetBoolean(interp, argv[4], &height) != TCL_OK)) { + Tcl_SetIntObj(Tcl_GetObjResult(interp), result); + return TCL_OK; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmStateCmd -- + * + * This procedure is invoked to process the "wm state" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmStateCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + static CONST char *optionStrings[] = { + "normal", "iconic", "withdrawn", "zoomed", (char *) NULL }; + enum options { + OPT_NORMAL, OPT_ICONIC, OPT_WITHDRAWN, OPT_ZOOMED }; + int index; + + if ((objc < 3) || (objc > 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?state?"); + return TCL_ERROR; + } + if (objc == 4) { + if (wmPtr->iconFor != NULL) { + Tcl_AppendResult(interp, "can't change state of ", + Tcl_GetString(objv[2]), + ": it is an icon for ", Tk_PathName(wmPtr->iconFor), + (char *) NULL); return TCL_ERROR; } - if (width) { - wmPtr->flags &= ~WM_WIDTH_NOT_RESIZABLE; - } else { - wmPtr->flags |= WM_WIDTH_NOT_RESIZABLE; - } - if (height) { - wmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE; - } else { - wmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE; - } - if (!((wmPtr->flags & WM_NEVER_MAPPED) - && !(winPtr->flags & TK_EMBEDDED))) { - UpdateWrapper(winPtr); - } - goto updateGeom; - } else if ((c == 's') && (strncmp(argv[1], "sizefrom", length) == 0) - && (length >= 2)) { - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " sizefrom window ?user|program?\"", + if (winPtr->flags & TK_EMBEDDED) { + Tcl_AppendResult(interp, "can't change state of ", + winPtr->pathName, ": it is an embedded window", (char *) NULL); return TCL_ERROR; } - if (argc == 3) { - if (wmPtr->sizeHintsFlags & USSize) { - Tcl_SetResult(interp, "user", TCL_STATIC); - } else if (wmPtr->sizeHintsFlags & PSize) { - Tcl_SetResult(interp, "program", TCL_STATIC); - } - return TCL_OK; - } - if (*argv[3] == '\0') { - wmPtr->sizeHintsFlags &= ~(USSize|PSize); - } else { - c = argv[3][0]; - length = strlen(argv[3]); - if ((c == 'u') && (strncmp(argv[3], "user", length) == 0)) { - wmPtr->sizeHintsFlags &= ~PSize; - wmPtr->sizeHintsFlags |= USSize; - } else if ((c == 'p') - && (strncmp(argv[3], "program", length) == 0)) { - wmPtr->sizeHintsFlags &= ~USSize; - wmPtr->sizeHintsFlags |= PSize; - } else { - Tcl_AppendResult(interp, "bad argument \"", argv[3], - "\": must be program or user", (char *) NULL); - return TCL_ERROR; - } - } - goto updateGeom; - } else if ((c == 's') && (strncmp(argv[1], "state", length) == 0) - && (length >= 2)) { - if ((argc < 3) || (argc > 4)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " state window ?state?\"", (char *) NULL); + + if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, + &index) != TCL_OK) { return TCL_ERROR; } - if (argc == 4) { - if (wmPtr->iconFor != NULL) { - Tcl_AppendResult(interp, "can't change state of ", argv[2], - ": it is an icon for ", Tk_PathName(wmPtr->iconFor), - (char *) NULL); - return TCL_ERROR; + + if (index == OPT_NORMAL) { + if (wmPtr->flags & WM_TRANSIENT_WITHDRAWN) { + wmPtr->flags &= ~WM_TRANSIENT_WITHDRAWN; } - if (winPtr->flags & TK_EMBEDDED) { - Tcl_AppendResult(interp, "can't change state of ", - winPtr->pathName, ": it is an embedded window", + TkpWmSetState(winPtr, NormalState); + /* + * This varies from 'wm deiconify' because it does not + * force the window to be raised and receive focus + */ + } else if (index == OPT_ICONIC) { + if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) { + Tcl_AppendResult(interp, "can't iconify \"", + winPtr->pathName, + "\": override-redirect flag is set", (char *) NULL); return TCL_ERROR; } - - c = argv[3][0]; - length = strlen(argv[3]); - - if ((c == 'n') && (strncmp(argv[3], "normal", length) == 0)) { - TkpWmSetState(winPtr, NormalState); - /* - * This varies from 'wm deiconify' because it does not - * force the window to be raised and receive focus - */ - } else if ((c == 'i') - && (strncmp(argv[3], "iconic", length) == 0)) { - if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) { - Tcl_AppendResult(interp, "can't iconify \"", - winPtr->pathName, - "\": override-redirect flag is set", - (char *) NULL); - return TCL_ERROR; - } - if (wmPtr->masterPtr != NULL) { - Tcl_AppendResult(interp, "can't iconify \"", - winPtr->pathName, - "\": it is a transient", (char *) NULL); - return TCL_ERROR; - } - TkpWmSetState(winPtr, IconicState); - } else if ((c == 'w') - && (strncmp(argv[3], "withdrawn", length) == 0)) { - TkpWmSetState(winPtr, WithdrawnState); - } else if ((c == 'z') - && (strncmp(argv[3], "zoomed", length) == 0)) { - TkpWmSetState(winPtr, ZoomState); - } else { - Tcl_AppendResult(interp, "bad argument \"", argv[3], - "\": must be normal, iconic, withdrawn or zoomed", - (char *) NULL); + if (wmPtr->masterPtr != NULL) { + Tcl_AppendResult(interp, "can't iconify \"", + winPtr->pathName, + "\": it is a transient", (char *) NULL); return TCL_ERROR; } - } else { - if (wmPtr->iconFor != NULL) { - Tcl_SetResult(interp, "icon", TCL_STATIC); - } else { - switch (wmPtr->hints.initial_state) { - case NormalState: - Tcl_SetResult(interp, "normal", TCL_STATIC); - break; - case IconicState: - Tcl_SetResult(interp, "iconic", TCL_STATIC); - break; - case WithdrawnState: - Tcl_SetResult(interp, "withdrawn", TCL_STATIC); - break; - case ZoomState: - Tcl_SetResult(interp, "zoomed", TCL_STATIC); - break; - } + TkpWmSetState(winPtr, IconicState); + } else if (index == OPT_WITHDRAWN) { + if (wmPtr->masterPtr != NULL) { + wmPtr->flags |= WM_TRANSIENT_WITHDRAWN; } + TkpWmSetState(winPtr, WithdrawnState); + } else { /* OPT_ZOOMED */ + TkpWmSetState(winPtr, ZoomState); } - } else if ((c == 't') && (strncmp(argv[1], "title", length) == 0) - && (length >= 2)) { - if (argc > 4) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " title window ?newTitle?\"", (char *) NULL); - return TCL_ERROR; - } - if (argc == 3) { - Tcl_SetResult(interp, ((wmPtr->titleUid != NULL) ? - wmPtr->titleUid : winPtr->nameUid), TCL_STATIC); - return TCL_OK; + } else { + if (wmPtr->iconFor != NULL) { + Tcl_SetResult(interp, "icon", TCL_STATIC); } else { - wmPtr->titleUid = Tk_GetUid(argv[3]); - if (!(wmPtr->flags & WM_NEVER_MAPPED) && wmPtr->wrapper != NULL) { - Tcl_DString titleString; - Tcl_UtfToExternalDString(NULL, wmPtr->titleUid, -1, - &titleString); - SetWindowText(wmPtr->wrapper, Tcl_DStringValue(&titleString)); - Tcl_DStringFree(&titleString); + switch (wmPtr->hints.initial_state) { + case NormalState: + Tcl_SetResult(interp, "normal", TCL_STATIC); + break; + case IconicState: + Tcl_SetResult(interp, "iconic", TCL_STATIC); + break; + case WithdrawnState: + Tcl_SetResult(interp, "withdrawn", TCL_STATIC); + break; + case ZoomState: + Tcl_SetResult(interp, "zoomed", TCL_STATIC); + break; } } - } else if ((c == 't') && (strncmp(argv[1], "transient", length) == 0) - && (length >= 3)) { - TkWindow *masterPtr = wmPtr->masterPtr; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmTitleCmd -- + * + * This procedure is invoked to process the "wm title" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " transient window ?master?\"", (char *) NULL); - return TCL_ERROR; +static int +WmTitleCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + char *argv3; + int length; + + if (objc > 4) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?newTitle?"); + return TCL_ERROR; + } + if (objc == 3) { + Tcl_SetResult(interp, (char *) + ((wmPtr->title != NULL) ? wmPtr->title : winPtr->nameUid), + TCL_STATIC); + return TCL_OK; + } else { + if (wmPtr->title != NULL) { + ckfree((char *) wmPtr->title); } - if (argc == 3) { - if (masterPtr != NULL) { - Tcl_SetResult(interp, Tk_PathName(masterPtr), TCL_STATIC); - } - return TCL_OK; + argv3 = Tcl_GetStringFromObj(objv[3], &length); + wmPtr->title = ckalloc((unsigned) (length + 1)); + strcpy(wmPtr->title, argv3); + + if (!(wmPtr->flags & WM_NEVER_MAPPED) && wmPtr->wrapper != NULL) { + Tcl_DString titleString; + Tcl_WinUtfToTChar(wmPtr->title, -1, &titleString); + (*tkWinProcs->setWindowText)(wmPtr->wrapper, + (LPCTSTR) Tcl_DStringValue(&titleString)); + Tcl_DStringFree(&titleString); } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmTransientCmd -- + * + * This procedure is invoked to process the "wm transient" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmTransientCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + TkWindow *masterPtr = wmPtr->masterPtr; + WmInfo *wmPtr2; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?master?"); + return TCL_ERROR; + } + if (objc == 3) { + if (masterPtr != NULL) { + Tcl_SetResult(interp, Tk_PathName(masterPtr), TCL_STATIC); + } + return TCL_OK; + } + if (Tcl_GetString(objv[3])[0] == '\0') { if (masterPtr != NULL) { /* * If we had a master, tell them that we aren't tied * to them anymore */ + masterPtr->wmInfoPtr->numTransients--; Tk_DeleteEventHandler((Tk_Window) masterPtr, - VisibilityChangeMask, - WmWaitVisibilityProc, (ClientData) winPtr); + VisibilityChangeMask|StructureNotifyMask, + WmWaitVisibilityOrMapProc, (ClientData) winPtr); } - if (argv[3][0] == '\0') { - wmPtr->masterPtr = NULL; - } else { - masterPtr = (TkWindow*) Tk_NameToWindow(interp, argv[3], tkwin); - if (masterPtr == NULL) { - return TCL_ERROR; - } - if (masterPtr == winPtr) { - wmPtr->masterPtr = NULL; - } else if (masterPtr != wmPtr->masterPtr) { - Tk_MakeWindowExist((Tk_Window)masterPtr); - /* - * Ensure that the master window is actually a Tk toplevel. - */ - - while (!(masterPtr->flags & TK_TOP_LEVEL)) { - masterPtr = masterPtr->parentPtr; - } - wmPtr->masterPtr = masterPtr; - masterPtr->wmInfoPtr->numTransients++; - - /* - * Bind a visibility event handler to the master window, - * to ensure that when it is mapped, the children will - * have their state set properly. - */ + wmPtr->masterPtr = NULL; + } else { + if (TkGetWindowFromObj(interp, tkwin, objv[3], + (Tk_Window *) &masterPtr) != TCL_OK) { + return TCL_ERROR; + } + while (!Tk_TopWinHierarchy(masterPtr)) { + /* + * Ensure that the master window is actually a Tk toplevel. + */ - Tk_CreateEventHandler((Tk_Window) masterPtr, - VisibilityChangeMask, - WmWaitVisibilityProc, (ClientData) winPtr); - } + masterPtr = masterPtr->parentPtr; } - if (!((wmPtr->flags & WM_NEVER_MAPPED) - && !(winPtr->flags & TK_EMBEDDED))) { - UpdateWrapper(winPtr); + Tk_MakeWindowExist((Tk_Window) masterPtr); + + if (wmPtr->iconFor != NULL) { + Tcl_AppendResult(interp, "can't make \"", + Tcl_GetString(objv[2]), + "\" a transient: it is an icon for ", + Tk_PathName(wmPtr->iconFor), + (char *) NULL); + return TCL_ERROR; } - } else if ((c == 'w') && (strncmp(argv[1], "withdraw", length) == 0)) { - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # arguments: must be \"", - argv[0], " withdraw window\"", (char *) NULL); + + wmPtr2 = masterPtr->wmInfoPtr; + + if (wmPtr2->iconFor != NULL) { + Tcl_AppendResult(interp, "can't make \"", + Tcl_GetString(objv[3]), + "\" a master: it is an icon for ", + Tk_PathName(wmPtr2->iconFor), + (char *) NULL); return TCL_ERROR; } - if (wmPtr->iconFor != NULL) { - Tcl_AppendResult(interp, "can't withdraw ", argv[2], - ": it is an icon for ", Tk_PathName(wmPtr->iconFor), + + if (masterPtr == winPtr) { + Tcl_AppendResult(interp, "can't make \"", Tk_PathName(winPtr), + "\" its own master", (char *) NULL); return TCL_ERROR; + } else if (masterPtr != wmPtr->masterPtr) { + /* + * Remove old master map/unmap binding before setting + * the new master. The event handler will ensure that + * transient states reflect the state of the master. + */ + + if (wmPtr->masterPtr != NULL) { + wmPtr->masterPtr->wmInfoPtr->numTransients--; + Tk_DeleteEventHandler((Tk_Window) wmPtr->masterPtr, + VisibilityChangeMask|StructureNotifyMask, + WmWaitVisibilityOrMapProc, (ClientData) winPtr); + } + + masterPtr->wmInfoPtr->numTransients++; + Tk_CreateEventHandler((Tk_Window) masterPtr, + VisibilityChangeMask|StructureNotifyMask, + WmWaitVisibilityOrMapProc, (ClientData) winPtr); + + wmPtr->masterPtr = masterPtr; } - TkpWmSetState(winPtr, WithdrawnState); - } else { - Tcl_AppendResult(interp, "unknown or ambiguous option \"", argv[1], - "\": must be aspect, client, command, deiconify, ", - "focusmodel, frame, geometry, grid, group, iconbitmap, ", - "iconify, iconmask, iconname, iconposition, ", - "iconwindow, maxsize, minsize, overrideredirect, ", - "positionfrom, protocol, resizable, sizefrom, state, title, ", - "transient, or withdraw", + } + if (!((wmPtr->flags & WM_NEVER_MAPPED) + && !(winPtr->flags & TK_EMBEDDED))) { + if (wmPtr->masterPtr != NULL && + !Tk_IsMapped(wmPtr->masterPtr)) { + TkpWmSetState(winPtr, WithdrawnState); + } else { + UpdateWrapper(winPtr); + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmWithdrawCmd -- + * + * This procedure is invoked to process the "wm withdraw" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmWithdrawCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + if (wmPtr->iconFor != NULL) { + Tcl_AppendResult(interp, "can't withdraw ", Tcl_GetString(objv[2]), + ": it is an icon for ", Tk_PathName(wmPtr->iconFor), (char *) NULL); return TCL_ERROR; } + if (wmPtr->masterPtr != NULL) { + wmPtr->flags |= WM_TRANSIENT_WITHDRAWN; + } + TkpWmSetState(winPtr, WithdrawnState); return TCL_OK; +} - updateGeom: +/* + * Invoked by those wm subcommands that affect geometry. + * Schedules a geometry update. + */ +static void +WmUpdateGeom(wmPtr, winPtr) + WmInfo *wmPtr; + TkWindow *winPtr; +{ if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr); wmPtr->flags |= WM_UPDATE_PENDING; } - return TCL_OK; } + /*ARGSUSED*/ static void -WmWaitVisibilityProc(clientData, eventPtr) +WmWaitVisibilityOrMapProc(clientData, eventPtr) ClientData clientData; /* Pointer to window. */ XEvent *eventPtr; /* Information about event. */ { TkWindow *winPtr = (TkWindow *) clientData; TkWindow *masterPtr = winPtr->wmInfoPtr->masterPtr; - if ((eventPtr->type == VisibilityNotify) && (masterPtr != NULL)) { + if (masterPtr == NULL) + return; + + if (eventPtr->type == MapNotify) { + if (!(winPtr->wmInfoPtr->flags & WM_TRANSIENT_WITHDRAWN)) + TkpWmSetState(winPtr, NormalState); + } else if (eventPtr->type == UnmapNotify) { + TkpWmSetState(winPtr, WithdrawnState); + } + + if (eventPtr->type == VisibilityNotify) { int state = masterPtr->wmInfoPtr->hints.initial_state; if ((state == NormalState) || (state == ZoomState)) { @@ -2391,10 +4784,13 @@ Tk_SetGrid(tkwin, reqWidth, reqHeight, widthInc, heightInc) * information. */ - while (!(winPtr->flags & TK_TOP_LEVEL)) { + while (!(winPtr->flags & TK_TOP_HIERARCHY)) { winPtr = winPtr->parentPtr; } wmPtr = winPtr->wmInfoPtr; + if (wmPtr == NULL) { + return; + } if ((wmPtr->gridWin != NULL) && (wmPtr->gridWin != tkwin)) { return; @@ -2426,7 +4822,7 @@ Tk_SetGrid(tkwin, reqWidth, reqHeight, widthInc, heightInc) wmPtr->height = -1; } - /* + /* * Set the new gridding information, and start the process of passing * all of this information to the window manager. */ @@ -2475,10 +4871,14 @@ Tk_UnsetGrid(tkwin) * information. */ - while (!(winPtr->flags & TK_TOP_LEVEL)) { + while (!(winPtr->flags & TK_TOP_HIERARCHY)) { winPtr = winPtr->parentPtr; } wmPtr = winPtr->wmInfoPtr; + if (wmPtr == NULL) { + return; + } + if (tkwin != wmPtr->gridWin) { return; } @@ -2536,7 +4936,7 @@ TopLevelEventProc(clientData, eventPtr) * Tk_DestroyWindow will try to destroy the window, but of course * it's already gone. */ - + handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1, (Tk_ErrorProc *) NULL, (ClientData) NULL); Tk_DestroyWindow((Tk_Window) winPtr); @@ -2583,7 +4983,7 @@ TopLevelReqProc(dummy, tkwin) WmInfo *wmPtr; wmPtr = winPtr->wmInfoPtr; - if (winPtr->flags & TK_EMBEDDED) { + if ((winPtr->flags & TK_EMBEDDED) && (wmPtr->wrapper != NULL)) { SendMessage(wmPtr->wrapper, TK_GEOMETRYREQ, Tk_ReqWidth(tkwin), Tk_ReqHeight(tkwin)); } @@ -2741,7 +5141,7 @@ UpdateGeometryInfo(clientData) wmPtr->configWidth = width; wmPtr->configHeight = height; - + /* * Don't bother moving the window if we are in the process of * creating it. Just update the geometry info based on what @@ -2808,7 +5208,7 @@ UpdateGeometryInfo(clientData) GetClientRect(wmPtr->wrapper, &windowRect); newHeight = windowRect.bottom - windowRect.top; - + if (newHeight == height) { /* * We're done. @@ -3209,7 +5609,7 @@ TkWmProtocolEventProc(winPtr, eventPtr) * Cache atom name, as we might destroy the window as a * result of the eval. */ - char *name = Tk_GetAtomName((Tk_Window) winPtr, protocol); + CONST char *name = Tk_GetAtomName((Tk_Window) winPtr, protocol); Tcl_Preserve((ClientData) protPtr); interp = protPtr->interp; @@ -3240,6 +5640,173 @@ TkWmProtocolEventProc(winPtr, eventPtr) /* *---------------------------------------------------------------------- * + * TkWmStackorderToplevelEnumProc -- + * + * This procedure is invoked once for each HWND Window on the + * display as a result of calling EnumWindows from + * TkWmStackorderToplevel. + * + * Results: + * TRUE to request further iteration. + * + * Side effects: + * Adds entries to the passed array of TkWindows. + * + *---------------------------------------------------------------------- + */ + +BOOL CALLBACK TkWmStackorderToplevelEnumProc(hwnd, lParam) + HWND hwnd; /* handle to parent window */ + LPARAM lParam; /* application-defined value */ +{ + Tcl_HashEntry *hPtr; + TkWindow *childWinPtr; + + TkWmStackorderToplevelPair *pair = + (TkWmStackorderToplevelPair *) lParam; + + /*fprintf(stderr, "Looking up HWND %d\n", hwnd);*/ + + hPtr = Tcl_FindHashEntry(pair->table, (char *) hwnd); + if (hPtr != NULL) { + childWinPtr = (TkWindow *) Tcl_GetHashValue(hPtr); + /* Double check that same HWND does not get passed twice */ + if (childWinPtr == NULL) { + panic("duplicate HWND in TkWmStackorderToplevelEnumProc"); + } else { + Tcl_SetHashValue(hPtr, NULL); + } + /*fprintf(stderr, "Found mapped HWND %d -> %x (%s)\n", hwnd, + childWinPtr, childWinPtr->pathName);*/ + *(pair->window_ptr)-- = childWinPtr; + } + return TRUE; +} + +/* + *---------------------------------------------------------------------- + * + * TkWmStackorderToplevelWrapperMap -- + * + * This procedure will create a table that maps the wrapper + * HWND id for a toplevel to the TkWindow structure that is wraps. + * + * Results: + * None. + * + * Side effects: + * Adds entries to the passed hashtable. + * + *---------------------------------------------------------------------- + */ + +static void +TkWmStackorderToplevelWrapperMap(winPtr, table) + TkWindow *winPtr; /* TkWindow to recurse on */ + Tcl_HashTable *table; /* Table to maps HWND to TkWindow */ +{ + TkWindow *childPtr; + Tcl_HashEntry *hPtr; + HWND wrapper; + int newEntry; + + if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr) && + !Tk_IsEmbedded(winPtr)) { + wrapper = TkWinGetWrapperWindow((Tk_Window) winPtr); + + /*fprintf(stderr, "Mapped HWND %d to %x (%s)\n", wrapper, + winPtr, winPtr->pathName);*/ + + hPtr = Tcl_CreateHashEntry(table, + (char *) wrapper, &newEntry); + Tcl_SetHashValue(hPtr, winPtr); + } + + for (childPtr = winPtr->childList; childPtr != NULL; + childPtr = childPtr->nextPtr) { + TkWmStackorderToplevelWrapperMap(childPtr, table); + } +} +/* + *---------------------------------------------------------------------- + * + * TkWmStackorderToplevel -- + * + * This procedure returns the stack order of toplevel windows. + * + * Results: + * An array of pointers to tk window objects in stacking order + * or else NULL if there was an error. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkWindow ** +TkWmStackorderToplevel(parentPtr) + TkWindow *parentPtr; /* Parent toplevel window. */ +{ + TkWmStackorderToplevelPair pair; + TkWindow **windows; + Tcl_HashTable table; + Tcl_HashEntry *hPtr; + Tcl_HashSearch search; + + /* + * Map HWND ids to a TkWindow of the wrapped toplevel. + */ + + Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS); + TkWmStackorderToplevelWrapperMap(parentPtr, &table); + + windows = (TkWindow **) ckalloc((table.numEntries+1) + * sizeof(TkWindow *)); + + /* + * Special cases: If zero or one toplevels were mapped + * there is no need to call EnumWindows. + */ + + switch (table.numEntries) { + case 0: + windows[0] = NULL; + goto done; + case 1: + hPtr = Tcl_FirstHashEntry(&table, &search); + windows[0] = (TkWindow *) Tcl_GetHashValue(hPtr); + windows[1] = NULL; + goto done; + } + + /* + * We will be inserting into the array starting at the end + * and working our way to the beginning since EnumWindows + * returns windows in highest to lowest order. + */ + + pair.table = &table; + pair.window_ptr = windows + table.numEntries; + *pair.window_ptr-- = NULL; + + if (EnumWindows((WNDENUMPROC) TkWmStackorderToplevelEnumProc, + (LPARAM) &pair) == 0) { + ckfree((char *) windows); + windows = NULL; + } else { + if (pair.window_ptr != (windows-1)) + panic("num matched toplevel windows does not equal num children"); + } + + done: + Tcl_DeleteHashTable(&table); + return windows; +} + +/* + *---------------------------------------------------------------------- + * * TkWmRestackToplevel -- * * This procedure restacks a top-level window. @@ -3340,10 +5907,14 @@ TkWmAddToColormapWindows(winPtr) return; } - if (topPtr->flags & TK_TOP_LEVEL) { + if (topPtr->flags & TK_TOP_HIERARCHY) { break; } } + if (topPtr->wmInfoPtr == NULL) { + return; + } + if (topPtr->wmInfoPtr->flags & WM_COLORMAPS_EXPLICIT) { return; } @@ -3447,6 +6018,10 @@ TkWmRemoveFromColormapWindows(winPtr) return; } + if (topPtr->wmInfoPtr == NULL) { + return; + } + /* * Find the window and slide the following ones down to cover * it up. @@ -3535,7 +6110,7 @@ ConfigureTopLevel(pos) int state; /* Current window state. */ RECT rect; WINDOWPLACEMENT windowPos; - + if (winPtr == NULL) { return; } @@ -3626,7 +6201,7 @@ ConfigureTopLevel(pos) if (state == NormalState) { - /* + /* * Update size information from the event. There are a couple of * tricky points here: * @@ -3689,9 +6264,9 @@ ConfigureTopLevel(pos) wmPtr->flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y); } } - + /* - * Update the wrapper window location information. + * Update the wrapper window location information. */ if (wmPtr->flags & WM_NEGATIVE_X) { @@ -3784,9 +6359,9 @@ InstallColormaps(hwnd, message, isForemost) HPALETTE oldPalette; TkWindow *winPtr = GetTopLevel(hwnd); WmInfo *wmPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - + if (winPtr == NULL) { return 0; } @@ -3946,10 +6521,10 @@ InvalidateSubTree(winPtr, colormap) childPtr = childPtr->nextPtr) { /* * We can stop the descent when we hit an unmapped or - * toplevel window. + * toplevel window. */ - if (!Tk_IsTopLevel(childPtr) && Tk_IsMapped(childPtr)) { + if (!Tk_TopWinHierarchy(childPtr) && Tk_IsMapped(childPtr)) { InvalidateSubTree(childPtr, colormap); } } @@ -3975,7 +6550,7 @@ InvalidateSubTree(winPtr, colormap) HPALETTE TkWinGetSystemPalette() { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); return tsdPtr->systemPalette; @@ -4150,7 +6725,7 @@ TopLevelProc(hwnd, message, wParam, lParam) if (message == WM_WINDOWPOSCHANGED) { WINDOWPOS *pos = (WINDOWPOS *) lParam; TkWindow *winPtr = (TkWindow *) Tk_HWNDToWindow(pos->hwnd); - + if (winPtr == NULL) { return 0; } @@ -4201,7 +6776,7 @@ WmProc(hwnd, message, wParam, lParam) LPARAM lParam; { static int inMoveSize = 0; - static oldMode; /* This static is set upon entering move/size mode + static int oldMode; /* This static is set upon entering move/size mode * and is used to reset the service mode after * leaving move/size mode. Note that this mechanism * assumes move/size is only one level deep. */ @@ -4240,7 +6815,7 @@ WmProc(hwnd, message, wParam, lParam) } break; - case WM_GETMINMAXINFO: + case WM_GETMINMAXINFO: SetLimits(hwnd, (MINMAXINFO *) lParam); result = 0; goto done; @@ -4253,7 +6828,7 @@ WmProc(hwnd, message, wParam, lParam) case WM_QUERYNEWPALETTE: result = InstallColormaps(hwnd, WM_QUERYNEWPALETTE, TRUE); goto done; - + case WM_WINDOWPOSCHANGED: ConfigureTopLevel((WINDOWPOS *) lParam); result = 0; @@ -4285,7 +6860,8 @@ WmProc(hwnd, message, wParam, lParam) * This allows us to pass the message onto the * native menus [Bug: 2272] */ - result = DefWindowProc(hwnd, message, wParam, lParam); + result = (*tkWinProcs->defWindowProc)(hwnd, message, + wParam, lParam); goto done; } @@ -4296,7 +6872,7 @@ WmProc(hwnd, message, wParam, lParam) * handle the mouse event. */ - if (winPtr) { + if (winPtr) { eventPtr = (ActivateEvent *)ckalloc(sizeof(ActivateEvent)); eventPtr->ev.proc = ActivateWindow; eventPtr->winPtr = winPtr; @@ -4318,10 +6894,11 @@ WmProc(hwnd, message, wParam, lParam) result = 0; } else if (!Tk_TranslateWinEvent(child, message, wParam, lParam, &result)) { - result = DefWindowProc(hwnd, message, wParam, lParam); + result = (*tkWinProcs->defWindowProc)(hwnd, message, + wParam, lParam); } } else { - result = DefWindowProc(hwnd, message, wParam, lParam); + result = (*tkWinProcs->defWindowProc)(hwnd, message, wParam, lParam); } done: @@ -4364,13 +6941,13 @@ TkpMakeMenuWindow(tkwin, transient) atts.override_redirect = False; atts.save_under = False; } - + if ((atts.override_redirect != Tk_Attributes(tkwin)->override_redirect) || (atts.save_under != Tk_Attributes(tkwin)->save_under)) { Tk_ChangeWindowAttributes(tkwin, CWOverrideRedirect|CWSaveUnder, &atts); } - + } /* @@ -4425,7 +7002,7 @@ TkWmFocusToplevel(winPtr) TkWindow *winPtr; /* Window that received a focus-related * event. */ { - if (!(winPtr->flags & TK_TOP_LEVEL)) { + if (!(winPtr->flags & TK_TOP_HIERARCHY)) { return NULL; } return winPtr; @@ -4455,7 +7032,7 @@ TkpGetWrapperWindow( TkWindow *winPtr) /* Window that received a focus-related * event. */ { - if (!(winPtr->flags & TK_TOP_LEVEL)) { + if (!(winPtr->flags & TK_TOP_HIERARCHY)) { return NULL; } return winPtr; @@ -4497,7 +7074,7 @@ ActivateWindow( if (winPtr && (TkGrabState(winPtr) != TK_GRAB_EXCLUDED)) { SetFocus(Tk_GetHWND(winPtr->window)); } - + return 1; } @@ -4525,7 +7102,7 @@ TkWinSetForegroundWindow(winPtr) TkWindow *winPtr; { register WmInfo *wmPtr = winPtr->wmInfoPtr; - + if (wmPtr->wrapper != NULL) { SetForegroundWindow(wmPtr->wrapper); } else { |