home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tcltk805.zip / tcl805s.zip / tk8.0.5 / os2 / tkOS2Wm.c < prev    next >
C/C++ Source or Header  |  2001-09-07  |  170KB  |  4,989 lines

  1. /* 
  2.  * tkOS2Wm.c --
  3.  *
  4.  *    This module takes care of the interactions between a Tk-based
  5.  *    application and the window manager.  Among other things, it
  6.  *    implements the "wm" command and passes geometry information
  7.  *    to the window manager.
  8.  *
  9.  * Copyright (c) 1996-2000 Illya Vaes
  10.  * Copyright (c) 1995 Sun Microsystems, Inc.
  11.  *
  12.  * See the file "license.terms" for information on usage and redistribution
  13.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  14.  */
  15.  
  16.  
  17. #include "tkOS2Int.h"
  18.  
  19. /*
  20.  * This module keeps a list of all top-level windows.
  21.  */
  22.  
  23. static WmInfo *firstWmPtr = NULL;    /* Points to first top-level window. */
  24. static WmInfo *foregroundWmPtr = NULL;    /* Points to the foreground window. */
  25.  
  26. /*
  27.  * The variable below is used to enable or disable tracing in this
  28.  * module.  If tracing is enabled, then information is printed on
  29.  * standard output about interesting interactions with the window
  30.  * manager.
  31.  */
  32.  
  33. static int wmTracing = 0;
  34.  
  35. /*
  36.  * The following structure is the official type record for geometry
  37.  * management of top-level windows.
  38.  */
  39.  
  40. static void        TopLevelReqProc (ClientData dummy, Tk_Window tkwin);
  41.  
  42. static Tk_GeomMgr wmMgrType = {
  43.     "wm",                /* name */
  44.     TopLevelReqProc,            /* requestProc */
  45.     (Tk_GeomLostSlaveProc *) NULL,    /* lostSlaveProc */
  46. };
  47.  
  48. /*
  49.  * Global system palette.  This value always refers to the currently
  50.  * installed foreground logical palette.
  51.  */
  52.  
  53. static HPAL systemPalette = NULLHANDLE;
  54.  
  55. /*
  56.  * Flag indicating whether this module has been initialized yet.
  57.  */
  58.  
  59. static int initialized = 0;
  60.  
  61. /*
  62.  * This flag is cleared when the first window is mapped in a non-iconic
  63.  * state.
  64.  */
  65.  
  66. static int firstWindow = 1;
  67.  
  68. /*
  69.  * Forward declarations for procedures defined in this file:
  70.  */
  71.  
  72. static void             ConfigureTopLevel _ANSI_ARGS_((SWP *pos));
  73. static void             GenerateConfigureNotify _ANSI_ARGS_((
  74.                             TkWindow *winPtr));
  75. static void             GetMaxSize _ANSI_ARGS_((WmInfo *wmPtr, int *maxWidthPtr,
  76.                             int *maxHeightPtr));
  77. static void             GetMinSize _ANSI_ARGS_((WmInfo *wmPtr, int *minWidthPtr,
  78.                             int *minHeightPtr));
  79. static TkWindow *       GetTopLevel _ANSI_ARGS_((HWND hwnd));
  80. static void             InitWm _ANSI_ARGS_((void));
  81. static MRESULT          InstallColormaps _ANSI_ARGS_((HWND hwnd, ULONG message,
  82.                             int isForemost));
  83. static void             InvalidateSubTree _ANSI_ARGS_((TkWindow *winPtr,
  84.                             Colormap colormap));
  85. static int            ParseGeometry _ANSI_ARGS_((Tcl_Interp *interp,
  86.                             char *string, TkWindow *winPtr));
  87. static void             RefreshColormap _ANSI_ARGS_((Colormap colormap));
  88. static void             SetLimits _ANSI_ARGS_((HWND hwnd,
  89.                             TRACKINFO *info));
  90. static MRESULT EXPENTRY TopLevelProc _ANSI_ARGS_((HWND hwnd, ULONG message,
  91.                             MPARAM param1, MPARAM param2));
  92. static void            TopLevelEventProc _ANSI_ARGS_((ClientData clientData,
  93.                             XEvent *eventPtr));
  94. static void            TopLevelReqProc _ANSI_ARGS_((ClientData dummy,
  95.                             Tk_Window tkwin));
  96. static void            UpdateGeometryInfo _ANSI_ARGS_((ClientData clientData));
  97. static void             UpdateWrapper _ANSI_ARGS_((TkWindow *winPtr));
  98. static MRESULT EXPENTRY WmProc _ANSI_ARGS_((HWND hwnd, ULONG message,
  99.                             MPARAM param1, MPARAM param2));
  100.  
  101. /*
  102.  *----------------------------------------------------------------------
  103.  *
  104.  * InitWm --
  105.  *
  106.  *      This routine creates the Wm toplevel decorative frame class.
  107.  *
  108.  * Results:
  109.  *      None.
  110.  *
  111.  * Side effects:
  112.  *      Registers a new window class.
  113.  *
  114.  *----------------------------------------------------------------------
  115.  */
  116.  
  117. static void
  118. InitWm(void)
  119. {
  120. #ifdef VERBOSE
  121.     printf("InitWm\n");
  122. #endif
  123.     if (initialized) {
  124.         return;
  125.     }
  126.     initialized = 1;
  127.  
  128. /*
  129.     if (!WinRegisterClass(TclOS2GetHAB(), TOC_TOPLEVEL, WmProc, CS_SIZEREDRAW,
  130.         0)) {
  131.         panic("Unable to register TkTopLevel class");
  132.     }
  133. */
  134. }
  135.  
  136. /*
  137.  *----------------------------------------------------------------------
  138.  *
  139.  * GetTopLevel --
  140.  *
  141.  *      This function retrieves the TkWindow associated with the
  142.  *      given HWND.
  143.  *
  144.  * Results:
  145.  *      Returns the matching TkWindow.
  146.  *
  147.  * Side effects:
  148.  *      None.
  149.  *
  150.  *----------------------------------------------------------------------
  151.  */
  152.  
  153. static TkWindow *
  154. GetTopLevel(hwnd)
  155.     HWND hwnd;
  156. {
  157. #ifdef VERBOSE
  158.     printf("GetTopLevel hwnd %x => %x\n", hwnd,
  159.            WinQueryWindowULong(hwnd, QWL_USER));
  160. #endif
  161.     return (TkWindow *) WinQueryWindowULong(hwnd, QWL_USER);
  162. }
  163.  
  164. /*
  165.  *----------------------------------------------------------------------
  166.  *
  167.  * SetLimits --
  168.  *
  169.  *      Updates the minimum and maximum window size constraints for
  170.  *      tracking.
  171.  *
  172.  * Results:
  173.  *      None.
  174.  *
  175.  * Side effects:
  176.  *      Changes the values of the track pointer to reflect the current
  177.  *      minimum and maximum size values.
  178.  *
  179.  *----------------------------------------------------------------------
  180.  */
  181.  
  182. void
  183. SetLimits(hwnd, trackPtr)
  184.     HWND hwnd;
  185.     TRACKINFO *trackPtr;
  186. {
  187.     register WmInfo *wmPtr;
  188.     int maxWidth, maxHeight;
  189.     int minWidth, minHeight;
  190.     int base;
  191.     TkWindow *winPtr = GetTopLevel(hwnd);
  192.     SWP pos;
  193.  
  194. #ifdef VERBOSE
  195.     printf("SetLimits hwnd %x, flags %x\n", hwnd, trackPtr->fs);
  196. #endif
  197.  
  198.     if (winPtr == NULL) {
  199.         return;
  200.     }
  201.  
  202.     wmPtr = winPtr->wmInfoPtr;
  203.  
  204.     /* Get present size as default max/min */
  205.     rc = WinQueryWindowPos(hwnd, &pos);
  206.     /* Fill in defaults */
  207.     trackPtr->cxBorder = trackPtr->cyBorder = 4; /* 4 pixels tracking */
  208.     trackPtr->cxGrid = trackPtr->cyGrid = 1; /* smooth tracking */
  209.     trackPtr->cxKeyboard = trackPtr->cyKeyboard = 8; /* fast keyboardtracking */
  210.     trackPtr->rclTrack.xLeft = pos.x;
  211.     trackPtr->rclTrack.yBottom = pos.y;
  212.     trackPtr->rclTrack.xRight = pos.x + pos.cx;
  213.     trackPtr->rclTrack.yTop = pos.y + pos.cy;
  214.     trackPtr->rclBoundary.xLeft = 0;
  215.     trackPtr->rclBoundary.yBottom = 0;
  216.     trackPtr->rclBoundary.xRight = xScreen;
  217.     trackPtr->rclBoundary.yTop = yScreen;
  218.     trackPtr->ptlMinTrackSize.x = 0;
  219.     trackPtr->ptlMinTrackSize.y = 0;
  220.     trackPtr->ptlMaxTrackSize.x = xScreen;
  221.     trackPtr->ptlMaxTrackSize.y = yScreen;
  222.     
  223.     /*
  224.      * Copy latest constraint info.
  225.      */
  226.  
  227.     wmPtr->defMinWidth = trackPtr->ptlMinTrackSize.x;
  228.     wmPtr->defMinHeight = trackPtr->ptlMinTrackSize.y;
  229.     wmPtr->defMaxWidth = trackPtr->ptlMaxTrackSize.x;
  230.     wmPtr->defMaxHeight = trackPtr->ptlMaxTrackSize.y;
  231.  
  232. #ifdef VERBOSE
  233.     printf("SetLimits, defMin %dx%d min %dx%d defMax %dx%d max %dx%d\n",
  234.            wmPtr->defMinWidth, wmPtr->defMinHeight,
  235.            wmPtr->minWidth, wmPtr->minHeight,
  236.            wmPtr->defMaxWidth, wmPtr->defMaxHeight,
  237.            wmPtr->minWidth, wmPtr->minHeight);
  238.     printf("    trackinfo: cxBorder %d, cyBorder %d, cxGrid %d, cyGrid %d,
  239.            cxKeyboard %d, cyKeyboard %d,
  240.            rclTrack (%d,%d->%d,%d), rclBoundary (%d,%d->%d,%d),
  241.            ptlMinTrackSize (%d,%d), ptlMaxTrackSize (%d,%d)\n",
  242.            trackPtr->cxBorder, trackPtr->cyBorder,
  243.            trackPtr->cxGrid, trackPtr->cyGrid,
  244.            trackPtr->cxKeyboard, trackPtr->cyKeyboard, trackPtr->rclTrack.xLeft,
  245.            trackPtr->rclTrack.yBottom, trackPtr->rclTrack.xRight,
  246.            trackPtr->rclTrack.yTop, trackPtr->rclBoundary.xLeft,
  247.            trackPtr->rclBoundary.yBottom, trackPtr->rclBoundary.xRight,
  248.            trackPtr->rclBoundary.yTop, trackPtr->ptlMinTrackSize.x,
  249.            trackPtr->ptlMinTrackSize.y, trackPtr->ptlMaxTrackSize.x,
  250.            trackPtr->ptlMaxTrackSize.y);
  251. #endif
  252.  
  253.     GetMaxSize(wmPtr, &maxWidth, &maxHeight);
  254.     GetMinSize(wmPtr, &minWidth, &minHeight);
  255.     
  256.     if (wmPtr->gridWin != NULL) {
  257.         base = winPtr->reqWidth - (wmPtr->reqGridWidth * wmPtr->widthInc);
  258.         if (base < 0) {
  259.             base = 0;
  260.         }
  261.         base += wmPtr->borderWidth;
  262.         trackPtr->ptlMinTrackSize.x = base + (minWidth * wmPtr->widthInc);
  263.         trackPtr->ptlMaxTrackSize.x = base + (maxWidth * wmPtr->widthInc);
  264.  
  265.         base = winPtr->reqHeight - (wmPtr->reqGridHeight * wmPtr->heightInc);
  266.         if (base < 0) {
  267.             base = 0;
  268.         }
  269.         base += wmPtr->borderHeight;
  270.         trackPtr->ptlMinTrackSize.y = base + (minHeight * wmPtr->heightInc);
  271.         trackPtr->ptlMaxTrackSize.y = base + (maxHeight * wmPtr->heightInc);
  272.     } else {
  273.         trackPtr->ptlMaxTrackSize.x = maxWidth + wmPtr->borderWidth;
  274.         trackPtr->ptlMaxTrackSize.y = maxHeight + wmPtr->borderHeight;
  275.         trackPtr->ptlMinTrackSize.x = minWidth + wmPtr->borderWidth;
  276.         trackPtr->ptlMinTrackSize.y = minHeight + wmPtr->borderHeight;
  277.     }
  278.  
  279.     /*
  280.      * If the window isn't supposed to be resizable, then set the
  281.      * minimum and maximum dimensions to be the same as the current size.
  282.      */
  283.  
  284.     if (!(wmPtr->flags & WM_SYNC_PENDING)) {
  285.         if (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) {
  286.             trackPtr->ptlMinTrackSize.x = winPtr->changes.width +
  287.                                           wmPtr->borderWidth;
  288.             trackPtr->ptlMaxTrackSize.x = trackPtr->ptlMinTrackSize.x;
  289.         }
  290.         if (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {
  291.             trackPtr->ptlMinTrackSize.y = winPtr->changes.height +
  292.                                           wmPtr->borderHeight;
  293.             trackPtr->ptlMaxTrackSize.y = trackPtr->ptlMinTrackSize.y;
  294.         }
  295.     }
  296. #ifdef VERBOSE
  297.     printf("    now: cxBorder %d, cyBorder %d, cxGrid %d, cyGrid %d,
  298.            cxKeyboard %d, cyKeyboard %d,
  299.            rclTrack (%d,%d->%d,%d), rclBoundary (%d,%d->%d,%d),
  300.            ptlMinTrackSize (%d,%d), ptlMaxTrackSize (%d,%d)\n",
  301.            trackPtr->cxBorder, trackPtr->cyBorder,
  302.            trackPtr->cxGrid, trackPtr->cyGrid,
  303.            trackPtr->cxKeyboard, trackPtr->cyKeyboard, trackPtr->rclTrack.xLeft,
  304.            trackPtr->rclTrack.yBottom, trackPtr->rclTrack.xRight,
  305.            trackPtr->rclTrack.yTop, trackPtr->rclBoundary.xLeft,
  306.            trackPtr->rclBoundary.yBottom, trackPtr->rclBoundary.xRight,
  307.            trackPtr->rclBoundary.yTop, trackPtr->ptlMinTrackSize.x,
  308.            trackPtr->ptlMinTrackSize.y, trackPtr->ptlMaxTrackSize.x,
  309.            trackPtr->ptlMaxTrackSize.y);
  310. #endif
  311. }
  312.  
  313. /*
  314.  *----------------------------------------------------------------------
  315.  *
  316.  * TkOS2WmCleanup --
  317.  *
  318.  *      Unregisters classes registered by the window manager. This is
  319.  *      called from the DLL main entry point when the DLL is unloaded.
  320.  *
  321.  * Results:
  322.  *      None.
  323.  *
  324.  * Side effects:
  325.  *      The window classes are discarded.
  326.  *
  327.  *----------------------------------------------------------------------
  328.  */
  329.  
  330. void
  331. TkOS2WmCleanup(hInstance)
  332.     HMODULE hInstance;
  333. {
  334.     if (!initialized) {
  335.         return;
  336.     }
  337.     initialized = 0;
  338. }
  339.  
  340. /*
  341.  *--------------------------------------------------------------
  342.  *
  343.  * TkWmNewWindow --
  344.  *
  345.  *    This procedure is invoked whenever a new top-level
  346.  *    window is created.  Its job is to initialize the WmInfo
  347.  *    structure for the window.
  348.  *
  349.  * Results:
  350.  *    None.
  351.  *
  352.  * Side effects:
  353.  *    A WmInfo structure gets allocated and initialized.
  354.  *
  355.  *--------------------------------------------------------------
  356.  */
  357.  
  358. void
  359. TkWmNewWindow(winPtr)
  360.     TkWindow *winPtr;        /* Newly-created top-level window. */
  361. {
  362.     register WmInfo *wmPtr;
  363.  
  364.     wmPtr = (WmInfo *) ckalloc(sizeof(WmInfo));
  365. #ifdef VERBOSE
  366.     printf("TkWmNewWindow, wmPtr %x\n", wmPtr);
  367. #endif
  368.     winPtr->wmInfoPtr = wmPtr;
  369.     wmPtr->winPtr = winPtr;
  370.     wmPtr->wrapper = NULLHANDLE;
  371.     wmPtr->titleUid = NULL;
  372.     wmPtr->iconName = NULL;
  373.     wmPtr->masterPtr = NULL;
  374.     wmPtr->hints.flags = InputHint | StateHint;
  375.     wmPtr->hints.input = True;
  376.     wmPtr->hints.initial_state = NormalState;
  377.     wmPtr->hints.icon_pixmap = None;
  378.     wmPtr->hints.icon_window = None;
  379.     wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;
  380.     wmPtr->hints.icon_mask = None;
  381.     wmPtr->hints.window_group = None;
  382.     wmPtr->leaderName = NULL;
  383.     wmPtr->icon = NULL;
  384.     wmPtr->iconFor = NULL;
  385.     wmPtr->sizeHintsFlags = 0;
  386.  
  387.     /*
  388.      * Default the maximum dimensions to the size of the display.
  389.      */
  390.  
  391.     wmPtr->defMinWidth = wmPtr->defMinHeight = 0;
  392.     wmPtr->defMaxWidth = DisplayWidth(winPtr->display,
  393.             winPtr->screenNum);
  394.     wmPtr->defMaxHeight = DisplayHeight(winPtr->display,
  395.             winPtr->screenNum);
  396.     wmPtr->minWidth = wmPtr->minHeight = 1;
  397.     wmPtr->maxWidth = wmPtr->maxHeight = 0;
  398.     wmPtr->gridWin = NULL;
  399.     wmPtr->widthInc = wmPtr->heightInc = 1;
  400.     wmPtr->minAspect.x = wmPtr->minAspect.y = 1;
  401.     wmPtr->maxAspect.x = wmPtr->maxAspect.y = 1;
  402.     wmPtr->reqGridWidth = wmPtr->reqGridHeight = -1;
  403.     wmPtr->gravity = NorthWestGravity;
  404.     wmPtr->width = -1;
  405.     wmPtr->height = -1;
  406.     wmPtr->hMenu = NULLHANDLE;
  407.     wmPtr->x = winPtr->changes.x;
  408.     wmPtr->y = winPtr->changes.y;
  409.  
  410. #ifdef VERBOSE
  411.     printf("TkWmNewWindow, x %d y %d\n", wmPtr->x, wmPtr->y);
  412. #endif
  413.     wmPtr->borderWidth = -1;
  414.     wmPtr->borderHeight = -1;
  415.  
  416.     wmPtr->cmapList = NULL;
  417.     wmPtr->cmapCount = 0;
  418.  
  419.     wmPtr->configWidth = -1;
  420.     wmPtr->configHeight = -1;
  421.     wmPtr->protPtr = NULL;
  422.     wmPtr->cmdArgv = NULL;
  423.     wmPtr->clientMachine = NULL;
  424.     wmPtr->flags = WM_NEVER_MAPPED;
  425.     wmPtr->nextPtr = firstWmPtr;
  426.     firstWmPtr = wmPtr;
  427.  
  428.     /*
  429.      * Tk must monitor structure events for top-level windows, in order
  430.      * to detect size and position changes caused by window managers.
  431.      */
  432.  
  433.     Tk_CreateEventHandler((Tk_Window) winPtr, StructureNotifyMask,
  434.             TopLevelEventProc, (ClientData) winPtr);
  435.  
  436.     /*
  437.      * Arrange for geometry requests to be reflected from the window
  438.      * to the window manager.
  439.      */
  440.  
  441.     Tk_ManageGeometry((Tk_Window) winPtr, &wmMgrType, (ClientData) 0);
  442. }
  443.  
  444. /*
  445.  *----------------------------------------------------------------------
  446.  *
  447.  * UpdateWrapper --
  448.  *
  449.  *      This function creates the wrapper window that contains the
  450.  *      window decorations and menus for a toplevel.  This function
  451.  *      may be called after a window is mapped to change the window
  452.  *      style.
  453.  *
  454.  * Results:
  455.  *      None.
  456.  *
  457.  * Side effects:
  458.  *      Destroys any old wrapper window and replaces it with a newly
  459.  *      created wrapper.
  460.  *
  461.  *----------------------------------------------------------------------
  462.  */
  463.  
  464. static void
  465. UpdateWrapper(winPtr)
  466.     TkWindow *winPtr;           /* Top-level window to redecorate. */
  467. {
  468.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  469.     HWND parentHWND = HWND_DESKTOP, oldWrapper;
  470.     HWND child = TkOS2GetHWND(winPtr->window);
  471.     int x, y, width, height, state;
  472. #ifdef VERBOSE
  473.     SWP place;
  474.     printf("UpdateWrapper winPtr %x, child %x, state %s\n", winPtr, child,
  475.            wmPtr->hints.initial_state == NormalState ? "NormalState" :
  476.            (wmPtr->hints.initial_state == IconicState ?  "IconicState" :
  477.            (wmPtr->hints.initial_state == ZoomState ? "ZoomState" :
  478.            (wmPtr->hints.initial_state == WithdrawnState ? "WithdrawnState" :
  479.             "unknown"))));
  480. #endif
  481.  
  482.     if (winPtr->flags & TK_EMBEDDED) {
  483.         wmPtr->wrapper = (HWND) winPtr->privatePtr;
  484.         if (wmPtr->wrapper == NULLHANDLE) {
  485.             panic("UpdateWrapper: Cannot find container window");
  486.         }
  487.         if (!WinIsWindow(TclOS2GetHAB(), wmPtr->wrapper)) {
  488.             panic("UpdateWrapper: Container was destroyed");
  489.         }
  490.  
  491.     } else {
  492.         FRAMECDATA fcdata;
  493.         /*
  494.          * Pick the decorative frame style.
  495.          * Override redirect windows get created as undecorated popups.
  496.          * Transient windows get a modal dialog frame.
  497.          * Neither override, nor transient windows appear in the tasklist.
  498.          * Note that a transient window does not resize
  499.          * by default, so we need to explicitly add the FCF_SIZEBORDER frame
  500.          * control flag and remove the FCF_DLGBORDER flag if we want it to be
  501.          * resizeable.
  502.          */
  503.  
  504.         if (winPtr->atts.override_redirect) {
  505.             wmPtr->style = WM_OVERRIDE_STYLE;
  506.             wmPtr->exStyle = EX_OVERRIDE_STYLE;
  507.         } else if (wmPtr->masterPtr) {
  508.             wmPtr->style = WM_TRANSIENT_STYLE;
  509.             wmPtr->exStyle = EX_TRANSIENT_STYLE;
  510.             parentHWND = Tk_GetHWND(Tk_WindowId(wmPtr->masterPtr));
  511.             if (! ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) &&
  512.                     (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE))) {
  513.                 wmPtr->exStyle &= ~FCF_DLGBORDER;
  514.                 wmPtr->exStyle |= FCF_SIZEBORDER;
  515.             }
  516.         } else {
  517.             wmPtr->style = WM_TOPLEVEL_STYLE;
  518.             wmPtr->exStyle = EX_TOPLEVEL_STYLE;
  519.         }
  520.  
  521.         /*
  522.          * Compute the geometry of the parent and child windows.
  523.          */
  524.  
  525.         wmPtr->flags |= WM_CREATE_PENDING|WM_MOVE_PENDING;
  526.         UpdateGeometryInfo((ClientData)winPtr);
  527.         wmPtr->flags &= ~(WM_CREATE_PENDING|WM_MOVE_PENDING);
  528.  
  529.         width = wmPtr->borderWidth + winPtr->changes.width;
  530.         height = wmPtr->borderHeight + winPtr->changes.height;
  531. #ifdef VERBOSE
  532.         printf("width: %d + %d => %d\nheight: %d + %d => %d\n",
  533.                wmPtr->borderWidth, winPtr->changes.width, width,
  534.                wmPtr->borderHeight, winPtr->changes.height, height);
  535. #endif
  536.  
  537.         /*
  538.          * Set the initial position from the user or program specified
  539.          * location.  If nothing has been specified, then let the system
  540.          * pick a location.
  541.          */
  542.  
  543.  
  544.         if (!(wmPtr->sizeHintsFlags & (USPosition | PPosition))
  545.                 && (wmPtr->flags & WM_NEVER_MAPPED)) {
  546.             SWP recommendedPos;
  547.             rc = WinQueryTaskSizePos(TclOS2GetHAB(), 0L, &recommendedPos);
  548.             if (rc == 0) {
  549.                 x = recommendedPos.x;
  550.                 y = recommendedPos.y;
  551. #ifdef VERBOSE
  552.                 printf("Positioning: WinQueryTaskSizePos OK: (%d,%d)\n", x, y);
  553. #endif
  554.             } else {
  555.                 x = winPtr->changes.x;
  556.                 y = winPtr->changes.y;
  557. #ifdef VERBOSE
  558.                 printf("Positioning: WinQueryTaskSizePos ERROR: (%d,%d)\n",
  559.                        x, y);
  560. #endif
  561.             }
  562.         } else {
  563.             x = winPtr->changes.x;
  564.             y = winPtr->changes.y;
  565.         }
  566.  
  567.         /*
  568.          * Create the containing window, and set the user data to point
  569.          * to the TkWindow.
  570.          */
  571.  
  572.         fcdata.cb = sizeof(FRAMECDATA);
  573.         fcdata.flCreateFlags = (ULONG)wmPtr->exStyle;
  574.         fcdata.hmodResources = 0L;
  575.         fcdata.idResources = 0;
  576.         /*
  577.          * Tk Dialogs as children of a toplevel and therefore limited to
  578.          * the space that toplevel offers is dumb in my opinion (and it
  579.          * wasn't that way in 4.2. The only reason I see for it would be
  580.          * in the Tcl Plugin, but that probably doesn't work anyway.
  581.          * I therefore always create a Wm window the way I think it should
  582.          * be as a "Window Manager window": as a toplevel = child of the
  583.          * desktop. Anybody disagreeing with me can change the HWND_DESKTOP
  584.          * to parentHWND to get the Windows equivalent.
  585.          */
  586. #define ID_FRAME 1
  587.         wmPtr->wrapper  = WinCreateWindow(
  588.                 HWND_DESKTOP,             /* Parent */
  589.                 WC_FRAME,        /* Class */
  590.                 wmPtr->titleUid,        /* Window text */
  591.                 wmPtr->style,           /* Style */
  592.                 x, yScreen - height - y,/* Initial X and Y coordinates */
  593.                 width,                  /* Width */
  594.                 height,                 /* Height */
  595.                 NULLHANDLE,             /* Owner */
  596.                 HWND_TOP,               /* Insertbehind (sibling) */
  597.                 ID_FRAME,               /* Window ID */
  598.                 &fcdata,                /* Ptr to control data */
  599.                 NULL);                  /* Ptr to presentation parameters */
  600.  
  601. #ifdef VERBOSE
  602.         printf("WinCreateWindow frame %x (%s) wmPtr %x (%d,%d) %dx%d\n",
  603.                wmPtr->wrapper, wmPtr->titleUid, wmPtr, x, yScreen - height - y,
  604.                width, height);
  605.         printf("     exStyle %x (%s) style %x (%s)\n", wmPtr->exStyle,
  606.                (wmPtr->exStyle & ~FCF_SHELLPOSITION) == EX_TOPLEVEL_STYLE
  607.                                                      ? "EX_TOPLEVEL_STYLE" :
  608.                ((wmPtr->exStyle & ~FCF_SHELLPOSITION) == EX_OVERRIDE_STYLE
  609.                                                      ? "EX_OVERRIDE_STYLE" :
  610.                ((wmPtr->exStyle & ~FCF_SHELLPOSITION) == EX_TRANSIENT_STYLE
  611.                                                      ? "EX_TRANSIENT_STYLE"
  612.                                                      : "unknown")),
  613.                wmPtr->style,
  614.                (wmPtr->style == WM_TOPLEVEL_STYLE ? "WM_TOPLEVEL_STYLE" :
  615.                (wmPtr->style == WM_OVERRIDE_STYLE ? "WM_OVERRIDE_STYLE" :
  616.                (wmPtr->style == WM_TRANSIENT_STYLE ? "WM_TRANSIENT_STYLE"
  617.                                                    : "unknown"))));
  618. #endif
  619.  
  620.         /* Subclass Frame window */
  621.         oldFrameProc = WinSubclassWindow(wmPtr->wrapper, WmProc);
  622.         /* Force frame window to display the title bar, buttons, ... */
  623.         WinSendMsg(wmPtr->wrapper, WM_UPDATEFRAME, MPVOID, MPVOID);
  624.         WinSetWindowULong(wmPtr->wrapper, QWL_USER, (ULONG)winPtr);
  625.  
  626. #ifdef VERBOSE
  627.         rc = WinQueryWindowPos(wmPtr->wrapper, &place);
  628.         if (rc == TRUE) {
  629.             printf("    WinQueryWindowPos frame %x OK: (%d,%d) %dx%d\n",
  630.                    wmPtr->wrapper, place.x, place.y, place.cx, place.cy);
  631.         } else {
  632.             printf("    WinQueryWindowPos frame %x ERROR %x\n", wmPtr->wrapper,
  633.                    WinGetLastError(TclOS2GetHAB()));
  634.         }
  635. #endif
  636.  
  637.         TkInstallFrameMenu((Tk_Window) winPtr);
  638.     }
  639.  
  640.     /*
  641.      * Now we need to reparent the contained window.
  642.      */
  643.  
  644.     if (winPtr->flags & TK_EMBEDDED) {
  645.         WinSetWindowPtr(child, QWP_PFNWP, (PVOID) TopLevelProc);
  646.     }
  647.     /* Determine old parent */
  648.     oldWrapper = WinQueryWindow(child, QW_PARENT);
  649.     rc = WinSetParent(child, wmPtr->wrapper, TRUE);
  650. #ifdef VERBOSE
  651.     printf("    WinSetParent(child %x, parent %x, TRUE) returns %d\n", child,
  652.            wmPtr->wrapper, rc);
  653.     rc = WinQueryWindowPos(child, &place);
  654.     if (rc == TRUE) {
  655.         printf("    WinQueryWindowPos child %x OK: (%d,%d) %dx%d\n",
  656.                child, place.x, place.y, place.cx, place.cy);
  657.     } else {
  658.         printf("    WinQueryWindowPos child %x ERROR %x\n", child,
  659.                WinGetLastError(TclOS2GetHAB()));
  660.     }
  661. #endif
  662.     if (oldWrapper != NULLHANDLE && (oldWrapper != wmPtr->wrapper)
  663.          && (oldWrapper != WinQueryDesktopWindow(TclOS2GetHAB(), NULLHANDLE))) {
  664.         HWND menu;
  665.  
  666.         WinSetWindowULong(oldWrapper, QWL_USER, (ULONG) NULL);
  667.  
  668.         /*
  669.          * Remove the menubar before destroying the window so the menubar
  670.          * isn't destroyed.
  671.          */
  672.  
  673.         /* Set parent and owner to HWND_DESKTOP */
  674.         menu = WinWindowFromID(oldWrapper, FID_MENU);
  675.         if (menu != NULLHANDLE) {
  676.             rc = WinSetParent(menu, HWND_DESKTOP, FALSE);
  677. #ifdef VERBOSE
  678.             printf("    WinSetParent(menu %x, HWND_DESKTOP,FALSE) returns %d\n",
  679.                    menu, rc);
  680. #endif
  681.             WinSetOwner(menu, NULLHANDLE);
  682.         }
  683.         WinDestroyWindow(oldWrapper);
  684.     }
  685.     wmPtr->flags &= ~WM_NEVER_MAPPED;
  686. #ifdef VERBOSE
  687.     printf("    before TK_ATTACHWINDOW\n");
  688.     fflush(stdout);
  689. #endif
  690.     WinSendMsg(wmPtr->wrapper, TK_ATTACHWINDOW, (MPARAM) child, MPVOID);
  691. #ifdef VERBOSE
  692.     printf("    after TK_ATTACHWINDOW\n");
  693.     fflush(stdout);
  694. #endif
  695. /*
  696. */
  697.  
  698.     /*
  699.      * Force an initial transition from withdrawn to the real
  700.      * initial state.
  701.      */
  702.  
  703.     state = wmPtr->hints.initial_state;
  704.     wmPtr->hints.initial_state = WithdrawnState;
  705.     TkpWmSetState(winPtr, state);
  706.  
  707.     /*
  708.      * If we are embedded then force a mapping of the window now,
  709.      * because we do not necessarily own the wrapper and may not
  710.      * get another opportunity to map ourselves. We should not be
  711.      * in either iconified or zoomed states when we get here, so
  712.      * it is safe to just check for TK_EMBEDDED without checking
  713.      * what state we are supposed to be in (default to NormalState).
  714.      */
  715.  
  716.     if (winPtr->flags & TK_EMBEDDED) {
  717.         XMapWindow(winPtr->display, winPtr->window);
  718.     }
  719.  
  720.     /*
  721.      * Set up menus on the wrapper if required.
  722.      */
  723.  
  724.     if (wmPtr->hMenu != NULLHANDLE) {
  725.         wmPtr->flags = WM_SYNC_PENDING;
  726.         rc = WinSetOwner(wmPtr->hMenu, wmPtr->wrapper);
  727. #ifdef VERBOSE
  728.         printf("    WinSetOwner(menu %x, parent %x) returns %d\n",
  729.                wmPtr->hMenu, wmPtr->wrapper, rc);
  730. #endif
  731.         rc = WinSetParent(wmPtr->hMenu, wmPtr->wrapper, FALSE);
  732. #ifdef VERBOSE
  733.         printf("    WinSetParent(menu %x, parent %x, FALSE) returns %d\n",
  734.                wmPtr->hMenu, wmPtr->wrapper, rc);
  735. #endif
  736.         rc = (LONG) WinSendMsg(wmPtr->wrapper, WM_UPDATEFRAME,
  737.                                MPFROMLONG(FCF_MENU), MPVOID);
  738. #ifdef VERBOSE
  739.         printf("    WinSendMsg(%x, WM_UPDATEFRAME, FCF_MENU %x) returns %d\n",
  740.                wmPtr->wrapper, FCF_MENU, rc);
  741. #endif
  742.         wmPtr->flags &= ~WM_SYNC_PENDING;
  743.     }
  744.  
  745.     /*
  746.      * If this is the first window created by the application, then
  747.      * we should activate the initial window.
  748.      */
  749.  
  750.     if (firstWindow) {
  751.         firstWindow = 0;
  752. #ifdef VERBOSE
  753.         printf("    before WinSetActiveWindow %x\n", wmPtr->wrapper);
  754. #endif
  755.         rc = WinSetActiveWindow(HWND_DESKTOP, wmPtr->wrapper);
  756. #ifdef VERBOSE
  757.         if (rc == TRUE) {
  758.              printf("    WinSetActiveWindow %x OK\n", wmPtr->wrapper);
  759.         } else {
  760.              printf("    WinSetActiveWindow %x ERROR %x\n", wmPtr->wrapper,
  761.                     WinGetLastError(TclOS2GetHAB()));
  762.         }
  763. #endif
  764.     }
  765. }
  766.  
  767. /*
  768.  *--------------------------------------------------------------
  769.  *
  770.  * TkWmMapWindow --
  771.  *
  772.  *      This procedure is invoked to map a top-level window.  This
  773.  *      module gets a chance to update all window-manager-related
  774.  *      information in properties before the window manager sees
  775.  *      the map event and checks the properties.  It also gets to
  776.  *      decide whether or not to even map the window after all.
  777.  *
  778.  * Results:
  779.  *      None.
  780.  *
  781.  * Side effects:
  782.  *      Properties of winPtr may get updated to provide up-to-date
  783.  *      information to the window manager.  The window may also get
  784.  *      mapped, but it may not be if this procedure decides that
  785.  *      isn't appropriate (e.g. because the window is withdrawn).
  786.  *
  787.  *--------------------------------------------------------------
  788.  */
  789.  
  790. void
  791. TkWmMapWindow(winPtr)
  792.     TkWindow *winPtr;           /* Top-level window that's about to
  793.                                  * be mapped. */
  794. {
  795.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  796.  
  797. #ifdef VERBOSE
  798.     printf("TkWmMapWindow winPtr %x\n", winPtr);
  799. #endif
  800.  
  801.     if (!initialized) {
  802.         InitWm();
  803.     }
  804.  
  805.     if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  806.         if (wmPtr->hints.initial_state == WithdrawnState) {
  807.             return;
  808.         }
  809.  
  810.         /*
  811.          * Map the window in either the iconified or normal state.  Note that
  812.          * we only send a map event if the window is in the normal state.
  813.          */
  814.  
  815.         TkpWmSetState(winPtr, wmPtr->hints.initial_state);
  816.     }
  817.  
  818.     /*
  819.      * This is the first time this window has ever been mapped.
  820.      * Store all the window-manager-related information for the
  821.      * window.
  822.      */
  823.  
  824.     if (wmPtr->titleUid == NULL) {
  825.         wmPtr->titleUid = winPtr->nameUid;
  826.     }
  827.     UpdateWrapper(winPtr);
  828. }
  829.  
  830. /*
  831.  *--------------------------------------------------------------
  832.  *
  833.  * TkWmUnmapWindow --
  834.  *
  835.  *    This procedure is invoked to unmap a top-level window.  The
  836.  *    only thing it does special is unmap the decorative frame before
  837.  *    unmapping the toplevel window.
  838.  *
  839.  * Results:
  840.  *    None.
  841.  *
  842.  * Side effects:
  843.  *    Unmaps the decorative frame and the window.
  844.  *
  845.  *--------------------------------------------------------------
  846.  */
  847.  
  848. void
  849. TkWmUnmapWindow(winPtr)
  850.     TkWindow *winPtr;        /* Top-level window that's about to
  851.                      * be unmapped. */
  852. {
  853. #ifdef VERBOSE
  854.     printf("TkWmUnmapWindow winPtr %x\n", winPtr);
  855. #endif
  856.     TkpWmSetState(winPtr, WithdrawnState);
  857. }
  858.  
  859. /*
  860.  *----------------------------------------------------------------------
  861.  *
  862.  * TkpWmSetState --
  863.  *
  864.  *      Sets the window manager state for the wrapper window of a
  865.  *      given toplevel window.
  866.  *
  867.  * Results:
  868.  *      None.
  869.  *
  870.  * Side effects:
  871.  *      May maximize, minimize, restore, or withdraw a window.
  872.  *
  873.  *----------------------------------------------------------------------
  874.  */
  875.  
  876. void
  877. TkpWmSetState(winPtr, state)
  878.      TkWindow *winPtr;          /* Toplevel window to operate on. */
  879.      int state;                 /* One of IconicState, ZoomState, NormalState,
  880.                                  * or WithdrawnState. */
  881. {
  882.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  883.     ULONG flags = 0;
  884.  
  885. #ifdef VERBOSE
  886.     SWP pos;
  887.  
  888.     printf("TkpWmSetState %s winPtr %x state %s\n",
  889.            wmPtr->flags & WM_NEVER_MAPPED ? "WM_NEVER_MAPPED" : "mapped",
  890.            winPtr, state == IconicState ? "IconicState"
  891.                          : (state == ZoomState ? "ZoomState"
  892.                                   : (state == NormalState ? "NormalState"
  893.                                            : "WithdrawnState" )));
  894. #endif
  895.  
  896.     if (wmPtr->flags & WM_NEVER_MAPPED) {
  897.         wmPtr->hints.initial_state = state;
  898.         return;
  899.     }
  900.  
  901.     if (wmPtr->flags & WM_UPDATE_PENDING) {
  902.         Tk_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
  903.     }
  904.     UpdateGeometryInfo((ClientData) winPtr);
  905.  
  906. #ifdef VERBOSE
  907.     rc = WinQueryWindowPos(wmPtr->wrapper, &pos);
  908.     if (rc != TRUE) {
  909.         printf("TkpWmSetState win %x h %x %s oldpos ERROR %x (%d,%d;%dx%d)\n",
  910.                winPtr, wmPtr->wrapper,
  911.                state == NormalState ? "NormalState" : (state == IconicState ?
  912.                "IconicState" : (state == ZoomState ? "ZoomState" :
  913.                (state == WithdrawnState ? "WithdrawnState" : "unknown"))),
  914.                WinGetLastError(TclOS2GetHAB()),
  915.                pos.x, pos.y, pos.cx, pos.cy);
  916.     } else {
  917.         printf("TkpWmSetState win %x h %x %s, oldpos OK (%d,%d;%dx%d)\n",
  918.                winPtr, wmPtr->wrapper,
  919.                state == NormalState ? "NormalState" : (state == IconicState ?
  920.                "IconicState" : (state == ZoomState ? "ZoomState" :
  921.                (state == WithdrawnState ? "WithdrawnState" : "unknown"))),
  922.                pos.x, pos.y, pos.cx, pos.cy);
  923.     }
  924. #endif
  925.  
  926.     wmPtr->flags |= WM_SYNC_PENDING;
  927.     if (state == WithdrawnState) {
  928.         /*
  929.         rc = WinShowWindow(wmPtr->wrapper, FALSE);
  930. #ifdef VERBOSE
  931.         if (rc==TRUE) printf("    WinShowWindow FALSE %x OK\n", wmPtr->wrapper);
  932.         else printf("    WinShowWindow FALSE %x ERROR: %x\n", wmPtr->wrapper,
  933.                     WinGetLastError(TclOS2GetHAB()));
  934. #endif
  935.         */
  936.         flags |= SWP_HIDE;
  937.     } else if (state == IconicState) {
  938.         flags |= SWP_MINIMIZE | SWP_SHOW;
  939.     } else if (state == NormalState) {
  940.         /*
  941.         rc = WinShowWindow(wmPtr->wrapper, TRUE);
  942. #ifdef VERBOSE
  943.         if (rc==TRUE) {
  944.             printf("    WinShowWindow TRUE %x OK\n", wmPtr->wrapper);
  945.         }
  946.         else {
  947.             printf("    WinShowWindow TRUE %x ERROR: %x\n", wmPtr->wrapper,
  948.                     WinGetLastError(TclOS2GetHAB()));
  949.         }
  950. #endif
  951.         */
  952.         flags |= SWP_RESTORE | SWP_SHOW | SWP_ZORDER;
  953.     } else if (state == ZoomState) {
  954.         flags |= SWP_MAXIMIZE | SWP_SHOW | SWP_ZORDER;
  955.     }
  956.     if (flags != 0) {
  957. #ifdef VERBOSE
  958.         printf("    before WinSetWindowPos (%x) %x\n", flags, wmPtr->wrapper);
  959.         fflush(stdout);
  960. #endif
  961.         rc = WinSetWindowPos(wmPtr->wrapper, HWND_TOP, 0L, 0L, 0L, 0L, flags);
  962. #ifdef VERBOSE
  963.         if (rc==TRUE) printf("    WinSetWindowPos (%x) %x OK\n", flags,
  964.                              wmPtr->wrapper);
  965.         else printf("    WinSetWindowPos (%x) %x ERROR: %x\n", flags,
  966.                     wmPtr->wrapper, WinGetLastError(TclOS2GetHAB()));
  967. #endif
  968.     }
  969.  
  970.     /* If applicable, add to/remove from task list */
  971.     if ((wmPtr->exStyle & FCF_TASKLIST) && wmPtr->wrapper != NULLHANDLE) {
  972.         HSWITCH hSwitch;
  973.         SWCNTRL switchData;
  974.         hSwitch = WinQuerySwitchHandle(wmPtr->wrapper, 0);
  975. #ifdef VERBOSE
  976.         if (hSwitch == NULLHANDLE) {
  977.             printf("WinQuerySwitchHandle %x ERROR %x\n", wmPtr->wrapper,
  978.                    WinGetLastError(TclOS2GetHAB()));
  979.         } else {
  980.             printf("WinQuerySwitchHandle %x OK:%x\n", wmPtr->wrapper, hSwitch);
  981.         }
  982. #endif
  983.         if (hSwitch == NULLHANDLE) goto end;
  984.         rc = WinQuerySwitchEntry(hSwitch, &switchData);
  985. #ifdef VERBOSE
  986.         if (rc != 0) {
  987.             printf("WinQuerySwitchEntry %x ERROR %x\n", hSwitch,
  988.                    WinGetLastError(TclOS2GetHAB()));
  989.         } else {
  990.             printf("WinQuerySwitchEntry %x OK\n", hSwitch);
  991.         }
  992. #endif
  993.         if (rc != 0) goto end;
  994.         if (state == WithdrawnState) {
  995.             /* Set visibility off */
  996.             switchData.uchVisibility = SWL_INVISIBLE;
  997. /*
  998. */
  999.         } else {
  1000.             /* Set visibility on */
  1001.             switchData.uchVisibility = SWL_VISIBLE;
  1002.         }
  1003.         rc = WinChangeSwitchEntry(hSwitch, &switchData);
  1004. #ifdef VERBOSE
  1005.         if (rc != 0) {
  1006.             printf("WinChangeSwitchEntry %x ERROR %x\n", hSwitch,
  1007.                    WinGetLastError(TclOS2GetHAB()));
  1008.         } else {
  1009.             printf("WinChangeSwitchEntry %x OK\n", hSwitch);
  1010.         }
  1011. #endif
  1012.     }
  1013.  
  1014. end:
  1015.     wmPtr->flags &= ~WM_SYNC_PENDING;
  1016. #ifdef VERBOSE
  1017.     WinQueryWindowPos(wmPtr->wrapper, &pos);
  1018.     printf("TkpWmSetState %x, newpos (%d,%d;%dx%d)\n", wmPtr->wrapper,
  1019.            pos.x, pos.y, pos.cx, pos.cy);
  1020. #endif
  1021. }
  1022.  
  1023. /*
  1024.  *--------------------------------------------------------------
  1025.  *
  1026.  * TkWmDeadWindow --
  1027.  *
  1028.  *    This procedure is invoked when a top-level window is
  1029.  *    about to be deleted.  It cleans up the wm-related data
  1030.  *    structures for the window.
  1031.  *
  1032.  * Results:
  1033.  *    None.
  1034.  *
  1035.  * Side effects:
  1036.  *    The WmInfo structure for winPtr gets freed up.
  1037.  *
  1038.  *--------------------------------------------------------------
  1039.  */
  1040.  
  1041. void
  1042. TkWmDeadWindow(winPtr)
  1043.     TkWindow *winPtr;        /* Top-level window that's being deleted. */
  1044. {
  1045.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  1046.     WmInfo *wmPtr2;
  1047.  
  1048.     if (wmPtr == NULL) {
  1049. #ifdef VERBOSE
  1050.         printf("TkWmDeadWindow, null wmPtr\n");
  1051. #endif
  1052.         return;
  1053.     }
  1054. #ifdef VERBOSE
  1055.     printf("TkWmDeadWindow\n");
  1056. #endif
  1057.  
  1058.     /*
  1059.      * Clean up event related window info.
  1060.      */
  1061.  
  1062.     if (firstWmPtr == wmPtr) {
  1063.         firstWmPtr = wmPtr->nextPtr;
  1064.     } else {
  1065.         register WmInfo *prevPtr;
  1066.  
  1067.         for (prevPtr = firstWmPtr; ; prevPtr = prevPtr->nextPtr) {
  1068.             if (prevPtr == NULL) {
  1069.                 panic("couldn't unlink window in TkWmDeadWindow");
  1070.             }
  1071.             if (prevPtr->nextPtr == wmPtr) {
  1072.                 prevPtr->nextPtr = wmPtr->nextPtr;
  1073.                 break;
  1074.             }
  1075.         }
  1076.     }
  1077.  
  1078.     /*
  1079.      * Reset all transient windows whose master is the dead window.
  1080.      */
  1081.     for (wmPtr2 = firstWmPtr; wmPtr2 != NULL; wmPtr2 = wmPtr2->nextPtr) {
  1082.         if (wmPtr2->masterPtr == winPtr) {
  1083.             wmPtr2->masterPtr = NULL;
  1084.             if ((wmPtr2->wrapper != None)
  1085.                     && !(wmPtr2->flags & (WM_NEVER_MAPPED))) {
  1086.                 UpdateWrapper(wmPtr2->winPtr);
  1087.             }
  1088.         }
  1089.     }
  1090.  
  1091.     if (wmPtr->hints.flags & IconPixmapHint) {
  1092.         Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
  1093.     }
  1094.     if (wmPtr->hints.flags & IconMaskHint) {
  1095.         Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);
  1096.     }
  1097.     if (wmPtr->leaderName != NULL) {
  1098.         ckfree(wmPtr->leaderName);
  1099.     }
  1100.     if (wmPtr->icon != NULL) {
  1101.         wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
  1102.         wmPtr2->iconFor = NULL;
  1103.     }
  1104.     if (wmPtr->iconFor != NULL) {
  1105.         wmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr;
  1106.         wmPtr2->icon = NULL;
  1107.         wmPtr2->hints.flags &= ~IconWindowHint;
  1108.     }
  1109.     while (wmPtr->protPtr != NULL) {
  1110.         ProtocolHandler *protPtr;
  1111.  
  1112.         protPtr = wmPtr->protPtr;
  1113.         wmPtr->protPtr = protPtr->nextPtr;
  1114.         Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC);
  1115.     }
  1116.     if (wmPtr->cmdArgv != NULL) {
  1117.         ckfree((char *) wmPtr->cmdArgv);
  1118.     }
  1119.     if (wmPtr->clientMachine != NULL) {
  1120.         ckfree((char *) wmPtr->clientMachine);
  1121.     }
  1122.     if (wmPtr->flags & WM_UPDATE_PENDING) {
  1123.         Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
  1124.     }
  1125.  
  1126.     /*
  1127.      * Destroy the decorative frame window.
  1128.      */
  1129.  
  1130.     if (!(winPtr->flags & TK_EMBEDDED)) {
  1131.         if (wmPtr->wrapper != NULLHANDLE) {
  1132.             WinDestroyWindow(wmPtr->wrapper);
  1133.         } else {
  1134.             WinDestroyWindow(Tk_GetHWND(winPtr->window));
  1135.         }
  1136.     }
  1137.     ckfree((char *) wmPtr);
  1138. #ifdef VERBOSE
  1139.     printf("TkWmDeadWindow freed wmPtr %x\n", wmPtr);
  1140. #endif
  1141.     winPtr->wmInfoPtr = NULL;
  1142. }
  1143.  
  1144. /*
  1145.  *--------------------------------------------------------------
  1146.  *
  1147.  * TkWmSetClass --
  1148.  *
  1149.  *    This procedure is invoked whenever a top-level window's
  1150.  *    class is changed.  If the window has been mapped then this
  1151.  *    procedure updates the window manager property for the
  1152.  *    class.  If the window hasn't been mapped, the update is
  1153.  *    deferred until just before the first mapping.
  1154.  *
  1155.  * Results:
  1156.  *    None.
  1157.  *
  1158.  * Side effects:
  1159.  *    A window property may get updated.
  1160.  *
  1161.  *--------------------------------------------------------------
  1162.  */
  1163.  
  1164. void
  1165. TkWmSetClass(winPtr)
  1166.     TkWindow *winPtr;        /* Newly-created top-level window. */
  1167. {
  1168.     return;
  1169. }
  1170.  
  1171. /*
  1172.  *----------------------------------------------------------------------
  1173.  *
  1174.  * Tk_WmCmd --
  1175.  *
  1176.  *    This procedure is invoked to process the "wm" Tcl command.
  1177.  *    See the user documentation for details on what it does.
  1178.  *
  1179.  * Results:
  1180.  *    A standard Tcl result.
  1181.  *
  1182.  * Side effects:
  1183.  *    See the user documentation.
  1184.  *
  1185.  *----------------------------------------------------------------------
  1186.  */
  1187.  
  1188.         /* ARGSUSED */
  1189. int
  1190. Tk_WmCmd(clientData, interp, argc, argv)
  1191.     ClientData clientData;    /* Main window associated with
  1192.                      * interpreter. */
  1193.     Tcl_Interp *interp;        /* Current interpreter. */
  1194.     int argc;            /* Number of arguments. */
  1195.     char **argv;        /* Argument strings. */
  1196. {
  1197.     Tk_Window tkwin = (Tk_Window) clientData;
  1198.     TkWindow *winPtr;
  1199.     register WmInfo *wmPtr;
  1200.     int c;
  1201.     size_t length;
  1202.  
  1203. #ifdef VERBOSE
  1204.     printf("Tk_WmCmd\n");
  1205. #endif
  1206.  
  1207.     if (argc < 2) {
  1208.         wrongNumArgs:
  1209.         Tcl_AppendResult(interp, "wrong # args: should be \"",
  1210.                 argv[0], " option window ?arg ...?\"", (char *) NULL);
  1211.         return TCL_ERROR;
  1212.     }
  1213.     c = argv[1][0];
  1214.     length = strlen(argv[1]);
  1215.     if ((c == 't') && (strncmp(argv[1], "tracing", length) == 0)
  1216.             && (length >= 3)) {
  1217.         if ((argc != 2) && (argc != 3)) {
  1218.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1219.                     argv[0], " tracing ?boolean?\"", (char *) NULL);
  1220.             return TCL_ERROR;
  1221.         }
  1222.         if (argc == 2) {
  1223.             interp->result = (wmTracing) ? "on" : "off";
  1224.             return TCL_OK;
  1225.         }
  1226.         return Tcl_GetBoolean(interp, argv[2], &wmTracing);
  1227.     }
  1228.  
  1229.     if (argc < 3) {
  1230.         goto wrongNumArgs;
  1231.     }
  1232. #ifdef VERBOSE
  1233.     printf("   %s %s %s\n", argv[0], argv[1], argv[2]);
  1234. #endif
  1235.     winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2], tkwin);
  1236.     if (winPtr == NULL) {
  1237.         return TCL_ERROR;
  1238.     }
  1239.     if (!(winPtr->flags & TK_TOP_LEVEL)) {
  1240.         Tcl_AppendResult(interp, "window \"", winPtr->pathName,
  1241.                 "\" isn't a top-level window", (char *) NULL);
  1242.         return TCL_ERROR;
  1243.     }
  1244.     wmPtr = winPtr->wmInfoPtr;
  1245.     if ((c == 'a') && (strncmp(argv[1], "aspect", length) == 0)) {
  1246.         int numer1, denom1, numer2, denom2;
  1247.  
  1248.         if ((argc != 3) && (argc != 7)) {
  1249.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1250.                     argv[0], " aspect window ?minNumer minDenom ",
  1251.                     "maxNumer maxDenom?\"", (char *) NULL);
  1252.             return TCL_ERROR;
  1253.         }
  1254.         if (argc == 3) {
  1255.             if (wmPtr->sizeHintsFlags & PAspect) {
  1256.                 sprintf(interp->result, "%d %d %d %d", wmPtr->minAspect.x,
  1257.                         wmPtr->minAspect.y, wmPtr->maxAspect.x,
  1258.                         wmPtr->maxAspect.y);
  1259.             }
  1260.             return TCL_OK;
  1261.         }
  1262.         if (*argv[3] == '\0') {
  1263.             wmPtr->sizeHintsFlags &= ~PAspect;
  1264.         } else {
  1265.             if ((Tcl_GetInt(interp, argv[3], &numer1) != TCL_OK)
  1266.                     || (Tcl_GetInt(interp, argv[4], &denom1) != TCL_OK)
  1267.                     || (Tcl_GetInt(interp, argv[5], &numer2) != TCL_OK)
  1268.                     || (Tcl_GetInt(interp, argv[6], &denom2) != TCL_OK)) {
  1269.                 return TCL_ERROR;
  1270.             }
  1271.             if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) ||
  1272.                     (denom2 <= 0)) {
  1273.                 interp->result = "aspect number can't be <= 0";
  1274.                 return TCL_ERROR;
  1275.             }
  1276.             wmPtr->minAspect.x = numer1;
  1277.             wmPtr->minAspect.y = denom1;
  1278.             wmPtr->maxAspect.x = numer2;
  1279.             wmPtr->maxAspect.y = denom2;
  1280.             wmPtr->sizeHintsFlags |= PAspect;
  1281.         }
  1282.         goto updateGeom;
  1283.     } else if ((c == 'c') && (strncmp(argv[1], "client", length) == 0)
  1284.             && (length >= 2)) {
  1285.         if ((argc != 3) && (argc != 4)) {
  1286.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1287.                     argv[0], " client window ?name?\"",
  1288.                     (char *) NULL);
  1289.             return TCL_ERROR;
  1290.         }
  1291.         if (argc == 3) {
  1292.             if (wmPtr->clientMachine != NULL) {
  1293.                 interp->result = wmPtr->clientMachine;
  1294.             }
  1295.             return TCL_OK;
  1296.         }
  1297.         if (argv[3][0] == 0) {
  1298.             if (wmPtr->clientMachine != NULL) {
  1299.                 ckfree((char *) wmPtr->clientMachine);
  1300.                 wmPtr->clientMachine = NULL;
  1301.                 if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  1302.                     XDeleteProperty(winPtr->display, winPtr->window,
  1303.                             Tk_InternAtom((Tk_Window) winPtr,
  1304.                             "WM_CLIENT_MACHINE"));
  1305.                 }
  1306.             }
  1307.             return TCL_OK;
  1308.         }
  1309.         if (wmPtr->clientMachine != NULL) {
  1310.             ckfree((char *) wmPtr->clientMachine);
  1311.         }
  1312.         wmPtr->clientMachine = (char *)
  1313.                 ckalloc((unsigned) (strlen(argv[3]) + 1));
  1314.         strcpy(wmPtr->clientMachine, argv[3]);
  1315.         if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  1316.             XTextProperty textProp;
  1317.             if (XStringListToTextProperty(&wmPtr->clientMachine, 1, &textProp)
  1318.                     != 0) {
  1319.                 XSetWMClientMachine(winPtr->display, winPtr->window,
  1320.                     &textProp);
  1321.             XFree((char *) textProp.value);
  1322.             }
  1323.         }
  1324.     } else if ((c == 'c') && (strncmp(argv[1], "colormapwindows", length) == 0)
  1325.             && (length >= 3)) {
  1326.         TkWindow **cmapList;
  1327.         TkWindow *winPtr2;
  1328.         int i, windowArgc, gotToplevel = 0;
  1329.         char **windowArgv;
  1330.  
  1331.         if ((argc != 3) && (argc != 4)) {
  1332.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1333.                 argv[0], " colormapwindows window ?windowList?\"",
  1334.                 (char *) NULL);
  1335.             return TCL_ERROR;
  1336.         }
  1337.         if (argc == 3) {
  1338.             Tk_MakeWindowExist((Tk_Window) winPtr);
  1339.             for (i = 0; i < wmPtr->cmapCount; i++) {
  1340.             if ((i == (wmPtr->cmapCount-1))
  1341.                 && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) {
  1342.                 break;
  1343.             }
  1344.             Tcl_AppendElement(interp, wmPtr->cmapList[i]->pathName);
  1345.             }
  1346.             return TCL_OK;
  1347.         }
  1348.         if (Tcl_SplitList(interp, argv[3], &windowArgc, &windowArgv)
  1349.             != TCL_OK) {
  1350.             return TCL_ERROR;
  1351.         }
  1352.         cmapList = (TkWindow **) ckalloc((unsigned)
  1353.             ((windowArgc+1)*sizeof(TkWindow*)));
  1354.         for (i = 0; i < windowArgc; i++) {
  1355.             winPtr2 = (TkWindow *) Tk_NameToWindow(interp, windowArgv[i],
  1356.                 tkwin);
  1357.             if (winPtr2 == NULL) {
  1358.             ckfree((char *) cmapList);
  1359.             ckfree((char *) windowArgv);
  1360.             return TCL_ERROR;
  1361.             }
  1362.             if (winPtr2 == winPtr) {
  1363.             gotToplevel = 1;
  1364.             }
  1365.             if (winPtr2->window == None) {
  1366.             Tk_MakeWindowExist((Tk_Window) winPtr2);
  1367.             }
  1368.             cmapList[i] = winPtr2;
  1369. #ifdef VERBOSE
  1370.             printf("    cmaplist[%d] = %s\n", i, winPtr2->pathName);
  1371. #endif
  1372.         }
  1373.         if (!gotToplevel) {
  1374.             wmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP;
  1375.             cmapList[windowArgc] = winPtr;
  1376. #ifdef VERBOSE
  1377.             printf("    cmapList[%d] = %s\n", windowArgc, winPtr->pathName);
  1378. #endif
  1379.             windowArgc++;
  1380.         } else {
  1381.             wmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP;
  1382.         }
  1383.         wmPtr->flags |= WM_COLORMAPS_EXPLICIT;
  1384.         if (wmPtr->cmapList != NULL) {
  1385.             ckfree((char *)wmPtr->cmapList);
  1386.         }
  1387.         wmPtr->cmapList = cmapList;
  1388.         wmPtr->cmapCount = windowArgc;
  1389.         ckfree((char *) windowArgv);
  1390.  
  1391.         /*
  1392.          * Now we need to force the updated colormaps to be installed.
  1393.          */
  1394.  
  1395.         if (wmPtr == foregroundWmPtr) {
  1396.             /* WM_QUERYNEWPALETTE -> WM_REALIZEPALETTE + focus notification */
  1397.             InstallColormaps(wmPtr->wrapper, WM_REALIZEPALETTE, 1);
  1398.         } else {
  1399.             /* WM_PALETTECHANGED -> WM_REALIZEPALETTE + focus notification */
  1400.             InstallColormaps(wmPtr->wrapper, WM_REALIZEPALETTE, 0);
  1401.         }
  1402.         return TCL_OK;
  1403.     } else if ((c == 'c') && (strncmp(argv[1], "command", length) == 0)
  1404.             && (length >= 3)) {
  1405.         int cmdArgc;
  1406.         char **cmdArgv;
  1407.  
  1408.         if ((argc != 3) && (argc != 4)) {
  1409.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1410.                 argv[0], " command window ?value?\"",
  1411.                 (char *) NULL);
  1412.             return TCL_ERROR;
  1413.         }
  1414.         if (argc == 3) {
  1415.             if (wmPtr->cmdArgv != NULL) {
  1416.             interp->result = Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv);
  1417.             interp->freeProc = TCL_DYNAMIC;
  1418.             }
  1419.             return TCL_OK;
  1420.         }
  1421.         if (argv[3][0] == 0) {
  1422.             if (wmPtr->cmdArgv != NULL) {
  1423.             ckfree((char *) wmPtr->cmdArgv);
  1424.             wmPtr->cmdArgv = NULL;
  1425.             if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  1426.                 XDeleteProperty(winPtr->display, winPtr->window,
  1427.                     Tk_InternAtom((Tk_Window) winPtr, "WM_COMMAND"));
  1428.             }
  1429.             }
  1430.             return TCL_OK;
  1431.         }
  1432.         if (Tcl_SplitList(interp, argv[3], &cmdArgc, &cmdArgv) != TCL_OK) {
  1433.             return TCL_ERROR;
  1434.         }
  1435.         if (wmPtr->cmdArgv != NULL) {
  1436.             ckfree((char *) wmPtr->cmdArgv);
  1437.         }
  1438.         wmPtr->cmdArgc = cmdArgc;
  1439.         wmPtr->cmdArgv = cmdArgv;
  1440.         if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  1441.             XSetCommand(winPtr->display, winPtr->window, cmdArgv, cmdArgc);
  1442.         }
  1443.     } else if ((c == 'd') && (strncmp(argv[1], "deiconify", length) == 0)) {
  1444.         if (argc != 3) {
  1445.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1446.                 argv[0], " deiconify window\"", (char *) NULL);
  1447.             return TCL_ERROR;
  1448.         }
  1449.         if (wmPtr->iconFor != NULL) {
  1450.             Tcl_AppendResult(interp, "can't deiconify ", argv[2],
  1451.                 ": it is an icon for ", winPtr->pathName, (char *) NULL);
  1452.             return TCL_ERROR;
  1453.         }
  1454.         if (winPtr->flags & TK_EMBEDDED) {
  1455.             Tcl_AppendResult(interp, "can't deiconify ", winPtr->pathName,
  1456.                     ": it is an embedded window", (char *) NULL);
  1457.             return TCL_ERROR;
  1458.         }
  1459.         TkpWmSetState(winPtr, NormalState);
  1460.     } else if ((c == 'f') && (strncmp(argv[1], "focusmodel", length) == 0)
  1461.             && (length >= 2)) {
  1462.         if ((argc != 3) && (argc != 4)) {
  1463.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1464.                 argv[0], " focusmodel window ?active|passive?\"",
  1465.                 (char *) NULL);
  1466.             return TCL_ERROR;
  1467.         }
  1468.         if (argc == 3) {
  1469.             interp->result = wmPtr->hints.input ? "passive" : "active";
  1470.             return TCL_OK;
  1471.         }
  1472.         c = argv[3][0];
  1473.         length = strlen(argv[3]);
  1474.         if ((c == 'a') && (strncmp(argv[3], "active", length) == 0)) {
  1475.             wmPtr->hints.input = False;
  1476.         } else if ((c == 'p') && (strncmp(argv[3], "passive", length) == 0)) {
  1477.             wmPtr->hints.input = True;
  1478.         } else {
  1479.             Tcl_AppendResult(interp, "bad argument \"", argv[3],
  1480.                 "\": must be active or passive", (char *) NULL);
  1481.             return TCL_ERROR;
  1482.         }
  1483.     } else if ((c == 'f') && (strncmp(argv[1], "frame", length) == 0)
  1484.             && (length >= 2)) {
  1485.         HWND hwnd;
  1486.  
  1487.         if (argc != 3) {
  1488.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1489.                 argv[0], " frame window\"", (char *) NULL);
  1490.             return TCL_ERROR;
  1491.         }
  1492.         if (Tk_WindowId((Tk_Window) winPtr) == None) {
  1493.             Tk_MakeWindowExist((Tk_Window) winPtr);
  1494.         }
  1495.         hwnd = wmPtr->wrapper;
  1496.         if (hwnd == NULLHANDLE) {
  1497.             hwnd = Tk_GetHWND(Tk_WindowId((Tk_Window) winPtr));
  1498.         }
  1499.         sprintf(interp->result, "0x%x", (unsigned int) hwnd);
  1500.     } else if ((c == 'g') && (strncmp(argv[1], "geometry", length) == 0)
  1501.             && (length >= 2)) {
  1502.         char xSign, ySign;
  1503.         int width, height;
  1504.  
  1505.         if ((argc != 3) && (argc != 4)) {
  1506.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1507.                 argv[0], " geometry window ?newGeometry?\"",
  1508.                 (char *) NULL);
  1509.             return TCL_ERROR;
  1510.         }
  1511.         if (argc == 3) {
  1512.             xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+';
  1513.             ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+';
  1514.             if (wmPtr->gridWin != NULL) {
  1515.             width = wmPtr->reqGridWidth + (winPtr->changes.width
  1516.                 - winPtr->reqWidth)/wmPtr->widthInc;
  1517.             height = wmPtr->reqGridHeight + (winPtr->changes.height
  1518.                 - winPtr->reqHeight)/wmPtr->heightInc;
  1519.             } else {
  1520.             width = winPtr->changes.width;
  1521.             height = winPtr->changes.height;
  1522.             }
  1523.             sprintf(interp->result, "%dx%d%c%d%c%d", width, height,
  1524.                 xSign, wmPtr->x, ySign, wmPtr->y);
  1525.             return TCL_OK;
  1526.         }
  1527.         if (*argv[3] == '\0') {
  1528.             wmPtr->width = -1;
  1529.             wmPtr->height = -1;
  1530.             goto updateGeom;
  1531.         }
  1532.         return ParseGeometry(interp, argv[3], winPtr);
  1533.     } else if ((c == 'g') && (strncmp(argv[1], "grid", length) == 0)
  1534.             && (length >= 3)) {
  1535.         int reqWidth, reqHeight, widthInc, heightInc;
  1536.  
  1537.         if ((argc != 3) && (argc != 7)) {
  1538.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1539.                 argv[0], " grid window ?baseWidth baseHeight ",
  1540.                 "widthInc heightInc?\"", (char *) NULL);
  1541.             return TCL_ERROR;
  1542.         }
  1543.         if (argc == 3) {
  1544.             if (wmPtr->sizeHintsFlags & PBaseSize) {
  1545.             sprintf(interp->result, "%d %d %d %d", wmPtr->reqGridWidth,
  1546.                 wmPtr->reqGridHeight, wmPtr->widthInc,
  1547.                 wmPtr->heightInc);
  1548.             }
  1549.             return TCL_OK;
  1550.         }
  1551.         if (*argv[3] == '\0') {
  1552.             /*
  1553.              * Turn off gridding and reset the width and height
  1554.              * to make sense as ungridded numbers.
  1555.              */
  1556.  
  1557.             wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc);
  1558.             if (wmPtr->width != -1) {
  1559.             wmPtr->width = winPtr->reqWidth + (wmPtr->width
  1560.                 - wmPtr->reqGridWidth)*wmPtr->widthInc;
  1561.             wmPtr->height = winPtr->reqHeight + (wmPtr->height
  1562.                 - wmPtr->reqGridHeight)*wmPtr->heightInc;
  1563.             }
  1564.             wmPtr->widthInc = 1;
  1565.             wmPtr->heightInc = 1;
  1566.         } else {
  1567.             if ((Tcl_GetInt(interp, argv[3], &reqWidth) != TCL_OK)
  1568.                 || (Tcl_GetInt(interp, argv[4], &reqHeight) != TCL_OK)
  1569.                 || (Tcl_GetInt(interp, argv[5], &widthInc) != TCL_OK)
  1570.                 || (Tcl_GetInt(interp, argv[6], &heightInc) != TCL_OK)) {
  1571.             return TCL_ERROR;
  1572.             }
  1573.             if (reqWidth < 0) {
  1574.             interp->result = "baseWidth can't be < 0";
  1575.             return TCL_ERROR;
  1576.             }
  1577.             if (reqHeight < 0) {
  1578.             interp->result = "baseHeight can't be < 0";
  1579.             return TCL_ERROR;
  1580.             }
  1581.             if (widthInc < 0) {
  1582.             interp->result = "widthInc can't be < 0";
  1583.             return TCL_ERROR;
  1584.             }
  1585.             if (heightInc < 0) {
  1586.             interp->result = "heightInc can't be < 0";
  1587.             return TCL_ERROR;
  1588.             }
  1589.             Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,
  1590.                 heightInc);
  1591.         }
  1592.         goto updateGeom;
  1593.     } else if ((c == 'g') && (strncmp(argv[1], "group", length) == 0)
  1594.             && (length >= 3)) {
  1595.         Tk_Window tkwin2;
  1596.  
  1597.         if ((argc != 3) && (argc != 4)) {
  1598.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1599.                 argv[0], " group window ?pathName?\"",
  1600.                 (char *) NULL);
  1601.             return TCL_ERROR;
  1602.         }
  1603.         if (argc == 3) {
  1604.             if (wmPtr->hints.flags & WindowGroupHint) {
  1605.             interp->result = wmPtr->leaderName;
  1606.             }
  1607.             return TCL_OK;
  1608.         }
  1609.         if (*argv[3] == '\0') {
  1610.             wmPtr->hints.flags &= ~WindowGroupHint;
  1611.             if (wmPtr->leaderName != NULL) {
  1612.                 ckfree(wmPtr->leaderName);
  1613.             }
  1614.             wmPtr->leaderName = NULL;
  1615.         } else {
  1616.             tkwin2 = Tk_NameToWindow(interp, argv[3], tkwin);
  1617.             if (tkwin2 == NULL) {
  1618.             return TCL_ERROR;
  1619.             }
  1620.             Tk_MakeWindowExist(tkwin2);
  1621.             wmPtr->hints.window_group = Tk_WindowId(tkwin2);
  1622.             wmPtr->hints.flags |= WindowGroupHint;
  1623.             wmPtr->leaderName = ckalloc((unsigned) (strlen(argv[3])+1));
  1624.             strcpy(wmPtr->leaderName, argv[3]);
  1625.         }
  1626.     } else if ((c == 'i') && (strncmp(argv[1], "iconbitmap", length) == 0)
  1627.             && (length >= 5)) {
  1628.         Pixmap pixmap;
  1629.  
  1630.         if ((argc != 3) && (argc != 4)) {
  1631.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1632.                 argv[0], " iconbitmap window ?bitmap?\"",
  1633.                 (char *) NULL);
  1634.             return TCL_ERROR;
  1635.         }
  1636.         if (argc == 3) {
  1637.             if (wmPtr->hints.flags & IconPixmapHint) {
  1638.             interp->result = Tk_NameOfBitmap(winPtr->display,
  1639.                 wmPtr->hints.icon_pixmap);
  1640.             }
  1641.             return TCL_OK;
  1642.         }
  1643.         if (*argv[3] == '\0') {
  1644.             if (wmPtr->hints.icon_pixmap != None) {
  1645.             Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
  1646.             }
  1647.             wmPtr->hints.flags &= ~IconPixmapHint;
  1648.         } else {
  1649.             pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr,
  1650.                 Tk_GetUid(argv[3]));
  1651.             if (pixmap == None) {
  1652.             return TCL_ERROR;
  1653.             }
  1654.             wmPtr->hints.icon_pixmap = pixmap;
  1655.             wmPtr->hints.flags |= IconPixmapHint;
  1656.         }
  1657.     } else if ((c == 'i') && (strncmp(argv[1], "iconify", length) == 0)
  1658.             && (length >= 5)) {
  1659.         if (argc != 3) {
  1660.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1661.                 argv[0], " iconify window\"", (char *) NULL);
  1662.             return TCL_ERROR;
  1663.         }
  1664.         if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
  1665.             Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName,
  1666.                 "\": override-redirect flag is set", (char *) NULL);
  1667.             return TCL_ERROR;
  1668.         }
  1669.         if (wmPtr->masterPtr != NULL) {
  1670.             Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName,
  1671.                 "\": it is a transient", (char *) NULL);
  1672.             return TCL_ERROR;
  1673.         }
  1674.         if (wmPtr->iconFor != NULL) {
  1675.             Tcl_AppendResult(interp, "can't iconify ", argv[2],
  1676.                 ": it is an icon for ", winPtr->pathName, (char *) NULL);
  1677.             return TCL_ERROR;
  1678.         }
  1679.         if (winPtr->flags & TK_EMBEDDED) {
  1680.             Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName,
  1681.                     ": it is an embedded window", (char *) NULL);
  1682.             return TCL_ERROR;
  1683.         }
  1684.         TkpWmSetState(winPtr, IconicState);
  1685.     } else if ((c == 'i') && (strncmp(argv[1], "iconmask", length) == 0)
  1686.             && (length >= 5)) {
  1687.         Pixmap pixmap;
  1688.  
  1689.         if ((argc != 3) && (argc != 4)) {
  1690.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1691.                 argv[0], " iconmask window ?bitmap?\"",
  1692.                 (char *) NULL);
  1693.             return TCL_ERROR;
  1694.         }
  1695.         if (argc == 3) {
  1696.             if (wmPtr->hints.flags & IconMaskHint) {
  1697.             interp->result = Tk_NameOfBitmap(winPtr->display,
  1698.                 wmPtr->hints.icon_mask);
  1699.             }
  1700.             return TCL_OK;
  1701.         }
  1702.         if (*argv[3] == '\0') {
  1703.             if (wmPtr->hints.icon_mask != None) {
  1704.             Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);
  1705.             }
  1706.             wmPtr->hints.flags &= ~IconMaskHint;
  1707.         } else {
  1708.             pixmap = Tk_GetBitmap(interp, tkwin, Tk_GetUid(argv[3]));
  1709.             if (pixmap == None) {
  1710.             return TCL_ERROR;
  1711.             }
  1712.             wmPtr->hints.icon_mask = pixmap;
  1713.             wmPtr->hints.flags |= IconMaskHint;
  1714.         }
  1715.     } else if ((c == 'i') && (strncmp(argv[1], "iconname", length) == 0)
  1716.             && (length >= 5)) {
  1717.         if (argc > 4) {
  1718.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1719.                 argv[0], " iconname window ?newName?\"", (char *) NULL);
  1720.             return TCL_ERROR;
  1721.         }
  1722.         if (argc == 3) {
  1723.             interp->result = (wmPtr->iconName != NULL) ? wmPtr->iconName : "";
  1724.             return TCL_OK;
  1725.         } else {
  1726.             wmPtr->iconName = Tk_GetUid(argv[3]);
  1727.             if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  1728.             XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName);
  1729.             }
  1730.         }
  1731.     } else if ((c == 'i') && (strncmp(argv[1], "iconposition", length) == 0)
  1732.             && (length >= 5)) {
  1733.         int x, y;
  1734.  
  1735.         if ((argc != 3) && (argc != 5)) {
  1736.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1737.                 argv[0], " iconposition window ?x y?\"",
  1738.                 (char *) NULL);
  1739.             return TCL_ERROR;
  1740.         }
  1741.         if (argc == 3) {
  1742.             if (wmPtr->hints.flags & IconPositionHint) {
  1743.             sprintf(interp->result, "%d %d", wmPtr->hints.icon_x,
  1744.                 wmPtr->hints.icon_y);
  1745.             }
  1746.             return TCL_OK;
  1747.         }
  1748.         if (*argv[3] == '\0') {
  1749.             wmPtr->hints.flags &= ~IconPositionHint;
  1750.         } else {
  1751.             if ((Tcl_GetInt(interp, argv[3], &x) != TCL_OK)
  1752.                 || (Tcl_GetInt(interp, argv[4], &y) != TCL_OK)){
  1753.             return TCL_ERROR;
  1754.             }
  1755.             wmPtr->hints.icon_x = x;
  1756.             wmPtr->hints.icon_y = y;
  1757.             wmPtr->hints.flags |= IconPositionHint;
  1758.         }
  1759.     } else if ((c == 'i') && (strncmp(argv[1], "iconwindow", length) == 0)
  1760.             && (length >= 5)) {
  1761.         Tk_Window tkwin2;
  1762.         WmInfo *wmPtr2;
  1763.         XSetWindowAttributes atts;
  1764.  
  1765.         if ((argc != 3) && (argc != 4)) {
  1766.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1767.                 argv[0], " iconwindow window ?pathName?\"",
  1768.                 (char *) NULL);
  1769.             return TCL_ERROR;
  1770.         }
  1771.         if (argc == 3) {
  1772.             if (wmPtr->icon != NULL) {
  1773.             interp->result = Tk_PathName(wmPtr->icon);
  1774.             }
  1775.             return TCL_OK;
  1776.         }
  1777.         if (*argv[3] == '\0') {
  1778.             wmPtr->hints.flags &= ~IconWindowHint;
  1779.             if (wmPtr->icon != NULL) {
  1780.                 /*
  1781.                  * Let the window use button events again, then remove
  1782.                  * it as icon window.
  1783.                  */
  1784.  
  1785.                 atts.event_mask = Tk_Attributes(wmPtr->icon)->event_mask
  1786.                         | ButtonPressMask;
  1787.                 Tk_ChangeWindowAttributes(wmPtr->icon, CWEventMask, &atts);
  1788.             wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
  1789.             wmPtr2->iconFor = NULL;
  1790.             wmPtr2->hints.initial_state = WithdrawnState;
  1791.             }
  1792.             wmPtr->icon = NULL;
  1793.         } else {
  1794.             tkwin2 = Tk_NameToWindow(interp, argv[3], tkwin);
  1795.             if (tkwin2 == NULL) {
  1796.             return TCL_ERROR;
  1797.             }
  1798.             if (!Tk_IsTopLevel(tkwin2)) {
  1799.             Tcl_AppendResult(interp, "can't use ", argv[3],
  1800.                 " as icon window: not at top level", (char *) NULL);
  1801.             return TCL_ERROR;
  1802.             }
  1803.             wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;
  1804.             if (wmPtr2->iconFor != NULL) {
  1805.             Tcl_AppendResult(interp, argv[3], " is already an icon for ",
  1806.                 Tk_PathName(wmPtr2->iconFor), (char *) NULL);
  1807.             return TCL_ERROR;
  1808.             }
  1809.             if (wmPtr->icon != NULL) {
  1810.             WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
  1811.             wmPtr3->iconFor = NULL;
  1812.  
  1813.                 /*
  1814.                  * Let the window use button events again.
  1815.                  */
  1816.  
  1817.                 atts.event_mask = Tk_Attributes(wmPtr->icon)->event_mask
  1818.                         | ButtonPressMask;
  1819.                 Tk_ChangeWindowAttributes(wmPtr->icon, CWEventMask, &atts);
  1820.             }
  1821.  
  1822.             /*
  1823.              * Disable button events in the icon window:  some window
  1824.              * managers (like olvwm) want to get the events themselves,
  1825.              * but X only allows one application at a time to receive
  1826.              * button events for a window.
  1827.              */
  1828.  
  1829.             atts.event_mask = Tk_Attributes(tkwin2)->event_mask
  1830.                     & ~ButtonPressMask;
  1831.             Tk_ChangeWindowAttributes(tkwin2, CWEventMask, &atts);
  1832.             Tk_MakeWindowExist(tkwin2);
  1833.             wmPtr->hints.icon_window = Tk_WindowId(tkwin2);
  1834.             wmPtr->hints.flags |= IconWindowHint;
  1835.             wmPtr->icon = tkwin2;
  1836.             wmPtr2->iconFor = (Tk_Window) winPtr;
  1837.             if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
  1838.             if (XWithdrawWindow(Tk_Display(tkwin2), Tk_WindowId(tkwin2),
  1839.                 Tk_ScreenNumber(tkwin2)) == 0) {
  1840.                 interp->result =
  1841.                     "couldn't send withdraw message to window manager";
  1842. #ifdef VERBOSE
  1843.                     printf("calling XWithdrawWindow(%x, %x, %d)\n",
  1844.                            Tk_Display(tkwin2), Tk_WindowId(tkwin2),
  1845.                            Tk_ScreenNumber(tkwin2));
  1846. #endif
  1847.                 return TCL_ERROR;
  1848.             }
  1849.             }
  1850.         }
  1851.     } else if ((c == 'm') && (strncmp(argv[1], "maxsize", length) == 0)
  1852.             && (length >= 2)) {
  1853.         int width, height;
  1854.         if ((argc != 3) && (argc != 5)) {
  1855.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1856.                 argv[0], " maxsize window ?width height?\"",
  1857.                     (char *) NULL);
  1858.             return TCL_ERROR;
  1859.         }
  1860.         if (argc == 3) {
  1861.             GetMaxSize(wmPtr, &width, &height);
  1862.             sprintf(interp->result, "%d %d", width, height);
  1863.             return TCL_OK;
  1864.         }
  1865.         if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK)
  1866.             || (Tcl_GetInt(interp, argv[4], &height) != TCL_OK)) {
  1867.             return TCL_ERROR;
  1868.         }
  1869.         wmPtr->maxWidth = width;
  1870.         wmPtr->maxHeight = height;
  1871.         goto updateGeom;
  1872.     } else if ((c == 'm') && (strncmp(argv[1], "minsize", length) == 0)
  1873.             && (length >= 2)) {
  1874.         int width, height;
  1875.         if ((argc != 3) && (argc != 5)) {
  1876.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1877.                 argv[0], " minsize window ?width height?\"",
  1878.                     (char *) NULL);
  1879.             return TCL_ERROR;
  1880.         }
  1881.         if (argc == 3) {
  1882.             GetMinSize(wmPtr, &width, &height);
  1883. #ifdef VERBOSE
  1884.             printf("wm minsize returns %d %d\n", width, height);
  1885. #endif
  1886.             sprintf(interp->result, "%d %d", width, height);
  1887.             return TCL_OK;
  1888.         }
  1889.         if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK)
  1890.             || (Tcl_GetInt(interp, argv[4], &height) != TCL_OK)) {
  1891.             return TCL_ERROR;
  1892.         }
  1893.         wmPtr->minWidth = width;
  1894.         wmPtr->minHeight = height;
  1895. #ifdef VERBOSE
  1896.         printf("wm minsize %d %d set\n", width, height);
  1897. #endif
  1898.         goto updateGeom;
  1899.     } else if ((c == 'o')
  1900.             && (strncmp(argv[1], "overrideredirect", length) == 0)) {
  1901.         int boolean;
  1902.         XSetWindowAttributes atts;
  1903.  
  1904.         if ((argc != 3) && (argc != 4)) {
  1905.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1906.                 argv[0], " overrideredirect window ?boolean?\"",
  1907.                 (char *) NULL);
  1908.             return TCL_ERROR;
  1909.         }
  1910.         if (argc == 3) {
  1911.             if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
  1912.             interp->result = "1";
  1913.             } else {
  1914.             interp->result = "0";
  1915.             }
  1916.             return TCL_OK;
  1917.         }
  1918.         if (Tcl_GetBoolean(interp, argv[3], &boolean) != TCL_OK) {
  1919.             return TCL_ERROR;
  1920.         }
  1921.         atts.override_redirect = (boolean) ? True : False;
  1922.         Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect,
  1923.             &atts);
  1924.         if (!(wmPtr->flags & (WM_NEVER_MAPPED)
  1925.                 && !(winPtr->flags & TK_EMBEDDED))) {
  1926.             UpdateWrapper(winPtr);
  1927.         }
  1928.     } else if ((c == 'p') && (strncmp(argv[1], "positionfrom", length) == 0)
  1929.             && (length >= 2)) {
  1930.         if ((argc != 3) && (argc != 4)) {
  1931.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1932.                 argv[0], " positionfrom window ?user/program?\"",
  1933.                 (char *) NULL);
  1934.             return TCL_ERROR;
  1935.         }
  1936.         if (argc == 3) {
  1937.             if (wmPtr->sizeHintsFlags & USPosition) {
  1938.             interp->result = "user";
  1939.             } else if (wmPtr->sizeHintsFlags & PPosition) {
  1940.             interp->result = "program";
  1941.             }
  1942.             return TCL_OK;
  1943.         }
  1944.         if (*argv[3] == '\0') {
  1945.             wmPtr->sizeHintsFlags &= ~(USPosition|PPosition);
  1946.         } else {
  1947.             c = argv[3][0];
  1948.             length = strlen(argv[3]);
  1949.             if ((c == 'u') && (strncmp(argv[3], "user", length) == 0)) {
  1950.             wmPtr->sizeHintsFlags &= ~PPosition;
  1951.             wmPtr->sizeHintsFlags |= USPosition;
  1952.             } else if ((c == 'p')
  1953.                     && (strncmp(argv[3], "program", length) == 0)) {
  1954.             wmPtr->sizeHintsFlags &= ~USPosition;
  1955.             wmPtr->sizeHintsFlags |= PPosition;
  1956.             } else {
  1957.             Tcl_AppendResult(interp, "bad argument \"", argv[3],
  1958.                 "\": must be program or user", (char *) NULL);
  1959.             return TCL_ERROR;
  1960.             }
  1961.         }
  1962.         goto updateGeom;
  1963.     } else if ((c == 'p') && (strncmp(argv[1], "protocol", length) == 0)
  1964.             && (length >= 2)) {
  1965.         register ProtocolHandler *protPtr, *prevPtr;
  1966.         Atom protocol;
  1967.         int cmdLength;
  1968.  
  1969.         if ((argc < 3) || (argc > 5)) {
  1970.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  1971.                 argv[0], " protocol window ?name? ?command?\"",
  1972.                 (char *) NULL);
  1973.             return TCL_ERROR;
  1974.         }
  1975.         if (argc == 3) {
  1976.             /*
  1977.              * Return a list of all defined protocols for the window.
  1978.              */
  1979.             for (protPtr = wmPtr->protPtr; protPtr != NULL;
  1980.                 protPtr = protPtr->nextPtr) {
  1981.             Tcl_AppendElement(interp,
  1982.                 Tk_GetAtomName((Tk_Window) winPtr, protPtr->protocol));
  1983.             }
  1984.             return TCL_OK;
  1985.         }
  1986.         protocol = Tk_InternAtom((Tk_Window) winPtr, argv[3]);
  1987.         if (argc == 4) {
  1988.             /*
  1989.              * Return the command to handle a given protocol.
  1990.              */
  1991.             for (protPtr = wmPtr->protPtr; protPtr != NULL;
  1992.                 protPtr = protPtr->nextPtr) {
  1993.             if (protPtr->protocol == protocol) {
  1994.                 interp->result = protPtr->command;
  1995.                 return TCL_OK;
  1996.             }
  1997.             }
  1998.             return TCL_OK;
  1999.         }
  2000.  
  2001.         /*
  2002.          * Delete any current protocol handler, then create a new
  2003.          * one with the specified command, unless the command is
  2004.          * empty.
  2005.          */
  2006.  
  2007.         for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL;
  2008.             prevPtr = protPtr, protPtr = protPtr->nextPtr) {
  2009.             if (protPtr->protocol == protocol) {
  2010.             if (prevPtr == NULL) {
  2011.                 wmPtr->protPtr = protPtr->nextPtr;
  2012.             } else {
  2013.                 prevPtr->nextPtr = protPtr->nextPtr;
  2014.             }
  2015.             Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC);
  2016.             break;
  2017.             }
  2018.         }
  2019.         cmdLength = strlen(argv[4]);
  2020.         if (cmdLength > 0) {
  2021.             protPtr = (ProtocolHandler *) ckalloc(HANDLER_SIZE(cmdLength));
  2022.             protPtr->protocol = protocol;
  2023.             protPtr->nextPtr = wmPtr->protPtr;
  2024.             wmPtr->protPtr = protPtr;
  2025.             protPtr->interp = interp;
  2026.             strcpy(protPtr->command, argv[4]);
  2027.         }
  2028.     } else if ((c == 'r') && (strncmp(argv[1], "resizable", length) == 0)) {
  2029.         int width, height;
  2030.  
  2031.         if ((argc != 3) && (argc != 5)) {
  2032.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  2033.                     argv[0], " resizable window ?width height?\"",
  2034.                     (char *) NULL);
  2035.             return TCL_ERROR;
  2036.         }
  2037.         if (argc == 3) {
  2038.             sprintf(interp->result, "%d %d",
  2039.                     (wmPtr->flags  & WM_WIDTH_NOT_RESIZABLE) ? 0 : 1,
  2040.                     (wmPtr->flags  & WM_HEIGHT_NOT_RESIZABLE) ? 0 : 1);
  2041.             return TCL_OK;
  2042.         }
  2043.         if ((Tcl_GetBoolean(interp, argv[3], &width) != TCL_OK)
  2044.                 || (Tcl_GetBoolean(interp, argv[4], &height) != TCL_OK)) {
  2045.             return TCL_ERROR;
  2046.         }
  2047.         if (width) {
  2048.             wmPtr->flags &= ~WM_WIDTH_NOT_RESIZABLE;
  2049.         } else {
  2050.             wmPtr->flags |= WM_WIDTH_NOT_RESIZABLE;
  2051.         }
  2052.         if (height) {
  2053.             wmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE;
  2054.         } else {
  2055.             wmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE;
  2056.         }
  2057.         wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
  2058.         goto updateGeom;
  2059.     } else if ((c == 's') && (strncmp(argv[1], "sizefrom", length) == 0)
  2060.             && (length >= 2)) {
  2061.         if ((argc != 3) && (argc != 4)) {
  2062.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  2063.                 argv[0], " sizefrom window ?user|program?\"",
  2064.                 (char *) NULL);
  2065.             return TCL_ERROR;
  2066.         }
  2067.         if (argc == 3) {
  2068.             if (wmPtr->sizeHintsFlags & USSize) {
  2069.             interp->result = "user";
  2070.             } else if (wmPtr->sizeHintsFlags & PSize) {
  2071.             interp->result = "program";
  2072.             }
  2073.             return TCL_OK;
  2074.         }
  2075.         if (*argv[3] == '\0') {
  2076.             wmPtr->sizeHintsFlags &= ~(USSize|PSize);
  2077.         } else {
  2078.             c = argv[3][0];
  2079.             length = strlen(argv[3]);
  2080.             if ((c == 'u') && (strncmp(argv[3], "user", length) == 0)) {
  2081.             wmPtr->sizeHintsFlags &= ~PSize;
  2082.             wmPtr->sizeHintsFlags |= USSize;
  2083.             } else if ((c == 'p')
  2084.                 && (strncmp(argv[3], "program", length) == 0)) {
  2085.             wmPtr->sizeHintsFlags &= ~USSize;
  2086.             wmPtr->sizeHintsFlags |= PSize;
  2087.             } else {
  2088.             Tcl_AppendResult(interp, "bad argument \"", argv[3],
  2089.                 "\": must be program or user", (char *) NULL);
  2090.             return TCL_ERROR;
  2091.             }
  2092.         }
  2093.         goto updateGeom;
  2094.     } else if ((c == 's') && (strncmp(argv[1], "state", length) == 0)
  2095.             && (length >= 2)) {
  2096.         if (argc != 3) {
  2097.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  2098.                 argv[0], " state window\"", (char *) NULL);
  2099.             return TCL_ERROR;
  2100.         }
  2101.         if (wmPtr->iconFor != NULL) {
  2102.             interp->result = "icon";
  2103.         } else {
  2104.             switch (wmPtr->hints.initial_state) {
  2105.                 case NormalState:
  2106.                     interp->result = "normal";
  2107.                     break;
  2108.                 case IconicState:
  2109.                     interp->result = "iconic";
  2110.                     break;
  2111.                 case WithdrawnState:
  2112.                     interp->result = "withdrawn";
  2113.                     break;
  2114.                 case ZoomState:
  2115.                     interp->result = "zoomed";
  2116.                     break;
  2117.             }
  2118.         }
  2119.     } else if ((c == 't') && (strncmp(argv[1], "title", length) == 0)
  2120.             && (length >= 2)) {
  2121.         if (argc > 4) {
  2122.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  2123.                 argv[0], " title window ?newTitle?\"", (char *) NULL);
  2124.             return TCL_ERROR;
  2125.         }
  2126.         if (argc == 3) {
  2127.             interp->result = (wmPtr->titleUid != NULL) ? wmPtr->titleUid
  2128.                 : winPtr->nameUid;
  2129.             return TCL_OK;
  2130.         } else {
  2131.             wmPtr->titleUid = Tk_GetUid(argv[3]);
  2132.             if ((!(wmPtr->flags & WM_NEVER_MAPPED)) &&
  2133.                     wmPtr->wrapper != NULLHANDLE) {
  2134.                 HSWITCH hSwitch;
  2135.                 SWCNTRL switchData;
  2136.  
  2137.                 hSwitch = WinQuerySwitchHandle(wmPtr->wrapper, 0);
  2138. #ifdef VERBOSE
  2139.                 if (hSwitch == NULLHANDLE) {
  2140.                     printf("WinQuerySwitchHandle %x ERROR %x\n", wmPtr->wrapper,
  2141.                            WinGetLastError(TclOS2GetHAB()));
  2142.                 } else {
  2143.                     printf("WinQuerySwitchHandle %x OK:%x\n", wmPtr->wrapper,
  2144.                            hSwitch);
  2145.                 }
  2146. #endif
  2147.                 rc = WinQuerySwitchEntry(hSwitch, &switchData);
  2148. #ifdef VERBOSE
  2149.                 if (rc != 0) {
  2150.                     printf("WinQuerySwitchEntry %x ERROR %x\n", hSwitch,
  2151.                            WinGetLastError(TclOS2GetHAB()));
  2152.                 } else {
  2153.                     printf("WinQuerySwitchEntry %x OK\n", hSwitch);
  2154.                 }
  2155. #endif
  2156.                 /* Set visibility on */
  2157.                 strncpy(switchData.szSwtitle, wmPtr->titleUid, MAXNAMEL+4);
  2158.                 rc = WinChangeSwitchEntry(hSwitch, &switchData);
  2159. #ifdef VERBOSE
  2160.                 if (rc != 0) {
  2161.                     printf("WinChangeSwitchEntry %x ERROR %x\n", hSwitch,
  2162.                            WinGetLastError(TclOS2GetHAB()));
  2163.                 } else {
  2164.                     printf("WinChangeSwitchEntry %x OK\n", hSwitch);
  2165.                 }
  2166. #endif
  2167.             WinSetWindowText(wmPtr->wrapper, wmPtr->titleUid);
  2168.             }
  2169.         }
  2170.     } else if ((c == 't') && (strncmp(argv[1], "transient", length) == 0)
  2171.             && (length >= 3)) {
  2172.         TkWindow *masterPtr;
  2173.  
  2174.         if ((argc != 3) && (argc != 4)) {
  2175.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  2176.                 argv[0], " transient window ?master?\"", (char *) NULL);
  2177.             return TCL_ERROR;
  2178.         }
  2179.         if (argc == 3) {
  2180.             if (wmPtr->masterPtr != NULL) {
  2181.                 Tcl_SetResult(interp, Tk_PathName(wmPtr->masterPtr),
  2182.                         TCL_STATIC);
  2183.             }
  2184.             return TCL_OK;
  2185.         }
  2186.         if (argv[3][0] == '\0') {
  2187.             wmPtr->masterPtr = NULL;
  2188.         } else {
  2189.             masterPtr = (TkWindow *) Tk_NameToWindow(interp, argv[3], tkwin);
  2190.             if (masterPtr == NULL) {
  2191.             return TCL_ERROR;
  2192.             }
  2193.             if (masterPtr == winPtr) {
  2194.                 wmPtr->masterPtr = NULL;
  2195.             } else {
  2196.                 Tk_MakeWindowExist((Tk_Window)masterPtr);
  2197.  
  2198.                 /*
  2199.                  * Ensure that the master window is actually a Tk toplevel.
  2200.                  */
  2201.  
  2202.                 while (!(masterPtr->flags & TK_TOP_LEVEL)) {
  2203.                     masterPtr = masterPtr->parentPtr;
  2204.                 }
  2205.                 wmPtr->masterPtr = masterPtr;
  2206.  
  2207.                 /*
  2208.                  * Ensure that the transient window is either mapped or
  2209.                  * unmapped like its master.
  2210.                  */
  2211.  
  2212.                 TkpWmSetState(winPtr, NormalState);
  2213.             }
  2214.         }
  2215.         if (!(wmPtr->flags & (WM_NEVER_MAPPED)
  2216.                 && !(winPtr->flags & TK_EMBEDDED))) {
  2217.             UpdateWrapper(winPtr);
  2218.         }
  2219.     } else if ((c == 'w') && (strncmp(argv[1], "withdraw", length) == 0)) {
  2220.         if (argc != 3) {
  2221.             Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  2222.                 argv[0], " withdraw window\"", (char *) NULL);
  2223.             return TCL_ERROR;
  2224.         }
  2225.         if (wmPtr->iconFor != NULL) {
  2226.             Tcl_AppendResult(interp, "can't withdraw ", argv[2],
  2227.                 ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
  2228.                 (char *) NULL);
  2229.             return TCL_ERROR;
  2230.         }
  2231.         TkpWmSetState(winPtr, WithdrawnState);
  2232.     } else {
  2233.         Tcl_AppendResult(interp, "unknown or ambiguous option \"", argv[1],
  2234.             "\": must be aspect, client, command, deiconify, ",
  2235.             "focusmodel, frame, geometry, grid, group, iconbitmap, ",
  2236.             "iconify, iconmask, iconname, iconposition, ",
  2237.             "iconwindow, maxsize, minsize, overrideredirect, ",
  2238.             "positionfrom, protocol, resizable, sizefrom, state, title, ",
  2239.             "transient, or withdraw",
  2240.             (char *) NULL);
  2241.         return TCL_ERROR;
  2242.     }
  2243.     return TCL_OK;
  2244.  
  2245.     updateGeom:
  2246.     if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
  2247.         Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
  2248.         wmPtr->flags |= WM_UPDATE_PENDING;
  2249.     }
  2250.     return TCL_OK;
  2251. }
  2252.  
  2253. /*
  2254.  *----------------------------------------------------------------------
  2255.  *
  2256.  * Tk_SetGrid --
  2257.  *
  2258.  *    This procedure is invoked by a widget when it wishes to set a grid
  2259.  *    coordinate system that controls the size of a top-level window.
  2260.  *    It provides a C interface equivalent to the "wm grid" command and
  2261.  *    is usually asscoiated with the -setgrid option.
  2262.  *
  2263.  * Results:
  2264.  *    None.
  2265.  *
  2266.  * Side effects:
  2267.  *    Grid-related information will be passed to the window manager, so
  2268.  *    that the top-level window associated with tkwin will resize on
  2269.  *    even grid units.  If some other window already controls gridding
  2270.  *    for the top-level window then this procedure call has no effect.
  2271.  *
  2272.  *----------------------------------------------------------------------
  2273.  */
  2274.  
  2275. void
  2276. Tk_SetGrid(tkwin, reqWidth, reqHeight, widthInc, heightInc)
  2277.     Tk_Window tkwin;        /* Token for window.  New window mgr info
  2278.                      * will be posted for the top-level window
  2279.                      * associated with this window. */
  2280.     int reqWidth;        /* Width (in grid units) corresponding to
  2281.                      * the requested geometry for tkwin. */
  2282.     int reqHeight;        /* Height (in grid units) corresponding to
  2283.                      * the requested geometry for tkwin. */
  2284.     int widthInc, heightInc;    /* Pixel increments corresponding to a
  2285.                      * change of one grid unit. */
  2286. {
  2287.     TkWindow *winPtr = (TkWindow *) tkwin;
  2288.     register WmInfo *wmPtr;
  2289.  
  2290. #ifdef VERBOSE
  2291.     printf("Tk_SetGrid\n");
  2292. #endif
  2293.  
  2294.     /*
  2295.      * Find the top-level window for tkwin, plus the window manager
  2296.      * information.
  2297.      */
  2298.  
  2299.     while (!(winPtr->flags & TK_TOP_LEVEL)) {
  2300.         winPtr = winPtr->parentPtr;
  2301.     }
  2302.     wmPtr = winPtr->wmInfoPtr;
  2303.  
  2304.     if ((wmPtr->gridWin != NULL) && (wmPtr->gridWin != tkwin)) {
  2305.         return;
  2306.     }
  2307.  
  2308.     if ((wmPtr->reqGridWidth == reqWidth)
  2309.             && (wmPtr->reqGridHeight == reqHeight)
  2310.             && (wmPtr->widthInc == widthInc)
  2311.             && (wmPtr->heightInc == heightInc)
  2312.             && ((wmPtr->sizeHintsFlags & (PBaseSize|PResizeInc))
  2313.                 == (PBaseSize|PResizeInc))) {
  2314.         return;
  2315.     }
  2316.  
  2317.     /*
  2318.      * If gridding was previously off, then forget about any window
  2319.      * size requests made by the user or via "wm geometry":  these are
  2320.      * in pixel units and there's no easy way to translate them to
  2321.      * grid units since the new requested size of the top-level window in
  2322.      * pixels may not yet have been registered yet (it may filter up
  2323.      * the hierarchy in DoWhenIdle handlers).  However, if the window
  2324.      * has never been mapped yet then just leave the window size alone:
  2325.      * assume that it is intended to be in grid units but just happened
  2326.      * to have been specified before this procedure was called.
  2327.      */
  2328.  
  2329.     if ((wmPtr->gridWin == NULL) && !(wmPtr->flags & WM_NEVER_MAPPED)) {
  2330.         wmPtr->width = -1;
  2331.         wmPtr->height = -1;
  2332.     }
  2333.  
  2334.     /* 
  2335.      * Set the new gridding information, and start the process of passing
  2336.      * all of this information to the window manager.
  2337.      */
  2338.  
  2339.     wmPtr->gridWin = tkwin;
  2340.     wmPtr->reqGridWidth = reqWidth;
  2341.     wmPtr->reqGridHeight = reqHeight;
  2342.     wmPtr->widthInc = widthInc;
  2343.     wmPtr->heightInc = heightInc;
  2344.     wmPtr->sizeHintsFlags |= PBaseSize|PResizeInc;
  2345.     if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
  2346.         Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
  2347.         wmPtr->flags |= WM_UPDATE_PENDING;
  2348.     }
  2349. }
  2350.  
  2351. /*
  2352.  *----------------------------------------------------------------------
  2353.  *
  2354.  * Tk_UnsetGrid --
  2355.  *
  2356.  *    This procedure cancels the effect of a previous call
  2357.  *    to Tk_SetGrid.
  2358.  *
  2359.  * Results:
  2360.  *    None.
  2361.  *
  2362.  * Side effects:
  2363.  *    If tkwin currently controls gridding for its top-level window,
  2364.  *    gridding is cancelled for that top-level window;  if some other
  2365.  *    window controls gridding then this procedure has no effect.
  2366.  *
  2367.  *----------------------------------------------------------------------
  2368.  */
  2369.  
  2370. void
  2371. Tk_UnsetGrid(tkwin)
  2372.     Tk_Window tkwin;        /* Token for window that is currently
  2373.                      * controlling gridding. */
  2374. {
  2375.     TkWindow *winPtr = (TkWindow *) tkwin;
  2376.     register WmInfo *wmPtr;
  2377.  
  2378. #ifdef VERBOSE
  2379.     printf("Tk_UnsetGrid\n");
  2380. #endif
  2381.  
  2382.     /*
  2383.      * Find the top-level window for tkwin, plus the window manager
  2384.      * information.
  2385.      */
  2386.  
  2387.     while (!(winPtr->flags & TK_TOP_LEVEL)) {
  2388.         winPtr = winPtr->parentPtr;
  2389.     }
  2390.     wmPtr = winPtr->wmInfoPtr;
  2391.     if (tkwin != wmPtr->gridWin) {
  2392.         return;
  2393.     }
  2394.  
  2395.     wmPtr->gridWin = NULL;
  2396.     wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc);
  2397.     if (wmPtr->width != -1) {
  2398.         wmPtr->width = winPtr->reqWidth + (wmPtr->width
  2399.             - wmPtr->reqGridWidth)*wmPtr->widthInc;
  2400.         wmPtr->height = winPtr->reqHeight + (wmPtr->height
  2401.             - wmPtr->reqGridHeight)*wmPtr->heightInc;
  2402.     }
  2403.     wmPtr->widthInc = 1;
  2404.     wmPtr->heightInc = 1;
  2405.  
  2406.     if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
  2407.         Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
  2408.         wmPtr->flags |= WM_UPDATE_PENDING;
  2409.     }
  2410. }
  2411.  
  2412. /*
  2413.  *----------------------------------------------------------------------
  2414.  *
  2415.  * TopLevelEventProc --
  2416.  *
  2417.  *    This procedure is invoked when a top-level (or other externally-
  2418.  *    managed window) is restructured in any way.
  2419.  *
  2420.  * Results:
  2421.  *    None.
  2422.  *
  2423.  * Side effects:
  2424.  *    Tk's internal data structures for the window get modified to
  2425.  *    reflect the structural change.
  2426.  *
  2427.  *----------------------------------------------------------------------
  2428.  */
  2429.  
  2430. static void
  2431. TopLevelEventProc(clientData, eventPtr)
  2432.     ClientData clientData;        /* Window for which event occurred. */
  2433.     XEvent *eventPtr;            /* Event that just happened. */
  2434. {
  2435.     register TkWindow *winPtr = (TkWindow *) clientData;
  2436.  
  2437. #ifdef VERBOSE
  2438.     printf("TopLevelEventProc, winPtr %x, eventPtr %x\n", winPtr, eventPtr);
  2439. #endif
  2440.  
  2441.     if (eventPtr->type == DestroyNotify) {
  2442.         Tk_ErrorHandler handler;
  2443.  
  2444.         if (!(winPtr->flags & TK_ALREADY_DEAD)) {
  2445.             /*
  2446.              * A top-level window was deleted externally (e.g., by the window
  2447.              * manager).  This is probably not a good thing, but cleanup as
  2448.              * best we can.  The error handler is needed because
  2449.              * Tk_DestroyWindow will try to destroy the window, but of course
  2450.              * it's already gone.
  2451.              */
  2452.     
  2453. #ifdef VERBOSE
  2454.             printf("    TK_ALREADY_DEAD\n");
  2455. #endif
  2456.             handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1,
  2457.                 (Tk_ErrorProc *) NULL, (ClientData) NULL);
  2458.             Tk_DestroyWindow((Tk_Window) winPtr);
  2459.             Tk_DeleteErrorHandler(handler);
  2460.         }
  2461.     } else if (eventPtr->type == ConfigureNotify) {
  2462.         WmInfo *wmPtr;
  2463.         wmPtr = winPtr->wmInfoPtr;
  2464.  
  2465.         if (winPtr->flags & TK_EMBEDDED) {
  2466.             Tk_Window tkwin = (Tk_Window)winPtr;
  2467.             WinSendMsg(wmPtr->wrapper, TK_GEOMETRYREQ,
  2468.                        (MPARAM) Tk_ReqWidth(tkwin),
  2469.                        (MPARAM) Tk_ReqHeight(tkwin));
  2470.         }
  2471.     }
  2472. }
  2473.  
  2474. /*
  2475.  *----------------------------------------------------------------------
  2476.  *
  2477.  * TopLevelReqProc --
  2478.  *
  2479.  *    This procedure is invoked by the geometry manager whenever
  2480.  *    the requested size for a top-level window is changed.
  2481.  *
  2482.  * Results:
  2483.  *    None.
  2484.  *
  2485.  * Side effects:
  2486.  *    Arrange for the window to be resized to satisfy the request
  2487.  *    (this happens as a when-idle action).
  2488.  *
  2489.  *----------------------------------------------------------------------
  2490.  */
  2491.  
  2492.         /* ARGSUSED */
  2493. static void
  2494. TopLevelReqProc(dummy, tkwin)
  2495.     ClientData dummy;            /* Not used. */
  2496.     Tk_Window tkwin;            /* Information about window. */
  2497. {
  2498.     TkWindow *winPtr = (TkWindow *) tkwin;
  2499.     WmInfo *wmPtr;
  2500.  
  2501. #ifdef VERBOSE
  2502.     printf("TopLevelReqProc\n");
  2503. #endif
  2504.  
  2505.     wmPtr = winPtr->wmInfoPtr;
  2506.     if (winPtr->flags & TK_EMBEDDED) {
  2507.         WinSendMsg(wmPtr->wrapper, TK_GEOMETRYREQ,
  2508.                    MPFROMLONG(Tk_ReqWidth(tkwin)),
  2509.                    MPFROMLONG(Tk_ReqHeight(tkwin)));
  2510.     }
  2511.     if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
  2512.         Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
  2513.         wmPtr->flags |= WM_UPDATE_PENDING;
  2514.     }
  2515. }
  2516.  
  2517. /*
  2518.  *----------------------------------------------------------------------
  2519.  *
  2520.  * UpdateGeometryInfo --
  2521.  *
  2522.  *    This procedure is invoked when a top-level window is first
  2523.  *    mapped, and also as a when-idle procedure, to bring the
  2524.  *    geometry and/or position of a top-level window back into
  2525.  *    line with what has been requested by the user and/or widgets.
  2526.  *    This procedure doesn't return until the system has
  2527.  *    responded to the geometry change.
  2528.  *
  2529.  * Results:
  2530.  *    None.
  2531.  *
  2532.  * Side effects:
  2533.  *    The window's size and location may change, unless the WM prevents
  2534.  *    that from happening.
  2535.  *
  2536.  *----------------------------------------------------------------------
  2537.  */
  2538.  
  2539. static void
  2540. UpdateGeometryInfo(clientData)
  2541.     ClientData clientData;        /* Pointer to the window's record. */
  2542. {
  2543.     int x, y;            /* Position of border on desktop */
  2544.     int width, height;        /* Size of client area */
  2545.     register TkWindow *winPtr = (TkWindow *) clientData;
  2546.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2547.     ULONG wrapperStyle;
  2548.  
  2549. #ifdef VERBOSE
  2550.     SWP oldPos;
  2551.     printf("UpdateGeometryInfo winPtr %x wrapper %x\n", winPtr, wmPtr->wrapper);
  2552.     if (wmPtr->wrapper != NULLHANDLE) {
  2553.     rc = WinQueryWindowPos(wmPtr->wrapper, &oldPos);
  2554.     printf("UpdateGeometryInfo pos before processing: (%d,%d) %dx%d x11y %d\n",
  2555.            oldPos.x, oldPos.y, oldPos.cx, oldPos.cy,
  2556.            yScreen - oldPos.y - oldPos.cy);
  2557.     }
  2558. #endif
  2559.  
  2560.     wmPtr->flags &= ~WM_UPDATE_PENDING;
  2561.  
  2562.     /*
  2563.      * If the window is minimized or maximized, we should not update
  2564.      * our geometry since it will end up with the wrong values.
  2565.      * ConfigureToplevel will reschedule UpdateGeometryInfo when the
  2566.      * state of the window changes.
  2567.      */
  2568.  
  2569.     if (wmPtr->wrapper != NULLHANDLE) {
  2570.         wrapperStyle = WinQueryWindowULong(wmPtr->wrapper, QWL_STYLE);
  2571.         if ((wrapperStyle & WS_MINIMIZED) || (wrapperStyle & WS_MAXIMIZED)) {
  2572.             return;
  2573.         }
  2574.     }
  2575.  
  2576.     /*
  2577.      * Compute the border size for the current window style.  This
  2578.      * size will include the resize handles, the title bar and the
  2579.      * menubar.
  2580.      * wmPtr->wrapper may be 0, so we cannot use WinCalcFrameRect
  2581.      * ande their will not be a menu bar => use defines.
  2582.      */
  2583.  
  2584.     if (!wmPtr->wrapper) {
  2585.         if (winPtr->atts.override_redirect) {
  2586.             wmPtr->borderWidth = BORDERWIDTH_OVERRIDE;
  2587.             wmPtr->borderHeight = BORDERHEIGHT_OVERRIDE;
  2588.         } else if (wmPtr->masterPtr) {
  2589.             if (! ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) &&
  2590.                     (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE))) {
  2591.                 wmPtr->borderWidth = BORDERWIDTH_TOPLEVEL;
  2592.                 wmPtr->borderHeight = BORDERHEIGHT_TOPLEVEL;
  2593.             } else {
  2594.                 wmPtr->borderWidth = BORDERWIDTH_TRANSIENT;
  2595.                 wmPtr->borderHeight = BORDERHEIGHT_TRANSIENT;
  2596.             }
  2597.         } else {
  2598.             wmPtr->borderWidth = BORDERWIDTH_TOPLEVEL;
  2599.             wmPtr->borderHeight = BORDERHEIGHT_TOPLEVEL;
  2600.         }
  2601.     } else {
  2602.         SWP oldPos;
  2603.         RECTL rectl;
  2604.         rc = WinQueryWindowPos(wmPtr->wrapper, &oldPos);
  2605. #ifdef VERBOSE
  2606.         if (rc == TRUE) {
  2607.              printf("    WinQueryWindowPos returned %d\n", rc);
  2608.         } else {
  2609.              printf("    WinQueryWindowPos ERROR %d\n",
  2610.                     WinGetLastError(TclOS2GetHAB()));
  2611.         }
  2612. #endif
  2613.         rectl.xLeft = oldPos.x;
  2614.         rectl.yBottom = oldPos.y;
  2615.         rectl.xRight = oldPos.x + oldPos.cx;
  2616.         rectl.yTop = oldPos.y + oldPos.cy;
  2617. #ifdef VERBOSE
  2618.         printf("    border WinCalcFrameRect (%d,%d) (%d,%d) =>\n", rectl.xLeft,
  2619.                rectl.yBottom, rectl.xRight, rectl.yTop);
  2620. #endif
  2621.         rc = WinCalcFrameRect(wmPtr->wrapper, &rectl, TRUE);
  2622. #ifdef VERBOSE
  2623.         if (rc == TRUE) {
  2624.             printf("   border WinCalcFrameRect OK => (%d,%d) (%d,%d)\n",
  2625.                    rectl.xLeft, rectl.yBottom, rectl.xRight, rectl.yTop);
  2626.         } else {
  2627.             if (rectl.xRight-rectl.xLeft ==0 || rectl.yTop-rectl.yBottom ==0) {
  2628.                 printf("   border WinCalcFrameRect %x empty=> (%d,%d)(%d,%d)\n",
  2629.                        wmPtr->wrapper, rectl.xLeft, rectl.yBottom, rectl.xRight,
  2630.                        rectl.yTop);
  2631.             } else {
  2632.             printf("   border WinCalcFrameRect %x ERROR %x => (%d,%d)(%d,%d)\n",
  2633.                    wmPtr->wrapper, WinGetLastError(TclOS2GetHAB()), rectl.xLeft,
  2634.                    rectl.yBottom, rectl.xRight, rectl.yTop);
  2635.             }
  2636.         }
  2637. #endif
  2638.         wmPtr->borderWidth = oldPos.cx - (rectl.xRight - rectl.xLeft);
  2639.         wmPtr->borderHeight = oldPos.cy - (rectl.yTop - rectl.yBottom);
  2640.     }
  2641. #ifdef VERBOSE
  2642.     printf("    borderWidth %d, borderHeight %d\n", wmPtr->borderWidth,
  2643.            wmPtr->borderHeight);
  2644. #endif
  2645.  
  2646.     /*
  2647.      * Compute the new size for the top-level window.  See the
  2648.      * user documentation for details on this, but the size
  2649.      * requested depends on (a) the size requested internally
  2650.      * by the window's widgets, (b) the size requested by the
  2651.      * user in a "wm geometry" command or via wm-based interactive
  2652.      * resizing (if any), and (c) whether or not the window is
  2653.      * gridded.  Don't permit sizes <= 0 because this upsets
  2654.      * the X server.
  2655.      */
  2656.  
  2657.     if (wmPtr->width == -1) {
  2658.         width = winPtr->reqWidth;
  2659. #ifdef VERBOSE
  2660.         printf("UpdateGeometryInfo width = winPtr->reqWidth: %d\n", width);
  2661. #endif
  2662.     } else if (wmPtr->gridWin != NULL) {
  2663.         width = winPtr->reqWidth
  2664.             + (wmPtr->width - wmPtr->reqGridWidth)*wmPtr->widthInc;
  2665. #ifdef VERBOSE
  2666.         printf("UpdateGeometryInfo width = winPtr->reqWidth + ...: %d (%d + (%d - %d)* %d\n",
  2667.                width, winPtr->reqWidth, wmPtr->width, wmPtr->reqGridWidth,
  2668.                wmPtr->widthInc);
  2669. #endif
  2670.     } else {
  2671.         width = wmPtr->width;
  2672. #ifdef VERBOSE
  2673.         printf("UpdateGeometryInfo width = wmPtr->width: %d\n", width);
  2674. #endif
  2675.     }
  2676.     if (width <= 0) {
  2677.         width = 1;
  2678. #ifdef VERBOSE
  2679.         printf("UpdateGeometryInfo width = 1\n");
  2680. #endif
  2681.     }
  2682.     if (wmPtr->height == -1) {
  2683.         height = winPtr->reqHeight;
  2684. #ifdef VERBOSE
  2685.         printf("UpdateGeometryInfo height = winPtr->reqHeight: %d\n", height);
  2686. #endif
  2687.     } else if (wmPtr->gridWin != NULL) {
  2688.         height = winPtr->reqHeight
  2689.                 + (wmPtr->height - wmPtr->reqGridHeight)*wmPtr->heightInc;
  2690. #ifdef VERBOSE
  2691.         printf("UpdateGeometryInfo height = winPtr->reqHeight + ...: %d (%d + (%d - %d)* %d\n",
  2692.                height, winPtr->reqHeight, wmPtr->height, wmPtr->reqGridHeight,
  2693.                wmPtr->heightInc);
  2694. #endif
  2695.     } else {
  2696.         height = wmPtr->height;
  2697. #ifdef VERBOSE
  2698.         printf("UpdateGeometryInfo height = wmPtr->height: %d\n", height);
  2699. #endif
  2700.     }
  2701.     if (height <= 0) {
  2702.         height = 1;
  2703. #ifdef VERBOSE
  2704.         printf("UpdateGeometryInfo height = 1\n");
  2705. #endif
  2706.     }
  2707.  
  2708.     /*
  2709.      * Compute the new position for the upper-left pixel of the window's
  2710.      * decorative frame.  This is tricky, because we need to include the
  2711.      * border widths supplied by a reparented parent in this calculation,
  2712.      * but can't use the parent's current overall size since that may
  2713.      * change as a result of this code.
  2714.      */
  2715.  
  2716.     if (wmPtr->flags & WM_NEGATIVE_X) {
  2717.         x = DisplayWidth(winPtr->display, winPtr->screenNum) - wmPtr->x
  2718.             - (width + wmPtr->borderWidth);
  2719.     } else {
  2720.         x =  wmPtr->x;
  2721. #ifdef VERBOSE
  2722.         printf("UpdateGeometryInfo x = wmPtr->x: %d\n", x);
  2723. #endif
  2724.     }
  2725.     if (wmPtr->flags & WM_NEGATIVE_Y) {
  2726. #ifdef VERBOSE
  2727.         printf("UpdateGeometryInfo WM_NEGATIVE_Y\n");
  2728. #endif
  2729.         y = DisplayHeight(winPtr->display, winPtr->screenNum) - wmPtr->y
  2730.             - (height + wmPtr->borderHeight);
  2731.     } else {
  2732. #ifdef VERBOSE
  2733.         printf("UpdateGeometryInfo non-WM_NEGATIVE_Y\n");
  2734. #endif
  2735.         y =  wmPtr->y;
  2736. #ifdef VERBOSE
  2737.         printf("UpdateGeometryInfo y = wmPtr->y: %d\n", y);
  2738. #endif
  2739.     }
  2740.  
  2741.     /*
  2742.      * If this window is embedded and the container is also in this
  2743.      * process, we don't need to do anything special about the
  2744.      * geometry, except to make sure that the desired size is known
  2745.      * by the container.  Also, zero out any position information,
  2746.      * since embedded windows are not allowed to move.
  2747.      */
  2748.  
  2749.     if (winPtr->flags & TK_BOTH_HALVES) {
  2750.         wmPtr->x = wmPtr->y = 0;
  2751.         wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y);
  2752.         Tk_GeometryRequest((Tk_Window) TkpGetOtherWindow(winPtr),
  2753.                 width, height);
  2754.         return;
  2755.     }
  2756.  
  2757.     /*
  2758.      * Reconfigure the window if it isn't already configured correctly.  Base
  2759.      * the size check on what we *asked for* last time, not what we got.
  2760.      * Return immediately if there have been no changes in the requested
  2761.      * geometry of the toplevel.
  2762.      */
  2763.     /* TODO: need to add flag for possible menu size change */
  2764.  
  2765.     if (!((wmPtr->flags & WM_MOVE_PENDING)
  2766.             || (width != wmPtr->configWidth)
  2767.             || (height != wmPtr->configHeight))) {
  2768.         return;
  2769.     }
  2770.     wmPtr->flags &= ~WM_MOVE_PENDING;
  2771.  
  2772.     wmPtr->configWidth = width;
  2773.     wmPtr->configHeight = height;
  2774.  
  2775.    /*
  2776.     * Don't bother moving the window if we are in the process of
  2777.     * creating it.  Just update the geometry info based on what
  2778.     * we asked for.
  2779.     */
  2780.  
  2781.     if (wmPtr->flags & WM_CREATE_PENDING) {
  2782.         winPtr->changes.x = x;
  2783.         winPtr->changes.y = y;
  2784.         winPtr->changes.width = width;
  2785.         winPtr->changes.height = height;
  2786. #ifdef VERBOSE
  2787.         printf("    now: wP->c.w %d (width %d), wP->c.h %d (height %d)\n",
  2788.                winPtr->changes.width, width, winPtr->changes.height, height);
  2789. #endif
  2790.         return;
  2791.     }
  2792.  
  2793.     wmPtr->flags |= WM_SYNC_PENDING;
  2794.     if (winPtr->flags & TK_EMBEDDED) {
  2795.         /*
  2796.          * The wrapper window is in a different process, so we need
  2797.          * to send it a geometry request.  This protocol assumes that
  2798.          * the other process understands this Tk message, otherwise
  2799.          * our requested geometry will be ignored.
  2800.          */
  2801.  
  2802.         WinSendMsg(wmPtr->wrapper, TK_GEOMETRYREQ, MPFROMLONG(width),
  2803.                    MPFROMLONG(height));
  2804.     } else {
  2805.         int reqHeight, reqWidth;
  2806.         RECTL windowRect;
  2807.         int menuInc = WinQuerySysValue(HWND_DESKTOP, SV_CYMENU);
  2808.         int newHeight;
  2809. #ifdef VERBOSE
  2810.         printf("SV_CYMENU %d\n", menuInc);
  2811. #endif
  2812.  
  2813.         /*
  2814.          * We have to keep resizing the window until we get the
  2815.          * requested height in the client area. If the client
  2816.          * area has zero height, then the window rect is too
  2817.          * small by definition. Try increasing the border height
  2818.          * and try again. Once we have a positive size, then
  2819.          * we can adjust the height exactly. If the window
  2820.          * rect comes back smaller than we requested, we have
  2821.          * hit the maximum constraints that OS/2 imposes.
  2822.          * Once we find a positive client size, the next size
  2823.          * is the one we try no matter what.
  2824.          * Use SWP_NOADJUST to prevent getting a WM_QUERYTRACKINFO msg
  2825.          * (because of WM_ADJUSTWINDOWPOS message handling), which causes
  2826.          * the window to move up.
  2827.          */
  2828.  
  2829.         reqHeight = height + wmPtr->borderHeight;
  2830.         reqWidth = width + wmPtr->borderWidth;
  2831.  
  2832.         while (1) {
  2833. #ifdef VERBOSE
  2834.             printf("   WinSetWindowPos(%x TOP (%d,%d) %dx%d S|M|NA)\n",
  2835.                    wmPtr->wrapper, x, yScreen - y - reqHeight,
  2836.                    reqWidth, reqHeight);
  2837. #endif
  2838.             rc = WinSetWindowPos(wmPtr->wrapper, HWND_TOP, x,
  2839.                                  yScreen - y - reqHeight,
  2840.                                  reqWidth, reqHeight,
  2841.                                  SWP_SIZE | SWP_MOVE | SWP_NOADJUST);
  2842. #ifdef VERBOSE
  2843.             if (rc == TRUE) {
  2844.                  printf("    WinSetWindowPos returned %d\n", rc);
  2845.             } else {
  2846.                  printf("    WinSetWindowPos ERROR %d\n",
  2847.                         WinGetLastError(TclOS2GetHAB()));
  2848.             }
  2849. #endif
  2850.             rc = WinQueryWindowRect(wmPtr->wrapper, &windowRect);
  2851.             newHeight = windowRect.yTop - windowRect.yBottom;
  2852. #ifdef VERBOSE
  2853.             printf("    WinQueryWindowRect %x returns %x, newHeight %d\n",
  2854.                    wmPtr->wrapper, rc, newHeight);
  2855. #endif
  2856.  
  2857.             /*
  2858.              * If the request wasn't satisfied, we have hit an external
  2859.              * constraint and must stop.
  2860.              */
  2861.  
  2862.             if (newHeight < reqHeight) {
  2863.                 break;
  2864.             }
  2865.  
  2866.             /*
  2867.              * Now check the size of the client area against our ideal.
  2868.              */
  2869.  
  2870.             rc = WinCalcFrameRect(wmPtr->wrapper, &windowRect, TRUE);
  2871.             newHeight = windowRect.yTop - windowRect.yBottom;
  2872. #ifdef VERBOSE
  2873.             printf("    WinCalcFrameRect %x returns %x newHeight %d\n",
  2874.                    wmPtr->wrapper, rc, newHeight);
  2875. #endif
  2876.  
  2877.             if (newHeight == height) {
  2878.                 /*
  2879.                  * We're done.
  2880.                  */
  2881.                 break;
  2882.             } else if (newHeight > height) {
  2883.                 /*
  2884.                  * One last resize to get rid of the extra space.
  2885.                  */
  2886.                 menuInc = newHeight - height;
  2887.                 reqHeight -= menuInc;
  2888.                 if (wmPtr->flags & WM_NEGATIVE_Y) {
  2889.                     y += menuInc;
  2890.                 }
  2891. #ifdef VERBOSE
  2892.                 printf("  last WinSetWindowPos(%x TOP (%d,%d) %dx%d S|M|NA)\n",
  2893.                        wmPtr->wrapper, x, yScreen - y - reqHeight,
  2894.                        reqWidth, reqHeight);
  2895. #endif
  2896.                 rc = WinSetWindowPos(wmPtr->wrapper, HWND_TOP, x,
  2897.                                      yScreen - y - reqHeight,
  2898.                          reqWidth, reqHeight,
  2899.                                      SWP_SIZE | SWP_MOVE | SWP_NOADJUST);
  2900. #ifdef VERBOSE
  2901.                 if (rc == TRUE) {
  2902.                      printf("    WinSetWindowPos returned %d\n", rc);
  2903.                 } else {
  2904.                      printf("    WinSetWindowPos ERROR %d\n",
  2905.                             WinGetLastError(TclOS2GetHAB()));
  2906.                 }
  2907. #endif
  2908.                 break;
  2909.             }
  2910.  
  2911.             /*
  2912.              * We didn't get enough space to satisfy our requested
  2913.              * height, so the menu must have wrapped.  Increase the
  2914.              * size of the window by one menu height and move the
  2915.              * window if it is positioned relative to the lower right
  2916.              * corner of the screen.
  2917.              */
  2918.  
  2919.             reqHeight += menuInc;
  2920.             if (wmPtr->flags & WM_NEGATIVE_Y) {
  2921.                 y -= menuInc;
  2922.             }
  2923.         }
  2924.         if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  2925.             /* Draw menu bar */
  2926.             WinSendMsg(wmPtr->wrapper, WM_UPDATEFRAME, MPFROMLONG(FCF_MENU),
  2927.                        MPVOID);
  2928.         }
  2929.     }
  2930.     wmPtr->flags &= ~WM_SYNC_PENDING;
  2931. }
  2932.  
  2933. /*
  2934.  *--------------------------------------------------------------
  2935.  *
  2936.  * ParseGeometry --
  2937.  *
  2938.  *    This procedure parses a geometry string and updates
  2939.  *    information used to control the geometry of a top-level
  2940.  *    window.
  2941.  *
  2942.  * Results:
  2943.  *    A standard Tcl return value, plus an error message in
  2944.  *    interp->result if an error occurs.
  2945.  *
  2946.  * Side effects:
  2947.  *    The size and/or location of winPtr may change.
  2948.  *
  2949.  *--------------------------------------------------------------
  2950.  */
  2951.  
  2952. static int
  2953. ParseGeometry(interp, string, winPtr)
  2954.     Tcl_Interp *interp;        /* Used for error reporting. */
  2955.     char *string;        /* String containing new geometry.  Has the
  2956.                      * standard form "=wxh+x+y". */
  2957.     TkWindow *winPtr;        /* Pointer to top-level window whose
  2958.                      * geometry is to be changed. */
  2959. {
  2960.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  2961.     int x, y, width, height, flags;
  2962.     char *end;
  2963.     register char *p = string;
  2964. #ifdef VERBOSE
  2965.     printf("ParseGeometry %s\n", p);
  2966. #endif
  2967.  
  2968.     /*
  2969.      * The leading "=" is optional.
  2970.      */
  2971.  
  2972.     if (*p == '=') {
  2973.         p++;
  2974.     }
  2975.  
  2976.     /*
  2977.      * Parse the width and height, if they are present.  Don't
  2978.      * actually update any of the fields of wmPtr until we've
  2979.      * successfully parsed the entire geometry string.
  2980.      */
  2981.  
  2982.     width = wmPtr->width;
  2983.     height = wmPtr->height;
  2984.     x = wmPtr->x;
  2985.     y = wmPtr->y;
  2986.     flags = wmPtr->flags;
  2987.     if (isdigit(UCHAR(*p))) {
  2988.         width = strtoul(p, &end, 10);
  2989.         p = end;
  2990.         if (*p != 'x') {
  2991.             goto error;
  2992.         }
  2993.         p++;
  2994.         if (!isdigit(UCHAR(*p))) {
  2995.             goto error;
  2996.         }
  2997.         height = strtoul(p, &end, 10);
  2998.         p = end;
  2999.     }
  3000.  
  3001.     /*
  3002.      * Parse the X and Y coordinates, if they are present.
  3003.      */
  3004.  
  3005.     if (*p != '\0') {
  3006.         flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y);
  3007.         if (*p == '-') {
  3008.             flags |= WM_NEGATIVE_X;
  3009.         } else if (*p != '+') {
  3010.             goto error;
  3011.         }
  3012.         p++;
  3013.         if (!isdigit(UCHAR(*p)) && (*p != '-')) {
  3014.             goto error;
  3015.         }
  3016.         x = strtol(p, &end, 10);
  3017.         /* Beware of apps using +-x, eg. SpecTcl 1.1 */
  3018.         if (x < 0) {
  3019.             flags |= WM_NEGATIVE_X;
  3020.             x = -x;
  3021.         }
  3022.         p = end;
  3023.         if (*p == '-') {
  3024.             flags |= WM_NEGATIVE_Y;
  3025.         } else if (*p != '+') {
  3026.             goto error;
  3027.         }
  3028.         p++;
  3029.         if (!isdigit(UCHAR(*p)) && (*p != '-')) {
  3030.             goto error;
  3031.         }
  3032.         y = strtol(p, &end, 10);
  3033.         /* Beware of apps using +-y, eg. SpecTcl 1.1 */
  3034.         if (y < 0) {
  3035.             flags |= WM_NEGATIVE_Y;
  3036.             y = -y;
  3037.         }
  3038.         if (*end != '\0') {
  3039.             goto error;
  3040.         }
  3041.  
  3042.         /*
  3043.          * Assume that the geometry information came from the user,
  3044.          * unless an explicit source has been specified.  Otherwise
  3045.          * most window managers assume that the size hints were
  3046.          * program-specified and they ignore them.
  3047.          */
  3048.  
  3049.         if ((wmPtr->sizeHintsFlags & (USPosition|PPosition)) == 0) {
  3050.             wmPtr->sizeHintsFlags |= USPosition;
  3051.         }
  3052.     }
  3053.  
  3054. #ifdef VERBOSE
  3055.     printf("ParseGeometry %dx%d+%d+%d\n", width, height, x, y);
  3056. #endif
  3057.  
  3058.     /*
  3059.      * Everything was parsed OK.  Update the fields of *wmPtr and
  3060.      * arrange for the appropriate information to be percolated out
  3061.      * to the window manager at the next idle moment.
  3062.      */
  3063.  
  3064.     wmPtr->width = width;
  3065.     wmPtr->height = height;
  3066.     wmPtr->x = x;
  3067.     wmPtr->y = y;
  3068.     flags |= WM_MOVE_PENDING;
  3069.     wmPtr->flags = flags;
  3070.  
  3071.     if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
  3072.         Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
  3073.         wmPtr->flags |= WM_UPDATE_PENDING;
  3074.     }
  3075.     return TCL_OK;
  3076.  
  3077.     error:
  3078.     Tcl_AppendResult(interp, "bad geometry specifier \"",
  3079.             string, "\"", (char *) NULL);
  3080.     return TCL_ERROR;
  3081. }
  3082.  
  3083. /*
  3084.  *----------------------------------------------------------------------
  3085.  *
  3086.  * Tk_GetRootCoords --
  3087.  *
  3088.  *    Given a token for a window, this procedure traces through the
  3089.  *    window's lineage to find the (virtual) root-window coordinates
  3090.  *    corresponding to point (0,0) in the window.
  3091.  *
  3092.  * Results:
  3093.  *    The locations pointed to by xPtr and yPtr are filled in with
  3094.  *    the root coordinates of the (0,0) point in tkwin.
  3095.  *
  3096.  * Side effects:
  3097.  *    None.
  3098.  *
  3099.  *----------------------------------------------------------------------
  3100.  */
  3101.  
  3102. void
  3103. Tk_GetRootCoords(tkwin, xPtr, yPtr)
  3104.     Tk_Window tkwin;        /* Token for window. */
  3105.     int *xPtr;            /* Where to store x-displacement of (0,0). */
  3106.     int *yPtr;            /* Where to store y-displacement of (0,0). */
  3107. {
  3108.     register TkWindow *winPtr = (TkWindow *) tkwin;
  3109.  
  3110. #ifdef VERBOSE
  3111.     printf("Tk_GetRootCoords tkwin %x\n", tkwin);
  3112. #endif
  3113.  
  3114.     /*
  3115.      * If the window is mapped, let OS/2 figure out the translation by taking
  3116.      * the top-left position in window coordinates: (0,0) on X and Win,
  3117.      * (0,height) on OS/2.
  3118.      */
  3119.  
  3120.     if (winPtr->window != None) {
  3121.         HWND hwnd = Tk_GetHWND(winPtr->window);
  3122.         POINTL point;
  3123.         SWP pos;
  3124.         rc = WinQueryWindowPos(hwnd, &pos);
  3125. #ifdef VERBOSE
  3126.         printf("Tk_GetRootCoords h %x WinQueryWindowPos (%d,%d) %dx%d\n", hwnd,
  3127.                pos.x, pos.y, pos.cx, pos.cy);
  3128. #endif
  3129.  
  3130.         point.x = 0;
  3131.         point.y = 0;
  3132. #ifdef VERBOSE
  3133.         printf("Tk_GetRootCoords h %x (%d,%d) =>\n", hwnd, point.x, point.y);
  3134. #endif
  3135.  
  3136.         rc = WinMapWindowPoints (hwnd, HWND_DESKTOP, &point, 1);
  3137.  
  3138.         *xPtr = point.x;
  3139.         /* Translate to PM coordinates */
  3140.         *yPtr = yScreen - point.y - pos.cy;
  3141.  
  3142. #ifdef VERBOSE
  3143.         printf("Tk_GetRootCoords => (%d,%d) (PM %d,%d)\n", *xPtr, *yPtr,
  3144.                point.x, point.y);
  3145.         if (rc == TRUE) {
  3146.             printf("    WinMapWindowPoints %x (%d,%d) OK\n", hwnd, point.x,
  3147.                    point.y);
  3148.         } else {
  3149.             printf("    WinMapWindowPoints %x (%d,%d) ERROR %x\n", hwnd,
  3150.                    point.x, point.y, WinGetLastError(TclOS2GetHAB()));
  3151.         }
  3152. #endif
  3153.     } else {
  3154.         *xPtr = 0;
  3155.         *yPtr = 0;
  3156. #ifdef VERBOSE
  3157.         printf("Tk_GetRootCoords not mapped (0,0)\n");
  3158. #endif
  3159.     }
  3160. }
  3161.  
  3162. /*
  3163.  *----------------------------------------------------------------------
  3164.  *
  3165.  * Tk_CoordsToWindow --
  3166.  *
  3167.  *    Given the (virtual) root coordinates of a point, this procedure
  3168.  *    returns the token for the top-most window covering that point,
  3169.  *    if there exists such a window in this application.
  3170.  *
  3171.  * Results:
  3172.  *    The return result is either a token for the window corresponding
  3173.  *    to rootX and rootY, or else NULL to indicate that there is no such
  3174.  *    window.
  3175.  *
  3176.  * Side effects:
  3177.  *    None.
  3178.  *
  3179.  *----------------------------------------------------------------------
  3180.  */
  3181.  
  3182. Tk_Window
  3183. Tk_CoordsToWindow(rootX, rootY, tkwin)
  3184.     int rootX, rootY;        /* Coordinates of point in root window.  If
  3185.                      * a virtual-root window manager is in use,
  3186.                      * these coordinates refer to the virtual
  3187.                      * root, not the real root. */
  3188.     Tk_Window tkwin;        /* Token for any window in application;
  3189.                      * used to identify the display. */
  3190. {
  3191.     POINTL pos;
  3192.     HWND hwnd;
  3193.     TkWindow *winPtr;
  3194.  
  3195.     pos.x = rootX;
  3196.     /* Translate to PM coordinates */
  3197.     pos.y = yScreen - rootY;
  3198.     hwnd = WinWindowFromPoint(HWND_DESKTOP, &pos, TRUE);
  3199.  
  3200. #ifdef VERBOSE
  3201.     printf("Tk_CoordsToWindow (%d,%d) PM %d tkwin %x gave hwnd %x\n", rootX,
  3202.            rootY, pos.y, tkwin, hwnd);
  3203. #endif
  3204.  
  3205.     winPtr = (TkWindow *) Tk_HWNDToWindow(hwnd);
  3206. #ifdef VERBOSE
  3207.     printf("Tk_HWNDToWindow (%x) winPtr %x\n", hwnd, winPtr);
  3208. #endif
  3209.     if (winPtr && (winPtr->mainPtr == ((TkWindow *) tkwin)->mainPtr)) {
  3210.         return (Tk_Window) winPtr;
  3211.     }
  3212.     return NULL;
  3213. }
  3214.  
  3215. /*
  3216.  *----------------------------------------------------------------------
  3217.  *
  3218.  * Tk_GetVRootGeometry --
  3219.  *
  3220.  *    This procedure returns information about the virtual root
  3221.  *    window corresponding to a particular Tk window.
  3222.  *
  3223.  * Results:
  3224.  *    The values at xPtr, yPtr, widthPtr, and heightPtr are set
  3225.  *    with the offset and dimensions of the root window corresponding
  3226.  *    to tkwin.  If tkwin is being managed by a virtual root window
  3227.  *    manager these values correspond to the virtual root window being
  3228.  *    used for tkwin;  otherwise the offsets will be 0 and the
  3229.  *    dimensions will be those of the screen.
  3230.  *
  3231.  * Side effects:
  3232.  *    Vroot window information is refreshed if it is out of date.
  3233.  *
  3234.  *----------------------------------------------------------------------
  3235.  */
  3236.  
  3237. void
  3238. Tk_GetVRootGeometry(tkwin, xPtr, yPtr, widthPtr, heightPtr)
  3239.     Tk_Window tkwin;        /* Window whose virtual root is to be
  3240.                      * queried. */
  3241.     int *xPtr, *yPtr;        /* Store x and y offsets of virtual root
  3242.                      * here. */
  3243.     int *widthPtr, *heightPtr;    /* Store dimensions of virtual root here. */
  3244. {
  3245.     TkWindow *winPtr = (TkWindow *) tkwin;
  3246.  
  3247. #ifdef VERBOSE
  3248.     printf("Tk_GetVRootGeometry\n");
  3249. #endif
  3250.  
  3251.     *xPtr = 0;
  3252.     *yPtr = 0;
  3253.     *widthPtr = DisplayWidth(winPtr->display, winPtr->screenNum);
  3254.     *heightPtr = DisplayHeight(winPtr->display, winPtr->screenNum);
  3255. }
  3256.  
  3257. /*
  3258.  *----------------------------------------------------------------------
  3259.  *
  3260.  * Tk_MoveToplevelWindow --
  3261.  *
  3262.  *    This procedure is called instead of Tk_MoveWindow to adjust
  3263.  *    the x-y location of a top-level window.  It delays the actual
  3264.  *    move to a later time and keeps window-manager information
  3265.  *    up-to-date with the move
  3266.  *
  3267.  * Results:
  3268.  *    None.
  3269.  *
  3270.  * Side effects:
  3271.  *    The window is eventually moved so that its upper-left corner
  3272.  *    (actually, the upper-left corner of the window's decorative
  3273.  *    frame, if there is one) is at (x,y).
  3274.  *
  3275.  *----------------------------------------------------------------------
  3276.  */
  3277.  
  3278. void
  3279. Tk_MoveToplevelWindow(tkwin, x, y)
  3280.     Tk_Window tkwin;        /* Window to move. */
  3281.     int x, y;            /* New location for window (within
  3282.                      * parent). */
  3283. {
  3284.     TkWindow *winPtr = (TkWindow *) tkwin;
  3285.     register WmInfo *wmPtr = winPtr->wmInfoPtr;
  3286.  
  3287. #ifdef VERBOSE
  3288.     printf("Tk_MoveToplevelWindow\n");
  3289. #endif
  3290.  
  3291.     if (!(winPtr->flags & TK_TOP_LEVEL)) {
  3292.         panic("Tk_MoveToplevelWindow called with non-toplevel window");
  3293.     }
  3294.     wmPtr->x = x;
  3295.     wmPtr->y = y;
  3296.     wmPtr->flags |= WM_MOVE_PENDING;
  3297.     wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y);
  3298.     if ((wmPtr->sizeHintsFlags & (USPosition|PPosition)) == 0) {
  3299.         wmPtr->sizeHintsFlags |= USPosition;
  3300.     }
  3301.  
  3302.     /*
  3303.      * If the window has already been mapped, must bring its geometry
  3304.      * up-to-date immediately, otherwise an event might arrive from the
  3305.      * server that would overwrite wmPtr->x and wmPtr->y and lose the
  3306.      * new position.
  3307.      */
  3308.  
  3309.     if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
  3310.         if (wmPtr->flags & WM_UPDATE_PENDING) {
  3311.             Tk_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
  3312.         }
  3313.         UpdateGeometryInfo((ClientData) winPtr);
  3314.     }
  3315. }
  3316.  
  3317. /*
  3318.  *----------------------------------------------------------------------
  3319.  *
  3320.  * TkWmProtocolEventProc --
  3321.  *
  3322.  *    This procedure is called by the Tk_HandleEvent whenever a
  3323.  *    ClientMessage event arrives whose type is "WM_PROTOCOLS".
  3324.  *    This procedure handles the message from the window manager
  3325.  *    in an appropriate fashion.
  3326.  *
  3327.  * Results:
  3328.  *    None.
  3329.  *
  3330.  * Side effects:
  3331.  *    Depends on what sort of handler, if any, was set up for the
  3332.  *    protocol.
  3333.  *
  3334.  *----------------------------------------------------------------------
  3335.  */
  3336.  
  3337. void
  3338. TkWmProtocolEventProc(winPtr, eventPtr)
  3339.     TkWindow *winPtr;        /* Window to which the event was sent. */
  3340.     XEvent *eventPtr;        /* X event. */
  3341. {
  3342.     WmInfo *wmPtr;
  3343.     register ProtocolHandler *protPtr;
  3344.     Atom protocol;
  3345.     int result;
  3346.     Tcl_Interp *interp;
  3347.  
  3348. #ifdef VERBOSE
  3349.     printf("TkWmProtocolEventProc\n");
  3350. #endif
  3351.  
  3352.     wmPtr = winPtr->wmInfoPtr;
  3353.     if (wmPtr == NULL) {
  3354.         return;
  3355.     }
  3356.     protocol = (Atom) eventPtr->xclient.data.l[0];
  3357.     for (protPtr = wmPtr->protPtr; protPtr != NULL;
  3358.             protPtr = protPtr->nextPtr) {
  3359.         if (protocol == protPtr->protocol) {
  3360.             Tcl_Preserve((ClientData) protPtr);
  3361.             interp = protPtr->interp;
  3362.             Tcl_Preserve((ClientData) interp);
  3363.             result = Tcl_GlobalEval(interp, protPtr->command);
  3364.             if (result != TCL_OK) {
  3365.                 Tcl_AddErrorInfo(interp, "\n    (command for \"");
  3366.                 Tcl_AddErrorInfo(interp,
  3367.                         Tk_GetAtomName((Tk_Window) winPtr, protocol));
  3368.                 Tcl_AddErrorInfo(interp, "\" window manager protocol)");
  3369.                 Tcl_BackgroundError(interp);
  3370.             }
  3371.             Tcl_Release((ClientData) interp);
  3372.             Tcl_Release((ClientData) protPtr);
  3373.             return;
  3374.         }
  3375.     }
  3376.  
  3377.     /*
  3378.      * No handler was present for this protocol.  If this is a
  3379.      * WM_DELETE_WINDOW message then just destroy the window.
  3380.      */
  3381.  
  3382.     if (protocol == Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW")) {
  3383.         Tk_DestroyWindow((Tk_Window) winPtr);
  3384.     }
  3385. }
  3386.  
  3387. /*
  3388.  *----------------------------------------------------------------------
  3389.  *
  3390.  * TkWmRestackToplevel --
  3391.  *
  3392.  *    This procedure restacks a top-level window.
  3393.  *
  3394.  * Results:
  3395.  *    None.
  3396.  *
  3397.  * Side effects:
  3398.  *    WinPtr gets restacked  as specified by aboveBelow and otherPtr.
  3399.  *    This procedure doesn't return until the restack has taken
  3400.  *    effect and the ConfigureNotify event for it has been received.
  3401.  *
  3402.  *----------------------------------------------------------------------
  3403.  */
  3404.  
  3405. void
  3406. TkWmRestackToplevel(winPtr, aboveBelow, otherPtr)
  3407.     TkWindow *winPtr;        /* Window to restack. */
  3408.     int aboveBelow;        /* Gives relative position for restacking;
  3409.                      * must be Above or Below. */
  3410.     TkWindow *otherPtr;        /* Window relative to which to restack;
  3411.                      * if NULL, then winPtr gets restacked
  3412.                      * above or below *all* siblings. */
  3413. {
  3414.     HWND hwnd, insertAfter;
  3415.  
  3416. #ifdef VERBOSE
  3417.     printf("TkWmRestackToplevel\n");
  3418. #endif
  3419.     /*
  3420.      * Can't set stacking order properly until the window is on the
  3421.      * screen (mapping it may give it a reparent window).
  3422.      */
  3423.  
  3424.     if (winPtr->window == None) {
  3425.         Tk_MakeWindowExist((Tk_Window) winPtr);
  3426.     }
  3427.     if (winPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {
  3428.         TkWmMapWindow(winPtr);
  3429.     }
  3430.     hwnd = (winPtr->wmInfoPtr->wrapper != NULLHANDLE)
  3431.         ? winPtr->wmInfoPtr->wrapper : Tk_GetHWND(winPtr->window);
  3432.  
  3433.     if (otherPtr != NULL) {
  3434.         if (otherPtr->window == None) {
  3435.             Tk_MakeWindowExist((Tk_Window) otherPtr);
  3436.         }
  3437.         if (otherPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {
  3438.             TkWmMapWindow(otherPtr);
  3439.         }
  3440.         insertAfter = (otherPtr->wmInfoPtr->wrapper != NULLHANDLE)
  3441.             ? otherPtr->wmInfoPtr->wrapper : Tk_GetHWND(otherPtr->window);
  3442.     } else {
  3443.         insertAfter = NULLHANDLE;
  3444.     }
  3445.  
  3446.     TkOS2SetWindowPos(hwnd, insertAfter, aboveBelow);
  3447. }
  3448.  
  3449. /*
  3450.  *----------------------------------------------------------------------
  3451.  *
  3452.  * TkWmAddToColormapWindows --
  3453.  *
  3454.  *    This procedure is called to add a given window to the
  3455.  *    WM_COLORMAP_WINDOWS property for its top-level, if it
  3456.  *    isn't already there.  It is invoked by the Tk code that
  3457.  *    creates a new colormap, in order to make sure that colormap
  3458.  *    information is propagated to the window manager by default.
  3459.  *
  3460.  * Results:
  3461.  *    None.
  3462.  *
  3463.  * Side effects:
  3464.  *    WinPtr's window gets added to the WM_COLORMAP_WINDOWS
  3465.  *    property of its nearest top-level ancestor, unless the
  3466.  *    colormaps have been set explicitly with the
  3467.  *    "wm colormapwindows" command.
  3468.  *
  3469.  *----------------------------------------------------------------------
  3470.  */
  3471.  
  3472. void
  3473. TkWmAddToColormapWindows(winPtr)
  3474.     TkWindow *winPtr;        /* Window with a non-default colormap.
  3475.                      * Should not be a top-level window. */
  3476. {
  3477.     TkWindow *topPtr;
  3478.     TkWindow **oldPtr, **newPtr;
  3479.     int count, i;
  3480.  
  3481. #ifdef VERBOSE
  3482.     printf("TkWmAddToColormapWindows\n");
  3483. #endif
  3484.  
  3485.     if (winPtr->window == None) {
  3486.         return;
  3487.     }
  3488.  
  3489.     for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) {
  3490.         if (topPtr == NULL) {
  3491.             /*
  3492.              * Window is being deleted.  Skip the whole operation.
  3493.              */
  3494.  
  3495.             return;
  3496.         }
  3497.         if (topPtr->flags & TK_TOP_LEVEL) {
  3498.             break;
  3499.         }
  3500.     }
  3501.     if (topPtr->wmInfoPtr->flags & WM_COLORMAPS_EXPLICIT) {
  3502.         return;
  3503.     }
  3504.  
  3505.     /*
  3506.      * Make sure that the window isn't already in the list.
  3507.      */
  3508.  
  3509.     count = topPtr->wmInfoPtr->cmapCount;
  3510.     oldPtr = topPtr->wmInfoPtr->cmapList;
  3511.  
  3512.     for (i = 0; i < count; i++) {
  3513. #ifdef VERBOSE
  3514.         printf("    oldPtr[%d] = %s\n", i, oldPtr[i]->pathName);
  3515. #endif
  3516.         if (oldPtr[i] == winPtr) {
  3517.             return;
  3518.         }
  3519.     }
  3520.  
  3521.     /*
  3522.      * Make a new bigger array and use it to reset the property.
  3523.      * Automatically add the toplevel itself as the last element
  3524.      * of the list.
  3525.      */
  3526.  
  3527.     newPtr = (TkWindow **) ckalloc((unsigned) ((count+2)*sizeof(TkWindow*)));
  3528.     if (count > 0) {
  3529.         memcpy(newPtr, oldPtr, count * sizeof(TkWindow*));
  3530.     }
  3531.     if (count == 0) {
  3532.         count++;
  3533.     }
  3534.     newPtr[count-1] = winPtr;
  3535.     newPtr[count] = topPtr;
  3536. #ifdef VERBOSE
  3537.     printf("    cmapList[count-1 = %d] = %s, cmapList[count] = %s\n", count-1,
  3538.            winPtr->pathName, topPtr->pathName);
  3539.     fflush(stdout);
  3540. #endif
  3541.     if (oldPtr != NULL) {
  3542.         ckfree((char *) oldPtr);
  3543.     }
  3544.  
  3545.     topPtr->wmInfoPtr->cmapList = newPtr;
  3546.     topPtr->wmInfoPtr->cmapCount = count+1;
  3547.  
  3548.     /*
  3549.      * Now we need to force the updated colormaps to be installed.
  3550.      */
  3551.  
  3552.     if (topPtr->wmInfoPtr == foregroundWmPtr) {
  3553.         /* WM_QUERYNEWPALETTE -> WM_REALIZEPALETTE + focus notification */
  3554.         InstallColormaps(topPtr->wmInfoPtr->wrapper, WM_REALIZEPALETTE, 1);
  3555.     } else {
  3556.         /* WM_PALETTECHANGED -> WM_REALIZEPALETTE + focus notification */
  3557.         InstallColormaps(topPtr->wmInfoPtr->wrapper, WM_REALIZEPALETTE, 0);
  3558.     }
  3559. }
  3560.  
  3561. /*
  3562.  *----------------------------------------------------------------------
  3563.  *
  3564.  * TkWmRemoveFromColormapWindows --
  3565.  *
  3566.  *      This procedure is called to remove a given window from the
  3567.  *      WM_COLORMAP_WINDOWS property for its top-level.  It is invoked
  3568.  *      when windows are deleted.
  3569.  *
  3570.  * Results:
  3571.  *      None.
  3572.  *
  3573.  * Side effects:
  3574.  *      WinPtr's window gets removed from the WM_COLORMAP_WINDOWS
  3575.  *      property of its nearest top-level ancestor, unless the
  3576.  *      top-level itself is being deleted too.
  3577.  *
  3578.  *----------------------------------------------------------------------
  3579.  */
  3580.  
  3581. void
  3582. TkWmRemoveFromColormapWindows(winPtr)
  3583.     TkWindow *winPtr;           /* Window that may be present in
  3584.                                  * WM_COLORMAP_WINDOWS property for its
  3585.                                  * top-level.  Should not be a top-level
  3586.                                  * window. */
  3587. {
  3588.     TkWindow *topPtr;
  3589.     TkWindow **oldPtr;
  3590.     int count, i, j;
  3591.  
  3592. #ifdef VERBOSE
  3593.     printf("TkWmRemoveFromColormapWindows\n");
  3594. #endif
  3595.  
  3596.     for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) {
  3597.         if (topPtr == NULL) {
  3598.             /*
  3599.              * Ancestors have been deleted, so skip the whole operation.
  3600.              * Seems like this can't ever happen?
  3601.              */
  3602.  
  3603.             return;
  3604.         }
  3605.         if (topPtr->flags & TK_TOP_LEVEL) {
  3606.             break;
  3607.         }
  3608.     }
  3609.     if (topPtr->flags & TK_ALREADY_DEAD) {
  3610.         /*
  3611.          * Top-level is being deleted, so there's no need to cleanup
  3612.          * the WM_COLORMAP_WINDOWS property.
  3613.          */
  3614.  
  3615.         return;
  3616.     }
  3617.  
  3618.     /*
  3619.      * Find the window and slide the following ones down to cover
  3620.      * it up.
  3621.      */
  3622.  
  3623.     count = topPtr->wmInfoPtr->cmapCount;
  3624.     oldPtr = topPtr->wmInfoPtr->cmapList;
  3625.     for (i = 0; i < count; i++) {
  3626.         if (oldPtr[i] == winPtr) {
  3627.             for (j = i ; j < count-1; j++) {
  3628.                 oldPtr[j] = oldPtr[j+1];
  3629.             }
  3630.             topPtr->wmInfoPtr->cmapCount = count-1;
  3631.             break;
  3632.         }
  3633.     }
  3634. }
  3635.  
  3636. /*
  3637.  *----------------------------------------------------------------------
  3638.  *
  3639.  * TkOS2SetMenu --
  3640.  *
  3641.  *      Associcates a given menu window handle to a window.
  3642.  *
  3643.  * Results:
  3644.  *      None.
  3645.  *
  3646.  * Side effects:
  3647.  *      The menu will end up being drawn in the window, and the geometry
  3648.  *      of the window will have to be changed.
  3649.  *
  3650.  *----------------------------------------------------------------------
  3651.  */
  3652.  
  3653. void
  3654. TkOS2SetMenu(tkwin, hMenu)
  3655.     Tk_Window tkwin;            /* the window to put the menu in */
  3656.     HWND hMenu;                 /* the menu to set */
  3657. {
  3658.     TkWindow *winPtr = (TkWindow *) tkwin;
  3659.     WmInfo *wmPtr = winPtr->wmInfoPtr;
  3660. #ifdef VERBOSE
  3661.     printf("TkOS2SetMenu tkwin %x, hMenu %x\n", tkwin, hMenu);
  3662. #endif
  3663.  
  3664.     wmPtr->hMenu = hMenu;
  3665.  
  3666.     if (!(wmPtr->flags & TK_EMBEDDED)) {
  3667.         if (!(wmPtr->flags & WM_NEVER_MAPPED) && (hMenu != NULLHANDLE)) {
  3668.             int syncPending = wmPtr->flags & WM_SYNC_PENDING;
  3669.  
  3670.             wmPtr->flags |= WM_SYNC_PENDING;
  3671.             rc = WinSetParent(hMenu, wmPtr->wrapper, FALSE);
  3672. #ifdef VERBOSE
  3673.             printf("    WinSetParent(menu %x, parent %x, FALSE) returns %d\n",
  3674.                    hMenu, wmPtr->wrapper, rc);
  3675. #endif
  3676.             WinSetOwner(hMenu, wmPtr->wrapper);
  3677.             WinSendMsg(wmPtr->wrapper, WM_UPDATEFRAME, MPFROMLONG(FCF_MENU),
  3678.                        MPVOID);
  3679.             if (!syncPending) {
  3680.                 wmPtr->flags &= ~WM_SYNC_PENDING;
  3681.             }
  3682.         }
  3683.         if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
  3684.             Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
  3685.             wmPtr->flags |= WM_UPDATE_PENDING|WM_MOVE_PENDING;
  3686.         }
  3687.     }
  3688. }
  3689.  
  3690. /*
  3691.  *----------------------------------------------------------------------
  3692.  *
  3693.  * ConfigureTopLevel --
  3694.  *
  3695.  *    Generate a ConfigureNotify event based on the current position
  3696.  *    information.  This procedure is called by WmProc.
  3697.  *
  3698.  * Results:
  3699.  *    None.
  3700.  *
  3701.  * Side effects:
  3702.  *    Queues a new event.
  3703.  *
  3704.  *----------------------------------------------------------------------
  3705.  */
  3706.  
  3707. static void
  3708. ConfigureTopLevel(pos)
  3709.     SWP *pos; /* OS/2 PM y-coordinate */
  3710. {
  3711.     TkWindow *winPtr = GetTopLevel(pos->hwnd);
  3712.     WmInfo *wmPtr;
  3713.     int state;                  /* Current window state. */
  3714.     RECTL rectl;
  3715.     HWND client;
  3716.  
  3717. #ifdef VERBOSE
  3718.     printf("ConfigureTopLevel %x fl %x old %x, (%d,%d) %dx%d (x11y %d) c %x\n",
  3719.            pos->hwnd, pos[0].fl, pos[1].fl, pos->x, pos->y, pos->cx, pos->cy,
  3720.            yScreen - pos->cy - pos->y, WinWindowFromID(pos->hwnd, FID_CLIENT));
  3721. #endif
  3722.  
  3723.     if (winPtr == NULL) {
  3724.         return;
  3725.     }
  3726.  
  3727.     wmPtr = winPtr->wmInfoPtr;
  3728.  
  3729.     /*
  3730.      * Determine the current window state.
  3731.      */
  3732.  
  3733.     if (!WinIsWindowVisible(wmPtr->wrapper)) {
  3734.         state = WithdrawnState;
  3735.     } else {
  3736.         if (pos[0].fl & SWP_MAXIMIZE) {
  3737.             state = ZoomState;
  3738.         } else if (pos[0].fl & SWP_MINIMIZE) {
  3739.             state = IconicState;
  3740.         } else {
  3741.             state = NormalState;
  3742.         }
  3743.     }
  3744. #ifdef VERBOSE
  3745.     printf("ConfigureTopLevel %x state %s\n", wmPtr->wrapper,
  3746.            state == WithdrawnState ? "WithdrawnState" :
  3747.            (state == ZoomState ? "ZoomState" :
  3748.             (state == IconicState ? "IconicState" :
  3749.              (state == NormalState ? "NormalState" : "UNKNOWN"))));
  3750. #endif
  3751.  
  3752.     /*
  3753.      * If the state of the window just changed, be sure to update the
  3754.      * child window information.
  3755.      */
  3756.  
  3757.     if (wmPtr->hints.initial_state != state) {
  3758.         wmPtr->hints.initial_state = state;
  3759.         switch (state) {
  3760.             case WithdrawnState:
  3761.             case IconicState:
  3762.                 XUnmapWindow(winPtr->display, winPtr->window);
  3763.                 break;
  3764.  
  3765.             case NormalState:
  3766.                 /*
  3767.                  * Schedule a geometry update.  Since we ignore geometry
  3768.                  * requests while in any other state, the geometry info
  3769.                  * may be stale.
  3770.                  */
  3771.  
  3772.                 if (!(wmPtr->flags & WM_UPDATE_PENDING)) {
  3773.                     Tcl_DoWhenIdle(UpdateGeometryInfo,
  3774.                             (ClientData) winPtr);
  3775.                     wmPtr->flags |= WM_UPDATE_PENDING;
  3776.                 }
  3777.                 /* fall through */
  3778.             case ZoomState:
  3779.                 XMapWindow(winPtr->display, winPtr->window);
  3780.                 pos[0].fl &= ~(SWP_MOVE | SWP_SIZE);
  3781.                 break;
  3782.         }
  3783.     }
  3784.  
  3785.     /*
  3786.      * Don't report geometry changes in the Iconic or Withdrawn states.
  3787.      */
  3788.  
  3789.     if (state == WithdrawnState || state == IconicState) {
  3790.         return;
  3791.     }
  3792.  
  3793.     /*
  3794.      * Compute the current geometry of the client area, reshape the
  3795.      * Tk window and generate a ConfigureNotify event.
  3796.      */
  3797.  
  3798.     client = WinWindowFromID(pos->hwnd, FID_CLIENT);
  3799.     rectl.xLeft = pos->x;
  3800.     rectl.xRight = pos->x + pos->cx;
  3801.     rectl.yBottom = pos->y;
  3802.     rectl.yTop = pos->y + pos->cy;
  3803. #ifdef VERBOSE
  3804.     printf("WinCalcFrameRect frame %x (%d,%d)(%d,%d) =>\n", pos->hwnd,
  3805.            rectl.xLeft, rectl.yBottom, rectl.xRight, rectl.yTop);
  3806. #endif
  3807.     rc = WinCalcFrameRect(pos->hwnd, &rectl, TRUE);
  3808. #ifdef VERBOSE
  3809.     printf("WinCalcFrameRect => (%d,%d)(%d,%d)\n", rectl.xLeft, rectl.yBottom,
  3810.            rectl.xRight, rectl.yTop);
  3811.     if (rc == TRUE) {
  3812.         printf("    configure WinCalcFrameRect OK => (%d,%d) (%d,%d)\n",
  3813.                rectl.xLeft, rectl.yBottom, rectl.xRight, rectl.yTop);
  3814.     } else {
  3815.         printf("    configure WinCalcFrameRect ERROR %x => (%d,%d) (%d,%d)\n",
  3816.                WinGetLastError(TclOS2GetHAB()), rectl.xLeft, rectl.yBottom,
  3817.            rectl.xRight, rectl.yTop);
  3818.     }
  3819. #endif
  3820.     winPtr->changes.x = rectl.xLeft;
  3821.     winPtr->changes.width = rectl.xRight - rectl.xLeft;
  3822.     winPtr->changes.height = rectl.yTop - rectl.yBottom;
  3823.     winPtr->changes.y = yScreen - rectl.yTop;
  3824. #ifdef VERBOSE
  3825.     printf("winPtr->changes (%d,%d) %dx%d\n", winPtr->changes.x,
  3826.            winPtr->changes.y, winPtr->changes.width, winPtr->changes.height);
  3827. #endif
  3828.     wmPtr->borderHeight = pos->cy - winPtr->changes.height;
  3829. #ifdef VERBOSE
  3830.     printf("    borderHeight %d (%d - %d)\n", wmPtr->borderHeight, pos->cy,
  3831.            winPtr->changes.height);
  3832. #endif
  3833.     rc = WinSetWindowPos(client, HWND_TOP, rectl.xLeft - pos->x,
  3834.                          rectl.yBottom - pos->y,
  3835.                          winPtr->changes.width, winPtr->changes.height,
  3836.                          SWP_SIZE | SWP_MOVE | SWP_NOADJUST);
  3837. #ifdef VERBOSE
  3838.     if (rc == TRUE) {
  3839.          printf("    WinSetWindowPos h %x (%d,%d) %dx%d returned %d (BH %d)\n",
  3840.                 client, rectl.xLeft - pos->x, rectl.yBottom - pos->y,
  3841.                 winPtr->changes.width, winPtr->changes.height, rc,
  3842.                 wmPtr->borderHeight);
  3843.     } else {
  3844.          printf("    WinSetWindowPos h %x (%d,%d) %dx%d ERROR %d (BH %d)\n",
  3845.                 client, rectl.xLeft - pos->x, rectl.yBottom - pos->y,
  3846.                 winPtr->changes.width, winPtr->changes.height,
  3847.                 WinGetLastError(TclOS2GetHAB()), wmPtr->borderHeight);
  3848.     }
  3849. #endif
  3850.     GenerateConfigureNotify(winPtr);
  3851.  
  3852.     /*
  3853.      * Update window manager geometry info if needed.
  3854.      */
  3855.  
  3856.     if (state == NormalState) {
  3857.  
  3858.         /*
  3859.          * Update size information from the event.  There are a couple of
  3860.          * tricky points here:
  3861.          *
  3862.          * 1. If the user changed the size externally then set wmPtr->width
  3863.          *    and wmPtr->height just as if a "wm geometry" command had been
  3864.          *    invoked with the same information.
  3865.          * 2. However, if the size is changing in response to a request
  3866.          *    coming from us (sync is set), then don't set
  3867.          *    wmPtr->width or wmPtr->height (otherwise the window will stop
  3868.          *    tracking geometry manager requests).
  3869.          */
  3870.  
  3871.         if (!(wmPtr->flags & WM_SYNC_PENDING)) {
  3872.             if (pos->fl & SWP_SIZE) {
  3873.                 if ((wmPtr->width == -1)
  3874.                         && (winPtr->changes.width == winPtr->reqWidth)) {
  3875.                     /*
  3876.                      * Don't set external width, since the user didn't
  3877.                      * change it from what the widgets asked for.
  3878.                      */
  3879.                 } else {
  3880.                     if (wmPtr->gridWin != NULL) {
  3881.                         wmPtr->width = wmPtr->reqGridWidth
  3882.                             + (winPtr->changes.width - winPtr->reqWidth)
  3883.                             / wmPtr->widthInc;
  3884.                         if (wmPtr->width < 0) {
  3885.                             wmPtr->width = 0;
  3886.                         }
  3887.                     } else {
  3888.                         wmPtr->width = winPtr->changes.width;
  3889.                     }
  3890.                 }
  3891.                 if ((wmPtr->height == -1)
  3892.                         && (winPtr->changes.height == winPtr->reqHeight)) {
  3893.                     /*
  3894.                      * Don't set external height, since the user didn't change
  3895.                      * it from what the widgets asked for.
  3896.                      */
  3897.                 } else {
  3898.                     if (wmPtr->gridWin != NULL) {
  3899.                         wmPtr->height = wmPtr->reqGridHeight
  3900.                             + (winPtr->changes.height - winPtr->reqHeight)
  3901.                             / wmPtr->heightInc;
  3902.                         if (wmPtr->height < 0) {
  3903.                             wmPtr->height = 0;
  3904.                         }
  3905.                     } else {
  3906.                         wmPtr->height = winPtr->changes.height;
  3907.                     }
  3908.                 }
  3909.                 wmPtr->configWidth = winPtr->changes.width;
  3910.                 wmPtr->configHeight = winPtr->changes.height;
  3911.             }
  3912.             /*
  3913.              * If the user moved the window, we should switch back
  3914.              * to normal coordinates.
  3915.              */
  3916.  
  3917.             if (pos->fl & SWP_MOVE) {
  3918.                 wmPtr->flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y);
  3919.             }
  3920.         }
  3921.  
  3922.         /*
  3923.          * Update the wrapper window location information.
  3924.          */
  3925.  
  3926.         if (wmPtr->flags & WM_NEGATIVE_X) {
  3927.             wmPtr->x = DisplayWidth(winPtr->display, winPtr->screenNum)
  3928.                 - pos->x - (winPtr->changes.width
  3929.                         + wmPtr->borderWidth);
  3930.         } else {
  3931.             wmPtr->x = pos->x;
  3932.         }
  3933.         if (wmPtr->flags & WM_NEGATIVE_Y) {
  3934.             wmPtr->y = pos->y;
  3935.         } else {
  3936.             wmPtr->y = yScreen - pos->y -
  3937.                        (winPtr->changes.height + wmPtr->borderHeight);
  3938.         }
  3939.     }
  3940. }
  3941.  
  3942. /*
  3943.  *----------------------------------------------------------------------
  3944.  *
  3945.  * GenerateConfigureNotify --
  3946.  *
  3947.  *      Generate a ConfigureNotify event from the current geometry
  3948.  *      information for the specified toplevel window.
  3949.  *
  3950.  * Results:
  3951.  *      None.
  3952.  *
  3953.  * Side effects:
  3954.  *      Sends an X event.
  3955.  *
  3956.  *----------------------------------------------------------------------
  3957.  */
  3958.  
  3959. static void
  3960. GenerateConfigureNotify(winPtr)
  3961.     TkWindow *winPtr;
  3962. {
  3963.     XEvent event;
  3964.  
  3965. #ifdef VERBOSE
  3966.     printf("GenerateConfigureNotify winPtr %x\n", winPtr);
  3967. #endif
  3968.  
  3969.     /*
  3970.      * Generate a ConfigureNotify event.
  3971.      */
  3972.  
  3973.     event.type = ConfigureNotify;
  3974.     event.xconfigure.serial = winPtr->display->request;
  3975.     event.xconfigure.send_event = False;
  3976.     event.xconfigure.display = winPtr->display;
  3977.     event.xconfigure.event = winPtr->window;
  3978.     event.xconfigure.window = winPtr->window;
  3979.     event.xconfigure.border_width = winPtr->changes.border_width;
  3980.     event.xconfigure.override_redirect = winPtr->atts.override_redirect;
  3981.     event.xconfigure.x = winPtr->changes.x;
  3982.     event.xconfigure.y = winPtr->changes.y;
  3983.     event.xconfigure.width = winPtr->changes.width;
  3984.     event.xconfigure.height = winPtr->changes.height;
  3985.     event.xconfigure.above = None;
  3986.     Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
  3987. }
  3988.  
  3989. /*
  3990.  *----------------------------------------------------------------------
  3991.  *
  3992.  * InstallColormaps --
  3993.  *
  3994.  *    Installs the colormaps associated with the toplevel which is
  3995.  *    currently active.
  3996.  *
  3997.  * Results:
  3998.  *    None
  3999.  *
  4000.  * Side effects:
  4001.  *    May change the system palette and generate damage.
  4002.  *
  4003.  *----------------------------------------------------------------------
  4004.  */
  4005.  
  4006. static MRESULT
  4007. InstallColormaps(hwnd, message, isForemost)
  4008.     HWND hwnd;            /* Toplevel wrapper window whose colormaps
  4009.                      * should be installed. */
  4010.     ULONG message;        /* Either WM_REALIZEPALETTE or
  4011.                      * WM_SETFOCUS */
  4012.     int isForemost;        /* 1 if window is foremost, else 0 */
  4013. {
  4014.     int i;
  4015.     HPS hps, winPS;
  4016.     HWND winHwnd;
  4017.     HPAL oldPalette;
  4018.     ULONG colorsChanged;
  4019.     TkWindow *winPtr = GetTopLevel(hwnd);
  4020.     WmInfo *wmPtr;
  4021.  
  4022. #ifdef VERBOSE
  4023.     printf("InstallColormap hwnd %x msg %s fore %d\n", hwnd,
  4024.            message == WM_SETFOCUS ? "WM_SETFOCUS" : "WM_REALIZEPALETTE",
  4025.            isForemost);
  4026. #endif
  4027.             
  4028.     if (winPtr == NULL) {
  4029.         return (MRESULT) 0;
  4030.     }
  4031.  
  4032.     wmPtr = winPtr->wmInfoPtr;
  4033. /*****
  4034.     if (message == WM_SETFOCUS) {
  4035.  
  4036.         foregroundWmPtr = wmPtr;
  4037.  
  4038.         if (wmPtr->cmapCount > 0) {
  4039.             winPtr = wmPtr->cmapList[0];
  4040.         }
  4041.  
  4042.         systemPalette = TkOS2GetPalette(winPtr->atts.colormap);
  4043.         hps = WinGetPS(hwnd);
  4044.         oldPalette = GpiSelectPalette(hps, systemPalette);
  4045.         if (WinRealizePalette(hwnd, hps, &colorsChanged) > 0) {
  4046.             RefreshColormap(winPtr->atts.colormap);
  4047.         } else if (wmPtr->cmapCount > 1) {
  4048.             GpiSelectPalette(hps, oldPalette);
  4049.             WinRealizePalette(hwnd, hps, &colorsChanged);
  4050.             WinReleasePS(hps);
  4051.             WinSendMsg(hwnd, WM_REALIZEPALETTE, (MPARAM)0L, (MPARAM)0L);
  4052.             return TRUE;
  4053.         }
  4054.         WinReleasePS(hps);
  4055.  
  4056.     } else {
  4057.  
  4058.  
  4059.         if (!isForemost) {
  4060.             if (wmPtr->cmapCount > 0) {
  4061.                 winPtr = wmPtr->cmapList[0];
  4062.             }
  4063.             i = 1;
  4064.         } else {
  4065.             if (wmPtr->cmapCount <= 1) {
  4066.                 return TRUE;
  4067.             }
  4068.             winPtr = wmPtr->cmapList[1];
  4069.             i = 2;
  4070.         }
  4071.         hps = WinGetPS(hwnd);
  4072.         oldPalette = GpiSelectPalette(hps,
  4073.                                       TkOS2GetPalette(winPtr->atts.colormap));
  4074.         if (WinRealizePalette(hwnd, hps, &colorsChanged) > 0) {
  4075.             RefreshColormap(winPtr->atts.colormap);
  4076.         }
  4077.         for (; i < wmPtr->cmapCount; i++) {
  4078.             winPtr = wmPtr->cmapList[i];
  4079.             winHwnd = TkOS2GetHWND(winPtr->window);
  4080.             winPS = WinGetPS(winHwnd);
  4081.             GpiSelectPalette(winPS, TkOS2GetPalette(winPtr->atts.colormap));
  4082.             if (WinRealizePalette(winHwnd, winPS, &colorsChanged)) {
  4083.                 RefreshColormap(winPtr->atts.colormap);
  4084.             }
  4085.             WinReleasePS(winPS);
  4086.         }
  4087.         WinReleasePS(hps);
  4088.     }
  4089.  
  4090.     return TRUE;
  4091. *****/
  4092.  
  4093.     hps = WinGetPS(hwnd);
  4094.  
  4095.     /*
  4096.      * The application should call WinRealizePalette if it has a palette,
  4097.      * or pass on to the default window procedure if it doesn't.
  4098.      * If the return value from WinRealizePalette is greater than 0, the
  4099.      * application should invalidate its window to cause a repaint using
  4100.      * the newly-realized palette.
  4101.      */
  4102.  
  4103.     /*
  4104.      * Install all of the palettes.
  4105.      */
  4106.  
  4107.     if (wmPtr->cmapCount > 0) {
  4108.         winPtr = wmPtr->cmapList[0];
  4109.     }
  4110.     i = 1;
  4111.  
  4112.     oldPalette = GpiSelectPalette(hps, TkOS2GetPalette(winPtr->atts.colormap));
  4113. #ifdef VERBOSE
  4114.     printf("    GpiSelectPalette returns %d\n", oldPalette);
  4115. #endif
  4116.     if ( WinRealizePalette(hwnd, hps, &colorsChanged) > 0 ) {
  4117. #ifdef VERBOSE
  4118.         printf("    WinRealizePalette %x %x returns %d\n", hwnd, hps,
  4119.                colorsChanged);
  4120. #endif
  4121.         /* Invalidates window to cause repaint with newly realized palette */
  4122.         RefreshColormap(winPtr->atts.colormap);
  4123.     }
  4124.     for (; i < wmPtr->cmapCount; i++) {
  4125.         winPtr = wmPtr->cmapList[i];
  4126. #ifdef VERBOSE
  4127.         printf("    colormap for %s\n", winPtr->pathName);
  4128.         fflush(stdout);
  4129. #endif
  4130.         winHwnd = TkOS2GetHWND(winPtr->window);
  4131.         winPS = WinGetPS(winHwnd);
  4132.         GpiSelectPalette(winPS, TkOS2GetPalette(winPtr->atts.colormap));
  4133.         if ( WinRealizePalette(winHwnd, winPS, &colorsChanged) > 0 ) {
  4134. #ifdef VERBOSE
  4135.             printf("    WinRealizePalette %x %x returns %d\n", winHwnd, winPS,
  4136.                    colorsChanged);
  4137.             fflush(stdout);
  4138. #endif
  4139.             /* Invalidate window to cause repaint with newly realized palette */
  4140. /*
  4141.             rc = WinInvalidateRect(winHwnd, NULL, FALSE);
  4142. #ifdef VERBOSE
  4143.             if (rc == TRUE) {
  4144.                 printf("    WinInvalidateRect %x successfull\n", winHwnd);
  4145.             } else {
  4146.                 printf("    WinInvalidateRect %x ERROR %x\n", winHwnd,
  4147.                        WinGetLastError(TclOS2GetHAB()));
  4148.             }
  4149. #endif
  4150. */
  4151.         }
  4152.         WinReleasePS(winPS);
  4153.     }
  4154.  
  4155.     WinReleasePS(hps);
  4156.     return (MRESULT) TRUE;
  4157. }
  4158.  
  4159. /*
  4160.  *----------------------------------------------------------------------
  4161.  *
  4162.  * RefreshColormap --
  4163.  *
  4164.  *      This function is called to force all of the windows that use
  4165.  *      a given colormap to redraw themselves.  The quickest way to
  4166.  *      do this is to iterate over the toplevels, looking in the
  4167.  *      cmapList for matches.  This will quickly eliminate subtrees
  4168.  *      that don't use a given colormap.
  4169.  *
  4170.  * Results:
  4171.  *      None.
  4172.  *
  4173.  * Side effects:
  4174.  *      Causes damage events to be generated.
  4175.  *
  4176.  *----------------------------------------------------------------------
  4177.  */
  4178.  
  4179. static void
  4180. RefreshColormap(colormap)
  4181.     Colormap colormap;
  4182. {
  4183.     WmInfo *wmPtr;
  4184.     int i;
  4185.  
  4186. #ifdef VERBOSE
  4187.     printf("RefreshColormap\n");
  4188. #endif
  4189.  
  4190.     for (wmPtr = firstWmPtr; wmPtr != NULL; wmPtr = wmPtr->nextPtr) {
  4191.         if (wmPtr->cmapCount > 0) {
  4192.             for (i = 0; i < wmPtr->cmapCount; i++) {
  4193.                 if ((wmPtr->cmapList[i]->atts.colormap == colormap)
  4194.                         && Tk_IsMapped(wmPtr->cmapList[i])) {
  4195.                     InvalidateSubTree(wmPtr->cmapList[i], colormap);
  4196.                 }
  4197.             }
  4198.         } else if ((wmPtr->winPtr->atts.colormap == colormap)
  4199.                 && Tk_IsMapped(wmPtr->winPtr)) {
  4200.             InvalidateSubTree(wmPtr->winPtr, colormap);
  4201.         }
  4202.     }
  4203. }
  4204.  
  4205. /*
  4206.  *----------------------------------------------------------------------
  4207.  *
  4208.  * InvalidateSubTree --
  4209.  *
  4210.  *      This function recursively generates damage for a window and
  4211.  *      all of its mapped children that belong to the same toplevel and
  4212.  *      are using the specified colormap.
  4213.  *
  4214.  * Results:
  4215.  *      None.
  4216.  *
  4217.  * Side effects:
  4218.  *      Generates damage for the specified subtree.
  4219.  *
  4220.  *----------------------------------------------------------------------
  4221.  */
  4222.  
  4223. static void
  4224. InvalidateSubTree(winPtr, colormap)
  4225.     TkWindow *winPtr;
  4226.     Colormap colormap;
  4227. {
  4228.  
  4229.     TkWindow *childPtr;
  4230.  
  4231.     /*
  4232.      * Generate damage for the current window if it is using the
  4233.      * specified colormap.
  4234.      */
  4235.  
  4236. #ifdef VERBOSE
  4237.     printf("InvalidateSubTree win %x, cmap %x\n", winPtr, colormap);
  4238. #endif
  4239.  
  4240.     if (winPtr->atts.colormap == colormap) {
  4241.         WinInvalidateRect(Tk_GetHWND(winPtr->window), NULL, FALSE);
  4242.     }
  4243.  
  4244.      for (childPtr = winPtr->childList; childPtr != NULL;
  4245.              childPtr = childPtr->nextPtr) {
  4246.          /*
  4247.           * We can stop the descent when we hit an unmapped or
  4248.           * toplevel window.
  4249.           */
  4250.  
  4251.          if (!Tk_IsTopLevel(childPtr) && Tk_IsMapped(childPtr)) {
  4252. #ifdef VERBOSE
  4253.              printf("    recurse from %x to %x\n", winPtr, childPtr);
  4254. #endif
  4255.              InvalidateSubTree(childPtr, colormap);
  4256.          }
  4257.      }
  4258. }
  4259.  
  4260. /*
  4261.  *----------------------------------------------------------------------
  4262.  *
  4263.  * TkOS2GetSystemPalette --
  4264.  *
  4265.  *    Retrieves the currently installed foreground palette.
  4266.  *
  4267.  * Results:
  4268.  *    Returns the global foreground palette, if there is one.
  4269.  *    Otherwise, returns NULL.
  4270.  *
  4271.  * Side effects:
  4272.  *    None.
  4273.  *
  4274.  *----------------------------------------------------------------------
  4275.  */
  4276.  
  4277. HPAL
  4278. TkOS2GetSystemPalette()
  4279. {
  4280.     return systemPalette;
  4281. }
  4282.  
  4283. /*
  4284.  *----------------------------------------------------------------------
  4285.  *
  4286.  * GetMinSize --
  4287.  *
  4288.  *      This procedure computes the current minWidth and minHeight
  4289.  *      values for a window, taking into account the possibility
  4290.  *      that they may be defaulted.
  4291.  *
  4292.  * Results:
  4293.  *      The values at *minWidthPtr and *minHeightPtr are filled
  4294.  *      in with the minimum allowable dimensions of wmPtr's window,
  4295.  *      in grid units.  If the requested minimum is smaller than the
  4296.  *      system required minimum, then this procedure computes the
  4297.  *      smallest size that will satisfy both the system and the
  4298.  *      grid constraints.
  4299.  *
  4300.  * Side effects:
  4301.  *      None.
  4302.  *
  4303.  *----------------------------------------------------------------------
  4304.  */
  4305.  
  4306. static void
  4307. GetMinSize(wmPtr, minWidthPtr, minHeightPtr)
  4308.     WmInfo *wmPtr;              /* Window manager information for the
  4309.                                  * window. */
  4310.     int *minWidthPtr;           /* Where to store the current minimum
  4311.                                  * width of the window. */
  4312.     int *minHeightPtr;          /* Where to store the current minimum
  4313.                                  * height of the window. */
  4314. {
  4315.     int tmp, base;
  4316.     TkWindow *winPtr = wmPtr->winPtr;
  4317.  
  4318. #ifdef VERBOSE
  4319.     printf("GetMinSize %x defMW %d borderW %d defMH %d borderH %d\n",
  4320.            wmPtr->wrapper, wmPtr->defMinWidth, wmPtr->borderWidth,
  4321.            wmPtr->defMinHeight, wmPtr->borderHeight);
  4322. #endif
  4323.  
  4324.     /*
  4325.      * Compute the minimum width by taking the default client size
  4326.      * and rounding it up to the nearest grid unit.  Return the greater
  4327.      * of the default minimum and the specified minimum.
  4328.      */
  4329.  
  4330.     tmp = wmPtr->defMinWidth - wmPtr->borderWidth;
  4331.     if (tmp < 0) {
  4332.         tmp = 0;
  4333.     }
  4334.     if (wmPtr->gridWin != NULL) {
  4335.         base = winPtr->reqWidth - (wmPtr->reqGridWidth * wmPtr->widthInc);
  4336.         if (base < 0) {
  4337.             base = 0;
  4338.         }
  4339.         tmp = ((tmp - base) + wmPtr->widthInc - 1)/wmPtr->widthInc;
  4340.     }
  4341.     if (tmp < wmPtr->minWidth) {
  4342.         tmp = wmPtr->minWidth;
  4343.     }
  4344.     *minWidthPtr = tmp;
  4345.  
  4346.     /*
  4347.      * Compute the minimum height in a similar fashion.
  4348.      */
  4349.  
  4350.     tmp = wmPtr->defMinHeight - wmPtr->borderHeight;
  4351.     if (tmp < 0) {
  4352.         tmp = 0;
  4353.     }
  4354.     if (wmPtr->gridWin != NULL) {
  4355.         base = winPtr->reqHeight - (wmPtr->reqGridHeight * wmPtr->heightInc);
  4356.         if (base < 0) {
  4357.             base = 0;
  4358.         }
  4359.         tmp = ((tmp - base) + wmPtr->heightInc - 1)/wmPtr->heightInc;
  4360.     }
  4361.     if (tmp < wmPtr->minHeight) {
  4362.         tmp = wmPtr->minHeight;
  4363.     }
  4364.     *minHeightPtr = tmp;
  4365. }
  4366.  
  4367. /*
  4368.  *----------------------------------------------------------------------
  4369.  *
  4370.  * GetMaxSize --
  4371.  *
  4372.  *      This procedure computes the current maxWidth and maxHeight
  4373.  *      values for a window, taking into account the possibility
  4374.  *      that they may be defaulted.
  4375.  *
  4376.  * Results:
  4377.  *      The values at *maxWidthPtr and *maxHeightPtr are filled
  4378.  *      in with the maximum allowable dimensions of wmPtr's window,
  4379.  *      in grid units.  If no maximum has been specified for the
  4380.  *      window, then this procedure computes the largest sizes that
  4381.  *      will fit on the screen.
  4382.  *
  4383.  * Side effects:
  4384.  *      None.
  4385.  *
  4386.  *----------------------------------------------------------------------
  4387.  */
  4388.  
  4389. static void
  4390. GetMaxSize(wmPtr, maxWidthPtr, maxHeightPtr)
  4391.     WmInfo *wmPtr;              /* Window manager information for the
  4392.                                  * window. */
  4393.     int *maxWidthPtr;           /* Where to store the current maximum
  4394.                                  * width of the window. */
  4395.     int *maxHeightPtr;          /* Where to store the current maximum
  4396.                                  * height of the window. */
  4397. {
  4398.     int tmp;
  4399.  
  4400. #ifdef VERBOSE
  4401.     printf("GetMaxSize\n");
  4402. #endif
  4403.  
  4404.     if (wmPtr->maxWidth > 0) {
  4405.         *maxWidthPtr = wmPtr->maxWidth;
  4406.     } else {
  4407.         /*
  4408.          * Must compute a default width.  Fill up the display, leaving a
  4409.          * bit of extra space for the window manager's borders.
  4410.          */
  4411.  
  4412.         tmp = wmPtr->defMaxWidth - wmPtr->borderWidth;
  4413.         if (wmPtr->gridWin != NULL) {
  4414.             /*
  4415.              * Gridding is turned on;  convert from pixels to grid units.
  4416.              */
  4417.  
  4418.             tmp = wmPtr->reqGridWidth
  4419.                     + (tmp - wmPtr->winPtr->reqWidth)/wmPtr->widthInc;
  4420.         }
  4421.         *maxWidthPtr = tmp;
  4422.     }
  4423.     if (wmPtr->maxHeight > 0) {
  4424.         *maxHeightPtr = wmPtr->maxHeight;
  4425.     } else {
  4426.         tmp = wmPtr->defMaxHeight - wmPtr->borderHeight;
  4427.         if (wmPtr->gridWin != NULL) {
  4428.             tmp = wmPtr->reqGridHeight
  4429.                     + (tmp - wmPtr->winPtr->reqHeight)/wmPtr->heightInc;
  4430.         }
  4431.         *maxHeightPtr = tmp;
  4432.     }
  4433. }
  4434.  
  4435. /*
  4436.  *----------------------------------------------------------------------
  4437.  *
  4438.  * TopLevelProc --
  4439.  *
  4440.  *      Callback from OS/2 PM whenever an event occurs on a top level
  4441.  *      (plug-in) window.
  4442.  *
  4443.  * Results:
  4444.  *      Standard PM return value.
  4445.  *
  4446.  * Side effects:
  4447.  *      Default window behavior.
  4448.  *
  4449.  *----------------------------------------------------------------------
  4450.  */
  4451.  
  4452. static MRESULT EXPENTRY
  4453. TopLevelProc(hwnd, message, param1, param2)
  4454.     HWND hwnd;
  4455.     ULONG message;
  4456.     MPARAM param1;
  4457.     MPARAM param2;
  4458. {
  4459. #ifdef VERBOSE
  4460.     printf("TopLevelProc hwnd %x, msg %x, param1 %x, param2 %x\n", hwnd,
  4461.            message, param1, param2);
  4462. #endif
  4463.     if (message == WM_WINDOWPOSCHANGED) {
  4464.         SWP *pos = (SWP *) PVOIDFROMMP(param1);
  4465.         TkWindow *winPtr = (TkWindow *) Tk_HWNDToWindow(pos->hwnd);
  4466. #ifdef VERBOSE
  4467.         printf("Tk_HWNDToWindow (%x) winPtr %x (%d,%d) %dx%d\n", pos->hwnd,
  4468.                winPtr, pos->x, pos->y, pos->cx, pos->cy);
  4469. #endif
  4470.  
  4471.         if (winPtr == NULL) {
  4472.             return 0;
  4473.         }
  4474.  
  4475.         /*
  4476.          * Update the shape of the contained window.
  4477.          */
  4478.  
  4479.         if (pos->fl & SWP_SIZE) {
  4480.             winPtr->changes.width = pos->cx;
  4481.             winPtr->changes.height = pos->cy;
  4482.         }
  4483.         if (pos->fl & SWP_MOVE) {
  4484.             winPtr->changes.x = pos->x;
  4485.             winPtr->changes.y = TkOS2TranslateY(hwnd, pos->y, pos->cy);
  4486.         }
  4487.  
  4488.         GenerateConfigureNotify(winPtr);
  4489.  
  4490.         Tcl_ServiceAll();
  4491.         return 0;
  4492.     }
  4493.     return TkOS2ChildProc(hwnd, message, param1, param2);
  4494. }
  4495.  
  4496. /*
  4497.  *----------------------------------------------------------------------
  4498.  *
  4499.  * WmProc --
  4500.  *
  4501.  *      Callback from OS/2 PM whenever an event occurs on the decorative
  4502.  *      frame.
  4503.  *
  4504.  * Results:
  4505.  *      Standard PM return value.
  4506.  *
  4507.  * Side effects:
  4508.  *      Default window behavior.
  4509.  *
  4510.  *----------------------------------------------------------------------
  4511.  */
  4512.  
  4513. static MRESULT EXPENTRY
  4514. WmProc(hwnd, message, param1, param2)
  4515.     HWND hwnd;
  4516.     ULONG message;
  4517.     MPARAM param1;
  4518.     MPARAM param2;
  4519. {
  4520.     static int inMoveSize = 0;
  4521.     static int oldMode; /* This static is set upon entering move/size mode
  4522.                          * and is used to reset the service mode after
  4523.                          * leaving move/size mode.  Note that this mechanism
  4524.                          * assumes move/size is only one level deep. */
  4525.     MRESULT result;
  4526.     TkWindow *winPtr;
  4527. #ifdef VERBOSE
  4528.     printf("WmProc hwnd %x, msg %x, param1 %x, param2 %x\n", hwnd,
  4529.            message, param1, param2);
  4530.     switch (message) {
  4531.         case WM_ACTIVATE: printf("   WM_ACTIVATE Wm %x\n", hwnd); break;
  4532.         case WM_ADJUSTFRAMEPOS:
  4533.             printf("   WM_ADJUSTFRAMEPOS Wm %x (%d,%d) %dx%d\n", hwnd,
  4534.                    ((PSWP)param1)->x, ((PSWP)param1)->y, ((PSWP)param1)->cx,
  4535.                ((PSWP)param1)->cy);
  4536.             break;
  4537.         case WM_ADJUSTWINDOWPOS:
  4538.             printf("   WM_ADJUSTWINDOWPOS Wm %x (%d,%d) %dx%d\n", hwnd,
  4539.                    ((PSWP)param1)->x, ((PSWP)param1)->y, ((PSWP)param1)->cx,
  4540.                ((PSWP)param1)->cy);
  4541.             break;
  4542.         case WM_BUTTON1DOWN: printf("   WM_BUTTON1DOWN Wm %x\n", hwnd); break;
  4543.         case WM_BUTTON1UP: printf("   WM_BUTTON1UP Wm %x\n", hwnd); break;
  4544.         case WM_BUTTON1DBLCLK: printf("   WM_BUTTON1DBLCLK Wm %x\n", hwnd); break;
  4545.         case WM_BUTTON2DOWN: printf("   WM_BUTTON2DOWN Wm %x\n", hwnd); break;
  4546.         case WM_BUTTON2UP: printf("   WM_BUTTON2UP Wm %x\n", hwnd); break;
  4547.         case WM_BUTTON2DBLCLK: printf("   WM_BUTTON2DBLCLK Wm %x\n", hwnd); break;
  4548.         case WM_BUTTON3DOWN: printf("   WM_BUTTON3DOWN Wm %x\n", hwnd); break;
  4549.         case WM_BUTTON3UP: printf("   WM_BUTTON3UP Wm %x\n", hwnd); break;
  4550.         case WM_BUTTON3DBLCLK: printf("   WM_BUTTON3DBLCLK Wm %x\n", hwnd); break;
  4551.         case WM_CALCFRAMERECT: printf("   WM_CALCFRAMERECT Wm %x\n", hwnd); break;
  4552.         case WM_CALCVALIDRECTS: printf("   WM_CALCVALIDRECTS Wm %x\n", hwnd); break;
  4553.         case WM_CHAR: printf("   WM_CHAR Wm %x\n", hwnd); break;
  4554.         case WM_CLOSE: printf("   WM_CLOSE Wm %x\n", hwnd); break;
  4555.         case WM_COMMAND: printf("   WM_COMMAND Wm %x cmd %d s %d p %d\n",
  4556.                                 hwnd, SHORT1FROMMP(param1),
  4557.                                 SHORT1FROMMP(param2), SHORT2FROMMP(param2));
  4558.              break;
  4559.         case WM_CREATE: printf("   WM_CREATE Wm %x\n", hwnd); break;
  4560.         case WM_ERASEBACKGROUND: printf("   WM_ERASEBACKGROUND Wm %x\n", hwnd); break;
  4561.         case WM_FOCUSCHANGE: printf("   WM_FOCUSCHANGE Wm %x\n", hwnd); break;
  4562.         case WM_FORMATFRAME: printf("   WM_FORMATFRAME Wm %x\n", hwnd); break;
  4563.         case WM_HSCROLL: printf("   WM_HSCROLL Wm %x\n", hwnd); break;
  4564.         case WM_MINMAXFRAME: printf("   WM_MINMAXFRAME Wm %x\n", hwnd); break;
  4565.         case WM_MOUSEMOVE: printf("   WM_MOUSEMOVE Wm %x\n", hwnd); break;
  4566.         case WM_MOVE: printf("   WM_MOVE Wm %x\n", hwnd); break;
  4567.         case WM_OWNERPOSCHANGE: printf("   WM_OWNERPOSCHANGE Wm %x\n", hwnd); break;
  4568.         case WM_PAINT: printf("   WM_PAINT Wm %x\n", hwnd); break;
  4569.         case WM_QUERYBORDERSIZE: printf("   WM_QUERYBORDERSIZE Wm %x\n", hwnd); break;
  4570.         case WM_QUERYDLGCODE: printf("   WM_QUERYDLGCODE Wm %x\n", hwnd); break;
  4571.         case WM_QUERYFRAMECTLCOUNT: printf("   WM_QUERYFRAMECTLCOUNT Wm %x\n", hwnd); break;
  4572.         case WM_QUERYFOCUSCHAIN: printf("   WM_QUERYFOCUSCHAIN Wm %x\n", hwnd); break;
  4573.         case WM_QUERYICON: printf("   WM_QUERYICON Wm %x\n", hwnd); break;
  4574.         case WM_QUERYTRACKINFO: printf("   WM_QUERYTRACKINFO Wm %x\n", hwnd); break;
  4575.         case WM_REALIZEPALETTE: printf("   WM_REALIZEPALETTE Wm %x\n", hwnd); break;
  4576.         case WM_SETFOCUS: printf("   WM_SETFOCUS Wm %x\n", hwnd); break;
  4577.         case WM_SETSELECTION: printf("   WM_SETSELECTION Wm %x\n", hwnd); break;
  4578.         case WM_TRANSLATEACCEL: printf("   WM_TRANSLATEACCEL Wm %x\n", hwnd); break;
  4579.         case WM_UPDATEFRAME: printf("   WM_UPDATEFRAME Wm %x\n", hwnd); break;
  4580.         case WM_VSCROLL: printf("   WM_VSCROLL Wm %x\n", hwnd); break;
  4581.         case WM_WINDOWPOSCHANGED:
  4582.             printf("   WM_WINDOWPOSCHANGED Wm %x (%d,%d) %dx%d\n", hwnd,
  4583.                    ((PSWP)param1)->x, ((PSWP)param1)->y, ((PSWP)param1)->cx,
  4584.                ((PSWP)param1)->cy);
  4585.             break;
  4586.     }
  4587. #endif
  4588.  
  4589.     if (TkOS2HandleMenuEvent(&hwnd, &message, ¶m1, ¶m2, &result)) {
  4590.         goto done;
  4591.     }
  4592.  
  4593.     switch (message) {
  4594. #ifdef VERBOSE
  4595.         case WM_TRANSLATEACCEL: {
  4596.             PQMSG pqmsg = PVOIDFROMMP(param1);
  4597.             USHORT flags = (USHORT) SHORT1FROMMP(pqmsg->mp1);
  4598.             USHORT charcode = (USHORT) SHORT1FROMMP(pqmsg->mp2);
  4599.             USHORT vkeycode = (USHORT) SHORT2FROMMP(pqmsg->mp2);
  4600.             printf("WM_TRANSLATEACCEL Wm vk %x char %x fl %x\n", vkeycode,
  4601.                    charcode, flags);
  4602.             break;
  4603.         }
  4604. #endif
  4605.  
  4606.         case WM_SETFOCUS:
  4607. #ifdef VERBOSE
  4608.             printf("WM_SETFOCUS hwnd %x focus %d\n", hwnd, param1);
  4609. #endif
  4610.             if (SHORT1FROMMP(param2) == FALSE) {
  4611.                 /* Losing focus */
  4612.                 result = (MRESULT)0;
  4613.                 goto done;
  4614.             }
  4615.             result = oldFrameProc(hwnd, message, param1, param2);
  4616.             goto done;
  4617.             break;
  4618.  
  4619.         case WM_FOCUSCHANGE:
  4620. #ifdef VERBOSE
  4621.             printf("WM_FOCUSCHANGE hwnd %x focus %x focuswin %x fl %x\n", hwnd,
  4622.                    SHORT1FROMMP(param2), param1, SHORT2FROMMP(param2));
  4623. #endif
  4624.             if (SHORT1FROMMP(param2) == TRUE &&
  4625.                 !(SHORT2FROMMP(param2) & FC_NOSETACTIVE) &&
  4626.                 !(SHORT2FROMMP(param2) & FC_NOBRINGTOTOP) &&
  4627.                 !(SHORT2FROMMP(param2) & FC_NOBRINGTOPFIRSTWINDOW)) {
  4628.                 WinSetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER);
  4629.             }
  4630.             result = oldFrameProc(hwnd, message, param1, param2);
  4631.             goto done;
  4632.  
  4633.         case WM_ERASEBACKGROUND:
  4634.             result = (MRESULT)0;
  4635.             goto done;
  4636.  
  4637.         case WM_ADJUSTFRAMEPOS:
  4638.         case WM_QUERYTRACKINFO: {
  4639.             TRACKINFO track;
  4640.             TRACKINFO *trackPtr;
  4641.             if (message == WM_ADJUSTFRAMEPOS) {
  4642.                 trackPtr = &track;
  4643.                 trackPtr->fs = TF_MOVE;
  4644.             } else {
  4645.                 trackPtr = (TRACKINFO *) PVOIDFROMMP(param2);
  4646.                 trackPtr->fs = SHORT1FROMMP(param1);
  4647. #ifdef VERBOSE
  4648.                 printf("QUERYTRACKINFO TF %x\n", trackPtr->fs);
  4649. #endif
  4650.             }
  4651.             inMoveSize = 1;
  4652.             oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
  4653.             SetLimits(hwnd, trackPtr);
  4654.             inMoveSize = 0;
  4655.             Tcl_SetServiceMode(oldMode);
  4656.             if (message == WM_ADJUSTFRAMEPOS) {
  4657.                 /* use restraint info to modify SWP if necessary */
  4658.                 PSWP swpPtr = (PSWP) PVOIDFROMMP(param1);
  4659.                 LONG x11y =  yScreen - swpPtr->y - swpPtr->cy;
  4660. #ifdef VERBOSE
  4661.                 printf("ADJUSTFRAMEPOS x11y %d (%d - %d - %d)\n", x11y, yScreen,
  4662.                        swpPtr->y, swpPtr->cy);
  4663. #endif
  4664.                 if (swpPtr->cx > trackPtr->ptlMaxTrackSize.x) {
  4665. #ifdef VERBOSE
  4666.                     printf("ADJUSTFRAMEPOS cx %d -> %d\n", swpPtr->cx,
  4667.                            trackPtr->ptlMaxTrackSize.x);
  4668. #endif
  4669.                     swpPtr->cx = trackPtr->ptlMaxTrackSize.x;
  4670.                 }
  4671.                 if (swpPtr->cy > trackPtr->ptlMaxTrackSize.y) {
  4672.                     /* Remember we have reversed y-coordinates! */
  4673. #ifdef VERBOSE
  4674.                     printf("ADJUSTFRAMEPOS cy %d -> %d\n", swpPtr->cy,
  4675.                            trackPtr->ptlMaxTrackSize.y);
  4676. #endif
  4677.                     swpPtr->cy = trackPtr->ptlMaxTrackSize.y;
  4678.                 }
  4679.                 if (swpPtr->cx < trackPtr->ptlMinTrackSize.x) {
  4680. #ifdef VERBOSE
  4681.                     printf("ADJUSTFRAMEPOS cx %d -> %d\n", swpPtr->cx,
  4682.                            trackPtr->ptlMinTrackSize.x);
  4683. #endif
  4684.                     swpPtr->cx = trackPtr->ptlMinTrackSize.x;
  4685.                 }
  4686.                 if (swpPtr->cy < trackPtr->ptlMinTrackSize.y) {
  4687.                     /* Remember we have reversed y-coordinates! */
  4688. #ifdef VERBOSE
  4689.                     printf("ADJUSTFRAMEPOS cy %d -> %d\n", swpPtr->cy,
  4690.                            trackPtr->ptlMinTrackSize.y);
  4691. #endif
  4692.                     swpPtr->cy = trackPtr->ptlMinTrackSize.y;
  4693.                 }
  4694.                 /* Recompute PM y coordinate */
  4695. #ifdef VERBOSE
  4696.                 printf("ADJUSTFRAMEPOS y %d -> %d / %d -> %d (%d - %d - %d)\n",
  4697.                        swpPtr->y, yScreen - x11y - swpPtr->cy,
  4698.                        trackPtr->ptlMinTrackSize.y, yScreen - x11y - swpPtr->cy,
  4699.                        yScreen, x11y, swpPtr->cy);
  4700. #endif
  4701.                 swpPtr->y = yScreen - x11y - swpPtr->cy;
  4702.                 trackPtr->rclTrack.yBottom = swpPtr->y;
  4703.                 result = oldFrameProc(hwnd, message, param1, param2);
  4704.                 goto done;
  4705.             } else {
  4706.                 result = (MRESULT)1; /* continue sizing/moving */
  4707.                 goto done;
  4708.             }
  4709.         }
  4710.  
  4711.         case WM_REALIZEPALETTE:
  4712.             if (hwnd == WinQueryFocus(HWND_DESKTOP)) {
  4713.                 /* Only do when we're gaining the focus */
  4714.                 InstallColormaps(hwnd, WM_REALIZEPALETTE, TRUE);
  4715.             } else {
  4716.                 /* Only do when we're NOT gaining the focus */
  4717.                 InstallColormaps(hwnd, WM_REALIZEPALETTE, FALSE);
  4718.             }
  4719.         rc = WinInvalidateRect(hwnd, NULL, FALSE);
  4720. #ifdef VERBOSE
  4721.         if (rc == TRUE) {
  4722.             printf("    WinInvalidateRect %x successfull\n", hwnd);
  4723.         } else {
  4724.             printf("    WinInvalidateRect %x ERROR %x\n", hwnd,
  4725.                    WinGetLastError(TclOS2GetHAB()));
  4726.         }
  4727. #endif
  4728.             result = 0;
  4729.             goto done;
  4730.  
  4731.         case WM_WINDOWPOSCHANGED:
  4732.             ConfigureTopLevel((PSWP) PVOIDFROMMP(param1));
  4733.             result = oldFrameProc(hwnd, message, param1, param2);
  4734.             goto done;
  4735.  
  4736. /*
  4737.         SMART: "WM_NCHITTEST
  4738.                 Subclass the frame window and frame controls and process the
  4739.                 WM_HITTEST message for each control, returning the
  4740.                 appropriately mapped hittest code."
  4741.                 result = (MRESULT)HT_NORMAL;
  4742. */
  4743. /***** REMOVED 20010907
  4744.         case WM_HITTEST: {
  4745.             winPtr = GetTopLevel(hwnd);
  4746.             if (winPtr && (TkGrabState(winPtr) == TK_GRAB_EXCLUDED)) {
  4747. ***** REMOVED 20010907 */
  4748.                 /*
  4749.                  * This window is outside the grab hierarchy, so don't let any
  4750.                  * of the normal non-client processing occur.  Note that this
  4751.                  * implementation is not strictly correct because the grab
  4752.                  * might change between now and when the event would have been
  4753.                  * processed by Tk, but it's close enough.
  4754.                  */
  4755.  
  4756. /***** REMOVED 20010907
  4757. #ifdef VERBOSE
  4758.                 printf("WmProc WM_HITTEST hwnd %x HT_DISCARD\n", hwnd);
  4759. #endif
  4760.                 result = (MRESULT)HT_DISCARD;
  4761.                 goto done;
  4762.             }
  4763. #ifdef VERBOSE
  4764.             printf("WmProc WM_HITTEST hwnd %x oldFrameProc (0x%x)\n", hwnd,
  4765.                    result);
  4766. #endif
  4767.             result = oldFrameProc(hwnd, message, param1, param2);
  4768.             goto done;
  4769.         }
  4770. ***** REMOVED 20010907 */
  4771.  
  4772.         /*
  4773.          * The default frame window procedure sends the WM_CLOSE to the
  4774.          * client (child) if it exists, so we have to handle it there.
  4775.          * Also hand off mouse/button to default procedure.
  4776.          * This all ensures that click-to-activate etc. work as expected.
  4777.          */
  4778.         case WM_CLOSE:
  4779.         case WM_BUTTON1DOWN:
  4780.         case WM_BUTTON1UP:
  4781.         case WM_BUTTON1DBLCLK:
  4782.         case WM_BUTTON2DOWN:
  4783.         case WM_BUTTON2UP:
  4784.         case WM_BUTTON2DBLCLK:
  4785.         case WM_BUTTON3DOWN:
  4786.         case WM_BUTTON3UP:
  4787.         case WM_BUTTON3DBLCLK:
  4788.         case WM_MOUSEMOVE:
  4789.             result = oldFrameProc(hwnd, message, param1, param2);
  4790.             goto done;
  4791.  
  4792.         default:
  4793.             break;
  4794.     }
  4795.  
  4796.     winPtr = GetTopLevel(hwnd);
  4797.     if (winPtr && winPtr->window) {
  4798.         HWND child = Tk_GetHWND(winPtr->window);
  4799.         if ((message == WM_SETFOCUS) && (SHORT1FROMMP(param2) == TRUE)) {
  4800.             WinSetFocus(HWND_DESKTOP, child);
  4801.             result = (MRESULT)0;
  4802. #ifdef VERBOSE
  4803.             printf("WmProc not calling oldFrameProc after WinSetFocus\n");
  4804. #endif
  4805.             result = oldFrameProc(hwnd, message, param1, param2);
  4806. /*
  4807. */
  4808.         } else if (!Tk_TranslateOS2Event(child, message, param1, param2,
  4809.                 &result)) {
  4810. #ifdef VERBOSE
  4811.             printf("WmProc calling oldFrameProc after translation 0\n");
  4812. #endif
  4813.             result = oldFrameProc(hwnd, message, param1, param2);
  4814.         }
  4815.     } else {
  4816. #ifdef VERBOSE
  4817.         printf("WmProc calling oldFrameProc in else\n");
  4818. #endif
  4819.         result = oldFrameProc(hwnd, message, param1, param2);
  4820.     }
  4821.  
  4822.     done:
  4823. #ifdef VERBOSE
  4824.     switch (message) {
  4825.         case WM_ADJUSTFRAMEPOS:
  4826.             printf("   WM_ADJUSTFRAMEPOS Wm %x now (%d,%d) %dx%d\n", hwnd,
  4827.                    ((PSWP)param1)->x, ((PSWP)param1)->y, ((PSWP)param1)->cx,
  4828.                    ((PSWP)param1)->cy);
  4829.             break;
  4830.         case WM_ADJUSTWINDOWPOS:
  4831.             printf("   WM_ADJUSTWINDOWPOS Wm %x now (%d,%d) %dx%d\n", hwnd,
  4832.                    ((PSWP)param1)->x, ((PSWP)param1)->y, ((PSWP)param1)->cx,
  4833.                    ((PSWP)param1)->cy);
  4834.             break;
  4835.         case WM_WINDOWPOSCHANGED:
  4836.             printf("   WM_WINDOWPOSCHANGED Wm %x now (%d,%d) %dx%d\n", hwnd,
  4837.                    ((PSWP)param1)->x, ((PSWP)param1)->y, ((PSWP)param1)->cx,
  4838.                    ((PSWP)param1)->cy);
  4839.             break;
  4840.     }
  4841. #endif
  4842.     Tcl_ServiceAll();
  4843.     return result;
  4844. }
  4845.  
  4846. /*
  4847.  *----------------------------------------------------------------------
  4848.  *
  4849.  * TkpMakeMenuWindow --
  4850.  *
  4851.  *      Configure the window to be either a pull-down (or pop-up)
  4852.  *      menu, or as a toplevel (torn-off) menu or palette.
  4853.  *
  4854.  * Results:
  4855.  *      None.
  4856.  *
  4857.  * Side effects:
  4858.  *      Changes the style bit used to create a new OS/2 PM toplevel.
  4859.  *
  4860.  *----------------------------------------------------------------------
  4861.  */
  4862.  
  4863. void
  4864. TkpMakeMenuWindow(tkwin, transient)
  4865.     Tk_Window tkwin;            /* New window. */
  4866.     int transient;              /* 1 means menu is only posted briefly as
  4867.                                  * a popup or pulldown or cascade.  0 means
  4868.                                  * menu is always visible, e.g. as a torn-off
  4869.                                  * menu.  Determines whether save_under and
  4870.                                  * override_redirect should be set. */
  4871. {
  4872.     XSetWindowAttributes atts;
  4873. #ifdef VERBOSE
  4874.     printf("TkpMakeMenuWindow tkwin %x transient %d\n", tkwin, transient);
  4875. #endif
  4876.  
  4877.     if (transient) {
  4878.         atts.override_redirect = True;
  4879.         atts.save_under = True;
  4880.     } else {
  4881.         atts.override_redirect = False;
  4882.         atts.save_under = False;
  4883.     }
  4884.  
  4885.     if ((atts.override_redirect != Tk_Attributes(tkwin)->override_redirect)
  4886.             || (atts.save_under != Tk_Attributes(tkwin)->save_under)) {
  4887.         Tk_ChangeWindowAttributes(tkwin,
  4888.                 CWOverrideRedirect|CWSaveUnder, &atts);
  4889.     }
  4890.  
  4891. }
  4892.  
  4893. /*
  4894.  *----------------------------------------------------------------------
  4895.  *
  4896.  * TkOS2GetWrapperWindow --
  4897.  *
  4898.  *      Gets the OS/2 HWND for a given window.
  4899.  *
  4900.  * Results:
  4901.  *      Returns the wrapper window for a Tk window.
  4902.  *
  4903.  * Side effects:
  4904.  *      None.
  4905.  *
  4906.  *----------------------------------------------------------------------
  4907.  */
  4908.  
  4909. HWND
  4910. TkOS2GetWrapperWindow(
  4911.     Tk_Window tkwin)            /* The window we need the wrapper from */
  4912. {
  4913.     TkWindow *winPtr = (TkWindow *)tkwin;
  4914. #ifdef VERBOSE
  4915.     printf("TkOS2GetWrapperWindow tkwin %x => hwnd %x\n", tkwin,
  4916.            winPtr->wmInfoPtr->wrapper);
  4917. #endif
  4918.     return (winPtr->wmInfoPtr->wrapper);
  4919. }
  4920.  
  4921. /*
  4922.  *----------------------------------------------------------------------
  4923.  *
  4924.  * TkWmFocusToplevel --
  4925.  *
  4926.  *      This is a utility procedure invoked by focus-management code. It
  4927.  *      exists because of the extra wrapper windows that exist under
  4928.  *      Unix; its job is to map from wrapper windows to the
  4929.  *      corresponding toplevel windows.  On PCs and Macs there are no
  4930.  *      wrapper windows so no mapping is necessary;  this procedure just
  4931.  *      determines whether a window is a toplevel or not.
  4932.  *
  4933.  * Results:
  4934.  *      If winPtr is a toplevel window, returns the pointer to the
  4935.  *      window; otherwise returns NULL.
  4936.  *
  4937.  * Side effects:
  4938.  *      None.
  4939.  *
  4940.  *----------------------------------------------------------------------
  4941.  */
  4942.  
  4943. TkWindow *
  4944. TkWmFocusToplevel(winPtr)
  4945.     TkWindow *winPtr;           /* Window that received a focus-related
  4946.                                  * event. */
  4947. {
  4948. #ifdef VERBOSE
  4949.     printf("TkWmFocusToplevel winPtr %x\n", winPtr);
  4950. #endif
  4951.     if (!(winPtr->flags & TK_TOP_LEVEL)) {
  4952.         return NULL;
  4953.     }
  4954.     return winPtr;
  4955. }
  4956.  
  4957. /*
  4958.  *----------------------------------------------------------------------
  4959.  *
  4960.  * TkpGetWrapperWindow --
  4961.  *
  4962.  *      This is a utility procedure invoked by focus-management code. It
  4963.  *      maps to the wrapper for a top-level, which is just the same
  4964.  *      as the top-level on Macs and PCs.
  4965.  *
  4966.  * Results:
  4967.  *      If winPtr is a toplevel window, returns the pointer to the
  4968.  *      window; otherwise returns NULL.
  4969.  *
  4970.  * Side effects:
  4971.  *      None.
  4972.  *
  4973.  *----------------------------------------------------------------------
  4974.  */
  4975.  
  4976. TkWindow *
  4977. TkpGetWrapperWindow(
  4978.     TkWindow *winPtr)           /* Window that received a focus-related
  4979.                                  * event. */
  4980. {
  4981. #ifdef VERBOSE
  4982.     printf("TkpGetWrapperWindow winPtr %x\n", winPtr);
  4983. #endif
  4984.     if (!(winPtr->flags & TK_TOP_LEVEL)) {
  4985.         return NULL;
  4986.     }
  4987.     return winPtr;
  4988. }
  4989.