diff options
Diffstat (limited to 'carbon/tkMacOSXMenu.c')
-rw-r--r-- | carbon/tkMacOSXMenu.c | 4750 |
1 files changed, 0 insertions, 4750 deletions
diff --git a/carbon/tkMacOSXMenu.c b/carbon/tkMacOSXMenu.c deleted file mode 100644 index b02c289..0000000 --- a/carbon/tkMacOSXMenu.c +++ /dev/null @@ -1,4750 +0,0 @@ -/* - * tkMacOSXMenu.c -- - * - * This module implements the Mac-platform specific features of menus. - * - * Copyright (c) 1996-1997 by Sun Microsystems, Inc. - * Copyright 2001, Apple Computer, Inc. - * Copyright (c) 2005-2007 Daniel A. Steffen <das@users.sourceforge.net> - * - * See the file "license.terms" for information on usage and redistribution of - * this file, and for a DISCLAIMER OF ALL WARRANTIES. - */ - -#include "tkMacOSXPrivate.h" -#include "tkMenubutton.h" -#include "tkMenu.h" -#include "tkColor.h" -#include "tkFont.h" -#include "tkMacOSXDebug.h" - -/* -#ifdef TK_MAC_DEBUG -#define TK_MAC_DEBUG_MENUS -#endif -*/ - -#define USE_TK_MDEF - -typedef struct MacMenu { - MenuRef menuHdl; /* The Menu Manager data structure. */ -#ifdef USE_TK_MDEF - int useMDEF; /* true if this menu uses the MDEF */ -#endif -} MacMenu; - -typedef struct MenuEntryUserData { - Drawable mdefDrawable; - TkMenuEntry *mePtr; - Tk_Font tkfont; - Tk_FontMetrics *fmPtr; -} MenuEntryUserData; - -/* - * Platform specific flags for menu entries - * - * ENTRY_COMMAND_ACCEL Indicates the entry has the command key - * in its accelerator string. - * ENTRY_OPTION_ACCEL Indicates the entry has the option key - * in its accelerator string. - * ENTRY_SHIFT_ACCEL Indicates the entry has the shift key - * in its accelerator string. - * ENTRY_CONTROL_ACCEL Indicates the entry has the control key - * in its accelerator string. - */ - -#define ENTRY_COMMAND_ACCEL ENTRY_PLATFORM_FLAG1 -#define ENTRY_OPTION_ACCEL ENTRY_PLATFORM_FLAG2 -#define ENTRY_SHIFT_ACCEL ENTRY_PLATFORM_FLAG3 -#define ENTRY_CONTROL_ACCEL ENTRY_PLATFORM_FLAG4 -#define ENTRY_ACCEL_MASK (ENTRY_COMMAND_ACCEL | ENTRY_OPTION_ACCEL \ - | ENTRY_SHIFT_ACCEL | ENTRY_CONTROL_ACCEL) -#define MODIFIER_NUM 4 - -/* - * This structure is used to keep track of subfields within Macintosh menu - * items. - */ - -typedef struct EntryGeometry { - int accelTextStart; /* Offset into the accel string where the text - * starts. Everything before this is modifier - * key descriptions. */ - int modifierWidth; /* Width of modifier symbols. */ - int accelTextWidth; /* Width of the text after the modifier - * keys. */ - int nonAccelMargin; /* The width of the margin for entries without - * accelerators. */ - int modifierNum; /* Number of modifiers */ - Tcl_UniChar modifierUniChars[MODIFIER_NUM]; - /* Modifiers in unicode */ - char accelGlyph; /* Accelerator glyph, if any */ -} EntryGeometry; - -/* - * Structure to keep track of toplevel windows and their menubars. - */ - -typedef struct TopLevelMenubarList { - struct TopLevelMenubarList *nextPtr; - /* The next window in the list. */ - Tk_Window tkwin; /* The toplevel window. */ - TkMenu *menuPtr; /* The menu associated with this toplevel. */ -} TopLevelMenubarList; - -/* - * Platform-specific flags for menus. - * - * MENU_APPLE_MENU 0 indicates a custom Apple menu has not been - * installed; 1 a custom Apple menu has been - * installed. - * MENU_HELP_MENU 0 indicates a custom Help menu has not been - * installed; 1 a custom Help menu has been - * installed. - * MENU_RECONFIGURE_PENDING 1 indicates that an idle handler has been - * scheduled to reconfigure the Macintosh - * MenuHandle. - */ - -#define MENU_APPLE_MENU MENU_PLATFORM_FLAG1 -#define MENU_HELP_MENU MENU_PLATFORM_FLAG2 -#define MENU_RECONFIGURE_PENDING MENU_PLATFORM_FLAG3 - -#define CASCADE_CMD (0x1b) /* The special command char for cascade - * menus. */ -#define MENUBAR_REDRAW_PENDING 1 - -static int gNoTkMenus = 0; /* This is used by Tk_MacOSXTurnOffMenus as - * the flag that Tk is not to draw any - * menus. */ - -static Tcl_HashTable commandTable; - /* The list of menuInstancePtrs associated - * with menu ids. */ -static short currentAppleMenuID; - /* The id of the current Apple menu. 0 for - * none. */ -static short currentHelpMenuID; /* The id of the current Help menu. 0 for - * none. */ -static Tcl_Interp *currentMenuBarInterp; - /* The interpreter of the window that owns the - * current menubar. */ -static char *currentMenuBarName; - /* Malloced. Name of current menu in menu bar. - * NULL if no menu set. TO DO: make this a - * DString. */ -static Tk_Window currentMenuBarOwner; - /* Which window owns the current menu bar. */ -static int inPostMenu; /* We cannot be re-entrant like X windows. */ -static short lastMenuID; /* To pass to NewMenu; need to figure out a - * good way to do this. */ -static short lastCascadeID; /* Cascades have to have ids that are less - * than 256. */ -static int menuBarFlags; /* Used for whether the menu bar needs - * redrawing or not. */ - -struct MenuCommandHandlerData { /* This is the ClientData we pass to */ - TkMenu *menuPtr; /* Tcl_DoWhenIdle to move handling */ - int index; /* menu commands to the event loop. */ -}; - -static TopLevelMenubarList *windowListPtr; - /* A list of windows that have menubars set. */ - -/* - * Array of unicode, charcode and utf representations of the most common - * special menu symbols. - */ - -typedef struct MenuSymbol { - const Tcl_UniChar unicode; - const char charCode; - /* char padding; */ - int utfLen, width; - char utf[TCL_UTF_MAX + 1]; -} MenuSymbol; - -static MenuSymbol menuSymbols[] = { - {kCommandUnicode, kCommandCharCode}, - {kOptionUnicode, kMenuOptionGlyph}, - {kControlUnicode, kMenuControlGlyph}, - {kShiftUnicode, kMenuShiftGlyph}, - {kCheckUnicode, kCheckCharCode}, - {kDiamondUnicode, kDiamondCharCode}, - {kBulletUnicode, kBulletCharCode}, - {0x2026, kNullCharCode}, - {0, 0}, -}; - -enum MenuSymbolIdx { - COMMAND_SYMBOL, - OPTION_SYMBOL, - CONTROL_SYMBOL, - SHIFT_SYMBOL, - CHECK_SYMBOL, - DIAMDOND_SYMBOL, - BULLET_SYMBOL, - ELLIPSIS_SYMBOL, -}; - -MenuRef tkCurrentAppleMenu = NULL; - -static SInt32 menuMarkColumnWidth = 0, menuMarkIndent = 0; -static SInt32 menuTextLeadingEdgeMargin = 0, menuTextTrailingEdgeMargin = 0; -static SInt16 menuItemExtraHeight = 0, menuItemExtraWidth = 0; -static SInt16 menuSeparatorHeight = 0; - -/* - * Forward declarations for procedures defined later in this file: - */ - -MODULE_SCOPE int TkMacOSXGetNewMenuID(Tcl_Interp *interp, - TkMenu *menuInstPtr, int cascade, - short *menuIDPtr); -MODULE_SCOPE void TkMacOSXFreeMenuID(short menuID); - -static void CompleteIdlers(TkMenu *menuPtr); -static void DrawMenuBarWhenIdle(ClientData clientData); -static void DrawMenuEntryAccelerator(TkMenu *menuPtr, - TkMenuEntry *mePtr, Drawable d, GC gc, - Tk_Font tkfont, const Tk_FontMetrics *fmPtr, - Tk_3DBorder activeBorder, int x, int y, int width, - int height, int drawArrow); -static void DrawMenuEntryBackground(TkMenu *menuPtr, - TkMenuEntry *mePtr, Drawable d, - Tk_3DBorder activeBorder, Tk_3DBorder bgBorder, - int x, int y, int width, int heigth); -static void DrawMenuEntryIndicator(TkMenu *menuPtr, - TkMenuEntry *mePtr, Drawable d, GC gc, - GC indicatorGC, Tk_Font tkfont, - const Tk_FontMetrics *fmPtr, int x, int y, - int width, int height); -static void DrawMenuEntryLabel(TkMenu *menuPtr,TkMenuEntry *mePtr, - Drawable d, GC gc, Tk_Font tkfont, - const Tk_FontMetrics *fmPtr, int x, int y, - int width, int height); -static void DrawMenuSeparator(TkMenu *menuPtr, TkMenuEntry *mePtr, - Drawable d, GC gc, Tk_Font tkfont, - const Tk_FontMetrics *fmPtr, int x, int y, - int width, int height); -static void DrawTearoffEntry(TkMenu *menuPtr, TkMenuEntry *mePtr, - Drawable d, GC gc, Tk_Font tkfont, - const Tk_FontMetrics *fmPtr, int x, int y, - int width, int height); -static void EventuallyInvokeMenu(ClientData data); -static void GetEntryText(TkMenuEntry *mePtr, - Tcl_DString *dStringPtr); -static void GetMenuAccelGeometry(TkMenu *menuPtr, - TkMenuEntry *mePtr, Tk_Font tkfont, - const Tk_FontMetrics *fmPtr, int *modWidthPtr, - int *textWidthPtr, int *heightPtr); -static void GetMenuLabelGeometry(TkMenuEntry *mePtr, - Tk_Font tkfont, const Tk_FontMetrics *fmPtr, - int *widthPtr, int *heightPtr); -static void GetMenuIndicatorGeometry(TkMenu *menuPtr, - TkMenuEntry *mePtr, Tk_Font tkfont, - const Tk_FontMetrics *fmPtr, int *widthPtr, - int *heightPtr); -static void GetMenuSeparatorGeometry(TkMenu *menuPtr, - TkMenuEntry *mePtr, Tk_Font tkfont, - const Tk_FontMetrics *fmPtr, int *widthPtr, - int *heightPtr); -static TkMenuEntry * GetParentMenuEntry(TkMenu *menuPtr); -static void GetTearoffEntryGeometry(TkMenu *menuPtr, - TkMenuEntry *mePtr, Tk_Font tkfont, - const Tk_FontMetrics *fmPtr, int *widthPtr, - int *heightPtr); -static char FindMarkCharacter(TkMenuEntry *mePtr); -static int GetUtfMarkCharacter(char markChar, - const char **markUtfPtr); -static TkMenu * MenuPtrForMenuRef(MenuRef menu); -static int ParseAccelerators(const char **accelStringPtr, - int *modifierNumPtr, - Tcl_UniChar *modifierUniChars, - int *modifierWidth); -static void MenuSelectEvent(TkMenu *menuPtr); -static void ReconfigureIndividualMenu(TkMenu *menuPtr, - MenuHandle macMenuHdl, int base); -static void ReconfigureMacintoshMenu(ClientData clientData); -static void RecursivelyClearActiveMenu(TkMenu *menuPtr); -static void RecursivelyDeleteMenu(TkMenu *menuPtr); -static void RecursivelyInsertMenu(TkMenu *menuPtr); -static void SetDefaultMenubar(void); -static int SetMenuCascade(TkMenu *menuPtr); - -#ifdef USE_TK_MDEF -#define SCREEN_MARGIN 5 -static MacDrawable macMDEFDrawable; - /* Drawable for use by MDEF code */ -static int MDEFScrollFlag = 0; /* Used so that popups don't scroll too - * soon. */ -static MenuItemDrawingUPP tkThemeMenuItemDrawingUPP; - /* Points to the UPP for theme Item - * drawing. */ -static Tcl_Obj *useMDEFVar; - -static void DrawMenuBackground(TkMenu *menuPtr, Rect *menuRectPtr, - Drawable d); -static void MenuDefProc(short message, MenuHandle menu, - Rect *menuRectPtr, Point hitPt, short *whichItem); -static void HandleMenuHiliteMsg(MenuRef menu, Rect *menuRectPtr, - Point hitPt, SInt16 *whichItem, TkMenu *menuPtr); -static void HandleMenuDrawMsg(MenuRef menu, Rect *menuRectPtr, - Point hitPt, SInt16 *whichItem, TkMenu *menuPtr); -static void HandleMenuFindItemMsg(MenuRef menu, Rect *menuRectPtr, - Point hitPt, SInt16 *whichItem, TkMenu *menuPtr); -static void HandleMenuPopUpMsg(MenuRef menu, Rect *menuRectPtr, - Point hitPt, SInt16 *whichItem, TkMenu *menuPtr); -static void HandleMenuCalcItemMsg(MenuRef menu, Rect *menuRectPtr, - Point hitPt, SInt16 *whichItem, TkMenu *menuPtr); -static void AppearanceEntryDrawWrapper(TkMenuEntry *mePtr, - Rect *menuRectPtr, MenuTrackingData *mtdPtr, - Drawable d, Tk_FontMetrics *fmPtr, Tk_Font tkfont, - int erase); -static pascal void ThemeMenuItemDrawingProc(const Rect *inBounds, - SInt16 inDepth, Boolean inIsColorDevice, - SInt32 inUserData); -#else /* USE_TK_MDEF */ -# define useMDEF 0 -#endif /* USE_TK_MDEF */ - -#define IS_THEME_MENU_FONT(tkfont) (strcmp(Tk_NameOfFont(tkfont), "menu") == 0) - -/* - *---------------------------------------------------------------------- - * - * DrawThemeText -- - * - * Wrapper for DrawThemeTextBox API. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static void -DrawThemeText( - Drawable d, - GC gc, - CFStringRef string, - ThemeFontID font, - ThemeDrawState drawState, - const Rect* bounds, - int baseline, - int just) -{ - TkMacOSXDrawingContext dc; - Rect adjustedBounds; - - /* - * Menu item text drawn with the .Keyboard font (used for - * kThemeMenuItemCmdKeyFont) won't always have the same ascent and - * baseline as text drawn with the regular menu item font, since the - * glyphs in the .Keyboard font may have a different height. Therefore, we - * first determine the baseline of the text and then adjust the bounds - * rect so the baseline aligns with the overall baseline of the menu item. - */ - - if (font == kThemeMenuItemCmdKeyFont) { - Point size; - SInt16 cmdKeyBaseline; - - GetThemeTextDimensions(string, font, drawState, false, &size, - &cmdKeyBaseline); - adjustedBounds = *bounds; - OffsetRect(&adjustedBounds, 0, baseline - bounds->top - size.v - - cmdKeyBaseline); - bounds = &adjustedBounds; - } - if (TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) { - ChkErr(DrawThemeTextBox, string, font, drawState, false, bounds, just, - dc.context); - TkMacOSXRestoreDrawingContext(&dc); - } -} - -/* - *---------------------------------------------------------------------- - * - * MeasureThemeText -- - * - * Wrapper for GetThemeTextDimensions API. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -MeasureThemeText( - CFStringRef string, - ThemeFontID font) -{ - Point pt; - - ChkErr(GetThemeTextDimensions, string, font, kThemeStateActive, false, &pt, - NULL); - return pt.h; -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXUseID -- - * - * Take the ID out of the available list for new menus. Used by the - * default menu bar's menus so that they do not get created at the tk - * level. See TkMacOSXGetNewMenuID for more information. - * - * Results: - * Returns TCL_OK if the id was not in use. Returns TCL_ERROR if the id - * was in use. - * - * Side effects: - * A hash table entry in the command table is created with a NULL value. - * - *---------------------------------------------------------------------- - */ - -int -TkMacOSXUseMenuID( - short macID) /* The id to take out of the table */ -{ - Tcl_HashEntry *commandEntryPtr; - int newEntry; - int iMacID = macID; /* Do this to remove compiler warning */ - - TkMenuInit(); - commandEntryPtr = Tcl_CreateHashEntry(&commandTable, (char *) iMacID, - &newEntry); - if (!newEntry) { - return TCL_ERROR; - } - Tcl_SetHashValue(commandEntryPtr, NULL); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXGetNewMenuID -- - * - * Allocates a new menu id and marks it in use. Each menu on the mac must - * be designated by a unique id, which is a short. In addition, some ids - * are reserved by the system. Since Tk uses mostly dynamic menus, we - * must allocate and free these ids on the fly. We use the id as a key - * into a hash table; if there is no hash entry, we know that we can use - * the id. - * - * Carbon allows a much larger number of menus than the old APIs. I - * believe this is 32768, but am not sure. This code just uses 2000 as - * the upper limit. Unfortunately tk leaks menus when cloning, under some - * circumstances (see bug on sourceforge). - * - * Results: - * Returns TCL_OK if succesful; TCL_ERROR if there are no more ids of the - * appropriate type to allocate. menuIDPtr contains the new id if - * succesful. - * - * Side effects: - * An entry is created for the menu in the command hash table, and the - * hash entry is stored in the appropriate field in the menu data - * structure. - * - *---------------------------------------------------------------------- - */ - -int -TkMacOSXGetNewMenuID( - Tcl_Interp *interp, /* Used for error reporting */ - TkMenu *menuPtr, /* The menu we are working with */ - int cascade, /* 0 if we are working with a normal menu; - * 1 if we are working with a cascade */ - short *menuIDPtr) /* The resulting id */ -{ - int found = 0; - int newEntry; - Tcl_HashEntry *commandEntryPtr = NULL; - short returnID = *menuIDPtr; - - /* - * The following code relies on shorts and unsigned chars wrapping when - * the highest value is incremented. Also, the values between 236 and 255 - * inclusive are reserved for DA's by the Mac OS. - */ - - if (!cascade) { - short curID = lastMenuID + 1; - - if (curID == 236) { - curID = 256; - } - - while (curID != lastMenuID) { - int iCurID = curID; - commandEntryPtr = Tcl_CreateHashEntry(&commandTable, - (char *) iCurID, &newEntry); - if (newEntry == 1) { - found = 1; - lastMenuID = returnID = curID; - break; - } - curID++; - if (curID == 236) { - curID = 256; - } - } - } else { - /* - * Cascade ids must be between 0 and 235 only, so they must be dealt - * with separately. - */ - - short curID = lastCascadeID + 1; - - if (curID == 2000) { - curID = 0; - } - - while (curID != lastCascadeID) { - int iCurID = curID; - commandEntryPtr = Tcl_CreateHashEntry(&commandTable, - (char *) iCurID, &newEntry); - if (newEntry == 1) { - found = 1; - lastCascadeID = returnID = curID; - break; - } - curID++; - if (curID == 2000) { - curID = 0; - } - } - } - - if (!found) { - Tcl_SetObjResult(menuPtr->interp, Tcl_NewStringObj( - "No more menus can be allocated.", -1)); - Tcl_SetErrorCode(menuPtr->interp, "TK", "MENU", "SYSTEM_RESOURCES", - NULL); - return TCL_ERROR; - } - Tcl_SetHashValue(commandEntryPtr, menuPtr); - *menuIDPtr = returnID; - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXFreeMenuID -- - * - * Marks the id as free. - * - * Results: - * None. - * - * Side effects: - * The hash table entry for the ID is cleared. - * - *---------------------------------------------------------------------- - */ - -void -TkMacOSXFreeMenuID( - short menuID) /* The id to free */ -{ - Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&commandTable, - (char*)(intptr_t)menuID); - - if (entryPtr != NULL) { - Tcl_DeleteHashEntry(entryPtr); - } - if (menuID == currentAppleMenuID) { - currentAppleMenuID = 0; - } - if (menuID == currentHelpMenuID) { - currentHelpMenuID = 0; - } -} - -/* - *---------------------------------------------------------------------- - * - * MenuPtrForMenuRef -- - * - * Returns a pointer to the TkMenu corresponding to a given Carbon - * MenuRef. - * - * Results: - * Returns a pointer to a TkMenu or NULL. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -TkMenu * -MenuPtrForMenuRef( - MenuRef menu) -{ - TkMenu *menuPtr = NULL; - MenuID menuID = GetMenuID(menu); - Tcl_HashEntry *commandEntryPtr = - Tcl_FindHashEntry(&commandTable, (char*)(intptr_t)menuID); - - if (commandEntryPtr) { - menuPtr = Tcl_GetHashValue(commandEntryPtr); - } - return menuPtr; -} - -/* - *---------------------------------------------------------------------- - * - * GetParentMenuEntry -- - * - * Returns a pointer to the parent's TkMenuEntry of a given TkMenu. - * - * Results: - * Returns a pointer to a TkMenuEntry or NULL. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -TkMenuEntry* -GetParentMenuEntry( - TkMenu *menuPtr) -{ - TkMenuEntry *cascadeEntryPtr; - - for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr; - cascadeEntryPtr != NULL; - cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) { - const char *name = (cascadeEntryPtr->namePtr == NULL) ? "" - : Tcl_GetString(cascadeEntryPtr->namePtr); - - if (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) { - break; - } - } - return cascadeEntryPtr; -} - -/* - *---------------------------------------------------------------------- - * - * TkpNewMenu -- - * - * Gets a new blank menu. Only the platform specific options are filled - * in. - * - * Results: - * Returns a standard TCL error. - * - * Side effects: - * Allocates a Macintosh menu handle and puts in the platformData field - * of the menuPtr. - * - *---------------------------------------------------------------------- - */ - -int -TkpNewMenu( - TkMenu *menuPtr) /* The common structure we are making the - * platform structure for. */ -{ - short menuID; - MenuRef macMenuHdl; -#ifdef USE_TK_MDEF - MenuDefSpec menuDefSpec; - Tcl_Obj *useMDEFObjPtr; - int useMDEF = 1; -#endif - int error = TCL_OK; - OSStatus err; - CFStringRef cfStr; - - error = TkMacOSXGetNewMenuID(menuPtr->interp, menuPtr, 0, &menuID); - if (error != TCL_OK) { - return error; - } - err = ChkErr(CreateNewMenu, menuID, kMenuAttrDoNotUseUserCommandKeys, - &macMenuHdl); - if (err != noErr) { - Tcl_SetObjResult(menuPtr->interp, Tcl_NewStringObj( - "CreateNewMenu failed.", -1)); - Tcl_SetErrorCode(menuPtr->interp, "TK", "MENU", "CREATE", NULL); - return TCL_ERROR; - } - cfStr = CFStringCreateWithCString(NULL, Tk_PathName(menuPtr->tkwin), - kCFStringEncodingUTF8); - if (!cfStr) { - Tcl_SetObjResult(menuPtr->interp, Tcl_NewStringObj( - "CFStringCreateWithCString failed.", -1)); - Tcl_SetErrorCode(menuPtr->interp, "TK", "MENU", "CREATE_STRING",NULL); - return TCL_ERROR; - } - err = ChkErr(SetMenuTitleWithCFString, macMenuHdl, cfStr); - CFRelease(cfStr); - if (err != noErr) { - Tcl_SetObjResult(menuPtr->interp, Tcl_NewStringObj( - "SetMenuTitleWithCFString failed.", -1)); - Tcl_SetErrorCode(menuPtr->interp, "TK", "MENU", "SET_TITLE", NULL); - return TCL_ERROR; - } - - menuPtr->platformData = ckalloc(sizeof(MacMenu)); - ((MacMenu *) menuPtr->platformData)->menuHdl = macMenuHdl; - -#ifdef USE_TK_MDEF - /* - * Check whether we want to use the custom mdef or not. For now - * the default is to use it unless the variable is explicitly - * set to no. - */ - - useMDEFObjPtr = Tcl_ObjGetVar2(menuPtr->interp, useMDEFVar, NULL, - TCL_GLOBAL_ONLY); - if (useMDEFObjPtr == NULL || Tcl_GetBooleanFromObj(NULL, useMDEFObjPtr, - &useMDEF) == TCL_ERROR || useMDEF) { - menuDefSpec.defType = kMenuDefProcPtr; - menuDefSpec.u.defProc = MenuDefProc; - ChkErr(SetMenuDefinition, macMenuHdl, &menuDefSpec); - } - ((MacMenu *) menuPtr->platformData)->useMDEF = useMDEF; -#endif /* USE_TK_MDEF */ - - if ((currentMenuBarInterp == menuPtr->interp) - && (currentMenuBarName != NULL)) { - Tk_Window parentWin = Tk_Parent(menuPtr->tkwin); - - if (strcmp(currentMenuBarName, Tk_PathName(parentWin)) == 0) { - if ((strcmp(Tk_PathName(menuPtr->tkwin) - + strlen(Tk_PathName(parentWin)), ".apple") == 0) - || (strcmp(Tk_PathName(menuPtr->tkwin) - + strlen(Tk_PathName(parentWin)), ".help") == 0)) { - if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) { - Tcl_DoWhenIdle(DrawMenuBarWhenIdle, NULL); - menuBarFlags |= MENUBAR_REDRAW_PENDING; - } - } - } - } - - menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; - Tcl_DoWhenIdle(ReconfigureMacintoshMenu, menuPtr); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * TkpDestroyMenu -- - * - * Destroys platform-specific menu structures. - * - * Results: - * None. - * - * Side effects: - * All platform-specific allocations are freed up. - * - *---------------------------------------------------------------------- - */ - -void -TkpDestroyMenu( - TkMenu *menuPtr) /* The common menu structure */ -{ - MenuRef macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl; - - if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) { - Tcl_CancelIdleCall(ReconfigureMacintoshMenu, menuPtr); - menuPtr->menuFlags &= ~MENU_RECONFIGURE_PENDING; - } - if (GetMenuID(macMenuHdl) == currentHelpMenuID) { - MenuRef helpMenuHdl; - MenuItemIndex helpIndex; - - if ((HMGetHelpMenu(&helpMenuHdl,&helpIndex) == noErr) - && (helpMenuHdl != NULL)) { - int i, count = CountMenuItems(helpMenuHdl); - - for (i = helpIndex; i <= count; i++) { - DeleteMenuItem(helpMenuHdl, helpIndex); - } - } - currentHelpMenuID = 0; - } - if (menuPtr->platformData != NULL) { - MenuID menuID = GetMenuID(macMenuHdl); - - DeleteMenu(menuID); - TkMacOSXFreeMenuID(menuID); - DisposeMenu(macMenuHdl); - ckfree(menuPtr->platformData); - menuPtr->platformData = NULL; - } -} - -/* - *---------------------------------------------------------------------- - * - * SetMenuCascade -- - * - * Does any cleanup to change a menu from a normal to a cascade. - * - * Results: - * Standard Tcl error. - * - * Side effects: - * The mac menu id is reset. - * - *---------------------------------------------------------------------- - */ - -int -SetMenuCascade( - TkMenu *menuPtr) /* The menu we are setting up to be a - * cascade. */ -{ - MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl; - MenuID newMenuID, menuID = GetMenuID(macMenuHdl); - int error = TCL_OK; - - if (menuID >= 256) { - error = TkMacOSXGetNewMenuID(menuPtr->interp, menuPtr, 1, &newMenuID); - if (error == TCL_OK) { - TkMacOSXFreeMenuID(menuID); - SetMenuID(macMenuHdl,newMenuID); - } - } - return error; -} - -/* - *---------------------------------------------------------------------- - * - * TkpDestroyMenuEntry -- - * - * Cleans up platform-specific menu entry items. - * - * Results: - * None - * - * Side effects: - * All platform-specific allocations are freed up. - * - *---------------------------------------------------------------------- - */ - -void -TkpDestroyMenuEntry( - TkMenuEntry *mePtr) /* The common structure for the menu entry. */ -{ - TkMenu *menuPtr = mePtr->menuPtr; - - ckfree(mePtr->platformEntryData); - if ((menuPtr->platformData != NULL) - && !(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) { - menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; - Tcl_DoWhenIdle(ReconfigureMacintoshMenu, menuPtr); - } -} - -/* - *---------------------------------------------------------------------- - * - * GetEntryText -- - * - * Given a menu entry, gives back the text that should go in it. - * Separators should be done by the caller, as they have to be handled - * specially. This is primarily used to do a substitution between "..." - * and the ellipsis character which looks nicer. - * - * Results: - * itemText points to the new text for the item. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -GetEntryText( - TkMenuEntry *mePtr, /* A pointer to the menu entry. */ - Tcl_DString *dStringPtr) /* The DString to put the text into. This - * will be initialized by this routine. */ -{ -#ifdef USE_TK_MDEF - const int useMDEF = ((MacMenu *) mePtr->menuPtr->platformData)->useMDEF; -#endif - int noLabel = (mePtr->labelPtr == NULL || mePtr->labelLength == 0); - - Tcl_DStringInit(dStringPtr); - if (mePtr->type == TEAROFF_ENTRY && (useMDEF || noLabel)) { - Tcl_DStringAppend(dStringPtr, "(Tear-off)", -1); - } else if (mePtr->imagePtr != NULL && (useMDEF || noLabel) && - mePtr->compound == COMPOUND_NONE) { - Tcl_DStringAppend(dStringPtr, "(Image)", -1); - } else if (mePtr->bitmapPtr != NULL && (useMDEF || noLabel) && - mePtr->compound == COMPOUND_NONE) { - Tcl_DStringAppend(dStringPtr, "(Pixmap)", -1); - } else if (noLabel) { - /* - * The Mac menu manager does not like null strings. - */ - - Tcl_DStringAppend(dStringPtr, " ", -1); - } else { - int length; - char *text = Tcl_GetStringFromObj(mePtr->labelPtr, &length); - char *dStringText; - int i; - - for (i = 0; *text; text++, i++) { - if ((*text == '.') && (*(text+1) == '.') && (*(text+2) == '.')) { - Tcl_DStringAppend(dStringPtr, menuSymbols[ELLIPSIS_SYMBOL].utf, - menuSymbols[ELLIPSIS_SYMBOL].utfLen); - i += menuSymbols[ELLIPSIS_SYMBOL].utfLen - 1; - text += 2; - } else { - Tcl_DStringSetLength(dStringPtr, - Tcl_DStringLength(dStringPtr) + 1); - dStringText = Tcl_DStringValue(dStringPtr); - dStringText[i] = *text; - } - } - } -} - -/* - *---------------------------------------------------------------------- - * - * FindMarkCharacter -- - * - * Finds the Macintosh mark character based on the font of the item. We - * calculate a good mark character based on the font that this item is - * rendered in. - * - * Results: - * Mark char. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -char -FindMarkCharacter( - TkMenuEntry *mePtr) /* The entry we are finding the character - * for. */ -{ - static const char markChars[] = {kCheckCharCode, kDiamondCharCode, - kBulletCharCode, '-', kCheckCharCode}; - const char *markChar = markChars; - int i = sizeof(markChars); - Tk_Font tkfont; - - tkfont = Tk_GetFontFromObj(mePtr->menuPtr->tkwin, - (mePtr->fontPtr == NULL) ? mePtr->menuPtr->fontPtr - : mePtr->fontPtr); - - while (--i) { - if (!TkMacOSXIsCharacterMissing(tkfont, *markChar)) { - break; - } - markChar++; - } - return *markChar; -} - -/* - *---------------------------------------------------------------------- - * - * GetUtfMarkCharacter -- - * - * Get the utf8 string for the given mark character, taking into account - * the special menu font char codes. - * - * Results: - * Length of returned utf8 string. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -int -GetUtfMarkCharacter( - char markChar, - const char **markUtfPtr) -{ - const MenuSymbol *ms = menuSymbols; - int len = 0; - - while (ms->unicode) { - if (ms->charCode && ms->charCode == markChar) { - *markUtfPtr = ms->utf; - len = ms->utfLen; - break; - } - ms++; - } - if (!len) { - static char markUtf[TCL_UTF_MAX + 1]; - - Tcl_ExternalToUtf(NULL, TkMacOSXCarbonEncoding, &markChar, 1, 0, NULL, - markUtf, TCL_UTF_MAX + 1, NULL, &len, NULL); - *markUtfPtr = markUtf; - } - return len; -} - -/* - *---------------------------------------------------------------------- - * - * ParseAccelerators -- - * - * Parse menu accelerator string. - * - * Results: - * Accelerator flags. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -int -ParseAccelerators( - const char **accelStringPtr, - int *modifierNumPtr, - Tcl_UniChar *modifierUniChars, - int *modifierWidth) -{ - struct Modif { - const char *name; - const size_t len; - const int flag, symbol; - }; -#define MODIF(n, f) { #n, sizeof(#n)-1, ENTRY_##f##_ACCEL, f##_SYMBOL } - static const struct Modif modifs[] = { - MODIF(Control, CONTROL), - MODIF(Ctrl, CONTROL), - MODIF(Option, OPTION), - MODIF(Opt, OPTION), - MODIF(Alt, OPTION), - MODIF(Shift, SHIFT), - MODIF(Command, COMMAND), - MODIF(Cmd, COMMAND), - MODIF(Meta, COMMAND), - { NULL, 0, 0, 0} - }; -#undef MODIF - const char *accelString = *accelStringPtr; - int flags = 0, num = 0, seen = 0, width = 0; - const struct Modif *m; - - while (1) { - m = modifs; - while (m->name) { - int l = m->len; - - if (!strncasecmp(accelString, m->name, l) && - (accelString[l] == '-' || accelString[l] == '+')) { - flags |= m->flag; - accelString += l+1; - break; - } - m++; - } - if (!m->name || !*accelString) { - break; - } - } - m = modifs; - while (m->name && num < MODIFIER_NUM) { - if (flags & m->flag && !(seen & m->flag)) { - modifierUniChars[num++] = menuSymbols[m->symbol].unicode; - width += menuSymbols[m->symbol].width; - seen |= m->flag; - } - m++; - } - *accelStringPtr = accelString; - *modifierNumPtr = num; - *modifierWidth = width; - return flags; -} - -/* - *---------------------------------------------------------------------- - * - * TkpConfigureMenuEntry -- - * - * Processes configurations for menu entries. - * - * Results: - * Returns standard TCL result. If TCL_ERROR is returned, then the - * interp's result contains an error message. - * - * Side effects: - * Configuration information get set for mePtr; old resources get freed, - * if any need it. - * - *---------------------------------------------------------------------- - */ - -int -TkpConfigureMenuEntry( - TkMenuEntry *mePtr) /* Information about menu entry; may or may - * not already have values for some fields. */ -{ - TkMenu *menuPtr = mePtr->menuPtr; - EntryGeometry *geometryPtr = (EntryGeometry *) mePtr->platformEntryData; - - /* - * Cascade menus have to have menu IDs of less than 256. So we need to - * change the child menu if this has been configured for a cascade item. - */ - - if (mePtr->type == CASCADE_ENTRY) { - if ((mePtr->childMenuRefPtr != NULL) - && (mePtr->childMenuRefPtr->menuPtr != NULL)) { - MenuHandle childMenuHdl = ((MacMenu *) mePtr - ->childMenuRefPtr->menuPtr->platformData)->menuHdl; - - if (childMenuHdl != NULL) { - int error = SetMenuCascade(mePtr->childMenuRefPtr->menuPtr); - - if (error != TCL_OK) { - return error; - } - - if (menuPtr->menuType == MENUBAR) { - CFStringRef cfStr = CFStringCreateWithCString(NULL, - (!(mePtr->labelPtr) ? "" : - Tcl_GetString(mePtr->labelPtr)), - kCFStringEncodingUTF8); - - if (cfStr) { - SetMenuTitleWithCFString(childMenuHdl, cfStr); - CFRelease(cfStr); - } - } - } - } - } - - /* - * We need to parse the accelerator string. If it has the strings for - * Command, Control, Shift or Option, we need to flag it so we can draw - * the symbols for it. We also need to precalcuate the position of the - * first real character we are drawing. - */ - - if (0 == mePtr->accelLength) { - geometryPtr->accelTextStart = -1; - } else { - const char *accelString = (mePtr->accelPtr == NULL) ? "" - : Tcl_GetString(mePtr->accelPtr); - const char *accelStart = accelString; - - mePtr->entryFlags &= ~ENTRY_ACCEL_MASK; - mePtr->entryFlags |= ParseAccelerators(&accelString, - &geometryPtr->modifierNum, geometryPtr->modifierUniChars, - &geometryPtr->modifierWidth); - geometryPtr->accelTextStart = (ptrdiff_t)(accelString - accelStart); - } - - if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) { - menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; - Tcl_DoWhenIdle(ReconfigureMacintoshMenu, menuPtr); - } - - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * ReconfigureIndividualMenu -- - * - * This routine redoes the guts of the menu. It works from a base item - * and offset, so that a regular menu will just have all of its items - * added, but the help menu will have all of its items appended after the - * apple-defined items. - * - * Results: - * None. - * - * Side effects: - * The Macintosh menu handle is updated - * - *---------------------------------------------------------------------- - */ - -void -ReconfigureIndividualMenu( - TkMenu *menuPtr, /* The menu we are affecting. */ - MenuHandle macMenuHdl, /* The macintosh menu we are affecting. Will - * not necessarily be menuPtr->platformData - * because this could be the help menu. */ - int base) /* The last index that we do not want touched. - * 0 for normal menus; # of system help menu - * items for help menus. */ -{ - int count; - int index; - TkMenuEntry *mePtr; - int parentDisabled = 0; - -#ifdef TK_MAC_DEBUG_MENUS - /* - * Carbon-internal menu debugging (c.f. Technote 2124) - */ - - TkMacOSXInitNamedDebugSymbol(HIToolbox, void, DebugPrintMenu, - MenuRef menu); - if (DebugPrintMenu) { - DebugPrintMenu(macMenuHdl); - } -#endif - - mePtr = GetParentMenuEntry(menuPtr); - if (mePtr && mePtr->state == ENTRY_DISABLED) { - parentDisabled = 1; - } - - /* - * First, we get rid of all of the old items. - */ - - count = CountMenuItems(macMenuHdl); - for (index = base; index < count; index++) { - DeleteMenuItem(macMenuHdl, base + 1); - } - - count = menuPtr->numEntries; - - for (index = 1; index <= count; index++) { - mePtr = menuPtr->entries[index - 1]; - - /* - * We have to do separators separately because SetMenuItemText does - * not parse meta-characters. - */ - - if (mePtr->type == SEPARATOR_ENTRY) { - AppendMenuItemTextWithCFString(macMenuHdl, NULL, - kMenuItemAttrSeparator | kMenuItemAttrDisabled, 0, NULL); - } else { - Tcl_DString itemTextDString; - CFStringRef cfStr; - - GetEntryText(mePtr, &itemTextDString); - cfStr = CFStringCreateWithCString(NULL, - Tcl_DStringValue(&itemTextDString), kCFStringEncodingUTF8); - if (cfStr) { - AppendMenuItemTextWithCFString(macMenuHdl, cfStr, 0, 0, NULL); - CFRelease(cfStr); - } else { - AppendMenuItemTextWithCFString(macMenuHdl, CFSTR ("<Error>"), - 0, 0, NULL); - } - Tcl_DStringFree(&itemTextDString); - - /* - * Set enabling and disabling correctly. - */ - - if (parentDisabled || (mePtr->state == ENTRY_DISABLED)) { - DisableMenuItem(macMenuHdl, base + index); - } else { - EnableMenuItem(macMenuHdl, base + index); - } - - /* - * Set the check mark for check entries and radio entries. - */ - - SetItemMark(macMenuHdl, base + index, 0); - if ((mePtr->type == CHECK_BUTTON_ENTRY) - || (mePtr->type == RADIO_BUTTON_ENTRY)) { - CheckMenuItem(macMenuHdl, base + index, (mePtr->entryFlags - & ENTRY_SELECTED) && mePtr->indicatorOn); - if (mePtr->indicatorOn - && (mePtr->entryFlags & ENTRY_SELECTED)) { - SetItemMark(macMenuHdl, base + index, - FindMarkCharacter(mePtr)); - } - } - - if (mePtr->type == CASCADE_ENTRY) { - if ((mePtr->childMenuRefPtr != NULL) - && (mePtr->childMenuRefPtr->menuPtr != NULL)) { - MenuHandle childMenuHdl = - ((MacMenu *) mePtr->childMenuRefPtr - ->menuPtr->platformData)->menuHdl; - - if (childMenuHdl != NULL) { - ChkErr(SetMenuItemHierarchicalID, macMenuHdl, - base + index, GetMenuID(childMenuHdl)); - } - - /* - * If we changed the highligthing of this menu, its - * children all have to be reconfigured so that their - * state will be reflected in the menubar. - */ - - if (!(mePtr->childMenuRefPtr->menuPtr->menuFlags - & MENU_RECONFIGURE_PENDING)) { - mePtr->childMenuRefPtr->menuPtr->menuFlags - |= MENU_RECONFIGURE_PENDING; - Tcl_DoWhenIdle(ReconfigureMacintoshMenu, - mePtr->childMenuRefPtr->menuPtr); - } - } - } - - if ((mePtr->type != CASCADE_ENTRY) && (mePtr->accelPtr != NULL)) { - int accelLen, modifiers = 0, hasCmd = 0; - EntryGeometry *geometryPtr = (EntryGeometry *) - mePtr->platformEntryData; - int offset = geometryPtr->accelTextStart; - char *accel = Tcl_GetStringFromObj(mePtr->accelPtr, &accelLen); - - accelLen -= offset; - accel += offset; - if (mePtr->entryFlags & ENTRY_OPTION_ACCEL) { - modifiers |= kMenuOptionModifier; - } - if (mePtr->entryFlags & ENTRY_SHIFT_ACCEL) { - modifiers |= kMenuShiftModifier; - } - if (mePtr->entryFlags & ENTRY_CONTROL_ACCEL) { - modifiers |= kMenuControlModifier; - } - if (mePtr->entryFlags & ENTRY_COMMAND_ACCEL) { - hasCmd = 1; - } - if (accelLen == 1) { - if (hasCmd || (modifiers != 0 && modifiers != - kMenuShiftModifier)) { - SetItemCmd(macMenuHdl, base + index, accel[0]); - if (!hasCmd) { - modifiers |= kMenuNoCommandModifier; - } - } - } else { - /* - * Convert from accelerator names to Carbon menu glyphs. - */ - - struct Glyph { - const char *name; - const size_t len; - const char glyph; - }; -#define GLYPH(n, g) { #n, sizeof(#n)-1, kMenu##g##Glyph } - static const struct Glyph glyphs[] = { - GLYPH(PageUp, PageUp), - GLYPH(PageDown, PageDown), - GLYPH(Left, LeftArrow), - GLYPH(Right, RightArrow), - GLYPH(Up, UpArrow), - GLYPH(Down, DownArrow), - GLYPH(Escape, Escape), - GLYPH(Clear, Clear), - GLYPH(Enter, Enter), - GLYPH(Backspace,DeleteLeft), - GLYPH(Space, Space), - GLYPH(Tab, TabRight), - GLYPH(Delete, DeleteRight), - GLYPH(Home, NorthwestArrow), - GLYPH(End, SoutheastArrow), - GLYPH(Return, Return), - GLYPH(Help, Help), - GLYPH(Power, Power), - { NULL, 0, 0} - }; -#undef GLYPH - const struct Glyph *g = glyphs; - char glyph = 0; - - if (accel[0] == 'F' && accelLen < 4 && - (accel[1] > '0' && accel[1] <= '9')) { - int fkey = accel[1] - '0'; - - if (accelLen == 3) { - if (accel[2] >= '0' && accel[2] <= '9') { - fkey = 10 * fkey + (accel[2] - '0'); - } else { - fkey = 0; - } - } - if (fkey >= 1 && fkey <= 12) { - glyph = kMenuF1Glyph + fkey - 1; - } else if (fkey >= 13 && fkey <= 15) { - glyph = kMenuF13Glyph + fkey - 13; - } - } else while (g->name) { - if (accel[0] == g->name[0] && - (size_t)accelLen == g->len && - !strncasecmp(accel, g->name, g->len)) { - glyph = g->glyph; - break; - } - g++; - } - if (glyph) { - ChkErr(SetMenuItemKeyGlyph, macMenuHdl, base + index, - glyph); - if (!hasCmd) { - modifiers |= kMenuNoCommandModifier; - } - geometryPtr->accelGlyph = glyph; - } - } - ChkErr(SetMenuItemModifiers, macMenuHdl, base + index, - modifiers); - } - } - } -} - -/* - *---------------------------------------------------------------------- - * - * ReconfigureMacintoshMenu -- - * - * Rebuilds the Macintosh MenuHandle items from the menu. Called usually - * as an idle handler, but can be called synchronously if the menu is - * about to be posted. - * - * Results: - * None. - * - * Side effects: - * Configuration information get set for mePtr; old resources get freed, - * if any need it. - * - *---------------------------------------------------------------------- - */ - -void -ReconfigureMacintoshMenu( - ClientData clientData) /* Information about menu entry; may or may - * not already have values for some fields. */ -{ - TkMenu *menuPtr = clientData; - MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl; - MenuHandle helpMenuHdl = NULL; - - menuPtr->menuFlags &= ~MENU_RECONFIGURE_PENDING; - - if (NULL == macMenuHdl) { - return; - } - - ReconfigureIndividualMenu(menuPtr, macMenuHdl, 0); - - if (GetMenuID(macMenuHdl) == currentHelpMenuID) { - MenuItemIndex helpIndex; - - HMGetHelpMenu(&helpMenuHdl,&helpIndex); - if (helpMenuHdl != NULL) { - ReconfigureIndividualMenu(menuPtr, helpMenuHdl, helpIndex - 1); - } - } - - if (menuPtr->menuType == MENUBAR) { - if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) { - Tcl_DoWhenIdle(DrawMenuBarWhenIdle, NULL); - menuBarFlags |= MENUBAR_REDRAW_PENDING; - } - } -} - -/* - *---------------------------------------------------------------------- - * - * CompleteIdlers -- - * - * Completes all idle handling so that the menus are in sync when the - * user invokes them with the mouse. - * - * Results: - * None. - * - * Side effects: - * The Macintosh menu handles are flushed out. - * - *---------------------------------------------------------------------- - */ - -void -CompleteIdlers( - TkMenu *menuPtr) /* The menu we are completing. */ -{ - int i; - - if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) { - Tcl_CancelIdleCall(ReconfigureMacintoshMenu, menuPtr); - ReconfigureMacintoshMenu(menuPtr); - } - - for (i = 0; i < menuPtr->numEntries; i++) { - if ((menuPtr->entries[i]->type == CASCADE_ENTRY) && - (menuPtr->entries[i]->childMenuRefPtr != NULL) && - (menuPtr->entries[i]->childMenuRefPtr->menuPtr != NULL)) { - CompleteIdlers(menuPtr->entries[i]->childMenuRefPtr->menuPtr); - } - } -} - -/* - *---------------------------------------------------------------------- - * - * TkpPostMenu -- - * - * Posts a menu on the screen - * - * Results: - * None. - * - * Side effects: - * The menu is posted and handled. - * - *---------------------------------------------------------------------- - */ - -int -TkpPostMenu( - Tcl_Interp *interp, /* The interpreter this menu lives in */ - TkMenu *menuPtr, /* The menu we are posting */ - int x, /* The global x-coordinate of the top, left- - * hand corner of where the menu is supposed - * to be posted. */ - int y) /* The global y-coordinate */ -{ - MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl; - long popUpResult; - int result; - - if (inPostMenu > 0) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "Cannot call post menu while already posting menu", -1)); - Tcl_SetErrorCode(interp, "TK", "MENU", "POSTING", NULL); - result = TCL_ERROR; - } else { - short menuID; - Window window; - int oldWidth = menuPtr->totalWidth; - - inPostMenu++; - result = TkPreprocessMenu(menuPtr); - - /* - * The post commands could have deleted the menu, which means we are - * dead and should go away. - */ - - if (result != TCL_OK || !menuPtr->tkwin) { - goto endPostMenu; - } - - CompleteIdlers(menuPtr); - if (menuBarFlags & MENUBAR_REDRAW_PENDING) { - Tcl_CancelIdleCall(DrawMenuBarWhenIdle, NULL); - DrawMenuBarWhenIdle(NULL); - } - RecursivelyInsertMenu(menuPtr); - - TkMacOSXTrackingLoop(1); - popUpResult = PopUpMenuSelect(macMenuHdl, y, x, menuPtr->active); - TkMacOSXTrackingLoop(0); - menuPtr->totalWidth = oldWidth; - - /* - * Simulate the mouse up. - */ - - window = Tk_WindowId(menuPtr->tkwin); - TkGenerateButtonEventForXPointer(window); - - /* - * Dispatch the command. - */ - - menuID = HiWord(popUpResult); - if (menuID != 0) { - result = TkMacOSXDispatchMenuEvent(menuID, LoWord(popUpResult)); - } - -endPostMenu: - inPostMenu--; - } - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TkpMenuNewEntry -- - * - * Adds a pointer to a new menu entry structure with the platform- - * specific fields filled in. The Macintosh uses the platformEntryData - * field of the TkMenuEntry record to store geometry information. - * - * Results: - * Standard TCL error. - * - * Side effects: - * Storage gets allocated. New menu entry data is put into the - * platformEntryData field of the mePtr. - * - *---------------------------------------------------------------------- - */ - -int -TkpMenuNewEntry( - TkMenuEntry *mePtr) /* The menu we are adding an entry to */ -{ - EntryGeometry *geometryPtr = ckalloc(sizeof(EntryGeometry)); - TkMenu *menuPtr = mePtr->menuPtr; - - geometryPtr->accelTextStart = 0; - geometryPtr->accelTextWidth = 0; - geometryPtr->nonAccelMargin = 0; - geometryPtr->modifierWidth = 0; - geometryPtr->modifierNum = 0; - geometryPtr->accelGlyph = 0; - mePtr->platformEntryData = (TkMenuPlatformEntryData) geometryPtr; - if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) { - menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; - Tcl_DoWhenIdle(ReconfigureMacintoshMenu, menuPtr); - } - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * Tk_MacOSXTurnOffMenus -- - * - * Turns off all the menu drawing code. This is more than just disabling - * the "menu" command, this means that Tk will NEVER touch the menubar. - * It is needed in the Plugin, where Tk does not own the menubar. - * - * Results: - * None. - * - * Side effects: - * A flag is set which will disable all menu drawing. - * - *---------------------------------------------------------------------- - */ - -void -Tk_MacOSXTurnOffMenus(void) -{ - gNoTkMenus = 1; -} - -/* - *---------------------------------------------------------------------- - * - * DrawMenuBarWhenIdle -- - * - * Update the menu bar next time there is an idle event. - * - * Results: - * None. - * - * Side effects: - * Menu bar is redrawn. - * - *---------------------------------------------------------------------- - */ - -void -DrawMenuBarWhenIdle( - ClientData clientData) /* ignored here */ -{ - TkMenuReferences *menuRefPtr; - TkMenu *appleMenuPtr, *helpMenuPtr, *menuBarPtr = NULL; - MenuHandle macMenuHdl; - Tcl_HashEntry *hashEntryPtr; - - /* - * If we have been turned off, exit. - */ - - if (gNoTkMenus) { - return; - } - - /* - * We need to clear the apple and help menus of any extra items. - */ - - if (currentAppleMenuID != 0) { - hashEntryPtr = Tcl_FindHashEntry(&commandTable, - (char*)(intptr_t)currentAppleMenuID); - appleMenuPtr = Tcl_GetHashValue(hashEntryPtr); - TkpDestroyMenu(appleMenuPtr); - TkpNewMenu(appleMenuPtr); - appleMenuPtr->menuFlags &= ~MENU_APPLE_MENU; - appleMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; - Tcl_DoWhenIdle(ReconfigureMacintoshMenu, appleMenuPtr); - } - - if (currentHelpMenuID != 0) { - hashEntryPtr = Tcl_FindHashEntry(&commandTable, - (char*)(intptr_t)currentHelpMenuID); - helpMenuPtr = Tcl_GetHashValue(hashEntryPtr); - TkpDestroyMenu(helpMenuPtr); - TkpNewMenu(helpMenuPtr); - helpMenuPtr->menuFlags &= ~MENU_HELP_MENU; - helpMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; - Tcl_DoWhenIdle(ReconfigureMacintoshMenu, helpMenuPtr); - } - - /* - * We need to find the clone of this menu that is the menubar. Once we do - * that, for every cascade in the menu, we need to insert the Mac menu in - * the Mac menubar. Finally, we need to redraw the menubar. - */ - - menuRefPtr = NULL; - if (currentMenuBarName != NULL) { - menuRefPtr = TkFindMenuReferences(currentMenuBarInterp, - currentMenuBarName); - } - if (menuRefPtr) { - TkMenu *menuPtr; - TkMenu *cascadeMenuPtr; - char *appleMenuName, *helpMenuName; - int appleIndex = -1, helpIndex = -1, i; - - menuPtr = menuRefPtr->menuPtr; - if (menuPtr != NULL) { - TkMenuReferences *specialMenuRefPtr; - TkMenuEntry *specialEntryPtr; - - appleMenuName = ckalloc(strlen(currentMenuBarName) + 1 + - strlen(".apple") + 1); - sprintf(appleMenuName, "%s.apple", Tk_PathName(menuPtr->tkwin)); - specialMenuRefPtr = TkFindMenuReferences(currentMenuBarInterp, - appleMenuName); - if ((specialMenuRefPtr != NULL) - && (specialMenuRefPtr->menuPtr != NULL)) { - for (specialEntryPtr = specialMenuRefPtr->parentEntryPtr; - specialEntryPtr != NULL; - specialEntryPtr = specialEntryPtr->nextCascadePtr) { - if (specialEntryPtr->menuPtr == menuPtr) { - appleIndex = specialEntryPtr->index; - break; - } - } - } - ckfree(appleMenuName); - - helpMenuName = ckalloc(strlen(currentMenuBarName) + 1 + - strlen(".help") + 1); - sprintf(helpMenuName, "%s.help", Tk_PathName(menuPtr->tkwin)); - specialMenuRefPtr = TkFindMenuReferences(currentMenuBarInterp, - helpMenuName); - if ((specialMenuRefPtr != NULL) - && (specialMenuRefPtr->menuPtr != NULL)) { - for (specialEntryPtr = specialMenuRefPtr->parentEntryPtr; - specialEntryPtr != NULL; - specialEntryPtr = specialEntryPtr->nextCascadePtr) { - if (specialEntryPtr->menuPtr == menuPtr) { - helpIndex = specialEntryPtr->index; - break; - } - } - } - ckfree(helpMenuName); - } - - for (menuBarPtr = menuPtr; - (menuBarPtr != NULL) && (menuBarPtr->menuType != MENUBAR); - menuBarPtr = menuBarPtr->nextInstancePtr) { - /* - * Null loop body. - */ - } - - if (menuBarPtr) { - if (menuBarPtr->tearoff != menuPtr->tearoff) { - if (menuBarPtr->tearoff) { - appleIndex = (-1 == appleIndex) ? appleIndex - : appleIndex + 1; - helpIndex = (-1 == helpIndex) ? helpIndex - : helpIndex + 1; - } else { - appleIndex = (-1 == appleIndex) ? appleIndex - : appleIndex - 1; - helpIndex = (-1 == helpIndex) ? helpIndex - : helpIndex - 1; - } - } - ClearMenuBar(); - - if (appleIndex == -1) { - InsertMenu(tkAppleMenu, 0); - currentAppleMenuID = 0; - tkCurrentAppleMenu = tkAppleMenu; - } else { - short appleID; - - appleMenuPtr = menuBarPtr->entries[appleIndex] - ->childMenuRefPtr->menuPtr; - TkpDestroyMenu(appleMenuPtr); - TkMacOSXGetNewMenuID(appleMenuPtr->interp, appleMenuPtr, 0, - &appleID); - macMenuHdl = NewMenu(appleID, "\p\024"); - appleMenuPtr->platformData = ckalloc(sizeof(MacMenu)); - ((MacMenu *)appleMenuPtr->platformData)->menuHdl - = macMenuHdl; - appleMenuPtr->menuFlags |= MENU_APPLE_MENU; - if (!(appleMenuPtr->menuFlags - & MENU_RECONFIGURE_PENDING)) { - appleMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; - Tcl_DoWhenIdle(ReconfigureMacintoshMenu, appleMenuPtr); - } - InsertMenu(macMenuHdl, 0); - RecursivelyInsertMenu(appleMenuPtr); - currentAppleMenuID = appleID; - tkCurrentAppleMenu = macMenuHdl; - } - if (helpIndex == -1) { - currentHelpMenuID = 0; - } - - for (i = 0; i < menuBarPtr->numEntries; i++) { - if (i == appleIndex) { - if (menuBarPtr->entries[i]->state == ENTRY_DISABLED) { - DisableMenuItem(((MacMenu *) menuBarPtr->entries[i] - ->childMenuRefPtr->menuPtr - ->platformData)->menuHdl, 0); - } else { - EnableMenuItem(((MacMenu *) menuBarPtr->entries[i] - ->childMenuRefPtr->menuPtr - ->platformData)->menuHdl, 0); - } - continue; - } else if (i == helpIndex) { - TkMenu *helpMenuPtr = menuBarPtr->entries[i] - ->childMenuRefPtr->menuPtr; - - if (helpMenuPtr == NULL) { - continue; - } - helpMenuPtr->menuFlags |= MENU_HELP_MENU; - if (!(helpMenuPtr->menuFlags - & MENU_RECONFIGURE_PENDING)) { - helpMenuPtr->menuFlags - |= MENU_RECONFIGURE_PENDING; - Tcl_DoWhenIdle(ReconfigureMacintoshMenu, helpMenuPtr); - } - macMenuHdl = - ((MacMenu *) helpMenuPtr->platformData)->menuHdl; - currentHelpMenuID = GetMenuID(macMenuHdl); - } else if (menuBarPtr->entries[i]->type - == CASCADE_ENTRY) { - if ((menuBarPtr->entries[i]->childMenuRefPtr != NULL) - && menuBarPtr->entries[i]->childMenuRefPtr - ->menuPtr != NULL) { - cascadeMenuPtr = menuBarPtr->entries[i] - ->childMenuRefPtr->menuPtr; - macMenuHdl = ((MacMenu *) cascadeMenuPtr - ->platformData)->menuHdl; - DeleteMenu(GetMenuID(macMenuHdl)); - InsertMenu(macMenuHdl, 0); - RecursivelyInsertMenu(cascadeMenuPtr); - if (menuBarPtr->entries[i]->state == ENTRY_DISABLED) { - DisableMenuItem(((MacMenu *) menuBarPtr->entries[i] - ->childMenuRefPtr->menuPtr - ->platformData)->menuHdl, 0); - } else { - EnableMenuItem(((MacMenu *) menuBarPtr->entries[i] - ->childMenuRefPtr->menuPtr - ->platformData)->menuHdl, 0); - } - } - } - } - } - } - if (!menuRefPtr || !menuBarPtr) { - SetDefaultMenubar(); - } - DrawMenuBar(); - menuBarFlags &= ~MENUBAR_REDRAW_PENDING; -} - -/* - *---------------------------------------------------------------------- - * - * RecursivelyInsertMenu -- - * - * Puts all of the cascades of this menu in the Mac hierarchical list. - * - * Results: - * None. - * - * Side effects: - * The menubar is changed. - * - *---------------------------------------------------------------------- - */ - -void -RecursivelyInsertMenu( - TkMenu *menuPtr) /* All of the cascade items in this menu will - * be inserted into the mac menubar. */ -{ - int i; - TkMenu *cascadeMenuPtr; - MenuHandle macMenuHdl; - - for (i = 0; i < menuPtr->numEntries; i++) { - if (menuPtr->entries[i]->type == CASCADE_ENTRY) { - if ((menuPtr->entries[i]->childMenuRefPtr != NULL) && - (menuPtr->entries[i]->childMenuRefPtr->menuPtr != NULL)) { - cascadeMenuPtr = menuPtr->entries[i]->childMenuRefPtr->menuPtr; - macMenuHdl = - ((MacMenu *) cascadeMenuPtr->platformData)->menuHdl; - InsertMenu(macMenuHdl, -1); - RecursivelyInsertMenu(cascadeMenuPtr); - } - } - } -} - -/* - *---------------------------------------------------------------------- - * - * RecursivelyDeleteMenu -- - * - * Takes all of the cascades of this menu out of the Mac hierarchical - * list. - * - * Results: - * None. - * - * Side effects: - * The menubar is changed. - * - *---------------------------------------------------------------------- - */ - -void -RecursivelyDeleteMenu( - TkMenu *menuPtr) /* All of the cascade items in this menu will - * be deleted from the mac menubar. */ -{ - int i; - TkMenu *cascadeMenuPtr; - MenuHandle macMenuHdl; - - for (i = 0; i < menuPtr->numEntries; i++) { - if (menuPtr->entries[i]->type == CASCADE_ENTRY) { - if ((menuPtr->entries[i]->childMenuRefPtr != NULL) && - (menuPtr->entries[i]->childMenuRefPtr->menuPtr != NULL)) { - cascadeMenuPtr = menuPtr->entries[i]->childMenuRefPtr->menuPtr; - macMenuHdl = - ((MacMenu *) cascadeMenuPtr->platformData)->menuHdl; - DeleteMenu(GetMenuID(macMenuHdl)); - RecursivelyDeleteMenu(cascadeMenuPtr); - } - } - } -} - -/* - *---------------------------------------------------------------------- - * - * SetDefaultMenubar -- - * - * Puts the Apple, File and Edit menus into the Macintosh menubar. - * - * Results: - * None. - * - * Side effects: - * The menubar is changed. - * - *---------------------------------------------------------------------- - */ - -void -SetDefaultMenubar(void) -{ - if (currentMenuBarName != NULL) { - ckfree(currentMenuBarName); - currentMenuBarName = NULL; - } - currentMenuBarOwner = NULL; - ClearMenuBar(); - InsertMenu(tkAppleMenu, 0); - InsertMenu(tkFileMenu, 0); - InsertMenu(tkEditMenu, 0); - if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) { - Tcl_DoWhenIdle(DrawMenuBarWhenIdle, NULL); - menuBarFlags |= MENUBAR_REDRAW_PENDING; - } -} - -/* - *---------------------------------------------------------------------- - * - * TkpSetMainMenubar -- - * - * Puts the menu associated with a window into the menubar. Should only - * be called when the window is in front. - * - * Results: - * None. - * - * Side effects: - * The menubar is changed. - * - *---------------------------------------------------------------------- - */ - -void -TkpSetMainMenubar( - Tcl_Interp *interp, /* The interpreter of the application */ - Tk_Window tkwin, /* The frame we are setting up */ - const char *menuName) /* The name of the menu to put in front. If - * NULL, use the default menu bar. */ -{ - TkWindow *winPtr = (TkWindow *) tkwin; - WindowRef macWindowPtr; - WindowRef frontNonFloating; - - macWindowPtr = TkMacOSXDrawableWindow(winPtr->window); - - frontNonFloating = ActiveNonFloatingWindow(); - if ((macWindowPtr == NULL) || (macWindowPtr != frontNonFloating)) { - return; - } - - if ((currentMenuBarInterp != interp) || (currentMenuBarOwner != tkwin) - || (currentMenuBarName == NULL) || (menuName == NULL) - || (strcmp(menuName, currentMenuBarName) != 0)) { - Tk_Window searchWindow; - TopLevelMenubarList *listPtr; - - if (currentMenuBarName != NULL) { - ckfree(currentMenuBarName); - } - - if (menuName == NULL) { - searchWindow = tkwin; - if (strcmp(Tk_Class(searchWindow), "Menu") == 0) { - TkMenuReferences *menuRefPtr; - - menuRefPtr = TkFindMenuReferences(interp, Tk_PathName(tkwin)); - if (menuRefPtr != NULL) { - TkMenu *menuPtr = menuRefPtr->menuPtr; - - if (menuPtr != NULL) { - searchWindow = menuPtr->masterMenuPtr->tkwin; - } - } - } - for (; searchWindow != NULL; - searchWindow = Tk_Parent(searchWindow)) { - for (listPtr = windowListPtr; listPtr != NULL; - listPtr = listPtr->nextPtr) { - if (listPtr->tkwin == searchWindow) { - break; - } - } - if (listPtr != NULL) { - menuName = Tk_PathName( - listPtr->menuPtr->masterMenuPtr->tkwin); - break; - } - } - } - - if (menuName == NULL) { - currentMenuBarName = NULL; - } else { - currentMenuBarName = ckalloc(strlen(menuName) + 1); - strcpy(currentMenuBarName, menuName); - } - currentMenuBarOwner = tkwin; - currentMenuBarInterp = interp; - } - if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) { - Tcl_DoWhenIdle(DrawMenuBarWhenIdle, NULL); - menuBarFlags |= MENUBAR_REDRAW_PENDING; - } -} - -/* - *---------------------------------------------------------------------- - * - * TkpSetWindowMenuBar -- - * - * Associates a given menu with a window. - * - * Results: - * None. - * - * Side effects: - * On Windows and UNIX, associates the platform menu with the platform - * window. - * - *---------------------------------------------------------------------- - */ - -void -TkpSetWindowMenuBar( - Tk_Window tkwin, /* The window we are setting the menu in */ - TkMenu *menuPtr) /* The menu we are setting */ -{ - TopLevelMenubarList *listPtr, *prevPtr; - - /* - * Remove any existing reference to this window. - */ - - for (prevPtr = NULL, listPtr = windowListPtr; - listPtr != NULL; - prevPtr = listPtr, listPtr = listPtr->nextPtr) { - if (listPtr->tkwin == tkwin) { - break; - } - } - - if (listPtr != NULL) { - if (prevPtr != NULL) { - prevPtr->nextPtr = listPtr->nextPtr; - } else { - windowListPtr = listPtr->nextPtr; - } - ckfree(listPtr); - } - - if (menuPtr != NULL) { - listPtr = ckalloc(sizeof(TopLevelMenubarList)); - listPtr->nextPtr = windowListPtr; - windowListPtr = listPtr; - listPtr->tkwin = tkwin; - listPtr->menuPtr = menuPtr; - } -} - -/* - *---------------------------------------------------------------------- - * - * EventuallyInvokeMenu -- - * - * This IdleTime callback actually invokes the menu command scheduled in - * TkMacOSXDispatchMenuEvent. - * - * Results: - * None. - * - * Side effects: - * Commands get executed. - * - *---------------------------------------------------------------------- - */ - -void -EventuallyInvokeMenu ( - ClientData data) -{ - struct MenuCommandHandlerData *realData = data; - int code; - - code = TkInvokeMenu(realData->menuPtr->interp, realData->menuPtr, - realData->index); - - if (code != TCL_OK && code != TCL_CONTINUE && code != TCL_BREAK) { - Tcl_AddErrorInfo(realData->menuPtr->interp, "\n (menu invoke)"); - Tcl_BackgroundException(realData->menuPtr->interp, code); - } - - if (realData->menuPtr->tkwin) { - RecursivelyClearActiveMenu(realData->menuPtr); - } - TkMacOSXClearMenubarActive(); - - Tcl_Release(realData->menuPtr->interp); - Tcl_Release(realData->menuPtr); -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXDispatchMenuEvent -- - * - * Given a menu id and an item, dispatches the command associated with - * it. - * - * Results: - * None. - * - * Side effects: - * Commands for the event are scheduled for execution at idle time. - * - *---------------------------------------------------------------------- - */ - -int -TkMacOSXDispatchMenuEvent( - int menuID, /* The menu id of the menu we are invoking */ - int index) /* The one-based index of the item that was - * selected. */ -{ - int result = TCL_OK; - - if (menuID != 0) { - if (menuID == kHMHelpMenuID) { - if (currentMenuBarOwner != NULL) { - TkMenuReferences *helpMenuRef; - char *helpMenuName = ckalloc(strlen(currentMenuBarName) - + strlen(".help") + 1); - - sprintf(helpMenuName, "%s.help", currentMenuBarName); - helpMenuRef = TkFindMenuReferences(currentMenuBarInterp, - helpMenuName); - ckfree(helpMenuName); - if ((helpMenuRef != NULL) && (helpMenuRef->menuPtr != NULL)) { - MenuRef outHelpMenu; - MenuItemIndex itemIndex; - int newIndex; - - HMGetHelpMenu(&outHelpMenu, &itemIndex); - newIndex = index - itemIndex; - result = TkInvokeMenu(currentMenuBarInterp, - helpMenuRef->menuPtr, newIndex); - } - } - } else { - Tcl_HashEntry *commandEntryPtr = - Tcl_FindHashEntry(&commandTable, (char*)(intptr_t)menuID); - if (commandEntryPtr != NULL) { - TkMenu *menuPtr = Tcl_GetHashValue(commandEntryPtr); - - if ((currentAppleMenuID == menuID) - && (index > menuPtr->numEntries + 1)) { - /* - * We don't need to do anything here, the standard - * Application event handler will open the built-in Apple - * menu item for us. - */ - - result = TCL_OK; - } else { - struct MenuCommandHandlerData *data = - ckalloc(sizeof(struct MenuCommandHandlerData)); - - Tcl_Preserve(menuPtr->interp); - Tcl_Preserve(menuPtr); - data->menuPtr = menuPtr; - data->index = index - 1; - Tcl_DoWhenIdle(EventuallyInvokeMenu, data); - /* result = TkInvokeMenu(menuPtr->interp, menuPtr, index - 1); */ - } - } else { - return TCL_ERROR; - } - } - } - return result; -} - -/* - *---------------------------------------------------------------------- - * - * GetMenuIndicatorGeometry -- - * - * Gets the width and height of the indicator area of a menu. - * - * Results: - * widthPtr and heightPtr are set. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -GetMenuIndicatorGeometry ( - TkMenu *menuPtr, /* The menu we are drawing */ - TkMenuEntry *mePtr, /* The entry we are measuring */ - Tk_Font tkfont, /* Precalculated font */ - const Tk_FontMetrics *fmPtr,/* Precalculated font metrics */ - int *widthPtr, /* The resulting width */ - int *heightPtr) /* The resulting height */ -{ - *heightPtr = fmPtr->linespace + menuItemExtraHeight; - if (IS_THEME_MENU_FONT(tkfont)) { - *widthPtr = menuMarkColumnWidth; - } else { - const char markChar = FindMarkCharacter(mePtr); - const char *markUtf = NULL; - int len; - - len = GetUtfMarkCharacter(markChar, &markUtf); - *widthPtr = Tk_TextWidth(tkfont, markUtf, len) + 2*menuMarkIndent; - } -} - -/* - *---------------------------------------------------------------------- - * - * GetMenuAccelGeometry -- - * - * Gets the width and height of the accelerator area of a menu. - * - * Results: - * widthPtr and heightPtr are set. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -GetMenuAccelGeometry ( - TkMenu *menuPtr, /* The menu we are measuring */ - TkMenuEntry *mePtr, /* The entry we are measuring */ - Tk_Font tkfont, /* The precalculated font */ - const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */ - int *modWidthPtr, /* The width of all of the key - * modifier symbols. */ - int *textWidthPtr, /* The resulting width */ - int *heightPtr) /* The resulting height */ -{ - *heightPtr = fmPtr->linespace + menuItemExtraHeight; - *modWidthPtr = menuSymbols[COMMAND_SYMBOL].width; - *textWidthPtr = 0; - if (mePtr->type != CASCADE_ENTRY && mePtr->accelLength > 0) { - const char *accel = (mePtr->accelPtr == NULL) ? "" - : Tcl_GetString(mePtr->accelPtr); - EntryGeometry *geometryPtr = (EntryGeometry*)mePtr->platformEntryData; - - if (IS_THEME_MENU_FONT(tkfont)) { - CFStringRef cfStr; - int width = 0; - int maxWidth = ((TkFont *)tkfont)->fm.maxWidth; - - if (geometryPtr->accelGlyph) { - cfStr = CFStringCreateWithBytes(NULL, - (UInt8*)&geometryPtr->accelGlyph, 1, - kTextEncodingMacKeyboardGlyphs, false); - if (cfStr) { - width = MeasureThemeText(cfStr, kThemeMenuItemCmdKeyFont); - CFRelease(cfStr); - } - } - if (!(mePtr->entryFlags & ENTRY_ACCEL_MASK)) { - if (!geometryPtr->accelGlyph) { - width = Tk_TextWidth(tkfont, accel, mePtr->accelLength); - } - *textWidthPtr = maxWidth; - if (width < maxWidth) { - *modWidthPtr = 0; - } else { - *modWidthPtr = width - maxWidth; - } - } else { - if (!geometryPtr->accelGlyph) { - width = Tk_TextWidth(tkfont, accel + - geometryPtr->accelTextStart, mePtr->accelLength - - geometryPtr->accelTextStart); - } - if (width < maxWidth) { - *textWidthPtr = maxWidth; - } else { - *textWidthPtr = width; - } - if (geometryPtr->modifierNum) { - *modWidthPtr = geometryPtr->modifierWidth; - } - } - } else { - *textWidthPtr = Tk_TextWidth(tkfont, accel, mePtr->accelLength); - } - } -} - -/* - *---------------------------------------------------------------------- - * - * GetTearoffEntryGeometry -- - * - * Gets the width and height of of a tearoff entry. - * - * Results: - * widthPtr and heightPtr are set. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -GetTearoffEntryGeometry ( - TkMenu *menuPtr, /* The menu we are drawing */ - TkMenuEntry *mePtr, /* The entry we are measuring */ - Tk_Font tkfont, /* The precalculated font */ - const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */ - int *widthPtr, /* The resulting width */ - int *heightPtr) /* The resulting height */ -{ -#ifdef USE_TK_MDEF - const int useMDEF = ((MacMenu *) menuPtr->platformData)->useMDEF; -#endif - if (useMDEF && menuPtr->menuType != TEAROFF_MENU) { - *heightPtr = fmPtr->linespace + menuItemExtraHeight; - *widthPtr = menuPtr->totalWidth; - } else { - *widthPtr = *heightPtr = 0; - } -} - -/* - *---------------------------------------------------------------------- - * - * GetMenuSeparatorGeometry -- - * - * Gets the width and height of menu separator. - * - * Results: - * widthPtr and heightPtr are set. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -GetMenuSeparatorGeometry( - TkMenu *menuPtr, /* The menu we are drawing */ - TkMenuEntry *mePtr, /* The entry we are measuring */ - Tk_Font tkfont, /* The precalculated font */ - const Tk_FontMetrics *fmPtr,/* The precalcualted font metrics */ - int *widthPtr, /* The resulting width */ - int *heightPtr) /* The resulting height */ -{ - *widthPtr = 0; - *heightPtr = menuSeparatorHeight; -} - -/* - *---------------------------------------------------------------------- - * - * DrawMenuEntryIndicator -- - * - * This procedure draws the indicator part of a menu. - * - * Results: - * None. - * - * Side effects: - * Commands are output to X to display the menu in its - * current mode. - * - *---------------------------------------------------------------------- - */ - -void -DrawMenuEntryIndicator( - TkMenu *menuPtr, /* The menu we are drawing */ - TkMenuEntry *mePtr, /* The entry we are drawing */ - Drawable d, /* The drawable we are drawing */ - GC gc, /* The GC we are drawing with */ - GC indicatorGC, /* The GC to use for the indicator */ - Tk_Font tkfont, /* The precalculated font */ - const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */ - int x, /* topleft hand corner of entry */ - int y, /* topleft hand corner of entry */ - int width, /* width of entry */ - int height) /* height of entry */ -{ - if ((mePtr->type == CHECK_BUTTON_ENTRY) || - (mePtr->type == RADIO_BUTTON_ENTRY)) { - if (mePtr->indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED)) { - short mark; - int baseline = y + (height + fmPtr->ascent - fmPtr->descent)/2; - - GetItemMark(((MacMenu *) menuPtr->platformData)->menuHdl, - mePtr->index + 1, &mark); - if (IS_THEME_MENU_FONT(tkfont)) { - ThemeFontID font = kThemeMenuItemMarkFont; - TextEncoding encoding = GetApplicationTextEncoding(); - CFStringRef cfStr; - ThemeDrawState drawState; - Rect bounds = {y, x + menuMarkIndent, y + height, x + width}; - - if (mark < kSpaceCharCode) { - font = kThemeMenuItemCmdKeyFont; - encoding = kTextEncodingMacKeyboardGlyphs; - } - switch (mePtr->state) { - case ENTRY_ACTIVE: - drawState = kThemeStatePressed; - break; - case ENTRY_DISABLED: - drawState = kThemeStateInactive; - break; - default: - drawState = kThemeStateActive; - break; - } - cfStr = CFStringCreateWithBytes(NULL, (UInt8*)&mark, 1, - encoding, false); - if (cfStr) { - DrawThemeText(d, gc, cfStr, font, drawState, &bounds, - baseline, teFlushDefault); - CFRelease(cfStr); - } - } else if (mark != 0) { - const char *markUtf = NULL; - int len; - - len = GetUtfMarkCharacter(mark, &markUtf); - Tk_DrawChars(menuPtr->display, d, gc, tkfont, markUtf, len, - x + menuMarkIndent, baseline); - } - } - } -} - -#ifdef USE_TK_MDEF -/* - *---------------------------------------------------------------------- - * - * DrawMenuBackground -- - * - * If Appearance is present, draws the Appearance background - * - * Results: - * Nothing - * - * Side effects: - * Commands are output to X to display the menu in its current mode. - * - *---------------------------------------------------------------------- - */ - -void -DrawMenuBackground( - TkMenu *menuPtr, - Rect *menuRectPtr, /* The menu rect */ - Drawable d) /* What we are drawing into */ -{ - Tk_3DBorder border; - - EraseMenuBackground(((MacMenu *) menuPtr->platformData)->menuHdl, - menuRectPtr, ((MacDrawable*)d)->context); - border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr); - Tk_Fill3DRectangle(menuPtr->tkwin, d, border, - menuRectPtr->left, menuRectPtr->top, - menuRectPtr->right - menuRectPtr->left, - menuRectPtr->bottom - menuRectPtr->top, 0, TK_RELIEF_FLAT); -} -#endif /* USE_TK_MDEF */ - -/* - *---------------------------------------------------------------------- - * - * DrawMenuEntryAccelerator -- - * - * This procedure draws the accelerator part of a menu. - * - * Results: - * None. - * - * Side effects: - * Commands are output to X to display the menu in its current mode. - * - *---------------------------------------------------------------------- - */ - -void -DrawMenuEntryAccelerator( - TkMenu *menuPtr, /* The menu we are drawing */ - TkMenuEntry *mePtr, /* The entry we are drawing */ - Drawable d, /* The drawable we are drawing in */ - GC gc, /* The gc to draw into */ - Tk_Font tkfont, /* The precalculated font */ - const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */ - Tk_3DBorder activeBorder, /* border for menu background */ - int x, /* The left side of the entry */ - int y, /* The top of the entry */ - int width, /* The width of the entry */ - int height, /* The height of the entry */ - int drawArrow) /* Whether or not to draw cascade arrow */ -{ - if (mePtr->type != CASCADE_ENTRY && mePtr->accelLength > 0) { - const char *accel = (mePtr->accelPtr == NULL) ? "" - : Tcl_GetString(mePtr->accelPtr); - EntryGeometry *geometryPtr = (EntryGeometry*)mePtr->platformEntryData; - int leftEdge = x + width - geometryPtr->accelTextWidth; - int baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2; - - if (IS_THEME_MENU_FONT(tkfont)) { - CFStringRef cfStr; - ThemeDrawState drawState; - - switch (mePtr->state) { - case ENTRY_ACTIVE: - drawState = kThemeStatePressed; - break; - case ENTRY_DISABLED: - drawState = kThemeStateInactive; - break; - default: - drawState = kThemeStateActive; - break; - } - if (!(mePtr->entryFlags & ENTRY_ACCEL_MASK)) { - leftEdge -= geometryPtr->modifierWidth; - } - if (geometryPtr->accelGlyph) { - Rect bounds = {y, leftEdge, y + height, leftEdge + - geometryPtr->accelTextWidth}; - - cfStr = CFStringCreateWithBytes(NULL, - (UInt8*)&geometryPtr->accelGlyph, 1, - kTextEncodingMacKeyboardGlyphs, false); - if (cfStr) { - DrawThemeText(d, gc, cfStr, kThemeMenuItemCmdKeyFont, - drawState, &bounds, baseline, teFlushDefault); - CFRelease(cfStr); - } - } else { - Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel + - geometryPtr->accelTextStart, mePtr->accelLength - - geometryPtr->accelTextStart, leftEdge, baseline); - } - if (geometryPtr->modifierNum) { - Rect bounds = {y, leftEdge - geometryPtr->modifierWidth, - y + height, leftEdge}; - - cfStr = CFStringCreateWithCharacters(NULL, - geometryPtr->modifierUniChars, - geometryPtr->modifierNum); - if (cfStr) { - DrawThemeText(d, gc, cfStr, kThemeMenuItemCmdKeyFont, - drawState, &bounds, baseline, teFlushDefault); - CFRelease(cfStr); - } - } - } else { - Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel, - mePtr->accelLength, leftEdge, baseline); - } - } -} - -/* - *---------------------------------------------------------------------- - * - * DrawMenuSeparator -- - * - * The menu separator is drawn. - * - * Results: - * None. - * - * Side effects: - * Commands are output to X to display the menu in its current mode. - * - *---------------------------------------------------------------------- - */ - -void -DrawMenuSeparator( - TkMenu *menuPtr, /* The menu we are drawing */ - TkMenuEntry *mePtr, /* The entry we are drawing */ - Drawable d, /* The drawable we are drawing into */ - GC gc, /* The gc we are drawing with */ - Tk_Font tkfont, /* The precalculated font */ - const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */ - int x, /* left coordinate of entry */ - int y, /* top coordinate of entry */ - int width, /* width of entry */ - int height) /* height of entry */ -{ - TkMacOSXDrawingContext dc; - Rect r; - - r.top = y; - r.left = x; - r.bottom = y + height; - r.right = x + width; - if (TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) { - ChkErr(DrawThemeMenuSeparator, &r); - TkMacOSXRestoreDrawingContext(&dc); - } -} - -#ifdef USE_TK_MDEF -/* - *---------------------------------------------------------------------- - * - * AppearanceEntryDrawWrapper -- - * - * It routes to the Appearance Managers DrawThemeEntry, which will then - * call us back after setting up the drawing context. - * - * Results: - * A menu entry is drawn - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -void -AppearanceEntryDrawWrapper( - TkMenuEntry *mePtr, - Rect *menuRectPtr, - MenuTrackingData *mtdPtr, - Drawable d, - Tk_FontMetrics *fmPtr, - Tk_Font tkfont, - int erase) -{ - MenuEntryUserData meData; - Rect itemRect; - ThemeMenuState theState; - ThemeMenuItemType theType; - Tk_FontMetrics entryMetrics; - - meData.mePtr = mePtr; - meData.mdefDrawable = d; - if (mePtr->fontPtr == NULL) { - meData.fmPtr = fmPtr; - meData.tkfont = tkfont; - } else { - meData.tkfont = Tk_GetFontFromObj(mePtr->menuPtr->tkwin, - mePtr->fontPtr); - Tk_GetFontMetrics(meData.tkfont, &entryMetrics); - fmPtr = &entryMetrics; - } - itemRect.left = menuRectPtr->left + mePtr->x; - itemRect.top = mtdPtr->virtualMenuTop + mePtr->y; - itemRect.right = mePtr->entryFlags & ENTRY_LAST_COLUMN ? - menuRectPtr->right : itemRect.left + mePtr->width; - itemRect.bottom = itemRect.top + mePtr->height; - - if (mePtr->state == ENTRY_ACTIVE) { - theState = kThemeMenuSelected; - } else if (mePtr->state == ENTRY_DISABLED) { - theState = kThemeMenuDisabled; - } else { - theState = kThemeMenuActive; - } - if (mePtr->type == CASCADE_ENTRY) { - theType = kThemeMenuItemHierarchical; - } else { - theType = kThemeMenuItemPlain; - } - if (erase) { - DisableScreenUpdates(); - DrawMenuBackground(mePtr->menuPtr, &itemRect, d); - } - DrawThemeMenuItem(menuRectPtr, &itemRect, - mtdPtr->virtualMenuTop, mtdPtr->virtualMenuBottom, theState, - theType | kThemeMenuItemNoBackground, tkThemeMenuItemDrawingUPP, - (unsigned long) &meData); - if (erase) { - EnableScreenUpdates(); - } -} - -/* - *---------------------------------------------------------------------- - * - * ThemeMenuItemDrawingProc -- - * - * This routine is called from the Appearance DrawThemeMenuEntry - * - * Results: - * A menu entry is drawn - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -pascal void -ThemeMenuItemDrawingProc( - const Rect *inBounds, - SInt16 inDepth, - Boolean inIsColorDevice, - SInt32 inUserData) -{ - MenuEntryUserData *meData = (MenuEntryUserData *) inUserData; - - TkpDrawMenuEntry(meData->mePtr, meData->mdefDrawable, meData->tkfont, - meData->fmPtr, inBounds->left, inBounds->top, inBounds->right - - inBounds->left + menuItemExtraWidth, inBounds->bottom - - inBounds->top + menuItemExtraHeight, 0, 1); -} -#endif /* USE_TK_MDEF */ - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXHandleTearoffMenu() -- - * - * This routine sees if the MDEF has set a menu and a mouse position for - * tearing off and makes a tearoff menu if it has. - * - * Results: - * menuPtr->interp will have the result of the tearoff command. - * - * Side effects: - * A new tearoff menu is created if it is supposed to be. - * - *---------------------------------------------------------------------- - */ - -void -TkMacOSXHandleTearoffMenu(void) -{ - /* - * Obsolete: Nothing to do. - */ -} - -/* - *-------------------------------------------------------------- - * - * TkpInitializeMenuBindings -- - * - * For every interp, initializes the bindings for Windows menus. Does - * nothing on Mac or XWindows. - * - * Results: - * None. - * - * Side effects: - * C-level bindings are setup for the interp which will handle Alt-key - * sequences for menus without beeping or interfering with user-defined - * Alt-key bindings. - * - *-------------------------------------------------------------- - */ - -void -TkpInitializeMenuBindings( - Tcl_Interp *interp, /* The interpreter to set. */ - Tk_BindingTable bindingTable) - /* The table to add to. */ -{ - /* - * Nothing to do. - */ -} - -/* - *-------------------------------------------------------------- - * - * TkpComputeMenubarGeometry -- - * - * This procedure is invoked to recompute the size and layout of a menu - * that is a menubar clone. - * - * Results: - * None. - * - * Side effects: - * Fields of menu entries are changed to reflect their current positions, - * and the size of the menu window itself may be changed. - * - *-------------------------------------------------------------- - */ - -void -TkpComputeMenubarGeometry( - TkMenu *menuPtr) /* Structure describing menu. */ -{ - TkpComputeStandardMenuGeometry(menuPtr); -} - -/* - *---------------------------------------------------------------------- - * - * DrawTearoffEntry -- - * - * This procedure draws a tearoff entry. - * - * Results: - * None. - * - * Side effects: - * Commands are output to X to display the menu in its current mode. - * - *---------------------------------------------------------------------- - */ - -void -DrawTearoffEntry( - TkMenu *menuPtr, /* The menu we are drawing */ - TkMenuEntry *mePtr, /* The entry we are drawing */ - Drawable d, /* The drawable we are drawing into */ - GC gc, /* The gc we are drawing with */ - Tk_Font tkfont, /* The font we are drawing with */ - const Tk_FontMetrics *fmPtr,/* The metrics we are drawing with */ - int x, /* Left edge of entry. */ - int y, /* Top edge of entry. */ - int width, /* Width of entry. */ - int height) /* Height of entry. */ -{ - XPoint points[2]; - int margin, segmentWidth, maxX; - Tk_3DBorder border; - - if (menuPtr->menuType != MASTER_MENU ) { - return; - } - - margin = fmPtr->linespace/2; - points[0].x = x; - points[0].y = y + height/2; - points[1].y = points[0].y; - segmentWidth = 6; - maxX = x + menuPtr->totalWidth - 1; - border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr); - - while (points[0].x < maxX) { - points[1].x = points[0].x + segmentWidth; - if (points[1].x > maxX) { - points[1].x = maxX; - } - Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1, - TK_RELIEF_RAISED); - points[0].x += 2*segmentWidth; - } -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXSetHelpMenuItemCount -- - * - * Has to be called after the first call to InsertMenu. Sets up the - * global variable for the number of items in the unmodified help menu. - * NB. Nobody uses this any more, since you can get the number of system - * help items from HMGetHelpMenu trivially. But it is in the stubs - * table... - * - * Results: - * None. - * - * Side effects: - * Nothing. - * - *---------------------------------------------------------------------- - */ - -void -TkMacOSXSetHelpMenuItemCount(void) -{ - /* - * Obsolete: Nothing to do. - */ -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXMenuClick -- - * - * Prepares a menubar for MenuSelect or MenuKey. - * - * Results: - * None. - * - * Side effects: - * Any pending configurations of the menubar are completed. - * - *---------------------------------------------------------------------- - */ - -void -TkMacOSXMenuClick(void) -{ - TkMenu *menuPtr; - TkMenuReferences *menuRefPtr; - - if ((currentMenuBarInterp != NULL) && (currentMenuBarName != NULL)) { - menuRefPtr = TkFindMenuReferences(currentMenuBarInterp, - currentMenuBarName); - for (menuPtr = menuRefPtr->menuPtr->masterMenuPtr; - menuPtr != NULL; menuPtr = menuPtr->nextInstancePtr) { - if (menuPtr->menuType == MENUBAR) { - CompleteIdlers(menuPtr); - break; - } - } - } - - if (menuBarFlags & MENUBAR_REDRAW_PENDING) { - Tcl_CancelIdleCall(DrawMenuBarWhenIdle, NULL); - DrawMenuBarWhenIdle(NULL); - } -} - -/* - *---------------------------------------------------------------------- - * - * TkpDrawMenuEntry -- - * - * Draws the given menu entry at the given coordinates with the given - * attributes. - * - * Results: - * None. - * - * Side effects: - * X Server commands are executed to display the menu entry. - * - *---------------------------------------------------------------------- - */ - -void -TkpDrawMenuEntry( - TkMenuEntry *mePtr, /* The entry to draw */ - Drawable d, /* What to draw into */ - Tk_Font tkfont, /* Precalculated font for menu */ - const Tk_FontMetrics *menuMetricsPtr, - /* Precalculated metrics for menu */ - int x, /* X-coordinate of topleft of entry */ - int y, /* Y-coordinate of topleft of entry */ - int width, /* Width of the entry rectangle */ - int height, /* Height of the current rectangle */ - int strictMotif, /* Boolean flag */ - int drawArrow) /* Whether or not to draw the cascade - * arrow for cascade items. Only applies - * to Windows. */ -{ - GC gc; - TkMenu *menuPtr = mePtr->menuPtr; - int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0; - GC indicatorGC; - Tk_3DBorder bgBorder, activeBorder; - const Tk_FontMetrics *fmPtr; - Tk_FontMetrics entryMetrics; - int adjustedY = y + padY; - int adjustedHeight = height - 2 * padY; - - /* - * Choose the gc for drawing the foreground part of the entry. Under - * Appearance, we pass a null (appearanceGC) to tell ourselves not to - * change whatever color the appearance manager has set. - */ - - if ((mePtr->state == ENTRY_ACTIVE) && !strictMotif) { - gc = mePtr->activeGC; - if (gc == NULL) { - gc = menuPtr->activeGC; - } - } else { - TkMenuEntry *parentEntryPtr = GetParentMenuEntry(menuPtr); - - if (((parentEntryPtr && parentEntryPtr->state == ENTRY_DISABLED) || - (mePtr->state == ENTRY_DISABLED)) && - (menuPtr->disabledFgPtr != NULL)) { - gc = mePtr->disabledGC; - if (gc == NULL) { - gc = menuPtr->disabledGC; - } - } else { - gc = mePtr->textGC; - if (gc == NULL) { - gc = menuPtr->textGC; - } - } - } - - indicatorGC = mePtr->indicatorGC; - if (indicatorGC == NULL) { - indicatorGC = menuPtr->indicatorGC; - } - - bgBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin, - (mePtr->borderPtr == NULL) - ? menuPtr->borderPtr : mePtr->borderPtr); - if (strictMotif) { - activeBorder = bgBorder; - } else { - activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin, - (mePtr->activeBorderPtr == NULL) - ? menuPtr->activeBorderPtr : mePtr->activeBorderPtr); - } - - if (mePtr->fontPtr == NULL) { - fmPtr = menuMetricsPtr; - } else { - tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr); - Tk_GetFontMetrics(tkfont, &entryMetrics); - fmPtr = &entryMetrics; - } - - /* - * Need to draw the entire background, including padding. On Unix, for - * menubars, we have to draw the rest of the entry taking into account the - * padding. - */ - - DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder, bgBorder, x, y, - width, height); - - if (mePtr->type == SEPARATOR_ENTRY) { - DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, - fmPtr, x, adjustedY, width, adjustedHeight); - } else if (mePtr->type == TEAROFF_ENTRY) { - DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY, - width, adjustedHeight); - } else { - DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, - adjustedY, width, adjustedHeight); - DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, - activeBorder, x, adjustedY, width, adjustedHeight, drawArrow); - if (!mePtr->hideMargin) { - DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, - fmPtr, x, adjustedY, width, adjustedHeight); - } - } -} - -/* - *-------------------------------------------------------------- - * - * TkpComputeStandardMenuGeometry -- - * - * This procedure is invoked to recompute the size and layout of a menu - * that is not a menubar clone. - * - * Results: - * None. - * - * Side effects: - * Fields of menu entries are changed to reflect their current positions, - * and the size of the menu window itself may be changed. - * - *-------------------------------------------------------------- - */ - -void -TkpComputeStandardMenuGeometry( - TkMenu *menuPtr) /* Structure describing menu. */ -{ - Tk_Font tkfont, menuFont; - Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr; - int x, y, height, modifierWidth, labelWidth, indicatorSpace; - int windowWidth, windowHeight, accelWidth, maxAccelTextWidth; - int i, j, lastColumnBreak, maxModifierWidth, maxWidth, nonAccelMargin; - int maxNonAccelMargin, maxEntryWithAccelWidth, maxEntryWithoutAccelWidth; - int entryWidth, maxIndicatorSpace, borderWidth, activeBorderWidth; - TkMenuEntry *mePtr, *columnEntryPtr; - EntryGeometry *geometryPtr; - int haveAccel = 0; - - if (menuPtr->tkwin == NULL) { - return; - } - - Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, - &borderWidth); - Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr, - &activeBorderWidth); - x = y = borderWidth; - indicatorSpace = labelWidth = accelWidth = maxAccelTextWidth = 0; - windowHeight = maxWidth = lastColumnBreak = 0; - maxModifierWidth = maxNonAccelMargin = 0; - maxEntryWithAccelWidth = maxEntryWithoutAccelWidth = 0; - maxIndicatorSpace = 0; - - /* - * On the Mac especially, getting font metrics can be quite slow, so we - * want to do it intelligently. We are going to precalculate them and pass - * them down to all of the measuring and drawing routines. We will measure - * the font metrics of the menu once. If an entry does not have its own - * font set, then we give the geometry/drawing routines the menu's font - * and metrics. If an entry has its own font, we will measure that font - * and give all of the geometry/drawing the entry's font and metrics. - */ - - menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr); - Tk_GetFontMetrics(menuFont, &menuMetrics); - - for (i = 0; i < menuPtr->numEntries; i++) { - mePtr = menuPtr->entries[i]; - if (mePtr->type == CASCADE_ENTRY || mePtr->accelLength > 0) { - haveAccel = 1; - break; - } - } - - for (i = 0; i < menuPtr->numEntries; i++) { - mePtr = menuPtr->entries[i]; - if (mePtr->fontPtr == NULL) { - tkfont = menuFont; - fmPtr = &menuMetrics; - } else { - tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr); - Tk_GetFontMetrics(tkfont, &entryMetrics); - fmPtr = &entryMetrics; - } - - if ((i > 0) && mePtr->columnBreak) { - if (maxIndicatorSpace != 0) { - maxIndicatorSpace += 2; - } - for (j = lastColumnBreak; j < i; j++) { - columnEntryPtr = menuPtr->entries[j]; - geometryPtr = - (EntryGeometry *) columnEntryPtr->platformEntryData; - - columnEntryPtr->indicatorSpace = maxIndicatorSpace; - columnEntryPtr->width = maxIndicatorSpace + maxWidth - + 2 * activeBorderWidth; - geometryPtr->accelTextWidth = maxAccelTextWidth; - geometryPtr->modifierWidth = maxModifierWidth; - columnEntryPtr->x = x; - columnEntryPtr->entryFlags &= ~ENTRY_LAST_COLUMN; - if (maxEntryWithoutAccelWidth > maxEntryWithAccelWidth) { - geometryPtr->nonAccelMargin = maxEntryWithoutAccelWidth - - maxEntryWithAccelWidth; - if (geometryPtr->nonAccelMargin > maxNonAccelMargin) { - geometryPtr->nonAccelMargin = maxNonAccelMargin; - } - } else { - geometryPtr->nonAccelMargin = 0; - } - } - x += maxIndicatorSpace + maxWidth + 2 * borderWidth; - windowWidth = x; - maxWidth = maxIndicatorSpace = maxAccelTextWidth = 0; - maxModifierWidth = maxNonAccelMargin = maxEntryWithAccelWidth = 0; - maxEntryWithoutAccelWidth = 0; - lastColumnBreak = i; - y = borderWidth; - } - /*geometryPtr = (EntryGeometry *) mePtr->platformEntryData;*/ /* dead code */ - - if (mePtr->type == SEPARATOR_ENTRY) { - GetMenuSeparatorGeometry(menuPtr, mePtr, tkfont, - fmPtr, &entryWidth, &height); - mePtr->height = height; - } else if (mePtr->type == TEAROFF_ENTRY) { - GetTearoffEntryGeometry(menuPtr, mePtr, tkfont, - fmPtr, &entryWidth, &height); - mePtr->height = height; - } else { - /* - * For each entry, compute the height required by that particular - * entry, plus three widths: the width of the label, the width to - * allow for an indicator to be displayed to the left of the label - * (if any), and the width of the accelerator to be displayed to - * the right of the label (if any). These sizes depend, of course, - * on the type of the entry. - */ - - GetMenuLabelGeometry(mePtr, tkfont, fmPtr, &labelWidth, &height); - mePtr->height = height; - - nonAccelMargin = 0; - if (mePtr->type == CASCADE_ENTRY) { - GetMenuAccelGeometry(menuPtr, mePtr, tkfont, fmPtr, - &modifierWidth, &accelWidth, &height); - } else if (mePtr->accelLength == 0) { - if (haveAccel && !mePtr->hideMargin) { - if (IS_THEME_MENU_FONT(tkfont)) { - nonAccelMargin = menuSymbols[COMMAND_SYMBOL].width; - } else { - nonAccelMargin = Tk_TextWidth(tkfont, - menuSymbols[COMMAND_SYMBOL].utf, - menuSymbols[COMMAND_SYMBOL].utfLen); - } - } - accelWidth = modifierWidth = 0; - } else { - GetMenuAccelGeometry(menuPtr, mePtr, tkfont, - fmPtr, &modifierWidth, &accelWidth, &height); - if (height > mePtr->height) { - mePtr->height = height; - } - } - - if (!(mePtr->hideMargin)) { - GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont, - fmPtr, &indicatorSpace, &height); - if (height > mePtr->height) { - mePtr->height = height; - } - } else { - indicatorSpace = 0; - } - - if (nonAccelMargin > maxNonAccelMargin) { - maxNonAccelMargin = nonAccelMargin; - } - if (accelWidth > maxAccelTextWidth) { - maxAccelTextWidth = accelWidth; - } - if (modifierWidth > maxModifierWidth) { - maxModifierWidth = modifierWidth; - } - if (indicatorSpace > maxIndicatorSpace) { - maxIndicatorSpace = indicatorSpace; - } - - entryWidth = labelWidth + modifierWidth + accelWidth - + nonAccelMargin; - - if (entryWidth > maxWidth) { - maxWidth = entryWidth; - } - - if (mePtr->accelLength > 0) { - if (entryWidth > maxEntryWithAccelWidth) { - maxEntryWithAccelWidth = entryWidth; - } - } else { - if (entryWidth > maxEntryWithoutAccelWidth) { - maxEntryWithoutAccelWidth = entryWidth; - } - } - mePtr->height += 2 * activeBorderWidth; - } - mePtr->y = y; - y += menuPtr->entries[i]->height + borderWidth; - if (y > windowHeight) { - windowHeight = y; - } - } - - for (j = lastColumnBreak; j < menuPtr->numEntries; j++) { - columnEntryPtr = menuPtr->entries[j]; - geometryPtr = (EntryGeometry *) columnEntryPtr->platformEntryData; - - columnEntryPtr->indicatorSpace = maxIndicatorSpace; - columnEntryPtr->width = maxIndicatorSpace + maxWidth - + 2 * activeBorderWidth; - geometryPtr->accelTextWidth = maxAccelTextWidth; - columnEntryPtr->x = x; - columnEntryPtr->entryFlags |= ENTRY_LAST_COLUMN; - if (maxEntryWithoutAccelWidth > maxEntryWithAccelWidth) { - geometryPtr->nonAccelMargin = maxEntryWithoutAccelWidth - - maxEntryWithAccelWidth; - if (geometryPtr->nonAccelMargin > maxNonAccelMargin) { - geometryPtr->nonAccelMargin = maxNonAccelMargin; - } - } else { - geometryPtr->nonAccelMargin = 0; - } - } - windowWidth = x + maxIndicatorSpace + maxWidth - + 2 * activeBorderWidth + borderWidth; - windowHeight += borderWidth; - - /* - * The X server doesn't like zero dimensions, so round up to at least 1 (a - * zero-sized menu should never really occur, anyway). - */ - - if (windowWidth <= 0) { - windowWidth = 1; - } - if (windowHeight <= 0) { - windowHeight = 1; - } - menuPtr->totalWidth = windowWidth; - menuPtr->totalHeight = windowHeight; -} - -/* - *---------------------------------------------------------------------- - * - * DrawMenuEntryLabel -- - * - * This procedure draws the label part of a menu. - * - * Results: - * None. - * - * Side effects: - * Commands are output to X to display the menu in its current mode. - * - *---------------------------------------------------------------------- - */ - -void -DrawMenuEntryLabel( - TkMenu *menuPtr, /* The menu we are drawing */ - TkMenuEntry *mePtr, /* The entry we are drawing */ - Drawable d, /* What we are drawing into */ - GC gc, /* The gc we are drawing into */ - Tk_Font tkfont, /* The precalculated font */ - const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */ - int x, /* left edge */ - int y, /* right edge */ - int width, /* width of entry */ - int height) /* height of entry */ -{ - int imageWidth, imageHeight, textWidth = 0, textHeight = 0; - int indicatorSpace = mePtr->indicatorSpace; - int leftEdge = x + indicatorSpace; - int haveImage = 0, haveText = 0; - int imageXOffset = 0, imageYOffset = 0; - int textXOffset = 0, textYOffset = 0; - Pixmap bitmap = (Pixmap) NULL; - Tcl_DString itemTextDString; - - /* - * Work out what we will need to draw first. - */ - - if (mePtr->image != NULL) { - Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight); - haveImage = 1; - } else if (mePtr->bitmapPtr != NULL) { - bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr); - Tk_SizeOfBitmap(menuPtr->display, bitmap, &imageWidth, &imageHeight); - haveImage = 1; - } - if (!haveImage || (mePtr->compound != COMPOUND_NONE)) { - if (mePtr->labelLength > 0) { - GetEntryText(mePtr, &itemTextDString); - if (mePtr->compound != COMPOUND_NONE) { - textWidth = Tk_TextWidth(tkfont, - Tcl_DStringValue(&itemTextDString), - Tcl_DStringLength(&itemTextDString)) + - menuTextLeadingEdgeMargin + menuTextTrailingEdgeMargin; - textHeight = fmPtr->linespace; - } - haveText = 1; - } - } - - /* - * Now work out what the relative positions are. - */ - - if (haveImage && haveText && (mePtr->compound != COMPOUND_NONE)) { - int fullWidth = (imageWidth > textWidth ? imageWidth : textWidth); - - switch ((enum compound) mePtr->compound) { - case COMPOUND_TOP: - textXOffset = (fullWidth - textWidth)/2; - textYOffset = imageHeight/2 + 2; - imageXOffset = (fullWidth - imageWidth)/2; - imageYOffset = -textHeight/2; - break; - case COMPOUND_BOTTOM: - textXOffset = (fullWidth - textWidth)/2; - textYOffset = -imageHeight/2; - imageXOffset = (fullWidth - imageWidth)/2; - imageYOffset = textHeight/2 + 2; - break; - case COMPOUND_LEFT: - /* - * Position image in the indicator space to the left of the - * entries, unless this entry is a radio|check button because then - * the indicator space will be used. - */ - - textXOffset = imageWidth + 2 - menuTextLeadingEdgeMargin; - if ((mePtr->type != CHECK_BUTTON_ENTRY) - && (mePtr->type != RADIO_BUTTON_ENTRY)) { - textXOffset -= indicatorSpace; - imageXOffset = -indicatorSpace; - } - if (textXOffset < 0) { - textXOffset = 0; - } - break; - case COMPOUND_RIGHT: - imageXOffset = textWidth + 2 - menuTextTrailingEdgeMargin; - break; - case COMPOUND_CENTER: - textXOffset = (fullWidth - textWidth)/2; - imageXOffset = (fullWidth - imageWidth)/2; - break; - case COMPOUND_NONE: - /* - * Never reached. - */ - break; - } - } - - /* - * Draw label and/or bitmap or image for entry. - */ - - if (mePtr->image != NULL) { - if ((mePtr->selectImage != NULL) - && (mePtr->entryFlags & ENTRY_SELECTED)) { - Tk_RedrawImage(mePtr->selectImage, 0, 0, imageWidth, imageHeight, - d, leftEdge + imageXOffset, - y + (mePtr->height - imageHeight)/2 + imageYOffset); - } else { - Tk_RedrawImage(mePtr->image, 0, 0, imageWidth, imageHeight, - d, leftEdge + imageXOffset, - y + (mePtr->height - imageHeight)/2 + imageYOffset); - } - } else if (mePtr->bitmapPtr != NULL) { - XCopyPlane(menuPtr->display, bitmap, d, gc, 0, 0, imageWidth, - imageHeight, leftEdge + imageXOffset, - y + (mePtr->height - imageHeight)/2 + imageYOffset, 1); - } - if (haveText) { - int baseline = y + (height + fmPtr->ascent - fmPtr->descent)/2; - - Tk_DrawChars(menuPtr->display, d, gc, tkfont, - Tcl_DStringValue(&itemTextDString), - Tcl_DStringLength(&itemTextDString), - leftEdge + menuTextLeadingEdgeMargin + textXOffset, - baseline + textYOffset); - Tcl_DStringFree(&itemTextDString); - } - - if (mePtr->state == ENTRY_DISABLED) { - if (menuPtr->disabledFgPtr == NULL) { - /* XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y, - width, height); */ - } else if ((mePtr->image != NULL) - && (menuPtr->disabledImageGC != None)) { - XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC, - leftEdge + imageXOffset, - y + (mePtr->height - imageHeight)/2 + imageYOffset, - imageWidth, imageHeight); - } - } -} - -/* - *---------------------------------------------------------------------- - * - * DrawMenuEntryBackground -- - * - * This procedure draws the background part of a menu entry. Under - * Appearance, we only draw the background if the entry's border is set, - * we DO NOT inherit it from the menu... - * - * Results: - * None. - * - * Side effects: - * Commands are output to X to display the menu in its current mode. - * - *---------------------------------------------------------------------- - */ - -void -DrawMenuEntryBackground( - TkMenu *menuPtr, /* The menu we are drawing. */ - TkMenuEntry *mePtr, /* The entry we are drawing. */ - Drawable d, /* What we are drawing into */ - Tk_3DBorder activeBorder, /* Border for active items */ - Tk_3DBorder bgBorder, /* Border for the background */ - int x, /* left edge */ - int y, /* top edge */ - int width, /* width of rectangle to draw */ - int height) /* height of rectangle to draw */ -{ - if ((menuPtr->menuType == TEAROFF_MENU) - || ((mePtr->state == ENTRY_ACTIVE) - && (mePtr->activeBorderPtr != None)) - || ((mePtr->state != ENTRY_ACTIVE) && (mePtr->borderPtr != None))) { - if (mePtr->state == ENTRY_ACTIVE) { - bgBorder = activeBorder; - } - Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, - x, y, width, height, 0, TK_RELIEF_FLAT); - } -} - -/* - *---------------------------------------------------------------------- - * - * GetMenuLabelGeometry -- - * - * Figures out the size of the label portion of a menu item. - * - * Results: - * widthPtr and heightPtr are filled in with the correct geometry - * information. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -GetMenuLabelGeometry( - TkMenuEntry *mePtr, /* The entry we are computing */ - Tk_Font tkfont, /* The precalculated font */ - const Tk_FontMetrics *fmPtr,/* The precalculated metrics */ - int *widthPtr, /* The resulting width of the label portion */ - int *heightPtr) /* The resulting height of the label portion */ -{ - TkMenu *menuPtr = mePtr->menuPtr; - int haveImage = 0, tornOff = (menuPtr->menuType == TEAROFF_MENU); -#ifdef USE_TK_MDEF - const int useMDEF = ((MacMenu *) menuPtr->platformData)->useMDEF; -#endif - - if (mePtr->image != NULL && (useMDEF || tornOff)) { - Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr); - haveImage = 1; - } else if (mePtr->bitmapPtr != NULL && (useMDEF || tornOff)) { - Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr); - Tk_SizeOfBitmap(menuPtr->display, bitmap, widthPtr, heightPtr); - haveImage = 1; - } - if (!haveImage || (mePtr->compound != COMPOUND_NONE)) { - int textWidth = 0, textHeight = fmPtr->linespace; - - if (mePtr->labelPtr != NULL) { - Tcl_DString itemTextDString; - - GetEntryText(mePtr, &itemTextDString); - textWidth = Tk_TextWidth(tkfont, - Tcl_DStringValue(&itemTextDString), - Tcl_DStringLength(&itemTextDString)) + - menuTextLeadingEdgeMargin + menuTextTrailingEdgeMargin; - Tcl_DStringFree(&itemTextDString); - - if (haveImage && (mePtr->compound != COMPOUND_NONE)) { - switch ((enum compound) mePtr->compound) { - int margin; - - case COMPOUND_TOP: - case COMPOUND_BOTTOM: - if (textWidth > *widthPtr) { - *widthPtr = textWidth; - } - *heightPtr += textHeight + 2; - break; - case COMPOUND_LEFT: - margin = *widthPtr + 2; - if (margin > menuTextLeadingEdgeMargin) { - margin = menuTextLeadingEdgeMargin; - } - *widthPtr += textWidth + 2 - margin; - if (textHeight > *heightPtr) { - *heightPtr = textHeight; - } - break; - case COMPOUND_RIGHT: - margin = menuTextTrailingEdgeMargin; - *widthPtr += textWidth + 2 - margin; - if (textHeight > *heightPtr) { - *heightPtr = textHeight; - } - break; - case COMPOUND_CENTER: - if (textWidth > *widthPtr) { - *widthPtr = textWidth; - } - if (textHeight > *heightPtr) { - *heightPtr = textHeight; - } - break; - case COMPOUND_NONE: - /* - * Never reached. - */ - break; - } - goto labelGeomDone; - } - } - *widthPtr = textWidth; - *heightPtr = textHeight; - } - - labelGeomDone: - *heightPtr += menuItemExtraHeight; - *widthPtr += menuItemExtraWidth; -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXGenerateParentMenuSelectEvent -- - * - * Respond to a hierarchical menu being opened. - * - * Results: - * True if event(s) are generated - false otherwise. - * - * Side effects: - * Places a virtual event on the event queue. - * - *---------------------------------------------------------------------- - */ - -int -TkMacOSXGenerateParentMenuSelectEvent( - MenuRef menu) -{ - TkMenu *menuPtr = MenuPtrForMenuRef(menu); - - if (menuPtr) { - TkMenuEntry *parentEntryPtr = GetParentMenuEntry(menuPtr); - - if (parentEntryPtr && (menuPtr = parentEntryPtr->menuPtr)) { - TkActivateMenuEntry(menuPtr, parentEntryPtr->index); - MenuSelectEvent(menuPtr); - Tcl_ServiceAll(); - return true; - } - } - return false; -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXGenerateMenuSelectEvent -- - * - * Respond to a menu item being selected. - * - * Results: - * True if event(s) are generated - false otherwise. - * - * Side effects: - * Places a virtual event on the event queue. - * - *---------------------------------------------------------------------- - */ - -int -TkMacOSXGenerateMenuSelectEvent( - MenuRef menu, - MenuItemIndex index) -{ - TkMenu *menuPtr = MenuPtrForMenuRef(menu); - int item = index - 1; - - if (menuPtr) { - if (item < 0 || item >= menuPtr->numEntries || - (menuPtr->entries[item])->state == ENTRY_DISABLED) { - TkActivateMenuEntry(menuPtr, -1); - } else { - TkActivateMenuEntry(menuPtr, item); - MenuSelectEvent(menuPtr); - Tcl_ServiceAll(); - return true; - } - } - return false; -} - -/* - *---------------------------------------------------------------------- - * - * MenuSelectEvent -- - * - * Generates a "MenuSelect" virtual event. This can be used to do - * context-sensitive menu help. - * - * Results: - * None. - * - * Side effects: - * Places a virtual event on the event queue. - * - *---------------------------------------------------------------------- - */ - -void -MenuSelectEvent( - TkMenu *menuPtr) /* the menu we have selected. */ -{ - XVirtualEvent event; - - bzero(&event, sizeof(XVirtualEvent)); - event.type = VirtualEvent; - event.serial = menuPtr->display->request; - event.send_event = false; - event.display = menuPtr->display; - Tk_MakeWindowExist(menuPtr->tkwin); - event.event = Tk_WindowId(menuPtr->tkwin); - event.root = XRootWindow(menuPtr->display, 0); - event.subwindow = None; - event.time = TkpGetMS(); - - XQueryPointer(NULL, None, NULL, NULL, &event.x_root, &event.y_root, NULL, - NULL, &event.state); - event.same_screen = true; - event.name = Tk_GetUid("MenuSelect"); - Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXClearActiveMenu -- - * - * Clears Tk's active entry for the given MenuRef. - * - * Results: - * None. - * - * Side effects: - * Generates <<MenuSelect>> virtual events. - * - *---------------------------------------------------------------------- - */ - -void -TkMacOSXClearActiveMenu( - MenuRef menu) -{ - TkMenu *menuPtr = MenuPtrForMenuRef(menu); - - if (menuPtr) { - RecursivelyClearActiveMenu(menuPtr); - } -} - -/* - *---------------------------------------------------------------------- - * - * RecursivelyClearActiveMenu -- - * - * Recursively clears the active entry in the menu's cascade hierarchy. - * - * Results: - * None. - * - * Side effects: - * Generates <<MenuSelect>> virtual events. - * - *---------------------------------------------------------------------- - */ - -void -RecursivelyClearActiveMenu( - TkMenu *menuPtr) /* The menu to reset. */ -{ - int i; - TkMenuEntry *mePtr; - - TkActivateMenuEntry(menuPtr, -1); - for (i = 0; i < menuPtr->numEntries; i++) { - mePtr = menuPtr->entries[i]; - if (mePtr->type == CASCADE_ENTRY) { - if ((mePtr->childMenuRefPtr != NULL) - && (mePtr->childMenuRefPtr->menuPtr != NULL)) { - RecursivelyClearActiveMenu(mePtr->childMenuRefPtr->menuPtr); - } - } - } -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXClearMenubarActive -- - * - * Recursively clears the active entry in the current menubar hierarchy. - * - * Results: - * None. - * - * Side effects: - * Generates <<MenuSelect>> virtual events. - * - *---------------------------------------------------------------------- - */ - -void -TkMacOSXClearMenubarActive(void) -{ - TkMenuReferences *menuBarRefPtr; - - if (currentMenuBarName != NULL) { - menuBarRefPtr = TkFindMenuReferences(currentMenuBarInterp, - currentMenuBarName); - if ((menuBarRefPtr != NULL) && (menuBarRefPtr->menuPtr != NULL)) { - TkMenu *menuPtr; - - for (menuPtr = menuBarRefPtr->menuPtr->masterMenuPtr; - menuPtr != NULL; menuPtr = menuPtr->nextInstancePtr) { - if (menuPtr->menuType == MENUBAR) { - RecursivelyClearActiveMenu(menuPtr); - } - } - } - } -} - -/* - *---------------------------------------------------------------------- - * - * TkpMenuNotifyToplevelCreate -- - * - * This routine reconfigures the menu and the clones indicated by - * menuName becuase a toplevel has been created and any system menus need - * to be created. Only applicable to Windows. - * - * Results: - * None. - * - * Side effects: - * An idle handler is set up to do the reconfiguration. - * - *---------------------------------------------------------------------- - */ - -void -TkpMenuNotifyToplevelCreate( - Tcl_Interp *interp, /* The interp the menu lives in. */ - const char *menuName) /* The name of the menu to reconfigure. */ -{ - /* - * Nothing to do. - */ -} - -/* - *---------------------------------------------------------------------- - * - * TkpMenuInit -- - * - * Initializes Mac-specific menu data. - * - * Results: - * None. - * - * Side effects: - * Allocates a hash table. - * - *---------------------------------------------------------------------- - */ - -void -TkpMenuInit(void) -{ - MenuSymbol *ms = menuSymbols; - CFStringRef cfStr; - - lastMenuID = 256; - Tcl_InitHashTable(&commandTable, TCL_ONE_WORD_KEYS); - currentMenuBarOwner = NULL; - currentAppleMenuID = 0; - currentHelpMenuID = 0; - currentMenuBarInterp = NULL; - currentMenuBarName = NULL; - windowListPtr = NULL; - -#ifdef USE_TK_MDEF - tkThemeMenuItemDrawingUPP - = NewMenuItemDrawingUPP(ThemeMenuItemDrawingProc); - useMDEFVar = Tcl_NewStringObj("::tk::mac::useCustomMDEF", -1); - macMDEFDrawable.winPtr = NULL; - macMDEFDrawable.xOff = 0; - macMDEFDrawable.yOff = 0; - macMDEFDrawable.visRgn = NULL; - macMDEFDrawable.aboveVisRgn = NULL; - macMDEFDrawable.drawRect = CGRectNull; - macMDEFDrawable.referenceCount = 0; - macMDEFDrawable.toplevel = NULL; - macMDEFDrawable.flags = 0; - macMDEFDrawable.grafPtr = NULL; - macMDEFDrawable.context = NULL; - macMDEFDrawable.size = CGSizeZero; -#endif - - ChkErr(GetThemeMetric, kThemeMetricMenuMarkColumnWidth, - &menuMarkColumnWidth); - ChkErr(GetThemeMetric, kThemeMetricMenuMarkIndent, &menuMarkIndent); - ChkErr(GetThemeMetric, kThemeMetricMenuTextLeadingEdgeMargin, - &menuTextLeadingEdgeMargin); - ChkErr(GetThemeMetric, kThemeMetricMenuTextTrailingEdgeMargin, - &menuTextTrailingEdgeMargin); - ChkErr(GetThemeMenuItemExtra, kThemeMenuItemPlain, &menuItemExtraHeight, - &menuItemExtraWidth); - ChkErr(GetThemeMenuSeparatorHeight, &menuSeparatorHeight); - - while (ms->unicode) { - ms->utfLen = Tcl_UniCharToUtf(ms->unicode, ms->utf); - ms->utf[ms->utfLen] = 0; - cfStr = CFStringCreateWithCharacters(NULL, &ms->unicode, 1); - if (cfStr) { - ms->width = MeasureThemeText(cfStr, kThemeMenuItemCmdKeyFont); - CFRelease(cfStr); - } - ms++; - } -} - -/* - *---------------------------------------------------------------------- - * - * TkpMenuThreadInit -- - * - * Does platform-specific initialization of thread-specific menu state. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -TkpMenuThreadInit(void) -{ - /* - * Nothing to do. - */ -} - -/* - *---------------------------------------------------------------------- - * - * TkpPreprocessMacMenu -- - * - * Handle preprocessing of menubar if it exists. - * - * Results: - * None. - * - * Side effects: - * All post commands for the current menubar get executed. - * - *---------------------------------------------------------------------- - */ - -void -TkMacOSXPreprocessMenu(void) -{ - if ((currentMenuBarName != NULL) && (currentMenuBarInterp != NULL)) { - TkMenuReferences *mbRefPtr = - TkFindMenuReferences(currentMenuBarInterp,currentMenuBarName); - - if ((mbRefPtr != NULL) && (mbRefPtr->menuPtr != NULL)) { - int code; - - Tcl_Preserve(currentMenuBarInterp); - code = TkPreprocessMenu(mbRefPtr->menuPtr->masterMenuPtr); - if ((code != TCL_OK) && (code != TCL_CONTINUE) - && (code != TCL_BREAK)) { - Tcl_AddErrorInfo(currentMenuBarInterp, - "\n (menu preprocess)"); - Tcl_BackgroundException(currentMenuBarInterp, code); - } - Tcl_Release(currentMenuBarInterp); - } - } -} - -#ifdef USE_TK_MDEF -#pragma mark MDEF -/* - *---------------------------------------------------------------------- - * - * MenuDefProc -- - * - * This routine is the MDEF handler for Tk. It receives all messages for - * the menu and dispatches them. - * - * Results: - * None. - * - * Side effects: - * This routine causes menus to be drawn and will certainly allocate - * memory as a result. Also, the menu can scroll up and down, and various - * other interface actions can take place. - * - *---------------------------------------------------------------------- - */ - -void -MenuDefProc( - SInt16 message, /* What action are we taking? */ - MenuRef menu, /* The menu we are working with */ - Rect *menuRectPtr, /* A pointer to the rect for the whole - * menu. */ - Point hitPt, /* Where the mouse was clicked for the - * appropriate messages. */ - SInt16 *whichItem) /* Output result. Which item was hit by the - * user? */ -{ - TkMenu *menuPtr; - Tcl_HashEntry *commandEntryPtr; - MenuID menuID; - - menuID = GetMenuID(menu); - commandEntryPtr = Tcl_FindHashEntry(&commandTable, (char*)(intptr_t)menuID); - if (!commandEntryPtr) return; - menuPtr = Tcl_GetHashValue(commandEntryPtr); - - switch (message) { - case kMenuInitMsg: - *whichItem = noErr; - break; - case kMenuDisposeMsg: - break; - case kMenuHiliteItemMsg: - HandleMenuHiliteMsg(menu, menuRectPtr, hitPt, whichItem, menuPtr); - break; - case kMenuCalcItemMsg: - HandleMenuCalcItemMsg(menu, menuRectPtr, hitPt, whichItem, menuPtr); - break; - case kMenuDrawItemsMsg: -#ifdef TK_MAC_DEBUG_MENUS - TkMacOSXDbgMsg("MDEF: DrawItemsMsg"); -#endif - /* - * We do nothing here, because we don't support the Menu Managers - * dynamic item groups - */ - - break; - case kMenuThemeSavvyMsg: - *whichItem = kThemeSavvyMenuResponse; - break; - case kMenuSizeMsg: -#ifdef TK_MAC_DEBUG_MENUS - TkMacOSXDbgMsg("MDEF: SizeMsg %d, %d", hitPt.h, hitPt.v); -#endif - SetMenuWidth(menu, hitPt.h < menuPtr->totalWidth ? hitPt.h : - menuPtr->totalWidth); - SetMenuHeight(menu, hitPt.v < menuPtr->totalHeight ? hitPt.v : - menuPtr->totalHeight); - break; - case kMenuDrawMsg: - HandleMenuDrawMsg(menu, menuRectPtr, hitPt, whichItem, menuPtr); - break; - case kMenuFindItemMsg: - HandleMenuFindItemMsg(menu, menuRectPtr, hitPt, whichItem, menuPtr); - break; - case kMenuPopUpMsg: - HandleMenuPopUpMsg(menu, menuRectPtr, hitPt, whichItem, menuPtr); - break; - } -} - -/* - *---------------------------------------------------------------------- - * - * HandleMenuHiliteMsg -- - * - * Handles the MenuDefProc's hilite message. - * - * Results: - * A menu entry is drawn - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -void -HandleMenuHiliteMsg( - MenuRef menu, - Rect *menuRectPtr, - Point hitPt, - SInt16 *whichItem, - TkMenu *menuPtr) -{ - OSStatus err; - Tk_Font tkfont; - Tk_FontMetrics fontMetrics; - MDEFHiliteItemData *hidPtr = (MDEFHiliteItemData *) whichItem; - int oldItem = hidPtr->previousItem - 1; - int newItem = hidPtr->newItem - 1; - MenuTrackingData mtd, *mtdPtr = &mtd; - -#ifdef TK_MAC_DEBUG_MENUS - TkMacOSXDbgMsg("MDEF: HiliteMsg %d -> %d", hidPtr->previousItem, - hidPtr->newItem); -#endif - GetPort(&macMDEFDrawable.grafPtr); - macMDEFDrawable.context = (CGContextRef) hidPtr->context; - - err = ChkErr(GetMenuTrackingData, menu, mtdPtr); - if (err != noErr) { - return; - } - - tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr); - Tk_GetFontMetrics(tkfont, &fontMetrics); - if (oldItem >= 0) { - AppearanceEntryDrawWrapper(menuPtr->entries[oldItem], menuRectPtr, - mtdPtr, (Drawable) &macMDEFDrawable, &fontMetrics, tkfont, 1); - } - if (newItem >= 0) { - AppearanceEntryDrawWrapper(menuPtr->entries[newItem], menuRectPtr, - mtdPtr, (Drawable) &macMDEFDrawable, &fontMetrics, tkfont, 0); - } -} - -/* - *---------------------------------------------------------------------- - * - * HandleMenuDrawMsg -- - * - * Handles the MenuDefProc's draw message. - * - * Results: - * A menu entry is drawn - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -void -HandleMenuDrawMsg( - MenuRef menu, - Rect *menuRectPtr, - Point hitPt, - SInt16 *whichItem, - TkMenu *menuPtr) -{ - Tk_Font menuFont; - Tk_FontMetrics fontMetrics; - TkMenuEntry *mePtr; - int i; - Rect menuClipRect, bounds; - MDEFDrawData *ddPtr = (MDEFDrawData *) whichItem; - MenuTrackingData *mtdPtr = &(ddPtr->trackingData); - TkWindow *winPtr = (TkWindow *) menuPtr->tkwin; - - GetPort(&macMDEFDrawable.grafPtr); - GetPortBounds(macMDEFDrawable.grafPtr, &bounds); - macMDEFDrawable.context = (CGContextRef) ddPtr->context; -#ifdef TK_MAC_DEBUG_MENUS - TkMacOSXDbgMsg("MDEF: DrawMsg %d - %d; %d - %d", menuRectPtr->top, - menuRectPtr->bottom, bounds.top, bounds.bottom); -#endif - winPtr->changes.x = menuRectPtr->left; - winPtr->changes.y = menuRectPtr->top; - winPtr->changes.width = menuRectPtr->right - menuRectPtr->left; - winPtr->changes.height = menuRectPtr->bottom - menuRectPtr->top; - TkpClipDrawableToRect(menuPtr->display, (Drawable) &macMDEFDrawable, - 0, 0, -1, -1); -#if 0 - if (menuPtr->menuRefPtr->topLevelListPtr != NULL) { - menuType = kThemeMenuTypePullDown; - } else if (menuPtr->menuRefPtr->parentEntryPtr != NULL) { - menuType = kThemeMenuTypeHierarchical; - } else { - menuType = kThemeMenuTypePopUp; - } -#endif - DrawMenuBackground(menuPtr, menuRectPtr, (Drawable) &macMDEFDrawable); - menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr); - Tk_GetFontMetrics(menuFont, &fontMetrics); - menuClipRect = *menuRectPtr; - mtdPtr->virtualMenuBottom = mtdPtr->virtualMenuTop + menuPtr->totalHeight; - - /* - * Next, figure out scrolling information. - */ - - if ((menuRectPtr->bottom - menuRectPtr->top) < menuPtr->totalHeight) { - short arrowHeight = fontMetrics.linespace + 1; - Rect arrowRect, eraseRect; - ThemeMenuState menuState = IsMenuItemEnabled(menu, 0) ? - kThemeMenuActive : kThemeMenuDisabled; - - if (mtdPtr->virtualMenuTop < menuRectPtr->top) { - arrowRect = bounds; - /*arrowRect.top += 1;*/ - arrowRect.bottom = arrowRect.top + arrowHeight; - eraseRect = arrowRect; - eraseRect.top = menuRectPtr->top; - menuClipRect.top = arrowRect.bottom; - ChkErr(EraseMenuBackground, menu, &eraseRect, - macMDEFDrawable.context); - ChkErr(DrawThemeMenuItem, menuRectPtr, &arrowRect, - mtdPtr->virtualMenuTop, mtdPtr->virtualMenuBottom, - menuState, kThemeMenuItemScrollUpArrow, NULL, 0); -#ifdef TK_MAC_DEBUG_MENUS - TkMacOSXDbgMsg("upArrow: %d - %d, %d - %d", arrowRect.top, - arrowRect.bottom, arrowRect.left, arrowRect.right); -#endif - } - if (mtdPtr->virtualMenuBottom > menuRectPtr->bottom) { - arrowRect = bounds; - arrowRect.bottom -= 1; - arrowRect.top = arrowRect.bottom - arrowHeight; - eraseRect = arrowRect; - eraseRect.bottom = menuRectPtr->bottom; - menuClipRect.bottom = arrowRect.top; - ChkErr(EraseMenuBackground, menu, &eraseRect, - macMDEFDrawable.context); - ChkErr(DrawThemeMenuItem, menuRectPtr, &arrowRect, - mtdPtr->virtualMenuTop, mtdPtr->virtualMenuBottom, - menuState, kThemeMenuItemScrollDownArrow, NULL, 0); -#ifdef TK_MAC_DEBUG_MENUS - TkMacOSXDbgMsg("downArrow: %d - %d, %d - %d", arrowRect.top, - arrowRect.bottom, arrowRect.left, arrowRect.right); -#endif - } - TkpClipDrawableToRect(menuPtr->display, (Drawable) &macMDEFDrawable, - menuClipRect.left, menuClipRect.top, menuClipRect.right - - menuClipRect.left, menuClipRect.bottom - menuClipRect.top); - } - - /* - * Now, actually draw the menu. Don't draw entries that are higher than - * the top arrow, and don't draw entries that are lower than the bottom. - */ - - for (i = 0; i < menuPtr->numEntries; i++) { - mePtr = menuPtr->entries[i]; - if (mtdPtr->virtualMenuTop + mePtr->y + mePtr->height < - menuClipRect.top || mtdPtr->virtualMenuTop + mePtr->y > - menuClipRect.bottom) { - continue; - } - AppearanceEntryDrawWrapper(mePtr, menuRectPtr, mtdPtr, - (Drawable) &macMDEFDrawable, &fontMetrics, menuFont, 0); - } - MDEFScrollFlag = 1; -} - -/* - *---------------------------------------------------------------------- - * - * HandleMenuFindItemMsg -- - * - * Handles the MenuDefProc's FindItems message. We have to respond by - * filling in the itemSelected, itemUnderMouse and itemRect fields. This - * is also the time to scroll the menu if it is too long to fit on the - * screen. - * - * Results: - * The Menu system is informed of the selected item & the item under the - * mouse. - * - * Side effects: - * The menu might get scrolled. - * - *---------------------------------------------------------------------- - */ - -void -HandleMenuFindItemMsg( - MenuRef menu, - Rect *menuRectPtr, - Point hitPt, - SInt16 *whichItem, - TkMenu *menuPtr) -{ - Tk_Font menuFont; - Tk_FontMetrics fontMetrics; - TkMenuEntry *mePtr; - int i, newItem = -1, itemUnderMouse = -1; - Rect itemRect = {0, 0, 0, 0}, menuClipRect, bounds; - int hasTopScroll, hasBottomScroll; - MDEFFindItemData *fiPtr = (MDEFFindItemData *)whichItem; - MenuTrackingData *mtdPtr = &(fiPtr->trackingData), topMtd; - enum { - DONT_SCROLL, DOWN_SCROLL, UP_SCROLL - } scrollDirection; - short arrowHeight; - -#ifdef TK_MAC_DEBUG_MENUS - static Point lastHitPt = {0, 0}; - - if (hitPt.h != lastHitPt.h || hitPt.v != lastHitPt.v) { - lastHitPt = hitPt; - TkMacOSXDbgMsg("MDEF: FindItemMsg: %d, %d", hitPt.h, hitPt.v); - } -#endif - - GetPort(&macMDEFDrawable.grafPtr); - GetPortBounds(macMDEFDrawable.grafPtr, &bounds); - macMDEFDrawable.context = (CGContextRef) fiPtr->context; - - /* - * Now we need to take care of scrolling the menu. - */ - - menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr); - Tk_GetFontMetrics(menuFont, &fontMetrics); - arrowHeight = fontMetrics.linespace + 1; - menuClipRect = *menuRectPtr; - hasTopScroll = mtdPtr->virtualMenuTop < menuRectPtr->top; - hasBottomScroll = mtdPtr->virtualMenuBottom > menuRectPtr->bottom; - scrollDirection = DONT_SCROLL; - if (hasTopScroll) { - menuClipRect.top = bounds.top + arrowHeight; - if (hitPt.v < menuClipRect.top) { - newItem = -1; - scrollDirection = DOWN_SCROLL; - } - } - if (hasBottomScroll) { - menuClipRect.bottom = bounds.bottom - 1 - arrowHeight; - if (hitPt.v > menuClipRect.bottom) { - newItem = -1; - scrollDirection = UP_SCROLL; - } - } - if (MDEFScrollFlag) { - scrollDirection = DONT_SCROLL; - MDEFScrollFlag = 0; - } - /* - * Don't scroll if there are other menus open above us - */ - ChkErr(GetMenuTrackingData, NULL, &topMtd); - if (menu != topMtd.menu) { - scrollDirection = DONT_SCROLL; - } - if (scrollDirection == DONT_SCROLL) { - /* - * Find out which item was hit. If it is the same as the old item, we - * don't need to do anything. - */ - - if (PtInRect(hitPt, menuRectPtr)) { - for (i = 0; i < menuPtr->numEntries; i++) { - mePtr = menuPtr->entries[i]; - itemRect.left = menuRectPtr->left + mePtr->x; - itemRect.top = mtdPtr->virtualMenuTop + mePtr->y; - itemRect.right = mePtr->entryFlags & ENTRY_LAST_COLUMN ? - menuRectPtr->right : itemRect.left + mePtr->width; - itemRect.bottom = itemRect.top + mePtr->height; - if (PtInRect(hitPt, &itemRect)) { - if ((mePtr->type == SEPARATOR_ENTRY) - || (mePtr->state == ENTRY_DISABLED)) { - newItem = -1; - itemUnderMouse = i; - } else { - TkMenuEntry *parentEntryPtr = - GetParentMenuEntry(menuPtr); - - if (parentEntryPtr && - parentEntryPtr->state == ENTRY_DISABLED) { - newItem = -1; - itemUnderMouse = i; - } else { - newItem = i; - itemUnderMouse = i; - } - } - break; - } - } - } - } else { - short scrollAmt; - unsigned long scrollDelay; - Rect arrowRect, eraseRect, scrolledMenuClipRect; - ThemeMenuState menuState = IsMenuItemEnabled(menu, 0) ? - kThemeMenuActive : kThemeMenuDisabled; - int oldItem = mtdPtr->itemSelected - 1; - short d; - - TkpClipDrawableToRect(menuPtr->display, (Drawable) &macMDEFDrawable, - 0, 0, -1, -1); - scrollAmt = fontMetrics.linespace + menuItemExtraHeight; - if (scrollDirection == UP_SCROLL) { - scrollAmt = -scrollAmt; - d = hitPt.v - bounds.bottom; - } else { - d = bounds.top - hitPt.v; - } - scrollDelay = (d >= scrollAmt/2) ? 1 : 10; - menuClipRect = *menuRectPtr; - if (mtdPtr->virtualMenuTop + scrollAmt < menuRectPtr->top) { - arrowRect = bounds; - /*arrowRect.top += 1;*/ - arrowRect.bottom = arrowRect.top + arrowHeight; - eraseRect = arrowRect; - eraseRect.top = menuRectPtr->top; - menuClipRect.top = arrowRect.bottom; - if (!hasTopScroll) { - ChkErr(EraseMenuBackground, menu, &eraseRect, - macMDEFDrawable.context); - ChkErr(DrawThemeMenuItem, menuRectPtr, &arrowRect, - mtdPtr->virtualMenuTop + scrollAmt, - mtdPtr->virtualMenuBottom + scrollAmt, - menuState, kThemeMenuItemScrollUpArrow, NULL, 0); -#ifdef TK_MAC_DEBUG_MENUS - TkMacOSXDbgMsg("upArrow: %d - %d, %d - %d", arrowRect.top, - arrowRect.bottom, arrowRect.left, arrowRect.right); -#endif - } - } - if (mtdPtr->virtualMenuBottom + scrollAmt > menuRectPtr->bottom) { - arrowRect = bounds; - arrowRect.bottom -= 1; - arrowRect.top = arrowRect.bottom - arrowHeight; - eraseRect = arrowRect; - eraseRect.bottom = menuRectPtr->bottom; - menuClipRect.bottom = arrowRect.top; - if (!hasBottomScroll) { - ChkErr(EraseMenuBackground, menu, &eraseRect, - macMDEFDrawable.context); - ChkErr(DrawThemeMenuItem, menuRectPtr, &arrowRect, - mtdPtr->virtualMenuTop + scrollAmt, - mtdPtr->virtualMenuBottom + scrollAmt, - menuState, kThemeMenuItemScrollDownArrow, NULL, 0); -#ifdef TK_MAC_DEBUG_MENUS - TkMacOSXDbgMsg("downArrow: %d - %d, %d - %d", arrowRect.top, - arrowRect.bottom, arrowRect.left, arrowRect.right); -#endif - } - } - TkpClipDrawableToRect(menuPtr->display, (Drawable) &macMDEFDrawable, - menuClipRect.left, menuClipRect.top, menuClipRect.right - - menuClipRect.left, menuClipRect.bottom - menuClipRect.top); - TkActivateMenuEntry(menuPtr, -1); - if (oldItem >= 0) { - AppearanceEntryDrawWrapper(menuPtr->entries[oldItem], menuRectPtr, - mtdPtr, (Drawable) &macMDEFDrawable, &fontMetrics, - menuFont, 1); - } - ChkErr(ScrollMenuImage, menu, &menuClipRect, 0, scrollAmt, - macMDEFDrawable.context); - mtdPtr->virtualMenuTop += scrollAmt; - mtdPtr->virtualMenuBottom += scrollAmt; - scrolledMenuClipRect = menuClipRect; - OffsetRect(&scrolledMenuClipRect, 0, scrollAmt); - menuClipRect = bounds; - if (mtdPtr->virtualMenuTop < menuRectPtr->top) { - menuClipRect.top += arrowHeight; - } - if (mtdPtr->virtualMenuBottom > menuRectPtr->bottom) { - menuClipRect.bottom -= arrowHeight; - } - TkpClipDrawableToRect(menuPtr->display, (Drawable) &macMDEFDrawable, - menuClipRect.left, menuClipRect.top, menuClipRect.right - - menuClipRect.left, menuClipRect.bottom - menuClipRect.top); - if (scrolledMenuClipRect.bottom < menuClipRect.bottom) { - menuClipRect.top = scrolledMenuClipRect.bottom; - } else if (scrolledMenuClipRect.top < menuClipRect.top) { - menuClipRect.bottom = scrolledMenuClipRect.top; - } - for (i = 0; i < menuPtr->numEntries; i++) { - mePtr = menuPtr->entries[i]; - if (mtdPtr->virtualMenuTop + mePtr->y + mePtr->height < - menuClipRect.top || mtdPtr->virtualMenuTop + mePtr->y > - menuClipRect.bottom) { - continue; - } -#ifdef TK_MAC_DEBUG_MENUS - TkMacOSXDbgMsg("Drawing item %i", i); -#endif - AppearanceEntryDrawWrapper(mePtr, menuRectPtr, mtdPtr, - (Drawable) &macMDEFDrawable, &fontMetrics, menuFont, 1); - } - Delay(scrollDelay, NULL); - } - mtdPtr->itemSelected = newItem + 1; - mtdPtr->itemUnderMouse = itemUnderMouse + 1; - mtdPtr->itemRect = itemRect; -} - -/* - *---------------------------------------------------------------------- - * - * HandleMenuPopUpMsg -- - * - * Handles the MenuDefProc's PopUp message. The menu is posted with the - * selected item at the point given in hitPt. - * - * Results: - * A menu is posted. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -HandleMenuPopUpMsg( - MenuRef menu, - Rect *menuRectPtr, - Point hitPt, - SInt16 *whichItem, - TkMenu *menuPtr) -{ - int maxMenuHeight; - int oldItem; - Rect portRect; - BitMap screenBits; - static SInt16 menuBarHeight = 0; - -#ifdef TK_MAC_DEBUG_MENUS - TkMacOSXDbgMsg("MDEF: PopUpMsg"); -#endif - - if (!menuBarHeight) { - ChkErr(GetThemeMenuBarHeight, &menuBarHeight); - } - GetQDGlobalsScreenBits(&screenBits); - - /* - * Note that for some oddball reason, h and v are reversed in the point - * given to us by the MDEF. - */ - - oldItem = *whichItem; - if (oldItem >= menuPtr->numEntries) { - oldItem = -1; - } - portRect.top = 0; - portRect.bottom = 1280; - maxMenuHeight = screenBits.bounds.bottom - screenBits.bounds.top - - menuBarHeight - SCREEN_MARGIN; - if (menuPtr->totalHeight > maxMenuHeight) { - menuRectPtr->top = menuBarHeight; - } else { - int delta; - - menuRectPtr->top = hitPt.h; - if (oldItem >= 0) { - menuRectPtr->top -= menuPtr->entries[oldItem]->y; - } - - if (menuRectPtr->top < menuBarHeight) { - /* - * Displace downward if the menu would stick off the top of the - * screen. - */ - - menuRectPtr->top = menuBarHeight + SCREEN_MARGIN; - } else { - /* - * Or upward if the menu sticks off the bottom end... - */ - - delta = menuRectPtr->top + menuPtr->totalHeight - maxMenuHeight; - if (delta > 0) { - menuRectPtr->top -= delta; - } - } - } - menuRectPtr->left = hitPt.v; - menuRectPtr->right = menuRectPtr->left + menuPtr->totalWidth; - menuRectPtr->bottom = menuRectPtr->top + - ((maxMenuHeight < menuPtr->totalHeight) - ? maxMenuHeight : menuPtr->totalHeight); - if (menuRectPtr->top == menuBarHeight) { - *whichItem = hitPt.h; - } else { - *whichItem = menuRectPtr->top; - } -} - -/* - *---------------------------------------------------------------------- - * - * HandleMenuCalcItemMsg -- - * - * Handles the MenuDefProc's CalcItem message. It is supposed to - * calculate the Rect of the menu entry in whichItem in the menu, and put - * that in menuRectPtr. I assume this works, but I have never seen the - * MenuManager send this message. - * - * Results: - * The Menu Manager is informed of the bounding rect of a menu rect. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -HandleMenuCalcItemMsg( - MenuRef menu, - Rect *menuRectPtr, - Point hitPt, - SInt16 *whichItem, - TkMenu *menuPtr) -{ - TkMenuEntry *mePtr; - MenuTrackingData mtd, *mtdPtr = &mtd; - OSStatus err; - int virtualTop, item = *whichItem-1; - - err = ChkErr(GetMenuTrackingData, menu, mtdPtr); - if (err == noErr) { - virtualTop = mtdPtr->virtualMenuTop; - } else { - virtualTop = 0; - } - - if (item >= 0 && item < menuPtr->numEntries) { - mePtr = menuPtr->entries[item]; - menuRectPtr->left = mePtr->x; - menuRectPtr->top = mePtr->y + virtualTop; - if (mePtr->entryFlags & ENTRY_LAST_COLUMN) { - menuRectPtr->right = menuPtr->totalWidth; - } else { - menuRectPtr->right = mePtr->x + mePtr->width; - } - menuRectPtr->bottom = menuRectPtr->top + mePtr->height; - } -#ifdef TK_MAC_DEBUG_MENUS - TkMacOSXDbgMsg("MDEF: CalcItemMsg %d: %d, %d", *whichItem, - menuRectPtr->left, menuRectPtr->top); -#endif -} -#endif /* USE_TK_MDEF */ - -/* - * Local Variables: - * fill-column: 78 - * c-basic-offset: 4 - * End: - */ |