*** tkWinWm.c.bak Wed Sep 27 12:03:30 2000
--- tkWinWm.c Mon Oct  9 15:55:28 2000
***************
*** 165,170 ****
--- 165,171 ----
                   * property, or NULL. */
      int flags;          /* Miscellaneous flags, defined below. */
      int numTransients;      /* number of transients on this window */
+     int styleFlags;     /* Flags for style information */
      struct TkWmInfo *nextPtr;   /* Next in list of all top-level windows. */
  } WmInfo;
  
***************
*** 227,232 ****
--- 228,250 ----
  #define EX_TRANSIENT_STYLE (WS_EX_DLGMODALFRAME)
  
  /*
+  * Window styles for WinXX specific styles
+  */
+ #define WM_STYLE_CAPTION        (1<<0)
+ #define WM_STYLE_DIALOG         (1<<1)
+ #define WM_STYLE_MAXIMIZE       (1<<2)
+ #define WM_STYLE_MINIMIZE       (1<<3)
+ #define WM_STYLE_STAYONTOP      (1<<4)
+ #define WM_STYLE_SYSMENU        (1<<5)
+ #define WM_STYLE_TASKBAR        (1<<6)
+ #define WM_STYLE_TRANSPARENT    (1<<7)
+ 
+ #define WM_STYLE_INITIAL        (WM_STYLE_CAPTION | WM_STYLE_MAXIMIZE | \
+                                  WM_STYLE_MINIMIZE | WM_STYLE_SYSMENU | \
+                                  WM_STYLE_TASKBAR)
+ 
+ 
+ /*
   * The following structure is the official type record for geometry
   * management of top-level windows.
   */
***************
*** 623,628 ****
--- 641,647 ----
      wmPtr->cmdArgv = NULL;
      wmPtr->clientMachine = NULL;
      wmPtr->flags = WM_NEVER_MAPPED;
+     wmPtr->styleFlags = WM_STYLE_INITIAL;
      wmPtr->nextPtr = winPtr->dispPtr->firstWmPtr;
      winPtr->dispPtr->firstWmPtr = wmPtr;
  
***************
*** 675,680 ****
--- 694,701 ----
      int *childStateInfo = NULL;
      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+     int styleChanged = 0, exStyleChanged = 0;
+     HWND insertAfter = HWND_TOP;
  
      parentHWND = NULL;
      child = TkWinGetHWND(winPtr->window);
