/[dtapublic]/projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkwinbutton.c
ViewVC logotype

Diff of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkwinbutton.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 69 by dashley, Sat Nov 5 10:54:17 2016 UTC revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
1  /* $Header$ */  /* $Header$ */
2    
3  /*  /*
4   * tkWinButton.c --   * tkWinButton.c --
5   *   *
6   *      This file implements the Windows specific portion of the button   *      This file implements the Windows specific portion of the button
7   *      widgets.   *      widgets.
8   *   *
9   * Copyright (c) 1996-1998 by Sun Microsystems, Inc.   * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
10   *   *
11   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
12   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13   *   *
14   * RCS: @(#) $Id: tkwinbutton.c,v 1.1.1.1 2001/06/13 05:11:56 dtashley Exp $   * RCS: @(#) $Id: tkwinbutton.c,v 1.1.1.1 2001/06/13 05:11:56 dtashley Exp $
15   */   */
16    
17  #define OEMRESOURCE  #define OEMRESOURCE
18  #include "tkWinInt.h"  #include "tkWinInt.h"
19  #include "tkButton.h"  #include "tkButton.h"
20    
21  #include "resource.h"  #include "resource.h"
22    /* Necessary to load the TK_BUTTONS.    /* Necessary to load the TK_BUTTONS.
23    */    */
24    
25  /*  /*
26   * These macros define the base style flags for the different button types.   * These macros define the base style flags for the different button types.
27   */   */
28    
29  #define LABEL_STYLE (BS_OWNERDRAW | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS)  #define LABEL_STYLE (BS_OWNERDRAW | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS)
30  #define PUSH_STYLE (BS_OWNERDRAW | BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS)  #define PUSH_STYLE (BS_OWNERDRAW | BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS)
31  #define CHECK_STYLE (BS_OWNERDRAW | BS_CHECKBOX | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS)  #define CHECK_STYLE (BS_OWNERDRAW | BS_CHECKBOX | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS)
32  #define RADIO_STYLE (BS_OWNERDRAW | BS_RADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS)  #define RADIO_STYLE (BS_OWNERDRAW | BS_RADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS)
33    
34  static DWORD buttonStyles[] = {  static DWORD buttonStyles[] = {
35      LABEL_STYLE, PUSH_STYLE, CHECK_STYLE, RADIO_STYLE      LABEL_STYLE, PUSH_STYLE, CHECK_STYLE, RADIO_STYLE
36  };  };
37    
38  /*  /*
39   * Declaration of Windows specific button structure.   * Declaration of Windows specific button structure.
40   */   */
41    
42  typedef struct WinButton {  typedef struct WinButton {
43      TkButton info;              /* Generic button info. */      TkButton info;              /* Generic button info. */
44      WNDPROC oldProc;            /* Old window procedure. */      WNDPROC oldProc;            /* Old window procedure. */
45      HWND hwnd;                  /* Current window handle. */      HWND hwnd;                  /* Current window handle. */
46      Pixmap pixmap;              /* Bitmap for rendering the button. */      Pixmap pixmap;              /* Bitmap for rendering the button. */
47      DWORD style;                /* Window style flags. */      DWORD style;                /* Window style flags. */
48  } WinButton;  } WinButton;
49    
50    
51  /*  /*
52   * The following macro reverses the order of RGB bytes to convert   * The following macro reverses the order of RGB bytes to convert
53   * between RGBQUAD and COLORREF values.   * between RGBQUAD and COLORREF values.
54   */   */
55    
56  #define FlipColor(rgb) (RGB(GetBValue(rgb),GetGValue(rgb),GetRValue(rgb)))  #define FlipColor(rgb) (RGB(GetBValue(rgb),GetGValue(rgb),GetRValue(rgb)))
57    
58  /*  /*
59   * The following enumeration defines the meaning of the palette entries   * The following enumeration defines the meaning of the palette entries
60   * in the "buttons" image used to draw checkbox and radiobutton indicators.   * in the "buttons" image used to draw checkbox and radiobutton indicators.
61   */   */
62    
63  enum {  enum {
64      PAL_CHECK = 0,      PAL_CHECK = 0,
65      PAL_TOP_OUTER = 1,      PAL_TOP_OUTER = 1,
66      PAL_BOTTOM_OUTER = 2,      PAL_BOTTOM_OUTER = 2,
67      PAL_BOTTOM_INNER = 3,      PAL_BOTTOM_INNER = 3,
68      PAL_INTERIOR = 4,      PAL_INTERIOR = 4,
69      PAL_TOP_INNER = 5,      PAL_TOP_INNER = 5,
70      PAL_BACKGROUND = 6      PAL_BACKGROUND = 6
71  };  };
72    
73  /*  /*
74   * Cached information about the boxes bitmap, and the default border   * Cached information about the boxes bitmap, and the default border
75   * width for a button in string form for use in Tk_OptionSpec for   * width for a button in string form for use in Tk_OptionSpec for
76   * the various button widget classes.   * the various button widget classes.
77   */   */
78    
79  typedef struct ThreadSpecificData {  typedef struct ThreadSpecificData {
80      BITMAPINFOHEADER *boxesPtr;   /* Information about the bitmap. */      BITMAPINFOHEADER *boxesPtr;   /* Information about the bitmap. */
81      DWORD *boxesPalette;          /* Pointer to color palette. */      DWORD *boxesPalette;          /* Pointer to color palette. */
82      LPSTR boxesBits;              /* Pointer to bitmap data. */      LPSTR boxesBits;              /* Pointer to bitmap data. */
83      DWORD boxHeight;              /* Height of each sub-image. */      DWORD boxHeight;              /* Height of each sub-image. */
84      DWORD boxWidth ;              /* Width of each sub-image. */      DWORD boxWidth ;              /* Width of each sub-image. */
85      char defWidth[TCL_INTEGER_SPACE];      char defWidth[TCL_INTEGER_SPACE];
86  } ThreadSpecificData;  } ThreadSpecificData;
87  static Tcl_ThreadDataKey dataKey;  static Tcl_ThreadDataKey dataKey;
88    
89  /*  /*
90   * Declarations for functions defined in this file.   * Declarations for functions defined in this file.
91   */   */
92    
93  static int              ButtonBindProc _ANSI_ARGS_((ClientData clientData,  static int              ButtonBindProc _ANSI_ARGS_((ClientData clientData,
94                              Tcl_Interp *interp, XEvent *eventPtr,                              Tcl_Interp *interp, XEvent *eventPtr,
95                              Tk_Window tkwin, KeySym keySym));                              Tk_Window tkwin, KeySym keySym));
96  static LRESULT CALLBACK ButtonProc _ANSI_ARGS_((HWND hwnd, UINT message,  static LRESULT CALLBACK ButtonProc _ANSI_ARGS_((HWND hwnd, UINT message,
97                              WPARAM wParam, LPARAM lParam));                              WPARAM wParam, LPARAM lParam));
98  static DWORD            ComputeStyle _ANSI_ARGS_((WinButton* butPtr));  static DWORD            ComputeStyle _ANSI_ARGS_((WinButton* butPtr));
99  static Window           CreateProc _ANSI_ARGS_((Tk_Window tkwin,  static Window           CreateProc _ANSI_ARGS_((Tk_Window tkwin,
100                              Window parent, ClientData instanceData));                              Window parent, ClientData instanceData));
101  static void             InitBoxes _ANSI_ARGS_((void));  static void             InitBoxes _ANSI_ARGS_((void));
102    
103  /*  /*
104   * The class procedure table for the button widgets.   * The class procedure table for the button widgets.
105   */   */
106    
107  TkClassProcs tkpButtonProcs = {  TkClassProcs tkpButtonProcs = {
108      CreateProc,                 /* createProc. */      CreateProc,                 /* createProc. */
109      TkButtonWorldChanged,       /* geometryProc. */      TkButtonWorldChanged,       /* geometryProc. */
110      NULL                        /* modalProc. */      NULL                        /* modalProc. */
111  };  };
112    
113    
114  /*  /*
115   *----------------------------------------------------------------------   *----------------------------------------------------------------------
116   *   *
117   * InitBoxes --   * InitBoxes --
118   *   *
119   *      This function load the Tk 3d button bitmap.  "buttons" is a 16   *      This function load the Tk 3d button bitmap.  "buttons" is a 16
120   *      color bitmap that is laid out such that the top row contains   *      color bitmap that is laid out such that the top row contains
121   *      the 4 checkbox images, and the bottom row contains the radio   *      the 4 checkbox images, and the bottom row contains the radio
122   *      button images. Note that the bitmap is stored in bottom-up   *      button images. Note that the bitmap is stored in bottom-up
123   *      format.  Also, the first seven palette entries are used to   *      format.  Also, the first seven palette entries are used to
124   *      identify the different parts of the bitmaps so we can do the   *      identify the different parts of the bitmaps so we can do the
125   *      appropriate color mappings based on the current button colors.   *      appropriate color mappings based on the current button colors.
126   *   *
127   * Results:   * Results:
128   *      None.   *      None.
129   *   *
130   * Side effects:   * Side effects:
131   *      Loads the "buttons" resource.   *      Loads the "buttons" resource.
132   *   *
133   *----------------------------------------------------------------------   *----------------------------------------------------------------------
134   */   */
135    
136  static void  static void
137  InitBoxes()  InitBoxes()
138  {  {
139      /*      /*
140       * For DLLs like Tk, the HINSTANCE is the same as the HMODULE.       * For DLLs like Tk, the HINSTANCE is the same as the HMODULE.
141       */       */
142    
143      HMODULE module = (HINSTANCE) Tk_GetHINSTANCE();      HMODULE module = (HINSTANCE) Tk_GetHINSTANCE();
144      HRSRC hrsrc;      HRSRC hrsrc;
145      HGLOBAL hblk;      HGLOBAL hblk;
146      LPBITMAPINFOHEADER newBitmap;      LPBITMAPINFOHEADER newBitmap;
147      DWORD size;      DWORD size;
148      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
149              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
150    
151      hrsrc = FindResource(module, (const char *)TK_BUTTONS, RT_BITMAP);      hrsrc = FindResource(module, (const char *)TK_BUTTONS, RT_BITMAP);
152         /* Found experimentally that using the constant defined in         /* Found experimentally that using the constant defined in
153         ** RESOURCE.H in the call above works as per Microsoft         ** RESOURCE.H in the call above works as per Microsoft
154         ** documentation.  Old line was:         ** documentation.  Old line was:
155         **     hrsrc = FindResource(module, "buttons", RT_BITMAP);         **     hrsrc = FindResource(module, "buttons", RT_BITMAP);
156         ** Didn't work reliably with GUI build after code ported.         ** Didn't work reliably with GUI build after code ported.
157         ** Believe the call above accesses the resource correctly.         ** Believe the call above accesses the resource correctly.
158         */         */
159    
160      if (hrsrc) {      if (hrsrc) {
161          hblk = LoadResource(module, hrsrc);          hblk = LoadResource(module, hrsrc);
162          tsdPtr->boxesPtr = (LPBITMAPINFOHEADER)LockResource(hblk);          tsdPtr->boxesPtr = (LPBITMAPINFOHEADER)LockResource(hblk);
163      }      }
164    
165      /*      /*
166       * Copy the DIBitmap into writable memory.       * Copy the DIBitmap into writable memory.
167       */       */
168    
169      if (tsdPtr->boxesPtr != NULL && !(tsdPtr->boxesPtr->biWidth % 4)      if (tsdPtr->boxesPtr != NULL && !(tsdPtr->boxesPtr->biWidth % 4)
170              && !(tsdPtr->boxesPtr->biHeight % 2)) {              && !(tsdPtr->boxesPtr->biHeight % 2)) {
171          size = tsdPtr->boxesPtr->biSize + (1 << tsdPtr->boxesPtr->biBitCount)          size = tsdPtr->boxesPtr->biSize + (1 << tsdPtr->boxesPtr->biBitCount)
172                  * sizeof(RGBQUAD) + tsdPtr->boxesPtr->biSizeImage;                  * sizeof(RGBQUAD) + tsdPtr->boxesPtr->biSizeImage;
173          newBitmap = (LPBITMAPINFOHEADER) ckalloc(size);          newBitmap = (LPBITMAPINFOHEADER) ckalloc(size);
174          memcpy(newBitmap, tsdPtr->boxesPtr, size);          memcpy(newBitmap, tsdPtr->boxesPtr, size);
175          tsdPtr->boxesPtr = newBitmap;          tsdPtr->boxesPtr = newBitmap;
176          tsdPtr->boxWidth = tsdPtr->boxesPtr->biWidth / 4;          tsdPtr->boxWidth = tsdPtr->boxesPtr->biWidth / 4;
177          tsdPtr->boxHeight = tsdPtr->boxesPtr->biHeight / 2;          tsdPtr->boxHeight = tsdPtr->boxesPtr->biHeight / 2;
178          tsdPtr->boxesPalette = (DWORD*) (((LPSTR) tsdPtr->boxesPtr)          tsdPtr->boxesPalette = (DWORD*) (((LPSTR) tsdPtr->boxesPtr)
179                  + tsdPtr->boxesPtr->biSize);                  + tsdPtr->boxesPtr->biSize);
180          tsdPtr->boxesBits = ((LPSTR) tsdPtr->boxesPalette)          tsdPtr->boxesBits = ((LPSTR) tsdPtr->boxesPalette)
181              + ((1 << tsdPtr->boxesPtr->biBitCount) * sizeof(RGBQUAD));              + ((1 << tsdPtr->boxesPtr->biBitCount) * sizeof(RGBQUAD));
182      } else {      } else {
183          tsdPtr->boxesPtr = NULL;          tsdPtr->boxesPtr = NULL;
184      }      }
185  }  }
186    
187  /*  /*
188   *----------------------------------------------------------------------   *----------------------------------------------------------------------
189   *   *
190   * TkpButtonSetDefaults --   * TkpButtonSetDefaults --
191   *   *
192   *      This procedure is invoked before option tables are created for   *      This procedure is invoked before option tables are created for
193   *      buttons.  It modifies some of the default values to match the   *      buttons.  It modifies some of the default values to match the
194   *      current values defined for this platform.   *      current values defined for this platform.
195   *   *
196   * Results:   * Results:
197   *      Some of the default values in *specPtr are modified.   *      Some of the default values in *specPtr are modified.
198   *   *
199   * Side effects:   * Side effects:
200   *      Updates some of.   *      Updates some of.
201   *   *
202   *----------------------------------------------------------------------   *----------------------------------------------------------------------
203   */   */
204    
205  void  void
206  TkpButtonSetDefaults(specPtr)  TkpButtonSetDefaults(specPtr)
207      Tk_OptionSpec *specPtr;     /* Points to an array of option specs,      Tk_OptionSpec *specPtr;     /* Points to an array of option specs,
208                                   * terminated by one with type                                   * terminated by one with type
209                                   * TK_OPTION_END. */                                   * TK_OPTION_END. */
210  {  {
211      int width;      int width;
212      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
213              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
214    
215      if (tsdPtr->defWidth[0] == 0) {      if (tsdPtr->defWidth[0] == 0) {
216          width = GetSystemMetrics(SM_CXEDGE);          width = GetSystemMetrics(SM_CXEDGE);
217          if (width == 0) {          if (width == 0) {
218              width = 1;              width = 1;
219          }          }
220          sprintf(tsdPtr->defWidth, "%d", width);          sprintf(tsdPtr->defWidth, "%d", width);
221      }      }
222      for ( ; specPtr->type != TK_OPTION_END; specPtr++) {      for ( ; specPtr->type != TK_OPTION_END; specPtr++) {
223          if (specPtr->internalOffset == Tk_Offset(TkButton, borderWidth)) {          if (specPtr->internalOffset == Tk_Offset(TkButton, borderWidth)) {
224              specPtr->defValue = tsdPtr->defWidth;              specPtr->defValue = tsdPtr->defWidth;
225          }          }
226      }      }
227  }  }
228    
229  /*  /*
230   *----------------------------------------------------------------------   *----------------------------------------------------------------------
231   *   *
232   * TkpCreateButton --   * TkpCreateButton --
233   *   *
234   *      Allocate a new TkButton structure.   *      Allocate a new TkButton structure.
235   *   *
236   * Results:   * Results:
237   *      Returns a newly allocated TkButton structure.   *      Returns a newly allocated TkButton structure.
238   *   *
239   * Side effects:   * Side effects:
240   *      Registers an event handler for the widget.   *      Registers an event handler for the widget.
241   *   *
242   *----------------------------------------------------------------------   *----------------------------------------------------------------------
243   */   */
244    
245  TkButton *  TkButton *
246  TkpCreateButton(tkwin)  TkpCreateButton(tkwin)
247      Tk_Window tkwin;      Tk_Window tkwin;
248  {  {
249      WinButton *butPtr;      WinButton *butPtr;
250    
251      butPtr = (WinButton *)ckalloc(sizeof(WinButton));      butPtr = (WinButton *)ckalloc(sizeof(WinButton));
252      butPtr->hwnd = NULL;      butPtr->hwnd = NULL;
253      return (TkButton *) butPtr;      return (TkButton *) butPtr;
254  }  }
255    
256  /*  /*
257   *----------------------------------------------------------------------   *----------------------------------------------------------------------
258   *   *
259   * CreateProc --   * CreateProc --
260   *   *
261   *      This function creates a new Button control, subclasses   *      This function creates a new Button control, subclasses
262   *      the instance, and generates a new Window object.   *      the instance, and generates a new Window object.
263   *   *
264   * Results:   * Results:
265   *      Returns the newly allocated Window object, or None on failure.   *      Returns the newly allocated Window object, or None on failure.
266   *   *
267   * Side effects:   * Side effects:
268   *      Causes a new Button control to come into existence.   *      Causes a new Button control to come into existence.
269   *   *
270   *----------------------------------------------------------------------   *----------------------------------------------------------------------
271   */   */
272    
273  static Window  static Window
274  CreateProc(tkwin, parentWin, instanceData)  CreateProc(tkwin, parentWin, instanceData)
275      Tk_Window tkwin;            /* Token for window. */      Tk_Window tkwin;            /* Token for window. */
276      Window parentWin;           /* Parent of new window. */      Window parentWin;           /* Parent of new window. */
277      ClientData instanceData;    /* Button instance data. */      ClientData instanceData;    /* Button instance data. */
278  {  {
279      Window window;      Window window;
280      HWND parent;      HWND parent;
281      char *class;      char *class;
282      WinButton *butPtr = (WinButton *)instanceData;      WinButton *butPtr = (WinButton *)instanceData;
283    
284      parent = Tk_GetHWND(parentWin);      parent = Tk_GetHWND(parentWin);
285      if (butPtr->info.type == TYPE_LABEL) {      if (butPtr->info.type == TYPE_LABEL) {
286          class = "STATIC";          class = "STATIC";
287          butPtr->style = SS_OWNERDRAW | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;          butPtr->style = SS_OWNERDRAW | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;
288      } else {      } else {
289          class = "BUTTON";          class = "BUTTON";
290          butPtr->style = BS_OWNERDRAW | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;          butPtr->style = BS_OWNERDRAW | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;
291      }      }
292      butPtr->hwnd = CreateWindow(class, NULL, butPtr->style,      butPtr->hwnd = CreateWindow(class, NULL, butPtr->style,
293              Tk_X(tkwin), Tk_Y(tkwin), Tk_Width(tkwin), Tk_Height(tkwin),              Tk_X(tkwin), Tk_Y(tkwin), Tk_Width(tkwin), Tk_Height(tkwin),
294              parent, NULL, Tk_GetHINSTANCE(), NULL);              parent, NULL, Tk_GetHINSTANCE(), NULL);
295      SetWindowPos(butPtr->hwnd, HWND_TOP, 0, 0, 0, 0,      SetWindowPos(butPtr->hwnd, HWND_TOP, 0, 0, 0, 0,
296                      SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);                      SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
297      butPtr->oldProc = (WNDPROC)SetWindowLong(butPtr->hwnd, GWL_WNDPROC,      butPtr->oldProc = (WNDPROC)SetWindowLong(butPtr->hwnd, GWL_WNDPROC,
298              (DWORD) ButtonProc);              (DWORD) ButtonProc);
299    
300      window = Tk_AttachHWND(tkwin, butPtr->hwnd);      window = Tk_AttachHWND(tkwin, butPtr->hwnd);
301      return window;      return window;
302  }  }
303    
304  /*  /*
305   *----------------------------------------------------------------------   *----------------------------------------------------------------------
306   *   *
307   * TkpDestroyButton --   * TkpDestroyButton --
308   *   *
309   *      Free data structures associated with the button control.   *      Free data structures associated with the button control.
310   *   *
311   * Results:   * Results:
312   *      None.   *      None.
313   *   *
314   * Side effects:   * Side effects:
315   *      Restores the default control state.   *      Restores the default control state.
316   *   *
317   *----------------------------------------------------------------------   *----------------------------------------------------------------------
318   */   */
319    
320  void  void
321  TkpDestroyButton(butPtr)  TkpDestroyButton(butPtr)
322      TkButton *butPtr;      TkButton *butPtr;
323  {  {
324      WinButton *winButPtr = (WinButton *)butPtr;      WinButton *winButPtr = (WinButton *)butPtr;
325      HWND hwnd = winButPtr->hwnd;      HWND hwnd = winButPtr->hwnd;
326      if (hwnd) {      if (hwnd) {
327          SetWindowLong(hwnd, GWL_WNDPROC, (DWORD) winButPtr->oldProc);          SetWindowLong(hwnd, GWL_WNDPROC, (DWORD) winButPtr->oldProc);
328      }      }
329  }  }
330    
331  /*  /*
332   *----------------------------------------------------------------------   *----------------------------------------------------------------------
333   *   *
334   * TkpDisplayButton --   * TkpDisplayButton --
335   *   *
336   *      This procedure is invoked to display a button widget.  It is   *      This procedure is invoked to display a button widget.  It is
337   *      normally invoked as an idle handler.   *      normally invoked as an idle handler.
338   *   *
339   * Results:   * Results:
340   *      None.   *      None.
341   *   *
342   * Side effects:   * Side effects:
343   *      Information appears on the screen.  The REDRAW_PENDING flag   *      Information appears on the screen.  The REDRAW_PENDING flag
344   *      is cleared.   *      is cleared.
345   *   *
346   *----------------------------------------------------------------------   *----------------------------------------------------------------------
347   */   */
348    
349  void  void
350  TkpDisplayButton(clientData)  TkpDisplayButton(clientData)
351      ClientData clientData;      /* Information about widget. */      ClientData clientData;      /* Information about widget. */
352  {  {
353      TkWinDCState state;      TkWinDCState state;
354      HDC dc;      HDC dc;
355      register TkButton *butPtr = (TkButton *) clientData;      register TkButton *butPtr = (TkButton *) clientData;
356      GC gc;      GC gc;
357      Tk_3DBorder border;      Tk_3DBorder border;
358      Pixmap pixmap;      Pixmap pixmap;
359      int x = 0;                  /* Initialization only needed to stop      int x = 0;                  /* Initialization only needed to stop
360                                   * compiler warning. */                                   * compiler warning. */
361      int y, relief;      int y, relief;
362      register Tk_Window tkwin = butPtr->tkwin;      register Tk_Window tkwin = butPtr->tkwin;
363      int width, height;      int width, height;
364      int defaultWidth;           /* Width of default ring. */      int defaultWidth;           /* Width of default ring. */
365      int offset;                 /* 0 means this is a label widget.  1 means      int offset;                 /* 0 means this is a label widget.  1 means
366                                   * it is a flavor of button, so we offset                                   * it is a flavor of button, so we offset
367                                   * the text to make the button appear to                                   * the text to make the button appear to
368                                   * move up and down as the relief changes. */                                   * move up and down as the relief changes. */
369      DWORD *boxesPalette;      DWORD *boxesPalette;
370    
371      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
372              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
373    
374      boxesPalette= tsdPtr->boxesPalette;      boxesPalette= tsdPtr->boxesPalette;
375      butPtr->flags &= ~REDRAW_PENDING;      butPtr->flags &= ~REDRAW_PENDING;
376      if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {      if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
377          return;          return;
378      }      }
379    
380      border = butPtr->normalBorder;      border = butPtr->normalBorder;
381      if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {      if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {
382          gc = butPtr->disabledGC;          gc = butPtr->disabledGC;
383      } else if ((butPtr->state == STATE_ACTIVE)      } else if ((butPtr->state == STATE_ACTIVE)
384              && !Tk_StrictMotif(butPtr->tkwin)) {              && !Tk_StrictMotif(butPtr->tkwin)) {
385          gc = butPtr->activeTextGC;          gc = butPtr->activeTextGC;
386          border = butPtr->activeBorder;          border = butPtr->activeBorder;
387      } else {      } else {
388          gc = butPtr->normalTextGC;          gc = butPtr->normalTextGC;
389      }      }
390      if ((butPtr->flags & SELECTED) && (butPtr->state != STATE_ACTIVE)      if ((butPtr->flags & SELECTED) && (butPtr->state != STATE_ACTIVE)
391              && (butPtr->selectBorder != NULL) && !butPtr->indicatorOn) {              && (butPtr->selectBorder != NULL) && !butPtr->indicatorOn) {
392          border = butPtr->selectBorder;          border = butPtr->selectBorder;
393      }      }
394    
395      /*      /*
396       * Override the relief specified for the button if this is a       * Override the relief specified for the button if this is a
397       * checkbutton or radiobutton and there's no indicator.       * checkbutton or radiobutton and there's no indicator.
398       */       */
399    
400      relief = butPtr->relief;      relief = butPtr->relief;
401      if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) {      if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) {
402          relief = (butPtr->flags & SELECTED) ? TK_RELIEF_SUNKEN          relief = (butPtr->flags & SELECTED) ? TK_RELIEF_SUNKEN
403                  : TK_RELIEF_RAISED;                  : TK_RELIEF_RAISED;
404      }      }
405    
406      /*      /*
407       * Compute width of default ring and offset for pushed buttons.       * Compute width of default ring and offset for pushed buttons.
408       */       */
409    
410      if (butPtr->type == TYPE_BUTTON) {      if (butPtr->type == TYPE_BUTTON) {
411          defaultWidth = ((butPtr->defaultState == DEFAULT_ACTIVE)          defaultWidth = ((butPtr->defaultState == DEFAULT_ACTIVE)
412                  ? butPtr->highlightWidth : 0);                  ? butPtr->highlightWidth : 0);
413          offset = 1;          offset = 1;
414      } else {      } else {
415          defaultWidth = 0;          defaultWidth = 0;
416          if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) {          if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) {
417              offset = 1;              offset = 1;
418          } else {          } else {
419              offset = 0;              offset = 0;
420          }          }
421      }      }
422    
423      /*      /*
424       * In order to avoid screen flashes, this procedure redraws       * In order to avoid screen flashes, this procedure redraws
425       * the button in a pixmap, then copies the pixmap to the       * the button in a pixmap, then copies the pixmap to the
426       * screen in a single operation.  This means that there's no       * screen in a single operation.  This means that there's no
427       * point in time where the on-sreen image has been cleared.       * point in time where the on-sreen image has been cleared.
428       */       */
429    
430      pixmap = Tk_GetPixmap(butPtr->display, Tk_WindowId(tkwin),      pixmap = Tk_GetPixmap(butPtr->display, Tk_WindowId(tkwin),
431              Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));              Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
432      Tk_Fill3DRectangle(tkwin, pixmap, border, 0, 0, Tk_Width(tkwin),      Tk_Fill3DRectangle(tkwin, pixmap, border, 0, 0, Tk_Width(tkwin),
433              Tk_Height(tkwin), 0, TK_RELIEF_FLAT);              Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
434    
435      /*      /*
436       * Display image or bitmap or text for button.       * Display image or bitmap or text for button.
437       */       */
438    
439      if (butPtr->image != None) {      if (butPtr->image != None) {
440          Tk_SizeOfImage(butPtr->image, &width, &height);          Tk_SizeOfImage(butPtr->image, &width, &height);
441    
442          imageOrBitmap:          imageOrBitmap:
443          TkComputeAnchor(butPtr->anchor, tkwin, 0, 0,          TkComputeAnchor(butPtr->anchor, tkwin, 0, 0,
444                  butPtr->indicatorSpace + width, height, &x, &y);                  butPtr->indicatorSpace + width, height, &x, &y);
445          x += butPtr->indicatorSpace;          x += butPtr->indicatorSpace;
446    
447          if (relief == TK_RELIEF_SUNKEN) {          if (relief == TK_RELIEF_SUNKEN) {
448              x += offset;              x += offset;
449              y += offset;              y += offset;
450          }          }
451          if (butPtr->image != NULL) {          if (butPtr->image != NULL) {
452              if ((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) {              if ((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) {
453                  Tk_RedrawImage(butPtr->selectImage, 0, 0, width, height,                  Tk_RedrawImage(butPtr->selectImage, 0, 0, width, height,
454                          pixmap, x, y);                          pixmap, x, y);
455              } else {              } else {
456                  Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap,                  Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap,
457                          x, y);                          x, y);
458              }              }
459          } else {          } else {
460              XSetClipOrigin(butPtr->display, gc, x, y);              XSetClipOrigin(butPtr->display, gc, x, y);
461              XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc, 0, 0,              XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc, 0, 0,
462                      (unsigned int) width, (unsigned int) height, x, y, 1);                      (unsigned int) width, (unsigned int) height, x, y, 1);
463              XSetClipOrigin(butPtr->display, gc, 0, 0);              XSetClipOrigin(butPtr->display, gc, 0, 0);
464          }          }
465          y += height/2;          y += height/2;
466      } else if (butPtr->bitmap != None) {      } else if (butPtr->bitmap != None) {
467          Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);          Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
468          goto imageOrBitmap;          goto imageOrBitmap;
469      } else {      } else {
470          RECT rect;          RECT rect;
471          TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY,          TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY,
472                  butPtr->indicatorSpace + butPtr->textWidth, butPtr->textHeight,                  butPtr->indicatorSpace + butPtr->textWidth, butPtr->textHeight,
473                  &x, &y);                  &x, &y);
474    
475          x += butPtr->indicatorSpace;          x += butPtr->indicatorSpace;
476    
477          if (relief == TK_RELIEF_SUNKEN) {          if (relief == TK_RELIEF_SUNKEN) {
478              x += offset;              x += offset;
479              y += offset;              y += offset;
480          }          }
481          Tk_DrawTextLayout(butPtr->display, pixmap, gc, butPtr->textLayout,          Tk_DrawTextLayout(butPtr->display, pixmap, gc, butPtr->textLayout,
482                  x, y, 0, -1);                  x, y, 0, -1);
483          Tk_UnderlineTextLayout(butPtr->display, pixmap, gc,          Tk_UnderlineTextLayout(butPtr->display, pixmap, gc,
484                  butPtr->textLayout, x, y, butPtr->underline);                  butPtr->textLayout, x, y, butPtr->underline);
485    
486          /*          /*
487           * Draw the focus ring.  If this is a push button then we need to put           * Draw the focus ring.  If this is a push button then we need to put
488           * it around the inner edge of the border, otherwise we put it around           * it around the inner edge of the border, otherwise we put it around
489           * the text.           * the text.
490           */           */
491    
492          if (butPtr->flags & GOT_FOCUS && butPtr->type != TYPE_LABEL) {          if (butPtr->flags & GOT_FOCUS && butPtr->type != TYPE_LABEL) {
493              dc = TkWinGetDrawableDC(butPtr->display, pixmap, &state);              dc = TkWinGetDrawableDC(butPtr->display, pixmap, &state);
494              if (butPtr->type == TYPE_BUTTON || !butPtr->indicatorOn) {              if (butPtr->type == TYPE_BUTTON || !butPtr->indicatorOn) {
495                  rect.top = butPtr->borderWidth + 1 + defaultWidth;                  rect.top = butPtr->borderWidth + 1 + defaultWidth;
496                  rect.left = rect.top;                  rect.left = rect.top;
497                  rect.right = Tk_Width(tkwin) - rect.left;                  rect.right = Tk_Width(tkwin) - rect.left;
498                  rect.bottom = Tk_Height(tkwin) - rect.top;                  rect.bottom = Tk_Height(tkwin) - rect.top;
499              } else {              } else {
500                  rect.top = y-2;                  rect.top = y-2;
501                  rect.left = x-2;                  rect.left = x-2;
502                  rect.right = x+butPtr->textWidth + 1;                  rect.right = x+butPtr->textWidth + 1;
503                  rect.bottom = y+butPtr->textHeight + 1;                  rect.bottom = y+butPtr->textHeight + 1;
504              }              }
505              SetTextColor(dc, gc->foreground);              SetTextColor(dc, gc->foreground);
506              SetBkColor(dc, gc->background);              SetBkColor(dc, gc->background);
507              DrawFocusRect(dc, &rect);              DrawFocusRect(dc, &rect);
508              TkWinReleaseDrawableDC(pixmap, dc, &state);              TkWinReleaseDrawableDC(pixmap, dc, &state);
509          }          }
510          y += butPtr->textHeight/2;          y += butPtr->textHeight/2;
511      }      }
512    
513      /*      /*
514       * Draw the indicator for check buttons and radio buttons.  At this       * Draw the indicator for check buttons and radio buttons.  At this
515       * point x and y refer to the top-left corner of the text or image       * point x and y refer to the top-left corner of the text or image
516       * or bitmap.       * or bitmap.
517       */       */
518    
519      if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn      if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn
520              && tsdPtr->boxesPtr) {              && tsdPtr->boxesPtr) {
521          int xSrc, ySrc;          int xSrc, ySrc;
522    
523          x -= butPtr->indicatorSpace;          x -= butPtr->indicatorSpace;
524          y -= butPtr->indicatorDiameter / 2;          y -= butPtr->indicatorDiameter / 2;
525    
526          xSrc = (butPtr->flags & SELECTED) ? tsdPtr->boxWidth : 0;          xSrc = (butPtr->flags & SELECTED) ? tsdPtr->boxWidth : 0;
527          if (butPtr->state == STATE_ACTIVE) {          if (butPtr->state == STATE_ACTIVE) {
528              xSrc += tsdPtr->boxWidth*2;              xSrc += tsdPtr->boxWidth*2;
529          }          }
530          ySrc = (butPtr->type == TYPE_RADIO_BUTTON) ? 0 : tsdPtr->boxHeight;          ySrc = (butPtr->type == TYPE_RADIO_BUTTON) ? 0 : tsdPtr->boxHeight;
531                                    
532          /*          /*
533           * Update the palette in the boxes bitmap to reflect the current           * Update the palette in the boxes bitmap to reflect the current
534           * button colors.  Note that this code relies on the layout of the           * button colors.  Note that this code relies on the layout of the
535           * bitmap's palette.  Also, all of the colors used to draw the           * bitmap's palette.  Also, all of the colors used to draw the
536           * bitmap must be in the palette that is selected into the DC of           * bitmap must be in the palette that is selected into the DC of
537           * the offscreen pixmap.  This requires that the static colors           * the offscreen pixmap.  This requires that the static colors
538           * be placed into the palette.           * be placed into the palette.
539           */           */
540    
541          boxesPalette[PAL_CHECK] = FlipColor(gc->foreground);          boxesPalette[PAL_CHECK] = FlipColor(gc->foreground);
542          boxesPalette[PAL_TOP_OUTER] = FlipColor(TkWinGetBorderPixels(tkwin,          boxesPalette[PAL_TOP_OUTER] = FlipColor(TkWinGetBorderPixels(tkwin,
543                  border, TK_3D_DARK_GC));                  border, TK_3D_DARK_GC));
544          boxesPalette[PAL_TOP_INNER] = FlipColor(TkWinGetBorderPixels(tkwin,          boxesPalette[PAL_TOP_INNER] = FlipColor(TkWinGetBorderPixels(tkwin,
545                  border, TK_3D_DARK2));                  border, TK_3D_DARK2));
546          boxesPalette[PAL_BOTTOM_INNER] = FlipColor(TkWinGetBorderPixels(tkwin,          boxesPalette[PAL_BOTTOM_INNER] = FlipColor(TkWinGetBorderPixels(tkwin,
547                  border, TK_3D_LIGHT2));                  border, TK_3D_LIGHT2));
548          boxesPalette[PAL_BOTTOM_OUTER] = FlipColor(TkWinGetBorderPixels(tkwin,          boxesPalette[PAL_BOTTOM_OUTER] = FlipColor(TkWinGetBorderPixels(tkwin,
549                  border, TK_3D_LIGHT_GC));                  border, TK_3D_LIGHT_GC));
550          if (butPtr->state == STATE_DISABLED) {          if (butPtr->state == STATE_DISABLED) {
551              boxesPalette[PAL_INTERIOR] = FlipColor(TkWinGetBorderPixels(tkwin,              boxesPalette[PAL_INTERIOR] = FlipColor(TkWinGetBorderPixels(tkwin,
552                  border, TK_3D_LIGHT2));                  border, TK_3D_LIGHT2));
553          } else if (butPtr->selectBorder != NULL) {          } else if (butPtr->selectBorder != NULL) {
554              boxesPalette[PAL_INTERIOR] = FlipColor(TkWinGetBorderPixels(tkwin,              boxesPalette[PAL_INTERIOR] = FlipColor(TkWinGetBorderPixels(tkwin,
555                      butPtr->selectBorder, TK_3D_FLAT_GC));                      butPtr->selectBorder, TK_3D_FLAT_GC));
556          } else {          } else {
557              boxesPalette[PAL_INTERIOR] = FlipColor(GetSysColor(COLOR_WINDOW));              boxesPalette[PAL_INTERIOR] = FlipColor(GetSysColor(COLOR_WINDOW));
558          }          }
559          boxesPalette[PAL_BACKGROUND] = FlipColor(TkWinGetBorderPixels(tkwin,          boxesPalette[PAL_BACKGROUND] = FlipColor(TkWinGetBorderPixels(tkwin,
560                  border, TK_3D_FLAT_GC));                  border, TK_3D_FLAT_GC));
561    
562          dc = TkWinGetDrawableDC(butPtr->display, pixmap, &state);          dc = TkWinGetDrawableDC(butPtr->display, pixmap, &state);
563          StretchDIBits(dc, x, y, tsdPtr->boxWidth, tsdPtr->boxHeight,          StretchDIBits(dc, x, y, tsdPtr->boxWidth, tsdPtr->boxHeight,
564                  xSrc, ySrc, tsdPtr->boxWidth, tsdPtr->boxHeight,                  xSrc, ySrc, tsdPtr->boxWidth, tsdPtr->boxHeight,
565                  tsdPtr->boxesBits, (LPBITMAPINFO) tsdPtr->boxesPtr,                  tsdPtr->boxesBits, (LPBITMAPINFO) tsdPtr->boxesPtr,
566                  DIB_RGB_COLORS, SRCCOPY);                  DIB_RGB_COLORS, SRCCOPY);
567          TkWinReleaseDrawableDC(pixmap, dc, &state);          TkWinReleaseDrawableDC(pixmap, dc, &state);
568      }      }
569    
570      /*      /*
571       * If the button is disabled with a stipple rather than a special       * If the button is disabled with a stipple rather than a special
572       * foreground color, generate the stippled effect.  If the widget       * foreground color, generate the stippled effect.  If the widget
573       * is selected and we use a different background color when selected,       * is selected and we use a different background color when selected,
574       * must temporarily modify the GC.       * must temporarily modify the GC.
575       */       */
576    
577      if ((butPtr->state == STATE_DISABLED)      if ((butPtr->state == STATE_DISABLED)
578              && ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) {              && ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) {
579          if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn          if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn
580                  && (butPtr->selectBorder != NULL)) {                  && (butPtr->selectBorder != NULL)) {
581              XSetForeground(butPtr->display, butPtr->disabledGC,              XSetForeground(butPtr->display, butPtr->disabledGC,
582                      Tk_3DBorderColor(butPtr->selectBorder)->pixel);                      Tk_3DBorderColor(butPtr->selectBorder)->pixel);
583          }          }
584          XFillRectangle(butPtr->display, pixmap, butPtr->disabledGC,          XFillRectangle(butPtr->display, pixmap, butPtr->disabledGC,
585                  butPtr->inset, butPtr->inset,                  butPtr->inset, butPtr->inset,
586                  (unsigned) (Tk_Width(tkwin) - 2*butPtr->inset),                  (unsigned) (Tk_Width(tkwin) - 2*butPtr->inset),
587                  (unsigned) (Tk_Height(tkwin) - 2*butPtr->inset));                  (unsigned) (Tk_Height(tkwin) - 2*butPtr->inset));
588          if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn          if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn
589                  && (butPtr->selectBorder != NULL)) {                  && (butPtr->selectBorder != NULL)) {
590              XSetForeground(butPtr->display, butPtr->disabledGC,              XSetForeground(butPtr->display, butPtr->disabledGC,
591                      Tk_3DBorderColor(butPtr->normalBorder)->pixel);                      Tk_3DBorderColor(butPtr->normalBorder)->pixel);
592          }          }
593      }      }
594    
595      /*      /*
596       * Draw the border and traversal highlight last.  This way, if the       * Draw the border and traversal highlight last.  This way, if the
597       * button's contents overflow they'll be covered up by the border.       * button's contents overflow they'll be covered up by the border.
598       */       */
599    
600      if (relief != TK_RELIEF_FLAT) {      if (relief != TK_RELIEF_FLAT) {
601          Tk_Draw3DRectangle(tkwin, pixmap, border,          Tk_Draw3DRectangle(tkwin, pixmap, border,
602                  defaultWidth, defaultWidth,                  defaultWidth, defaultWidth,
603                  Tk_Width(tkwin) - 2*defaultWidth,                  Tk_Width(tkwin) - 2*defaultWidth,
604                  Tk_Height(tkwin) - 2*defaultWidth,                  Tk_Height(tkwin) - 2*defaultWidth,
605                  butPtr->borderWidth, relief);                  butPtr->borderWidth, relief);
606      }      }
607      if (defaultWidth != 0) {      if (defaultWidth != 0) {
608          dc = TkWinGetDrawableDC(butPtr->display, pixmap, &state);          dc = TkWinGetDrawableDC(butPtr->display, pixmap, &state);
609          TkWinFillRect(dc, 0, 0, Tk_Width(tkwin), defaultWidth,          TkWinFillRect(dc, 0, 0, Tk_Width(tkwin), defaultWidth,
610                  butPtr->highlightColorPtr->pixel);                  butPtr->highlightColorPtr->pixel);
611          TkWinFillRect(dc, 0, 0, defaultWidth, Tk_Height(tkwin),          TkWinFillRect(dc, 0, 0, defaultWidth, Tk_Height(tkwin),
612                  butPtr->highlightColorPtr->pixel);                  butPtr->highlightColorPtr->pixel);
613          TkWinFillRect(dc, 0, Tk_Height(tkwin) - defaultWidth,          TkWinFillRect(dc, 0, Tk_Height(tkwin) - defaultWidth,
614                  Tk_Width(tkwin), defaultWidth,                  Tk_Width(tkwin), defaultWidth,
615                  butPtr->highlightColorPtr->pixel);                  butPtr->highlightColorPtr->pixel);
616          TkWinFillRect(dc, Tk_Width(tkwin) - defaultWidth, 0,          TkWinFillRect(dc, Tk_Width(tkwin) - defaultWidth, 0,
617                  defaultWidth, Tk_Height(tkwin),                  defaultWidth, Tk_Height(tkwin),
618                  butPtr->highlightColorPtr->pixel);                  butPtr->highlightColorPtr->pixel);
619          TkWinReleaseDrawableDC(pixmap, dc, &state);          TkWinReleaseDrawableDC(pixmap, dc, &state);
620      }      }
621    
622      /*      /*
623       * Copy the information from the off-screen pixmap onto the screen,       * Copy the information from the off-screen pixmap onto the screen,
624       * then delete the pixmap.       * then delete the pixmap.
625       */       */
626    
627      XCopyArea(butPtr->display, pixmap, Tk_WindowId(tkwin),      XCopyArea(butPtr->display, pixmap, Tk_WindowId(tkwin),
628              butPtr->copyGC, 0, 0, (unsigned) Tk_Width(tkwin),              butPtr->copyGC, 0, 0, (unsigned) Tk_Width(tkwin),
629              (unsigned) Tk_Height(tkwin), 0, 0);              (unsigned) Tk_Height(tkwin), 0, 0);
630      Tk_FreePixmap(butPtr->display, pixmap);      Tk_FreePixmap(butPtr->display, pixmap);
631  }  }
632    
633  /*  /*
634   *----------------------------------------------------------------------   *----------------------------------------------------------------------
635   *   *
636   * TkpComputeButtonGeometry --   * TkpComputeButtonGeometry --
637   *   *
638   *      After changes in a button's text or bitmap, this procedure   *      After changes in a button's text or bitmap, this procedure
639   *      recomputes the button's geometry and passes this information   *      recomputes the button's geometry and passes this information
640   *      along to the geometry manager for the window.   *      along to the geometry manager for the window.
641   *   *
642   * Results:   * Results:
643   *      None.   *      None.
644   *   *
645   * Side effects:   * Side effects:
646   *      The button's window may change size.   *      The button's window may change size.
647   *   *
648   *----------------------------------------------------------------------   *----------------------------------------------------------------------
649   */   */
650    
651  void  void
652  TkpComputeButtonGeometry(butPtr)  TkpComputeButtonGeometry(butPtr)
653      register TkButton *butPtr;  /* Button whose geometry may have changed. */      register TkButton *butPtr;  /* Button whose geometry may have changed. */
654  {  {
655      int width, height, avgWidth;      int width, height, avgWidth;
656      Tk_FontMetrics fm;      Tk_FontMetrics fm;
657      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
658              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
659    
660      if (butPtr->highlightWidth < 0) {      if (butPtr->highlightWidth < 0) {
661          butPtr->highlightWidth = 0;          butPtr->highlightWidth = 0;
662      }      }
663      butPtr->inset = butPtr->highlightWidth + butPtr->borderWidth;      butPtr->inset = butPtr->highlightWidth + butPtr->borderWidth;
664      butPtr->indicatorSpace = 0;      butPtr->indicatorSpace = 0;
665    
666      if (!tsdPtr->boxesPtr) {      if (!tsdPtr->boxesPtr) {
667          InitBoxes();          InitBoxes();
668      }      }
669    
670      if (butPtr->image != NULL) {      if (butPtr->image != NULL) {
671          Tk_SizeOfImage(butPtr->image, &width, &height);          Tk_SizeOfImage(butPtr->image, &width, &height);
672          imageOrBitmap:          imageOrBitmap:
673          if (butPtr->width > 0) {          if (butPtr->width > 0) {
674              width = butPtr->width;              width = butPtr->width;
675          }          }
676          if (butPtr->height > 0) {          if (butPtr->height > 0) {
677              height = butPtr->height;              height = butPtr->height;
678          }          }
679          if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {          if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {
680              butPtr->indicatorSpace = tsdPtr->boxWidth * 2;              butPtr->indicatorSpace = tsdPtr->boxWidth * 2;
681              butPtr->indicatorDiameter = tsdPtr->boxHeight;              butPtr->indicatorDiameter = tsdPtr->boxHeight;
682          }          }
683      } else if (butPtr->bitmap != None) {      } else if (butPtr->bitmap != None) {
684          Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);          Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
685          goto imageOrBitmap;          goto imageOrBitmap;
686      } else {      } else {
687          Tk_FreeTextLayout(butPtr->textLayout);          Tk_FreeTextLayout(butPtr->textLayout);
688          butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,          butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,
689                  Tcl_GetString(butPtr->textPtr), -1, butPtr->wrapLength,                  Tcl_GetString(butPtr->textPtr), -1, butPtr->wrapLength,
690                  butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight);                  butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight);
691    
692          width = butPtr->textWidth;          width = butPtr->textWidth;
693          height = butPtr->textHeight;          height = butPtr->textHeight;
694          avgWidth = Tk_TextWidth(butPtr->tkfont, "0", 1);          avgWidth = Tk_TextWidth(butPtr->tkfont, "0", 1);
695          Tk_GetFontMetrics(butPtr->tkfont, &fm);          Tk_GetFontMetrics(butPtr->tkfont, &fm);
696    
697          if (butPtr->width > 0) {          if (butPtr->width > 0) {
698              width = butPtr->width * avgWidth;              width = butPtr->width * avgWidth;
699          }          }
700          if (butPtr->height > 0) {          if (butPtr->height > 0) {
701              height = butPtr->height * fm.linespace;              height = butPtr->height * fm.linespace;
702          }          }
703    
704          if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {          if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {
705              butPtr->indicatorDiameter = tsdPtr->boxHeight;              butPtr->indicatorDiameter = tsdPtr->boxHeight;
706              butPtr->indicatorSpace = butPtr->indicatorDiameter + avgWidth;              butPtr->indicatorSpace = butPtr->indicatorDiameter + avgWidth;
707          }          }
708    
709          /*          /*
710           * Increase the inset to allow for the focus ring.           * Increase the inset to allow for the focus ring.
711           */           */
712    
713          if (butPtr->type != TYPE_LABEL) {          if (butPtr->type != TYPE_LABEL) {
714              butPtr->inset += 3;              butPtr->inset += 3;
715          }          }
716      }      }
717    
718      /*      /*
719       * When issuing the geometry request, add extra space for the indicator,       * When issuing the geometry request, add extra space for the indicator,
720       * if any, and for the border and padding, plus an extra pixel so the       * if any, and for the border and padding, plus an extra pixel so the
721       * display can be offset by 1 pixel in either direction for the raised       * display can be offset by 1 pixel in either direction for the raised
722       * or lowered effect.       * or lowered effect.
723       */       */
724    
725      if ((butPtr->image == NULL) && (butPtr->bitmap == None)) {      if ((butPtr->image == NULL) && (butPtr->bitmap == None)) {
726          width += 2*butPtr->padX;          width += 2*butPtr->padX;
727          height += 2*butPtr->padY;          height += 2*butPtr->padY;
728      }      }
729      if ((butPtr->type == TYPE_BUTTON)      if ((butPtr->type == TYPE_BUTTON)
730              || ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn)) {              || ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn)) {
731          width += 1;          width += 1;
732          height += 1;          height += 1;
733      }      }
734      Tk_GeometryRequest(butPtr->tkwin, (int) (width + butPtr->indicatorSpace      Tk_GeometryRequest(butPtr->tkwin, (int) (width + butPtr->indicatorSpace
735              + 2*butPtr->inset), (int) (height + 2*butPtr->inset));              + 2*butPtr->inset), (int) (height + 2*butPtr->inset));
736      Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);      Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
737  }  }
738    
739  /*  /*
740   *----------------------------------------------------------------------   *----------------------------------------------------------------------
741   *   *
742   * ButtonProc --   * ButtonProc --
743   *   *
744   *      This function is call by Windows whenever an event occurs on   *      This function is call by Windows whenever an event occurs on
745   *      a button control created by Tk.   *      a button control created by Tk.
746   *   *
747   * Results:   * Results:
748   *      Standard Windows return value.   *      Standard Windows return value.
749   *   *
750   * Side effects:   * Side effects:
751   *      May generate events.   *      May generate events.
752   *   *
753   *----------------------------------------------------------------------   *----------------------------------------------------------------------
754   */   */
755    
756  static LRESULT CALLBACK  static LRESULT CALLBACK
757  ButtonProc(hwnd, message, wParam, lParam)  ButtonProc(hwnd, message, wParam, lParam)
758      HWND hwnd;      HWND hwnd;
759      UINT message;      UINT message;
760      WPARAM wParam;      WPARAM wParam;
761      LPARAM lParam;      LPARAM lParam;
762  {  {
763      LRESULT result;      LRESULT result;
764      WinButton *butPtr;      WinButton *butPtr;
765      Tk_Window tkwin = Tk_HWNDToWindow(hwnd);      Tk_Window tkwin = Tk_HWNDToWindow(hwnd);
766    
767      if (tkwin == NULL) {      if (tkwin == NULL) {
768          panic("ButtonProc called on an invalid HWND");          panic("ButtonProc called on an invalid HWND");
769      }      }
770      butPtr = (WinButton *)((TkWindow*)tkwin)->instanceData;      butPtr = (WinButton *)((TkWindow*)tkwin)->instanceData;
771    
772      switch(message) {      switch(message) {
773          case WM_ERASEBKGND:          case WM_ERASEBKGND:
774              return 0;              return 0;
775    
776          case BM_GETCHECK:          case BM_GETCHECK:
777              if (((butPtr->info.type == TYPE_CHECK_BUTTON)              if (((butPtr->info.type == TYPE_CHECK_BUTTON)
778                      || (butPtr->info.type == TYPE_RADIO_BUTTON))                      || (butPtr->info.type == TYPE_RADIO_BUTTON))
779                      && butPtr->info.indicatorOn) {                      && butPtr->info.indicatorOn) {
780                  return (butPtr->info.flags & SELECTED)                  return (butPtr->info.flags & SELECTED)
781                      ? BST_CHECKED : BST_UNCHECKED;                      ? BST_CHECKED : BST_UNCHECKED;
782              }              }
783              return 0;              return 0;
784    
785          case BM_GETSTATE: {          case BM_GETSTATE: {
786              DWORD state = 0;              DWORD state = 0;
787              if (((butPtr->info.type == TYPE_CHECK_BUTTON)              if (((butPtr->info.type == TYPE_CHECK_BUTTON)
788                      || (butPtr->info.type == TYPE_RADIO_BUTTON))                      || (butPtr->info.type == TYPE_RADIO_BUTTON))
789                      && butPtr->info.indicatorOn) {                      && butPtr->info.indicatorOn) {
790                  state = (butPtr->info.flags & SELECTED)                  state = (butPtr->info.flags & SELECTED)
791                      ? BST_CHECKED : BST_UNCHECKED;                      ? BST_CHECKED : BST_UNCHECKED;
792              }              }
793              if (butPtr->info.flags & GOT_FOCUS) {              if (butPtr->info.flags & GOT_FOCUS) {
794                  state |= BST_FOCUS;                  state |= BST_FOCUS;
795              }              }
796              return state;              return state;
797          }          }
798          case WM_ENABLE:          case WM_ENABLE:
799              break;              break;
800    
801          case WM_PAINT: {          case WM_PAINT: {
802              PAINTSTRUCT ps;              PAINTSTRUCT ps;
803              BeginPaint(hwnd, &ps);              BeginPaint(hwnd, &ps);
804              EndPaint(hwnd, &ps);              EndPaint(hwnd, &ps);
805              TkpDisplayButton((ClientData)butPtr);              TkpDisplayButton((ClientData)butPtr);
806    
807              /*              /*
808               * Special note: must cancel any existing idle handler               * Special note: must cancel any existing idle handler
809               * for TkpDisplayButton;  it's no longer needed, and               * for TkpDisplayButton;  it's no longer needed, and
810               * TkpDisplayButton cleared the REDRAW_PENDING flag.               * TkpDisplayButton cleared the REDRAW_PENDING flag.
811               */               */
812                        
813              Tcl_CancelIdleCall(TkpDisplayButton, (ClientData)butPtr);              Tcl_CancelIdleCall(TkpDisplayButton, (ClientData)butPtr);
814              return 0;              return 0;
815          }          }
816          case BN_CLICKED: {          case BN_CLICKED: {
817              int code;              int code;
818              Tcl_Interp *interp = butPtr->info.interp;              Tcl_Interp *interp = butPtr->info.interp;
819              if (butPtr->info.state != STATE_DISABLED) {              if (butPtr->info.state != STATE_DISABLED) {
820                  Tcl_Preserve((ClientData)interp);                  Tcl_Preserve((ClientData)interp);
821                  code = TkInvokeButton((TkButton*)butPtr);                  code = TkInvokeButton((TkButton*)butPtr);
822                  if (code != TCL_OK && code != TCL_CONTINUE                  if (code != TCL_OK && code != TCL_CONTINUE
823                          && code != TCL_BREAK) {                          && code != TCL_BREAK) {
824                      Tcl_AddErrorInfo(interp, "\n    (button invoke)");                      Tcl_AddErrorInfo(interp, "\n    (button invoke)");
825                      Tcl_BackgroundError(interp);                      Tcl_BackgroundError(interp);
826                  }                  }
827                  Tcl_Release((ClientData)interp);                  Tcl_Release((ClientData)interp);
828              }              }
829              Tcl_ServiceAll();              Tcl_ServiceAll();
830              return 0;              return 0;
831          }          }
832    
833          default:          default:
834              if (Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) {              if (Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
835                  return result;                  return result;
836              }              }
837      }      }
838      return DefWindowProc(hwnd, message, wParam, lParam);      return DefWindowProc(hwnd, message, wParam, lParam);
839  }  }
840    
841  /* End of tkwinbutton.c */  /* End of tkwinbutton.c */

Legend:
Removed from v.69  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25