summaryrefslogtreecommitdiffstats
path: root/carbon/tkMacOSXMenu.c
diff options
context:
space:
mode:
Diffstat (limited to 'carbon/tkMacOSXMenu.c')
-rw-r--r--carbon/tkMacOSXMenu.c4750
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:
- */