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

Diff of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkwinmenu.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   * tkWinMenu.c --   * tkWinMenu.c --
5   *   *
6   *      This module implements the Windows platform-specific features of menus.   *      This module implements the Windows platform-specific features of menus.
7   *   *
8   * Copyright (c) 1996-1998 by Sun Microsystems, Inc.   * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
9   * Copyright (c) 1998-1999 by Scriptics Corporation.   * Copyright (c) 1998-1999 by Scriptics Corporation.
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: tkwinmenu.c,v 1.1.1.1 2001/06/13 05:14:08 dtashley Exp $   * RCS: @(#) $Id: tkwinmenu.c,v 1.1.1.1 2001/06/13 05:14:08 dtashley Exp $
15   */   */
16    
17  #define OEMRESOURCE  #define OEMRESOURCE
18  #include "tkWinInt.h"  #include "tkWinInt.h"
19  #include "tkMenu.h"  #include "tkMenu.h"
20    
21  #include <string.h>  #include <string.h>
22    
23  /*  /*
24   * The class of the window for popup menus.   * The class of the window for popup menus.
25   */   */
26    
27  #define MENU_CLASS_NAME "MenuWindowClass"  #define MENU_CLASS_NAME "MenuWindowClass"
28    
29  /*  /*
30   * Used to align a windows bitmap inside a rectangle   * Used to align a windows bitmap inside a rectangle
31   */   */
32    
33  #define ALIGN_BITMAP_LEFT   0x00000001  #define ALIGN_BITMAP_LEFT   0x00000001
34  #define ALIGN_BITMAP_RIGHT  0x00000002  #define ALIGN_BITMAP_RIGHT  0x00000002
35  #define ALIGN_BITMAP_TOP    0x00000004  #define ALIGN_BITMAP_TOP    0x00000004
36  #define ALIGN_BITMAP_BOTTOM 0x00000008  #define ALIGN_BITMAP_BOTTOM 0x00000008
37    
38  /*  /*
39   * Platform-specific menu flags:   * Platform-specific menu flags:
40   *   *
41   * MENU_SYSTEM_MENU     Non-zero means that the Windows menu handle   * MENU_SYSTEM_MENU     Non-zero means that the Windows menu handle
42   *                      was retrieved with GetSystemMenu and needs   *                      was retrieved with GetSystemMenu and needs
43   *                      to be disposed of specially.   *                      to be disposed of specially.
44   * MENU_RECONFIGURE_PENDING   * MENU_RECONFIGURE_PENDING
45   *                      Non-zero means that an idle handler has   *                      Non-zero means that an idle handler has
46   *                      been set up to reconfigure the Windows menu   *                      been set up to reconfigure the Windows menu
47   *                      handle for this menu.   *                      handle for this menu.
48   */   */
49    
50  #define MENU_SYSTEM_MENU            MENU_PLATFORM_FLAG1  #define MENU_SYSTEM_MENU            MENU_PLATFORM_FLAG1
51  #define MENU_RECONFIGURE_PENDING    MENU_PLATFORM_FLAG2  #define MENU_RECONFIGURE_PENDING    MENU_PLATFORM_FLAG2
52    
53  static int indicatorDimensions[2];  static int indicatorDimensions[2];
54                                  /* The dimensions of the indicator space                                  /* The dimensions of the indicator space
55                                   * in a menu entry. Calculated at init                                   * in a menu entry. Calculated at init
56                                   * time to save time. */                                   * time to save time. */
57    
58  typedef struct ThreadSpecificData {  typedef struct ThreadSpecificData {
59      Tcl_HashTable commandTable;      Tcl_HashTable commandTable;
60                                  /* A map of command ids to menu entries */                                  /* A map of command ids to menu entries */
61      int inPostMenu;             /* We cannot be re-entrant like X Windows. */      int inPostMenu;             /* We cannot be re-entrant like X Windows. */
62      WORD lastCommandID;         /* The last command ID we allocated. */      WORD lastCommandID;         /* The last command ID we allocated. */
63      HWND menuHWND;              /* A window to service popup-menu messages      HWND menuHWND;              /* A window to service popup-menu messages
64                                   * in. */                                   * in. */
65      int oldServiceMode;         /* Used while processing a menu; we need      int oldServiceMode;         /* Used while processing a menu; we need
66                                   * to set the event mode specially when we                                   * to set the event mode specially when we
67                                   * enter the menu processing modal loop                                   * enter the menu processing modal loop
68                                   * and reset it when menus go away. */                                   * and reset it when menus go away. */
69      TkMenu *modalMenuPtr;       /* The menu we are processing inside the modal      TkMenu *modalMenuPtr;       /* The menu we are processing inside the modal
70                                   * loop. We need this to reset all of the                                   * loop. We need this to reset all of the
71                                   * active items when menus go away since                                   * active items when menus go away since
72                                   * Windows does not see fit to give this                                   * Windows does not see fit to give this
73                                   * to us when it sends its WM_MENUSELECT. */                                   * to us when it sends its WM_MENUSELECT. */
74      Tcl_HashTable winMenuTable;      Tcl_HashTable winMenuTable;
75                                  /* Need this to map HMENUs back to menuPtrs */                                  /* Need this to map HMENUs back to menuPtrs */
76  } ThreadSpecificData;  } ThreadSpecificData;
77  static Tcl_ThreadDataKey dataKey;  static Tcl_ThreadDataKey dataKey;
78    
79  /*  /*
80   * The following are default menu value strings.   * The following are default menu value strings.
81   */   */
82    
83  static int defaultBorderWidth;  /* The windows default border width. */  static int defaultBorderWidth;  /* The windows default border width. */
84  static Tcl_DString menuFontDString;  static Tcl_DString menuFontDString;
85                                  /* A buffer to store the default menu font                                  /* A buffer to store the default menu font
86                                   * string. */                                   * string. */
87  TCL_DECLARE_MUTEX(winMenuMutex)  TCL_DECLARE_MUTEX(winMenuMutex)
88    
89  /*  /*
90   * Forward declarations for procedures defined later in this file:   * Forward declarations for procedures defined later in this file:
91   */   */
92    
93  static void             DrawMenuEntryAccelerator _ANSI_ARGS_((  static void             DrawMenuEntryAccelerator _ANSI_ARGS_((
94                              TkMenu *menuPtr, TkMenuEntry *mePtr,                              TkMenu *menuPtr, TkMenuEntry *mePtr,
95                              Drawable d, GC gc, Tk_Font tkfont,                              Drawable d, GC gc, Tk_Font tkfont,
96                              CONST Tk_FontMetrics *fmPtr,                              CONST Tk_FontMetrics *fmPtr,
97                              Tk_3DBorder activeBorder, int x, int y,                              Tk_3DBorder activeBorder, int x, int y,
98                              int width, int height, int drawArrow));                              int width, int height, int drawArrow));
99  static void             DrawMenuEntryBackground _ANSI_ARGS_((  static void             DrawMenuEntryBackground _ANSI_ARGS_((
100                              TkMenu *menuPtr, TkMenuEntry *mePtr,                              TkMenu *menuPtr, TkMenuEntry *mePtr,
101                              Drawable d, Tk_3DBorder activeBorder,                              Drawable d, Tk_3DBorder activeBorder,
102                              Tk_3DBorder bgBorder, int x, int y,                              Tk_3DBorder bgBorder, int x, int y,
103                              int width, int heigth));                              int width, int heigth));
104  static void             DrawMenuEntryIndicator _ANSI_ARGS_((  static void             DrawMenuEntryIndicator _ANSI_ARGS_((
105                              TkMenu *menuPtr, TkMenuEntry *mePtr,                              TkMenu *menuPtr, TkMenuEntry *mePtr,
106                              Drawable d, GC gc, GC indicatorGC,                              Drawable d, GC gc, GC indicatorGC,
107                              Tk_Font tkfont,                              Tk_Font tkfont,
108                              CONST Tk_FontMetrics *fmPtr, int x, int y,                              CONST Tk_FontMetrics *fmPtr, int x, int y,
109                              int width, int height));                              int width, int height));
110  static void             DrawMenuEntryLabel _ANSI_ARGS_((  static void             DrawMenuEntryLabel _ANSI_ARGS_((
111                              TkMenu * menuPtr, TkMenuEntry *mePtr, Drawable d,                              TkMenu * menuPtr, TkMenuEntry *mePtr, Drawable d,
112                              GC gc, Tk_Font tkfont,                              GC gc, Tk_Font tkfont,
113                              CONST Tk_FontMetrics *fmPtr, int x, int y,                              CONST Tk_FontMetrics *fmPtr, int x, int y,
114                              int width, int height));                              int width, int height));
115  static void             DrawMenuSeparator _ANSI_ARGS_((TkMenu *menuPtr,  static void             DrawMenuSeparator _ANSI_ARGS_((TkMenu *menuPtr,
116                              TkMenuEntry *mePtr, Drawable d, GC gc,                              TkMenuEntry *mePtr, Drawable d, GC gc,
117                              Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,                              Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
118                              int x, int y, int width, int height));                              int x, int y, int width, int height));
119  static void             DrawTearoffEntry _ANSI_ARGS_((TkMenu *menuPtr,  static void             DrawTearoffEntry _ANSI_ARGS_((TkMenu *menuPtr,
120                              TkMenuEntry *mePtr, Drawable d, GC gc,                              TkMenuEntry *mePtr, Drawable d, GC gc,
121                              Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,                              Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
122                              int x, int y, int width, int height));                              int x, int y, int width, int height));
123  static void             DrawMenuUnderline _ANSI_ARGS_((TkMenu *menuPtr,  static void             DrawMenuUnderline _ANSI_ARGS_((TkMenu *menuPtr,
124                              TkMenuEntry *mePtr, Drawable d, GC gc,                              TkMenuEntry *mePtr, Drawable d, GC gc,
125                              Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, int x,                              Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, int x,
126                              int y, int width, int height));                              int y, int width, int height));
127  static void             DrawWindowsSystemBitmap _ANSI_ARGS_((  static void             DrawWindowsSystemBitmap _ANSI_ARGS_((
128                              Display *display, Drawable drawable,                              Display *display, Drawable drawable,
129                              GC gc, CONST RECT *rectPtr, int bitmapID,                              GC gc, CONST RECT *rectPtr, int bitmapID,
130                              int alignFlags));                              int alignFlags));
131  static void             FreeID _ANSI_ARGS_((int commandID));  static void             FreeID _ANSI_ARGS_((int commandID));
132  static TCHAR *          GetEntryText _ANSI_ARGS_((TkMenuEntry *mePtr));  static TCHAR *          GetEntryText _ANSI_ARGS_((TkMenuEntry *mePtr));
133  static void             GetMenuAccelGeometry _ANSI_ARGS_((TkMenu *menuPtr,  static void             GetMenuAccelGeometry _ANSI_ARGS_((TkMenu *menuPtr,
134                              TkMenuEntry *mePtr, Tk_Font tkfont,                              TkMenuEntry *mePtr, Tk_Font tkfont,
135                              CONST Tk_FontMetrics *fmPtr, int *widthPtr,                              CONST Tk_FontMetrics *fmPtr, int *widthPtr,
136                              int *heightPtr));                              int *heightPtr));
137  static void             GetMenuLabelGeometry _ANSI_ARGS_((TkMenuEntry *mePtr,  static void             GetMenuLabelGeometry _ANSI_ARGS_((TkMenuEntry *mePtr,
138                              Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,                              Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
139                              int *widthPtr, int *heightPtr));                              int *widthPtr, int *heightPtr));
140  static void             GetMenuIndicatorGeometry _ANSI_ARGS_((  static void             GetMenuIndicatorGeometry _ANSI_ARGS_((
141                              TkMenu *menuPtr, TkMenuEntry *mePtr,                              TkMenu *menuPtr, TkMenuEntry *mePtr,
142                              Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,                              Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
143                              int *widthPtr, int *heightPtr));                              int *widthPtr, int *heightPtr));
144  static void             GetMenuSeparatorGeometry _ANSI_ARGS_((  static void             GetMenuSeparatorGeometry _ANSI_ARGS_((
145                              TkMenu *menuPtr, TkMenuEntry *mePtr,                              TkMenu *menuPtr, TkMenuEntry *mePtr,
146                              Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,                              Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
147                              int *widthPtr, int *heightPtr));                              int *widthPtr, int *heightPtr));
148  static void             GetTearoffEntryGeometry _ANSI_ARGS_((TkMenu *menuPtr,  static void             GetTearoffEntryGeometry _ANSI_ARGS_((TkMenu *menuPtr,
149                              TkMenuEntry *mePtr, Tk_Font tkfont,                              TkMenuEntry *mePtr, Tk_Font tkfont,
150                              CONST Tk_FontMetrics *fmPtr, int *widthPtr,                              CONST Tk_FontMetrics *fmPtr, int *widthPtr,
151                              int *heightPtr));                              int *heightPtr));
152  static int              GetNewID _ANSI_ARGS_((TkMenuEntry *mePtr,  static int              GetNewID _ANSI_ARGS_((TkMenuEntry *mePtr,
153                              int *menuIDPtr));                              int *menuIDPtr));
154  static void             MenuExitProc _ANSI_ARGS_((ClientData clientData));  static void             MenuExitProc _ANSI_ARGS_((ClientData clientData));
155  static int              MenuKeyBindProc _ANSI_ARGS_((  static int              MenuKeyBindProc _ANSI_ARGS_((
156                              ClientData clientData,                              ClientData clientData,
157                              Tcl_Interp *interp, XEvent *eventPtr,                              Tcl_Interp *interp, XEvent *eventPtr,
158                              Tk_Window tkwin, KeySym keySym));                              Tk_Window tkwin, KeySym keySym));
159  static void             MenuSelectEvent _ANSI_ARGS_((TkMenu *menuPtr));  static void             MenuSelectEvent _ANSI_ARGS_((TkMenu *menuPtr));
160  static void             ReconfigureWindowsMenu _ANSI_ARGS_((  static void             ReconfigureWindowsMenu _ANSI_ARGS_((
161                              ClientData clientData));                              ClientData clientData));
162  static void             RecursivelyClearActiveMenu _ANSI_ARGS_((  static void             RecursivelyClearActiveMenu _ANSI_ARGS_((
163                              TkMenu *menuPtr));                              TkMenu *menuPtr));
164  static void             SetDefaults _ANSI_ARGS_((int firstTime));  static void             SetDefaults _ANSI_ARGS_((int firstTime));
165  static LRESULT CALLBACK TkWinMenuProc _ANSI_ARGS_((HWND hwnd,  static LRESULT CALLBACK TkWinMenuProc _ANSI_ARGS_((HWND hwnd,
166                              UINT message, WPARAM wParam,                              UINT message, WPARAM wParam,
167                              LPARAM lParam));                              LPARAM lParam));
168    
169    
170    
171  /*  /*
172   *----------------------------------------------------------------------   *----------------------------------------------------------------------
173   *   *
174   * GetNewID --   * GetNewID --
175   *   *
176   *      Allocates a new menu id and marks it in use.   *      Allocates a new menu id and marks it in use.
177   *   *
178   * Results:   * Results:
179   *      Returns TCL_OK if succesful; TCL_ERROR if there are no more   *      Returns TCL_OK if succesful; TCL_ERROR if there are no more
180   *      ids of the appropriate type to allocate. menuIDPtr contains   *      ids of the appropriate type to allocate. menuIDPtr contains
181   *      the new id if succesful.   *      the new id if succesful.
182   *   *
183   * Side effects:   * Side effects:
184   *      An entry is created for the menu in the command hash table,   *      An entry is created for the menu in the command hash table,
185   *      and the hash entry is stored in the appropriate field in the   *      and the hash entry is stored in the appropriate field in the
186   *      menu data structure.   *      menu data structure.
187   *   *
188   *----------------------------------------------------------------------   *----------------------------------------------------------------------
189   */   */
190    
191  static int  static int
192  GetNewID(mePtr, menuIDPtr)  GetNewID(mePtr, menuIDPtr)
193      TkMenuEntry *mePtr;         /* The menu we are working with */      TkMenuEntry *mePtr;         /* The menu we are working with */
194      int *menuIDPtr;             /* The resulting id */      int *menuIDPtr;             /* The resulting id */
195  {  {
196      int found = 0;      int found = 0;
197      int newEntry;      int newEntry;
198      Tcl_HashEntry *commandEntryPtr;      Tcl_HashEntry *commandEntryPtr;
199      WORD returnID;      WORD returnID;
200      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
201              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
202    
203      WORD curID = tsdPtr->lastCommandID + 1;      WORD curID = tsdPtr->lastCommandID + 1;
204    
205      /*      /*
206       * The following code relies on WORD wrapping when the highest value is       * The following code relies on WORD wrapping when the highest value is
207       * incremented.       * incremented.
208       */       */
209            
210      while (curID != tsdPtr->lastCommandID) {      while (curID != tsdPtr->lastCommandID) {
211          commandEntryPtr = Tcl_CreateHashEntry(&tsdPtr->commandTable,          commandEntryPtr = Tcl_CreateHashEntry(&tsdPtr->commandTable,
212                  (char *) curID, &newEntry);                  (char *) curID, &newEntry);
213          if (newEntry == 1) {          if (newEntry == 1) {
214              found = 1;              found = 1;
215              returnID = curID;              returnID = curID;
216              break;              break;
217          }          }
218          curID++;          curID++;
219      }      }
220    
221      if (found) {      if (found) {
222          Tcl_SetHashValue(commandEntryPtr, (char *) mePtr);          Tcl_SetHashValue(commandEntryPtr, (char *) mePtr);
223          *menuIDPtr = (int) returnID;          *menuIDPtr = (int) returnID;
224          tsdPtr->lastCommandID = returnID;          tsdPtr->lastCommandID = returnID;
225          return TCL_OK;          return TCL_OK;
226      } else {      } else {
227          return TCL_ERROR;          return TCL_ERROR;
228      }      }
229  }  }
230    
231  /*  /*
232   *----------------------------------------------------------------------   *----------------------------------------------------------------------
233   *   *
234   * FreeID --   * FreeID --
235   *   *
236   *      Marks the itemID as free.   *      Marks the itemID as free.
237   *   *
238   * Results:   * Results:
239   *      None.   *      None.
240   *   *
241   * Side effects:   * Side effects:
242   *      The hash table entry for the ID is cleared.   *      The hash table entry for the ID is cleared.
243   *   *
244   *----------------------------------------------------------------------   *----------------------------------------------------------------------
245   */   */
246    
247  static void  static void
248  FreeID(commandID)  FreeID(commandID)
249      int commandID;      int commandID;
250  {  {
251      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
252              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
253    
254      Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,      Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
255              (char *) commandID);              (char *) commandID);
256            
257      if (entryPtr != NULL) {      if (entryPtr != NULL) {
258           Tcl_DeleteHashEntry(entryPtr);           Tcl_DeleteHashEntry(entryPtr);
259      }      }
260  }  }
261    
262  /*  /*
263   *----------------------------------------------------------------------   *----------------------------------------------------------------------
264   *   *
265   * TkpNewMenu --   * TkpNewMenu --
266   *   *
267   *      Gets a new blank menu. Only the platform specific options are filled   *      Gets a new blank menu. Only the platform specific options are filled
268   *      in.   *      in.
269   *   *
270   * Results:   * Results:
271   *      Standard TCL error.   *      Standard TCL error.
272   *   *
273   * Side effects:   * Side effects:
274   *      Allocates a Windows menu handle and places it in the platformData   *      Allocates a Windows menu handle and places it in the platformData
275   *      field of the menuPtr.   *      field of the menuPtr.
276   *   *
277   *----------------------------------------------------------------------   *----------------------------------------------------------------------
278   */   */
279    
280  int  int
281  TkpNewMenu(menuPtr)  TkpNewMenu(menuPtr)
282      TkMenu *menuPtr;    /* The common structure we are making the      TkMenu *menuPtr;    /* The common structure we are making the
283                           * platform structure for. */                           * platform structure for. */
284  {  {
285      HMENU winMenuHdl;      HMENU winMenuHdl;
286      Tcl_HashEntry *hashEntryPtr;      Tcl_HashEntry *hashEntryPtr;
287      int newEntry;      int newEntry;
288      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
289              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
290    
291      winMenuHdl = CreatePopupMenu();      winMenuHdl = CreatePopupMenu();
292            
293      if (winMenuHdl == NULL) {      if (winMenuHdl == NULL) {
294          Tcl_AppendResult(menuPtr->interp, "No more menus can be allocated.",          Tcl_AppendResult(menuPtr->interp, "No more menus can be allocated.",
295                  (char *) NULL);                  (char *) NULL);
296          return TCL_ERROR;          return TCL_ERROR;
297      }      }
298    
299      /*      /*
300       * We hash all of the HMENU's so that we can get their menu ptrs       * We hash all of the HMENU's so that we can get their menu ptrs
301       * back when dispatch messages.       * back when dispatch messages.
302       */       */
303    
304      hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable, (char *) winMenuHdl,      hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable, (char *) winMenuHdl,
305              &newEntry);              &newEntry);
306      Tcl_SetHashValue(hashEntryPtr, (char *) menuPtr);      Tcl_SetHashValue(hashEntryPtr, (char *) menuPtr);
307    
308      menuPtr->platformData = (TkMenuPlatformData) winMenuHdl;      menuPtr->platformData = (TkMenuPlatformData) winMenuHdl;
309      return TCL_OK;      return TCL_OK;
310  }  }
311    
312  /*  /*
313   *----------------------------------------------------------------------   *----------------------------------------------------------------------
314   *   *
315   * TkpDestroyMenu --   * TkpDestroyMenu --
316   *   *
317   *      Destroys platform-specific menu structures.   *      Destroys platform-specific menu structures.
318   *   *
319   * Results:   * Results:
320   *      None.   *      None.
321   *   *
322   * Side effects:   * Side effects:
323   *      All platform-specific allocations are freed up.   *      All platform-specific allocations are freed up.
324   *   *
325   *----------------------------------------------------------------------   *----------------------------------------------------------------------
326   */   */
327    
328  void  void
329  TkpDestroyMenu(menuPtr)  TkpDestroyMenu(menuPtr)
330      TkMenu *menuPtr;        /* The common menu structure */      TkMenu *menuPtr;        /* The common menu structure */
331  {  {
332      HMENU winMenuHdl = (HMENU) menuPtr->platformData;      HMENU winMenuHdl = (HMENU) menuPtr->platformData;
333      char *searchName;      char *searchName;
334      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
335              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
336    
337      if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {      if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
338          Tcl_CancelIdleCall(ReconfigureWindowsMenu, (ClientData) menuPtr);          Tcl_CancelIdleCall(ReconfigureWindowsMenu, (ClientData) menuPtr);
339      }      }
340            
341      if (winMenuHdl == NULL) {      if (winMenuHdl == NULL) {
342          return;          return;
343      }      }
344    
345      if (menuPtr->menuFlags & MENU_SYSTEM_MENU) {      if (menuPtr->menuFlags & MENU_SYSTEM_MENU) {
346          TkMenuEntry *searchEntryPtr;          TkMenuEntry *searchEntryPtr;
347          Tcl_HashTable *tablePtr = TkGetMenuHashTable(menuPtr->interp);          Tcl_HashTable *tablePtr = TkGetMenuHashTable(menuPtr->interp);
348          char *menuName = Tcl_GetHashKey(tablePtr,          char *menuName = Tcl_GetHashKey(tablePtr,
349                  menuPtr->menuRefPtr->hashEntryPtr);                  menuPtr->menuRefPtr->hashEntryPtr);
350    
351          /*          /*
352           * Search for the menu in the menubar, if it is present, get the           * Search for the menu in the menubar, if it is present, get the
353           * wrapper window associated with the toplevel and reset its           * wrapper window associated with the toplevel and reset its
354           * system menu to the default menu.           * system menu to the default menu.
355           */           */
356    
357          for (searchEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;          for (searchEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
358               searchEntryPtr != NULL;               searchEntryPtr != NULL;
359               searchEntryPtr = searchEntryPtr->nextCascadePtr) {               searchEntryPtr = searchEntryPtr->nextCascadePtr) {
360              searchName = Tcl_GetStringFromObj(searchEntryPtr->namePtr, NULL);              searchName = Tcl_GetStringFromObj(searchEntryPtr->namePtr, NULL);
361              if (strcmp(searchName, menuName) == 0) {              if (strcmp(searchName, menuName) == 0) {
362                  Tk_Window parentTopLevelPtr = searchEntryPtr                  Tk_Window parentTopLevelPtr = searchEntryPtr
363                      ->menuPtr->parentTopLevelPtr;                      ->menuPtr->parentTopLevelPtr;
364    
365                  if (parentTopLevelPtr != NULL) {                  if (parentTopLevelPtr != NULL) {
366                      GetSystemMenu(TkWinGetWrapperWindow(parentTopLevelPtr),                      GetSystemMenu(TkWinGetWrapperWindow(parentTopLevelPtr),
367                              TRUE);                              TRUE);
368                  }                  }
369                  break;                  break;
370              }              }
371          }          }
372      } else {      } else {
373          Tcl_HashEntry *hashEntryPtr;          Tcl_HashEntry *hashEntryPtr;
374    
375          /*          /*
376           * Remove the menu from the menu hash table, then destroy the handle.           * Remove the menu from the menu hash table, then destroy the handle.
377           */           */
378    
379          hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,          hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
380                  (char *) winMenuHdl);                  (char *) winMenuHdl);
381          if (hashEntryPtr != NULL) {          if (hashEntryPtr != NULL) {
382              Tcl_DeleteHashEntry(hashEntryPtr);              Tcl_DeleteHashEntry(hashEntryPtr);
383          }          }
384          DestroyMenu(winMenuHdl);          DestroyMenu(winMenuHdl);
385      }      }
386      menuPtr->platformData = NULL;      menuPtr->platformData = NULL;
387    
388      if (menuPtr == tsdPtr->modalMenuPtr) {      if (menuPtr == tsdPtr->modalMenuPtr) {
389          tsdPtr->modalMenuPtr = NULL;          tsdPtr->modalMenuPtr = NULL;
390      }      }
391  }  }
392    
393  /*  /*
394   *----------------------------------------------------------------------   *----------------------------------------------------------------------
395   *   *
396   * TkpDestroyMenuEntry --   * TkpDestroyMenuEntry --
397   *   *
398   *      Cleans up platform-specific menu entry items.   *      Cleans up platform-specific menu entry items.
399   *   *
400   * Results:   * Results:
401   *      None   *      None
402   *   *
403   * Side effects:   * Side effects:
404   *      All platform-specific allocations are freed up.   *      All platform-specific allocations are freed up.
405   *   *
406   *----------------------------------------------------------------------   *----------------------------------------------------------------------
407   */   */
408    
409  void  void
410  TkpDestroyMenuEntry(mePtr)  TkpDestroyMenuEntry(mePtr)
411      TkMenuEntry *mePtr;             /* The entry to destroy */      TkMenuEntry *mePtr;             /* The entry to destroy */
412  {  {
413      TkMenu *menuPtr = mePtr->menuPtr;      TkMenu *menuPtr = mePtr->menuPtr;
414      HMENU winMenuHdl = (HMENU) menuPtr->platformData;      HMENU winMenuHdl = (HMENU) menuPtr->platformData;
415    
416      if (NULL != winMenuHdl) {      if (NULL != winMenuHdl) {
417          if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {          if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
418              menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;              menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
419              Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) menuPtr);              Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) menuPtr);
420          }          }
421      }      }
422      FreeID((int) mePtr->platformEntryData);      FreeID((int) mePtr->platformEntryData);
423      mePtr->platformEntryData = NULL;      mePtr->platformEntryData = NULL;
424  }  }
425    
426  /*  /*
427   *----------------------------------------------------------------------   *----------------------------------------------------------------------
428   *   *
429   * GetEntryText --   * GetEntryText --
430   *   *
431   *      Given a menu entry, gives back the text that should go in it.   *      Given a menu entry, gives back the text that should go in it.
432   *      Separators should be done by the caller, as they have to be   *      Separators should be done by the caller, as they have to be
433   *      handled specially. Allocates the memory with alloc. The caller   *      handled specially. Allocates the memory with alloc. The caller
434   *      should free the memory.   *      should free the memory.
435   *   *
436   * Results:   * Results:
437   *      itemText points to the new text for the item.   *      itemText points to the new text for the item.
438   *   *
439   * Side effects:   * Side effects:
440   *      None.   *      None.
441   *   *
442   *----------------------------------------------------------------------   *----------------------------------------------------------------------
443   */   */
444    
445  static char *  static char *
446  GetEntryText(mePtr)  GetEntryText(mePtr)
447      TkMenuEntry *mePtr;         /* A pointer to the menu entry. */      TkMenuEntry *mePtr;         /* A pointer to the menu entry. */
448  {  {
449      char *itemText;      char *itemText;
450    
451      if (mePtr->type == TEAROFF_ENTRY) {      if (mePtr->type == TEAROFF_ENTRY) {
452          itemText = ckalloc(sizeof("(Tear-off)"));          itemText = ckalloc(sizeof("(Tear-off)"));
453          strcpy(itemText, "(Tear-off)");          strcpy(itemText, "(Tear-off)");
454      } else if (mePtr->imagePtr != NULL) {      } else if (mePtr->imagePtr != NULL) {
455          itemText = ckalloc(sizeof("(Image)"));          itemText = ckalloc(sizeof("(Image)"));
456          strcpy(itemText, "(Image)");          strcpy(itemText, "(Image)");
457      } else if (mePtr->bitmapPtr != NULL) {      } else if (mePtr->bitmapPtr != NULL) {
458          itemText = ckalloc(sizeof("(Pixmap)"));          itemText = ckalloc(sizeof("(Pixmap)"));
459          strcpy(itemText, "(Pixmap)");          strcpy(itemText, "(Pixmap)");
460      } else if (mePtr->labelPtr == NULL || mePtr->labelLength == 0) {      } else if (mePtr->labelPtr == NULL || mePtr->labelLength == 0) {
461          itemText = ckalloc(sizeof("( )"));          itemText = ckalloc(sizeof("( )"));
462          strcpy(itemText, "( )");          strcpy(itemText, "( )");
463      } else {      } else {
464          int i;          int i;
465          char *label = (mePtr->labelPtr == NULL) ? ""          char *label = (mePtr->labelPtr == NULL) ? ""
466                  : Tcl_GetStringFromObj(mePtr->labelPtr, NULL);                  : Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
467          char *accel = (mePtr->accelPtr == NULL) ? ""          char *accel = (mePtr->accelPtr == NULL) ? ""
468                  : Tcl_GetStringFromObj(mePtr->accelPtr, NULL);                  : Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
469          char *p, *next;          char *p, *next;
470          Tcl_DString itemString;          Tcl_DString itemString;
471    
472          /*          /*
473           * We have to construct the string with an ampersand           * We have to construct the string with an ampersand
474           * preceeding the underline character, and a tab seperating           * preceeding the underline character, and a tab seperating
475           * the text and the accel text. We have to be careful with           * the text and the accel text. We have to be careful with
476           * ampersands in the string.           * ampersands in the string.
477           */           */
478    
479          Tcl_DStringInit(&itemString);          Tcl_DStringInit(&itemString);
480    
481          for (p = label, i = 0; *p != '\0'; i++, p = next) {          for (p = label, i = 0; *p != '\0'; i++, p = next) {
482              if (i == mePtr->underline) {              if (i == mePtr->underline) {
483                  Tcl_DStringAppend(&itemString, "&", 1);                  Tcl_DStringAppend(&itemString, "&", 1);
484              }              }
485              if (*p == '&') {              if (*p == '&') {
486                  Tcl_DStringAppend(&itemString, "&", 1);                  Tcl_DStringAppend(&itemString, "&", 1);
487              }              }
488              next = Tcl_UtfNext(p);              next = Tcl_UtfNext(p);
489              Tcl_DStringAppend(&itemString, p, next - p);              Tcl_DStringAppend(&itemString, p, next - p);
490          }          }
491          if (mePtr->accelLength > 0) {          if (mePtr->accelLength > 0) {
492              Tcl_DStringAppend(&itemString, "\t", 1);              Tcl_DStringAppend(&itemString, "\t", 1);
493              for (p = accel, i = 0; *p != '\0'; i++, p = next) {              for (p = accel, i = 0; *p != '\0'; i++, p = next) {
494                  if (*p == '&') {                  if (*p == '&') {
495                      Tcl_DStringAppend(&itemString, "&", 1);                      Tcl_DStringAppend(&itemString, "&", 1);
496                  }                  }
497                  next = Tcl_UtfNext(p);                  next = Tcl_UtfNext(p);
498                  Tcl_DStringAppend(&itemString, p, next - p);                  Tcl_DStringAppend(&itemString, p, next - p);
499              }              }
500          }                    }          
501    
502          itemText = ckalloc(Tcl_DStringLength(&itemString) + 1);          itemText = ckalloc(Tcl_DStringLength(&itemString) + 1);
503          strcpy(itemText, Tcl_DStringValue(&itemString));          strcpy(itemText, Tcl_DStringValue(&itemString));
504          Tcl_DStringFree(&itemString);          Tcl_DStringFree(&itemString);
505      }      }
506      return itemText;      return itemText;
507  }  }
508    
509  /*  /*
510   *----------------------------------------------------------------------   *----------------------------------------------------------------------
511   *   *
512   * ReconfigureWindowsMenu --   * ReconfigureWindowsMenu --
513   *   *
514   *      Tears down and rebuilds the platform-specific part of this menu.   *      Tears down and rebuilds the platform-specific part of this menu.
515   *   *
516   * Results:   * Results:
517   *      None.   *      None.
518   *   *
519   * Side effects:   * Side effects:
520   *      Configuration information get set for mePtr; old resources   *      Configuration information get set for mePtr; old resources
521   *      get freed, if any need it.   *      get freed, if any need it.
522   *   *
523   *----------------------------------------------------------------------   *----------------------------------------------------------------------
524   */   */
525    
526  static void  static void
527  ReconfigureWindowsMenu(  ReconfigureWindowsMenu(
528      ClientData clientData)          /* The menu we are rebuilding */      ClientData clientData)          /* The menu we are rebuilding */
529  {  {
530      TkMenu *menuPtr = (TkMenu *) clientData;      TkMenu *menuPtr = (TkMenu *) clientData;
531      TkMenuEntry *mePtr;      TkMenuEntry *mePtr;
532      HMENU winMenuHdl = (HMENU) menuPtr->platformData;      HMENU winMenuHdl = (HMENU) menuPtr->platformData;
533      TCHAR *itemText = NULL;      TCHAR *itemText = NULL;
534      const TCHAR *lpNewItem;      const TCHAR *lpNewItem;
535      UINT flags;      UINT flags;
536      UINT itemID;      UINT itemID;
537      int i, count, systemMenu = 0, base;      int i, count, systemMenu = 0, base;
538      int width, height;      int width, height;
539      Tcl_DString translatedText;      Tcl_DString translatedText;
540        
541      if (NULL == winMenuHdl) {      if (NULL == winMenuHdl) {
542          return;          return;
543      }      }
544    
545      /*      /*
546       * Reconstruct the entire menu. Takes care of nasty system menu and index       * Reconstruct the entire menu. Takes care of nasty system menu and index
547       * problem.       * problem.
548       *       *
549       */       */
550    
551      if ((menuPtr->menuType == MENUBAR)      if ((menuPtr->menuType == MENUBAR)
552              && (menuPtr->parentTopLevelPtr != NULL)) {              && (menuPtr->parentTopLevelPtr != NULL)) {
553          width = Tk_Width(menuPtr->parentTopLevelPtr);          width = Tk_Width(menuPtr->parentTopLevelPtr);
554          height = Tk_Height(menuPtr->parentTopLevelPtr);          height = Tk_Height(menuPtr->parentTopLevelPtr);
555      }      }
556    
557      base = (menuPtr->menuFlags & MENU_SYSTEM_MENU) ? 7 : 0;      base = (menuPtr->menuFlags & MENU_SYSTEM_MENU) ? 7 : 0;
558      count = GetMenuItemCount(winMenuHdl);      count = GetMenuItemCount(winMenuHdl);
559      for (i = base; i < count; i++) {      for (i = base; i < count; i++) {
560          RemoveMenu(winMenuHdl, base, MF_BYPOSITION);          RemoveMenu(winMenuHdl, base, MF_BYPOSITION);
561      }      }
562    
563      count = menuPtr->numEntries;      count = menuPtr->numEntries;
564      for (i = 0; i < count; i++) {      for (i = 0; i < count; i++) {
565          mePtr = menuPtr->entries[i];          mePtr = menuPtr->entries[i];
566          lpNewItem = NULL;          lpNewItem = NULL;
567          flags = MF_BYPOSITION;          flags = MF_BYPOSITION;
568          itemID = 0;          itemID = 0;
569          Tcl_DStringInit(&translatedText);          Tcl_DStringInit(&translatedText);
570    
571          if ((menuPtr->menuType == MENUBAR) && (mePtr->type == TEAROFF_ENTRY)) {          if ((menuPtr->menuType == MENUBAR) && (mePtr->type == TEAROFF_ENTRY)) {
572              continue;              continue;
573          }          }
574    
575          itemText = GetEntryText(mePtr);          itemText = GetEntryText(mePtr);
576          if ((menuPtr->menuType == MENUBAR)          if ((menuPtr->menuType == MENUBAR)
577                  || (menuPtr->menuFlags & MENU_SYSTEM_MENU)) {                  || (menuPtr->menuFlags & MENU_SYSTEM_MENU)) {
578              Tcl_UtfToExternalDString(NULL, itemText, -1, &translatedText);              Tcl_UtfToExternalDString(NULL, itemText, -1, &translatedText);
579              lpNewItem = Tcl_DStringValue(&translatedText);              lpNewItem = Tcl_DStringValue(&translatedText);
580          } else {          } else {
581              lpNewItem = (LPCTSTR) mePtr;              lpNewItem = (LPCTSTR) mePtr;
582              flags |= MF_OWNERDRAW;              flags |= MF_OWNERDRAW;
583          }          }
584                    
585          /*          /*
586           * Set enabling and disabling correctly.           * Set enabling and disabling correctly.
587           */           */
588                    
589          if (mePtr->state == ENTRY_DISABLED) {          if (mePtr->state == ENTRY_DISABLED) {
590              flags |= MF_DISABLED;              flags |= MF_DISABLED;
591          }          }
592                    
593          /*          /*
594           * Set the check mark for check entries and radio entries.           * Set the check mark for check entries and radio entries.
595           */           */
596                    
597          if (((mePtr->type == CHECK_BUTTON_ENTRY)          if (((mePtr->type == CHECK_BUTTON_ENTRY)
598                  || (mePtr->type == RADIO_BUTTON_ENTRY))                  || (mePtr->type == RADIO_BUTTON_ENTRY))
599                  && (mePtr->entryFlags & ENTRY_SELECTED)) {                  && (mePtr->entryFlags & ENTRY_SELECTED)) {
600              flags |= MF_CHECKED;              flags |= MF_CHECKED;
601          }          }
602                    
603          if (mePtr->columnBreak) {          if (mePtr->columnBreak) {
604              flags |= MF_MENUBREAK;              flags |= MF_MENUBREAK;
605          }          }
606                    
607          itemID = (int) mePtr->platformEntryData;          itemID = (int) mePtr->platformEntryData;
608          if ((mePtr->type == CASCADE_ENTRY)          if ((mePtr->type == CASCADE_ENTRY)
609                  && (mePtr->childMenuRefPtr != NULL)                  && (mePtr->childMenuRefPtr != NULL)
610                  && (mePtr->childMenuRefPtr->menuPtr != NULL)) {                  && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
611              HMENU childMenuHdl = (HMENU) mePtr->childMenuRefPtr->menuPtr              HMENU childMenuHdl = (HMENU) mePtr->childMenuRefPtr->menuPtr
612                  ->platformData;                  ->platformData;
613              if (childMenuHdl != NULL) {              if (childMenuHdl != NULL) {
614                  itemID = (UINT) childMenuHdl;                  itemID = (UINT) childMenuHdl;
615                  flags |= MF_POPUP;                  flags |= MF_POPUP;
616              }              }
617              if ((menuPtr->menuType == MENUBAR)              if ((menuPtr->menuType == MENUBAR)
618                      && !(mePtr->childMenuRefPtr->menuPtr->menuFlags                      && !(mePtr->childMenuRefPtr->menuPtr->menuFlags
619                              & MENU_SYSTEM_MENU)) {                              & MENU_SYSTEM_MENU)) {
620                  Tcl_DString ds;                  Tcl_DString ds;
621                  TkMenuReferences *menuRefPtr;                  TkMenuReferences *menuRefPtr;
622                  TkMenu *systemMenuPtr = mePtr->childMenuRefPtr->menuPtr;                  TkMenu *systemMenuPtr = mePtr->childMenuRefPtr->menuPtr;
623                                    
624                  Tcl_DStringInit(&ds);                  Tcl_DStringInit(&ds);
625                  Tcl_DStringAppend(&ds,                  Tcl_DStringAppend(&ds,
626                          Tk_PathName(menuPtr->masterMenuPtr->tkwin), -1);                          Tk_PathName(menuPtr->masterMenuPtr->tkwin), -1);
627                  Tcl_DStringAppend(&ds, ".system", 7);                  Tcl_DStringAppend(&ds, ".system", 7);
628                                    
629                  menuRefPtr = TkFindMenuReferences(menuPtr->interp,                  menuRefPtr = TkFindMenuReferences(menuPtr->interp,
630                          Tcl_DStringValue(&ds));                          Tcl_DStringValue(&ds));
631                                    
632                  Tcl_DStringFree(&ds);                  Tcl_DStringFree(&ds);
633                                    
634                  if ((menuRefPtr != NULL)                  if ((menuRefPtr != NULL)
635                          && (menuRefPtr->menuPtr != NULL)                          && (menuRefPtr->menuPtr != NULL)
636                          && (menuPtr->parentTopLevelPtr != NULL)                          && (menuPtr->parentTopLevelPtr != NULL)
637                          && (systemMenuPtr->masterMenuPtr                          && (systemMenuPtr->masterMenuPtr
638                                  == menuRefPtr->menuPtr)) {                                  == menuRefPtr->menuPtr)) {
639                      HMENU systemMenuHdl =                      HMENU systemMenuHdl =
640                          (HMENU) systemMenuPtr->platformData;                          (HMENU) systemMenuPtr->platformData;
641                      HWND wrapper = TkWinGetWrapperWindow(menuPtr                      HWND wrapper = TkWinGetWrapperWindow(menuPtr
642                              ->parentTopLevelPtr);                              ->parentTopLevelPtr);
643                      if (wrapper != NULL) {                      if (wrapper != NULL) {
644                          DestroyMenu(systemMenuHdl);                          DestroyMenu(systemMenuHdl);
645                          systemMenuHdl = GetSystemMenu(wrapper, FALSE);                          systemMenuHdl = GetSystemMenu(wrapper, FALSE);
646                          systemMenuPtr->menuFlags |= MENU_SYSTEM_MENU;                          systemMenuPtr->menuFlags |= MENU_SYSTEM_MENU;
647                          systemMenuPtr->platformData =                          systemMenuPtr->platformData =
648                              (TkMenuPlatformData) systemMenuHdl;                              (TkMenuPlatformData) systemMenuHdl;
649                          if (!(systemMenuPtr->menuFlags                          if (!(systemMenuPtr->menuFlags
650                                  & MENU_RECONFIGURE_PENDING)) {                                  & MENU_RECONFIGURE_PENDING)) {
651                              systemMenuPtr->menuFlags                              systemMenuPtr->menuFlags
652                                  |= MENU_RECONFIGURE_PENDING;                                  |= MENU_RECONFIGURE_PENDING;
653                              Tcl_DoWhenIdle(ReconfigureWindowsMenu,                              Tcl_DoWhenIdle(ReconfigureWindowsMenu,
654                                      (ClientData) systemMenuPtr);                                      (ClientData) systemMenuPtr);
655                          }                          }
656                      }                      }
657                  }                  }
658              }              }
659              if (mePtr->childMenuRefPtr->menuPtr->menuFlags              if (mePtr->childMenuRefPtr->menuPtr->menuFlags
660                      & MENU_SYSTEM_MENU) {                      & MENU_SYSTEM_MENU) {
661                  systemMenu++;                  systemMenu++;
662              }              }
663          }          }
664          if (!systemMenu) {          if (!systemMenu) {
665              InsertMenu(winMenuHdl, 0xFFFFFFFF, flags, itemID, lpNewItem);              InsertMenu(winMenuHdl, 0xFFFFFFFF, flags, itemID, lpNewItem);
666          }          }
667          Tcl_DStringFree(&translatedText);          Tcl_DStringFree(&translatedText);
668          if (itemText != NULL) {          if (itemText != NULL) {
669              ckfree(itemText);              ckfree(itemText);
670              itemText = NULL;              itemText = NULL;
671          }          }
672      }      }
673    
674    
675      if ((menuPtr->menuType == MENUBAR)      if ((menuPtr->menuType == MENUBAR)
676              && (menuPtr->parentTopLevelPtr != NULL)) {              && (menuPtr->parentTopLevelPtr != NULL)) {
677          DrawMenuBar(TkWinGetWrapperWindow(menuPtr->parentTopLevelPtr));          DrawMenuBar(TkWinGetWrapperWindow(menuPtr->parentTopLevelPtr));
678          Tk_GeometryRequest(menuPtr->parentTopLevelPtr, width, height);          Tk_GeometryRequest(menuPtr->parentTopLevelPtr, width, height);
679      }      }
680            
681      menuPtr->menuFlags &= ~(MENU_RECONFIGURE_PENDING);      menuPtr->menuFlags &= ~(MENU_RECONFIGURE_PENDING);
682  }  }
683    
684  /*  /*
685   *----------------------------------------------------------------------   *----------------------------------------------------------------------
686   *   *
687   * TkpPostMenu --   * TkpPostMenu --
688   *   *
689   *      Posts a menu on the screen   *      Posts a menu on the screen
690   *   *
691   * Results:   * Results:
692   *      None.   *      None.
693   *   *
694   * Side effects:   * Side effects:
695   *      The menu is posted and handled.   *      The menu is posted and handled.
696   *   *
697   *----------------------------------------------------------------------   *----------------------------------------------------------------------
698   */   */
699    
700  int  int
701  TkpPostMenu(interp, menuPtr, x, y)  TkpPostMenu(interp, menuPtr, x, y)
702      Tcl_Interp *interp;      Tcl_Interp *interp;
703      TkMenu *menuPtr;      TkMenu *menuPtr;
704      int x;      int x;
705      int y;      int y;
706  {  {
707      HMENU winMenuHdl = (HMENU) menuPtr->platformData;      HMENU winMenuHdl = (HMENU) menuPtr->platformData;
708      int result, flags;      int result, flags;
709      RECT noGoawayRect;      RECT noGoawayRect;
710      POINT point;      POINT point;
711      Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin);      Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin);
712      int oldServiceMode = Tcl_GetServiceMode();      int oldServiceMode = Tcl_GetServiceMode();
713      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
714              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
715    
716      tsdPtr->inPostMenu++;      tsdPtr->inPostMenu++;
717    
718      if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {      if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
719          Tcl_CancelIdleCall(ReconfigureWindowsMenu, (ClientData) menuPtr);          Tcl_CancelIdleCall(ReconfigureWindowsMenu, (ClientData) menuPtr);
720          ReconfigureWindowsMenu((ClientData) menuPtr);          ReconfigureWindowsMenu((ClientData) menuPtr);
721      }      }
722    
723      result = TkPreprocessMenu(menuPtr);      result = TkPreprocessMenu(menuPtr);
724      if (result != TCL_OK) {      if (result != TCL_OK) {
725          tsdPtr->inPostMenu--;          tsdPtr->inPostMenu--;
726          return result;          return result;
727      }      }
728    
729      /*      /*
730       * The post commands could have deleted the menu, which means       * The post commands could have deleted the menu, which means
731       * we are dead and should go away.       * we are dead and should go away.
732       */       */
733            
734      if (menuPtr->tkwin == NULL) {      if (menuPtr->tkwin == NULL) {
735          tsdPtr->inPostMenu--;          tsdPtr->inPostMenu--;
736          return TCL_OK;          return TCL_OK;
737      }      }
738    
739      if (NULL == parentWindow) {      if (NULL == parentWindow) {
740          noGoawayRect.top = y - 50;          noGoawayRect.top = y - 50;
741          noGoawayRect.bottom = y + 50;          noGoawayRect.bottom = y + 50;
742          noGoawayRect.left = x - 50;          noGoawayRect.left = x - 50;
743          noGoawayRect.right = x + 50;          noGoawayRect.right = x + 50;
744      } else {      } else {
745          int left, top;          int left, top;
746          Tk_GetRootCoords(parentWindow, &left, &top);          Tk_GetRootCoords(parentWindow, &left, &top);
747          noGoawayRect.left = left;          noGoawayRect.left = left;
748          noGoawayRect.top = top;          noGoawayRect.top = top;
749          noGoawayRect.bottom = noGoawayRect.top + Tk_Height(parentWindow);          noGoawayRect.bottom = noGoawayRect.top + Tk_Height(parentWindow);
750          noGoawayRect.right = noGoawayRect.left + Tk_Width(parentWindow);          noGoawayRect.right = noGoawayRect.left + Tk_Width(parentWindow);
751      }      }
752    
753      Tcl_SetServiceMode(TCL_SERVICE_NONE);      Tcl_SetServiceMode(TCL_SERVICE_NONE);
754            
755      /*      /*
756       * Make an assumption here. If the right button is down,       * Make an assumption here. If the right button is down,
757       * then we want to track it. Otherwise, track the left mouse button.       * then we want to track it. Otherwise, track the left mouse button.
758       */       */
759    
760      flags = TPM_LEFTALIGN;      flags = TPM_LEFTALIGN;
761      if (GetSystemMetrics(SM_SWAPBUTTON)) {      if (GetSystemMetrics(SM_SWAPBUTTON)) {
762          if (GetAsyncKeyState(VK_LBUTTON) < 0) {          if (GetAsyncKeyState(VK_LBUTTON) < 0) {
763              flags |= TPM_RIGHTBUTTON;              flags |= TPM_RIGHTBUTTON;
764          } else {          } else {
765              flags |= TPM_LEFTBUTTON;              flags |= TPM_LEFTBUTTON;
766          }          }
767      } else {      } else {
768          if (GetAsyncKeyState(VK_RBUTTON) < 0) {          if (GetAsyncKeyState(VK_RBUTTON) < 0) {
769              flags |= TPM_RIGHTBUTTON;              flags |= TPM_RIGHTBUTTON;
770          } else {          } else {
771              flags |= TPM_LEFTBUTTON;              flags |= TPM_LEFTBUTTON;
772          }          }
773      }      }
774    
775      TrackPopupMenu(winMenuHdl, flags, x, y, 0,      TrackPopupMenu(winMenuHdl, flags, x, y, 0,
776              tsdPtr->menuHWND, &noGoawayRect);              tsdPtr->menuHWND, &noGoawayRect);
777      Tcl_SetServiceMode(oldServiceMode);      Tcl_SetServiceMode(oldServiceMode);
778    
779      GetCursorPos(&point);      GetCursorPos(&point);
780      Tk_PointerEvent(NULL, point.x, point.y);      Tk_PointerEvent(NULL, point.x, point.y);
781    
782      if (tsdPtr->inPostMenu) {      if (tsdPtr->inPostMenu) {
783          tsdPtr->inPostMenu = 0;          tsdPtr->inPostMenu = 0;
784      }      }
785      return TCL_OK;      return TCL_OK;
786  }  }
787    
788  /*  /*
789   *----------------------------------------------------------------------   *----------------------------------------------------------------------
790   *   *
791   * TkpMenuNewEntry --   * TkpMenuNewEntry --
792   *   *
793   *      Adds a pointer to a new menu entry structure with the platform-   *      Adds a pointer to a new menu entry structure with the platform-
794   *      specific fields filled in.   *      specific fields filled in.
795   *   *
796   * Results:   * Results:
797   *      Standard TCL error.   *      Standard TCL error.
798   *   *
799   * Side effects:   * Side effects:
800   *      A new command ID is allocated and stored in the platformEntryData   *      A new command ID is allocated and stored in the platformEntryData
801   *      field of mePtr.   *      field of mePtr.
802   *   *
803   *----------------------------------------------------------------------   *----------------------------------------------------------------------
804   */   */
805    
806  int  int
807  TkpMenuNewEntry(mePtr)  TkpMenuNewEntry(mePtr)
808      TkMenuEntry *mePtr;      TkMenuEntry *mePtr;
809  {  {
810      int commandID;      int commandID;
811      TkMenu *menuPtr = mePtr->menuPtr;      TkMenu *menuPtr = mePtr->menuPtr;
812    
813      if (GetNewID(mePtr, &commandID) != TCL_OK) {      if (GetNewID(mePtr, &commandID) != TCL_OK) {
814          return TCL_ERROR;          return TCL_ERROR;
815      }      }
816    
817      if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {      if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
818          menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;          menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
819          Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) menuPtr);          Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) menuPtr);
820      }      }
821            
822      mePtr->platformEntryData = (TkMenuPlatformEntryData) commandID;      mePtr->platformEntryData = (TkMenuPlatformEntryData) commandID;
823    
824      return TCL_OK;      return TCL_OK;
825  }  }
826    
827  /*  /*
828   *----------------------------------------------------------------------   *----------------------------------------------------------------------
829   *   *
830   * TkWinMenuProc --   * TkWinMenuProc --
831   *   *
832   *      The window proc for the dummy window we put popups in. This allows   *      The window proc for the dummy window we put popups in. This allows
833   *      is to post a popup whether or not we know what the parent window   *      is to post a popup whether or not we know what the parent window
834   *      is.   *      is.
835   *   *
836   * Results:   * Results:
837   *      Returns whatever is appropriate for the message in question.   *      Returns whatever is appropriate for the message in question.
838   *   *
839   * Side effects:   * Side effects:
840   *      Normal side-effect for windows messages.   *      Normal side-effect for windows messages.
841   *   *
842   *----------------------------------------------------------------------   *----------------------------------------------------------------------
843   */   */
844    
845  static LRESULT CALLBACK  static LRESULT CALLBACK
846  TkWinMenuProc(hwnd, message, wParam, lParam)  TkWinMenuProc(hwnd, message, wParam, lParam)
847      HWND hwnd;      HWND hwnd;
848      UINT message;      UINT message;
849      WPARAM wParam;      WPARAM wParam;
850      LPARAM lParam;      LPARAM lParam;
851  {  {
852      LRESULT lResult;      LRESULT lResult;
853    
854      if (!TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam, &lResult)) {      if (!TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam, &lResult)) {
855          lResult = DefWindowProc(hwnd, message, wParam, lParam);          lResult = DefWindowProc(hwnd, message, wParam, lParam);
856      }      }
857      return lResult;      return lResult;
858  }  }
859    
860  /*  /*
861   *----------------------------------------------------------------------   *----------------------------------------------------------------------
862   *   *
863   * TkWinHandleMenuEvent --   * TkWinHandleMenuEvent --
864   *   *
865   *      Filters out menu messages from messages passed to a top-level.   *      Filters out menu messages from messages passed to a top-level.
866   *      Will respond appropriately to WM_COMMAND, WM_MENUSELECT,   *      Will respond appropriately to WM_COMMAND, WM_MENUSELECT,
867   *      WM_MEASUREITEM, WM_DRAWITEM   *      WM_MEASUREITEM, WM_DRAWITEM
868   *   *
869   * Result:   * Result:
870   *      Returns 1 if this handled the message; 0 if it did not.   *      Returns 1 if this handled the message; 0 if it did not.
871   *   *
872   * Side effects:   * Side effects:
873   *      All of the parameters may be modified so that the caller can   *      All of the parameters may be modified so that the caller can
874   *      think it is getting a different message. plResult points to   *      think it is getting a different message. plResult points to
875   *      the result that should be returned to windows from this message.   *      the result that should be returned to windows from this message.
876   *   *
877   *----------------------------------------------------------------------   *----------------------------------------------------------------------
878   */   */
879    
880  int  int
881  TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)  TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
882      HWND *phwnd;      HWND *phwnd;
883      UINT *pMessage;      UINT *pMessage;
884      WPARAM *pwParam;      WPARAM *pwParam;
885      LPARAM *plParam;      LPARAM *plParam;
886      LRESULT *plResult;      LRESULT *plResult;
887  {  {
888      Tcl_HashEntry *hashEntryPtr;      Tcl_HashEntry *hashEntryPtr;
889      int returnResult = 0;      int returnResult = 0;
890      TkMenu *menuPtr;      TkMenu *menuPtr;
891      TkMenuEntry *mePtr;      TkMenuEntry *mePtr;
892      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
893              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
894    
895      switch (*pMessage) {      switch (*pMessage) {
896          case WM_INITMENU:          case WM_INITMENU:
897              TkMenuInit();              TkMenuInit();
898              hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,              hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
899                      (char *) *pwParam);                      (char *) *pwParam);
900              if (hashEntryPtr != NULL) {              if (hashEntryPtr != NULL) {
901                  tsdPtr->oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);                  tsdPtr->oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
902                  menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);                  menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
903                  tsdPtr->modalMenuPtr = menuPtr;                  tsdPtr->modalMenuPtr = menuPtr;
904                  if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {                  if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
905                      Tcl_CancelIdleCall(ReconfigureWindowsMenu,                      Tcl_CancelIdleCall(ReconfigureWindowsMenu,
906                              (ClientData) menuPtr);                              (ClientData) menuPtr);
907                      ReconfigureWindowsMenu((ClientData) menuPtr);                      ReconfigureWindowsMenu((ClientData) menuPtr);
908                  }                  }
909                  if (!tsdPtr->inPostMenu) {                  if (!tsdPtr->inPostMenu) {
910                      Tcl_Interp *interp;                      Tcl_Interp *interp;
911                      int code;                      int code;
912    
913                      interp = menuPtr->interp;                      interp = menuPtr->interp;
914                      Tcl_Preserve((ClientData)interp);                      Tcl_Preserve((ClientData)interp);
915                      code = TkPreprocessMenu(menuPtr);                      code = TkPreprocessMenu(menuPtr);
916                      if ((code != TCL_OK) && (code != TCL_CONTINUE)                      if ((code != TCL_OK) && (code != TCL_CONTINUE)
917                              && (code != TCL_BREAK)) {                              && (code != TCL_BREAK)) {
918                          Tcl_AddErrorInfo(interp, "\n    (menu preprocess)");                          Tcl_AddErrorInfo(interp, "\n    (menu preprocess)");
919                          Tcl_BackgroundError(interp);                          Tcl_BackgroundError(interp);
920                      }                      }
921                      Tcl_Release((ClientData)interp);                      Tcl_Release((ClientData)interp);
922                  }                  }
923                  TkActivateMenuEntry(menuPtr, -1);                  TkActivateMenuEntry(menuPtr, -1);
924                  *plResult = 0;                  *plResult = 0;
925                  returnResult = 1;                  returnResult = 1;
926              } else {              } else {
927                  tsdPtr->modalMenuPtr = NULL;                  tsdPtr->modalMenuPtr = NULL;
928              }              }
929              break;              break;
930    
931          case WM_SYSCOMMAND:          case WM_SYSCOMMAND:
932          case WM_COMMAND: {          case WM_COMMAND: {
933              TkMenuInit();              TkMenuInit();
934              if (HIWORD(*pwParam) != 0) {              if (HIWORD(*pwParam) != 0) {
935                  break;                  break;
936              }              }
937              hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,              hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
938                      (char *)LOWORD(*pwParam));                      (char *)LOWORD(*pwParam));
939              if (hashEntryPtr == NULL) {              if (hashEntryPtr == NULL) {
940                  break;                  break;
941              }              }
942              mePtr = (TkMenuEntry *) Tcl_GetHashValue(hashEntryPtr);              mePtr = (TkMenuEntry *) Tcl_GetHashValue(hashEntryPtr);
943              if (mePtr != NULL) {              if (mePtr != NULL) {
944                  TkMenuReferences *menuRefPtr;                  TkMenuReferences *menuRefPtr;
945                  TkMenuEntry *parentEntryPtr;                  TkMenuEntry *parentEntryPtr;
946                  Tcl_Interp *interp;                  Tcl_Interp *interp;
947                  int code;                  int code;
948    
949                  /*                  /*
950                   * We have to set the parent of this menu to be active                   * We have to set the parent of this menu to be active
951                   * if this is a submenu so that tearoffs will get the                   * if this is a submenu so that tearoffs will get the
952                   * correct title.                   * correct title.
953                   */                   */
954    
955                  menuPtr = mePtr->menuPtr;                  menuPtr = mePtr->menuPtr;
956                  menuRefPtr = TkFindMenuReferences(menuPtr->interp,                  menuRefPtr = TkFindMenuReferences(menuPtr->interp,
957                          Tk_PathName(menuPtr->tkwin));                          Tk_PathName(menuPtr->tkwin));
958                  if ((menuRefPtr != NULL)                  if ((menuRefPtr != NULL)
959                          && (menuRefPtr->parentEntryPtr != NULL)) {                          && (menuRefPtr->parentEntryPtr != NULL)) {
960                      char *name;                      char *name;
961    
962                      for (parentEntryPtr = menuRefPtr->parentEntryPtr;                      for (parentEntryPtr = menuRefPtr->parentEntryPtr;
963                           ;                           ;
964                           parentEntryPtr =                           parentEntryPtr =
965                               parentEntryPtr->nextCascadePtr) {                               parentEntryPtr->nextCascadePtr) {
966                          name = Tcl_GetStringFromObj(                          name = Tcl_GetStringFromObj(
967                              parentEntryPtr->namePtr, NULL);                              parentEntryPtr->namePtr, NULL);
968                          if (strcmp(name, Tk_PathName(menuPtr->tkwin))                          if (strcmp(name, Tk_PathName(menuPtr->tkwin))
969                                  == 0) {                                  == 0) {
970                              break;                              break;
971                          }                          }
972                      }                      }
973                      if (parentEntryPtr->menuPtr->entries[parentEntryPtr->index]                      if (parentEntryPtr->menuPtr->entries[parentEntryPtr->index]
974                              ->state != ENTRY_DISABLED) {                              ->state != ENTRY_DISABLED) {
975                          TkActivateMenuEntry(parentEntryPtr->menuPtr,                          TkActivateMenuEntry(parentEntryPtr->menuPtr,
976                                  parentEntryPtr->index);                                  parentEntryPtr->index);
977                      }                      }
978                  }                  }
979    
980                  interp = menuPtr->interp;                  interp = menuPtr->interp;
981                  Tcl_Preserve((ClientData)interp);                  Tcl_Preserve((ClientData)interp);
982                  code = TkInvokeMenu(interp, menuPtr, mePtr->index);                  code = TkInvokeMenu(interp, menuPtr, mePtr->index);
983                  if (code != TCL_OK && code != TCL_CONTINUE                  if (code != TCL_OK && code != TCL_CONTINUE
984                          && code != TCL_BREAK) {                          && code != TCL_BREAK) {
985                      Tcl_AddErrorInfo(interp, "\n    (menu invoke)");                      Tcl_AddErrorInfo(interp, "\n    (menu invoke)");
986                      Tcl_BackgroundError(interp);                      Tcl_BackgroundError(interp);
987                  }                  }
988                  Tcl_Release((ClientData)interp);                  Tcl_Release((ClientData)interp);
989              }              }
990              *plResult = 0;              *plResult = 0;
991              returnResult = 1;              returnResult = 1;
992              break;              break;
993          }          }
994    
995    
996          case WM_MENUCHAR: {          case WM_MENUCHAR: {
997              unsigned char menuChar = (unsigned char) LOWORD(*pwParam);              unsigned char menuChar = (unsigned char) LOWORD(*pwParam);
998              hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,              hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
999                      (char *) *plParam);                      (char *) *plParam);
1000              if (hashEntryPtr != NULL) {              if (hashEntryPtr != NULL) {
1001                  int i;                  int i;
1002    
1003                  *plResult = 0;                  *plResult = 0;
1004                  menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);                  menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
1005                  for (i = 0; i < menuPtr->numEntries; i++) {                  for (i = 0; i < menuPtr->numEntries; i++) {
1006                      int underline;                      int underline;
1007                      char *label;                      char *label;
1008    
1009                      underline = menuPtr->entries[i]->underline;                      underline = menuPtr->entries[i]->underline;
1010                      if (menuPtr->entries[i]->labelPtr != NULL) {                      if (menuPtr->entries[i]->labelPtr != NULL) {
1011                          label = Tcl_GetStringFromObj(                          label = Tcl_GetStringFromObj(
1012                                  menuPtr->entries[i]->labelPtr, NULL);                                  menuPtr->entries[i]->labelPtr, NULL);
1013                      }                      }
1014                      if ((-1 != underline)                      if ((-1 != underline)
1015                              && (NULL != menuPtr->entries[i]->labelPtr)                              && (NULL != menuPtr->entries[i]->labelPtr)
1016                              && (CharUpper((LPTSTR) menuChar)                              && (CharUpper((LPTSTR) menuChar)
1017                              == CharUpper((LPTSTR) (unsigned char)                              == CharUpper((LPTSTR) (unsigned char)
1018                              label[underline]))) {                              label[underline]))) {
1019                          *plResult = (2 << 16) | i;                          *plResult = (2 << 16) | i;
1020                          returnResult = 1;                          returnResult = 1;
1021                          break;                          break;
1022                      }                      }
1023                  }                  }
1024              }              }
1025              break;              break;
1026          }          }
1027    
1028          case WM_MEASUREITEM: {          case WM_MEASUREITEM: {
1029              LPMEASUREITEMSTRUCT itemPtr = (LPMEASUREITEMSTRUCT) *plParam;              LPMEASUREITEMSTRUCT itemPtr = (LPMEASUREITEMSTRUCT) *plParam;
1030            
1031              if (itemPtr != NULL) {              if (itemPtr != NULL) {
1032                  mePtr = (TkMenuEntry *) itemPtr->itemData;                  mePtr = (TkMenuEntry *) itemPtr->itemData;
1033                  menuPtr = mePtr->menuPtr;                  menuPtr = mePtr->menuPtr;
1034    
1035                  TkRecomputeMenu(menuPtr);                  TkRecomputeMenu(menuPtr);
1036                  itemPtr->itemHeight = mePtr->height;                  itemPtr->itemHeight = mePtr->height;
1037                  itemPtr->itemWidth = mePtr->width;                  itemPtr->itemWidth = mePtr->width;
1038                  if (mePtr->hideMargin) {                  if (mePtr->hideMargin) {
1039                      itemPtr->itemWidth += 2 - indicatorDimensions[1];                      itemPtr->itemWidth += 2 - indicatorDimensions[1];
1040                  } else {                  } else {
1041                      int activeBorderWidth;                      int activeBorderWidth;
1042                                            
1043                      Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,                      Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
1044                              menuPtr->activeBorderWidthPtr,                              menuPtr->activeBorderWidthPtr,
1045                              &activeBorderWidth);                              &activeBorderWidth);
1046                      itemPtr->itemWidth += 2 * activeBorderWidth;                      itemPtr->itemWidth += 2 * activeBorderWidth;
1047                  }                  }
1048                  *plResult = 1;                  *plResult = 1;
1049                  returnResult = 1;                  returnResult = 1;
1050              }              }
1051              break;              break;
1052          }          }
1053                    
1054          case WM_DRAWITEM: {          case WM_DRAWITEM: {
1055              TkWinDrawable *twdPtr;              TkWinDrawable *twdPtr;
1056              LPDRAWITEMSTRUCT itemPtr = (LPDRAWITEMSTRUCT) *plParam;              LPDRAWITEMSTRUCT itemPtr = (LPDRAWITEMSTRUCT) *plParam;
1057              Tk_FontMetrics fontMetrics;              Tk_FontMetrics fontMetrics;
1058    
1059              if (itemPtr != NULL) {              if (itemPtr != NULL) {
1060                  Tk_Font tkfont;                  Tk_Font tkfont;
1061    
1062                  mePtr = (TkMenuEntry *) itemPtr->itemData;                  mePtr = (TkMenuEntry *) itemPtr->itemData;
1063                  menuPtr = mePtr->menuPtr;                  menuPtr = mePtr->menuPtr;
1064                  twdPtr = (TkWinDrawable *) ckalloc(sizeof(TkWinDrawable));                  twdPtr = (TkWinDrawable *) ckalloc(sizeof(TkWinDrawable));
1065                  twdPtr->type = TWD_WINDC;                  twdPtr->type = TWD_WINDC;
1066                  twdPtr->winDC.hdc = itemPtr->hDC;                  twdPtr->winDC.hdc = itemPtr->hDC;
1067    
1068                  if (mePtr->state != ENTRY_DISABLED) {                  if (mePtr->state != ENTRY_DISABLED) {
1069                      if (itemPtr->itemState & ODS_SELECTED) {                      if (itemPtr->itemState & ODS_SELECTED) {
1070                          TkActivateMenuEntry(menuPtr, mePtr->index);                          TkActivateMenuEntry(menuPtr, mePtr->index);
1071                      } else {                      } else {
1072                          TkActivateMenuEntry(menuPtr, -1);                          TkActivateMenuEntry(menuPtr, -1);
1073                      }                      }
1074                  }                  }
1075    
1076                  tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);                  tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
1077                  Tk_GetFontMetrics(tkfont, &fontMetrics);                  Tk_GetFontMetrics(tkfont, &fontMetrics);
1078                  TkpDrawMenuEntry(mePtr, (Drawable) twdPtr, tkfont,                  TkpDrawMenuEntry(mePtr, (Drawable) twdPtr, tkfont,
1079                          &fontMetrics, itemPtr->rcItem.left,                          &fontMetrics, itemPtr->rcItem.left,
1080                          itemPtr->rcItem.top, itemPtr->rcItem.right                          itemPtr->rcItem.top, itemPtr->rcItem.right
1081                          - itemPtr->rcItem.left, itemPtr->rcItem.bottom                          - itemPtr->rcItem.left, itemPtr->rcItem.bottom
1082                          - itemPtr->rcItem.top, 0, 0);                          - itemPtr->rcItem.top, 0, 0);
1083    
1084                  ckfree((char *) twdPtr);                  ckfree((char *) twdPtr);
1085                  *plResult = 1;                  *plResult = 1;
1086                  returnResult = 1;                  returnResult = 1;
1087              }              }
1088              break;              break;
1089          }          }
1090    
1091          case WM_MENUSELECT: {          case WM_MENUSELECT: {
1092              UINT flags = HIWORD(*pwParam);              UINT flags = HIWORD(*pwParam);
1093    
1094              TkMenuInit();              TkMenuInit();
1095    
1096              if ((flags == 0xFFFF) && (*plParam == 0)) {              if ((flags == 0xFFFF) && (*plParam == 0)) {
1097                  Tcl_SetServiceMode(tsdPtr->oldServiceMode);                  Tcl_SetServiceMode(tsdPtr->oldServiceMode);
1098                  if (tsdPtr->modalMenuPtr != NULL) {                  if (tsdPtr->modalMenuPtr != NULL) {
1099                      RecursivelyClearActiveMenu(tsdPtr->modalMenuPtr);                      RecursivelyClearActiveMenu(tsdPtr->modalMenuPtr);
1100                  }                  }
1101              } else {              } else {
1102                  menuPtr = NULL;                  menuPtr = NULL;
1103                  if (*plParam != 0) {                  if (*plParam != 0) {
1104                      hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,                      hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
1105                              (char *) *plParam);                              (char *) *plParam);
1106                      if (hashEntryPtr != NULL) {                      if (hashEntryPtr != NULL) {
1107                          menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);                          menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
1108                      }                      }
1109                  }                  }
1110    
1111                  if (menuPtr != NULL) {                  if (menuPtr != NULL) {
1112                      mePtr = NULL;                      mePtr = NULL;
1113                      if (flags != 0xFFFF) {                      if (flags != 0xFFFF) {
1114                          if (flags & MF_POPUP) {                          if (flags & MF_POPUP) {
1115                              mePtr = menuPtr->entries[LOWORD(*pwParam)];                              mePtr = menuPtr->entries[LOWORD(*pwParam)];
1116                          } else {                          } else {
1117                              hashEntryPtr = Tcl_FindHashEntry(                              hashEntryPtr = Tcl_FindHashEntry(
1118                                      &tsdPtr->commandTable,                                      &tsdPtr->commandTable,
1119                                      (char *) LOWORD(*pwParam));                                      (char *) LOWORD(*pwParam));
1120                              if (hashEntryPtr != NULL) {                              if (hashEntryPtr != NULL) {
1121                                  mePtr = (TkMenuEntry *)                                  mePtr = (TkMenuEntry *)
1122                                          Tcl_GetHashValue(hashEntryPtr);                                          Tcl_GetHashValue(hashEntryPtr);
1123                              }                              }
1124                          }                          }
1125                      }                          }    
1126    
1127                      if ((mePtr == NULL) || (mePtr->state == ENTRY_DISABLED)) {                      if ((mePtr == NULL) || (mePtr->state == ENTRY_DISABLED)) {
1128                          TkActivateMenuEntry(menuPtr, -1);                          TkActivateMenuEntry(menuPtr, -1);
1129                      } else {                      } else {
1130                          TkActivateMenuEntry(menuPtr, mePtr->index);                          TkActivateMenuEntry(menuPtr, mePtr->index);
1131                      }                      }
1132                      MenuSelectEvent(menuPtr);                      MenuSelectEvent(menuPtr);
1133                      Tcl_ServiceAll();                      Tcl_ServiceAll();
1134                  }                  }
1135              }              }
1136          }          }
1137      }      }
1138      return returnResult;      return returnResult;
1139  }  }
1140    
1141  /*  /*
1142   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1143   *   *
1144   * RecursivelyClearActiveMenu --   * RecursivelyClearActiveMenu --
1145   *   *
1146   *      Recursively clears the active entry in the menu's cascade hierarchy.   *      Recursively clears the active entry in the menu's cascade hierarchy.
1147   *   *
1148   * Results:   * Results:
1149   *      None.   *      None.
1150   *   *
1151   * Side effects:   * Side effects:
1152   *      Generates <<MenuSelect>> virtual events.   *      Generates <<MenuSelect>> virtual events.
1153   *   *
1154   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1155   */   */
1156    
1157  void  void
1158  RecursivelyClearActiveMenu(  RecursivelyClearActiveMenu(
1159      TkMenu *menuPtr)            /* The menu to reset. */      TkMenu *menuPtr)            /* The menu to reset. */
1160  {  {
1161      int i;      int i;
1162      TkMenuEntry *mePtr;      TkMenuEntry *mePtr;
1163            
1164      TkActivateMenuEntry(menuPtr, -1);      TkActivateMenuEntry(menuPtr, -1);
1165      MenuSelectEvent(menuPtr);      MenuSelectEvent(menuPtr);
1166      for (i = 0; i < menuPtr->numEntries; i++) {      for (i = 0; i < menuPtr->numEntries; i++) {
1167          mePtr = menuPtr->entries[i];          mePtr = menuPtr->entries[i];
1168          if (mePtr->type == CASCADE_ENTRY) {          if (mePtr->type == CASCADE_ENTRY) {
1169              if ((mePtr->childMenuRefPtr != NULL)              if ((mePtr->childMenuRefPtr != NULL)
1170                      && (mePtr->childMenuRefPtr->menuPtr != NULL)) {                      && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
1171                  RecursivelyClearActiveMenu(mePtr->childMenuRefPtr->menuPtr);                  RecursivelyClearActiveMenu(mePtr->childMenuRefPtr->menuPtr);
1172              }              }
1173          }          }
1174      }      }
1175  }  }
1176    
1177  /*  /*
1178   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1179   *   *
1180   * TkpSetWindowMenuBar --   * TkpSetWindowMenuBar --
1181   *   *
1182   *      Associates a given menu with a window.   *      Associates a given menu with a window.
1183   *   *
1184   * Results:   * Results:
1185   *      None.   *      None.
1186   *   *
1187   * Side effects:   * Side effects:
1188   *      On Windows and UNIX, associates the platform menu with the   *      On Windows and UNIX, associates the platform menu with the
1189   *      platform window.   *      platform window.
1190   *   *
1191   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1192   */   */
1193    
1194  void  void
1195  TkpSetWindowMenuBar(tkwin, menuPtr)  TkpSetWindowMenuBar(tkwin, menuPtr)
1196      Tk_Window tkwin;        /* The window we are putting the menubar into.*/      Tk_Window tkwin;        /* The window we are putting the menubar into.*/
1197      TkMenu *menuPtr;        /* The menu we are inserting */      TkMenu *menuPtr;        /* The menu we are inserting */
1198  {  {
1199      HMENU winMenuHdl;      HMENU winMenuHdl;
1200      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
1201              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
1202    
1203      if (menuPtr != NULL) {      if (menuPtr != NULL) {
1204          Tcl_HashEntry *hashEntryPtr;          Tcl_HashEntry *hashEntryPtr;
1205          int newEntry;          int newEntry;
1206    
1207          winMenuHdl = (HMENU) menuPtr->platformData;          winMenuHdl = (HMENU) menuPtr->platformData;
1208          hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,          hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
1209                  (char *) winMenuHdl);                  (char *) winMenuHdl);
1210          Tcl_DeleteHashEntry(hashEntryPtr);          Tcl_DeleteHashEntry(hashEntryPtr);
1211          DestroyMenu(winMenuHdl);          DestroyMenu(winMenuHdl);
1212          winMenuHdl = CreateMenu();          winMenuHdl = CreateMenu();
1213          hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable,          hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable,
1214                  (char *) winMenuHdl, &newEntry);                  (char *) winMenuHdl, &newEntry);
1215          Tcl_SetHashValue(hashEntryPtr, (char *) menuPtr);          Tcl_SetHashValue(hashEntryPtr, (char *) menuPtr);
1216          menuPtr->platformData = (TkMenuPlatformData) winMenuHdl;          menuPtr->platformData = (TkMenuPlatformData) winMenuHdl;
1217          TkWinSetMenu(tkwin, winMenuHdl);          TkWinSetMenu(tkwin, winMenuHdl);
1218          if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {          if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
1219              Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) menuPtr);              Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) menuPtr);
1220              menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;              menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
1221          }          }
1222      } else {      } else {
1223          TkWinSetMenu(tkwin, NULL);          TkWinSetMenu(tkwin, NULL);
1224      }      }
1225  }  }
1226    
1227    
1228  /*  /*
1229   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1230   *   *
1231   * TkpSetMainMenubar --   * TkpSetMainMenubar --
1232   *   *
1233   *      Puts the menu associated with a window into the menubar. Should   *      Puts the menu associated with a window into the menubar. Should
1234   *      only be called when the window is in front.   *      only be called when the window is in front.
1235   *   *
1236   * Results:   * Results:
1237   *      None.   *      None.
1238   *   *
1239   * Side effects:   * Side effects:
1240   *      The menubar is changed.   *      The menubar is changed.
1241   *   *
1242   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1243   */   */
1244  void  void
1245  TkpSetMainMenubar(  TkpSetMainMenubar(
1246      Tcl_Interp *interp,         /* The interpreter of the application */      Tcl_Interp *interp,         /* The interpreter of the application */
1247      Tk_Window tkwin,            /* The frame we are setting up */      Tk_Window tkwin,            /* The frame we are setting up */
1248      char *menuName)             /* The name of the menu to put in front.      char *menuName)             /* The name of the menu to put in front.
1249                                   * If NULL, use the default menu bar.                                   * If NULL, use the default menu bar.
1250                                   */                                   */
1251  {  {
1252      /*      /*
1253       * Nothing to do.       * Nothing to do.
1254       */       */
1255  }  }
1256    
1257  /*  /*
1258   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1259   *   *
1260   * GetMenuIndicatorGeometry --   * GetMenuIndicatorGeometry --
1261   *   *
1262   *      Gets the width and height of the indicator area of a menu.   *      Gets the width and height of the indicator area of a menu.
1263   *   *
1264   * Results:   * Results:
1265   *      widthPtr and heightPtr are set.   *      widthPtr and heightPtr are set.
1266   *   *
1267   * Side effects:   * Side effects:
1268   *      None.   *      None.
1269   *   *
1270   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1271   */   */
1272    
1273  void  void
1274  GetMenuIndicatorGeometry (  GetMenuIndicatorGeometry (
1275      TkMenu *menuPtr,                    /* The menu we are measuring */      TkMenu *menuPtr,                    /* The menu we are measuring */
1276      TkMenuEntry *mePtr,                 /* The entry we are measuring */      TkMenuEntry *mePtr,                 /* The entry we are measuring */
1277      Tk_Font tkfont,                     /* Precalculated font */      Tk_Font tkfont,                     /* Precalculated font */
1278      CONST Tk_FontMetrics *fmPtr,        /* Precalculated font metrics */      CONST Tk_FontMetrics *fmPtr,        /* Precalculated font metrics */
1279      int *widthPtr,                      /* The resulting width */      int *widthPtr,                      /* The resulting width */
1280      int *heightPtr)                     /* The resulting height */      int *heightPtr)                     /* The resulting height */
1281  {  {
1282      *heightPtr = indicatorDimensions[0];      *heightPtr = indicatorDimensions[0];
1283      if (mePtr->hideMargin) {      if (mePtr->hideMargin) {
1284          *widthPtr = 0;          *widthPtr = 0;
1285      } else {      } else {
1286          int borderWidth;          int borderWidth;
1287    
1288          Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,          Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
1289                  menuPtr->borderWidthPtr, &borderWidth);                  menuPtr->borderWidthPtr, &borderWidth);
1290          *widthPtr = indicatorDimensions[1] - borderWidth;          *widthPtr = indicatorDimensions[1] - borderWidth;
1291      }      }
1292  }  }
1293    
1294  /*  /*
1295   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1296   *   *
1297   * GetMenuAccelGeometry --   * GetMenuAccelGeometry --
1298   *   *
1299   *      Gets the width and height of the indicator area of a menu.   *      Gets the width and height of the indicator area of a menu.
1300   *   *
1301   * Results:   * Results:
1302   *      widthPtr and heightPtr are set.   *      widthPtr and heightPtr are set.
1303   *   *
1304   * Side effects:   * Side effects:
1305   *      None.   *      None.
1306   *   *
1307   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1308   */   */
1309    
1310  void  void
1311  GetMenuAccelGeometry (  GetMenuAccelGeometry (
1312      TkMenu *menuPtr,                    /* The menu we are measuring */      TkMenu *menuPtr,                    /* The menu we are measuring */
1313      TkMenuEntry *mePtr,                 /* The entry we are measuring */      TkMenuEntry *mePtr,                 /* The entry we are measuring */
1314      Tk_Font tkfont,                     /* The precalculated font */      Tk_Font tkfont,                     /* The precalculated font */
1315      CONST Tk_FontMetrics *fmPtr,        /* The precalculated font metrics */      CONST Tk_FontMetrics *fmPtr,        /* The precalculated font metrics */
1316      int *widthPtr,                      /* The resulting width */      int *widthPtr,                      /* The resulting width */
1317      int *heightPtr)                     /* The resulting height */      int *heightPtr)                     /* The resulting height */
1318  {  {
1319      *heightPtr = fmPtr->linespace;      *heightPtr = fmPtr->linespace;
1320      if (mePtr->type == CASCADE_ENTRY) {      if (mePtr->type == CASCADE_ENTRY) {
1321          *widthPtr = 0;          *widthPtr = 0;
1322      } else if (mePtr->accelPtr == NULL) {      } else if (mePtr->accelPtr == NULL) {
1323          *widthPtr = 0;          *widthPtr = 0;
1324      } else {      } else {
1325          char *accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);          char *accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
1326          *widthPtr = Tk_TextWidth(tkfont, accel, mePtr->accelLength);          *widthPtr = Tk_TextWidth(tkfont, accel, mePtr->accelLength);
1327      }      }
1328  }  }
1329    
1330  /*  /*
1331   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1332   *   *
1333   * GetTearoffEntryGeometry --   * GetTearoffEntryGeometry --
1334   *   *
1335   *      Gets the width and height of the indicator area of a menu.   *      Gets the width and height of the indicator area of a menu.
1336   *   *
1337   * Results:   * Results:
1338   *      widthPtr and heightPtr are set.   *      widthPtr and heightPtr are set.
1339   *   *
1340   * Side effects:   * Side effects:
1341   *      None.   *      None.
1342   *   *
1343   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1344   */   */
1345    
1346  void  void
1347  GetTearoffEntryGeometry (  GetTearoffEntryGeometry (
1348      TkMenu *menuPtr,                    /* The menu we are measuring */      TkMenu *menuPtr,                    /* The menu we are measuring */
1349      TkMenuEntry *mePtr,                 /* The entry we are measuring */      TkMenuEntry *mePtr,                 /* The entry we are measuring */
1350      Tk_Font tkfont,                     /* The precalculated font */      Tk_Font tkfont,                     /* The precalculated font */
1351      CONST Tk_FontMetrics *fmPtr,        /* The precalculated font metrics */      CONST Tk_FontMetrics *fmPtr,        /* The precalculated font metrics */
1352      int *widthPtr,                      /* The resulting width */      int *widthPtr,                      /* The resulting width */
1353      int *heightPtr)                     /* The resulting height */      int *heightPtr)                     /* The resulting height */
1354  {  {
1355      if (menuPtr->menuType != MASTER_MENU) {      if (menuPtr->menuType != MASTER_MENU) {
1356          *heightPtr = 0;          *heightPtr = 0;
1357      } else {      } else {
1358          *heightPtr = fmPtr->linespace;          *heightPtr = fmPtr->linespace;
1359      }      }
1360      *widthPtr = 0;      *widthPtr = 0;
1361  }  }
1362    
1363  /*  /*
1364   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1365   *   *
1366   * GetMenuSeparatorGeometry --   * GetMenuSeparatorGeometry --
1367   *   *
1368   *      Gets the width and height of the indicator area of a menu.   *      Gets the width and height of the indicator area of a menu.
1369   *   *
1370   * Results:   * Results:
1371   *      widthPtr and heightPtr are set.   *      widthPtr and heightPtr are set.
1372   *   *
1373   * Side effects:   * Side effects:
1374   *      None.   *      None.
1375   *   *
1376   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1377   */   */
1378    
1379  void  void
1380  GetMenuSeparatorGeometry (  GetMenuSeparatorGeometry (
1381      TkMenu *menuPtr,                    /* The menu we are measuring */      TkMenu *menuPtr,                    /* The menu we are measuring */
1382      TkMenuEntry *mePtr,                 /* The entry we are measuring */      TkMenuEntry *mePtr,                 /* The entry we are measuring */
1383      Tk_Font tkfont,                     /* The precalculated font */      Tk_Font tkfont,                     /* The precalculated font */
1384      CONST Tk_FontMetrics *fmPtr,        /* The precalcualted font metrics */      CONST Tk_FontMetrics *fmPtr,        /* The precalcualted font metrics */
1385      int *widthPtr,                      /* The resulting width */      int *widthPtr,                      /* The resulting width */
1386      int *heightPtr)                     /* The resulting height */      int *heightPtr)                     /* The resulting height */
1387  {  {
1388      *widthPtr = 0;      *widthPtr = 0;
1389      *heightPtr = fmPtr->linespace;      *heightPtr = fmPtr->linespace;
1390  }  }
1391    
1392  /*  /*
1393   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1394   *   *
1395   * DrawWindowsSystemBitmap --   * DrawWindowsSystemBitmap --
1396   *   *
1397   *      Draws the windows system bitmap given by bitmapID into the rect   *      Draws the windows system bitmap given by bitmapID into the rect
1398   *      given by rectPtr in the drawable. The bitmap is centered in the   *      given by rectPtr in the drawable. The bitmap is centered in the
1399   *      rectangle. It is not clipped, so if the bitmap is bigger than   *      rectangle. It is not clipped, so if the bitmap is bigger than
1400   *      the rect it will bleed.   *      the rect it will bleed.
1401   *   *
1402   * Results:   * Results:
1403   *      None.   *      None.
1404   *   *
1405   * Side effects:   * Side effects:
1406   *      Drawing occurs. Some storage is allocated and released.   *      Drawing occurs. Some storage is allocated and released.
1407   *   *
1408   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1409   */   */
1410    
1411  static void  static void
1412  DrawWindowsSystemBitmap(display, drawable, gc, rectPtr, bitmapID, alignFlags)  DrawWindowsSystemBitmap(display, drawable, gc, rectPtr, bitmapID, alignFlags)
1413      Display *display;                   /* The display we are drawing into */      Display *display;                   /* The display we are drawing into */
1414      Drawable drawable;                  /* The drawable we are working with */      Drawable drawable;                  /* The drawable we are working with */
1415      GC gc;                              /* The GC to draw with */      GC gc;                              /* The GC to draw with */
1416      CONST RECT *rectPtr;                /* The rectangle to draw into */      CONST RECT *rectPtr;                /* The rectangle to draw into */
1417      int bitmapID;                       /* The windows id of the system      int bitmapID;                       /* The windows id of the system
1418                                           * bitmap to draw. */                                           * bitmap to draw. */
1419      int alignFlags;                     /* How to align the bitmap inside the      int alignFlags;                     /* How to align the bitmap inside the
1420                                           * rectangle. */                                           * rectangle. */
1421  {  {
1422      TkWinDCState state;      TkWinDCState state;
1423      HDC hdc = TkWinGetDrawableDC(display, drawable, &state);      HDC hdc = TkWinGetDrawableDC(display, drawable, &state);
1424      HDC scratchDC;      HDC scratchDC;
1425      HBITMAP bitmap;      HBITMAP bitmap;
1426      BITMAP bm;      BITMAP bm;
1427      POINT ptSize;      POINT ptSize;
1428      POINT ptOrg;      POINT ptOrg;
1429      int topOffset, leftOffset;      int topOffset, leftOffset;
1430            
1431      SetBkColor(hdc, gc->background);      SetBkColor(hdc, gc->background);
1432      SetTextColor(hdc, gc->foreground);      SetTextColor(hdc, gc->foreground);
1433    
1434      scratchDC = CreateCompatibleDC(hdc);      scratchDC = CreateCompatibleDC(hdc);
1435      bitmap = LoadBitmap(NULL, MAKEINTRESOURCE(bitmapID));      bitmap = LoadBitmap(NULL, MAKEINTRESOURCE(bitmapID));
1436    
1437      SelectObject(scratchDC, bitmap);      SelectObject(scratchDC, bitmap);
1438      SetMapMode(scratchDC, GetMapMode(hdc));      SetMapMode(scratchDC, GetMapMode(hdc));
1439      GetObject(bitmap, sizeof(BITMAP), &bm);      GetObject(bitmap, sizeof(BITMAP), &bm);
1440      ptSize.x = bm.bmWidth;      ptSize.x = bm.bmWidth;
1441      ptSize.y = bm.bmHeight;      ptSize.y = bm.bmHeight;
1442      DPtoLP(hdc, &ptSize, 1);      DPtoLP(hdc, &ptSize, 1);
1443    
1444      ptOrg.y = ptOrg.x = 0;      ptOrg.y = ptOrg.x = 0;
1445      DPtoLP(hdc, &ptOrg, 1);      DPtoLP(hdc, &ptOrg, 1);
1446    
1447      if (alignFlags & ALIGN_BITMAP_TOP) {      if (alignFlags & ALIGN_BITMAP_TOP) {
1448          topOffset = 0;          topOffset = 0;
1449      } else if (alignFlags & ALIGN_BITMAP_BOTTOM) {      } else if (alignFlags & ALIGN_BITMAP_BOTTOM) {
1450          topOffset = (rectPtr->bottom - rectPtr->top) - ptSize.y;          topOffset = (rectPtr->bottom - rectPtr->top) - ptSize.y;
1451      } else {      } else {
1452          topOffset = (rectPtr->bottom - rectPtr->top) / 2 - (ptSize.y / 2);          topOffset = (rectPtr->bottom - rectPtr->top) / 2 - (ptSize.y / 2);
1453      }      }
1454    
1455      if (alignFlags & ALIGN_BITMAP_LEFT) {      if (alignFlags & ALIGN_BITMAP_LEFT) {
1456          leftOffset = 0;          leftOffset = 0;
1457      } else if (alignFlags & ALIGN_BITMAP_RIGHT) {      } else if (alignFlags & ALIGN_BITMAP_RIGHT) {
1458          leftOffset = (rectPtr->right - rectPtr->left) - ptSize.x;          leftOffset = (rectPtr->right - rectPtr->left) - ptSize.x;
1459      } else {      } else {
1460          leftOffset = (rectPtr->right - rectPtr->left) / 2 - (ptSize.x / 2);          leftOffset = (rectPtr->right - rectPtr->left) / 2 - (ptSize.x / 2);
1461      }      }
1462            
1463      BitBlt(hdc, rectPtr->left + leftOffset, rectPtr->top + topOffset, ptSize.x,      BitBlt(hdc, rectPtr->left + leftOffset, rectPtr->top + topOffset, ptSize.x,
1464              ptSize.y, scratchDC, ptOrg.x, ptOrg.y, SRCCOPY);              ptSize.y, scratchDC, ptOrg.x, ptOrg.y, SRCCOPY);
1465      DeleteDC(scratchDC);      DeleteDC(scratchDC);
1466      DeleteObject(bitmap);      DeleteObject(bitmap);
1467    
1468      TkWinReleaseDrawableDC(drawable, hdc, &state);      TkWinReleaseDrawableDC(drawable, hdc, &state);
1469  }  }
1470    
1471  /*  /*
1472   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1473   *   *
1474   * DrawMenuEntryIndicator --   * DrawMenuEntryIndicator --
1475   *   *
1476   *      This procedure draws the indicator part of a menu.   *      This procedure draws the indicator part of a menu.
1477   *   *
1478   * Results:   * Results:
1479   *      None.   *      None.
1480   *   *
1481   * Side effects:   * Side effects:
1482   *      Commands are output to X to display the menu in its   *      Commands are output to X to display the menu in its
1483   *      current mode.   *      current mode.
1484   *   *
1485   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1486   */   */
1487  void  void
1488  DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, fmPtr, x,  DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, fmPtr, x,
1489          y, width, height)          y, width, height)
1490      TkMenu *menuPtr;                /* The menu we are drawing */      TkMenu *menuPtr;                /* The menu we are drawing */
1491      TkMenuEntry *mePtr;             /* The entry we are drawing */      TkMenuEntry *mePtr;             /* The entry we are drawing */
1492      Drawable d;                     /* What we are drawing into */      Drawable d;                     /* What we are drawing into */
1493      GC gc;                          /* The gc we are drawing with */      GC gc;                          /* The gc we are drawing with */
1494      GC indicatorGC;                 /* The gc for indicator objects */      GC indicatorGC;                 /* The gc for indicator objects */
1495      Tk_Font tkfont;                 /* The precalculated font */      Tk_Font tkfont;                 /* The precalculated font */
1496      CONST Tk_FontMetrics *fmPtr;    /* The precalculated font metrics */      CONST Tk_FontMetrics *fmPtr;    /* The precalculated font metrics */
1497      int x;                          /* Left edge */      int x;                          /* Left edge */
1498      int y;                          /* Top edge */      int y;                          /* Top edge */
1499      int width;      int width;
1500      int height;      int height;
1501  {  {
1502      if ((mePtr->type == CHECK_BUTTON_ENTRY)      if ((mePtr->type == CHECK_BUTTON_ENTRY)
1503              || (mePtr->type == RADIO_BUTTON_ENTRY)) {              || (mePtr->type == RADIO_BUTTON_ENTRY)) {
1504          if (mePtr->indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED)) {          if (mePtr->indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED)) {
1505              RECT rect;              RECT rect;
1506              GC whichGC;              GC whichGC;
1507              int borderWidth, activeBorderWidth;              int borderWidth, activeBorderWidth;
1508              if (mePtr->state != ENTRY_NORMAL) {              if (mePtr->state != ENTRY_NORMAL) {
1509                  whichGC = gc;                  whichGC = gc;
1510              } else {              } else {
1511                  whichGC = indicatorGC;                  whichGC = indicatorGC;
1512              }              }
1513    
1514              rect.top = y;              rect.top = y;
1515              rect.bottom = y + mePtr->height;              rect.bottom = y + mePtr->height;
1516              Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,              Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
1517                      menuPtr->borderWidthPtr, &borderWidth);                      menuPtr->borderWidthPtr, &borderWidth);
1518              Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,              Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
1519                      menuPtr->activeBorderWidthPtr, &activeBorderWidth);                      menuPtr->activeBorderWidthPtr, &activeBorderWidth);
1520              rect.left = borderWidth + activeBorderWidth + x;              rect.left = borderWidth + activeBorderWidth + x;
1521              rect.right = mePtr->indicatorSpace + x;              rect.right = mePtr->indicatorSpace + x;
1522    
1523              if ((mePtr->state == ENTRY_DISABLED)              if ((mePtr->state == ENTRY_DISABLED)
1524                      && (menuPtr->disabledFgPtr != NULL)) {                      && (menuPtr->disabledFgPtr != NULL)) {
1525                  RECT hilightRect;                  RECT hilightRect;
1526                  COLORREF oldFgColor = whichGC->foreground;                  COLORREF oldFgColor = whichGC->foreground;
1527                            
1528                  whichGC->foreground = GetSysColor(COLOR_3DHILIGHT);                  whichGC->foreground = GetSysColor(COLOR_3DHILIGHT);
1529                  hilightRect.top = rect.top + 1;                  hilightRect.top = rect.top + 1;
1530                  hilightRect.bottom = rect.bottom + 1;                  hilightRect.bottom = rect.bottom + 1;
1531                  hilightRect.left = rect.left + 1;                  hilightRect.left = rect.left + 1;
1532                  hilightRect.right = rect.right + 1;                  hilightRect.right = rect.right + 1;
1533                  DrawWindowsSystemBitmap(menuPtr->display, d, whichGC,                  DrawWindowsSystemBitmap(menuPtr->display, d, whichGC,
1534                          &hilightRect, OBM_CHECK, 0);                          &hilightRect, OBM_CHECK, 0);
1535                  whichGC->foreground = oldFgColor;                  whichGC->foreground = oldFgColor;
1536              }              }
1537    
1538              DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, &rect,              DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, &rect,
1539                      OBM_CHECK, 0);                      OBM_CHECK, 0);
1540          }          }
1541      }          }    
1542  }  }
1543    
1544  /*  /*
1545   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1546   *   *
1547   * DrawMenuEntryAccelerator --   * DrawMenuEntryAccelerator --
1548   *   *
1549   *      This procedure draws the accelerator part of a menu. We   *      This procedure draws the accelerator part of a menu. We
1550   *      need to decide what to draw here. Should we replace strings   *      need to decide what to draw here. Should we replace strings
1551   *      like "Control", "Command", etc?   *      like "Control", "Command", etc?
1552   *   *
1553   * Results:   * Results:
1554   *      None.   *      None.
1555   *   *
1556   * Side effects:   * Side effects:
1557   *      Commands are output to X to display the menu in its   *      Commands are output to X to display the menu in its
1558   *      current mode.   *      current mode.
1559   *   *
1560   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1561   */   */
1562    
1563  void  void
1564  DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,  DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,
1565          activeBorder, x, y, width, height, drawArrow)          activeBorder, x, y, width, height, drawArrow)
1566      TkMenu *menuPtr;                    /* The menu we are drawing */      TkMenu *menuPtr;                    /* The menu we are drawing */
1567      TkMenuEntry *mePtr;                 /* The entry we are drawing */      TkMenuEntry *mePtr;                 /* The entry we are drawing */
1568      Drawable d;                         /* What we are drawing into */      Drawable d;                         /* What we are drawing into */
1569      GC gc;                              /* The gc we are drawing with */      GC gc;                              /* The gc we are drawing with */
1570      Tk_Font tkfont;                     /* The precalculated font */      Tk_Font tkfont;                     /* The precalculated font */
1571      CONST Tk_FontMetrics *fmPtr;        /* The precalculated font metrics */      CONST Tk_FontMetrics *fmPtr;        /* The precalculated font metrics */
1572      Tk_3DBorder activeBorder;           /* The border when an item is active */      Tk_3DBorder activeBorder;           /* The border when an item is active */
1573      int x;                              /* left edge */      int x;                              /* left edge */
1574      int y;                              /* top edge */      int y;                              /* top edge */
1575      int width;                          /* Width of menu entry */      int width;                          /* Width of menu entry */
1576      int height;                         /* Height of menu entry */      int height;                         /* Height of menu entry */
1577      int drawArrow;                      /* For cascade menus, whether of not      int drawArrow;                      /* For cascade menus, whether of not
1578                                           * to draw the arraw. I cannot figure                                           * to draw the arraw. I cannot figure
1579                                           * out Windows' algorithm for where                                           * out Windows' algorithm for where
1580                                           * to draw this. */                                           * to draw this. */
1581  {  {
1582      int baseline;      int baseline;
1583      int leftEdge = x + mePtr->indicatorSpace + mePtr->labelWidth;      int leftEdge = x + mePtr->indicatorSpace + mePtr->labelWidth;
1584      char *accel;      char *accel;
1585            
1586      if (mePtr->accelPtr != NULL) {      if (mePtr->accelPtr != NULL) {
1587          accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);          accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
1588      }      }
1589    
1590      baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;      baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
1591    
1592      if ((mePtr->state == ENTRY_DISABLED) && (menuPtr->disabledFgPtr != NULL)      if ((mePtr->state == ENTRY_DISABLED) && (menuPtr->disabledFgPtr != NULL)
1593              && ((mePtr->accelPtr != NULL)              && ((mePtr->accelPtr != NULL)
1594                      || ((mePtr->type == CASCADE_ENTRY) && drawArrow))) {                      || ((mePtr->type == CASCADE_ENTRY) && drawArrow))) {
1595          COLORREF oldFgColor = gc->foreground;          COLORREF oldFgColor = gc->foreground;
1596    
1597          gc->foreground = GetSysColor(COLOR_3DHILIGHT);          gc->foreground = GetSysColor(COLOR_3DHILIGHT);
1598          if (mePtr->accelPtr != NULL) {          if (mePtr->accelPtr != NULL) {
1599              Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,              Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
1600                      mePtr->accelLength, leftEdge + 1, baseline + 1);                      mePtr->accelLength, leftEdge + 1, baseline + 1);
1601          }          }
1602    
1603          if (mePtr->type == CASCADE_ENTRY) {          if (mePtr->type == CASCADE_ENTRY) {
1604              RECT rect;              RECT rect;
1605    
1606              rect.top = y + GetSystemMetrics(SM_CYBORDER) + 1;              rect.top = y + GetSystemMetrics(SM_CYBORDER) + 1;
1607              rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER) + 1;              rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER) + 1;
1608              rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth + 1;              rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth + 1;
1609              rect.right = x + width;              rect.right = x + width;
1610              DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect,              DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect,
1611                      OBM_MNARROW, ALIGN_BITMAP_RIGHT);                      OBM_MNARROW, ALIGN_BITMAP_RIGHT);
1612          }          }
1613          gc->foreground = oldFgColor;          gc->foreground = oldFgColor;
1614      }      }
1615    
1616      if (mePtr->accelPtr != NULL) {      if (mePtr->accelPtr != NULL) {
1617          Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,          Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
1618                  mePtr->accelLength, leftEdge, baseline);                  mePtr->accelLength, leftEdge, baseline);
1619      }      }
1620    
1621      if ((mePtr->type == CASCADE_ENTRY) && drawArrow) {      if ((mePtr->type == CASCADE_ENTRY) && drawArrow) {
1622          RECT rect;          RECT rect;
1623    
1624          rect.top = y + GetSystemMetrics(SM_CYBORDER);          rect.top = y + GetSystemMetrics(SM_CYBORDER);
1625          rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER);          rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER);
1626          rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth;          rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth;
1627          rect.right = x + width - 1;          rect.right = x + width - 1;
1628          DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, OBM_MNARROW,          DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, OBM_MNARROW,
1629                  ALIGN_BITMAP_RIGHT);                  ALIGN_BITMAP_RIGHT);
1630      }      }
1631  }  }
1632    
1633  /*  /*
1634   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1635   *   *
1636   * DrawMenuSeparator --   * DrawMenuSeparator --
1637   *   *
1638   *      The menu separator is drawn.   *      The menu separator is drawn.
1639   *   *
1640   * Results:   * Results:
1641   *      None.   *      None.
1642   *   *
1643   * Side effects:   * Side effects:
1644   *      Commands are output to X to display the menu in its   *      Commands are output to X to display the menu in its
1645   *      current mode.   *      current mode.
1646   *   *
1647   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1648   */   */
1649  void  void
1650  DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)  DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
1651      TkMenu *menuPtr;                    /* The menu we are drawing */      TkMenu *menuPtr;                    /* The menu we are drawing */
1652      TkMenuEntry *mePtr;                 /* The entry we are drawing */      TkMenuEntry *mePtr;                 /* The entry we are drawing */
1653      Drawable d;                         /* What we are drawing into */      Drawable d;                         /* What we are drawing into */
1654      GC gc;                              /* The gc we are drawing with */      GC gc;                              /* The gc we are drawing with */
1655      Tk_Font tkfont;                     /* The precalculated font */      Tk_Font tkfont;                     /* The precalculated font */
1656      CONST Tk_FontMetrics *fmPtr;        /* The precalculated font metrics */      CONST Tk_FontMetrics *fmPtr;        /* The precalculated font metrics */
1657      int x;                              /* left edge */      int x;                              /* left edge */
1658      int y;                              /* top edge */      int y;                              /* top edge */
1659      int width;                          /* width of item */      int width;                          /* width of item */
1660      int height;                         /* height of item */      int height;                         /* height of item */
1661  {  {
1662      XPoint points[2];      XPoint points[2];
1663      Tk_3DBorder border;      Tk_3DBorder border;
1664    
1665      points[0].x = x;      points[0].x = x;
1666      points[0].y = y + height / 2;      points[0].y = y + height / 2;
1667      points[1].x = x + width - 1;      points[1].x = x + width - 1;
1668      points[1].y = points[0].y;      points[1].y = points[0].y;
1669      border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);      border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
1670      Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,      Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,
1671              TK_RELIEF_RAISED);              TK_RELIEF_RAISED);
1672  }  }
1673    
1674  /*  /*
1675   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1676   *   *
1677   * DrawMenuUnderline --   * DrawMenuUnderline --
1678   *   *
1679   *      On appropriate platforms, draw the underline character for the   *      On appropriate platforms, draw the underline character for the
1680   *      menu.   *      menu.
1681   *   *
1682   * Results:   * Results:
1683   *      None.   *      None.
1684   *   *
1685   * Side effects:   * Side effects:
1686   *      Commands are output to X to display the menu in its   *      Commands are output to X to display the menu in its
1687   *      current mode.   *      current mode.
1688   *   *
1689   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1690   */   */
1691  static void  static void
1692  DrawMenuUnderline(  DrawMenuUnderline(
1693      TkMenu *menuPtr,                    /* The menu to draw into */      TkMenu *menuPtr,                    /* The menu to draw into */
1694      TkMenuEntry *mePtr,                 /* The entry we are drawing */      TkMenuEntry *mePtr,                 /* The entry we are drawing */
1695      Drawable d,                         /* What we are drawing into */      Drawable d,                         /* What we are drawing into */
1696      GC gc,                              /* The gc to draw into */      GC gc,                              /* The gc to draw into */
1697      Tk_Font tkfont,                     /* The precalculated font */      Tk_Font tkfont,                     /* The precalculated font */
1698      CONST Tk_FontMetrics *fmPtr,        /* The precalculated font metrics */      CONST Tk_FontMetrics *fmPtr,        /* The precalculated font metrics */
1699      int x,                              /* Left Edge */      int x,                              /* Left Edge */
1700      int y,                              /* Top Edge */      int y,                              /* Top Edge */
1701      int width,                          /* Width of entry */      int width,                          /* Width of entry */
1702      int height)                         /* Height of entry */      int height)                         /* Height of entry */
1703  {  {
1704      if (mePtr->underline >= 0) {      if (mePtr->underline >= 0) {
1705          char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);          char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
1706          char *start = Tcl_UtfAtIndex(label, mePtr->underline);          char *start = Tcl_UtfAtIndex(label, mePtr->underline);
1707          char *end = Tcl_UtfNext(start);          char *end = Tcl_UtfNext(start);
1708    
1709          Tk_UnderlineChars(menuPtr->display, d,          Tk_UnderlineChars(menuPtr->display, d,
1710                  gc, tkfont, label, x + mePtr->indicatorSpace,                  gc, tkfont, label, x + mePtr->indicatorSpace,
1711                  y + (height + fmPtr->ascent - fmPtr->descent) / 2,                  y + (height + fmPtr->ascent - fmPtr->descent) / 2,
1712                  start - label, end - label);                  start - label, end - label);
1713      }                }          
1714  }  }
1715    
1716  /*  /*
1717   *--------------------------------------------------------------   *--------------------------------------------------------------
1718   *   *
1719   * MenuKeyBindProc --   * MenuKeyBindProc --
1720   *   *
1721   *      This procedure is invoked when keys related to pulling   *      This procedure is invoked when keys related to pulling
1722   *      down menus is pressed. The corresponding Windows events   *      down menus is pressed. The corresponding Windows events
1723   *      are generated and passed to DefWindowProc if appropriate.   *      are generated and passed to DefWindowProc if appropriate.
1724   *   *
1725   * Results:   * Results:
1726   *      Always returns TCL_OK.   *      Always returns TCL_OK.
1727   *   *
1728   * Side effects:   * Side effects:
1729   *      The menu system may take over and process user events   *      The menu system may take over and process user events
1730   *      for menu input.   *      for menu input.
1731   *   *
1732   *--------------------------------------------------------------   *--------------------------------------------------------------
1733   */   */
1734    
1735  static int  static int
1736  MenuKeyBindProc(clientData, interp, eventPtr, tkwin, keySym)  MenuKeyBindProc(clientData, interp, eventPtr, tkwin, keySym)
1737      ClientData clientData;      /* not used in this proc */      ClientData clientData;      /* not used in this proc */
1738      Tcl_Interp *interp;         /* The interpreter of the receiving window. */      Tcl_Interp *interp;         /* The interpreter of the receiving window. */
1739      XEvent *eventPtr;           /* The XEvent to process */      XEvent *eventPtr;           /* The XEvent to process */
1740      Tk_Window tkwin;            /* The window receiving the event */      Tk_Window tkwin;            /* The window receiving the event */
1741      KeySym keySym;              /* The key sym that is produced. */      KeySym keySym;              /* The key sym that is produced. */
1742  {  {
1743      UINT scanCode;      UINT scanCode;
1744      UINT virtualKey;      UINT virtualKey;
1745      TkWindow *winPtr = (TkWindow *)tkwin;      TkWindow *winPtr = (TkWindow *)tkwin;
1746      int i;      int i;
1747    
1748      if (eventPtr->type == KeyPress) {      if (eventPtr->type == KeyPress) {
1749          switch (keySym) {          switch (keySym) {
1750          case XK_Alt_L:          case XK_Alt_L:
1751              scanCode = MapVirtualKey(VK_LMENU, 0);              scanCode = MapVirtualKey(VK_LMENU, 0);
1752              CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),              CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
1753                      WM_SYSKEYDOWN, VK_MENU, (scanCode << 16)                      WM_SYSKEYDOWN, VK_MENU, (scanCode << 16)
1754                      | (1 << 29));                      | (1 << 29));
1755              break;              break;
1756          case XK_Alt_R:          case XK_Alt_R:
1757              scanCode = MapVirtualKey(VK_RMENU, 0);              scanCode = MapVirtualKey(VK_RMENU, 0);
1758              CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),              CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
1759                      WM_SYSKEYDOWN, VK_MENU, (scanCode << 16)                      WM_SYSKEYDOWN, VK_MENU, (scanCode << 16)
1760                      | (1 << 29) | (1 << 24));                      | (1 << 29) | (1 << 24));
1761              break;              break;
1762          case XK_F10:          case XK_F10:
1763              scanCode = MapVirtualKey(VK_F10, 0);              scanCode = MapVirtualKey(VK_F10, 0);
1764              CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),              CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
1765                      WM_SYSKEYDOWN, VK_F10, (scanCode << 16));                      WM_SYSKEYDOWN, VK_F10, (scanCode << 16));
1766              break;              break;
1767          default:          default:
1768              virtualKey = XKeysymToKeycode(winPtr->display, keySym);              virtualKey = XKeysymToKeycode(winPtr->display, keySym);
1769              scanCode = MapVirtualKey(virtualKey, 0);              scanCode = MapVirtualKey(virtualKey, 0);
1770              if (0 != scanCode) {              if (0 != scanCode) {
1771                  CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),                  CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
1772                          WM_SYSKEYDOWN, virtualKey, ((scanCode << 16)                          WM_SYSKEYDOWN, virtualKey, ((scanCode << 16)
1773                          | (1 << 29)));                          | (1 << 29)));
1774                  if (eventPtr->xkey.nbytes > 0) {                  if (eventPtr->xkey.nbytes > 0) {
1775                      for (i = 0; i < eventPtr->xkey.nbytes; i++) {                      for (i = 0; i < eventPtr->xkey.nbytes; i++) {
1776                          CallWindowProc(DefWindowProc,                          CallWindowProc(DefWindowProc,
1777                                  Tk_GetHWND(Tk_WindowId(tkwin)),                                  Tk_GetHWND(Tk_WindowId(tkwin)),
1778                                  WM_SYSCHAR,                                  WM_SYSCHAR,
1779                                  eventPtr->xkey.trans_chars[i],                                  eventPtr->xkey.trans_chars[i],
1780                                  ((scanCode << 16) | (1 << 29)));                                  ((scanCode << 16) | (1 << 29)));
1781                      }                      }
1782                  }                  }
1783              }              }
1784          }          }
1785      } else if (eventPtr->type == KeyRelease) {      } else if (eventPtr->type == KeyRelease) {
1786          switch (keySym) {          switch (keySym) {
1787          case XK_Alt_L:          case XK_Alt_L:
1788              scanCode = MapVirtualKey(VK_LMENU, 0);              scanCode = MapVirtualKey(VK_LMENU, 0);
1789              CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),              CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
1790                      WM_SYSKEYUP, VK_MENU, (scanCode << 16)                      WM_SYSKEYUP, VK_MENU, (scanCode << 16)
1791                      | (1 << 29) | (1 << 30) | (1 << 31));                      | (1 << 29) | (1 << 30) | (1 << 31));
1792              break;              break;
1793          case XK_Alt_R:          case XK_Alt_R:
1794              scanCode = MapVirtualKey(VK_RMENU, 0);              scanCode = MapVirtualKey(VK_RMENU, 0);
1795              CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),              CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
1796                      WM_SYSKEYUP, VK_MENU, (scanCode << 16) | (1 << 24)                      WM_SYSKEYUP, VK_MENU, (scanCode << 16) | (1 << 24)
1797                      | (0x111 << 29) | (1 << 30) | (1 << 31));                      | (0x111 << 29) | (1 << 30) | (1 << 31));
1798              break;              break;
1799          case XK_F10:          case XK_F10:
1800              scanCode = MapVirtualKey(VK_F10, 0);              scanCode = MapVirtualKey(VK_F10, 0);
1801              CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),              CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
1802                      WM_SYSKEYUP, VK_F10, (scanCode << 16)                      WM_SYSKEYUP, VK_F10, (scanCode << 16)
1803                      | (1 << 30) | (1 << 31));                      | (1 << 30) | (1 << 31));
1804              break;              break;
1805          default:          default:
1806              virtualKey = XKeysymToKeycode(winPtr->display, keySym);              virtualKey = XKeysymToKeycode(winPtr->display, keySym);
1807              scanCode = MapVirtualKey(virtualKey, 0);              scanCode = MapVirtualKey(virtualKey, 0);
1808              if (0 != scanCode) {              if (0 != scanCode) {
1809                  CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),                  CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
1810                          WM_SYSKEYUP, virtualKey, ((scanCode << 16)                          WM_SYSKEYUP, virtualKey, ((scanCode << 16)
1811                          | (1 << 29) | (1 << 30) | (1 << 31)));                          | (1 << 29) | (1 << 30) | (1 << 31)));
1812              }              }
1813          }          }
1814      }      }
1815      return TCL_OK;      return TCL_OK;
1816  }    }  
1817    
1818  /*  /*
1819   *--------------------------------------------------------------   *--------------------------------------------------------------
1820   *   *
1821   * TkpInitializeMenuBindings --   * TkpInitializeMenuBindings --
1822   *   *
1823   *      For every interp, initializes the bindings for Windows   *      For every interp, initializes the bindings for Windows
1824   *      menus. Does nothing on Mac or XWindows.   *      menus. Does nothing on Mac or XWindows.
1825   *   *
1826   * Results:   * Results:
1827   *      None.   *      None.
1828   *   *
1829   * Side effects:   * Side effects:
1830   *      C-level bindings are setup for the interp which will   *      C-level bindings are setup for the interp which will
1831   *      handle Alt-key sequences for menus without beeping   *      handle Alt-key sequences for menus without beeping
1832   *      or interfering with user-defined Alt-key bindings.   *      or interfering with user-defined Alt-key bindings.
1833   *   *
1834   *--------------------------------------------------------------   *--------------------------------------------------------------
1835   */   */
1836    
1837  void  void
1838  TkpInitializeMenuBindings(interp, bindingTable)  TkpInitializeMenuBindings(interp, bindingTable)
1839      Tcl_Interp *interp;             /* The interpreter to set. */      Tcl_Interp *interp;             /* The interpreter to set. */
1840      Tk_BindingTable bindingTable;   /* The table to add to. */      Tk_BindingTable bindingTable;   /* The table to add to. */
1841  {  {
1842      Tk_Uid uid = Tk_GetUid("all");      Tk_Uid uid = Tk_GetUid("all");
1843    
1844      /*      /*
1845       * We need to set up the bindings for menubars. These have to       * We need to set up the bindings for menubars. These have to
1846       * recreate windows events, so we need to have a C-level       * recreate windows events, so we need to have a C-level
1847       * binding for this. We have to generate the WM_SYSKEYDOWNS       * binding for this. We have to generate the WM_SYSKEYDOWNS
1848       * and WM_SYSKEYUPs appropriately.       * and WM_SYSKEYUPs appropriately.
1849       */       */
1850            
1851      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,
1852              "<Alt_L>", MenuKeyBindProc, NULL, NULL);              "<Alt_L>", MenuKeyBindProc, NULL, NULL);
1853      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,
1854              "<KeyRelease-Alt_L>", MenuKeyBindProc, NULL, NULL);              "<KeyRelease-Alt_L>", MenuKeyBindProc, NULL, NULL);
1855      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,
1856              "<Alt_R>", MenuKeyBindProc, NULL, NULL);              "<Alt_R>", MenuKeyBindProc, NULL, NULL);
1857      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,
1858              "<KeyRelease-Alt_R>", MenuKeyBindProc, NULL, NULL);              "<KeyRelease-Alt_R>", MenuKeyBindProc, NULL, NULL);
1859      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,
1860              "<Alt-KeyPress>", MenuKeyBindProc, NULL, NULL);              "<Alt-KeyPress>", MenuKeyBindProc, NULL, NULL);
1861      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,
1862              "<Alt-KeyRelease>", MenuKeyBindProc, NULL, NULL);              "<Alt-KeyRelease>", MenuKeyBindProc, NULL, NULL);
1863      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,
1864              "<KeyPress-F10>", MenuKeyBindProc, NULL, NULL);              "<KeyPress-F10>", MenuKeyBindProc, NULL, NULL);
1865      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,      TkCreateBindingProcedure(interp, bindingTable, (ClientData)uid,
1866              "<KeyRelease-F10>", MenuKeyBindProc, NULL, NULL);              "<KeyRelease-F10>", MenuKeyBindProc, NULL, NULL);
1867  }  }
1868    
1869  /*  /*
1870   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1871   *   *
1872   * DrawMenuEntryLabel --   * DrawMenuEntryLabel --
1873   *   *
1874   *      This procedure draws the label part of a menu.   *      This procedure draws the label part of a menu.
1875   *   *
1876   * Results:   * Results:
1877   *      None.   *      None.
1878   *   *
1879   * Side effects:   * Side effects:
1880   *      Commands are output to X to display the menu in its   *      Commands are output to X to display the menu in its
1881   *      current mode.   *      current mode.
1882   *   *
1883   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1884   */   */
1885    
1886  static void  static void
1887  DrawMenuEntryLabel(  DrawMenuEntryLabel(
1888      TkMenu *menuPtr,                    /* The menu we are drawing */      TkMenu *menuPtr,                    /* The menu we are drawing */
1889      TkMenuEntry *mePtr,                 /* The entry we are drawing */      TkMenuEntry *mePtr,                 /* The entry we are drawing */
1890      Drawable d,                         /* What we are drawing into */      Drawable d,                         /* What we are drawing into */
1891      GC gc,                              /* The gc we are drawing into */      GC gc,                              /* The gc we are drawing into */
1892      Tk_Font tkfont,                     /* The precalculated font */      Tk_Font tkfont,                     /* The precalculated font */
1893      CONST Tk_FontMetrics *fmPtr,        /* The precalculated font metrics */      CONST Tk_FontMetrics *fmPtr,        /* The precalculated font metrics */
1894      int x,                              /* left edge */      int x,                              /* left edge */
1895      int y,                              /* right edge */      int y,                              /* right edge */
1896      int width,                          /* width of entry */      int width,                          /* width of entry */
1897      int height)                         /* height of entry */      int height)                         /* height of entry */
1898  {  {
1899      int baseline;      int baseline;
1900      int indicatorSpace =  mePtr->indicatorSpace;      int indicatorSpace =  mePtr->indicatorSpace;
1901      int activeBorderWidth;      int activeBorderWidth;
1902      int leftEdge;      int leftEdge;
1903      int imageHeight, imageWidth;      int imageHeight, imageWidth;
1904    
1905      Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,      Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
1906              menuPtr->activeBorderWidthPtr, &activeBorderWidth);              menuPtr->activeBorderWidthPtr, &activeBorderWidth);
1907      leftEdge = x + indicatorSpace + activeBorderWidth;      leftEdge = x + indicatorSpace + activeBorderWidth;
1908    
1909      /*      /*
1910       * Draw label or bitmap or image for entry.       * Draw label or bitmap or image for entry.
1911       */       */
1912    
1913      baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;      baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
1914      if (mePtr->image != NULL) {      if (mePtr->image != NULL) {
1915          Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);          Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);
1916          if ((mePtr->selectImage != NULL)          if ((mePtr->selectImage != NULL)
1917                  && (mePtr->entryFlags & ENTRY_SELECTED)) {                  && (mePtr->entryFlags & ENTRY_SELECTED)) {
1918              Tk_RedrawImage(mePtr->selectImage, 0, 0,              Tk_RedrawImage(mePtr->selectImage, 0, 0,
1919                      imageWidth, imageHeight, d, leftEdge,                      imageWidth, imageHeight, d, leftEdge,
1920                      (int) (y + (mePtr->height - imageHeight)/2));                      (int) (y + (mePtr->height - imageHeight)/2));
1921          } else {          } else {
1922              Tk_RedrawImage(mePtr->image, 0, 0, imageWidth,              Tk_RedrawImage(mePtr->image, 0, 0, imageWidth,
1923                      imageHeight, d, leftEdge,                      imageHeight, d, leftEdge,
1924                      (int) (y + (mePtr->height - imageHeight)/2));                      (int) (y + (mePtr->height - imageHeight)/2));
1925          }          }
1926      } else if (mePtr->bitmapPtr != NULL) {      } else if (mePtr->bitmapPtr != NULL) {
1927          int width, height;          int width, height;
1928          Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);          Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
1929          Tk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height);          Tk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height);
1930          XCopyPlane(menuPtr->display, bitmap, d, gc, 0, 0, (unsigned) width,          XCopyPlane(menuPtr->display, bitmap, d, gc, 0, 0, (unsigned) width,
1931                  (unsigned) height, leftEdge,                  (unsigned) height, leftEdge,
1932                  (int) (y + (mePtr->height - height)/2), 1);                  (int) (y + (mePtr->height - height)/2), 1);
1933      } else {      } else {
1934          if (mePtr->labelLength > 0) {          if (mePtr->labelLength > 0) {
1935              char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);              char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
1936              Tk_DrawChars(menuPtr->display, d, gc, tkfont, label,              Tk_DrawChars(menuPtr->display, d, gc, tkfont, label,
1937                      mePtr->labelLength, leftEdge, baseline);                      mePtr->labelLength, leftEdge, baseline);
1938              DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y,              DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y,
1939                      width, height);                      width, height);
1940          }          }
1941      }      }
1942    
1943      if (mePtr->state == ENTRY_DISABLED) {      if (mePtr->state == ENTRY_DISABLED) {
1944          if (menuPtr->disabledFgPtr == NULL) {          if (menuPtr->disabledFgPtr == NULL) {
1945              XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,              XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
1946                      (unsigned) width, (unsigned) height);                      (unsigned) width, (unsigned) height);
1947          } else if ((mePtr->image != NULL)          } else if ((mePtr->image != NULL)
1948                  && (menuPtr->disabledImageGC != None)) {                  && (menuPtr->disabledImageGC != None)) {
1949              XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,              XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
1950                      leftEdge,                      leftEdge,
1951                      (int) (y + (mePtr->height - imageHeight)/2),                      (int) (y + (mePtr->height - imageHeight)/2),
1952                      (unsigned) imageWidth, (unsigned) imageHeight);                      (unsigned) imageWidth, (unsigned) imageHeight);
1953          }          }
1954      }      }
1955  }  }
1956    
1957  /*  /*
1958   *--------------------------------------------------------------   *--------------------------------------------------------------
1959   *   *
1960   * TkpComputeMenubarGeometry --   * TkpComputeMenubarGeometry --
1961   *   *
1962   *      This procedure is invoked to recompute the size and   *      This procedure is invoked to recompute the size and
1963   *      layout of a menu that is a menubar clone.   *      layout of a menu that is a menubar clone.
1964   *   *
1965   * Results:   * Results:
1966   *      None.   *      None.
1967   *   *
1968   * Side effects:   * Side effects:
1969   *      Fields of menu entries are changed to reflect their   *      Fields of menu entries are changed to reflect their
1970   *      current positions, and the size of the menu window   *      current positions, and the size of the menu window
1971   *      itself may be changed.   *      itself may be changed.
1972   *   *
1973   *--------------------------------------------------------------   *--------------------------------------------------------------
1974   */   */
1975    
1976  void  void
1977  TkpComputeMenubarGeometry(menuPtr)  TkpComputeMenubarGeometry(menuPtr)
1978      TkMenu *menuPtr;            /* Structure describing menu. */      TkMenu *menuPtr;            /* Structure describing menu. */
1979  {  {
1980      TkpComputeStandardMenuGeometry(menuPtr);      TkpComputeStandardMenuGeometry(menuPtr);
1981  }  }
1982    
1983  /*  /*
1984   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1985   *   *
1986   * DrawTearoffEntry --   * DrawTearoffEntry --
1987   *   *
1988   *      This procedure draws the background part of a menu.   *      This procedure draws the background part of a menu.
1989   *   *
1990   * Results:   * Results:
1991   *      None.   *      None.
1992   *   *
1993   * Side effects:   * Side effects:
1994   *      Commands are output to X to display the menu in its   *      Commands are output to X to display the menu in its
1995   *      current mode.   *      current mode.
1996   *   *
1997   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1998   */   */
1999    
2000  void  void
2001  DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)  DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
2002      TkMenu *menuPtr;                    /* The menu we are drawing */      TkMenu *menuPtr;                    /* The menu we are drawing */
2003      TkMenuEntry *mePtr;                 /* The entry we are drawing */      TkMenuEntry *mePtr;                 /* The entry we are drawing */
2004      Drawable d;                         /* The drawable we are drawing into */      Drawable d;                         /* The drawable we are drawing into */
2005      GC gc;                              /* The gc we are drawing with */      GC gc;                              /* The gc we are drawing with */
2006      Tk_Font tkfont;                     /* The font we are drawing with */      Tk_Font tkfont;                     /* The font we are drawing with */
2007      CONST Tk_FontMetrics *fmPtr;        /* The metrics we are drawing with */      CONST Tk_FontMetrics *fmPtr;        /* The metrics we are drawing with */
2008      int x;      int x;
2009      int y;      int y;
2010      int width;      int width;
2011      int height;      int height;
2012  {  {
2013      XPoint points[2];      XPoint points[2];
2014      int segmentWidth, maxX;      int segmentWidth, maxX;
2015      Tk_3DBorder border;      Tk_3DBorder border;
2016    
2017      if (menuPtr->menuType != MASTER_MENU) {      if (menuPtr->menuType != MASTER_MENU) {
2018          return;          return;
2019      }      }
2020            
2021      points[0].x = x;      points[0].x = x;
2022      points[0].y = y + height/2;      points[0].y = y + height/2;
2023      points[1].y = points[0].y;      points[1].y = points[0].y;
2024      segmentWidth = 6;      segmentWidth = 6;
2025      maxX  = width - 1;      maxX  = width - 1;
2026      border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);      border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
2027    
2028      while (points[0].x < maxX) {      while (points[0].x < maxX) {
2029          points[1].x = points[0].x + segmentWidth;          points[1].x = points[0].x + segmentWidth;
2030          if (points[1].x > maxX) {          if (points[1].x > maxX) {
2031              points[1].x = maxX;              points[1].x = maxX;
2032          }          }
2033          Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,          Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,
2034                  TK_RELIEF_RAISED);                  TK_RELIEF_RAISED);
2035          points[0].x += 2*segmentWidth;          points[0].x += 2*segmentWidth;
2036      }      }
2037  }  }
2038    
2039  /*  /*
2040   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2041   *   *
2042   * TkpConfigureMenuEntry --   * TkpConfigureMenuEntry --
2043   *   *
2044   *      Processes configurations for menu entries.   *      Processes configurations for menu entries.
2045   *   *
2046   * Results:   * Results:
2047   *      Returns standard TCL result. If TCL_ERROR is returned, then   *      Returns standard TCL result. If TCL_ERROR is returned, then
2048   *      the interp's result contains an error message.   *      the interp's result contains an error message.
2049   *   *
2050   * Side effects:   * Side effects:
2051   *      Configuration information get set for mePtr; old resources   *      Configuration information get set for mePtr; old resources
2052   *      get freed, if any need it.   *      get freed, if any need it.
2053   *   *
2054   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2055   */   */
2056    
2057  int  int
2058  TkpConfigureMenuEntry(mePtr)  TkpConfigureMenuEntry(mePtr)
2059      register TkMenuEntry *mePtr;        /* Information about menu entry;  may      register TkMenuEntry *mePtr;        /* Information about menu entry;  may
2060                                           * or may not already have values for                                           * or may not already have values for
2061                                           * some fields. */                                           * some fields. */
2062  {  {
2063      TkMenu *menuPtr = mePtr->menuPtr;      TkMenu *menuPtr = mePtr->menuPtr;
2064    
2065      if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {      if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
2066          menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;          menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
2067          Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) menuPtr);          Tcl_DoWhenIdle(ReconfigureWindowsMenu, (ClientData) menuPtr);
2068      }      }
2069      return TCL_OK;      return TCL_OK;
2070  }  }
2071    
2072  /*  /*
2073   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2074   *   *
2075   * TkpDrawMenuEntry --   * TkpDrawMenuEntry --
2076   *   *
2077   *      Draws the given menu entry at the given coordinates with the   *      Draws the given menu entry at the given coordinates with the
2078   *      given attributes.   *      given attributes.
2079   *   *
2080   * Results:   * Results:
2081   *      None.   *      None.
2082   *   *
2083   * Side effects:   * Side effects:
2084   *      X Server commands are executed to display the menu entry.   *      X Server commands are executed to display the menu entry.
2085   *   *
2086   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2087   */   */
2088    
2089  void  void
2090  TkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height,  TkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height,
2091          strictMotif, drawArrow)          strictMotif, drawArrow)
2092      TkMenuEntry *mePtr;             /* The entry to draw */      TkMenuEntry *mePtr;             /* The entry to draw */
2093      Drawable d;                     /* What to draw into */      Drawable d;                     /* What to draw into */
2094      Tk_Font tkfont;                 /* Precalculated font for menu */      Tk_Font tkfont;                 /* Precalculated font for menu */
2095      CONST Tk_FontMetrics *menuMetricsPtr;      CONST Tk_FontMetrics *menuMetricsPtr;
2096                                      /* Precalculated metrics for menu */                                      /* Precalculated metrics for menu */
2097      int x;                          /* X-coordinate of topleft of entry */      int x;                          /* X-coordinate of topleft of entry */
2098      int y;                          /* Y-coordinate of topleft of entry */      int y;                          /* Y-coordinate of topleft of entry */
2099      int width;                      /* Width of the entry rectangle */      int width;                      /* Width of the entry rectangle */
2100      int height;                     /* Height of the current rectangle */      int height;                     /* Height of the current rectangle */
2101      int strictMotif;                /* Boolean flag */      int strictMotif;                /* Boolean flag */
2102      int drawArrow;                  /* Whether or not to draw the cascade      int drawArrow;                  /* Whether or not to draw the cascade
2103                                       * arrow for cascade items. Only applies                                       * arrow for cascade items. Only applies
2104                                       * to Windows. */                                       * to Windows. */
2105  {  {
2106      GC gc, indicatorGC;      GC gc, indicatorGC;
2107      TkMenu *menuPtr = mePtr->menuPtr;      TkMenu *menuPtr = mePtr->menuPtr;
2108      Tk_3DBorder bgBorder, activeBorder;      Tk_3DBorder bgBorder, activeBorder;
2109      CONST Tk_FontMetrics *fmPtr;      CONST Tk_FontMetrics *fmPtr;
2110      Tk_FontMetrics entryMetrics;      Tk_FontMetrics entryMetrics;
2111      int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0;      int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0;
2112      int adjustedY = y + padY;      int adjustedY = y + padY;
2113      int adjustedHeight = height - 2 * padY;      int adjustedHeight = height - 2 * padY;
2114    
2115      /*      /*
2116       * Choose the gc for drawing the foreground part of the entry.       * Choose the gc for drawing the foreground part of the entry.
2117       */       */
2118    
2119      if ((mePtr->state == ENTRY_ACTIVE) && !strictMotif) {      if ((mePtr->state == ENTRY_ACTIVE) && !strictMotif) {
2120          gc = mePtr->activeGC;          gc = mePtr->activeGC;
2121          if (gc == NULL) {          if (gc == NULL) {
2122              gc = menuPtr->activeGC;              gc = menuPtr->activeGC;
2123          }          }
2124      } else {      } else {
2125          TkMenuEntry *cascadeEntryPtr;          TkMenuEntry *cascadeEntryPtr;
2126          int parentDisabled = 0;          int parentDisabled = 0;
2127          char *name;          char *name;
2128                    
2129          for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;          for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
2130                  cascadeEntryPtr != NULL;                  cascadeEntryPtr != NULL;
2131                  cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {                  cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
2132              name = Tcl_GetStringFromObj(cascadeEntryPtr->namePtr, NULL);              name = Tcl_GetStringFromObj(cascadeEntryPtr->namePtr, NULL);
2133              if (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) {              if (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) {
2134                  if (mePtr->state == ENTRY_DISABLED) {                  if (mePtr->state == ENTRY_DISABLED) {
2135                      parentDisabled = 1;                      parentDisabled = 1;
2136                  }                  }
2137                  break;                  break;
2138              }              }
2139          }          }
2140    
2141          if (((parentDisabled || (mePtr->state == ENTRY_DISABLED)))          if (((parentDisabled || (mePtr->state == ENTRY_DISABLED)))
2142                  && (menuPtr->disabledFgPtr != NULL)) {                  && (menuPtr->disabledFgPtr != NULL)) {
2143              gc = mePtr->disabledGC;              gc = mePtr->disabledGC;
2144              if (gc == NULL) {              if (gc == NULL) {
2145                  gc = menuPtr->disabledGC;                  gc = menuPtr->disabledGC;
2146              }              }
2147          } else {          } else {
2148              gc = mePtr->textGC;              gc = mePtr->textGC;
2149              if (gc == NULL) {              if (gc == NULL) {
2150                  gc = menuPtr->textGC;                  gc = menuPtr->textGC;
2151              }              }
2152          }          }
2153      }      }
2154      indicatorGC = mePtr->indicatorGC;      indicatorGC = mePtr->indicatorGC;
2155      if (indicatorGC == NULL) {      if (indicatorGC == NULL) {
2156          indicatorGC = menuPtr->indicatorGC;          indicatorGC = menuPtr->indicatorGC;
2157      }      }
2158    
2159      bgBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,      bgBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
2160              (mePtr->borderPtr == NULL) ? menuPtr->borderPtr              (mePtr->borderPtr == NULL) ? menuPtr->borderPtr
2161              : mePtr->borderPtr);              : mePtr->borderPtr);
2162      if (strictMotif) {      if (strictMotif) {
2163          activeBorder = bgBorder;          activeBorder = bgBorder;
2164      } else {      } else {
2165          activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,          activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
2166              (mePtr->activeBorderPtr == NULL) ? menuPtr->activeBorderPtr              (mePtr->activeBorderPtr == NULL) ? menuPtr->activeBorderPtr
2167              : mePtr->activeBorderPtr);              : mePtr->activeBorderPtr);
2168      }      }
2169    
2170      if (mePtr->fontPtr == NULL) {      if (mePtr->fontPtr == NULL) {
2171          fmPtr = menuMetricsPtr;          fmPtr = menuMetricsPtr;
2172      } else {      } else {
2173          tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);          tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
2174          Tk_GetFontMetrics(tkfont, &entryMetrics);          Tk_GetFontMetrics(tkfont, &entryMetrics);
2175          fmPtr = &entryMetrics;          fmPtr = &entryMetrics;
2176      }      }
2177    
2178      /*      /*
2179       * Need to draw the entire background, including padding. On Unix,       * Need to draw the entire background, including padding. On Unix,
2180       * for menubars, we have to draw the rest of the entry taking       * for menubars, we have to draw the rest of the entry taking
2181       * into account the padding.       * into account the padding.
2182       */       */
2183            
2184      DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder,      DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder,
2185              bgBorder, x, y, width, height);              bgBorder, x, y, width, height);
2186            
2187      if (mePtr->type == SEPARATOR_ENTRY) {      if (mePtr->type == SEPARATOR_ENTRY) {
2188          DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont,          DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont,
2189                  fmPtr, x, adjustedY, width, adjustedHeight);                  fmPtr, x, adjustedY, width, adjustedHeight);
2190      } else if (mePtr->type == TEAROFF_ENTRY) {      } else if (mePtr->type == TEAROFF_ENTRY) {
2191          DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,          DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,
2192                  width, adjustedHeight);                  width, adjustedHeight);
2193      } else {      } else {
2194          DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,          DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,
2195                  width, adjustedHeight);                  width, adjustedHeight);
2196          DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,          DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,
2197                  activeBorder, x, adjustedY, width, adjustedHeight, drawArrow);                  activeBorder, x, adjustedY, width, adjustedHeight, drawArrow);
2198          if (!mePtr->hideMargin) {          if (!mePtr->hideMargin) {
2199              DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont,              DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont,
2200                      fmPtr, x, adjustedY, width, adjustedHeight);                      fmPtr, x, adjustedY, width, adjustedHeight);
2201          }          }
2202      }      }
2203  }  }
2204    
2205  /*  /*
2206   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2207   *   *
2208   * GetMenuLabelGeometry --   * GetMenuLabelGeometry --
2209   *   *
2210   *      Figures out the size of the label portion of a menu item.   *      Figures out the size of the label portion of a menu item.
2211   *   *
2212   * Results:   * Results:
2213   *      widthPtr and heightPtr are filled in with the correct geometry   *      widthPtr and heightPtr are filled in with the correct geometry
2214   *      information.   *      information.
2215   *   *
2216   * Side effects:   * Side effects:
2217   *      None.   *      None.
2218   *   *
2219   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2220   */   */
2221    
2222  static void  static void
2223  GetMenuLabelGeometry(mePtr, tkfont, fmPtr, widthPtr, heightPtr)  GetMenuLabelGeometry(mePtr, tkfont, fmPtr, widthPtr, heightPtr)
2224      TkMenuEntry *mePtr;                 /* The entry we are computing */      TkMenuEntry *mePtr;                 /* The entry we are computing */
2225      Tk_Font tkfont;                     /* The precalculated font */      Tk_Font tkfont;                     /* The precalculated font */
2226      CONST Tk_FontMetrics *fmPtr;        /* The precalculated metrics */      CONST Tk_FontMetrics *fmPtr;        /* The precalculated metrics */
2227      int *widthPtr;                      /* The resulting width of the label      int *widthPtr;                      /* The resulting width of the label
2228                                           * portion */                                           * portion */
2229      int *heightPtr;                     /* The resulting height of the label      int *heightPtr;                     /* The resulting height of the label
2230                                           * portion */                                           * portion */
2231  {  {
2232      TkMenu *menuPtr = mePtr->menuPtr;      TkMenu *menuPtr = mePtr->menuPtr;
2233    
2234      if (mePtr->image != NULL) {      if (mePtr->image != NULL) {
2235          Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr);          Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr);
2236      } else if (mePtr->bitmapPtr != NULL) {      } else if (mePtr->bitmapPtr != NULL) {
2237          Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);          Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
2238          Tk_SizeOfBitmap(menuPtr->display, bitmap, widthPtr, heightPtr);          Tk_SizeOfBitmap(menuPtr->display, bitmap, widthPtr, heightPtr);
2239      } else {      } else {
2240          *heightPtr = fmPtr->linespace;          *heightPtr = fmPtr->linespace;
2241                    
2242          if (mePtr->labelPtr != NULL) {          if (mePtr->labelPtr != NULL) {
2243              char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);              char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
2244    
2245              *widthPtr = Tk_TextWidth(tkfont, label, mePtr->labelLength);              *widthPtr = Tk_TextWidth(tkfont, label, mePtr->labelLength);
2246          } else {          } else {
2247              *widthPtr = 0;              *widthPtr = 0;
2248          }          }
2249      }      }
2250      *heightPtr += 1;      *heightPtr += 1;
2251  }  }
2252    
2253  /*  /*
2254   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2255   *   *
2256   * DrawMenuEntryBackground --   * DrawMenuEntryBackground --
2257   *   *
2258   *      This procedure draws the background part of a menu.   *      This procedure draws the background part of a menu.
2259   *   *
2260   * Results:   * Results:
2261   *      None.   *      None.
2262   *   *
2263   * Side effects:   * Side effects:
2264   *      Commands are output to X to display the menu in its   *      Commands are output to X to display the menu in its
2265   *      current mode.   *      current mode.
2266   *   *
2267   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2268   */   */
2269    
2270  static void  static void
2271  DrawMenuEntryBackground(  DrawMenuEntryBackground(
2272      TkMenu *menuPtr,                    /* The menu we are drawing. */      TkMenu *menuPtr,                    /* The menu we are drawing. */
2273      TkMenuEntry *mePtr,                 /* The entry we are drawing. */      TkMenuEntry *mePtr,                 /* The entry we are drawing. */
2274      Drawable d,                         /* What we are drawing into */      Drawable d,                         /* What we are drawing into */
2275      Tk_3DBorder activeBorder,           /* Border for active items */      Tk_3DBorder activeBorder,           /* Border for active items */
2276      Tk_3DBorder bgBorder,               /* Border for the background */      Tk_3DBorder bgBorder,               /* Border for the background */
2277      int x,                              /* left edge */      int x,                              /* left edge */
2278      int y,                              /* top edge */      int y,                              /* top edge */
2279      int width,                          /* width of rectangle to draw */      int width,                          /* width of rectangle to draw */
2280      int height)                         /* height of rectangle to draw */      int height)                         /* height of rectangle to draw */
2281  {  {
2282      if (mePtr->state == ENTRY_ACTIVE) {      if (mePtr->state == ENTRY_ACTIVE) {
2283          bgBorder = activeBorder;          bgBorder = activeBorder;
2284      }      }
2285      Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder,      Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder,
2286              x, y, width, height, 0, TK_RELIEF_FLAT);              x, y, width, height, 0, TK_RELIEF_FLAT);
2287  }  }
2288    
2289  /*  /*
2290   *--------------------------------------------------------------   *--------------------------------------------------------------
2291   *   *
2292   * TkpComputeStandardMenuGeometry --   * TkpComputeStandardMenuGeometry --
2293   *   *
2294   *      This procedure is invoked to recompute the size and   *      This procedure is invoked to recompute the size and
2295   *      layout of a menu that is not a menubar clone.   *      layout of a menu that is not a menubar clone.
2296   *   *
2297   * Results:   * Results:
2298   *      None.   *      None.
2299   *   *
2300   * Side effects:   * Side effects:
2301   *      Fields of menu entries are changed to reflect their   *      Fields of menu entries are changed to reflect their
2302   *      current positions, and the size of the menu window   *      current positions, and the size of the menu window
2303   *      itself may be changed.   *      itself may be changed.
2304   *   *
2305   *--------------------------------------------------------------   *--------------------------------------------------------------
2306   */   */
2307    
2308  void  void
2309  TkpComputeStandardMenuGeometry(  TkpComputeStandardMenuGeometry(
2310      TkMenu *menuPtr)            /* Structure describing menu. */      TkMenu *menuPtr)            /* Structure describing menu. */
2311  {  {
2312      Tk_Font menuFont, tkfont;      Tk_Font menuFont, tkfont;
2313      Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;      Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
2314      int x, y, height, width, indicatorSpace, labelWidth, accelWidth;      int x, y, height, width, indicatorSpace, labelWidth, accelWidth;
2315      int windowWidth, windowHeight, accelSpace;      int windowWidth, windowHeight, accelSpace;
2316      int i, j, lastColumnBreak = 0;      int i, j, lastColumnBreak = 0;
2317      int activeBorderWidth, borderWidth;      int activeBorderWidth, borderWidth;
2318            
2319      if (menuPtr->tkwin == NULL) {      if (menuPtr->tkwin == NULL) {
2320          return;          return;
2321      }      }
2322    
2323      Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,      Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
2324              menuPtr->borderWidthPtr, &borderWidth);              menuPtr->borderWidthPtr, &borderWidth);
2325      x = y = borderWidth;      x = y = borderWidth;
2326      indicatorSpace = labelWidth = accelWidth = 0;      indicatorSpace = labelWidth = accelWidth = 0;
2327      windowHeight = 0;      windowHeight = 0;
2328    
2329      /*      /*
2330       * On the Mac especially, getting font metrics can be quite slow,       * On the Mac especially, getting font metrics can be quite slow,
2331       * so we want to do it intelligently. We are going to precalculate       * so we want to do it intelligently. We are going to precalculate
2332       * them and pass them down to all of the measuring and drawing       * them and pass them down to all of the measuring and drawing
2333       * routines. We will measure the font metrics of the menu once.       * routines. We will measure the font metrics of the menu once.
2334       * If an entry does not have its own font set, then we give       * If an entry does not have its own font set, then we give
2335       * the geometry/drawing routines the menu's font and metrics.       * the geometry/drawing routines the menu's font and metrics.
2336       * If an entry has its own font, we will measure that font and       * If an entry has its own font, we will measure that font and
2337       * give all of the geometry/drawing the entry's font and metrics.       * give all of the geometry/drawing the entry's font and metrics.
2338       */       */
2339    
2340      menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);      menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
2341      Tk_GetFontMetrics(menuFont, &menuMetrics);      Tk_GetFontMetrics(menuFont, &menuMetrics);
2342      accelSpace = Tk_TextWidth(menuFont, "M", 1);      accelSpace = Tk_TextWidth(menuFont, "M", 1);
2343      Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,      Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
2344              menuPtr->activeBorderWidthPtr, &activeBorderWidth);              menuPtr->activeBorderWidthPtr, &activeBorderWidth);
2345    
2346      for (i = 0; i < menuPtr->numEntries; i++) {      for (i = 0; i < menuPtr->numEntries; i++) {
2347          if (menuPtr->entries[i]->fontPtr == NULL) {          if (menuPtr->entries[i]->fontPtr == NULL) {
2348              tkfont = menuFont;              tkfont = menuFont;
2349              fmPtr = &menuMetrics;              fmPtr = &menuMetrics;
2350          } else {          } else {
2351              tkfont = Tk_GetFontFromObj(menuPtr->tkwin,              tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
2352                      menuPtr->entries[i]->fontPtr);                      menuPtr->entries[i]->fontPtr);
2353              Tk_GetFontMetrics(tkfont, &entryMetrics);              Tk_GetFontMetrics(tkfont, &entryMetrics);
2354              fmPtr = &entryMetrics;              fmPtr = &entryMetrics;
2355          }          }
2356          if ((i > 0) && menuPtr->entries[i]->columnBreak) {          if ((i > 0) && menuPtr->entries[i]->columnBreak) {
2357              if (accelWidth != 0) {              if (accelWidth != 0) {
2358                  labelWidth += accelSpace;                  labelWidth += accelSpace;
2359              }              }
2360              for (j = lastColumnBreak; j < i; j++) {              for (j = lastColumnBreak; j < i; j++) {
2361                  menuPtr->entries[j]->indicatorSpace = indicatorSpace;                  menuPtr->entries[j]->indicatorSpace = indicatorSpace;
2362                  menuPtr->entries[j]->labelWidth = labelWidth;                  menuPtr->entries[j]->labelWidth = labelWidth;
2363                  menuPtr->entries[j]->width = indicatorSpace + labelWidth                  menuPtr->entries[j]->width = indicatorSpace + labelWidth
2364                          + accelWidth + 2 * activeBorderWidth;                          + accelWidth + 2 * activeBorderWidth;
2365                  menuPtr->entries[j]->x = x;                  menuPtr->entries[j]->x = x;
2366                  menuPtr->entries[j]->entryFlags &= ~ENTRY_LAST_COLUMN;                  menuPtr->entries[j]->entryFlags &= ~ENTRY_LAST_COLUMN;
2367              }              }
2368              x += indicatorSpace + labelWidth + accelWidth              x += indicatorSpace + labelWidth + accelWidth
2369                      + 2 * borderWidth;                      + 2 * borderWidth;
2370              indicatorSpace = labelWidth = accelWidth = 0;              indicatorSpace = labelWidth = accelWidth = 0;
2371              lastColumnBreak = i;              lastColumnBreak = i;
2372              y = borderWidth;              y = borderWidth;
2373          }          }
2374    
2375          if (menuPtr->entries[i]->type == SEPARATOR_ENTRY) {          if (menuPtr->entries[i]->type == SEPARATOR_ENTRY) {
2376              GetMenuSeparatorGeometry(menuPtr, menuPtr->entries[i], tkfont,              GetMenuSeparatorGeometry(menuPtr, menuPtr->entries[i], tkfont,
2377                      fmPtr, &width, &height);                      fmPtr, &width, &height);
2378              menuPtr->entries[i]->height = height;              menuPtr->entries[i]->height = height;
2379          } else if (menuPtr->entries[i]->type == TEAROFF_ENTRY) {          } else if (menuPtr->entries[i]->type == TEAROFF_ENTRY) {
2380              GetTearoffEntryGeometry(menuPtr, menuPtr->entries[i], tkfont,              GetTearoffEntryGeometry(menuPtr, menuPtr->entries[i], tkfont,
2381                      fmPtr, &width, &height);                      fmPtr, &width, &height);
2382              menuPtr->entries[i]->height = height;              menuPtr->entries[i]->height = height;
2383          } else {          } else {
2384                            
2385              /*              /*
2386               * For each entry, compute the height required by that               * For each entry, compute the height required by that
2387               * particular entry, plus three widths:  the width of the               * particular entry, plus three widths:  the width of the
2388               * label, the width to allow for an indicator to be displayed               * label, the width to allow for an indicator to be displayed
2389               * to the left of the label (if any), and the width of the               * to the left of the label (if any), and the width of the
2390               * accelerator to be displayed to the right of the label               * accelerator to be displayed to the right of the label
2391               * (if any).  These sizes depend, of course, on the type               * (if any).  These sizes depend, of course, on the type
2392               * of the entry.               * of the entry.
2393               */               */
2394                            
2395              GetMenuLabelGeometry(menuPtr->entries[i], tkfont, fmPtr, &width,              GetMenuLabelGeometry(menuPtr->entries[i], tkfont, fmPtr, &width,
2396                      &height);                      &height);
2397              menuPtr->entries[i]->height = height;              menuPtr->entries[i]->height = height;
2398              if (width > labelWidth) {              if (width > labelWidth) {
2399                  labelWidth = width;                  labelWidth = width;
2400              }              }
2401                    
2402              GetMenuAccelGeometry(menuPtr, menuPtr->entries[i], tkfont,              GetMenuAccelGeometry(menuPtr, menuPtr->entries[i], tkfont,
2403                      fmPtr, &width, &height);                      fmPtr, &width, &height);
2404              if (height > menuPtr->entries[i]->height) {              if (height > menuPtr->entries[i]->height) {
2405                  menuPtr->entries[i]->height = height;                  menuPtr->entries[i]->height = height;
2406              }              }
2407              if (width > accelWidth) {              if (width > accelWidth) {
2408                  accelWidth = width;                  accelWidth = width;
2409              }              }
2410    
2411              GetMenuIndicatorGeometry(menuPtr, menuPtr->entries[i], tkfont,              GetMenuIndicatorGeometry(menuPtr, menuPtr->entries[i], tkfont,
2412                      fmPtr, &width, &height);                      fmPtr, &width, &height);
2413              if (height > menuPtr->entries[i]->height) {              if (height > menuPtr->entries[i]->height) {
2414                  menuPtr->entries[i]->height = height;                  menuPtr->entries[i]->height = height;
2415              }              }
2416              if (width > indicatorSpace) {              if (width > indicatorSpace) {
2417                  indicatorSpace = width;                  indicatorSpace = width;
2418              }              }
2419    
2420              menuPtr->entries[i]->height += 2 * activeBorderWidth + 1;              menuPtr->entries[i]->height += 2 * activeBorderWidth + 1;
2421          }          }
2422          menuPtr->entries[i]->y = y;          menuPtr->entries[i]->y = y;
2423          y += menuPtr->entries[i]->height;          y += menuPtr->entries[i]->height;
2424          if (y > windowHeight) {          if (y > windowHeight) {
2425              windowHeight = y;              windowHeight = y;
2426          }          }
2427      }      }
2428    
2429      if (accelWidth != 0) {      if (accelWidth != 0) {
2430          labelWidth += accelSpace;          labelWidth += accelSpace;
2431      }      }
2432      for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {      for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {
2433          menuPtr->entries[j]->indicatorSpace = indicatorSpace;          menuPtr->entries[j]->indicatorSpace = indicatorSpace;
2434          menuPtr->entries[j]->labelWidth = labelWidth;          menuPtr->entries[j]->labelWidth = labelWidth;
2435          menuPtr->entries[j]->width = indicatorSpace + labelWidth          menuPtr->entries[j]->width = indicatorSpace + labelWidth
2436                  + accelWidth + 2 * activeBorderWidth;                  + accelWidth + 2 * activeBorderWidth;
2437          menuPtr->entries[j]->x = x;          menuPtr->entries[j]->x = x;
2438          menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;          menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;
2439      }      }
2440      windowWidth = x + indicatorSpace + labelWidth + accelWidth + accelSpace      windowWidth = x + indicatorSpace + labelWidth + accelWidth + accelSpace
2441              + 2 * activeBorderWidth + 2 * borderWidth;              + 2 * activeBorderWidth + 2 * borderWidth;
2442    
2443    
2444      windowHeight += borderWidth;      windowHeight += borderWidth;
2445            
2446      /*      /*
2447       * The X server doesn't like zero dimensions, so round up to at least       * The X server doesn't like zero dimensions, so round up to at least
2448       * 1 (a zero-sized menu should never really occur, anyway).       * 1 (a zero-sized menu should never really occur, anyway).
2449       */       */
2450    
2451      if (windowWidth <= 0) {      if (windowWidth <= 0) {
2452          windowWidth = 1;          windowWidth = 1;
2453      }      }
2454      if (windowHeight <= 0) {      if (windowHeight <= 0) {
2455          windowHeight = 1;          windowHeight = 1;
2456      }      }
2457      menuPtr->totalWidth = windowWidth;      menuPtr->totalWidth = windowWidth;
2458      menuPtr->totalHeight = windowHeight;      menuPtr->totalHeight = windowHeight;
2459  }  }
2460    
2461  /*  /*
2462   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2463   *   *
2464   * MenuSelectEvent --   * MenuSelectEvent --
2465   *   *
2466   *      Generates a "MenuSelect" virtual event. This can be used to   *      Generates a "MenuSelect" virtual event. This can be used to
2467   *      do context-sensitive menu help.   *      do context-sensitive menu help.
2468   *   *
2469   * Results:   * Results:
2470   *      None.   *      None.
2471   *   *
2472   * Side effects:   * Side effects:
2473   *      Places a virtual event on the event queue.   *      Places a virtual event on the event queue.
2474   *   *
2475   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2476   */   */
2477    
2478  static void  static void
2479  MenuSelectEvent(  MenuSelectEvent(
2480      TkMenu *menuPtr)            /* the menu we have selected. */      TkMenu *menuPtr)            /* the menu we have selected. */
2481  {  {
2482      XVirtualEvent event;      XVirtualEvent event;
2483      POINTS rootPoint;      POINTS rootPoint;
2484      DWORD msgPos;      DWORD msgPos;
2485        
2486      event.type = VirtualEvent;      event.type = VirtualEvent;
2487      event.serial = menuPtr->display->request;      event.serial = menuPtr->display->request;
2488      event.send_event = 0;      event.send_event = 0;
2489      event.display = menuPtr->display;      event.display = menuPtr->display;
2490      Tk_MakeWindowExist(menuPtr->tkwin);      Tk_MakeWindowExist(menuPtr->tkwin);
2491      event.event = Tk_WindowId(menuPtr->tkwin);      event.event = Tk_WindowId(menuPtr->tkwin);
2492      event.root = XRootWindow(menuPtr->display, 0);      event.root = XRootWindow(menuPtr->display, 0);
2493      event.subwindow = None;      event.subwindow = None;
2494      event.time = TkpGetMS();      event.time = TkpGetMS();
2495            
2496      msgPos = GetMessagePos();      msgPos = GetMessagePos();
2497      rootPoint = MAKEPOINTS(msgPos);      rootPoint = MAKEPOINTS(msgPos);
2498      event.x_root = rootPoint.x;      event.x_root = rootPoint.x;
2499      event.y_root = rootPoint.y;      event.y_root = rootPoint.y;
2500      event.state = TkWinGetModifierState();      event.state = TkWinGetModifierState();
2501      event.same_screen = 1;      event.same_screen = 1;
2502      event.name = Tk_GetUid("MenuSelect");      event.name = Tk_GetUid("MenuSelect");
2503      Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);      Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
2504  }  }
2505    
2506  /*  /*
2507   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2508   *   *
2509   * TkpMenuNotifyToplevelCreate --   * TkpMenuNotifyToplevelCreate --
2510   *   *
2511   *      This routine reconfigures the menu and the clones indicated by   *      This routine reconfigures the menu and the clones indicated by
2512   *      menuName becuase a toplevel has been created and any system   *      menuName becuase a toplevel has been created and any system
2513   *      menus need to be created.   *      menus need to be created.
2514   *   *
2515   * Results:   * Results:
2516   *      None.   *      None.
2517   *   *
2518   * Side effects:   * Side effects:
2519   *      An idle handler is set up to do the reconfiguration.   *      An idle handler is set up to do the reconfiguration.
2520   *   *
2521   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2522   */   */
2523    
2524  void  void
2525  TkpMenuNotifyToplevelCreate(  TkpMenuNotifyToplevelCreate(
2526      Tcl_Interp *interp,                 /* The interp the menu lives in. */      Tcl_Interp *interp,                 /* The interp the menu lives in. */
2527      char *menuName)                     /* The name of the menu to      char *menuName)                     /* The name of the menu to
2528                                           * reconfigure. */                                           * reconfigure. */
2529  {  {
2530      TkMenuReferences *menuRefPtr;      TkMenuReferences *menuRefPtr;
2531      TkMenu *menuPtr;      TkMenu *menuPtr;
2532    
2533      if ((menuName != NULL) && (menuName[0] != '\0')) {      if ((menuName != NULL) && (menuName[0] != '\0')) {
2534          menuRefPtr = TkFindMenuReferences(interp, menuName);          menuRefPtr = TkFindMenuReferences(interp, menuName);
2535          if ((menuRefPtr != NULL) && (menuRefPtr->menuPtr != NULL)) {          if ((menuRefPtr != NULL) && (menuRefPtr->menuPtr != NULL)) {
2536              for (menuPtr = menuRefPtr->menuPtr->masterMenuPtr; menuPtr != NULL;              for (menuPtr = menuRefPtr->menuPtr->masterMenuPtr; menuPtr != NULL;
2537                      menuPtr = menuPtr->nextInstancePtr) {                      menuPtr = menuPtr->nextInstancePtr) {
2538                  if ((menuPtr->menuType == MENUBAR)                  if ((menuPtr->menuType == MENUBAR)
2539                          && !(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {                          && !(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
2540                      menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;                      menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
2541                      Tcl_DoWhenIdle(ReconfigureWindowsMenu,                      Tcl_DoWhenIdle(ReconfigureWindowsMenu,
2542                              (ClientData) menuPtr);                              (ClientData) menuPtr);
2543                  }                  }
2544              }              }
2545          }          }
2546      }      }
2547  }  }
2548    
2549  /*  /*
2550   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2551   *   *
2552   * MenuExitHandler --   * MenuExitHandler --
2553   *   *
2554   *      Throws away the utility window needed for menus and unregisters   *      Throws away the utility window needed for menus and unregisters
2555   *      the class.   *      the class.
2556   *   *
2557   * Results:   * Results:
2558   *      None.   *      None.
2559   *   *
2560   * Side effects:   * Side effects:
2561   *      Menus have to be reinitialized next time.   *      Menus have to be reinitialized next time.
2562   *   *
2563   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2564   */   */
2565    
2566  static void  static void
2567  MenuExitHandler(  MenuExitHandler(
2568      ClientData clientData)          /* Not used */      ClientData clientData)          /* Not used */
2569  {  {
2570      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
2571              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
2572    
2573      DestroyWindow(tsdPtr->menuHWND);      DestroyWindow(tsdPtr->menuHWND);
2574      UnregisterClass(MENU_CLASS_NAME, Tk_GetHINSTANCE());      UnregisterClass(MENU_CLASS_NAME, Tk_GetHINSTANCE());
2575  }  }
2576    
2577  /*  /*
2578   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2579   *   *
2580   * TkWinGetMenuSystemDefault --   * TkWinGetMenuSystemDefault --
2581   *   *
2582   *      Gets the Windows specific default value for a given X resource   *      Gets the Windows specific default value for a given X resource
2583   *      database name.   *      database name.
2584   *   *
2585   * Results:   * Results:
2586   *      Returns a Tcl_Obj * with the default value. If there is no   *      Returns a Tcl_Obj * with the default value. If there is no
2587   *      Windows-specific default for this attribute, returns NULL.   *      Windows-specific default for this attribute, returns NULL.
2588   *      This object has a ref count of 0.   *      This object has a ref count of 0.
2589   *   *
2590   * Side effects:   * Side effects:
2591   *      Storage is allocated.   *      Storage is allocated.
2592   *   *
2593   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2594   */   */
2595    
2596  Tcl_Obj *  Tcl_Obj *
2597  TkWinGetMenuSystemDefault(  TkWinGetMenuSystemDefault(
2598      Tk_Window tkwin,            /* A window to use. */      Tk_Window tkwin,            /* A window to use. */
2599      char *dbName,               /* The option database name. */      char *dbName,               /* The option database name. */
2600      char *className)            /* The name of the option class. */      char *className)            /* The name of the option class. */
2601  {  {
2602      Tcl_Obj *valuePtr = NULL;      Tcl_Obj *valuePtr = NULL;
2603    
2604      if ((strcmp(dbName, "activeBorderWidth") == 0) ||      if ((strcmp(dbName, "activeBorderWidth") == 0) ||
2605              (strcmp(dbName, "borderWidth") == 0)) {              (strcmp(dbName, "borderWidth") == 0)) {
2606          valuePtr = Tcl_NewIntObj(defaultBorderWidth);          valuePtr = Tcl_NewIntObj(defaultBorderWidth);
2607      } else if (strcmp(dbName, "font") == 0) {      } else if (strcmp(dbName, "font") == 0) {
2608          valuePtr = Tcl_NewStringObj(Tcl_DStringValue(&menuFontDString),          valuePtr = Tcl_NewStringObj(Tcl_DStringValue(&menuFontDString),
2609                  -1);                  -1);
2610      }      }
2611    
2612      return valuePtr;      return valuePtr;
2613  }  }
2614    
2615  /*  /*
2616   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2617   *   *
2618   * TkWinMenuSetDefaults --   * TkWinMenuSetDefaults --
2619   *   *
2620   *      Sets up the hash tables and the variables used by the menu package.   *      Sets up the hash tables and the variables used by the menu package.
2621   *   *
2622   * Results:   * Results:
2623   *      None.   *      None.
2624   *   *
2625   * Side effects:   * Side effects:
2626   *      lastMenuID gets initialized, and the parent hash and the command hash   *      lastMenuID gets initialized, and the parent hash and the command hash
2627   *      are allocated.   *      are allocated.
2628   *   *
2629   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2630   */   */
2631    
2632  void  void
2633  SetDefaults(  SetDefaults(
2634      int firstTime)                  /* Is this the first time this      int firstTime)                  /* Is this the first time this
2635                                       * has been called? */                                       * has been called? */
2636  {  {
2637      char sizeString[TCL_INTEGER_SPACE];      char sizeString[TCL_INTEGER_SPACE];
2638      char faceName[LF_FACESIZE];      char faceName[LF_FACESIZE];
2639      HDC scratchDC;      HDC scratchDC;
2640      Tcl_DString boldItalicDString;      Tcl_DString boldItalicDString;
2641      int bold = 0;      int bold = 0;
2642      int italic = 0;      int italic = 0;
2643      TEXTMETRIC tm;      TEXTMETRIC tm;
2644      int pointSize;      int pointSize;
2645      HFONT menuFont;      HFONT menuFont;
2646      NONCLIENTMETRICS ncMetrics;      NONCLIENTMETRICS ncMetrics;
2647    
2648      /*      /*
2649       * Set all of the default options. The loop will terminate when we run       * Set all of the default options. The loop will terminate when we run
2650       * out of options via a break statement.       * out of options via a break statement.
2651       */       */
2652    
2653      defaultBorderWidth = GetSystemMetrics(SM_CXBORDER);      defaultBorderWidth = GetSystemMetrics(SM_CXBORDER);
2654      if (GetSystemMetrics(SM_CYBORDER) > defaultBorderWidth) {      if (GetSystemMetrics(SM_CYBORDER) > defaultBorderWidth) {
2655          defaultBorderWidth = GetSystemMetrics(SM_CYBORDER);          defaultBorderWidth = GetSystemMetrics(SM_CYBORDER);
2656      }      }
2657    
2658      scratchDC = CreateDC("DISPLAY", NULL, NULL, NULL);      scratchDC = CreateDC("DISPLAY", NULL, NULL, NULL);
2659      if (!firstTime) {      if (!firstTime) {
2660          Tcl_DStringFree(&menuFontDString);          Tcl_DStringFree(&menuFontDString);
2661      }      }
2662      Tcl_DStringInit(&menuFontDString);      Tcl_DStringInit(&menuFontDString);
2663    
2664      ncMetrics.cbSize = sizeof(ncMetrics);      ncMetrics.cbSize = sizeof(ncMetrics);
2665      SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncMetrics),      SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncMetrics),
2666              &ncMetrics, 0);              &ncMetrics, 0);
2667      menuFont = CreateFontIndirect(&ncMetrics.lfMenuFont);      menuFont = CreateFontIndirect(&ncMetrics.lfMenuFont);
2668      SelectObject(scratchDC, menuFont);      SelectObject(scratchDC, menuFont);
2669      GetTextMetrics(scratchDC, &tm);      GetTextMetrics(scratchDC, &tm);
2670      GetTextFace(scratchDC, LF_FACESIZE, faceName);      GetTextFace(scratchDC, LF_FACESIZE, faceName);
2671      pointSize = MulDiv(tm.tmHeight - tm.tmInternalLeading,      pointSize = MulDiv(tm.tmHeight - tm.tmInternalLeading,
2672              72, GetDeviceCaps(scratchDC, LOGPIXELSY));              72, GetDeviceCaps(scratchDC, LOGPIXELSY));
2673      if (tm.tmWeight >= 700) {      if (tm.tmWeight >= 700) {
2674          bold = 1;          bold = 1;
2675      }      }
2676      if (tm.tmItalic) {      if (tm.tmItalic) {
2677          italic = 1;          italic = 1;
2678      }      }
2679    
2680      SelectObject(scratchDC, GetStockObject(SYSTEM_FONT));      SelectObject(scratchDC, GetStockObject(SYSTEM_FONT));
2681      DeleteDC(scratchDC);      DeleteDC(scratchDC);
2682    
2683      DeleteObject(menuFont);      DeleteObject(menuFont);
2684            
2685      Tcl_DStringAppendElement(&menuFontDString, faceName);      Tcl_DStringAppendElement(&menuFontDString, faceName);
2686      sprintf(sizeString, "%d", pointSize);      sprintf(sizeString, "%d", pointSize);
2687      Tcl_DStringAppendElement(&menuFontDString, sizeString);      Tcl_DStringAppendElement(&menuFontDString, sizeString);
2688    
2689      if (bold == 1 || italic == 1) {      if (bold == 1 || italic == 1) {
2690          Tcl_DStringInit(&boldItalicDString);          Tcl_DStringInit(&boldItalicDString);
2691          if (bold == 1) {          if (bold == 1) {
2692              Tcl_DStringAppendElement(&boldItalicDString, "bold");              Tcl_DStringAppendElement(&boldItalicDString, "bold");
2693          }          }
2694          if (italic == 1) {          if (italic == 1) {
2695              Tcl_DStringAppendElement(&boldItalicDString, "italic");              Tcl_DStringAppendElement(&boldItalicDString, "italic");
2696          }          }
2697          Tcl_DStringAppendElement(&menuFontDString,          Tcl_DStringAppendElement(&menuFontDString,
2698                  Tcl_DStringValue(&boldItalicDString));                  Tcl_DStringValue(&boldItalicDString));
2699      }      }
2700    
2701      /*      /*
2702       * Now we go ahead and get the dimensions of the check mark and the       * Now we go ahead and get the dimensions of the check mark and the
2703       * appropriate margins. Since this is fairly hairy, we do it here       * appropriate margins. Since this is fairly hairy, we do it here
2704       * to save time when traversing large sets of menu items.       * to save time when traversing large sets of menu items.
2705       *       *
2706       * The code below was given to me by Microsoft over the phone. It       * The code below was given to me by Microsoft over the phone. It
2707       * is the only way to insure menu items lining up, and is not       * is the only way to insure menu items lining up, and is not
2708       * documented.       * documented.
2709       */       */
2710    
2711      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_WINDOWS) {      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_WINDOWS) {
2712          indicatorDimensions[0] = GetSystemMetrics(SM_CYMENUCHECK);          indicatorDimensions[0] = GetSystemMetrics(SM_CYMENUCHECK);
2713          indicatorDimensions[1] = ((GetSystemMetrics(SM_CXFIXEDFRAME) +          indicatorDimensions[1] = ((GetSystemMetrics(SM_CXFIXEDFRAME) +
2714                  GetSystemMetrics(SM_CXBORDER)                  GetSystemMetrics(SM_CXBORDER)
2715                  + GetSystemMetrics(SM_CXMENUCHECK) + 7) & 0xFFF8)                  + GetSystemMetrics(SM_CXMENUCHECK) + 7) & 0xFFF8)
2716                  - GetSystemMetrics(SM_CXFIXEDFRAME);                  - GetSystemMetrics(SM_CXFIXEDFRAME);
2717      } else {      } else {
2718          DWORD dimensions = GetMenuCheckMarkDimensions();          DWORD dimensions = GetMenuCheckMarkDimensions();
2719          indicatorDimensions[0] = HIWORD(dimensions);          indicatorDimensions[0] = HIWORD(dimensions);
2720          indicatorDimensions[1] = LOWORD(dimensions);          indicatorDimensions[1] = LOWORD(dimensions);
2721     }     }
2722  }  }
2723    
2724  /*  /*
2725   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2726   *   *
2727   * TkpMenuInit --   * TkpMenuInit --
2728   *   *
2729   *      Sets up the process-wide variables used by the menu package.   *      Sets up the process-wide variables used by the menu package.
2730   *   *
2731   * Results:   * Results:
2732   *      None.   *      None.
2733   *   *
2734   * Side effects:   * Side effects:
2735   *      lastMenuID gets initialized.   *      lastMenuID gets initialized.
2736   *   *
2737   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2738   */   */
2739    
2740  void  void
2741  TkpMenuInit()  TkpMenuInit()
2742  {  {
2743      WNDCLASS wndClass;      WNDCLASS wndClass;
2744      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
2745              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
2746    
2747      wndClass.style = CS_OWNDC;      wndClass.style = CS_OWNDC;
2748      wndClass.lpfnWndProc = TkWinMenuProc;      wndClass.lpfnWndProc = TkWinMenuProc;
2749      wndClass.cbClsExtra = 0;      wndClass.cbClsExtra = 0;
2750      wndClass.cbWndExtra = 0;      wndClass.cbWndExtra = 0;
2751      wndClass.hInstance = Tk_GetHINSTANCE();      wndClass.hInstance = Tk_GetHINSTANCE();
2752      wndClass.hIcon = NULL;      wndClass.hIcon = NULL;
2753      wndClass.hCursor = NULL;      wndClass.hCursor = NULL;
2754      wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);      wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2755      wndClass.lpszMenuName = NULL;      wndClass.lpszMenuName = NULL;
2756      wndClass.lpszClassName = MENU_CLASS_NAME;      wndClass.lpszClassName = MENU_CLASS_NAME;
2757      RegisterClass(&wndClass);      RegisterClass(&wndClass);
2758    
2759      tsdPtr->menuHWND = CreateWindow(MENU_CLASS_NAME, "MenuWindow", WS_POPUP,      tsdPtr->menuHWND = CreateWindow(MENU_CLASS_NAME, "MenuWindow", WS_POPUP,
2760          0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);          0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);
2761    
2762      Tcl_CreateExitHandler(MenuExitHandler, (ClientData) NULL);      Tcl_CreateExitHandler(MenuExitHandler, (ClientData) NULL);
2763      SetDefaults(1);      SetDefaults(1);
2764  }  }
2765    
2766  /*  /*
2767   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2768   *   *
2769   * TkpMenuThreadInit --   * TkpMenuThreadInit --
2770   *   *
2771   *      Sets up the thread-local hash tables used by the menu module.   *      Sets up the thread-local hash tables used by the menu module.
2772   *   *
2773   * Results:   * Results:
2774   *      None.   *      None.
2775   *   *
2776   * Side effects:   * Side effects:
2777   *      Hash tables winMenuTable and commandTable are initialized.   *      Hash tables winMenuTable and commandTable are initialized.
2778   *   *
2779   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2780   */   */
2781    
2782  void  void
2783  TkpMenuThreadInit()  TkpMenuThreadInit()
2784  {  {
2785      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
2786              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
2787    
2788      Tcl_InitHashTable(&tsdPtr->winMenuTable, TCL_ONE_WORD_KEYS);      Tcl_InitHashTable(&tsdPtr->winMenuTable, TCL_ONE_WORD_KEYS);
2789      Tcl_InitHashTable(&tsdPtr->commandTable, TCL_ONE_WORD_KEYS);      Tcl_InitHashTable(&tsdPtr->commandTable, TCL_ONE_WORD_KEYS);
2790  }  }
2791    
2792  /* End of tkwinmenu.c */  /* End of tkwinmenu.c */

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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25