***************
*** 817,822 ****
--- 838,946 ----
      SendMessage(wmPtr->wrapper, TK_ATTACHWINDOW, (WPARAM) child, 0);
  
      /*
+      * Now, after the window has been created but before it has been
+      * mapped, apply any additional style flags. We need to do this
+      * before mapping for the taskbar style, so we just do them all
+      * here.
+      */
+     if (wmPtr->styleFlags != WM_STYLE_INITIAL) {
+         long style, exStyle;
+ 
+         style = GetWindowLong(wmPtr->wrapper, GWL_STYLE);
+         exStyle = GetWindowLong(wmPtr->wrapper, GWL_EXSTYLE);
+ 
+         if ((WM_STYLE_INITIAL & WM_STYLE_CAPTION) ^
+             (wmPtr->styleFlags & WM_STYLE_CAPTION)) {
+             styleChanged = 1;
+             if (wmPtr->styleFlags & WM_STYLE_CAPTION) {
+                 style |= WS_CAPTION;
+             } else {
+                 style &= ~WS_CAPTION;
+             }
+         }
+ 
+         if ((WM_STYLE_INITIAL & WM_STYLE_DIALOG) ^
+             (wmPtr->styleFlags & WM_STYLE_DIALOG)) {
+             exStyleChanged = 1;
+             if (wmPtr->styleFlags & WM_STYLE_DIALOG) {
+                 exStyle |= WS_EX_DLGMODALFRAME;
+             } else {
+                 exStyle &= ~WS_EX_DLGMODALFRAME;
+             }
+         }
+ 
+         if ((WM_STYLE_INITIAL & WM_STYLE_MAXIMIZE) ^
+             (wmPtr->styleFlags & WM_STYLE_MAXIMIZE)) {
+             styleChanged = 1;
+             if (wmPtr->styleFlags & WM_STYLE_MAXIMIZE) {
+                 style |= WS_MAXIMIZEBOX;
+             } else {
+                 style &= ~WS_MAXIMIZEBOX;
+             }
+         }
+ 
+         if ((WM_STYLE_INITIAL & WM_STYLE_MINIMIZE) ^
+             (wmPtr->styleFlags & WM_STYLE_MINIMIZE)) {
+             styleChanged = 1;
+             if (wmPtr->styleFlags & WM_STYLE_MINIMIZE) {
+                 style |= WS_MINIMIZEBOX;
+             } else {
+                 style &= ~WS_MINIMIZEBOX;
+             }
+         }
+ 
+         if ((WM_STYLE_INITIAL & WM_STYLE_STAYONTOP) ^
+             (wmPtr->styleFlags & WM_STYLE_STAYONTOP)) {
+             exStyleChanged = 1;
+             if (wmPtr->styleFlags & WM_STYLE_STAYONTOP) {
+                 exStyle |= WS_EX_TOPMOST;
+                 insertAfter = HWND_TOPMOST;
+             } else {
+                 exStyle &= ~WS_EX_TOPMOST;
+                 insertAfter = HWND_NOTOPMOST;
+             }
+         }
+ 
+         if ((WM_STYLE_INITIAL & WM_STYLE_SYSMENU) ^
+             (wmPtr->styleFlags & WM_STYLE_SYSMENU)) {
+             styleChanged = 1;
+             if (wmPtr->styleFlags & WM_STYLE_SYSMENU) {
+                 style |= WS_SYSMENU;
+             } else {
+                 style &= ~WS_SYSMENU;
+             }
+         }
+ 
+         if ((WM_STYLE_INITIAL & WM_STYLE_TASKBAR) ^
+             (wmPtr->styleFlags & WM_STYLE_TASKBAR)) {
+             exStyleChanged = 1;
+             if (wmPtr->styleFlags & WM_STYLE_TASKBAR) {
+                 exStyle &= ~WS_EX_TOOLWINDOW;
+             } else {
+                 exStyle |= WS_EX_TOOLWINDOW;
+             }
+         }
+ 
+         if ((WM_STYLE_INITIAL & WM_STYLE_TRANSPARENT) ^
+             (wmPtr->styleFlags & WM_STYLE_TRANSPARENT)) {
+             exStyleChanged = 1;
+             if (wmPtr->styleFlags & WM_STYLE_TRANSPARENT) {
+                 exStyle |= WS_EX_TRANSPARENT;
+             } else {
+                 exStyle &= ~WS_EX_TRANSPARENT;
+             }
+         }
+ 
+         if (styleChanged) {
+             SetWindowLong(wmPtr->wrapper, GWL_STYLE, style);
+         }
+ 
+         if (exStyleChanged) {
+             SetWindowLong(wmPtr->wrapper, GWL_EXSTYLE, exStyle);
+         }
+     }
+ 
+     /*
       * Force an initial transition from withdrawn to the real
       * initial state.
       */
***************
*** 839,844 ****
--- 963,982 ----
      }
  
      /*
+      * Now, if we applied any changed styles, we need to get those
+      * changes noticed, and we have to do it after the window has
+      * been mapped. Why? Because otherwise the window might not
+      * appear, depending on the styles changed. Why? Because that's
+      * the way WinXX appears to work. Believe me, I experimented
+      * quite a bit with this.
+      */
+     if (styleChanged || exStyleChanged) {
+         SetWindowPos(wmPtr->wrapper, insertAfter, 0, 0, 0, 0,
+             SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOACTIVATE |
+             (insertAfter == HWND_TOP ? SWP_NOZORDER : 0));
+     }
+ 
+     /*
       * Set up menus on the wrapper if required.
       */
  
***************
*** 2134,2140 ****
  	}
  	goto updateGeom;
      } else if ((c == 's') && (strncmp(argv[1], "state", length) == 0)
! 	    && (length >= 2)) {
  	if ((argc < 3) || (argc > 4)) {
  	    Tcl_AppendResult(interp, "wrong # arguments: must be \"",
  		    argv[0], " state window ?state?\"", (char *) NULL);
--- 2272,2278 ----
      }
      goto updateGeom;
      } else if ((c == 's') && (strncmp(argv[1], "state", length) == 0)
!         && (length >= 3)) {
      if ((argc < 3) || (argc > 4)) {
          Tcl_AppendResult(interp, "wrong # arguments: must be \"",
              argv[0], " state window ?state?\"", (char *) NULL);
***************
*** 2211,2216 ****
--- 2349,2517 ----
          }
          }
      }
