4
* This module implements the Mac-platform specific features of menus.
6
* Copyright (c) 1996-1997 by Sun Microsystems, Inc.
8
* See the file "license.terms" for information on usage and redistribution
9
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11
* RCS: @(#) $Id: tkMacMenu.c,v 1.6 1998/11/11 17:30:44 jingham Exp $
17
#include <Resources.h>
19
#include <ToolUtils.h>
21
#include <Appearance.h>
26
#include "tkMenuButton.h"
29
typedef struct MacMenu {
30
MenuHandle menuHdl; /* The Menu Manager data structure. */
31
Rect menuRect; /* The rectangle as calculated in the
32
* MDEF. This is used to figure ou the
33
* clipping rgn before we push
34
* the <<MenuSelect>> virtual binding
38
typedef struct MenuEntryUserData {
39
Drawable mdefDrawable;
42
Tk_FontMetrics *fmPtr;
45
* Various geometry definitions:
48
#define CASCADE_ARROW_HEIGHT 10
49
#define CASCADE_ARROW_WIDTH 8
50
#define DECORATION_BORDER_WIDTH 2
51
#define MAC_MARGIN_WIDTH 8
54
* The following are constants relating to the SICNs used for drawing the MDEF.
57
#define SICN_RESOURCE_NUMBER 128
59
#define SICN_HEIGHT 16
61
#define CASCADE_ICON_WIDTH 7
62
#define SHIFT_ICON_WIDTH 10
63
#define OPTION_ICON_WIDTH 16
64
#define CONTROL_ICON_WIDTH 12
65
#define COMMAND_ICON_WIDTH 10
67
#define CASCADE_ARROW 0
70
#define CONTROL_ICON 3
71
#define COMMAND_ICON 4
76
* Platform specific flags for menu entries
78
* ENTRY_COMMAND_ACCEL Indicates the entry has the command key
79
* in its accelerator string.
80
* ENTRY_OPTION_ACCEL Indicates the entry has the option key
81
* in its accelerator string.
82
* ENTRY_SHIFT_ACCEL Indicates the entry has the shift key
83
* in its accelerator string.
84
* ENTRY_CONTROL_ACCEL Indicates the entry has the control key
85
* in its accelerator string.
88
#define ENTRY_COMMAND_ACCEL ENTRY_PLATFORM_FLAG1
89
#define ENTRY_OPTION_ACCEL ENTRY_PLATFORM_FLAG2
90
#define ENTRY_SHIFT_ACCEL ENTRY_PLATFORM_FLAG3
91
#define ENTRY_CONTROL_ACCEL ENTRY_PLATFORM_FLAG4
92
#define ENTRY_ACCEL_MASK (ENTRY_COMMAND_ACCEL | ENTRY_OPTION_ACCEL \
93
| ENTRY_SHIFT_ACCEL | ENTRY_CONTROL_ACCEL)
96
* This structure is used to keep track of subfields within Macintosh menu
100
typedef struct EntryGeometry {
101
int accelTextStart; /* Offset into the accel string where
102
* the text starts. Everything before
103
* this is modifier key descriptions.
105
int modifierWidth; /* Width of modifier symbols. */
106
int accelTextWidth; /* Width of the text after the modifier
108
int nonAccelMargin; /* The width of the margin for entries
109
* without accelerators. */
113
* Structure to keep track of toplevel windows and their menubars.
116
typedef struct TopLevelMenubarList {
117
struct TopLevelMenubarList *nextPtr;
118
/* The next window in the list. */
119
Tk_Window tkwin; /* The toplevel window. */
120
TkMenu *menuPtr; /* The menu associated with this
122
} TopLevelMenubarList;
125
* Platform-specific flags for menus.
127
* MENU_APPLE_MENU 0 indicates a custom Apple menu has
128
* not been installed; 1 a custom Apple
129
* menu has been installed.
130
* MENU_HELP_MENU 0 indicates a custom Help menu has
131
* not been installed; 1 a custom Help
132
* menu has been installed.
133
* MENU_RECONFIGURE_PENDING 1 indicates that an idle handler has
134
* been scheduled to reconfigure the
135
* Macintosh MenuHandle.
138
#define MENU_APPLE_MENU MENU_PLATFORM_FLAG1
139
#define MENU_HELP_MENU MENU_PLATFORM_FLAG2
140
#define MENU_RECONFIGURE_PENDING MENU_PLATFORM_FLAG3
142
#define CASCADE_CMD (0x1b)
143
/* The special command char for cascade
145
#define SEPARATOR_TEXT "\p(-"
146
/* The text for a menu separator. */
148
#define MENUBAR_REDRAW_PENDING 1
150
static int gNoTkMenus = 0; /* This is used by Tk_MacTurnOffMenus as the
151
* flag that Tk is not to draw any menus. */
152
RgnHandle tkMenuCascadeRgn = NULL;
153
/* The region to clip drawing to when the
155
int tkUseMenuCascadeRgn = 0; /* If this is 1, clipping code
156
* should intersect tkMenuCascadeRgn
157
* before drawing occurs.
158
* tkMenuCascadeRgn will only
159
* be valid when the value of this
162
static Tcl_HashTable commandTable;
163
/* The list of menuInstancePtrs associated with
165
static short currentAppleMenuID;
166
/* The id of the current Apple menu. 0 for
168
static short currentHelpMenuID; /* The id of the current Help menu. 0 for
170
static Tcl_Interp *currentMenuBarInterp;
171
/* The interpreter of the window that owns
172
* the current menubar. */
173
static char *currentMenuBarName;
174
/* Malloced. Name of current menu in menu bar.
175
* NULL if no menu set. TO DO: make this a
177
static Tk_Window currentMenuBarOwner;
178
/* Which window owns the current menu bar. */
179
static int helpItemCount; /* The number of items in the help menu.
180
* -1 means that the help menu is
181
* unavailable. This does not include
182
* the automatically generated separator. */
183
static int inPostMenu; /* We cannot be re-entrant like X
185
static short lastMenuID; /* To pass to NewMenu; need to figure out
186
* a good way to do this. */
187
static unsigned char lastCascadeID;
188
/* Cascades have to have ids that are
190
static MacDrawable macMDEFDrawable;
191
/* Drawable for use by MDEF code */
192
static MDEFScrollFlag = 0; /* Used so that popups don't scroll too soon. */
193
static int menuBarFlags; /* Used for whether the menu bar needs
194
* redrawing or not. */
195
static TkMenuDefUPP menuDefProc;/* The routine descriptor to the MDEF proc.
196
* The MDEF is needed to draw menus with
197
* non-standard attributes and to support
199
static struct TearoffSelect {
200
TkMenu *menuPtr; /* The menu that is torn off */
201
Point point; /* The point to place the new menu */
202
Rect excludeRect; /* We don't want to drag tearoff highlights
203
* when we are in this menu */
206
static RgnHandle totalMenuRgn = NULL;
207
/* Used to update windows which have been
208
* obscured by menus. */
209
static RgnHandle utilRgn = NULL;/* Used when creating the region that is to
210
* be clipped out while the MDEF is active. */
212
static TopLevelMenubarList *windowListPtr;
213
/* A list of windows that have menubars set. */
214
static MenuItemDrawingUPP tkThemeMenuItemDrawingUPP;
215
/* Points to the UPP for theme Item drawing. */
217
static GC appearanceGC = NULL; /* The fake appearance GC. If you
218
pass the foreground of this to TkMacSetColor,
219
it will return false, so you will know
220
not to set the foreground color */
224
* Forward declarations for procedures defined later in this file:
227
static void CompleteIdlers _ANSI_ARGS_((TkMenu *menuPtr));
228
static void DrawMenuBarWhenIdle _ANSI_ARGS_((
229
ClientData clientData));
230
static void DrawMenuBackground _ANSI_ARGS_((
231
Rect *menuRectPtr, Drawable d, ThemeMenuType type));
232
static void DrawMenuEntryAccelerator _ANSI_ARGS_((
233
TkMenu *menuPtr, TkMenuEntry *mePtr,
234
Drawable d, GC gc, Tk_Font tkfont,
235
CONST Tk_FontMetrics *fmPtr,
236
Tk_3DBorder activeBorder, int x, int y,
237
int width, int height, int drawArrow));
238
static void DrawMenuEntryBackground _ANSI_ARGS_((
239
TkMenu *menuPtr, TkMenuEntry *mePtr,
240
Drawable d, Tk_3DBorder activeBorder,
241
Tk_3DBorder bgBorder, int x, int y,
242
int width, int heigth));
243
static void DrawMenuEntryIndicator _ANSI_ARGS_((
244
TkMenu *menuPtr, TkMenuEntry *mePtr,
245
Drawable d, GC gc, GC indicatorGC,
247
CONST Tk_FontMetrics *fmPtr, int x, int y,
248
int width, int height));
249
static void DrawMenuEntryLabel _ANSI_ARGS_((
250
TkMenu * menuPtr, TkMenuEntry *mePtr, Drawable d,
251
GC gc, Tk_Font tkfont,
252
CONST Tk_FontMetrics *fmPtr, int x, int y,
253
int width, int height));
254
static void DrawMenuSeparator _ANSI_ARGS_((TkMenu *menuPtr,
255
TkMenuEntry *mePtr, Drawable d, GC gc,
256
Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
257
int x, int y, int width, int height));
258
static void DrawTearoffEntry _ANSI_ARGS_((TkMenu *menuPtr,
259
TkMenuEntry *mePtr, Drawable d, GC gc,
260
Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
261
int x, int y, int width, int height));
262
static Handle FixMDEF _ANSI_ARGS_((void));
263
static void GetMenuAccelGeometry _ANSI_ARGS_((TkMenu *menuPtr,
264
TkMenuEntry *mePtr, Tk_Font tkfont,
265
CONST Tk_FontMetrics *fmPtr, int *modWidthPtr,
266
int *textWidthPtr, int *heightPtr));
267
static void GetMenuLabelGeometry _ANSI_ARGS_((TkMenuEntry *mePtr,
268
Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
269
int *widthPtr, int *heightPtr));
270
static void GetMenuIndicatorGeometry _ANSI_ARGS_((
271
TkMenu *menuPtr, TkMenuEntry *mePtr,
272
Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
273
int *widthPtr, int *heightPtr));
274
static void GetMenuSeparatorGeometry _ANSI_ARGS_((
275
TkMenu *menuPtr, TkMenuEntry *mePtr,
276
Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
277
int *widthPtr, int *heightPtr));
278
static void GetTearoffEntryGeometry _ANSI_ARGS_((TkMenu *menuPtr,
279
TkMenuEntry *mePtr, Tk_Font tkfont,
280
CONST Tk_FontMetrics *fmPtr, int *widthPtr,
282
static int GetNewID _ANSI_ARGS_((Tcl_Interp *interp,
283
TkMenu *menuInstPtr, int cascade,
285
static char FindMarkCharacter _ANSI_ARGS_((TkMenuEntry *mePtr));
286
static void FreeID _ANSI_ARGS_((short menuID));
287
static void InvalidateMDEFRgns _ANSI_ARGS_((void));
288
static void MenuDefProc _ANSI_ARGS_((short message,
289
MenuHandle menu, Rect *menuRectPtr,
290
Point hitPt, short *whichItem,
291
TkMenuLowMemGlobals *globalsPtr));
292
static void MenuSelectEvent _ANSI_ARGS_((TkMenu *menuPtr));
293
static void ReconfigureIndividualMenu _ANSI_ARGS_((
294
TkMenu *menuPtr, MenuHandle macMenuHdl,
296
static void ReconfigureMacintoshMenu _ANSI_ARGS_ ((
297
ClientData clientData));
298
static void RecursivelyClearActiveMenu _ANSI_ARGS_((
300
static void RecursivelyDeleteMenu _ANSI_ARGS_((
302
static void RecursivelyInsertMenu _ANSI_ARGS_((
304
static void SetDefaultMenubar _ANSI_ARGS_((void));
305
static int SetMenuCascade _ANSI_ARGS_((TkMenu *menuPtr));
306
static void SetMenuIndicator _ANSI_ARGS_((TkMenuEntry *mePtr));
307
static void AppearanceEntryDrawWrapper _ANSI_ARGS_((TkMenuEntry *mePtr,
308
Rect * menuRectPtr, TkMenuLowMemGlobals *globalsPtr,
309
Drawable d, Tk_FontMetrics *fmPtr, Tk_Font tkfont,
310
int x, int y, int width, int height));
311
pascal void tkThemeMenuItemDrawingProc _ANSI_ARGS_ ((const Rect *inBounds,
312
SInt16 inDepth, Boolean inIsColorDevice,
317
*----------------------------------------------------------------------
321
* Take the ID out of the available list for new menus. Used by the
322
* default menu bar's menus so that they do not get created at the tk
323
* level. See GetNewID for more information.
326
* Returns TCL_OK if the id was not in use. Returns TCL_ERROR if the
330
* A hash table entry in the command table is created with a NULL
333
*----------------------------------------------------------------------
338
short macID) /* The id to take out of the table */
340
Tcl_HashEntry *commandEntryPtr;
344
commandEntryPtr = Tcl_CreateHashEntry(&commandTable, (char *) macID,
347
Tcl_SetHashValue(commandEntryPtr, NULL);
355
*----------------------------------------------------------------------
359
* Allocates a new menu id and marks it in use. Each menu on the
360
* mac must be designated by a unique id, which is a short. In
361
* addition, some ids are reserved by the system. Since Tk uses
362
* mostly dynamic menus, we must allocate and free these ids on
363
* the fly. We use the id as a key into a hash table; if there
364
* is no hash entry, we know that we can use the id.
367
* Returns TCL_OK if succesful; TCL_ERROR if there are no more
368
* ids of the appropriate type to allocate. menuIDPtr contains
369
* the new id if succesful.
372
* An entry is created for the menu in the command hash table,
373
* and the hash entry is stored in the appropriate field in the
374
* menu data structure.
376
*----------------------------------------------------------------------
381
Tcl_Interp *interp, /* Used for error reporting */
382
TkMenu *menuPtr, /* The menu we are working with */
383
int cascade, /* 0 if we are working with a normal menu;
384
1 if we are working with a cascade */
385
short *menuIDPtr) /* The resulting id */
389
Tcl_HashEntry *commandEntryPtr;
390
short returnID = *menuIDPtr;
393
* The following code relies on shorts and unsigned chars wrapping
394
* when the highest value is incremented. Also, the values between
395
* 236 and 255 inclusive are reserved for DA's by the Mac OS.
399
short curID = lastMenuID + 1;
404
while (curID != lastMenuID) {
405
commandEntryPtr = Tcl_CreateHashEntry(&commandTable,
406
(char *) curID, &newEntry);
409
lastMenuID = returnID = curID;
420
* Cascade ids must be between 0 and 235 only, so they must be
421
* dealt with separately.
424
unsigned char curID = lastCascadeID + 1;
429
while (curID != lastCascadeID) {
430
commandEntryPtr = Tcl_CreateHashEntry(&commandTable,
431
(char *) curID, &newEntry);
434
lastCascadeID = returnID = curID;
445
Tcl_SetHashValue(commandEntryPtr, (char *) menuPtr);
446
*menuIDPtr = returnID;
449
Tcl_AppendResult(interp, "No more menus can be allocated.",
456
*----------------------------------------------------------------------
460
* Marks the id as free.
466
* The hash table entry for the ID is cleared.
468
*----------------------------------------------------------------------
473
short menuID) /* The id to free */
475
Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&commandTable,
478
if (entryPtr != NULL) {
479
Tcl_DeleteHashEntry(entryPtr);
481
if (menuID == currentAppleMenuID) {
482
currentAppleMenuID = 0;
484
if (menuID == currentHelpMenuID) {
485
currentHelpMenuID = 0;
490
*----------------------------------------------------------------------
494
* Gets a new blank menu. Only the platform specific options are filled
498
* Returns a standard TCL error.
501
* Allocates a Macintosh menu handle and puts in the platformData
502
* field of the menuPtr.
504
*----------------------------------------------------------------------
509
TkMenu *menuPtr) /* The common structure we are making the
510
* platform structure for. */
515
MenuHandle macMenuHdl;
518
error = GetNewID(menuPtr->interp, menuPtr, 0, &menuID);
519
if (error != TCL_OK) {
522
length = strlen(Tk_PathName(menuPtr->tkwin));
523
memmove(&itemText[1], Tk_PathName(menuPtr->tkwin),
524
(length > 230) ? 230 : length);
525
itemText[0] = (length > 230) ? 230 : length;
526
macMenuHdl = NewMenu(menuID, itemText);
529
Handle mdefProc = FixMDEF();
530
if ((mdefProc != NULL)) {
531
(*macMenuHdl)->menuProc = mdefProc;
535
menuPtr->platformData = (TkMenuPlatformData) ckalloc(sizeof(MacMenu));
536
((MacMenu *) menuPtr->platformData)->menuHdl = macMenuHdl;
537
SetRect(&((MacMenu *) menuPtr->platformData)->menuRect, 0, 0, 0, 0);
539
if ((currentMenuBarInterp == menuPtr->interp)
540
&& (currentMenuBarName != NULL)) {
541
Tk_Window parentWin = Tk_Parent(menuPtr->tkwin);
543
if (strcmp(currentMenuBarName, Tk_PathName(parentWin)) == 0) {
544
if ((strcmp(Tk_PathName(menuPtr->tkwin)
545
+ strlen(Tk_PathName(parentWin)), ".apple") == 0)
546
|| (strcmp(Tk_PathName(menuPtr->tkwin)
547
+ strlen(Tk_PathName(parentWin)), ".help") == 0)) {
548
if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) {
549
Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL);
550
menuBarFlags |= MENUBAR_REDRAW_PENDING;
556
menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
557
Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr);
562
*----------------------------------------------------------------------
566
* Destroys platform-specific menu structures.
572
* All platform-specific allocations are freed up.
574
*----------------------------------------------------------------------
579
TkMenu *menuPtr) /* The common menu structure */
581
MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
583
if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
584
Tcl_CancelIdleCall(ReconfigureMacintoshMenu, (ClientData) menuPtr);
585
menuPtr->menuFlags &= ~MENU_RECONFIGURE_PENDING;
588
if ((*macMenuHdl)->menuID == currentHelpMenuID) {
589
MenuHandle helpMenuHdl;
591
if ((HMGetHelpMenuHandle(&helpMenuHdl) == noErr)
592
&& (helpMenuHdl != NULL)) {
593
int i, count = CountMItems(helpMenuHdl);
595
for (i = helpItemCount; i <= count; i++) {
596
DeleteMenuItem(helpMenuHdl, helpItemCount);
599
currentHelpMenuID = 0;
602
if (menuPtr->platformData != NULL) {
603
DeleteMenu((*macMenuHdl)->menuID);
604
FreeID((*macMenuHdl)->menuID);
605
DisposeMenu(macMenuHdl);
606
ckfree((char *) menuPtr->platformData);
607
menuPtr->platformData = NULL;
612
*----------------------------------------------------------------------
616
* Does any cleanup to change a menu from a normal to a cascade.
619
* Standard Tcl error.
622
* The mac menu id is reset.
624
*----------------------------------------------------------------------
629
TkMenu* menuPtr) /* The menu we are setting up to be a
632
MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
633
short newMenuID, menuID = (*macMenuHdl)->menuID;
637
error = GetNewID(menuPtr->interp, menuPtr, 1, &newMenuID);
638
if (error == TCL_OK) {
640
(*macMenuHdl)->menuID = newMenuID;
647
*----------------------------------------------------------------------
649
* TkpDestroyMenuEntry --
651
* Cleans up platform-specific menu entry items.
657
* All platform-specific allocations are freed up.
659
*----------------------------------------------------------------------
664
TkMenuEntry *mePtr) /* The common structure for the menu
667
TkMenu *menuPtr = mePtr->menuPtr;
669
ckfree((char *) mePtr->platformEntryData);
670
if ((menuPtr->platformData != NULL)
671
&& !(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
672
menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
673
Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr);
678
*----------------------------------------------------------------------
682
* Given a menu entry, gives back the text that should go in it.
683
* Separators should be done by the caller, as they have to be
687
* itemText points to the new text for the item.
692
*----------------------------------------------------------------------
697
TkMenuEntry *mePtr, /* A pointer to the menu entry. */
698
Str255 itemText) /* The pascal string containing the text */
700
if (mePtr->type == TEAROFF_ENTRY) {
701
strcpy((char *)itemText, (const char *)"\p(Tear-off)");
702
} else if (mePtr->imageString != NULL) {
703
strcpy((char *)itemText, (const char *)"\p(Image)");
704
} else if (mePtr->bitmap != None) {
705
strcpy((char *)itemText, (const char *)"\p(Pixmap)");
706
} else if (mePtr->label == NULL || mePtr->labelLength == 0) {
709
* The Mac menu manager does not like null strings.
712
strcpy((char *)itemText, (const char *)"\p ");
714
char *text = mePtr->label;
718
for (i = 1; (*text != '\0') && (i <= 230); i++, text++) {
720
&& (*(text + 1) != '\0') && (*(text + 1) == '.')
721
&& (*(text + 2) != '\0') && (*(text + 2) == '.')) {
733
*----------------------------------------------------------------------
735
* FindMarkCharacter --
737
* Finds the Macintosh mark character based on the font of the
738
* item. We calculate a good mark character based on the font
739
* that this item is rendered in.
741
* We try the following special mac characters. If none of them
742
* are present, just use the check mark.
743
* '' - Check mark character
744
* 'ļæ½' - Bullet character
745
* '' - Filled diamond
746
* 'ļæ½' - Hollow diamond
747
* 'ļæ½' = Long dash ("em dash")
748
* '-' = short dash (minus, "en dash");
754
* New item is added to platform menu
756
*----------------------------------------------------------------------
761
TkMenuEntry *mePtr) /* The entry we are finding the character
765
Tk_Font tkfont = (mePtr->tkfont == NULL) ? mePtr->menuPtr->tkfont
768
if (!TkMacIsCharacterMissing(tkfont, '')) {
770
} else if (!TkMacIsCharacterMissing(tkfont, 'ļæ½')) {
772
} else if (!TkMacIsCharacterMissing(tkfont, '')) {
774
} else if (!TkMacIsCharacterMissing(tkfont, 'ļæ½')) {
776
} else if (!TkMacIsCharacterMissing(tkfont, 'ļæ½')) {
778
} else if (!TkMacIsCharacterMissing(tkfont, '-')) {
787
*----------------------------------------------------------------------
789
* SetMenuIndicator --
791
* Sets the Macintosh mark character based on the font of the
798
* New item is added to platform menu
800
*----------------------------------------------------------------------
805
TkMenuEntry *mePtr) /* The entry we are setting */
807
TkMenu *menuPtr = mePtr->menuPtr;
808
MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
812
* There can be no indicators on menus that are not checkbuttons
813
* or radiobuttons. However, we should go ahead and set them
814
* so that menus look right when they are displayed. We should
815
* not set cascade entries, however, as the mark character
816
* means something different for cascade items on the Mac.
817
* Also, we do reflect the tearOff menu items in the Mac menu
818
* handle, so we ignore them.
821
if (mePtr->type == CASCADE_ENTRY) {
825
if (((mePtr->type == RADIO_BUTTON_ENTRY)
826
|| (mePtr->type == CHECK_BUTTON_ENTRY))
827
&& (mePtr->indicatorOn)
828
&& (mePtr->entryFlags & ENTRY_SELECTED)) {
829
markChar = FindMarkCharacter(mePtr);
833
SetItemMark(macMenuHdl, mePtr->index + 1, markChar);
837
*----------------------------------------------------------------------
841
* Sets title of menu so that the text displays correctly in menubar.
842
* This code directly manipulates menu handle data. This code
843
* was originally part of an ancient Apple Developer Response mail.
849
* The menu handle will change size depending on the length of the
852
*----------------------------------------------------------------------
857
MenuHandle menuHdl, /* The menu we are setting the title of. */
858
char *title) /* The C string to set the title to. */
860
int oldLength, newLength, oldHandleSize, dataLength;
863
menuDataPtr = (Ptr) (*menuHdl)->menuData;
865
if (strncmp(title, menuDataPtr + 1, menuDataPtr[0]) != 0) {
866
newLength = strlen(title) + 1;
867
oldLength = menuDataPtr[0] + 1;
868
oldHandleSize = GetHandleSize((Handle) menuHdl);
869
dataLength = oldHandleSize - (sizeof(MenuInfo) - sizeof(Str255))
871
if (newLength > oldLength) {
872
SetHandleSize((Handle) menuHdl, oldHandleSize + (newLength
874
menuDataPtr = (Ptr) (*menuHdl)->menuData;
877
BlockMove(menuDataPtr + oldLength, menuDataPtr + newLength,
879
BlockMove(title, menuDataPtr + 1, newLength - 1);
880
menuDataPtr[0] = newLength - 1;
882
if (newLength < oldLength) {
883
SetHandleSize((Handle) menuHdl, oldHandleSize + (newLength
890
*----------------------------------------------------------------------
892
* TkpConfigureMenuEntry --
894
* Processes configurations for menu entries.
897
* Returns standard TCL result. If TCL_ERROR is returned, then
898
* interp->result contains an error message.
901
* Configuration information get set for mePtr; old resources
902
* get freed, if any need it.
904
*----------------------------------------------------------------------
908
TkpConfigureMenuEntry(
909
register TkMenuEntry *mePtr) /* Information about menu entry; may
910
* or may not already have values for
913
TkMenu *menuPtr = mePtr->menuPtr;
914
int index = mePtr->index;
915
MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
916
MenuHandle helpMenuHdl = NULL;
919
* Cascade menus have to have menu IDs of less than 256. So
920
* we need to change the child menu if this has been configured
921
* for a cascade item.
924
if (mePtr->type == CASCADE_ENTRY) {
925
if ((mePtr->childMenuRefPtr != NULL)
926
&& (mePtr->childMenuRefPtr->menuPtr != NULL)) {
927
MenuHandle childMenuHdl = ((MacMenu *) mePtr
928
->childMenuRefPtr->menuPtr->platformData)->menuHdl;
930
if (childMenuHdl != NULL) {
931
int error = SetMenuCascade(mePtr->childMenuRefPtr->menuPtr);
933
if (error != TCL_OK) {
937
if (menuPtr->menuType == MENUBAR) {
938
SetMenuTitle(childMenuHdl, mePtr->label);
945
* We need to parse the accelerator string. If it has the strings
946
* for Command, Control, Shift or Option, we need to flag it
947
* so we can draw the symbols for it. We also need to precalcuate
948
* the position of the first real character we are drawing.
951
if (0 == mePtr->accelLength) {
952
((EntryGeometry *)mePtr->platformEntryData)->accelTextStart = -1;
954
char *accelString = mePtr->accel;
955
mePtr->entryFlags |= ~ENTRY_ACCEL_MASK;
958
if ((0 == strncasecmp("Control", accelString, 6))
959
&& (('-' == accelString[6]) || ('+' == accelString[6]))) {
960
mePtr->entryFlags |= ENTRY_CONTROL_ACCEL;
962
} else if ((0 == strncasecmp("Ctrl", accelString, 4))
963
&& (('-' == accelString[4]) || ('+' == accelString[4]))) {
964
mePtr->entryFlags |= ENTRY_CONTROL_ACCEL;
966
} else if ((0 == strncasecmp("Shift", accelString, 5))
967
&& (('-' == accelString[5]) || ('+' == accelString[5]))) {
968
mePtr->entryFlags |= ENTRY_SHIFT_ACCEL;
970
} else if ((0 == strncasecmp("Option", accelString, 6))
971
&& (('-' == accelString[6]) || ('+' == accelString[6]))) {
972
mePtr->entryFlags |= ENTRY_OPTION_ACCEL;
974
} else if ((0 == strncasecmp("Opt", accelString, 3))
975
&& (('-' == accelString[3]) || ('+' == accelString[3]))) {
976
mePtr->entryFlags |= ENTRY_OPTION_ACCEL;
978
} else if ((0 == strncasecmp("Command", accelString, 7))
979
&& (('-' == accelString[7]) || ('+' == accelString[7]))) {
980
mePtr->entryFlags |= ENTRY_COMMAND_ACCEL;
982
} else if ((0 == strncasecmp("Cmd", accelString, 3))
983
&& (('-' == accelString[3]) || ('+' == accelString[3]))) {
984
mePtr->entryFlags |= ENTRY_COMMAND_ACCEL;
986
} else if ((0 == strncasecmp("Alt", accelString, 3))
987
&& (('-' == accelString[3]) || ('+' == accelString[3]))) {
988
mePtr->entryFlags |= ENTRY_OPTION_ACCEL;
990
} else if ((0 == strncasecmp("Meta", accelString, 4))
991
&& (('-' == accelString[4]) || ('+' == accelString[4]))) {
992
mePtr->entryFlags |= ENTRY_COMMAND_ACCEL;
999
((EntryGeometry *)mePtr->platformEntryData)->accelTextStart
1000
= ((long) accelString - (long) mePtr->accel);
1003
if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
1004
menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
1005
Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr);
1012
*----------------------------------------------------------------------
1014
* ReconfigureIndividualMenu --
1016
* This routine redoes the guts of the menu. It works from
1017
* a base item and offset, so that a regular menu will
1018
* just have all of its items added, but the help menu will
1019
* have all of its items appended after the apple-defined
1026
* The Macintosh menu handle is updated
1028
*----------------------------------------------------------------------
1032
ReconfigureIndividualMenu(
1033
TkMenu *menuPtr, /* The menu we are affecting. */
1034
MenuHandle macMenuHdl, /* The macintosh menu we are affecting.
1035
* Will not necessarily be
1036
* menuPtr->platformData because this could
1037
* be the help menu. */
1038
int base) /* The last index that we do not want
1039
* touched. 0 for normal menus;
1040
* helpMenuItemCount for help menus. */
1046
int parentDisabled = 0;
1048
for (mePtr = menuPtr->menuRefPtr->parentEntryPtr; mePtr != NULL;
1049
mePtr = mePtr->nextCascadePtr) {
1050
if (strcmp(Tk_PathName(menuPtr->tkwin), mePtr->name) == 0) {
1051
if (mePtr->state == tkDisabledUid) {
1059
* First, we get rid of all of the old items.
1062
count = CountMItems(macMenuHdl);
1063
for (index = base; index < count; index++) {
1064
DeleteMenuItem(macMenuHdl, base + 1);
1067
count = menuPtr->numEntries;
1069
for (index = 1; index <= count; index++) {
1070
mePtr = menuPtr->entries[index - 1];
1073
* We have to do separators separately because SetMenuItemText
1074
* does not parse meta-characters.
1077
if (mePtr->type == SEPARATOR_ENTRY) {
1078
AppendMenu(macMenuHdl, SEPARATOR_TEXT);
1080
GetEntryText(mePtr, itemText);
1081
AppendMenu(macMenuHdl, "\px");
1082
SetMenuItemText(macMenuHdl, base + index, itemText);
1085
* Set enabling and disabling correctly.
1088
if (parentDisabled || (mePtr->state == tkDisabledUid)) {
1089
DisableItem(macMenuHdl, base + index);
1091
EnableItem(macMenuHdl, base + index);
1095
* Set the check mark for check entries and radio entries.
1098
SetItemMark(macMenuHdl, base + index, 0);
1099
if ((mePtr->type == CHECK_BUTTON_ENTRY)
1100
|| (mePtr->type == RADIO_BUTTON_ENTRY)) {
1101
CheckItem(macMenuHdl, base + index, (mePtr->entryFlags
1102
& ENTRY_SELECTED) && (mePtr->indicatorOn));
1103
if ((mePtr->indicatorOn)
1104
&& (mePtr->entryFlags & ENTRY_SELECTED)) {
1105
SetItemMark(macMenuHdl, base + index,
1106
FindMarkCharacter(mePtr));
1110
if (mePtr->type == CASCADE_ENTRY) {
1111
if ((mePtr->childMenuRefPtr != NULL)
1112
&& (mePtr->childMenuRefPtr->menuPtr != NULL)) {
1113
MenuHandle childMenuHdl =
1114
((MacMenu *) mePtr->childMenuRefPtr
1115
->menuPtr->platformData)->menuHdl;
1117
if (childMenuHdl == NULL) {
1118
childMenuHdl = ((MacMenu *) mePtr->childMenuRefPtr
1119
->menuPtr->platformData)->menuHdl;
1121
if (childMenuHdl != NULL) {
1122
if (TkMacHaveAppearance() > 1) {
1123
SetMenuItemHierarchicalID(macMenuHdl, base + index,
1124
(*childMenuHdl)->menuID);
1126
SetItemMark(macMenuHdl, base + index,
1127
(*childMenuHdl)->menuID);
1128
SetItemCmd(macMenuHdl, base + index, CASCADE_CMD);
1132
* If we changed the highligthing of this menu, its
1133
* children all have to be reconfigured so that
1134
* their state will be reflected in the menubar.
1137
if (!(mePtr->childMenuRefPtr->menuPtr->menuFlags
1138
& MENU_RECONFIGURE_PENDING)) {
1139
mePtr->childMenuRefPtr->menuPtr->menuFlags
1140
|= MENU_RECONFIGURE_PENDING;
1141
Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
1142
(ClientData) mePtr->childMenuRefPtr->menuPtr);
1147
if ((mePtr->type != CASCADE_ENTRY)
1148
&& (ENTRY_COMMAND_ACCEL
1149
== (mePtr->entryFlags & ENTRY_ACCEL_MASK))) {
1150
SetItemCmd(macMenuHdl, index, mePtr
1151
->accel[((EntryGeometry *)mePtr->platformEntryData)
1159
*----------------------------------------------------------------------
1161
* ReconfigureMacintoshMenu --
1163
* Rebuilds the Macintosh MenuHandle items from the menu. Called
1164
* usually as an idle handler, but can be called synchronously
1165
* if the menu is about to be posted.
1171
* Configuration information get set for mePtr; old resources
1172
* get freed, if any need it.
1174
*----------------------------------------------------------------------
1178
ReconfigureMacintoshMenu(
1179
ClientData clientData) /* Information about menu entry; may
1180
* or may not already have values for
1183
TkMenu *menuPtr = (TkMenu *) clientData;
1184
MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
1185
MenuHandle helpMenuHdl = NULL;
1187
menuPtr->menuFlags &= ~MENU_RECONFIGURE_PENDING;
1189
if (NULL == macMenuHdl) {
1193
ReconfigureIndividualMenu(menuPtr, macMenuHdl, 0);
1195
if (menuPtr->menuFlags & MENU_APPLE_MENU) {
1196
AddResMenu(macMenuHdl, 'DRVR');
1199
if ((*macMenuHdl)->menuID == currentHelpMenuID) {
1200
HMGetHelpMenuHandle(&helpMenuHdl);
1201
if (helpMenuHdl != NULL) {
1202
ReconfigureIndividualMenu(menuPtr, helpMenuHdl, helpItemCount);
1206
if (menuPtr->menuType == MENUBAR) {
1207
if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) {
1208
Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL);
1209
menuBarFlags |= MENUBAR_REDRAW_PENDING;
1215
*----------------------------------------------------------------------
1219
* Completes all idle handling so that the menus are in sync when
1220
* the user invokes them with the mouse.
1226
* The Macintosh menu handles are flushed out.
1228
*----------------------------------------------------------------------
1233
TkMenu *menuPtr) /* The menu we are completing. */
1237
if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
1238
Tcl_CancelIdleCall(ReconfigureMacintoshMenu, (ClientData) menuPtr);
1239
ReconfigureMacintoshMenu((ClientData) menuPtr);
1242
for (i = 0; i < menuPtr->numEntries; i++) {
1243
if (menuPtr->entries[i]->type == CASCADE_ENTRY) {
1244
if ((menuPtr->entries[i]->childMenuRefPtr != NULL)
1245
&& (menuPtr->entries[i]->childMenuRefPtr->menuPtr
1247
CompleteIdlers(menuPtr->entries[i]->childMenuRefPtr
1255
*----------------------------------------------------------------------
1259
* Posts a menu on the screen
1265
* The menu is posted and handled.
1267
*----------------------------------------------------------------------
1272
Tcl_Interp *interp, /* The interpreter this menu lives in */
1273
TkMenu *menuPtr, /* The menu we are posting */
1274
int x, /* The global x-coordinate of the top, left-
1275
* hand corner of where the menu is supposed
1277
int y) /* The global y-coordinate */
1279
MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
1285
Tcl_AppendResult(interp,
1286
"Cannot call post menu while already posting menu",
1292
int dummy, mouseX, mouseY;
1295
int oldWidth = menuPtr->totalWidth;
1296
Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin);
1300
result = TkPreprocessMenu(menuPtr);
1301
if (result != TCL_OK) {
1307
* The post commands could have deleted the menu, which means
1308
* we are dead and should go away.
1311
if (menuPtr->tkwin == NULL) {
1316
CompleteIdlers(menuPtr);
1317
if (menuBarFlags & MENUBAR_REDRAW_PENDING) {
1318
Tcl_CancelIdleCall(DrawMenuBarWhenIdle, (ClientData *) NULL);
1319
DrawMenuBarWhenIdle((ClientData *) NULL);
1322
if (NULL == parentWindow) {
1323
tearoffStruct.excludeRect.top = tearoffStruct.excludeRect.left
1324
= tearoffStruct.excludeRect.bottom
1325
= tearoffStruct.excludeRect.right = SHRT_MAX;
1329
Tk_GetRootCoords(parentWindow, &left, &top);
1330
tearoffStruct.excludeRect.left = left;
1331
tearoffStruct.excludeRect.top = top;
1332
tearoffStruct.excludeRect.right = left + Tk_Width(parentWindow);
1333
tearoffStruct.excludeRect.bottom = top + Tk_Height(parentWindow);
1334
if (Tk_Class(parentWindow) == Tk_GetUid("Menubutton")) {
1335
TkWindow *parentWinPtr = (TkWindow *) parentWindow;
1336
TkMenuButton *mbPtr =
1337
(TkMenuButton *) parentWinPtr->instanceData;
1338
int menuButtonWidth = Tk_Width(parentWindow)
1339
- 2 * (mbPtr->highlightWidth + mbPtr->borderWidth + 1);
1340
menuPtr->totalWidth = menuButtonWidth > menuPtr->totalWidth
1341
? menuButtonWidth : menuPtr->totalWidth;
1345
InsertMenu(macMenuHdl, -1);
1346
RecursivelyInsertMenu(menuPtr);
1347
CountMItems(macMenuHdl);
1350
oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
1351
popUpResult = PopUpMenuSelect(macMenuHdl, y, x, menuPtr->active);
1352
Tcl_SetServiceMode(oldMode);
1354
menuPtr->totalWidth = oldWidth;
1355
RecursivelyDeleteMenu(menuPtr);
1356
DeleteMenu((*macMenuHdl)->menuID);
1359
* Simulate the mouse up.
1362
XQueryPointer(NULL, None, &dummyWin, &dummyWin, &mouseX,
1363
&mouseY, &dummy, &dummy, &state);
1364
window = Tk_WindowId(menuPtr->tkwin);
1365
TkGenerateButtonEvent(mouseX, mouseY, window, state);
1368
* Dispatch the command.
1371
menuID = HiWord(popUpResult);
1373
result = TkMacDispatchMenuEvent(menuID, LoWord(popUpResult));
1375
TkMacHandleTearoffMenu();
1378
InvalidateMDEFRgns();
1379
RecursivelyClearActiveMenu(menuPtr);
1387
*----------------------------------------------------------------------
1389
* TkpMenuNewEntry --
1391
* Adds a pointer to a new menu entry structure with the platform-
1392
* specific fields filled in. The Macintosh uses the
1393
* platformEntryData field of the TkMenuEntry record to store
1394
* geometry information.
1397
* Standard TCL error.
1400
* Storage gets allocated. New menu entry data is put into the
1401
* platformEntryData field of the mePtr.
1403
*----------------------------------------------------------------------
1408
TkMenuEntry *mePtr) /* The menu we are adding an entry to */
1410
EntryGeometry *geometryPtr =
1411
(EntryGeometry *) ckalloc(sizeof(EntryGeometry));
1412
TkMenu *menuPtr = mePtr->menuPtr;
1414
geometryPtr->accelTextStart = 0;
1415
geometryPtr->accelTextWidth = 0;
1416
geometryPtr->nonAccelMargin = 0;
1417
geometryPtr->modifierWidth = 0;
1418
mePtr->platformEntryData = (TkMenuPlatformEntryData) geometryPtr;
1419
if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
1420
menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
1421
Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr);
1427
*----------------------------------------------------------------------
1430
* Tk_MacTurnOffMenus --
1432
* Turns off all the menu drawing code. This is more than just disabling
1433
* the "menu" command, this means that Tk will NEVER touch the menubar.
1434
* It is needed in the Plugin, where Tk does not own the menubar.
1440
* A flag is set which will disable all menu drawing.
1442
*----------------------------------------------------------------------
1446
Tk_MacTurnOffMenus()
1452
*----------------------------------------------------------------------
1455
* DrawMenuBarWhenIdle --
1457
* Update the menu bar next time there is an idle event.
1463
* Menu bar is redrawn.
1465
*----------------------------------------------------------------------
1469
DrawMenuBarWhenIdle(
1470
ClientData clientData) /* ignored here */
1472
TkMenuReferences *menuRefPtr;
1473
TkMenu *appleMenuPtr, *helpMenuPtr;
1474
MenuHandle macMenuHdl;
1475
Tcl_HashEntry *hashEntryPtr;
1478
* If we have been turned off, exit.
1486
* We need to clear the apple and help menus of any extra items.
1489
if (currentAppleMenuID != 0) {
1490
hashEntryPtr = Tcl_FindHashEntry(&commandTable,
1491
(char *) currentAppleMenuID);
1492
appleMenuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
1493
TkpDestroyMenu(appleMenuPtr);
1494
TkpNewMenu(appleMenuPtr);
1495
appleMenuPtr->menuFlags &= ~MENU_APPLE_MENU;
1496
appleMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
1497
Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
1498
(ClientData) appleMenuPtr);
1501
if (currentHelpMenuID != 0) {
1502
hashEntryPtr = Tcl_FindHashEntry(&commandTable,
1503
(char *) currentHelpMenuID);
1504
helpMenuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
1505
TkpDestroyMenu(helpMenuPtr);
1506
TkpNewMenu(helpMenuPtr);
1507
helpMenuPtr->menuFlags &= ~MENU_HELP_MENU;
1508
helpMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
1509
Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
1510
(ClientData) helpMenuPtr);
1514
* We need to find the clone of this menu that is the menubar.
1515
* Once we do that, for every cascade in the menu, we need to
1516
* insert the Mac menu in the Mac menubar. Finally, we need
1517
* to redraw the menubar.
1521
if (currentMenuBarName != NULL) {
1522
menuRefPtr = TkFindMenuReferences(currentMenuBarInterp,
1523
currentMenuBarName);
1525
if (menuRefPtr != NULL) {
1526
TkMenu *menuPtr, *menuBarPtr;
1527
TkMenu *cascadeMenuPtr;
1528
char *appleMenuName, *helpMenuName;
1529
int appleIndex = -1, helpIndex = -1;
1532
menuPtr = menuRefPtr->menuPtr;
1533
if (menuPtr != NULL) {
1534
TkMenuReferences *specialMenuRefPtr;
1535
TkMenuEntry *specialEntryPtr;
1537
appleMenuName = ckalloc(strlen(currentMenuBarName)
1538
+ 1 + strlen(".apple") + 1);
1539
sprintf(appleMenuName, "%s.apple",
1540
Tk_PathName(menuPtr->tkwin));
1541
specialMenuRefPtr = TkFindMenuReferences(currentMenuBarInterp,
1543
if ((specialMenuRefPtr != NULL)
1544
&& (specialMenuRefPtr->menuPtr != NULL)) {
1545
for (specialEntryPtr
1546
= specialMenuRefPtr->parentEntryPtr;
1547
specialEntryPtr != NULL;
1549
= specialEntryPtr->nextCascadePtr) {
1550
if (specialEntryPtr->menuPtr == menuPtr) {
1551
appleIndex = specialEntryPtr->index;
1556
ckfree(appleMenuName);
1558
helpMenuName = ckalloc(strlen(currentMenuBarName)
1559
+ 1 + strlen(".help") + 1);
1560
sprintf(helpMenuName, "%s.help",
1561
Tk_PathName(menuPtr->tkwin));
1562
specialMenuRefPtr = TkFindMenuReferences(currentMenuBarInterp,
1564
if ((specialMenuRefPtr != NULL)
1565
&& (specialMenuRefPtr->menuPtr != NULL)) {
1566
for (specialEntryPtr
1567
= specialMenuRefPtr->parentEntryPtr;
1568
specialEntryPtr != NULL;
1570
= specialEntryPtr->nextCascadePtr) {
1571
if (specialEntryPtr->menuPtr == menuPtr) {
1572
helpIndex = specialEntryPtr->index;
1577
ckfree(helpMenuName);
1581
for (menuBarPtr = menuPtr;
1582
(menuBarPtr != NULL)
1583
&& (menuBarPtr->menuType != MENUBAR);
1584
menuBarPtr = menuBarPtr->nextInstancePtr) {
1592
if (menuBarPtr == NULL) {
1593
SetDefaultMenubar();
1595
if (menuBarPtr->tearOff != menuPtr->tearOff) {
1596
if (menuBarPtr->tearOff) {
1597
appleIndex = (-1 == appleIndex) ? appleIndex
1599
helpIndex = (-1 == helpIndex) ? helpIndex
1602
appleIndex = (-1 == appleIndex) ? appleIndex
1604
helpIndex = (-1 == helpIndex) ? helpIndex
1610
if (appleIndex == -1) {
1611
InsertMenu(tkAppleMenu, 0);
1612
currentAppleMenuID = 0;
1615
appleMenuPtr = menuBarPtr->entries[appleIndex]
1616
->childMenuRefPtr->menuPtr;
1617
TkpDestroyMenu(appleMenuPtr);
1618
GetNewID(appleMenuPtr->interp, appleMenuPtr, 0,
1620
macMenuHdl = NewMenu(appleID, "\p\024");
1621
appleMenuPtr->platformData =
1622
(TkMenuPlatformData) ckalloc(sizeof(MacMenu));
1623
((MacMenu *)appleMenuPtr->platformData)->menuHdl
1625
SetRect(&((MacMenu *) appleMenuPtr->platformData)->menuRect,
1627
appleMenuPtr->menuFlags |= MENU_APPLE_MENU;
1628
if (!(appleMenuPtr->menuFlags
1629
& MENU_RECONFIGURE_PENDING)) {
1630
appleMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
1631
Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
1632
(ClientData) appleMenuPtr);
1634
InsertMenu(macMenuHdl, 0);
1635
RecursivelyInsertMenu(appleMenuPtr);
1636
currentAppleMenuID = appleID;
1638
if (helpIndex == -1) {
1639
currentHelpMenuID = 0;
1642
for (i = 0; i < menuBarPtr->numEntries; i++) {
1643
if (i == appleIndex) {
1644
if (menuBarPtr->entries[i]->state == tkDisabledUid) {
1645
DisableItem(((MacMenu *) menuBarPtr->entries[i]
1646
->childMenuRefPtr->menuPtr
1647
->platformData)->menuHdl,
1650
EnableItem(((MacMenu *) menuBarPtr->entries[i]
1651
->childMenuRefPtr->menuPtr
1652
->platformData)->menuHdl,
1656
} else if (i == helpIndex) {
1657
TkMenu *helpMenuPtr = menuBarPtr->entries[i]
1658
->childMenuRefPtr->menuPtr;
1659
MenuHandle helpMenuHdl = NULL;
1661
if (helpMenuPtr == NULL) {
1664
helpMenuPtr->menuFlags |= MENU_HELP_MENU;
1665
if (!(helpMenuPtr->menuFlags
1666
& MENU_RECONFIGURE_PENDING)) {
1667
helpMenuPtr->menuFlags
1668
|= MENU_RECONFIGURE_PENDING;
1669
Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
1670
(ClientData) helpMenuPtr);
1673
((MacMenu *) helpMenuPtr->platformData)->menuHdl;
1674
currentHelpMenuID = (*macMenuHdl)->menuID;
1675
} else if (menuBarPtr->entries[i]->type
1677
if ((menuBarPtr->entries[i]->childMenuRefPtr != NULL)
1678
&& menuBarPtr->entries[i]->childMenuRefPtr
1679
->menuPtr != NULL) {
1680
cascadeMenuPtr = menuBarPtr->entries[i]
1681
->childMenuRefPtr->menuPtr;
1682
macMenuHdl = ((MacMenu *) cascadeMenuPtr
1683
->platformData)->menuHdl;
1684
DeleteMenu((*macMenuHdl)->menuID);
1685
InsertMenu(macMenuHdl, 0);
1686
RecursivelyInsertMenu(cascadeMenuPtr);
1687
if (menuBarPtr->entries[i]->state == tkDisabledUid) {
1688
DisableItem(((MacMenu *) menuBarPtr->entries[i]
1689
->childMenuRefPtr->menuPtr
1690
->platformData)->menuHdl,
1693
EnableItem(((MacMenu *) menuBarPtr->entries[i]
1694
->childMenuRefPtr->menuPtr
1695
->platformData)->menuHdl,
1703
SetDefaultMenubar();
1706
menuBarFlags &= ~MENUBAR_REDRAW_PENDING;
1711
*----------------------------------------------------------------------
1713
* RecursivelyInsertMenu --
1715
* Puts all of the cascades of this menu in the Mac hierarchical list.
1722
* The menubar is changed.
1724
*----------------------------------------------------------------------
1728
RecursivelyInsertMenu(
1729
TkMenu *menuPtr) /* All of the cascade items in this menu
1730
* will be inserted into the mac menubar. */
1733
TkMenu *cascadeMenuPtr;
1734
MenuHandle macMenuHdl;
1736
for (i = 0; i < menuPtr->numEntries; i++) {
1737
if (menuPtr->entries[i]->type == CASCADE_ENTRY) {
1738
if ((menuPtr->entries[i]->childMenuRefPtr != NULL)
1739
&& (menuPtr->entries[i]->childMenuRefPtr->menuPtr
1741
cascadeMenuPtr = menuPtr->entries[i]->childMenuRefPtr->menuPtr;
1742
macMenuHdl = ((MacMenu *) cascadeMenuPtr->platformData)->menuHdl;
1743
InsertMenu(macMenuHdl, -1);
1744
RecursivelyInsertMenu(cascadeMenuPtr);
1751
*----------------------------------------------------------------------
1753
* RecursivelyDeleteMenu --
1755
* Takes all of the cascades of this menu out of the Mac hierarchical
1763
* The menubar is changed.
1765
*----------------------------------------------------------------------
1769
RecursivelyDeleteMenu(
1770
TkMenu *menuPtr) /* All of the cascade items in this menu
1771
* will be inserted into the mac menubar. */
1774
TkMenu *cascadeMenuPtr;
1775
MenuHandle macMenuHdl;
1777
for (i = 0; i < menuPtr->numEntries; i++) {
1778
if (menuPtr->entries[i]->type == CASCADE_ENTRY) {
1779
if ((menuPtr->entries[i]->childMenuRefPtr != NULL)
1780
&& (menuPtr->entries[i]->childMenuRefPtr->menuPtr
1782
cascadeMenuPtr = menuPtr->entries[i]->childMenuRefPtr->menuPtr;
1783
macMenuHdl = ((MacMenu *) cascadeMenuPtr->platformData)->menuHdl;
1784
DeleteMenu((*macMenuHdl)->menuID);
1785
RecursivelyInsertMenu(cascadeMenuPtr);
1792
*----------------------------------------------------------------------
1794
* SetDefaultMenubar --
1796
* Puts the Apple, File and Edit menus into the Macintosh menubar.
1802
* The menubar is changed.
1804
*----------------------------------------------------------------------
1810
if (currentMenuBarName != NULL) {
1811
ckfree(currentMenuBarName);
1812
currentMenuBarName = NULL;
1814
currentMenuBarOwner = NULL;
1816
InsertMenu(tkAppleMenu, 0);
1817
InsertMenu(tkFileMenu, 0);
1818
InsertMenu(tkEditMenu, 0);
1819
if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) {
1820
Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL);
1821
menuBarFlags |= MENUBAR_REDRAW_PENDING;
1826
*----------------------------------------------------------------------
1828
* TkpSetMainMenubar --
1830
* Puts the menu associated with a window into the menubar. Should
1831
* only be called when the window is in front.
1837
* The menubar is changed.
1839
*----------------------------------------------------------------------
1844
Tcl_Interp *interp, /* The interpreter of the application */
1845
Tk_Window tkwin, /* The frame we are setting up */
1846
char *menuName) /* The name of the menu to put in front.
1847
* If NULL, use the default menu bar.
1850
TkWindow *winPtr = (TkWindow *) tkwin;
1851
WindowRef macWindowPtr = (WindowRef) TkMacGetDrawablePort(winPtr->window);
1853
if ((macWindowPtr == NULL) || (macWindowPtr != FrontWindow())) {
1857
if ((currentMenuBarInterp != interp)
1858
|| (currentMenuBarOwner != tkwin)
1859
|| (currentMenuBarName == NULL)
1860
|| (menuName == NULL)
1861
|| (strcmp(menuName, currentMenuBarName) != 0)) {
1862
Tk_Window searchWindow;
1863
TopLevelMenubarList *listPtr;
1865
if (currentMenuBarName != NULL) {
1866
ckfree(currentMenuBarName);
1869
if (menuName == NULL) {
1870
searchWindow = tkwin;
1871
if (strcmp(Tk_Class(searchWindow), "Menu") == 0) {
1872
TkMenuReferences *menuRefPtr;
1874
menuRefPtr = TkFindMenuReferences(interp, Tk_PathName(tkwin));
1875
if (menuRefPtr != NULL) {
1876
TkMenu *menuPtr = menuRefPtr->menuPtr;
1877
if (menuPtr != NULL) {
1878
menuPtr = menuPtr->masterMenuPtr;
1879
searchWindow = menuPtr->tkwin;
1883
for (; searchWindow != NULL;
1884
searchWindow = Tk_Parent(searchWindow)) {
1886
for (listPtr = windowListPtr; listPtr != NULL;
1887
listPtr = listPtr->nextPtr) {
1888
if (listPtr->tkwin == searchWindow) {
1892
if (listPtr != NULL) {
1893
menuName = Tk_PathName(listPtr->menuPtr->masterMenuPtr->tkwin);
1899
if (menuName == NULL) {
1900
currentMenuBarName = NULL;
1902
currentMenuBarName = ckalloc(strlen(menuName) + 1);
1903
strcpy(currentMenuBarName, menuName);
1905
currentMenuBarOwner = tkwin;
1906
currentMenuBarInterp = interp;
1908
if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) {
1909
Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL);
1910
menuBarFlags |= MENUBAR_REDRAW_PENDING;
1915
*----------------------------------------------------------------------
1917
* TkpSetWindowMenuBar --
1919
* Associates a given menu with a window.
1925
* On Windows and UNIX, associates the platform menu with the
1928
*----------------------------------------------------------------------
1932
TkpSetWindowMenuBar(
1933
Tk_Window tkwin, /* The window we are setting the menu in */
1934
TkMenu *menuPtr) /* The menu we are setting */
1936
TopLevelMenubarList *listPtr, *prevPtr;
1939
* Remove any existing reference to this window.
1942
for (prevPtr = NULL, listPtr = windowListPtr;
1944
prevPtr = listPtr, listPtr = listPtr->nextPtr) {
1945
if (listPtr->tkwin == tkwin) {
1950
if (listPtr != NULL) {
1951
if (prevPtr != NULL) {
1952
prevPtr->nextPtr = listPtr->nextPtr;
1954
windowListPtr = listPtr->nextPtr;
1956
ckfree((char *) listPtr);
1959
if (menuPtr != NULL) {
1960
listPtr = (TopLevelMenubarList *) ckalloc(sizeof(TopLevelMenubarList));
1961
listPtr->nextPtr = windowListPtr;
1962
windowListPtr = listPtr;
1963
listPtr->tkwin = tkwin;
1964
listPtr->menuPtr = menuPtr;
1969
*----------------------------------------------------------------------
1971
* TkMacDispatchMenuEvent --
1973
* Given a menu id and an item, dispatches the command associated
1980
* Commands get executed.
1982
*----------------------------------------------------------------------
1986
TkMacDispatchMenuEvent(
1987
int menuID, /* The menu id of the menu we are invoking */
1988
int index) /* The one-based index of the item that was
1991
int result = TCL_OK;
1993
if (menuID == kHMHelpMenuID) {
1994
if (currentMenuBarOwner != NULL) {
1995
TkMenuReferences *helpMenuRef;
1996
char *helpMenuName = ckalloc(strlen(currentMenuBarName)
1997
+ strlen(".help") + 1);
1998
sprintf(helpMenuName, "%s.help", currentMenuBarName);
1999
helpMenuRef = TkFindMenuReferences(currentMenuBarInterp,
2001
ckfree(helpMenuName);
2002
if ((helpMenuRef != NULL) && (helpMenuRef->menuPtr != NULL)) {
2003
int newIndex = index - helpItemCount - 1;
2004
result = TkInvokeMenu(currentMenuBarInterp,
2005
helpMenuRef->menuPtr, newIndex);
2009
Tcl_HashEntry *commandEntryPtr =
2010
Tcl_FindHashEntry(&commandTable, (char *) menuID);
2011
TkMenu *menuPtr = (TkMenu *) Tcl_GetHashValue(commandEntryPtr);
2012
if ((currentAppleMenuID == menuID)
2013
&& (index > menuPtr->numEntries + 1)) {
2016
GetMenuItemText(GetMenuHandle(menuID), index, itemText);
2017
OpenDeskAcc(itemText);
2020
result = TkInvokeMenu(menuPtr->interp, menuPtr, index - 1);
2028
*----------------------------------------------------------------------
2030
* GetMenuIndicatorGeometry --
2032
* Gets the width and height of the indicator area of a menu.
2035
* widthPtr and heightPtr are set.
2040
*----------------------------------------------------------------------
2044
GetMenuIndicatorGeometry (
2045
TkMenu *menuPtr, /* The menu we are drawing */
2046
TkMenuEntry *mePtr, /* The entry we are measuring */
2047
Tk_Font tkfont, /* Precalculated font */
2048
CONST Tk_FontMetrics *fmPtr, /* Precalculated font metrics */
2049
int *widthPtr, /* The resulting width */
2050
int *heightPtr) /* The resulting height */
2054
*heightPtr = fmPtr->linespace;
2056
markChar = (char) FindMarkCharacter(mePtr);
2057
*widthPtr = Tk_TextWidth(tkfont, &markChar, 1) + 4;
2061
*----------------------------------------------------------------------
2063
* GetMenuAccelGeometry --
2065
* Gets the width and height of the accelerator area of a menu.
2068
* widthPtr and heightPtr are set.
2073
*----------------------------------------------------------------------
2077
GetMenuAccelGeometry (
2078
TkMenu *menuPtr, /* The menu we are measuring */
2079
TkMenuEntry *mePtr, /* The entry we are measuring */
2080
Tk_Font tkfont, /* The precalculated font */
2081
CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */
2082
int *modWidthPtr, /* The width of all of the key
2083
* modifier symbols. */
2084
int *textWidthPtr, /* The resulting width */
2085
int *heightPtr) /* The resulting height */
2087
*heightPtr = fmPtr->linespace;
2089
if (mePtr->type == CASCADE_ENTRY) {
2090
*textWidthPtr = SICN_HEIGHT;
2091
*modWidthPtr = Tk_TextWidth(tkfont, "W", 1);
2092
} else if (0 == mePtr->accelLength) {
2096
if (NULL == GetResource('SICN', SICN_RESOURCE_NUMBER)) {
2097
*textWidthPtr = Tk_TextWidth(tkfont, mePtr->accel,
2098
mePtr->accelLength);
2100
int emWidth = Tk_TextWidth(tkfont, "W", 1) + 1;
2101
if ((mePtr->entryFlags & ENTRY_ACCEL_MASK) == 0) {
2102
int width = Tk_TextWidth(tkfont, mePtr->accel,
2103
mePtr->accelLength);
2104
*textWidthPtr = emWidth;
2105
if (width < emWidth) {
2108
*modWidthPtr = width - emWidth;
2111
int length = ((EntryGeometry *)mePtr->platformEntryData)
2113
if (mePtr->entryFlags & ENTRY_CONTROL_ACCEL) {
2114
*modWidthPtr += CONTROL_ICON_WIDTH;
2116
if (mePtr->entryFlags & ENTRY_SHIFT_ACCEL) {
2117
*modWidthPtr += SHIFT_ICON_WIDTH;
2119
if (mePtr->entryFlags & ENTRY_OPTION_ACCEL) {
2120
*modWidthPtr += OPTION_ICON_WIDTH;
2122
if (mePtr->entryFlags & ENTRY_COMMAND_ACCEL) {
2123
*modWidthPtr += COMMAND_ICON_WIDTH;
2125
if (1 == (mePtr->accelLength - length)) {
2126
*textWidthPtr = emWidth;
2128
*textWidthPtr += Tk_TextWidth(tkfont, mePtr->accel
2129
+ length, mePtr->accelLength - length);
2137
*----------------------------------------------------------------------
2139
* GetTearoffEntryGeometry --
2141
* Gets the width and height of of a tearoff entry.
2144
* widthPtr and heightPtr are set.
2149
*----------------------------------------------------------------------
2153
GetTearoffEntryGeometry (
2154
TkMenu *menuPtr, /* The menu we are drawing */
2155
TkMenuEntry *mePtr, /* The entry we are measuring */
2156
Tk_Font tkfont, /* The precalculated font */
2157
CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */
2158
int *widthPtr, /* The resulting width */
2159
int *heightPtr) /* The resulting height */
2161
if ((GetResource('MDEF', 591) == NULL) &&
2162
(menuPtr->menuType == MASTER_MENU)) {
2163
*heightPtr = fmPtr->linespace;
2166
*widthPtr = *heightPtr = 0;
2171
*----------------------------------------------------------------------
2173
* GetMenuSeparatorGeometry --
2175
* Gets the width and height of menu separator.
2178
* widthPtr and heightPtr are set.
2183
*----------------------------------------------------------------------
2187
GetMenuSeparatorGeometry(
2188
TkMenu *menuPtr, /* The menu we are drawing */
2189
TkMenuEntry *mePtr, /* The entry we are measuring */
2190
Tk_Font tkfont, /* The precalculated font */
2191
CONST Tk_FontMetrics *fmPtr, /* The precalcualted font metrics */
2192
int *widthPtr, /* The resulting width */
2193
int *heightPtr) /* The resulting height */
2195
if (TkMacHaveAppearance() > 1) {
2198
GetThemeMenuSeparatorHeight(&outHeight);
2200
*heightPtr = outHeight;
2203
*heightPtr = fmPtr->linespace;
2208
*----------------------------------------------------------------------
2210
* DrawMenuEntryIndicator --
2212
* This procedure draws the indicator part of a menu.
2218
* Commands are output to X to display the menu in its
2221
*----------------------------------------------------------------------
2225
DrawMenuEntryIndicator(
2226
TkMenu *menuPtr, /* The menu we are drawing */
2227
TkMenuEntry *mePtr, /* The entry we are drawing */
2228
Drawable d, /* The drawable we are drawing */
2229
GC gc, /* The GC we are drawing with */
2230
GC indicatorGC, /* The GC to use for the indicator */
2231
Tk_Font tkfont, /* The precalculated font */
2232
CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */
2233
int x, /* topleft hand corner of entry */
2234
int y, /* topleft hand corner of entry */
2235
int width, /* width of entry */
2236
int height) /* height of entry */
2238
if (((mePtr->type == CHECK_BUTTON_ENTRY) ||
2239
(mePtr->type == RADIO_BUTTON_ENTRY))
2240
&& (mePtr->indicatorOn)
2241
&& (mePtr->entryFlags & ENTRY_SELECTED)) {
2246
baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
2247
GetItemMark(((MacMenu *) menuPtr->platformData)->menuHdl,
2248
mePtr->index + 1, &markShort);
2249
if (markShort != 0) {
2250
markChar = (char) markShort;
2251
Tk_DrawChars(menuPtr->display, d, gc, tkfont, &markChar, 1,
2258
*----------------------------------------------------------------------
2260
* DrawMenuBackground --
2262
* If Appearance is present, draws the Appearance background
2268
* Commands are output to X to display the menu in its
2271
*----------------------------------------------------------------------
2275
Rect *menuRectPtr, /* The menu rect */
2276
Drawable d, /* What we are drawing into */
2277
ThemeMenuType type /* Type of menu */
2280
if (!TkMacHaveAppearance()) {
2284
GDHandle saveDevice;
2287
destPort = TkMacGetDrawablePort(d);
2288
GetGWorld(&saveWorld, &saveDevice);
2289
SetGWorld(destPort, NULL);
2290
TkMacSetUpClippingRgn(d);
2291
DrawThemeMenuBackground (menuRectPtr, type);
2292
SetGWorld(saveWorld, saveDevice);
2298
*----------------------------------------------------------------------
2302
* Given a resource id and an index, loads the appropriate SICN
2303
* and draws it into a given drawable using the given gc.
2306
* Returns 1 if the SICN was found, 0 if not found.
2309
* Commands are output to X to display the menu in its
2312
*----------------------------------------------------------------------
2316
int resourceID, /* The resource # of the SICN table */
2317
int index, /* The index into the SICN table of the
2319
Drawable d, /* What we are drawing into */
2320
GC gc, /* The GC to draw with */
2321
int x, /* The left hand coord of the SICN */
2322
int y) /* The top coord of the SICN */
2324
Handle sicnHandle = (Handle) GetResource('SICN', SICN_RESOURCE_NUMBER);
2326
if (NULL == sicnHandle) {
2332
GDHandle saveDevice;
2334
BitMapPtr destBitMap;
2335
RGBColor origForeColor, origBackColor, foreColor, backColor;
2338
destPort = TkMacGetDrawablePort(d);
2339
GetGWorld(&saveWorld, &saveDevice);
2340
SetGWorld(destPort, NULL);
2341
TkMacSetUpClippingRgn(d);
2342
TkMacSetUpGraphicsPort(gc);
2343
GetForeColor(&origForeColor);
2344
GetBackColor(&origBackColor);
2346
if (TkSetMacColor(gc->foreground, &foreColor) == true) {
2347
RGBForeColor(&foreColor);
2350
if (TkSetMacColor(gc->background, &backColor) == true) {
2351
RGBBackColor(&backColor);
2354
SetRect(&destRect, x, y, x + SICN_HEIGHT, y + SICN_HEIGHT);
2355
sicnBitmap.baseAddr = (Ptr) (*sicnHandle) + index * SICN_HEIGHT
2357
sicnBitmap.rowBytes = SICN_ROWS;
2358
SetRect(&sicnBitmap.bounds, 0, 0, 16, 16);
2359
destBitMap = &((GrafPtr) destPort)->portBits;
2360
CopyBits(&sicnBitmap, destBitMap, &sicnBitmap.bounds, &destRect,
2361
destPort->txMode, NULL);
2362
HUnlock(sicnHandle);
2363
RGBForeColor(&origForeColor);
2364
RGBBackColor(&origBackColor);
2365
SetGWorld(saveWorld, saveDevice);
2371
*----------------------------------------------------------------------
2373
* DrawMenuEntryAccelerator --
2375
* This procedure draws the accelerator part of a menu. We
2376
* need to decide what to draw here. Should we replace strings
2377
* like "Control", "Command", etc?
2383
* Commands are output to X to display the menu in its
2386
*----------------------------------------------------------------------
2390
DrawMenuEntryAccelerator(
2391
TkMenu *menuPtr, /* The menu we are drawing */
2392
TkMenuEntry *mePtr, /* The entry we are drawing */
2393
Drawable d, /* The drawable we are drawing in */
2394
GC gc, /* The gc to draw into */
2395
Tk_Font tkfont, /* The precalculated font */
2396
CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */
2397
Tk_3DBorder activeBorder, /* border for menu background */
2398
int x, /* The left side of the entry */
2399
int y, /* The top of the entry */
2400
int width, /* The width of the entry */
2401
int height, /* The height of the entry */
2402
int drawArrow) /* Whether or not to draw cascade arrow */
2404
if (mePtr->type == CASCADE_ENTRY) {
2406
* Under Appearance, we let the Appearance Manager draw the icon
2409
if (!TkMacHaveAppearance()) {
2410
if (0 == DrawSICN(SICN_RESOURCE_NUMBER, CASCADE_ARROW, d, gc,
2411
x + width - SICN_HEIGHT, (y + (height / 2))
2412
- (SICN_HEIGHT / 2))) {
2414
Tk_Window tkwin = menuPtr->tkwin;
2416
if (mePtr->type == CASCADE_ENTRY) {
2417
points[0].x = width - menuPtr->activeBorderWidth
2418
- MAC_MARGIN_WIDTH - CASCADE_ARROW_WIDTH;
2419
points[0].y = y + (height - CASCADE_ARROW_HEIGHT)/2;
2420
points[1].x = points[0].x;
2421
points[1].y = points[0].y + CASCADE_ARROW_HEIGHT;
2422
points[2].x = points[0].x + CASCADE_ARROW_WIDTH;
2423
points[2].y = points[0].y + CASCADE_ARROW_HEIGHT/2;
2424
Tk_Fill3DPolygon(menuPtr->tkwin, d, activeBorder, points,
2425
3, DECORATION_BORDER_WIDTH, TK_RELIEF_FLAT);
2429
} else if (mePtr->accelLength != 0) {
2430
int leftEdge = x + width;
2431
int baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
2433
if (NULL == GetResource('SICN', SICN_RESOURCE_NUMBER)) {
2434
leftEdge -= ((EntryGeometry *) mePtr->platformEntryData)
2436
Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel,
2437
mePtr->accelLength, leftEdge, baseline);
2439
EntryGeometry *geometryPtr =
2440
(EntryGeometry *) mePtr->platformEntryData;
2441
int length = mePtr->accelLength - geometryPtr->accelTextStart;
2443
leftEdge -= geometryPtr->accelTextWidth;
2444
if ((mePtr->entryFlags & ENTRY_ACCEL_MASK) == 0) {
2445
leftEdge -= geometryPtr->modifierWidth;
2448
Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel
2449
+ geometryPtr->accelTextStart, length, leftEdge, baseline);
2451
if (mePtr->entryFlags & ENTRY_COMMAND_ACCEL) {
2452
leftEdge -= COMMAND_ICON_WIDTH;
2453
DrawSICN(SICN_RESOURCE_NUMBER, COMMAND_ICON, d, gc,
2454
leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
2457
if (mePtr->entryFlags & ENTRY_OPTION_ACCEL) {
2458
leftEdge -= OPTION_ICON_WIDTH;
2459
DrawSICN(SICN_RESOURCE_NUMBER, OPTION_ICON, d, gc,
2460
leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
2463
if (mePtr->entryFlags & ENTRY_SHIFT_ACCEL) {
2464
leftEdge -= SHIFT_ICON_WIDTH;
2465
DrawSICN(SICN_RESOURCE_NUMBER, SHIFT_ICON, d, gc,
2466
leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
2469
if (mePtr->entryFlags & ENTRY_CONTROL_ACCEL) {
2470
leftEdge -= CONTROL_ICON_WIDTH;
2471
DrawSICN(SICN_RESOURCE_NUMBER, CONTROL_ICON, d, gc,
2472
leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
2479
*----------------------------------------------------------------------
2481
* DrawMenuSeparator --
2483
* The menu separator is drawn.
2489
* Commands are output to X to display the menu in its
2492
*----------------------------------------------------------------------
2497
TkMenu *menuPtr, /* The menu we are drawing */
2498
TkMenuEntry *mePtr, /* The entry we are drawing */
2499
Drawable d, /* The drawable we are drawing into */
2500
GC gc, /* The gc we are drawing with */
2501
Tk_Font tkfont, /* The precalculated font */
2502
CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */
2503
int x, /* left coordinate of entry */
2504
int y, /* top coordinate of entry */
2505
int width, /* width of entry */
2506
int height) /* height of entry */
2509
GDHandle saveDevice;
2512
destPort = TkMacGetDrawablePort(d);
2513
GetGWorld(&saveWorld, &saveDevice);
2514
SetGWorld(destPort, NULL);
2515
TkMacSetUpClippingRgn(d);
2516
if (TkMacHaveAppearance() > 1) {
2520
r.bottom = y + height;
2521
r.right = x + width;
2523
DrawThemeMenuSeparator(&r);
2526
* We don't want to use the text GC for drawing the separator. It
2527
* needs to be the same color as disabled items.
2530
TkMacSetUpGraphicsPort(mePtr->disabledGC != None ? mePtr->disabledGC
2531
: menuPtr->disabledGC);
2533
MoveTo(x, y + (height / 2));
2536
SetGWorld(saveWorld, saveDevice);
2541
*----------------------------------------------------------------------
2545
* This routine is the MDEF handler for Tk. It receives all messages
2546
* for the menu and dispatches them.
2552
* This routine causes menus to be drawn and will certainly allocate
2553
* memory as a result. Also, the menu can scroll up and down, and
2554
* various other interface actions can take place.
2556
*----------------------------------------------------------------------
2561
short message, /* What action are we taking? */
2562
MenuHandle menu, /* The menu we are working with */
2563
Rect *menuRectPtr, /* A pointer to the rect for the
2565
Point hitPt, /* Where the mouse was clicked for
2566
* the appropriate messages. */
2567
short *whichItem, /* Output result. Which item was
2568
* hit by the user? */
2569
TkMenuLowMemGlobals *globalsPtr) /* The low mem globals we have
2572
#define SCREEN_MARGIN 5
2574
TkMenuEntry *parentEntryPtr;
2575
Tcl_HashEntry *commandEntryPtr;
2576
GrafPtr windowMgrPort;
2578
Tk_FontMetrics fontMetrics, entryMetrics;
2579
Tk_FontMetrics *fmPtr;
2588
WindowRef whichWindow;
2591
RGBColor origFgColor;
2592
PenState origPenState;
2594
Rect scratchRect = {-32768, -32768, 32767, 32767};
2595
RgnHandle oldClipRgn;
2596
TkMenuReferences *menuRefPtr;
2597
TkMenu *searchMenuPtr;
2600
HLock((Handle) menu);
2601
commandEntryPtr = Tcl_FindHashEntry(&commandTable,
2602
(char *) (*menu)->menuID);
2603
HUnlock((Handle) menu);
2604
menuPtr = (TkMenu *) Tcl_GetHashValue(commandEntryPtr);
2608
GetWMgrPort(&windowMgrPort);
2609
maxMenuHeight = windowMgrPort->portRect.bottom
2610
- windowMgrPort->portRect.top
2611
- GetMBarHeight() - SCREEN_MARGIN;
2612
(*menu)->menuWidth = menuPtr->totalWidth;
2613
(*menu)->menuHeight = maxMenuHeight < menuPtr->totalHeight ?
2614
maxMenuHeight : menuPtr->totalHeight;
2620
* Store away the menu rectangle so we can keep track of the
2621
* different regions that the menu obscures.
2624
((MacMenu *) menuPtr->platformData)->menuRect = *menuRectPtr;
2625
if (tkMenuCascadeRgn == NULL) {
2626
tkMenuCascadeRgn = NewRgn();
2628
if (utilRgn == NULL) {
2631
if (totalMenuRgn == NULL) {
2632
totalMenuRgn = NewRgn();
2634
SetEmptyRgn(tkMenuCascadeRgn);
2635
for (searchMenuPtr = menuPtr; searchMenuPtr != NULL; ) {
2637
&((MacMenu *) searchMenuPtr->platformData)->menuRect);
2638
InsetRgn(utilRgn, -1, -1);
2639
UnionRgn(tkMenuCascadeRgn, utilRgn, tkMenuCascadeRgn);
2640
OffsetRgn(utilRgn, 1, 1);
2641
UnionRgn(tkMenuCascadeRgn, utilRgn, tkMenuCascadeRgn);
2643
if (searchMenuPtr->menuRefPtr->parentEntryPtr != NULL) {
2644
searchMenuPtr = searchMenuPtr->menuRefPtr
2645
->parentEntryPtr->menuPtr;
2649
if (searchMenuPtr->menuType == MENUBAR) {
2653
UnionRgn(totalMenuRgn, tkMenuCascadeRgn, totalMenuRgn);
2654
SetEmptyRgn(utilRgn);
2657
* Now draw the background if Appearance is present...
2660
GetGWorld(&macMDEFDrawable.portPtr, &device);
2661
if (TkMacHaveAppearance() > 1) {
2662
ThemeMenuType menuType;
2664
if (menuPtr->menuRefPtr->topLevelListPtr != NULL) {
2665
menuType = kThemeMenuTypePullDown;
2666
} else if (menuPtr->menuRefPtr->parentEntryPtr != NULL) {
2667
menuType = kThemeMenuTypeHierarchical;
2669
menuType = kThemeMenuTypePopUp;
2672
DrawMenuBackground(menuRectPtr, (Drawable) &macMDEFDrawable,
2677
* Next, figure out scrolling information.
2680
menuClipRect = *menuRectPtr;
2681
if ((menuClipRect.bottom - menuClipRect.top)
2682
< menuPtr->totalHeight) {
2683
if (globalsPtr->menuTop < menuRectPtr->top) {
2684
DrawSICN(SICN_RESOURCE_NUMBER, UP_ARROW,
2685
(Drawable) &macMDEFDrawable,
2688
+ menuPtr->entries[1]->indicatorSpace,
2690
menuClipRect.top += SICN_HEIGHT;
2692
if ((globalsPtr->menuTop + menuPtr->totalHeight)
2693
> menuRectPtr->bottom) {
2694
DrawSICN(SICN_RESOURCE_NUMBER, DOWN_ARROW,
2695
(Drawable) &macMDEFDrawable,
2698
+ menuPtr->entries[1]->indicatorSpace,
2699
menuRectPtr->bottom - SICN_HEIGHT);
2700
menuClipRect.bottom -= SICN_HEIGHT;
2706
* Now, actually draw the menu. Don't draw entries that
2707
* are higher than the top arrow, and don't draw entries
2708
* that are lower than the bottom.
2711
Tk_GetFontMetrics(menuPtr->tkfont, &fontMetrics);
2712
for (i = 0; i < menuPtr->numEntries; i++) {
2713
mePtr = menuPtr->entries[i];
2714
if (globalsPtr->menuTop + mePtr->y + mePtr->height
2715
< menuClipRect.top) {
2717
} else if (globalsPtr->menuTop + mePtr->y
2718
> menuClipRect.bottom) {
2721
/* ClipRect(&menuClipRect); */
2722
if (mePtr->tkfont == NULL) {
2723
fmPtr = &fontMetrics;
2724
tkfont = menuPtr->tkfont;
2726
tkfont = mePtr->tkfont;
2727
Tk_GetFontMetrics(tkfont, &entryMetrics);
2728
fmPtr = &entryMetrics;
2730
AppearanceEntryDrawWrapper(mePtr, menuRectPtr, globalsPtr,
2731
(Drawable) &macMDEFDrawable, fmPtr, tkfont,
2732
menuRectPtr->left + mePtr->x,
2733
globalsPtr->menuTop + mePtr->y,
2734
(mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
2735
menuPtr->totalWidth - mePtr->x : mePtr->width,
2736
menuPtr->entries[i]->height);
2738
globalsPtr->menuBottom = globalsPtr->menuTop
2739
+ menuPtr->totalHeight;
2740
if (!EmptyRgn(utilRgn)) {
2742
SetEmptyRgn(utilRgn);
2748
int hasTopScroll, hasBottomScroll;
2750
DONT_SCROLL, DOWN_SCROLL, UP_SCROLL
2754
RGBColor origForeColor, origBackColor, foreColor, backColor;
2756
GetGWorld(&macMDEFDrawable.portPtr, &device);
2757
GetForeColor(&origForeColor);
2758
GetBackColor(&origBackColor);
2760
if (TkSetMacColor(menuPtr->textGC->foreground,
2761
&foreColor) == true) {
2762
if (!TkMacHaveAppearance()) {
2763
RGBForeColor(&foreColor);
2766
if (TkSetMacColor(menuPtr->textGC->background,
2767
&backColor) == true) {
2768
if (!TkMacHaveAppearance()) {
2769
RGBBackColor(&backColor);
2774
* Find out which item was hit. If it is the same as the old item,
2775
* we don't need to do anything.
2778
oldItem = *whichItem - 1;
2780
if (PtInRect(hitPt, menuRectPtr)) {
2781
for (i = 0; i < menuPtr->numEntries; i++) {
2782
mePtr = menuPtr->entries[i];
2783
itemRect.left = menuRectPtr->left + mePtr->x;
2784
itemRect.top = globalsPtr->menuTop + mePtr->y;
2785
if (mePtr->entryFlags & ENTRY_LAST_COLUMN) {
2786
itemRect.right = itemRect.left + menuPtr->totalWidth
2789
itemRect.right = itemRect.left + mePtr->width;
2791
itemRect.bottom = itemRect.top
2792
+ menuPtr->entries[i]->height;
2793
if (PtInRect(hitPt, &itemRect)) {
2794
if ((mePtr->type == SEPARATOR_ENTRY)
2795
|| (mePtr->state == tkDisabledUid)) {
2798
TkMenuEntry *cascadeEntryPtr;
2799
int parentDisabled = 0;
2801
for (cascadeEntryPtr
2802
= menuPtr->menuRefPtr->parentEntryPtr;
2803
cascadeEntryPtr != NULL;
2805
= cascadeEntryPtr->nextCascadePtr) {
2806
if (strcmp(cascadeEntryPtr->name,
2807
Tk_PathName(menuPtr->tkwin)) == 0) {
2808
if (cascadeEntryPtr->state
2815
if (parentDisabled) {
2819
if ((mePtr->type == CASCADE_ENTRY)
2820
&& (oldItem != newItem)) {
2821
globalsPtr->itemRect = itemRect;
2831
* Now we need to take care of scrolling the menu.
2834
hasTopScroll = globalsPtr->menuTop < menuRectPtr->top;
2835
hasBottomScroll = globalsPtr->menuBottom > menuRectPtr->bottom;
2836
scrollDirection = DONT_SCROLL;
2838
&& (hitPt.v < menuRectPtr->top + SICN_HEIGHT)) {
2840
scrollDirection = DOWN_SCROLL;
2841
} else if (hasBottomScroll
2842
&& (hitPt.v > menuRectPtr->bottom - SICN_HEIGHT)) {
2844
scrollDirection = UP_SCROLL;
2846
menuClipRect = *menuRectPtr;
2848
menuClipRect.top += SICN_HEIGHT;
2850
if (hasBottomScroll) {
2851
menuClipRect.bottom -= SICN_HEIGHT;
2853
if (MDEFScrollFlag) {
2854
scrollDirection = DONT_SCROLL;
2858
ClipRect(&menuClipRect);
2860
if (oldItem != newItem) {
2862
mePtr = menuPtr->entries[oldItem];
2863
tkfont = mePtr->tkfont ? mePtr->tkfont : menuPtr->tkfont;
2864
Tk_GetFontMetrics(tkfont, &fontMetrics);
2865
AppearanceEntryDrawWrapper(mePtr, menuRectPtr, globalsPtr,
2866
(Drawable) &macMDEFDrawable, &fontMetrics, tkfont,
2867
menuRectPtr->left + mePtr->x,
2868
globalsPtr->menuTop + mePtr->y,
2869
(mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
2870
menuPtr->totalWidth - mePtr->x : mePtr->width,
2873
if (newItem != -1) {
2874
int oldActiveItem = menuPtr->active;
2876
mePtr = menuPtr->entries[newItem];
2877
if (mePtr->state != tkDisabledUid) {
2878
TkActivateMenuEntry(menuPtr, newItem);
2880
tkfont = mePtr->tkfont ? mePtr->tkfont : menuPtr->tkfont;
2881
Tk_GetFontMetrics(tkfont, &fontMetrics);
2882
AppearanceEntryDrawWrapper(mePtr, menuRectPtr, globalsPtr,
2883
(Drawable) &macMDEFDrawable, &fontMetrics, tkfont,
2884
menuRectPtr->left + mePtr->x,
2885
globalsPtr->menuTop + mePtr->y,
2886
(mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
2887
menuPtr->totalWidth - mePtr->x : mePtr->width,
2891
tkUseMenuCascadeRgn = 1;
2892
MenuSelectEvent(menuPtr);
2894
tkUseMenuCascadeRgn = 0;
2895
if (mePtr->state != tkDisabledUid) {
2896
TkActivateMenuEntry(menuPtr, -1);
2898
*whichItem = newItem + 1;
2900
globalsPtr->menuDisable = ((*menu)->menuID << 16) | (newItem + 1);
2902
if (scrollDirection == UP_SCROLL) {
2903
scrollAmt = menuClipRect.bottom - hitPt.v;
2904
if (scrollAmt < menuRectPtr->bottom
2905
- globalsPtr->menuBottom) {
2906
scrollAmt = menuRectPtr->bottom - globalsPtr->menuBottom;
2908
if (!hasTopScroll && ((globalsPtr->menuTop + scrollAmt) < menuRectPtr->top)) {
2909
SetRect(&updateRect, menuRectPtr->left,
2910
globalsPtr->menuTop, menuRectPtr->right,
2911
globalsPtr->menuTop + SICN_HEIGHT);
2912
EraseRect(&updateRect);
2913
DrawSICN(SICN_RESOURCE_NUMBER, UP_ARROW,
2914
(Drawable) &macMDEFDrawable,
2915
menuPtr->textGC, menuRectPtr->left
2916
+ menuPtr->entries[1]->indicatorSpace,
2918
menuClipRect.top += SICN_HEIGHT;
2920
} else if (scrollDirection == DOWN_SCROLL) {
2921
scrollAmt = menuClipRect.top - hitPt.v;
2922
if (scrollAmt > menuRectPtr->top - globalsPtr->menuTop) {
2923
scrollAmt = menuRectPtr->top - globalsPtr->menuTop;
2925
if (!hasBottomScroll && ((globalsPtr->menuBottom + scrollAmt)
2926
> menuRectPtr->bottom)) {
2927
SetRect(&updateRect, menuRectPtr->left,
2928
globalsPtr->menuBottom - SICN_HEIGHT,
2929
menuRectPtr->right, globalsPtr->menuBottom);
2930
EraseRect(&updateRect);
2931
DrawSICN(SICN_RESOURCE_NUMBER, DOWN_ARROW,
2932
(Drawable) &macMDEFDrawable,
2933
menuPtr->textGC, menuRectPtr->left
2934
+ menuPtr->entries[1]->indicatorSpace,
2935
menuRectPtr->bottom - SICN_HEIGHT);
2936
menuClipRect.bottom -= SICN_HEIGHT;
2939
if (scrollDirection != DONT_SCROLL) {
2940
RgnHandle updateRgn = NewRgn();
2941
ScrollRect(&menuClipRect, 0, scrollAmt, updateRgn);
2942
updateRect = (*updateRgn)->rgnBBox;
2943
DisposeRgn(updateRgn);
2944
globalsPtr->menuTop += scrollAmt;
2945
globalsPtr->menuBottom += scrollAmt;
2946
if (globalsPtr->menuTop == menuRectPtr->top) {
2947
updateRect.top -= SICN_HEIGHT;
2949
if (globalsPtr->menuBottom == menuRectPtr->bottom) {
2950
updateRect.bottom += SICN_HEIGHT;
2952
ClipRect(&updateRect);
2953
EraseRect(&updateRect);
2954
Tk_GetFontMetrics(menuPtr->tkfont, &fontMetrics);
2955
for (i = 0; i < menuPtr->numEntries; i++) {
2956
mePtr = menuPtr->entries[i];
2957
if (globalsPtr->menuTop + mePtr->y + mePtr->height
2960
} else if (globalsPtr->menuTop + mePtr->y
2961
> updateRect.bottom) {
2964
if (mePtr->tkfont == NULL) {
2965
fmPtr = &fontMetrics;
2966
tkfont = menuPtr->tkfont;
2968
tkfont = mePtr->tkfont;
2969
Tk_GetFontMetrics(tkfont, &entryMetrics);
2970
fmPtr = &entryMetrics;
2972
AppearanceEntryDrawWrapper(mePtr, menuRectPtr, globalsPtr,
2973
(Drawable) &macMDEFDrawable, fmPtr, tkfont,
2974
menuRectPtr->left + mePtr->x,
2975
globalsPtr->menuTop + mePtr->y,
2976
(mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
2977
menuPtr->totalWidth - mePtr->x : mePtr->width,
2978
menuPtr->entries[i]->height);
2983
SetEmptyRgn(utilRgn);
2984
RGBForeColor(&origForeColor);
2985
RGBBackColor(&origBackColor);
2988
* If the menu is a tearoff, and the mouse is outside the menu,
2989
* we need to draw the drag rectangle.
2991
* In order for tearoffs to work properly, we need to set
2992
* the active member of the containing menubar.
2995
menuRefPtr = TkFindMenuReferences(menuPtr->interp,
2996
Tk_PathName(menuPtr->tkwin));
2997
if ((menuRefPtr != NULL) && (menuRefPtr->parentEntryPtr != NULL)) {
2998
for (parentEntryPtr = menuRefPtr->parentEntryPtr;
2999
strcmp(parentEntryPtr->name,
3000
Tk_PathName(menuPtr->tkwin)) == 0;
3001
parentEntryPtr = parentEntryPtr->nextCascadePtr) {
3003
if (parentEntryPtr != NULL) {
3004
TkActivateMenuEntry(parentEntryPtr->menuPtr,
3005
parentEntryPtr->index);
3009
if (menuPtr->tearOff) {
3010
scratchRect = *menuRectPtr;
3011
if (tearoffStruct.menuPtr == NULL) {
3012
scratchRect.top -= 10;
3013
scratchRect.bottom += 10;
3014
scratchRect.left -= 10;
3015
scratchRect.right += 10;
3018
windowPart = FindWindow(hitPt, &whichWindow);
3019
if ((windowPart != inMenuBar) && (newItem == -1)
3020
&& (hitPt.v != 0) && (hitPt.h != 0)
3021
&& (!PtInRect(hitPt, &scratchRect))
3022
&& (!PtInRect(hitPt, &tearoffStruct.excludeRect))) {
3024
* This is the second argument to the Toolbox Delay function. It changed
3025
* from long to unsigned long between Universal Headers 2.0 & 3.0
3027
#if !defined(UNIVERSAL_INTERFACES_VERSION) || (UNIVERSAL_INTERFACES_VERSION < 0x0300)
3030
unsigned long dummy;
3032
oldClipRgn = NewRgn();
3033
GetClip(oldClipRgn);
3034
GetForeColor(&origFgColor);
3035
GetPenState(&origPenState);
3036
GetForeColor(&fgColor);
3037
GetBackColor(&bgColor);
3038
GetGray(device, &bgColor, &fgColor);
3039
RGBForeColor(&fgColor);
3040
SetRect(&scratchRect, -32768, -32768, 32767, 32767);
3041
ClipRect(&scratchRect);
3043
dragRect = *menuRectPtr;
3044
tearoffStruct.menuPtr = menuPtr;
3047
dragRect = *menuRectPtr;
3048
OffsetRect(&dragRect, -dragRect.left, -dragRect.top);
3049
OffsetRect(&dragRect, tearoffStruct.point.h,
3050
tearoffStruct.point.v);
3051
if ((dragRect.top != 0) && (dragRect.left != 0)) {
3052
FrameRect(&dragRect);
3054
FrameRect(&dragRect);
3056
tearoffStruct.point = hitPt;
3058
SetClip(oldClipRgn);
3059
DisposeRgn(oldClipRgn);
3060
RGBForeColor(&origFgColor);
3061
SetPenState(&origPenState);
3063
tearoffStruct.menuPtr = NULL;
3064
tearoffStruct.point.h = tearoffStruct.point.v = 0;
3067
tearoffStruct.menuPtr = NULL;
3068
tearoffStruct.point.h = tearoffStruct.point.v = 0;
3077
* Note that for some oddball reason, h and v are reversed in the
3078
* point given to us by the MDEF.
3081
oldItem = *whichItem;
3082
if (oldItem >= menuPtr->numEntries) {
3085
GetWMgrPort(&windowMgrPort);
3086
maxMenuHeight = windowMgrPort->portRect.bottom
3087
- windowMgrPort->portRect.top
3088
- GetMBarHeight() - SCREEN_MARGIN;
3089
if (menuPtr->totalHeight > maxMenuHeight) {
3090
menuRectPtr->top = GetMBarHeight();
3092
menuRectPtr->top = hitPt.h;
3094
menuRectPtr->top -= menuPtr->entries[oldItem]->y;
3096
if (menuRectPtr->top + menuPtr->totalHeight > maxMenuHeight) {
3097
menuRectPtr->top -= maxMenuHeight - menuPtr->totalHeight;
3100
menuRectPtr->left = hitPt.v;
3101
menuRectPtr->right = menuRectPtr->left + menuPtr->totalWidth;
3102
menuRectPtr->bottom = menuRectPtr->top +
3103
((maxMenuHeight < menuPtr->totalHeight)
3104
? maxMenuHeight : menuPtr->totalHeight);
3105
if (menuRectPtr->top == GetMBarHeight()) {
3106
*whichItem = hitPt.h;
3108
*whichItem = menuRectPtr->top;
3115
*----------------------------------------------------------------------
3117
* AppearanceEntryDrawWrapper --
3119
* This routine wraps the TkpDrawMenuEntry function. Under Appearance,
3120
* it routes to the Appearance Managers DrawThemeEntry, otherwise it
3121
* just goes straight to TkpDrawMenuEntry.
3124
* A menu entry is drawn
3129
*----------------------------------------------------------------------
3132
AppearanceEntryDrawWrapper(
3135
TkMenuLowMemGlobals *globalsPtr,
3137
Tk_FontMetrics *fmPtr,
3144
if (TkMacHaveAppearance() > 1) {
3145
MenuEntryUserData meData;
3147
ThemeMenuState theState;
3148
ThemeMenuItemType theType;
3150
meData.mePtr = mePtr;
3151
meData.mdefDrawable = d;
3152
meData.fmPtr = fmPtr;
3153
meData.tkfont = tkfont;
3157
itemRect.bottom = itemRect.top + height;
3158
itemRect.right = itemRect.left + width;
3160
if (mePtr->state == tkActiveUid) {
3161
theState = kThemeMenuSelected;
3162
} else if (mePtr->state == tkDisabledUid) {
3163
theState = kThemeMenuDisabled;
3165
theState = kThemeMenuActive;
3168
if (mePtr->type == CASCADE_ENTRY) {
3169
theType = kThemeMenuItemHierarchical;
3171
theType = kThemeMenuItemPlain;
3174
DrawThemeMenuItem (menuRectPtr, &itemRect,
3175
globalsPtr->menuTop, globalsPtr->menuBottom, theState,
3176
theType, tkThemeMenuItemDrawingUPP,
3177
(unsigned long) &meData);
3180
TkpDrawMenuEntry(mePtr, d, tkfont, fmPtr,
3181
x, y, width, height, 0, 1);
3186
*----------------------------------------------------------------------
3188
* tkThemeMenuItemDrawingProc --
3190
* This routine is called from the Appearance DrawThemeMenuEntry
3193
* A menu entry is drawn
3198
*----------------------------------------------------------------------
3201
tkThemeMenuItemDrawingProc (
3202
const Rect *inBounds,
3204
Boolean inIsColorDevice,
3207
MenuEntryUserData *meData = (MenuEntryUserData *) inUserData;
3209
TkpDrawMenuEntry(meData->mePtr, meData->mdefDrawable,
3210
meData->tkfont, meData->fmPtr, inBounds->left,
3211
inBounds->top, inBounds->right - inBounds->left,
3212
inBounds->bottom - inBounds->top, 0, 1);
3217
*----------------------------------------------------------------------
3219
* TkMacHandleTearoffMenu() --
3221
* This routine sees if the MDEF has set a menu and a mouse position
3222
* for tearing off and makes a tearoff menu if it has.
3225
* menuPtr->interp will have the result of the tearoff command.
3228
* A new tearoff menu is created if it is supposed to be.
3230
*----------------------------------------------------------------------
3234
TkMacHandleTearoffMenu(void)
3236
if (tearoffStruct.menuPtr != NULL) {
3237
Tcl_DString tearoffCmdStr;
3240
WindowRef whichWindow;
3242
windowPart = FindWindow(tearoffStruct.point, &whichWindow);
3244
if (windowPart != inMenuBar) {
3245
Tcl_DStringInit(&tearoffCmdStr);
3246
Tcl_DStringAppendElement(&tearoffCmdStr, "tkTearOffMenu");
3247
Tcl_DStringAppendElement(&tearoffCmdStr,
3248
Tk_PathName(tearoffStruct.menuPtr->tkwin));
3249
sprintf(intString, "%d", tearoffStruct.point.h);
3250
Tcl_DStringAppendElement(&tearoffCmdStr, intString);
3251
sprintf(intString, "%d", tearoffStruct.point.v);
3252
Tcl_DStringAppendElement(&tearoffCmdStr, intString);
3253
Tcl_Eval(tearoffStruct.menuPtr->interp,
3254
Tcl_DStringValue(&tearoffCmdStr));
3255
Tcl_DStringFree(&tearoffCmdStr);
3256
tearoffStruct.menuPtr = NULL;
3262
*--------------------------------------------------------------
3264
* TkpInitializeMenuBindings --
3266
* For every interp, initializes the bindings for Windows
3267
* menus. Does nothing on Mac or XWindows.
3273
* C-level bindings are setup for the interp which will
3274
* handle Alt-key sequences for menus without beeping
3275
* or interfering with user-defined Alt-key bindings.
3277
*--------------------------------------------------------------
3281
TkpInitializeMenuBindings(interp, bindingTable)
3282
Tcl_Interp *interp; /* The interpreter to set. */
3283
Tk_BindingTable bindingTable; /* The table to add to. */
3291
*--------------------------------------------------------------
3293
* TkpComputeMenubarGeometry --
3295
* This procedure is invoked to recompute the size and
3296
* layout of a menu that is a menubar clone.
3302
* Fields of menu entries are changed to reflect their
3303
* current positions, and the size of the menu window
3304
* itself may be changed.
3306
*--------------------------------------------------------------
3310
TkpComputeMenubarGeometry(menuPtr)
3311
TkMenu *menuPtr; /* Structure describing menu. */
3313
TkpComputeStandardMenuGeometry(menuPtr);
3317
*----------------------------------------------------------------------
3319
* DrawTearoffEntry --
3321
* This procedure draws the background part of a menu.
3327
* Commands are output to X to display the menu in its
3330
*----------------------------------------------------------------------
3335
TkMenu *menuPtr, /* The menu we are drawing */
3336
TkMenuEntry *mePtr, /* The entry we are drawing */
3337
Drawable d, /* The drawable we are drawing into */
3338
GC gc, /* The gc we are drawing with */
3339
Tk_Font tkfont, /* The font we are drawing with */
3340
CONST Tk_FontMetrics *fmPtr, /* The metrics we are drawing with */
3341
int x, /* Left edge of entry. */
3342
int y, /* Top edge of entry. */
3343
int width, /* Width of entry. */
3344
int height) /* Height of entry. */
3347
int margin, segmentWidth, maxX;
3349
if ((menuPtr->menuType != MASTER_MENU) || (FixMDEF() != NULL)) {
3353
margin = (fmPtr->ascent + fmPtr->descent)/2;
3355
points[0].y = y + height/2;
3356
points[1].y = points[0].y;
3360
while (points[0].x < maxX) {
3361
points[1].x = points[0].x + segmentWidth;
3362
if (points[1].x > maxX) {
3365
Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 2, 1,
3367
points[0].x += 2*segmentWidth;
3372
*----------------------------------------------------------------------
3374
* TkMacSetHelpMenuItemCount --
3376
* Has to be called after the first call to InsertMenu. Sets
3377
* up the global variable for the number of items in the
3378
* unmodified help menu.
3384
* Sets the global helpItemCount.
3386
*----------------------------------------------------------------------
3390
TkMacSetHelpMenuItemCount()
3392
MenuHandle helpMenuHandle;
3394
if ((HMGetHelpMenuHandle(&helpMenuHandle) != noErr)
3395
|| (helpMenuHandle == NULL)) {
3398
helpItemCount = CountMItems(helpMenuHandle);
3399
DeleteMenuItem(helpMenuHandle, helpItemCount);
3404
*----------------------------------------------------------------------
3408
* Prepares a menubar for MenuSelect or MenuKey.
3414
* Any pending configurations of the menubar are completed.
3416
*----------------------------------------------------------------------
3423
TkMenuReferences *menuRefPtr;
3425
if ((currentMenuBarInterp != NULL) && (currentMenuBarName != NULL)) {
3426
menuRefPtr = TkFindMenuReferences(currentMenuBarInterp,
3427
currentMenuBarName);
3428
for (menuPtr = menuRefPtr->menuPtr->masterMenuPtr;
3429
menuPtr != NULL; menuPtr = menuPtr->nextInstancePtr) {
3430
if (menuPtr->menuType == MENUBAR) {
3431
CompleteIdlers(menuPtr);
3437
if (menuBarFlags & MENUBAR_REDRAW_PENDING) {
3438
Tcl_CancelIdleCall(DrawMenuBarWhenIdle, (ClientData *) NULL);
3439
DrawMenuBarWhenIdle((ClientData *) NULL);
3444
*----------------------------------------------------------------------
3446
* TkpDrawMenuEntry --
3448
* Draws the given menu entry at the given coordinates with the
3455
* X Server commands are executed to display the menu entry.
3457
*----------------------------------------------------------------------
3462
TkMenuEntry *mePtr, /* The entry to draw */
3463
Drawable d, /* What to draw into */
3464
Tk_Font tkfont, /* Precalculated font for menu */
3465
CONST Tk_FontMetrics *menuMetricsPtr,
3466
/* Precalculated metrics for menu */
3467
int x, /* X-coordinate of topleft of entry */
3468
int y, /* Y-coordinate of topleft of entry */
3469
int width, /* Width of the entry rectangle */
3470
int height, /* Height of the current rectangle */
3471
int strictMotif, /* Boolean flag */
3472
int drawArrow) /* Whether or not to draw the cascade
3473
* arrow for cascade items. Only applies
3477
TkMenu *menuPtr = mePtr->menuPtr;
3478
Tk_3DBorder bgBorder, activeBorder;
3479
CONST Tk_FontMetrics *fmPtr;
3480
Tk_FontMetrics entryMetrics;
3481
int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0;
3482
int adjustedY = y + padY;
3483
int adjustedHeight = height - 2 * padY;
3486
* Choose the gc for drawing the foreground part of the entry.
3487
* Under Appearance, we pass a null (appearanceGC) to tell
3488
* ourselves not to change whatever color the appearance manager has set.
3491
if ((mePtr->state == tkActiveUid)
3493
gc = mePtr->activeGC;
3495
if ((TkMacHaveAppearance() > 1) && (menuPtr->menuType != TEAROFF_MENU)) {
3496
SetThemeTextColor(kThemeSelectedMenuItemTextColor,32,true);
3499
gc = menuPtr->activeGC;
3503
TkMenuEntry *cascadeEntryPtr;
3504
int parentDisabled = 0;
3506
for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
3507
cascadeEntryPtr != NULL;
3508
cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
3509
if (strcmp(cascadeEntryPtr->name,
3510
Tk_PathName(menuPtr->tkwin)) == 0) {
3511
if (cascadeEntryPtr->state == tkDisabledUid) {
3518
if (((parentDisabled || (mePtr->state == tkDisabledUid)))
3519
&& (menuPtr->disabledFg != NULL)) {
3520
gc = mePtr->disabledGC;
3522
if ((TkMacHaveAppearance() > 1) && (mePtr->bitmap == NULL)) {
3523
SetThemeTextColor(kThemeDisabledMenuItemTextColor,32,true);
3526
gc = menuPtr->disabledGC;
3532
if ((TkMacHaveAppearance() > 1) && (mePtr->bitmap == NULL)) {
3533
SetThemeTextColor(kThemeActiveMenuItemTextColor,32,true);
3536
gc = menuPtr->textGC;
3542
indicatorGC = mePtr->indicatorGC;
3543
if (indicatorGC == NULL) {
3544
indicatorGC = menuPtr->indicatorGC;
3547
bgBorder = mePtr->border;
3548
if (bgBorder == NULL) {
3549
bgBorder = menuPtr->border;
3552
activeBorder = bgBorder;
3554
activeBorder = mePtr->activeBorder;
3555
if (activeBorder == NULL) {
3556
activeBorder = menuPtr->activeBorder;
3560
if (mePtr->tkfont == NULL) {
3561
fmPtr = menuMetricsPtr;
3563
tkfont = mePtr->tkfont;
3564
Tk_GetFontMetrics(tkfont, &entryMetrics);
3565
fmPtr = &entryMetrics;
3569
* Need to draw the entire background, including padding. On Unix,
3570
* for menubars, we have to draw the rest of the entry taking
3571
* into account the padding.
3574
DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder,
3575
bgBorder, x, y, width, height);
3577
if (mePtr->type == SEPARATOR_ENTRY) {
3578
DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont,
3579
fmPtr, x, adjustedY, width, adjustedHeight);
3580
} else if (mePtr->type == TEAROFF_ENTRY) {
3581
DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,
3582
width, adjustedHeight);
3584
DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x,
3585
adjustedY, width, adjustedHeight);
3586
DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,
3587
activeBorder, x, adjustedY, width, adjustedHeight, drawArrow);
3588
if (!mePtr->hideMargin) {
3589
DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont,
3590
fmPtr, x, adjustedY, width, adjustedHeight);
3597
*--------------------------------------------------------------
3599
* TkpComputeStandardMenuGeometry --
3601
* This procedure is invoked to recompute the size and
3602
* layout of a menu that is not a menubar clone.
3608
* Fields of menu entries are changed to reflect their
3609
* current positions, and the size of the menu window
3610
* itself may be changed.
3612
*--------------------------------------------------------------
3616
TkpComputeStandardMenuGeometry(
3617
TkMenu *menuPtr) /* Structure describing menu. */
3620
Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
3621
int x, y, height, modifierWidth, labelWidth, indicatorSpace;
3622
int windowWidth, windowHeight, accelWidth, maxAccelTextWidth;
3623
int i, j, lastColumnBreak, maxModifierWidth, maxWidth, nonAccelMargin;
3624
int maxNonAccelMargin, maxEntryWithAccelWidth, maxEntryWithoutAccelWidth;
3625
int entryWidth, maxIndicatorSpace;
3626
TkMenuEntry *mePtr, *columnEntryPtr;
3627
EntryGeometry *geometryPtr;
3629
if (menuPtr->tkwin == NULL) {
3633
x = y = menuPtr->borderWidth;
3634
indicatorSpace = labelWidth = accelWidth = maxAccelTextWidth = 0;
3635
windowHeight = windowWidth = maxWidth = lastColumnBreak = 0;
3636
maxModifierWidth = nonAccelMargin = maxNonAccelMargin = 0;
3637
maxEntryWithAccelWidth = maxEntryWithoutAccelWidth = 0;
3638
maxIndicatorSpace = 0;
3641
* On the Mac especially, getting font metrics can be quite slow,
3642
* so we want to do it intelligently. We are going to precalculate
3643
* them and pass them down to all of the measuring and drawing
3644
* routines. We will measure the font metrics of the menu once.
3645
* If an entry does not have its own font set, then we give
3646
* the geometry/drawing routines the menu's font and metrics.
3647
* If an entry has its own font, we will measure that font and
3648
* give all of the geometry/drawing the entry's font and metrics.
3651
Tk_GetFontMetrics(menuPtr->tkfont, &menuMetrics);
3653
for (i = 0; i < menuPtr->numEntries; i++) {
3654
mePtr = menuPtr->entries[i];
3655
tkfont = mePtr->tkfont;
3656
if (tkfont == NULL) {
3657
tkfont = menuPtr->tkfont;
3658
fmPtr = &menuMetrics;
3660
Tk_GetFontMetrics(tkfont, &entryMetrics);
3661
fmPtr = &entryMetrics;
3664
if ((i > 0) && mePtr->columnBreak) {
3665
if (maxIndicatorSpace != 0) {
3666
maxIndicatorSpace += 2;
3668
for (j = lastColumnBreak; j < i; j++) {
3669
columnEntryPtr = menuPtr->entries[j];
3671
(EntryGeometry *) columnEntryPtr->platformEntryData;
3673
columnEntryPtr->indicatorSpace = maxIndicatorSpace;
3674
columnEntryPtr->width = maxIndicatorSpace + maxWidth
3675
+ 2 * menuPtr->activeBorderWidth;
3676
geometryPtr->accelTextWidth = maxAccelTextWidth;
3677
geometryPtr->modifierWidth = maxModifierWidth;
3678
columnEntryPtr->x = x;
3679
columnEntryPtr->entryFlags &= ~ENTRY_LAST_COLUMN;
3680
if (maxEntryWithoutAccelWidth > maxEntryWithAccelWidth) {
3681
geometryPtr->nonAccelMargin = maxEntryWithoutAccelWidth
3682
- maxEntryWithAccelWidth;
3683
if (geometryPtr->nonAccelMargin > maxNonAccelMargin) {
3684
geometryPtr->nonAccelMargin = maxNonAccelMargin;
3687
geometryPtr->nonAccelMargin = 0;
3690
x += maxIndicatorSpace + maxWidth + 2 * menuPtr->borderWidth;
3692
maxWidth = maxIndicatorSpace = maxAccelTextWidth = 0;
3693
maxModifierWidth = maxNonAccelMargin = maxEntryWithAccelWidth = 0;
3694
maxEntryWithoutAccelWidth = 0;
3695
lastColumnBreak = i;
3696
y = menuPtr->borderWidth;
3699
if (mePtr->type == SEPARATOR_ENTRY) {
3700
GetMenuSeparatorGeometry(menuPtr, mePtr, tkfont,
3701
fmPtr, &entryWidth, &height);
3702
mePtr->height = height;
3703
} else if (mePtr->type == TEAROFF_ENTRY) {
3704
GetTearoffEntryGeometry(menuPtr, mePtr, tkfont,
3705
fmPtr, &entryWidth, &height);
3706
mePtr->height = height;
3710
* For each entry, compute the height required by that
3711
* particular entry, plus three widths: the width of the
3712
* label, the width to allow for an indicator to be displayed
3713
* to the left of the label (if any), and the width of the
3714
* accelerator to be displayed to the right of the label
3715
* (if any). These sizes depend, of course, on the type
3719
GetMenuLabelGeometry(mePtr, tkfont, fmPtr, &labelWidth,
3721
mePtr->height = height;
3723
if (mePtr->type == CASCADE_ENTRY) {
3724
GetMenuAccelGeometry(menuPtr, mePtr, tkfont, fmPtr,
3725
&modifierWidth, &accelWidth, &height);
3727
} else if (mePtr->accelLength == 0) {
3728
nonAccelMargin = mePtr->hideMargin ? 0
3729
: Tk_TextWidth(tkfont, "m", 1);
3730
accelWidth = modifierWidth = 0;
3732
labelWidth += Tk_TextWidth(tkfont, "m", 1);
3733
GetMenuAccelGeometry(menuPtr, mePtr, tkfont,
3734
fmPtr, &modifierWidth, &accelWidth, &height);
3735
if (height > mePtr->height) {
3736
mePtr->height = height;
3741
if (!(mePtr->hideMargin)) {
3742
GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont,
3743
fmPtr, &indicatorSpace, &height);
3744
if (height > mePtr->height) {
3745
mePtr->height = height;
3751
if (nonAccelMargin > maxNonAccelMargin) {
3752
maxNonAccelMargin = nonAccelMargin;
3754
if (accelWidth > maxAccelTextWidth) {
3755
maxAccelTextWidth = accelWidth;
3757
if (modifierWidth > maxModifierWidth) {
3758
maxModifierWidth = modifierWidth;
3760
if (indicatorSpace > maxIndicatorSpace) {
3761
maxIndicatorSpace = indicatorSpace;
3764
entryWidth = labelWidth + modifierWidth + accelWidth
3767
if (entryWidth > maxWidth) {
3768
maxWidth = entryWidth;
3771
if (mePtr->accelLength > 0) {
3772
if (entryWidth > maxEntryWithAccelWidth) {
3773
maxEntryWithAccelWidth = entryWidth;
3776
if (entryWidth > maxEntryWithoutAccelWidth) {
3777
maxEntryWithoutAccelWidth = entryWidth;
3781
mePtr->height += 2 * menuPtr->activeBorderWidth;
3784
y += menuPtr->entries[i]->height + menuPtr->borderWidth;
3785
if (y > windowHeight) {
3790
for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {
3791
columnEntryPtr = menuPtr->entries[j];
3792
geometryPtr = (EntryGeometry *) columnEntryPtr->platformEntryData;
3794
columnEntryPtr->indicatorSpace = maxIndicatorSpace;
3795
columnEntryPtr->width = maxIndicatorSpace + maxWidth
3796
+ 2 * menuPtr->activeBorderWidth;
3797
geometryPtr->accelTextWidth = maxAccelTextWidth;
3798
geometryPtr->modifierWidth = maxModifierWidth;
3799
columnEntryPtr->x = x;
3800
columnEntryPtr->entryFlags |= ENTRY_LAST_COLUMN;
3801
if (maxEntryWithoutAccelWidth > maxEntryWithAccelWidth) {
3802
geometryPtr->nonAccelMargin = maxEntryWithoutAccelWidth
3803
- maxEntryWithAccelWidth;
3804
if (geometryPtr->nonAccelMargin > maxNonAccelMargin) {
3805
geometryPtr->nonAccelMargin = maxNonAccelMargin;
3808
geometryPtr->nonAccelMargin = 0;
3811
windowWidth = x + maxIndicatorSpace + maxWidth
3812
+ 2 * menuPtr->activeBorderWidth + menuPtr->borderWidth;
3813
windowHeight += menuPtr->borderWidth;
3816
* The X server doesn't like zero dimensions, so round up to at least
3817
* 1 (a zero-sized menu should never really occur, anyway).
3820
if (windowWidth <= 0) {
3823
if (windowHeight <= 0) {
3826
menuPtr->totalWidth = windowWidth;
3827
menuPtr->totalHeight = windowHeight;
3831
*----------------------------------------------------------------------
3833
* DrawMenuEntryLabel --
3835
* This procedure draws the label part of a menu.
3841
* Commands are output to X to display the menu in its
3844
*----------------------------------------------------------------------
3849
TkMenu *menuPtr, /* The menu we are drawing */
3850
TkMenuEntry *mePtr, /* The entry we are drawing */
3851
Drawable d, /* What we are drawing into */
3852
GC gc, /* The gc we are drawing into */
3853
Tk_Font tkfont, /* The precalculated font */
3854
CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */
3855
int x, /* left edge */
3856
int y, /* right edge */
3857
int width, /* width of entry */
3858
int height) /* height of entry */
3861
int indicatorSpace = mePtr->indicatorSpace;
3862
int leftEdge = x + indicatorSpace;
3863
int imageHeight, imageWidth;
3866
* Draw label or bitmap or image for entry.
3869
baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
3870
if (mePtr->image != NULL) {
3871
Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);
3872
if ((mePtr->selectImage != NULL)
3873
&& (mePtr->entryFlags & ENTRY_SELECTED)) {
3874
Tk_RedrawImage(mePtr->selectImage, 0, 0,
3875
imageWidth, imageHeight, d, leftEdge,
3876
(int) (y + (mePtr->height - imageHeight)/2));
3878
Tk_RedrawImage(mePtr->image, 0, 0, imageWidth,
3879
imageHeight, d, leftEdge,
3880
(int) (y + (mePtr->height - imageHeight)/2));
3882
} else if (mePtr->bitmap != None) {
3885
Tk_SizeOfBitmap(menuPtr->display,
3886
mePtr->bitmap, &width, &height);
3887
XCopyPlane(menuPtr->display,
3889
gc, 0, 0, (unsigned) width, (unsigned) height, leftEdge,
3890
(int) (y + (mePtr->height - height)/2), 1);
3892
if (mePtr->labelLength > 0) {
3895
GetEntryText(mePtr, itemText);
3896
Tk_DrawChars(menuPtr->display, d, gc,
3897
tkfont, (char *) itemText + 1, itemText[0],
3898
leftEdge, baseline);
3899
/* TkpDrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y,
3904
if (mePtr->state == tkDisabledUid) {
3905
if (menuPtr->disabledFg == NULL) {
3906
if (!TkMacHaveAppearance()) {
3907
XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
3908
(unsigned) width, (unsigned) height);
3910
} else if ((mePtr->image != NULL)
3911
&& (menuPtr->disabledImageGC != None)) {
3912
XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
3914
(int) (y + (mePtr->height - imageHeight)/2),
3915
(unsigned) imageWidth, (unsigned) imageHeight);
3921
*----------------------------------------------------------------------
3923
* DrawMenuEntryBackground --
3925
* This procedure draws the background part of a menu entry.
3926
* Under Appearance, we only draw the background if the entry's
3927
* border is set, we DO NOT inherit it from the menu...
3933
* Commands are output to X to display the menu in its
3936
*----------------------------------------------------------------------
3940
DrawMenuEntryBackground(
3941
TkMenu *menuPtr, /* The menu we are drawing. */
3942
TkMenuEntry *mePtr, /* The entry we are drawing. */
3943
Drawable d, /* What we are drawing into */
3944
Tk_3DBorder activeBorder, /* Border for active items */
3945
Tk_3DBorder bgBorder, /* Border for the background */
3946
int x, /* left edge */
3947
int y, /* top edge */
3948
int width, /* width of rectangle to draw */
3949
int height) /* height of rectangle to draw */
3951
if (!TkMacHaveAppearance()
3952
|| (menuPtr->menuType == TEAROFF_MENU)
3953
|| ((mePtr->state == tkActiveUid) && (mePtr->activeBorder != NULL))
3954
|| ((mePtr->state != tkActiveUid) && (mePtr->border != NULL))) {
3955
if (mePtr->state == tkActiveUid) {
3956
bgBorder = activeBorder;
3958
Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder,
3959
x, y, width, height, 0, TK_RELIEF_FLAT);
3964
*----------------------------------------------------------------------
3966
* GetMenuLabelGeometry --
3968
* Figures out the size of the label portion of a menu item.
3971
* widthPtr and heightPtr are filled in with the correct geometry
3977
*----------------------------------------------------------------------
3981
GetMenuLabelGeometry(
3982
TkMenuEntry *mePtr, /* The entry we are computing */
3983
Tk_Font tkfont, /* The precalculated font */
3984
CONST Tk_FontMetrics *fmPtr, /* The precalculated metrics */
3985
int *widthPtr, /* The resulting width of the label
3987
int *heightPtr) /* The resulting height of the label
3990
TkMenu *menuPtr = mePtr->menuPtr;
3992
if (mePtr->image != NULL) {
3993
Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr);
3994
} else if (mePtr->bitmap != (Pixmap) NULL) {
3995
Tk_SizeOfBitmap(menuPtr->display, mePtr->bitmap, widthPtr, heightPtr);
3997
*heightPtr = fmPtr->linespace;
3999
if (mePtr->label != NULL) {
4002
GetEntryText(mePtr, itemText);
4003
*widthPtr = Tk_TextWidth(tkfont, (char *) itemText + 1,
4013
*----------------------------------------------------------------------
4015
* MenuSelectEvent --
4017
* Generates a "MenuSelect" virtual event. This can be used to
4018
* do context-sensitive menu help.
4024
* Places a virtual event on the event queue.
4026
*----------------------------------------------------------------------
4031
TkMenu *menuPtr) /* the menu we have selected. */
4033
XVirtualEvent event;
4036
event.type = VirtualEvent;
4037
event.serial = menuPtr->display->request;
4038
event.send_event = false;
4039
event.display = menuPtr->display;
4040
Tk_MakeWindowExist(menuPtr->tkwin);
4041
event.event = Tk_WindowId(menuPtr->tkwin);
4042
event.root = XRootWindow(menuPtr->display, 0);
4043
event.subwindow = None;
4044
event.time = TkpGetMS();
4047
event.x_root = where.h;
4048
event.y_root = where.v;
4049
event.state = TkMacButtonKeyState();
4050
event.same_screen = true;
4051
event.name = Tk_GetUid("MenuSelect");
4052
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
4056
*----------------------------------------------------------------------
4058
* RecursivelyClearActiveMenu --
4060
* Recursively clears the active entry in the menu's cascade hierarchy.
4066
* Generates <<MenuSelect>> virtual events.
4068
*----------------------------------------------------------------------
4072
RecursivelyClearActiveMenu(
4073
TkMenu *menuPtr) /* The menu to reset. */
4078
TkActivateMenuEntry(menuPtr, -1);
4079
MenuSelectEvent(menuPtr);
4080
for (i = 0; i < menuPtr->numEntries; i++) {
4081
mePtr = menuPtr->entries[i];
4082
if (mePtr->type == CASCADE_ENTRY) {
4083
if ((mePtr->childMenuRefPtr != NULL)
4084
&& (mePtr->childMenuRefPtr->menuPtr != NULL)) {
4085
RecursivelyClearActiveMenu(mePtr->childMenuRefPtr->menuPtr);
4092
*----------------------------------------------------------------------
4094
* InvalidateMDEFRgns --
4096
* Invalidates the regions covered by menus that did redrawing and
4103
* Generates Mac update events for affected windows.
4105
*----------------------------------------------------------------------
4109
InvalidateMDEFRgns(void) {
4110
GDHandle saveDevice;
4111
GWorldPtr saveWorld, destPort;
4113
MacDrawable *macDraw;
4114
TkMacWindowList *listPtr;
4116
if (totalMenuRgn == NULL) {
4120
GetGWorld(&saveWorld, &saveDevice);
4121
for (listPtr = tkMacWindowListPtr ; listPtr != NULL;
4122
listPtr = listPtr->nextPtr) {
4123
macDraw = (MacDrawable *) Tk_WindowId(listPtr->winPtr);
4124
if (macDraw->flags & TK_DRAWN_UNDER_MENU) {
4125
destPort = TkMacGetDrawablePort(Tk_WindowId(listPtr->winPtr));
4126
SetGWorld(destPort, NULL);
4127
scratch.h = scratch.v = 0;
4128
GlobalToLocal(&scratch);
4129
OffsetRgn(totalMenuRgn, scratch.v, scratch.h);
4130
InvalRgn(totalMenuRgn);
4131
OffsetRgn(totalMenuRgn, -scratch.v, -scratch.h);
4132
macDraw->flags &= ~TK_DRAWN_UNDER_MENU;
4136
SetGWorld(saveWorld, saveDevice);
4137
SetEmptyRgn(totalMenuRgn);
4141
*----------------------------------------------------------------------
4143
* TkMacClearMenubarActive --
4145
* Recursively clears the active entry in the current menubar hierarchy.
4151
* Generates <<MenuSelect>> virtual events.
4153
*----------------------------------------------------------------------
4157
TkMacClearMenubarActive(void) {
4158
TkMenuReferences *menuBarRefPtr;
4160
if (currentMenuBarName != NULL) {
4161
menuBarRefPtr = TkFindMenuReferences(currentMenuBarInterp,
4162
currentMenuBarName);
4163
if ((menuBarRefPtr != NULL) && (menuBarRefPtr->menuPtr != NULL)) {
4166
for (menuPtr = menuBarRefPtr->menuPtr->masterMenuPtr; menuPtr != NULL;
4167
menuPtr = menuPtr->nextInstancePtr) {
4168
if (menuPtr->menuType == MENUBAR) {
4169
RecursivelyClearActiveMenu(menuPtr);
4174
InvalidateMDEFRgns();
4179
*----------------------------------------------------------------------
4181
* TkpMenuNotifyToplevelCreate --
4183
* This routine reconfigures the menu and the clones indicated by
4184
* menuName becuase a toplevel has been created and any system
4185
* menus need to be created. Only applicable to Windows.
4191
* An idle handler is set up to do the reconfiguration.
4193
*----------------------------------------------------------------------
4197
TkpMenuNotifyToplevelCreate(
4198
Tcl_Interp *interp, /* The interp the menu lives in. */
4199
char *menuName) /* The name of the menu to
4208
*----------------------------------------------------------------------
4212
* Loads the MDEF and blasts our routine descriptor into it.
4213
* We have to set up the MDEF. This is pretty slimy. The real MDEF
4214
* resource is 68K code. All this code does is call another procedure.
4215
* When the application in launched, a dummy value for the procedure
4216
* is compiled into the MDEF. We are going to replace that dummy
4217
* value with a routine descriptor. When the routine descriptor
4218
* is invoked, the globals and everything will be setup, and we
4219
* can do what we need. This will not work from 68K or CFM 68k
4220
* currently, so we will conditional compile this until we
4224
* Returns the MDEF handle.
4227
* The MDEF is read in and massaged.
4229
*----------------------------------------------------------------------
4235
#ifdef GENERATINGCFM
4236
Handle MDEFHandle = GetResource('MDEF', 591);
4237
Handle SICNHandle = GetResource('SICN', SICN_RESOURCE_NUMBER);
4238
if ((MDEFHandle != NULL) && (SICNHandle != NULL)) {
4241
if (menuDefProc == NULL) {
4242
menuDefProc = TkNewMenuDefProc(MenuDefProc);
4244
memmove((void *) (((long) (*MDEFHandle)) + 0x24), &menuDefProc, 4);
4255
*----------------------------------------------------------------------
4259
* Initializes Mac-specific menu data.
4265
* Allcates a hash table.
4267
*----------------------------------------------------------------------
4274
Tcl_InitHashTable(&commandTable, TCL_ONE_WORD_KEYS);
4275
currentMenuBarOwner = NULL;
4276
tearoffStruct.menuPtr = NULL;
4277
currentAppleMenuID = 0;
4278
currentHelpMenuID = 0;
4279
currentMenuBarInterp = NULL;
4280
currentMenuBarName = NULL;
4281
windowListPtr = NULL;
4284
* Get the GC that we will use as the sign to the font
4285
* routines that they should not muck with the foreground color...
4288
if (TkMacHaveAppearance() > 1) {
4289
XGCValues tmpValues;
4290
TkColor *tmpColorPtr;
4292
tmpColorPtr = TkpGetColor(NULL, "systemAppearanceColor");
4293
tmpValues.foreground = tmpColorPtr->color.pixel;
4294
tmpValues.background = tmpColorPtr->color.pixel;
4295
appearanceGC = XCreateGC(NULL, NULL, GCForeground | GCBackground, &tmpValues);
4296
ckfree((char *) tmpColorPtr);
4298
tkThemeMenuItemDrawingUPP = NewMenuItemDrawingProc(tkThemeMenuItemDrawingProc);