+     } else if ((c == 's') && (strncmp(argv[1], "style", length) == 0)
+         && (length >= 3)) {
+     if ((argc < 4) || (argc > 5)) {
+         Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+             argv[0], " style window ?style? ?boolean?\"", (char *) NULL);
+         return TCL_ERROR;
+     }
+     c = argv[3][0];
+     length = strlen(argv[3]);
+ 
+     if (argc == 5) {
+         HWND insertAfter = HWND_TOP;
+         long oldstyle, newstyle, setflag, setstyle;
+         int boolean, nIndex, setit = 0;
+ 
+         if (Tcl_GetBoolean(interp, argv[4], &boolean) != TCL_OK) {
+             return TCL_ERROR;
+         }
+         if (Tk_WindowId((Tk_Window) winPtr) == None) {
+             Tk_MakeWindowExist((Tk_Window) winPtr);
+         }
+         if ((c == 'c') && (strncmp(argv[3], "caption", length) == 0)) {
+             setit = (boolean != (wmPtr->styleFlags & WM_STYLE_CAPTION));
+             nIndex = GWL_STYLE;
+             setstyle = WS_CAPTION;
+             setflag = WM_STYLE_CAPTION;
+         } else if ((c == 'd') && (strncmp(argv[3], "dialog", length) == 0)) {
+             setit = (boolean != (wmPtr->styleFlags & WM_STYLE_DIALOG));
+             nIndex = GWL_EXSTYLE;
+             setstyle = WS_EX_DLGMODALFRAME;
+             setflag = WM_STYLE_DIALOG;
+         } else if ((c == 'm') && (length >= 2) &&
+             (strncmp(argv[3], "maximize", length) == 0)) {
+             setit = (boolean != (wmPtr->styleFlags & WM_STYLE_MAXIMIZE));
+             nIndex = GWL_STYLE;
+             setstyle = WS_MAXIMIZEBOX;
+             setflag = WM_STYLE_MAXIMIZE;
+         } else if ((c == 'm') && (length >= 2) &&
+             (strncmp(argv[3], "minimize", length) == 0)) {
+             setit = (boolean != (wmPtr->styleFlags & WM_STYLE_MINIMIZE));
+             nIndex = GWL_STYLE;
+             setstyle = WS_MINIMIZEBOX;
+             setflag = WM_STYLE_MINIMIZE;
+         } else if ((c == 's') && (length >= 2) &&
+             (strncmp(argv[3], "stayontop", length) == 0)) {
+             setit = (boolean != (wmPtr->styleFlags & WM_STYLE_STAYONTOP));
+             nIndex = GWL_EXSTYLE;
+             setstyle = WS_EX_TOPMOST;
+             setflag = WM_STYLE_STAYONTOP;
+             insertAfter = boolean ? HWND_TOPMOST : HWND_NOTOPMOST;
+         } else if ((c == 's') && (length >= 2) &&
+             (strncmp(argv[3], "sysmenu", length) == 0)) {
+             setit = (boolean != (wmPtr->styleFlags & WM_STYLE_SYSMENU));
+             nIndex = GWL_STYLE;
+             setstyle = WS_SYSMENU;
+             setflag = WM_STYLE_SYSMENU;
+         } else if ((c == 't') && (length >= 2) &&
+             (strncmp(argv[3], "taskbar", length) == 0)) {
+             /*
+              * Note: for this to take effect, the use must withdraw
+              * the window, change the style, and deiconify the window.
+              */
+             setit = (boolean != (wmPtr->styleFlags & WM_STYLE_TASKBAR));
+             nIndex = GWL_EXSTYLE;
+             setstyle = WS_EX_TOOLWINDOW;
+             setflag = WM_STYLE_TASKBAR;
+         } else if ((c == 't') && (length >= 2) &&
+             (strncmp(argv[3], "transparent", length) == 0)) {
+             setit = (boolean != (wmPtr->styleFlags & WM_STYLE_TRANSPARENT));
+             nIndex = GWL_EXSTYLE;
+             setstyle = WS_EX_TRANSPARENT;
+             setflag = WM_STYLE_TRANSPARENT;
+         } else {
+             Tcl_AppendResult(interp, "bad argument \"", argv[3],
+                 "\": must be caption, dialog, maximize, minimize, ",
+                 "stayontop, sysmenu, taskbar, or transparent",
+                 (char *) NULL);
+             return TCL_ERROR;
+         }
+         /* Update style flag setting */
+         if (boolean) {
+             wmPtr->styleFlags |= setflag;
+         } else {
+             wmPtr->styleFlags &= ~setflag;
+         }
+ 
+         /*
+          * Now update the window if the setting changed and it has
+          * already been mapped. We do the SetWindowPos to make sure
+          * frame changes get noticed in the cache. This is suggested
+          * to be done for any changes to the frame, and is required
+          * for stayontop, due to the specific insertAfter setting.
+          */
+         if (setit && !(wmPtr->flags & WM_NEVER_MAPPED) && wmPtr->wrapper) {
+             oldstyle = GetWindowLong(wmPtr->wrapper, nIndex);
+             if (boolean) {
+                 if (setflag == WM_STYLE_TASKBAR) {
+                     newstyle = oldstyle & ~setstyle;
+                 } else {
+                     newstyle = oldstyle | setstyle;
+                 }
+             } else {
+                 if (setflag == WM_STYLE_TASKBAR) {
+                     newstyle = oldstyle | setstyle;
+                 } else {
+                     newstyle = oldstyle & ~setstyle;
+                 }
+             }
+             SetWindowLong(wmPtr->wrapper, nIndex, newstyle);
+             SetWindowPos(wmPtr->wrapper, insertAfter, 0, 0, 0, 0,
+                 SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOACTIVATE |
+                 (insertAfter == HWND_TOP ? SWP_NOZORDER : 0));
+         }
+ 
+     } else {
+         if ((c == 'c') &&
+             (strncmp(argv[3], "caption", length) == 0)) {
+             Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
+                 (wmPtr->styleFlags & WM_STYLE_CAPTION));
+             return TCL_OK;
+         } else if ((c == 'd') &&
+             (strncmp(argv[3], "dialog", length) == 0)) {
+             Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
+                 (wmPtr->styleFlags & WM_STYLE_DIALOG));
+             return TCL_OK;
+         } else if ((c == 'm') && (length >= 2) &&
+             (strncmp(argv[3], "maximize", length) == 0)) {
+             Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
+                 (wmPtr->styleFlags & WM_STYLE_MAXIMIZE));
+             return TCL_OK;
+         } else if ((c == 'm') && (length >= 2) &&
+             (strncmp(argv[3], "minimize", length) == 0)) {
+             Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
+                 (wmPtr->styleFlags & WM_STYLE_MINIMIZE));
+             return TCL_OK;
+         } else if ((c == 's') && (length >= 2) &&
+             (strncmp(argv[3], "stayontop", length) == 0)) {
+             Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
+                 (wmPtr->styleFlags & WM_STYLE_STAYONTOP));
+             return TCL_OK;
+         } else if ((c == 's') && (length >= 2) &&
+             (strncmp(argv[3], "sysmenu", length) == 0)) {
+             Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
+                 (wmPtr->styleFlags & WM_STYLE_SYSMENU));
+             return TCL_OK;
+         } else if ((c == 't') && (length >= 2) &&
+             (strncmp(argv[3], "taskbar", length) == 0)) {
+             Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
+                 (wmPtr->styleFlags & WM_STYLE_TASKBAR));
+             return TCL_OK;
+         } else if ((c == 't') && (length >= 2) &&
+             (strncmp(argv[3], "transparent", length) == 0)) {
+             Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
+                 (wmPtr->styleFlags & WM_STYLE_TRANSPARENT));
+             return TCL_OK;
+         } else {
+             Tcl_AppendResult(interp, "bad argument \"", argv[3],
+                 "\": must be caption, dialog, maximize, minimize, ",
+                 "stayontop, sysmenu, taskbar, or transparent",
+                 (char *) NULL);
+             return TCL_ERROR;
+         }
+     }
      } else if ((c == 't') && (strncmp(argv[1], "title", length) == 0)
          && (length >= 2)) {
      if (argc > 4) {
***************
*** 2313,2320 ****
  		"focusmodel, frame, geometry, grid, group, iconbitmap, ",
  		"iconify, iconmask, iconname, iconposition, ",
  		"iconwindow, maxsize, minsize, overrideredirect, ",
! 		"positionfrom, protocol, resizable, sizefrom, state, title, ",
! 		"transient, or withdraw",
  		(char *) NULL);
  	return TCL_ERROR;
      }
--- 2614,2621 ----
          "focusmodel, frame, geometry, grid, group, iconbitmap, ",
          "iconify, iconmask, iconname, iconposition, ",
          "iconwindow, maxsize, minsize, overrideredirect, ",
!         "positionfrom, protocol, resizable, sizefrom, state, style, ",
!         "title, transient, or withdraw",
          (char *) NULL);
      return TCL_ERROR;
      }
