summaryrefslogtreecommitdiffstats
path: root/mac/tkMacMenu.c
diff options
context:
space:
mode:
Diffstat (limited to 'mac/tkMacMenu.c')
-rw-r--r--mac/tkMacMenu.c4607
1 files changed, 0 insertions, 4607 deletions
diff --git a/mac/tkMacMenu.c b/mac/tkMacMenu.c
deleted file mode 100644
index ed29f5d..0000000
--- a/mac/tkMacMenu.c
+++ /dev/null
@@ -1,4607 +0,0 @@
-/*
- * tkMacMenu.c --
- *
- * This module implements the Mac-platform specific features of menus.
- *
- * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * RCS: @(#) $Id: tkMacMenu.c,v 1.21 2001/11/23 02:06:07 das Exp $
- */
-
-#include "tkMacInt.h"
-#include "tkMenu.h"
-#include "tkMenuButton.h"
-#include "tkColor.h"
-#include "tkMacInt.h"
-#undef Status
-#include <Menus.h>
-#include <OSUtils.h>
-#include <Palettes.h>
-#include <Resources.h>
-#include <string.h>
-#include <ToolUtils.h>
-#include <Balloons.h>
-#include <Appearance.h>
-#include <Devices.h>
-
-typedef struct MacMenu {
- MenuHandle menuHdl; /* The Menu Manager data structure. */
- Rect menuRect; /* The rectangle as calculated in the
- * MDEF. This is used to figure ou the
- * clipping rgn before we push
- * the <<MenuSelect>> virtual binding
- * through. */
-} MacMenu;
-
-typedef struct MenuEntryUserData {
- Drawable mdefDrawable;
- TkMenuEntry *mePtr;
- Tk_Font tkfont;
- Tk_FontMetrics *fmPtr;
-} MenuEntryUserData;
-/*
- * Various geometry definitions:
- */
-
-#define CASCADE_ARROW_HEIGHT 10
-#define CASCADE_ARROW_WIDTH 8
-#define DECORATION_BORDER_WIDTH 2
-#define MAC_MARGIN_WIDTH 8
-
-/*
- * The following are constants relating to the SICNs used for drawing the MDEF.
- */
-
-#define SICN_RESOURCE_NUMBER 128
-
-#define SICN_HEIGHT 16
-#define SICN_ROWS 2
-#define CASCADE_ICON_WIDTH 7
-#define SHIFT_ICON_WIDTH 10
-#define OPTION_ICON_WIDTH 16
-#define CONTROL_ICON_WIDTH 12
-#define COMMAND_ICON_WIDTH 10
-
-#define CASCADE_ARROW 0
-#define SHIFT_ICON 1
-#define OPTION_ICON 2
-#define CONTROL_ICON 3
-#define COMMAND_ICON 4
-#define DOWN_ARROW 5
-#define UP_ARROW 6
-
-/*
- * 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)
-
-/*
- * 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. */
-} 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 SEPARATOR_TEXT "\p(-"
- /* The text for a menu separator. */
-
-#define MENUBAR_REDRAW_PENDING 1
-
-static int gNoTkMenus = 0; /* This is used by Tk_MacTurnOffMenus as the
- * flag that Tk is not to draw any menus. */
-RgnHandle tkMenuCascadeRgn = NULL;
- /* The region to clip drawing to when the
- * MDEF is up. */
-int tkUseMenuCascadeRgn = 0; /* If this is 1, clipping code
- * should intersect tkMenuCascadeRgn
- * before drawing occurs.
- * tkMenuCascadeRgn will only
- * be valid when the value of this
- * variable is 1. */
-
-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 char elipsisString[TCL_UTF_MAX + 1];
- /* The UTF representation of the elipsis (Š)
- * character. */
-static int helpItemCount; /* The number of items in the help menu.
- * -1 means that the help menu is
- * unavailable. This does not include
- * the automatically generated separator. */
-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 unsigned char lastCascadeID;
- /* Cascades have to have ids that are
- * less than 256. */
-static MacDrawable macMDEFDrawable;
- /* Drawable for use by MDEF code */
-static MDEFScrollFlag = 0; /* Used so that popups don't scroll too soon. */
-static int menuBarFlags; /* Used for whether the menu bar needs
- * redrawing or not. */
-static TkMenuDefUPP menuDefProc = NULL ;
- /* The routine descriptor to the MDEF proc.
- * The MDEF is needed to draw menus with
- * non-standard attributes and to support
- * tearoff menus. */
-static struct TearoffSelect {
- TkMenu *menuPtr; /* The menu that is torn off */
- Point point; /* The point to place the new menu */
- Rect excludeRect; /* We don't want to drag tearoff highlights
- * when we are in this menu */
-} tearoffStruct;
-
-static RgnHandle totalMenuRgn = NULL;
- /* Used to update windows which have been
- * obscured by menus. */
-static RgnHandle utilRgn = NULL;/* Used when creating the region that is to
- * be clipped out while the MDEF is active. */
-
-static TopLevelMenubarList *windowListPtr;
- /* A list of windows that have menubars set. */
-static MenuItemDrawingUPP tkThemeMenuItemDrawingUPP;
- /* Points to the UPP for theme Item drawing. */
-
-
-/*
- * Forward declarations for procedures defined later in this file:
- */
-
-static void CompleteIdlers _ANSI_ARGS_((TkMenu *menuPtr));
-static void DrawMenuBarWhenIdle _ANSI_ARGS_((
- ClientData clientData));
-static void DrawMenuBackground _ANSI_ARGS_((
- Rect *menuRectPtr, Drawable d, ThemeMenuType type));
-static void DrawMenuEntryAccelerator _ANSI_ARGS_((
- 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 _ANSI_ARGS_((
- TkMenu *menuPtr, TkMenuEntry *mePtr,
- Drawable d, Tk_3DBorder activeBorder,
- Tk_3DBorder bgBorder, int x, int y,
- int width, int heigth));
-static void DrawMenuEntryIndicator _ANSI_ARGS_((
- 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 _ANSI_ARGS_((
- 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 _ANSI_ARGS_((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 _ANSI_ARGS_((TkMenu *menuPtr,
- TkMenuEntry *mePtr, Drawable d, GC gc,
- Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
- int x, int y, int width, int height));
-static Handle FixMDEF _ANSI_ARGS_((void));
-static void GetEntryText _ANSI_ARGS_((TkMenuEntry *mePtr,
- Tcl_DString *dStringPtr));
-static void GetMenuAccelGeometry _ANSI_ARGS_((TkMenu *menuPtr,
- TkMenuEntry *mePtr, Tk_Font tkfont,
- CONST Tk_FontMetrics *fmPtr, int *modWidthPtr,
- int *textWidthPtr, int *heightPtr));
-static void GetMenuLabelGeometry _ANSI_ARGS_((TkMenuEntry *mePtr,
- Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
- int *widthPtr, int *heightPtr));
-static void GetMenuIndicatorGeometry _ANSI_ARGS_((
- TkMenu *menuPtr, TkMenuEntry *mePtr,
- Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
- int *widthPtr, int *heightPtr));
-static void GetMenuSeparatorGeometry _ANSI_ARGS_((
- TkMenu *menuPtr, TkMenuEntry *mePtr,
- Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
- int *widthPtr, int *heightPtr));
-static void GetTearoffEntryGeometry _ANSI_ARGS_((TkMenu *menuPtr,
- TkMenuEntry *mePtr, Tk_Font tkfont,
- CONST Tk_FontMetrics *fmPtr, int *widthPtr,
- int *heightPtr));
-static int GetNewID _ANSI_ARGS_((Tcl_Interp *interp,
- TkMenu *menuInstPtr, int cascade,
- short *menuIDPtr));
-static char FindMarkCharacter _ANSI_ARGS_((TkMenuEntry *mePtr));
-static void FreeID _ANSI_ARGS_((short menuID));
-static void InvalidateMDEFRgns _ANSI_ARGS_((void));
-static void MenuDefProc _ANSI_ARGS_((short message,
- MenuHandle menu, Rect *menuRectPtr,
- Point hitPt, short *whichItem,
- TkMenuLowMemGlobals *globalsPtr));
-static void MenuSelectEvent _ANSI_ARGS_((TkMenu *menuPtr));
-static void ReconfigureIndividualMenu _ANSI_ARGS_((
- TkMenu *menuPtr, MenuHandle macMenuHdl,
- int base));
-static void ReconfigureMacintoshMenu _ANSI_ARGS_ ((
- ClientData clientData));
-static void RecursivelyClearActiveMenu _ANSI_ARGS_((
- TkMenu *menuPtr));
-static void RecursivelyDeleteMenu _ANSI_ARGS_((
- TkMenu *menuPtr));
-static void RecursivelyInsertMenu _ANSI_ARGS_((
- TkMenu *menuPtr));
-static void SetDefaultMenubar _ANSI_ARGS_((void));
-static int SetMenuCascade _ANSI_ARGS_((TkMenu *menuPtr));
-static void SetMenuIndicator _ANSI_ARGS_((TkMenuEntry *mePtr));
-static void SetMenuTitle _ANSI_ARGS_((MenuHandle menuHdl,
- Tcl_Obj *titlePtr));
-static void AppearanceEntryDrawWrapper _ANSI_ARGS_((TkMenuEntry *mePtr,
- Rect * menuRectPtr, TkMenuLowMemGlobals *globalsPtr,
- Drawable d, Tk_FontMetrics *fmPtr, Tk_Font tkfont,
- int x, int y, int width, int height));
-pascal void tkThemeMenuItemDrawingProc _ANSI_ARGS_ ((const Rect *inBounds,
- SInt16 inDepth, Boolean inIsColorDevice,
- SInt32 inUserData));
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TkMacUseID --
- *
- * 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 GetNewID 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
-TkMacUseMenuID(
- short macID) /* The id to take out of the table */
-{
- Tcl_HashEntry *commandEntryPtr;
- int newEntry;
-
- TkMenuInit();
- commandEntryPtr = Tcl_CreateHashEntry(&commandTable, (char *) macID,
- &newEntry);
- if (newEntry == 1) {
- Tcl_SetHashValue(commandEntryPtr, NULL);
- return TCL_OK;
- } else {
- return TCL_ERROR;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetNewID --
- *
- * 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.
- *
- * 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.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-GetNewID(
- 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;
- 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) {
- commandEntryPtr = Tcl_CreateHashEntry(&commandTable,
- (char *) curID, &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.
- */
-
- unsigned char curID = lastCascadeID + 1;
- if (curID == 236) {
- curID = 0;
- }
-
- while (curID != lastCascadeID) {
- commandEntryPtr = Tcl_CreateHashEntry(&commandTable,
- (char *) curID, &newEntry);
- if (newEntry == 1) {
- found = 1;
- lastCascadeID = returnID = curID;
- break;
- }
- curID++;
- if (curID == 236) {
- curID = 0;
- }
- }
- }
-
- if (found) {
- Tcl_SetHashValue(commandEntryPtr, (char *) menuPtr);
- *menuIDPtr = returnID;
- return TCL_OK;
- } else {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "No more menus can be allocated.",
- (char *) NULL);
- return TCL_ERROR;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FreeID --
- *
- * Marks the id as free.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The hash table entry for the ID is cleared.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-FreeID(
- short menuID) /* The id to free */
-{
- Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&commandTable,
- (char *) menuID);
-
- if (entryPtr != NULL) {
- Tcl_DeleteHashEntry(entryPtr);
- }
- if (menuID == currentAppleMenuID) {
- currentAppleMenuID = 0;
- }
- if (menuID == currentHelpMenuID) {
- currentHelpMenuID = 0;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * 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;
- Str255 itemText;
- int length;
- MenuHandle macMenuHdl;
- int error = TCL_OK;
-
- error = GetNewID(menuPtr->interp, menuPtr, 0, &menuID);
- if (error != TCL_OK) {
- return error;
- }
- length = strlen(Tk_PathName(menuPtr->tkwin));
- memmove(&itemText[1], Tk_PathName(menuPtr->tkwin),
- (length > 230) ? 230 : length);
- itemText[0] = (length > 230) ? 230 : length;
- macMenuHdl = NewMenu(menuID, itemText);
-#if GENERATINGCFM
- {
- Handle mdefProc = FixMDEF();
- if ((mdefProc != NULL)) {
- (*macMenuHdl)->menuProc = mdefProc;
- }
- }
-#endif
- menuPtr->platformData = (TkMenuPlatformData) ckalloc(sizeof(MacMenu));
- ((MacMenu *) menuPtr->platformData)->menuHdl = macMenuHdl;
- SetRect(&((MacMenu *) menuPtr->platformData)->menuRect, 0, 0, 0, 0);
-
- 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, (ClientData *) NULL);
- menuBarFlags |= MENUBAR_REDRAW_PENDING;
- }
- }
- }
- }
-
- menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
- Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) 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 */
-{
- MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
-
- if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
- Tcl_CancelIdleCall(ReconfigureMacintoshMenu, (ClientData) menuPtr);
- menuPtr->menuFlags &= ~MENU_RECONFIGURE_PENDING;
- }
-
- if ((*macMenuHdl)->menuID == currentHelpMenuID) {
- MenuHandle helpMenuHdl;
-
- if ((HMGetHelpMenuHandle(&helpMenuHdl) == noErr)
- && (helpMenuHdl != NULL)) {
- int i, count = CountMItems(helpMenuHdl);
-
- for (i = helpItemCount; i <= count; i++) {
- DeleteMenuItem(helpMenuHdl, helpItemCount);
- }
- }
- currentHelpMenuID = 0;
- }
-
- if (menuPtr->platformData != NULL) {
- DeleteMenu((*macMenuHdl)->menuID);
- FreeID((*macMenuHdl)->menuID);
- DisposeMenu(macMenuHdl);
- ckfree((char *) 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.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-SetMenuCascade(
- TkMenu* menuPtr) /* The menu we are setting up to be a
- * cascade. */
-{
- MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
- short newMenuID, menuID = (*macMenuHdl)->menuID;
- int error = TCL_OK;
-
- if (menuID >= 256) {
- error = GetNewID(menuPtr->interp, menuPtr, 1, &newMenuID);
- if (error == TCL_OK) {
- FreeID(menuID);
- (*macMenuHdl)->menuID = 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((char *) mePtr->platformEntryData);
- if ((menuPtr->platformData != NULL)
- && !(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
- menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
- Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) 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 "Š".
- *
- * Results:
- * itemText points to the new text for the item.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static 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. */
-{
- Tcl_DStringInit(dStringPtr);
- if (mePtr->type == TEAROFF_ENTRY) {
- Tcl_DStringAppend(dStringPtr, "(Tear-off)", -1);
- } else if ((mePtr->imagePtr != NULL) && (mePtr->compound == COMPOUND_NONE)) {
- Tcl_DStringAppend(dStringPtr, "(Image)", -1);
- } else if ((mePtr->bitmapPtr != NULL) && (mePtr->compound == COMPOUND_NONE)) {
- Tcl_DStringAppend(dStringPtr, "(Pixmap)", -1);
- } else if (mePtr->labelPtr == NULL || mePtr->labelLength == 0) {
- /*
- * 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) != '\0') && (*(text + 1) == '.')
- && (*(text + 2) != '\0') && (*(text + 2) == '.')) {
- Tcl_DStringAppend(dStringPtr, elipsisString, -1);
- i += strlen(elipsisString) - 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.
- *
- * We try the following special mac characters. If none of them
- * are present, just use the check mark.
- * '' - Check mark character (\022)
- * '€' - Mac Bullet character (\245)
- * '' - Filled diamond (\023)
- * '×' - Hollow diamond (\327)
- * '‹' = Mac Long dash ("em dash") (\321)
- * '-' = short dash (minus, "en dash");
- *
- * Results:
- * None.
- *
- * Side effects:
- * New item is added to platform menu
- *
- *----------------------------------------------------------------------
- */
-
-static char
-FindMarkCharacter(
- TkMenuEntry *mePtr) /* The entry we are finding the character
- * for. */
-{
- char markChar;
- Tk_Font tkfont;
-
- tkfont = Tk_GetFontFromObj(mePtr->menuPtr->tkwin,
- (mePtr->fontPtr == NULL) ? mePtr->menuPtr->fontPtr
- : mePtr->fontPtr);
-
- if (!TkMacIsCharacterMissing(tkfont, '\022')) {
- markChar = '\022'; /* Check mark */
- } else if (!TkMacIsCharacterMissing(tkfont, '\245')) {
- markChar = '\245'; /* Bullet */
- } else if (!TkMacIsCharacterMissing(tkfont, '\023')) {
- markChar = '\023'; /* Filled Diamond */
- } else if (!TkMacIsCharacterMissing(tkfont, '\327')) {
- markChar = '\327'; /* Hollow Diamond */
- } else if (!TkMacIsCharacterMissing(tkfont, '\321')) {
- markChar = '\321'; /* Long Dash */
- } else if (!TkMacIsCharacterMissing(tkfont, '-')) {
- markChar = '-'; /* Short Dash */
- } else {
- markChar = '\022'; /* Check mark */
- }
- return markChar;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SetMenuIndicator --
- *
- * Sets the Macintosh mark character based on the font of the
- * item.
- *
- * Results:
- * None.
- *
- * Side effects:
- * New item is added to platform menu
- *
- *----------------------------------------------------------------------
- */
-
-static void
-SetMenuIndicator(
- TkMenuEntry *mePtr) /* The entry we are setting */
-{
- TkMenu *menuPtr = mePtr->menuPtr;
- MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
- char markChar;
-
- /*
- * There can be no indicators on menus that are not checkbuttons
- * or radiobuttons. However, we should go ahead and set them
- * so that menus look right when they are displayed. We should
- * not set cascade entries, however, as the mark character
- * means something different for cascade items on the Mac.
- * Also, we do reflect the tearOff menu items in the Mac menu
- * handle, so we ignore them.
- */
-
- if (mePtr->type == CASCADE_ENTRY) {
- return;
- }
-
- markChar = 0;
- if ((mePtr->type == RADIO_BUTTON_ENTRY)
- || (mePtr->type == CHECK_BUTTON_ENTRY)) {
- if (mePtr->indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED)) {
- markChar = FindMarkCharacter(mePtr);
- }
- }
- SetItemMark(macMenuHdl, mePtr->index + 1, markChar);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SetMenuTitle --
- *
- * Sets title of menu so that the text displays correctly in menubar.
- * This code directly manipulates menu handle data. This code
- * was originally part of an ancient Apple Developer Response mail.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The menu handle will change size depending on the length of the
- * title
- *
- *----------------------------------------------------------------------
- */
-
-static void
-SetMenuTitle(
- MenuHandle menuHdl, /* The menu we are setting the title of. */
- Tcl_Obj *titlePtr) /* The C string to set the title to. */
-{
- int oldLength, newLength, oldHandleSize, dataLength;
- Ptr menuDataPtr;
- char *title = (titlePtr == NULL) ? ""
- : Tcl_GetStringFromObj(titlePtr, NULL);
-
- menuDataPtr = (Ptr) (*menuHdl)->menuData;
-
- if (strncmp(title, menuDataPtr + 1, menuDataPtr[0]) != 0) {
- newLength = strlen(title) + 1;
- oldLength = menuDataPtr[0] + 1;
- oldHandleSize = GetHandleSize((Handle) menuHdl);
- dataLength = oldHandleSize - (sizeof(MenuInfo) - sizeof(Str255))
- - oldLength;
- if (newLength > oldLength) {
- SetHandleSize((Handle) menuHdl, oldHandleSize + (newLength
- - oldLength));
- menuDataPtr = (Ptr) (*menuHdl)->menuData;
- }
-
- BlockMove(menuDataPtr + oldLength, menuDataPtr + newLength,
- dataLength);
- BlockMove(title, menuDataPtr + 1, newLength - 1);
- menuDataPtr[0] = newLength - 1;
-
- if (newLength < oldLength) {
- SetHandleSize((Handle) menuHdl, oldHandleSize + (newLength
- - oldLength));
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * 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(
- register TkMenuEntry *mePtr) /* Information about menu entry; may
- * or may not already have values for
- * some fields. */
-{
- TkMenu *menuPtr = mePtr->menuPtr;
- int index = mePtr->index;
- MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
- MenuHandle helpMenuHdl = NULL;
-
- /*
- * 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) {
- SetMenuTitle(childMenuHdl, mePtr->labelPtr);
- }
- }
- }
- }
-
- /*
- * 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) {
- ((EntryGeometry *)mePtr->platformEntryData)->accelTextStart = -1;
- } else {
- char *accelString = (mePtr->accelPtr == NULL) ? ""
- : Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
- char *accel = accelString;
- mePtr->entryFlags |= ~ENTRY_ACCEL_MASK;
-
- while (1) {
- if ((0 == strncasecmp("Control", accelString, 6))
- && (('-' == accelString[6]) || ('+' == accelString[6]))) {
- mePtr->entryFlags |= ENTRY_CONTROL_ACCEL;
- accelString += 7;
- } else if ((0 == strncasecmp("Ctrl", accelString, 4))
- && (('-' == accelString[4]) || ('+' == accelString[4]))) {
- mePtr->entryFlags |= ENTRY_CONTROL_ACCEL;
- accelString += 5;
- } else if ((0 == strncasecmp("Shift", accelString, 5))
- && (('-' == accelString[5]) || ('+' == accelString[5]))) {
- mePtr->entryFlags |= ENTRY_SHIFT_ACCEL;
- accelString += 6;
- } else if ((0 == strncasecmp("Option", accelString, 6))
- && (('-' == accelString[6]) || ('+' == accelString[6]))) {
- mePtr->entryFlags |= ENTRY_OPTION_ACCEL;
- accelString += 7;
- } else if ((0 == strncasecmp("Opt", accelString, 3))
- && (('-' == accelString[3]) || ('+' == accelString[3]))) {
- mePtr->entryFlags |= ENTRY_OPTION_ACCEL;
- accelString += 4;
- } else if ((0 == strncasecmp("Command", accelString, 7))
- && (('-' == accelString[7]) || ('+' == accelString[7]))) {
- mePtr->entryFlags |= ENTRY_COMMAND_ACCEL;
- accelString += 8;
- } else if ((0 == strncasecmp("Cmd", accelString, 3))
- && (('-' == accelString[3]) || ('+' == accelString[3]))) {
- mePtr->entryFlags |= ENTRY_COMMAND_ACCEL;
- accelString += 4;
- } else if ((0 == strncasecmp("Alt", accelString, 3))
- && (('-' == accelString[3]) || ('+' == accelString[3]))) {
- mePtr->entryFlags |= ENTRY_OPTION_ACCEL;
- accelString += 4;
- } else if ((0 == strncasecmp("Meta", accelString, 4))
- && (('-' == accelString[4]) || ('+' == accelString[4]))) {
- mePtr->entryFlags |= ENTRY_COMMAND_ACCEL;
- accelString += 5;
- } else {
- break;
- }
- }
-
- ((EntryGeometry *)mePtr->platformEntryData)->accelTextStart
- = ((long) accelString - (long) accel);
- }
-
- if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
- menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
- Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) 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
- *
- *----------------------------------------------------------------------
- */
-
-static 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;
- * helpMenuItemCount for help menus. */
-{
- int count;
- int index;
- TkMenuEntry *mePtr;
- Str255 itemText;
- int parentDisabled = 0;
-
- for (mePtr = menuPtr->menuRefPtr->parentEntryPtr; mePtr != NULL;
- mePtr = mePtr->nextCascadePtr) {
- char *name = (mePtr->namePtr == NULL) ? ""
- : Tcl_GetStringFromObj(mePtr->namePtr, NULL);
-
- if (strcmp(Tk_PathName(menuPtr->tkwin), name) == 0) {
- if (mePtr->state == ENTRY_DISABLED) {
- parentDisabled = 1;
- }
- break;
- }
- }
-
- /*
- * First, we get rid of all of the old items.
- */
-
- count = CountMItems(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) {
- AppendMenu(macMenuHdl, SEPARATOR_TEXT);
- } else {
- Tcl_DString itemTextDString;
- int destWrote;
-
- GetEntryText(mePtr, &itemTextDString);
- Tcl_UtfToExternal(NULL, NULL, Tcl_DStringValue(&itemTextDString),
- Tcl_DStringLength(&itemTextDString), 0, NULL,
- (char *) &itemText[1],
- 231, NULL, &destWrote, NULL);
- itemText[0] = destWrote;
-
- AppendMenu(macMenuHdl, "\px");
- SetMenuItemText(macMenuHdl, base + index, itemText);
- Tcl_DStringFree(&itemTextDString);
-
- /*
- * Set enabling and disabling correctly.
- */
-
- if (parentDisabled || (mePtr->state == ENTRY_DISABLED)) {
- DisableItem(macMenuHdl, base + index);
- } else {
- EnableItem(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)) {
- CheckItem(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) {
- childMenuHdl = ((MacMenu *) mePtr->childMenuRefPtr
- ->menuPtr->platformData)->menuHdl;
- }
- if (childMenuHdl != NULL) {
- if (TkMacHaveAppearance() > 1) {
- SetMenuItemHierarchicalID(macMenuHdl, base + index,
- (*childMenuHdl)->menuID);
- } else {
- SetItemMark(macMenuHdl, base + index,
- (*childMenuHdl)->menuID);
- SetItemCmd(macMenuHdl, base + index, CASCADE_CMD);
- }
- }
- /*
- * 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,
- (ClientData) mePtr->childMenuRefPtr->menuPtr);
- }
- }
- }
-
- if ((mePtr->type != CASCADE_ENTRY)
- && (ENTRY_COMMAND_ACCEL
- == (mePtr->entryFlags & ENTRY_ACCEL_MASK))) {
- char *accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
- SetItemCmd(macMenuHdl, base + index, accel[((EntryGeometry *)
- mePtr->platformEntryData)->accelTextStart]);
- }
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * 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.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-ReconfigureMacintoshMenu(
- ClientData clientData) /* Information about menu entry; may
- * or may not already have values for
- * some fields. */
-{
- TkMenu *menuPtr = (TkMenu *) clientData;
- MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
- MenuHandle helpMenuHdl = NULL;
-
- menuPtr->menuFlags &= ~MENU_RECONFIGURE_PENDING;
-
- if (NULL == macMenuHdl) {
- return;
- }
-
- ReconfigureIndividualMenu(menuPtr, macMenuHdl, 0);
-
- if (menuPtr->menuFlags & MENU_APPLE_MENU) {
- AppendResMenu(macMenuHdl, 'DRVR');
- }
-
- if ((*macMenuHdl)->menuID == currentHelpMenuID) {
- HMGetHelpMenuHandle(&helpMenuHdl);
- if (helpMenuHdl != NULL) {
- ReconfigureIndividualMenu(menuPtr, helpMenuHdl, helpItemCount);
- }
- }
-
- if (menuPtr->menuType == MENUBAR) {
- if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) {
- Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) 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.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-CompleteIdlers(
- TkMenu *menuPtr) /* The menu we are completing. */
-{
- int i;
-
- if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
- Tcl_CancelIdleCall(ReconfigureMacintoshMenu, (ClientData) menuPtr);
- ReconfigureMacintoshMenu((ClientData) menuPtr);
- }
-
- 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)) {
- 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;
- int oldMode;
-
- if (inPostMenu) {
- Tcl_AppendResult(interp,
- "Cannot call post menu while already posting menu",
- (char *) NULL);
- result = TCL_ERROR;
- } else {
- Window dummyWin;
- unsigned int state;
- int dummy, mouseX, mouseY;
- short menuID;
- Window window;
- int oldWidth = menuPtr->totalWidth;
- Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin);
-
- inPostMenu++;
-
- result = TkPreprocessMenu(menuPtr);
- if (result != TCL_OK) {
- inPostMenu--;
- return result;
- }
-
- /*
- * The post commands could have deleted the menu, which means
- * we are dead and should go away.
- */
-
- if (menuPtr->tkwin == NULL) {
- inPostMenu--;
- return TCL_OK;
- }
-
- CompleteIdlers(menuPtr);
- if (menuBarFlags & MENUBAR_REDRAW_PENDING) {
- Tcl_CancelIdleCall(DrawMenuBarWhenIdle, (ClientData *) NULL);
- DrawMenuBarWhenIdle((ClientData *) NULL);
- }
-
- if (NULL == parentWindow) {
- tearoffStruct.excludeRect.top = tearoffStruct.excludeRect.left
- = tearoffStruct.excludeRect.bottom
- = tearoffStruct.excludeRect.right = SHRT_MAX;
- } else {
- int left, top;
-
- Tk_GetRootCoords(parentWindow, &left, &top);
- tearoffStruct.excludeRect.left = left;
- tearoffStruct.excludeRect.top = top;
- tearoffStruct.excludeRect.right = left + Tk_Width(parentWindow);
- tearoffStruct.excludeRect.bottom = top + Tk_Height(parentWindow);
- if (Tk_Class(parentWindow) == Tk_GetUid("Menubutton")) {
- TkWindow *parentWinPtr = (TkWindow *) parentWindow;
- TkMenuButton *mbPtr =
- (TkMenuButton *) parentWinPtr->instanceData;
- int menuButtonWidth = Tk_Width(parentWindow)
- - 2 * (mbPtr->highlightWidth + mbPtr->borderWidth + 1);
- menuPtr->totalWidth = menuButtonWidth > menuPtr->totalWidth
- ? menuButtonWidth : menuPtr->totalWidth;
- }
- }
-
- InsertMenu(macMenuHdl, -1);
- RecursivelyInsertMenu(menuPtr);
- CountMItems(macMenuHdl);
-
- FixMDEF();
- oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
- popUpResult = PopUpMenuSelect(macMenuHdl, y, x, menuPtr->active);
- Tcl_SetServiceMode(oldMode);
-
- menuPtr->totalWidth = oldWidth;
- RecursivelyDeleteMenu(menuPtr);
- DeleteMenu((*macMenuHdl)->menuID);
-
- /*
- * Simulate the mouse up.
- */
-
- XQueryPointer(NULL, None, &dummyWin, &dummyWin, &mouseX,
- &mouseY, &dummy, &dummy, &state);
- window = Tk_WindowId(menuPtr->tkwin);
- TkGenerateButtonEvent(mouseX, mouseY, window, state);
-
- /*
- * Dispatch the command.
- */
-
- menuID = HiWord(popUpResult);
- if (menuID != 0) {
- result = TkMacDispatchMenuEvent(menuID, LoWord(popUpResult));
- } else {
- TkMacHandleTearoffMenu();
- result = TCL_OK;
- }
- InvalidateMDEFRgns();
- RecursivelyClearActiveMenu(menuPtr);
-
- 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 =
- (EntryGeometry *) ckalloc(sizeof(EntryGeometry));
- TkMenu *menuPtr = mePtr->menuPtr;
-
- geometryPtr->accelTextStart = 0;
- geometryPtr->accelTextWidth = 0;
- geometryPtr->nonAccelMargin = 0;
- geometryPtr->modifierWidth = 0;
- mePtr->platformEntryData = (TkMenuPlatformEntryData) geometryPtr;
- if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
- menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
- Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr);
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- *
- * Tk_MacTurnOffMenus --
- *
- * 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_MacTurnOffMenus()
-{
- gNoTkMenus = 1;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- *
- * DrawMenuBarWhenIdle --
- *
- * Update the menu bar next time there is an idle event.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Menu bar is redrawn.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-DrawMenuBarWhenIdle(
- ClientData clientData) /* ignored here */
-{
- TkMenuReferences *menuRefPtr;
- TkMenu *appleMenuPtr, *helpMenuPtr;
- 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 *) currentAppleMenuID);
- appleMenuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
- TkpDestroyMenu(appleMenuPtr);
- TkpNewMenu(appleMenuPtr);
- appleMenuPtr->menuFlags &= ~MENU_APPLE_MENU;
- appleMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
- Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
- (ClientData) appleMenuPtr);
- }
-
- if (currentHelpMenuID != 0) {
- hashEntryPtr = Tcl_FindHashEntry(&commandTable,
- (char *) currentHelpMenuID);
- helpMenuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
- TkpDestroyMenu(helpMenuPtr);
- TkpNewMenu(helpMenuPtr);
- helpMenuPtr->menuFlags &= ~MENU_HELP_MENU;
- helpMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
- Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
- (ClientData) 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 != NULL) {
- TkMenu *menuPtr, *menuBarPtr;
- TkMenu *cascadeMenuPtr;
- char *appleMenuName, *helpMenuName;
- int appleIndex = -1, helpIndex = -1;
- int 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 == NULL) {
- SetDefaultMenubar();
- } else {
- 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;
- } else {
- short appleID;
- appleMenuPtr = menuBarPtr->entries[appleIndex]
- ->childMenuRefPtr->menuPtr;
- TkpDestroyMenu(appleMenuPtr);
- GetNewID(appleMenuPtr->interp, appleMenuPtr, 0,
- &appleID);
- macMenuHdl = NewMenu(appleID, "\p\024");
- appleMenuPtr->platformData =
- (TkMenuPlatformData) ckalloc(sizeof(MacMenu));
- ((MacMenu *)appleMenuPtr->platformData)->menuHdl
- = macMenuHdl;
- SetRect(&((MacMenu *) appleMenuPtr->platformData)->menuRect,
- 0, 0, 0, 0);
- appleMenuPtr->menuFlags |= MENU_APPLE_MENU;
- if (!(appleMenuPtr->menuFlags
- & MENU_RECONFIGURE_PENDING)) {
- appleMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
- Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
- (ClientData) appleMenuPtr);
- }
- InsertMenu(macMenuHdl, 0);
- RecursivelyInsertMenu(appleMenuPtr);
- currentAppleMenuID = appleID;
- }
- if (helpIndex == -1) {
- currentHelpMenuID = 0;
- }
-
- for (i = 0; i < menuBarPtr->numEntries; i++) {
- if (i == appleIndex) {
- if (menuBarPtr->entries[i]->state == ENTRY_DISABLED) {
- DisableItem(((MacMenu *) menuBarPtr->entries[i]
- ->childMenuRefPtr->menuPtr
- ->platformData)->menuHdl,
- 0);
- } else {
- EnableItem(((MacMenu *) menuBarPtr->entries[i]
- ->childMenuRefPtr->menuPtr
- ->platformData)->menuHdl,
- 0);
- }
- continue;
- } else if (i == helpIndex) {
- TkMenu *helpMenuPtr = menuBarPtr->entries[i]
- ->childMenuRefPtr->menuPtr;
- MenuHandle helpMenuHdl = NULL;
-
- if (helpMenuPtr == NULL) {
- continue;
- }
- helpMenuPtr->menuFlags |= MENU_HELP_MENU;
- if (!(helpMenuPtr->menuFlags
- & MENU_RECONFIGURE_PENDING)) {
- helpMenuPtr->menuFlags
- |= MENU_RECONFIGURE_PENDING;
- Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
- (ClientData) helpMenuPtr);
- }
- macMenuHdl =
- ((MacMenu *) helpMenuPtr->platformData)->menuHdl;
- currentHelpMenuID = (*macMenuHdl)->menuID;
- } 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((*macMenuHdl)->menuID);
- InsertMenu(macMenuHdl, 0);
- RecursivelyInsertMenu(cascadeMenuPtr);
- if (menuBarPtr->entries[i]->state == ENTRY_DISABLED) {
- DisableItem(((MacMenu *) menuBarPtr->entries[i]
- ->childMenuRefPtr->menuPtr
- ->platformData)->menuHdl,
- 0);
- } else {
- EnableItem(((MacMenu *) menuBarPtr->entries[i]
- ->childMenuRefPtr->menuPtr
- ->platformData)->menuHdl,
- 0);
- }
- }
- }
- }
- }
- } else {
- 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.
- *
- *----------------------------------------------------------------------
- */
-
-static 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.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-RecursivelyDeleteMenu(
- 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;
- DeleteMenu((*macMenuHdl)->menuID);
- RecursivelyInsertMenu(cascadeMenuPtr);
- }
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SetDefaultMenubar --
- *
- * Puts the Apple, File and Edit menus into the Macintosh menubar.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The menubar is changed.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-SetDefaultMenubar()
-{
- 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, (ClientData *) 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 */
- 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) TkMacGetDrawablePort(winPtr->window);
- WindowRef frontNonFloating;
-
- if (TkMacHaveAppearance() >= 0x110) {
- frontNonFloating = FrontNonFloatingWindow();
- } else {
- frontNonFloating = FrontWindow();
- }
-
- 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) {
- menuPtr = menuPtr->masterMenuPtr;
- searchWindow = menuPtr->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, (ClientData *) 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((char *) listPtr);
- }
-
- if (menuPtr != NULL) {
- listPtr = (TopLevelMenubarList *) ckalloc(sizeof(TopLevelMenubarList));
- listPtr->nextPtr = windowListPtr;
- windowListPtr = listPtr;
- listPtr->tkwin = tkwin;
- listPtr->menuPtr = menuPtr;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkMacDispatchMenuEvent --
- *
- * Given a menu id and an item, dispatches the command associated
- * with it.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Commands get executed.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TkMacDispatchMenuEvent(
- 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)) {
- int newIndex = index - helpItemCount - 1;
- result = TkInvokeMenu(currentMenuBarInterp,
- helpMenuRef->menuPtr, newIndex);
- }
- }
- } else {
- Tcl_HashEntry *commandEntryPtr =
- Tcl_FindHashEntry(&commandTable, (char *) menuID);
- TkMenu *menuPtr = (TkMenu *) Tcl_GetHashValue(commandEntryPtr);
- if ((currentAppleMenuID == menuID)
- && (index > menuPtr->numEntries + 1)) {
- Str255 itemText;
-
- GetMenuItemText(GetMenuHandle(menuID), index, itemText);
- OpenDeskAcc(itemText);
- result = TCL_OK;
- } else {
- result = TkInvokeMenu(menuPtr->interp, menuPtr, index - 1);
- }
- }
- }
- return result;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetMenuIndicatorGeometry --
- *
- * Gets the width and height of the indicator area of a menu.
- *
- * Results:
- * widthPtr and heightPtr are set.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static 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 */
-{
- char markChar;
-
- *heightPtr = fmPtr->linespace;
-
- markChar = (char) FindMarkCharacter(mePtr);
- *widthPtr = Tk_TextWidth(tkfont, &markChar, 1) + 4;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetMenuAccelGeometry --
- *
- * Gets the width and height of the accelerator area of a menu.
- *
- * Results:
- * widthPtr and heightPtr are set.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static 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;
- *modWidthPtr = 0;
- if (mePtr->type == CASCADE_ENTRY) {
- *textWidthPtr = SICN_HEIGHT;
- *modWidthPtr = Tk_TextWidth(tkfont, "W", 1);
- } else if (0 == mePtr->accelLength) {
- *textWidthPtr = 0;
- } else {
- char *accel = (mePtr->accelPtr == NULL) ? ""
- : Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
-
- if (NULL == GetResource('SICN', SICN_RESOURCE_NUMBER)) {
- *textWidthPtr = Tk_TextWidth(tkfont, accel, mePtr->accelLength);
- } else {
- int emWidth = Tk_TextWidth(tkfont, "W", 1) + 1;
- if ((mePtr->entryFlags & ENTRY_ACCEL_MASK) == 0) {
- int width = Tk_TextWidth(tkfont, accel, mePtr->accelLength);
- *textWidthPtr = emWidth;
- if (width < emWidth) {
- *modWidthPtr = 0;
- } else {
- *modWidthPtr = width - emWidth;
- }
- } else {
- int length = ((EntryGeometry *)mePtr->platformEntryData)
- ->accelTextStart;
- if (mePtr->entryFlags & ENTRY_CONTROL_ACCEL) {
- *modWidthPtr += CONTROL_ICON_WIDTH;
- }
- if (mePtr->entryFlags & ENTRY_SHIFT_ACCEL) {
- *modWidthPtr += SHIFT_ICON_WIDTH;
- }
- if (mePtr->entryFlags & ENTRY_OPTION_ACCEL) {
- *modWidthPtr += OPTION_ICON_WIDTH;
- }
- if (mePtr->entryFlags & ENTRY_COMMAND_ACCEL) {
- *modWidthPtr += COMMAND_ICON_WIDTH;
- }
- if (1 == (mePtr->accelLength - length)) {
- *textWidthPtr = emWidth;
- } else {
- *textWidthPtr += Tk_TextWidth(tkfont, accel
- + length, mePtr->accelLength - length);
- }
- }
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetTearoffEntryGeometry --
- *
- * Gets the width and height of of a tearoff entry.
- *
- * Results:
- * widthPtr and heightPtr are set.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static 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 */
-{
- if ((GetResource('MDEF', 591) == NULL) &&
- (menuPtr->menuType == MASTER_MENU)) {
- *heightPtr = fmPtr->linespace;
- *widthPtr = 0;
- } else {
- *widthPtr = *heightPtr = 0;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetMenuSeparatorGeometry --
- *
- * Gets the width and height of menu separator.
- *
- * Results:
- * widthPtr and heightPtr are set.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static 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 */
-{
- if (TkMacHaveAppearance() > 1) {
- SInt16 outHeight;
-
- GetThemeMenuSeparatorHeight(&outHeight);
- *widthPtr = 0;
- *heightPtr = outHeight;
- } else {
- *widthPtr = 0;
- *heightPtr = fmPtr->linespace;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * 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.
- *
- *----------------------------------------------------------------------
- */
-
-static 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)) {
- int baseline;
- short markShort;
-
- baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
- GetItemMark(((MacMenu *) menuPtr->platformData)->menuHdl,
- mePtr->index + 1, &markShort);
- if (markShort != 0) {
- char markChar;
- char markCharUTF[TCL_UTF_MAX + 1];
- int dstWrote;
-
- markChar = (char) markShort;
- Tcl_ExternalToUtf(NULL, NULL, &markChar, 1, 0, NULL,
- markCharUTF, TCL_UTF_MAX + 1, NULL, &dstWrote, NULL);
- Tk_DrawChars(menuPtr->display, d, gc, tkfont, markCharUTF,
- dstWrote, x + 2, baseline);
- }
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * 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.
- *
- *----------------------------------------------------------------------
- */
-static void
-DrawMenuBackground(
- Rect *menuRectPtr, /* The menu rect */
- Drawable d, /* What we are drawing into */
- ThemeMenuType type /* Type of menu */
- )
-{
- if (!TkMacHaveAppearance()) {
- return;
- } else {
- CGrafPtr saveWorld;
- GDHandle saveDevice;
- GWorldPtr destPort;
-
- destPort = TkMacGetDrawablePort(d);
- GetGWorld(&saveWorld, &saveDevice);
- SetGWorld(destPort, NULL);
- TkMacSetUpClippingRgn(d);
- DrawThemeMenuBackground (menuRectPtr, type);
- SetGWorld(saveWorld, saveDevice);
- return;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * DrawSICN --
- *
- * Given a resource id and an index, loads the appropriate SICN
- * and draws it into a given drawable using the given gc.
- *
- * Results:
- * Returns 1 if the SICN was found, 0 if not found.
- *
- * Side effects:
- * Commands are output to X to display the menu in its
- * current mode.
- *
- *----------------------------------------------------------------------
- */
-static int
-DrawSICN(
- int resourceID, /* The resource # of the SICN table */
- int index, /* The index into the SICN table of the
- * icon we want. */
- Drawable d, /* What we are drawing into */
- GC gc, /* The GC to draw with */
- int x, /* The left hand coord of the SICN */
- int y) /* The top coord of the SICN */
-{
- Handle sicnHandle = (Handle) GetResource('SICN', SICN_RESOURCE_NUMBER);
-
- if (NULL == sicnHandle) {
- return 0;
- } else {
- BitMap sicnBitmap;
- Rect destRect;
- CGrafPtr saveWorld;
- GDHandle saveDevice;
- GWorldPtr destPort;
- BitMapPtr destBitMap;
- RGBColor origForeColor, origBackColor, foreColor, backColor;
-
- HLock(sicnHandle);
- destPort = TkMacGetDrawablePort(d);
- GetGWorld(&saveWorld, &saveDevice);
- SetGWorld(destPort, NULL);
- TkMacSetUpClippingRgn(d);
- TkMacSetUpGraphicsPort(gc);
- GetForeColor(&origForeColor);
- GetBackColor(&origBackColor);
-
- if (TkSetMacColor(gc->foreground, &foreColor)) {
- RGBForeColor(&foreColor);
- }
-
- if (TkSetMacColor(gc->background, &backColor)) {
- RGBBackColor(&backColor);
- }
-
- SetRect(&destRect, x, y, x + SICN_HEIGHT, y + SICN_HEIGHT);
- sicnBitmap.baseAddr = (Ptr) (*sicnHandle) + index * SICN_HEIGHT
- * SICN_ROWS;
- sicnBitmap.rowBytes = SICN_ROWS;
- SetRect(&sicnBitmap.bounds, 0, 0, 16, 16);
- destBitMap = &((GrafPtr) destPort)->portBits;
- CopyBits(&sicnBitmap, destBitMap, &sicnBitmap.bounds, &destRect,
- destPort->txMode, NULL);
- HUnlock(sicnHandle);
- RGBForeColor(&origForeColor);
- RGBBackColor(&origBackColor);
- SetGWorld(saveWorld, saveDevice);
- return 1;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * DrawMenuEntryAccelerator --
- *
- * This procedure draws the accelerator part of a menu. We
- * need to decide what to draw here. Should we replace strings
- * like "Control", "Command", etc?
- *
- * Results:
- * None.
- *
- * Side effects:
- * Commands are output to X to display the menu in its
- * current mode.
- *
- *----------------------------------------------------------------------
- */
-
-static 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 */
-{
- int activeBorderWidth;
-
- Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,
- &activeBorderWidth);
- if (mePtr->type == CASCADE_ENTRY) {
- /*
- * Under Appearance, we let the Appearance Manager draw the icon
- */
-
- if (!TkMacHaveAppearance()) {
- if (0 == DrawSICN(SICN_RESOURCE_NUMBER, CASCADE_ARROW, d, gc,
- x + width - SICN_HEIGHT, (y + (height / 2))
- - (SICN_HEIGHT / 2))) {
- XPoint points[3];
- Tk_Window tkwin = menuPtr->tkwin;
-
- if (mePtr->type == CASCADE_ENTRY) {
- points[0].x = width - activeBorderWidth
- - MAC_MARGIN_WIDTH - CASCADE_ARROW_WIDTH;
- points[0].y = y + (height - CASCADE_ARROW_HEIGHT)/2;
- points[1].x = points[0].x;
- points[1].y = points[0].y + CASCADE_ARROW_HEIGHT;
- points[2].x = points[0].x + CASCADE_ARROW_WIDTH;
- points[2].y = points[0].y + CASCADE_ARROW_HEIGHT/2;
- Tk_Fill3DPolygon(menuPtr->tkwin, d, activeBorder, points,
- 3, DECORATION_BORDER_WIDTH, TK_RELIEF_FLAT);
- }
- }
- }
- } else if (mePtr->accelLength != 0) {
- int leftEdge = x + width;
- int baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
- char *accel;
-
- accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
-
- if (NULL == GetResource('SICN', SICN_RESOURCE_NUMBER)) {
- leftEdge -= ((EntryGeometry *) mePtr->platformEntryData)
- ->accelTextWidth;
- Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
- mePtr->accelLength, leftEdge, baseline);
- } else {
- EntryGeometry *geometryPtr =
- (EntryGeometry *) mePtr->platformEntryData;
- int length = mePtr->accelLength - geometryPtr->accelTextStart;
-
- leftEdge -= geometryPtr->accelTextWidth;
- if ((mePtr->entryFlags & ENTRY_ACCEL_MASK) == 0) {
- leftEdge -= geometryPtr->modifierWidth;
- }
-
- Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel
- + geometryPtr->accelTextStart, length, leftEdge, baseline);
-
- if (mePtr->entryFlags & ENTRY_COMMAND_ACCEL) {
- leftEdge -= COMMAND_ICON_WIDTH;
- DrawSICN(SICN_RESOURCE_NUMBER, COMMAND_ICON, d, gc,
- leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
- }
-
- if (mePtr->entryFlags & ENTRY_OPTION_ACCEL) {
- leftEdge -= OPTION_ICON_WIDTH;
- DrawSICN(SICN_RESOURCE_NUMBER, OPTION_ICON, d, gc,
- leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
- }
-
- if (mePtr->entryFlags & ENTRY_SHIFT_ACCEL) {
- leftEdge -= SHIFT_ICON_WIDTH;
- DrawSICN(SICN_RESOURCE_NUMBER, SHIFT_ICON, d, gc,
- leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
- }
-
- if (mePtr->entryFlags & ENTRY_CONTROL_ACCEL) {
- leftEdge -= CONTROL_ICON_WIDTH;
- DrawSICN(SICN_RESOURCE_NUMBER, CONTROL_ICON, d, gc,
- leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
- }
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * DrawMenuSeparator --
- *
- * The menu separator is drawn.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Commands are output to X to display the menu in its
- * current mode.
- *
- *----------------------------------------------------------------------
- */
-
-static 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 */
-{
- CGrafPtr saveWorld;
- GDHandle saveDevice;
- GWorldPtr destPort;
-
- destPort = TkMacGetDrawablePort(d);
- GetGWorld(&saveWorld, &saveDevice);
- SetGWorld(destPort, NULL);
- TkMacSetUpClippingRgn(d);
- if (TkMacHaveAppearance() > 1) {
- Rect r;
- r.top = y;
- r.left = x;
- r.bottom = y + height;
- r.right = x + width;
-
- DrawThemeMenuSeparator(&r);
- } else {
- /*
- * We don't want to use the text GC for drawing the separator. It
- * needs to be the same color as disabled items.
- */
-
- TkMacSetUpGraphicsPort(mePtr->disabledGC != None ? mePtr->disabledGC
- : menuPtr->disabledGC);
-
- MoveTo(x, y + (height / 2));
- Line(width, 0);
-
- SetGWorld(saveWorld, saveDevice);
-}
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * 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.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-MenuDefProc(
- short message, /* What action are we taking? */
- MenuHandle 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. */
- short *whichItem, /* Output result. Which item was
- * hit by the user? */
- TkMenuLowMemGlobals *globalsPtr) /* The low mem globals we have
- * to change */
-{
-#define SCREEN_MARGIN 5
- TkMenu *menuPtr;
- TkMenuEntry *parentEntryPtr;
- Tcl_HashEntry *commandEntryPtr;
- GrafPtr windowMgrPort;
- Tk_Font tkfont, menuFont;
- Tk_FontMetrics fontMetrics, entryMetrics;
- Tk_FontMetrics *fmPtr;
- TkMenuEntry *mePtr;
- int i;
- int maxMenuHeight;
- int oldItem;
- int newItem = -1;
- GDHandle device;
- Rect itemRect;
- short windowPart;
- WindowRef whichWindow;
- RGBColor bgColor;
- RGBColor fgColor;
- RGBColor origFgColor;
- PenState origPenState;
- Rect dragRect;
- Rect scratchRect = {-32768, -32768, 32767, 32767};
- RgnHandle oldClipRgn;
- TkMenuReferences *menuRefPtr;
- TkMenu *searchMenuPtr;
- Rect menuClipRect;
-
- HLock((Handle) menu);
- commandEntryPtr = Tcl_FindHashEntry(&commandTable,
- (char *) (*menu)->menuID);
- HUnlock((Handle) menu);
- menuPtr = (TkMenu *) Tcl_GetHashValue(commandEntryPtr);
-
- switch (message) {
- case mSizeMsg:
- GetWMgrPort(&windowMgrPort);
- maxMenuHeight = windowMgrPort->portRect.bottom
- - windowMgrPort->portRect.top
- - GetMBarHeight() - SCREEN_MARGIN;
- (*menu)->menuWidth = menuPtr->totalWidth;
- (*menu)->menuHeight = maxMenuHeight < menuPtr->totalHeight ?
- maxMenuHeight : menuPtr->totalHeight;
- break;
-
- case mDrawMsg:
-
- /*
- * Store away the menu rectangle so we can keep track of the
- * different regions that the menu obscures.
- */
-
- ((MacMenu *) menuPtr->platformData)->menuRect = *menuRectPtr;
- if (tkMenuCascadeRgn == NULL) {
- tkMenuCascadeRgn = NewRgn();
- }
- if (utilRgn == NULL) {
- utilRgn = NewRgn();
- }
- if (totalMenuRgn == NULL) {
- totalMenuRgn = NewRgn();
- }
- SetEmptyRgn(tkMenuCascadeRgn);
- for (searchMenuPtr = menuPtr; searchMenuPtr != NULL; ) {
- RectRgn(utilRgn,
- &((MacMenu *) searchMenuPtr->platformData)->menuRect);
- InsetRgn(utilRgn, -1, -1);
- UnionRgn(tkMenuCascadeRgn, utilRgn, tkMenuCascadeRgn);
- OffsetRgn(utilRgn, 1, 1);
- UnionRgn(tkMenuCascadeRgn, utilRgn, tkMenuCascadeRgn);
-
- if (searchMenuPtr->menuRefPtr->parentEntryPtr != NULL) {
- searchMenuPtr = searchMenuPtr->menuRefPtr
- ->parentEntryPtr->menuPtr;
- } else {
- break;
- }
- if (searchMenuPtr->menuType == MENUBAR) {
- break;
- }
- }
- UnionRgn(totalMenuRgn, tkMenuCascadeRgn, totalMenuRgn);
- SetEmptyRgn(utilRgn);
-
- /*
- * Now draw the background if Appearance is present...
- */
-
- GetGWorld(&macMDEFDrawable.portPtr, &device);
- if (TkMacHaveAppearance() > 1) {
- ThemeMenuType menuType;
-
- if (menuPtr->menuRefPtr->topLevelListPtr != NULL) {
- menuType = kThemeMenuTypePullDown;
- } else if (menuPtr->menuRefPtr->parentEntryPtr != NULL) {
- menuType = kThemeMenuTypeHierarchical;
- } else {
- menuType = kThemeMenuTypePopUp;
- }
-
- DrawMenuBackground(menuRectPtr, (Drawable) &macMDEFDrawable,
- menuType);
- }
-
- /*
- * Next, figure out scrolling information.
- */
-
- menuClipRect = *menuRectPtr;
- if ((menuClipRect.bottom - menuClipRect.top)
- < menuPtr->totalHeight) {
- if (globalsPtr->menuTop < menuRectPtr->top) {
- DrawSICN(SICN_RESOURCE_NUMBER, UP_ARROW,
- (Drawable) &macMDEFDrawable,
- menuPtr->textGC,
- menuRectPtr->left
- + menuPtr->entries[1]->indicatorSpace,
- menuRectPtr->top);
- menuClipRect.top += SICN_HEIGHT;
- }
- if ((globalsPtr->menuTop + menuPtr->totalHeight)
- > menuRectPtr->bottom) {
- DrawSICN(SICN_RESOURCE_NUMBER, DOWN_ARROW,
- (Drawable) &macMDEFDrawable,
- menuPtr->textGC,
- menuRectPtr->left
- + menuPtr->entries[1]->indicatorSpace,
- menuRectPtr->bottom - SICN_HEIGHT);
- menuClipRect.bottom -= SICN_HEIGHT;
- }
- GetClip(utilRgn);
- }
-
- /*
- * 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.
- */
-
- menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
- Tk_GetFontMetrics(menuFont, &fontMetrics);
- for (i = 0; i < menuPtr->numEntries; i++) {
- mePtr = menuPtr->entries[i];
- if (globalsPtr->menuTop + mePtr->y + mePtr->height
- < menuClipRect.top) {
- continue;
- } else if (globalsPtr->menuTop + mePtr->y
- > menuClipRect.bottom) {
- continue;
- }
- /* ClipRect(&menuClipRect); */
- if (mePtr->fontPtr == NULL) {
- fmPtr = &fontMetrics;
- tkfont = menuFont;
- } else {
- tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
- Tk_GetFontMetrics(tkfont, &entryMetrics);
- fmPtr = &entryMetrics;
- }
- AppearanceEntryDrawWrapper(mePtr, menuRectPtr, globalsPtr,
- (Drawable) &macMDEFDrawable, fmPtr, tkfont,
- menuRectPtr->left + mePtr->x,
- globalsPtr->menuTop + mePtr->y,
- (mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
- menuPtr->totalWidth - mePtr->x : mePtr->width,
- menuPtr->entries[i]->height);
- }
- globalsPtr->menuBottom = globalsPtr->menuTop
- + menuPtr->totalHeight;
- if (!EmptyRgn(utilRgn)) {
- SetClip(utilRgn);
- SetEmptyRgn(utilRgn);
- }
- MDEFScrollFlag = 1;
- break;
-
- case mChooseMsg: {
- int hasTopScroll, hasBottomScroll;
- enum {
- DONT_SCROLL, DOWN_SCROLL, UP_SCROLL
- } scrollDirection;
- Rect updateRect;
- short scrollAmt;
- RGBColor origForeColor, origBackColor, foreColor, backColor;
-
- GetGWorld(&macMDEFDrawable.portPtr, &device);
- GetForeColor(&origForeColor);
- GetBackColor(&origBackColor);
-
- if (TkSetMacColor(menuPtr->textGC->foreground,
- &foreColor)) {
- /* if (!TkMacHaveAppearance()) { */
- RGBForeColor(&foreColor);
- /* } */
- }
- if (TkSetMacColor(menuPtr->textGC->background,
- &backColor)) {
- /* if (!TkMacHaveAppearance()) { */
- RGBBackColor(&backColor);
- /* } */
- }
-
- /*
- * Find out which item was hit. If it is the same as the old item,
- * we don't need to do anything.
- */
-
- oldItem = *whichItem - 1;
-
- if (PtInRect(hitPt, menuRectPtr)) {
- for (i = 0; i < menuPtr->numEntries; i++) {
- mePtr = menuPtr->entries[i];
- itemRect.left = menuRectPtr->left + mePtr->x;
- itemRect.top = globalsPtr->menuTop + mePtr->y;
- if (mePtr->entryFlags & ENTRY_LAST_COLUMN) {
- itemRect.right = itemRect.left + menuPtr->totalWidth
- - mePtr->x;
- } else {
- itemRect.right = itemRect.left + mePtr->width;
- }
- itemRect.bottom = itemRect.top
- + menuPtr->entries[i]->height;
- if (PtInRect(hitPt, &itemRect)) {
- if ((mePtr->type == SEPARATOR_ENTRY)
- || (mePtr->state == ENTRY_DISABLED)) {
- newItem = -1;
- } else {
- TkMenuEntry *cascadeEntryPtr;
- int parentDisabled = 0;
-
- for (cascadeEntryPtr
- = menuPtr->menuRefPtr->parentEntryPtr;
- cascadeEntryPtr != NULL;
- cascadeEntryPtr
- = cascadeEntryPtr->nextCascadePtr) {
- char *name;
-
- name = Tcl_GetStringFromObj(
- cascadeEntryPtr->namePtr, NULL);
- if (strcmp(name, Tk_PathName(menuPtr->tkwin))
- == 0) {
- if (cascadeEntryPtr->state == ENTRY_DISABLED) {
- parentDisabled = 1;
- }
- break;
- }
- }
- if (parentDisabled) {
- newItem = -1;
- } else {
- newItem = i;
- if ((mePtr->type == CASCADE_ENTRY)
- && (oldItem != newItem)) {
- globalsPtr->itemRect = itemRect;
- }
- }
- }
- break;
- }
- }
- }
-
- /*
- * Now we need to take care of scrolling the menu.
- */
-
- hasTopScroll = globalsPtr->menuTop < menuRectPtr->top;
- hasBottomScroll = globalsPtr->menuBottom > menuRectPtr->bottom;
- scrollDirection = DONT_SCROLL;
- if (hasTopScroll
- && (hitPt.v < menuRectPtr->top + SICN_HEIGHT)) {
- newItem = -1;
- scrollDirection = DOWN_SCROLL;
- } else if (hasBottomScroll
- && (hitPt.v > menuRectPtr->bottom - SICN_HEIGHT)) {
- newItem = -1;
- scrollDirection = UP_SCROLL;
- }
- menuClipRect = *menuRectPtr;
- if (hasTopScroll) {
- menuClipRect.top += SICN_HEIGHT;
- }
- if (hasBottomScroll) {
- menuClipRect.bottom -= SICN_HEIGHT;
- }
- if (MDEFScrollFlag) {
- scrollDirection = DONT_SCROLL;
- MDEFScrollFlag = 0;
- }
- GetClip(utilRgn);
- ClipRect(&menuClipRect);
-
- if (oldItem != newItem) {
- if (oldItem >= 0) {
- mePtr = menuPtr->entries[oldItem];
- if (mePtr->fontPtr == NULL) {
- tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
- menuPtr->fontPtr);
- } else {
- tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
- mePtr->fontPtr);
- }
- Tk_GetFontMetrics(tkfont, &fontMetrics);
- AppearanceEntryDrawWrapper(mePtr, menuRectPtr, globalsPtr,
- (Drawable) &macMDEFDrawable, &fontMetrics, tkfont,
- menuRectPtr->left + mePtr->x,
- globalsPtr->menuTop + mePtr->y,
- (mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
- menuPtr->totalWidth - mePtr->x : mePtr->width,
- mePtr->height);
- }
- if (newItem != -1) {
- int oldActiveItem = menuPtr->active;
-
- mePtr = menuPtr->entries[newItem];
- if (mePtr->state != ENTRY_DISABLED) {
- TkActivateMenuEntry(menuPtr, newItem);
- }
- if (mePtr->fontPtr == NULL) {
- tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
- menuPtr->fontPtr);
- } else {
- tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
- mePtr->fontPtr);
- }
- Tk_GetFontMetrics(tkfont, &fontMetrics);
- AppearanceEntryDrawWrapper(mePtr, menuRectPtr, globalsPtr,
- (Drawable) &macMDEFDrawable, &fontMetrics, tkfont,
- menuRectPtr->left + mePtr->x,
- globalsPtr->menuTop + mePtr->y,
- (mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
- menuPtr->totalWidth - mePtr->x : mePtr->width,
- mePtr->height);
- }
-
- tkUseMenuCascadeRgn = 1;
- MenuSelectEvent(menuPtr);
- Tcl_ServiceAll();
- tkUseMenuCascadeRgn = 0;
- if (mePtr->state != ENTRY_DISABLED) {
- TkActivateMenuEntry(menuPtr, -1);
- }
- *whichItem = newItem + 1;
- }
- globalsPtr->menuDisable = ((*menu)->menuID << 16) | (newItem + 1);
-
- if (scrollDirection == UP_SCROLL) {
- scrollAmt = menuClipRect.bottom - hitPt.v;
- if (scrollAmt < menuRectPtr->bottom
- - globalsPtr->menuBottom) {
- scrollAmt = menuRectPtr->bottom - globalsPtr->menuBottom;
- }
- if (!hasTopScroll && ((globalsPtr->menuTop + scrollAmt)
- < menuRectPtr->top)) {
- SetRect(&updateRect, menuRectPtr->left,
- globalsPtr->menuTop, menuRectPtr->right,
- globalsPtr->menuTop + SICN_HEIGHT);
- EraseRect(&updateRect);
- DrawSICN(SICN_RESOURCE_NUMBER, UP_ARROW,
- (Drawable) &macMDEFDrawable,
- menuPtr->textGC, menuRectPtr->left
- + menuPtr->entries[1]->indicatorSpace,
- menuRectPtr->top);
- menuClipRect.top += SICN_HEIGHT;
- }
- } else if (scrollDirection == DOWN_SCROLL) {
- scrollAmt = menuClipRect.top - hitPt.v;
- if (scrollAmt > menuRectPtr->top - globalsPtr->menuTop) {
- scrollAmt = menuRectPtr->top - globalsPtr->menuTop;
- }
- if (!hasBottomScroll && ((globalsPtr->menuBottom + scrollAmt)
- > menuRectPtr->bottom)) {
- SetRect(&updateRect, menuRectPtr->left,
- globalsPtr->menuBottom - SICN_HEIGHT,
- menuRectPtr->right, globalsPtr->menuBottom);
- EraseRect(&updateRect);
- DrawSICN(SICN_RESOURCE_NUMBER, DOWN_ARROW,
- (Drawable) &macMDEFDrawable,
- menuPtr->textGC, menuRectPtr->left
- + menuPtr->entries[1]->indicatorSpace,
- menuRectPtr->bottom - SICN_HEIGHT);
- menuClipRect.bottom -= SICN_HEIGHT;
- }
- }
- if (scrollDirection != DONT_SCROLL) {
- Tk_Font menuFont;
- RgnHandle updateRgn = NewRgn();
- ScrollRect(&menuClipRect, 0, scrollAmt, updateRgn);
- updateRect = (*updateRgn)->rgnBBox;
- DisposeRgn(updateRgn);
- globalsPtr->menuTop += scrollAmt;
- globalsPtr->menuBottom += scrollAmt;
- if (globalsPtr->menuTop == menuRectPtr->top) {
- updateRect.top -= SICN_HEIGHT;
- }
- if (globalsPtr->menuBottom == menuRectPtr->bottom) {
- updateRect.bottom += SICN_HEIGHT;
- }
- ClipRect(&updateRect);
- EraseRect(&updateRect);
- menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
- Tk_GetFontMetrics(menuFont, &fontMetrics);
- for (i = 0; i < menuPtr->numEntries; i++) {
- mePtr = menuPtr->entries[i];
- if (globalsPtr->menuTop + mePtr->y + mePtr->height
- < updateRect.top) {
- continue;
- } else if (globalsPtr->menuTop + mePtr->y
- > updateRect.bottom) {
- continue;
- }
- if (mePtr->fontPtr == NULL) {
- fmPtr = &fontMetrics;
- tkfont = menuFont;
- } else {
- tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
- mePtr->fontPtr);
- Tk_GetFontMetrics(tkfont, &entryMetrics);
- fmPtr = &entryMetrics;
- }
- AppearanceEntryDrawWrapper(mePtr, menuRectPtr, globalsPtr,
- (Drawable) &macMDEFDrawable, fmPtr, tkfont,
- menuRectPtr->left + mePtr->x,
- globalsPtr->menuTop + mePtr->y,
- (mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
- menuPtr->totalWidth - mePtr->x : mePtr->width,
- menuPtr->entries[i]->height);
- }
- }
-
- SetClip(utilRgn);
- SetEmptyRgn(utilRgn);
- RGBForeColor(&origForeColor);
- RGBBackColor(&origBackColor);
-
- /*
- * If the menu is a tearoff, and the mouse is outside the menu,
- * we need to draw the drag rectangle.
- *
- * In order for tearoffs to work properly, we need to set
- * the active member of the containing menubar.
- */
-
- menuRefPtr = TkFindMenuReferences(menuPtr->interp,
- Tk_PathName(menuPtr->tkwin));
- if ((menuRefPtr != NULL) && (menuRefPtr->parentEntryPtr != NULL)) {
- char *name;
- for (parentEntryPtr = menuRefPtr->parentEntryPtr;
- parentEntryPtr != NULL
- ; parentEntryPtr = parentEntryPtr->nextCascadePtr) {
- name = Tcl_GetStringFromObj(parentEntryPtr->namePtr,
- NULL);
- if (strcmp(name, Tk_PathName(menuPtr->tkwin)) != 0) {
- break;
- }
- }
- if (parentEntryPtr != NULL) {
- TkActivateMenuEntry(parentEntryPtr->menuPtr,
- parentEntryPtr->index);
- }
- }
-
- if (menuPtr->tearoff) {
- scratchRect = *menuRectPtr;
- if (tearoffStruct.menuPtr == NULL) {
- scratchRect.top -= 10;
- scratchRect.bottom += 10;
- scratchRect.left -= 10;
- scratchRect.right += 10;
- }
-
- windowPart = FindWindow(hitPt, &whichWindow);
- if ((windowPart != inMenuBar) && (newItem == -1)
- && (hitPt.v != 0) && (hitPt.h != 0)
- && (!PtInRect(hitPt, &scratchRect))
- && (!PtInRect(hitPt, &tearoffStruct.excludeRect))) {
-/*
- * This is the second argument to the Toolbox Delay function. It changed
- * from long to unsigned long between Universal Headers 2.0 & 3.0
- */
-#if !defined(UNIVERSAL_INTERFACES_VERSION) || (UNIVERSAL_INTERFACES_VERSION < 0x0300)
- long dummy;
-#else
- unsigned long dummy;
-#endif
- oldClipRgn = NewRgn();
- GetClip(oldClipRgn);
- GetForeColor(&origFgColor);
- GetPenState(&origPenState);
- GetForeColor(&fgColor);
- GetBackColor(&bgColor);
- GetGray(device, &bgColor, &fgColor);
- RGBForeColor(&fgColor);
- SetRect(&scratchRect, -32768, -32768, 32767, 32767);
- ClipRect(&scratchRect);
-
- dragRect = *menuRectPtr;
- tearoffStruct.menuPtr = menuPtr;
-
- PenMode(srcXor);
- dragRect = *menuRectPtr;
- OffsetRect(&dragRect, -dragRect.left, -dragRect.top);
- OffsetRect(&dragRect, tearoffStruct.point.h,
- tearoffStruct.point.v);
- if ((dragRect.top != 0) && (dragRect.left != 0)) {
- FrameRect(&dragRect);
- Delay(1, &dummy);
- FrameRect(&dragRect);
- }
- tearoffStruct.point = hitPt;
-
- SetClip(oldClipRgn);
- DisposeRgn(oldClipRgn);
- RGBForeColor(&origFgColor);
- SetPenState(&origPenState);
- } else {
- tearoffStruct.menuPtr = NULL;
- tearoffStruct.point.h = tearoffStruct.point.v = 0;
- }
- } else {
- tearoffStruct.menuPtr = NULL;
- tearoffStruct.point.h = tearoffStruct.point.v = 0;
- }
-
- break;
- }
-
- case mPopUpMsg:
-
- /*
- * 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;
- }
- GetWMgrPort(&windowMgrPort);
- maxMenuHeight = windowMgrPort->portRect.bottom
- - windowMgrPort->portRect.top
- - GetMBarHeight() - SCREEN_MARGIN;
- if (menuPtr->totalHeight > maxMenuHeight) {
- menuRectPtr->top = GetMBarHeight();
- } else {
- int delta;
- menuRectPtr->top = hitPt.h;
- if (oldItem >= 0) {
- menuRectPtr->top -= menuPtr->entries[oldItem]->y;
- }
-
- if (menuRectPtr->top < GetMBarHeight()) {
- /* Displace downward if the menu would stick off the
- * top of the screen.
- */
-
- menuRectPtr->top = GetMBarHeight() + 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 == GetMBarHeight()) {
- *whichItem = hitPt.h;
- } else {
- *whichItem = menuRectPtr->top;
- }
- globalsPtr->menuTop = *whichItem;
- globalsPtr->menuBottom = menuRectPtr->bottom;
- break;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * AppearanceEntryDrawWrapper --
- *
- * This routine wraps the TkpDrawMenuEntry function. Under Appearance,
- * it routes to the Appearance Managers DrawThemeEntry, otherwise it
- * just goes straight to TkpDrawMenuEntry.
- *
- * Results:
- * A menu entry is drawn
- *
- * Side effects:
- * None
- *
- *----------------------------------------------------------------------
- */
-static void
-AppearanceEntryDrawWrapper(
- TkMenuEntry *mePtr,
- Rect *menuRectPtr,
- TkMenuLowMemGlobals *globalsPtr,
- Drawable d,
- Tk_FontMetrics *fmPtr,
- Tk_Font tkfont,
- int x,
- int y,
- int width,
- int height)
-{
- if (TkMacHaveAppearance() > 1) {
- MenuEntryUserData meData;
- Rect itemRect;
- ThemeMenuState theState;
- ThemeMenuItemType theType;
-
- meData.mePtr = mePtr;
- meData.mdefDrawable = d;
- meData.fmPtr = fmPtr;
- meData.tkfont = tkfont;
-
- itemRect.top = y;
- itemRect.left = x;
- itemRect.bottom = itemRect.top + height;
- itemRect.right = itemRect.left + width;
-
- 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;
- }
-
- DrawThemeMenuItem (menuRectPtr, &itemRect,
- globalsPtr->menuTop, globalsPtr->menuBottom, theState,
- theType, tkThemeMenuItemDrawingUPP,
- (unsigned long) &meData);
-
- } else {
- TkpDrawMenuEntry(mePtr, d, tkfont, fmPtr,
- x, y, width, height, 0, 1);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tkThemeMenuItemDrawingProc --
- *
- * This routine is called from the Appearance DrawThemeMenuEntry
- *
- * Results:
- * A menu entry is drawn
- *
- * Side effects:
- * None
- *
- *----------------------------------------------------------------------
- */
-pascal void
-tkThemeMenuItemDrawingProc (
- 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,
- inBounds->bottom - inBounds->top, 0, 1);
-
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkMacHandleTearoffMenu() --
- *
- * 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
-TkMacHandleTearoffMenu(void)
-{
- if (tearoffStruct.menuPtr != NULL) {
- Tcl_DString tearoffCmdStr;
- char intString[TCL_INTEGER_SPACE];
- short windowPart;
- WindowRef whichWindow;
-
- windowPart = FindWindow(tearoffStruct.point, &whichWindow);
-
- if (windowPart != inMenuBar) {
- Tcl_DStringInit(&tearoffCmdStr);
- Tcl_DStringAppendElement(&tearoffCmdStr, "tk::TearOffMenu");
- Tcl_DStringAppendElement(&tearoffCmdStr,
- Tk_PathName(tearoffStruct.menuPtr->tkwin));
- sprintf(intString, "%d", tearoffStruct.point.h);
- Tcl_DStringAppendElement(&tearoffCmdStr, intString);
- sprintf(intString, "%d", tearoffStruct.point.v);
- Tcl_DStringAppendElement(&tearoffCmdStr, intString);
- Tcl_Eval(tearoffStruct.menuPtr->interp,
- Tcl_DStringValue(&tearoffCmdStr));
- Tcl_DStringFree(&tearoffCmdStr);
- tearoffStruct.menuPtr = NULL;
- }
- }
-}
-
-/*
- *--------------------------------------------------------------
- *
- * 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(interp, bindingTable)
- 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(menuPtr)
- TkMenu *menuPtr; /* Structure describing menu. */
-{
- TkpComputeStandardMenuGeometry(menuPtr);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * DrawTearoffEntry --
- *
- * This procedure draws the background part of a menu.
- *
- * 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) || (FixMDEF() != NULL)) {
- return;
- }
-
- margin = (fmPtr->ascent + fmPtr->descent)/2;
- points[0].x = x;
- points[0].y = y + height/2;
- points[1].y = points[0].y;
- segmentWidth = 6;
- maxX = width - 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;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkMacSetHelpMenuItemCount --
- *
- * 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.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Sets the global helpItemCount.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TkMacSetHelpMenuItemCount()
-{
- MenuHandle helpMenuHandle;
-
- if ((HMGetHelpMenuHandle(&helpMenuHandle) != noErr)
- || (helpMenuHandle == NULL)) {
- helpItemCount = -1;
- } else {
- helpItemCount = CountMItems(helpMenuHandle);
- DeleteMenuItem(helpMenuHandle, helpItemCount);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkMacMenuClick --
- *
- * Prepares a menubar for MenuSelect or MenuKey.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Any pending configurations of the menubar are completed.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TkMacMenuClick()
-{
- 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, (ClientData *) NULL);
- DrawMenuBarWhenIdle((ClientData *) 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 *cascadeEntryPtr;
- int parentDisabled = 0;
-
- for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
- cascadeEntryPtr != NULL;
- cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
- char *name = (cascadeEntryPtr->namePtr == NULL) ? ""
- : Tcl_GetStringFromObj(cascadeEntryPtr->namePtr, NULL);
-
- if (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) {
- if (cascadeEntryPtr->state == ENTRY_DISABLED) {
- parentDisabled = 1;
- }
- break;
- }
- }
-
- if (((parentDisabled || (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;
-
- 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 = windowWidth = maxWidth = lastColumnBreak = 0;
- maxModifierWidth = nonAccelMargin = 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->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;
- }
-
- 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;
-
- if (mePtr->type == CASCADE_ENTRY) {
- GetMenuAccelGeometry(menuPtr, mePtr, tkfont, fmPtr,
- &modifierWidth, &accelWidth, &height);
- nonAccelMargin = 0;
- } else if (mePtr->accelLength == 0) {
- nonAccelMargin = mePtr->hideMargin ? 0
- : Tk_TextWidth(tkfont, "m", 1);
- accelWidth = modifierWidth = 0;
- } else {
- labelWidth += Tk_TextWidth(tkfont, "m", 1);
- GetMenuAccelGeometry(menuPtr, mePtr, tkfont,
- fmPtr, &modifierWidth, &accelWidth, &height);
- if (height > mePtr->height) {
- mePtr->height = height;
- }
- nonAccelMargin = 0;
- }
-
- 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;
- 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;
- }
- }
- 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.
- *
- *----------------------------------------------------------------------
- */
-
-static 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 indicatorSpace = mePtr->indicatorSpace;
- int leftEdge = x + indicatorSpace;
- int imageHeight, imageWidth;
- int textHeight, textWidth;
- int haveImage = 0, haveText = 0;
- int imageXOffset = 0, imageYOffset = 0;
- int textXOffset = 0, textYOffset = 0;
-
- /*
- * 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) {
- Pixmap 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) {
- Tcl_DString itemTextDString;
- textHeight = fmPtr->linespace;
- GetEntryText(mePtr, &itemTextDString);
- textWidth = Tk_TextWidth(tkfont,
- Tcl_DStringValue(&itemTextDString),
- Tcl_DStringLength(&itemTextDString));
- Tcl_DStringFree(&itemTextDString);
- haveText = 1;
- }
- }
-
- /*
- * Now work out what the relative positions are.
- */
-
- if (haveImage && haveText) {
- 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: {
- textXOffset = imageWidth + 2;
- textYOffset = 0;
- imageXOffset = 0;
- imageYOffset = 0;
- break;
- }
- case COMPOUND_RIGHT: {
- textXOffset = 0;
- textYOffset = 0;
- imageXOffset = textWidth + 2;
- imageYOffset = 0;
- break;
- }
- case COMPOUND_CENTER: {
- textXOffset = (fullWidth - textWidth)/2;
- textYOffset = 0;
- imageXOffset = (fullWidth - imageWidth)/2;
- imageYOffset = 0;
- break;
- }
- case COMPOUND_NONE: {break;}
- }
- } else {
- textXOffset = 0;
- textYOffset = 0;
- imageXOffset = 0;
- imageYOffset = 0;
- }
-
- /*
- * Draw label and/or bitmap or image for entry.
- */
-
- if (mePtr->image != NULL) {
- Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);
- if ((mePtr->selectImage != NULL)
- && (mePtr->entryFlags & ENTRY_SELECTED)) {
- Tk_RedrawImage(mePtr->selectImage, 0, 0,
- imageWidth, imageHeight, d, leftEdge + imageXOffset,
- (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset));
- } else {
- Tk_RedrawImage(mePtr->image, 0, 0, imageWidth,
- imageHeight, d, leftEdge + imageXOffset,
- (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset));
- }
- } else if (mePtr->bitmapPtr != NULL) {
- Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
- XCopyPlane(menuPtr->display, bitmap, d, gc, 0, 0,
- (unsigned) imageWidth, (unsigned) imageHeight,
- leftEdge + imageXOffset,
- (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset), 1);
- }
- if ((mePtr->compound != COMPOUND_NONE) || !haveImage) {
- if (mePtr->labelLength > 0) {
- Tcl_DString itemTextDString, convertedTextDString;
- int baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
-
- GetEntryText(mePtr, &itemTextDString);
-
- /* Somehow DrawChars is changing the colors, it is odd, since
- it works for the Apple Platinum Appearance, but not for
- some Kaleidoscope Themes... Untill I can figure out what
- exactly is going on, this will have to do: */
-
- TkMacSetUpGraphicsPort(gc);
- MoveTo((short) leftEdge + textXOffset,
- (short) baseline + textYOffset);
- Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&itemTextDString),
- Tcl_DStringLength(&itemTextDString), &convertedTextDString);
- DrawText(Tcl_DStringValue(&convertedTextDString), 0,
- Tcl_DStringLength(&convertedTextDString));
-
- /* Tk_DrawChars(menuPtr->display, d, gc,
- tkfont, Tcl_DStringValue(&itemTextDString),
- Tcl_DStringLength(&itemTextDString),
- leftEdge, baseline); */
-
- Tcl_DStringFree(&itemTextDString);
- }
- }
-
- if (mePtr->state == ENTRY_DISABLED) {
- if (menuPtr->disabledFgPtr == NULL) {
- if (!TkMacHaveAppearance()) {
- XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
- (unsigned) width, (unsigned) height);
- }
- } else if ((mePtr->image != NULL)
- && (menuPtr->disabledImageGC != None)) {
- XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
- leftEdge + imageXOffset,
- (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset),
- (unsigned) imageWidth, (unsigned) 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.
- *
- *----------------------------------------------------------------------
- */
-
-static 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 (!TkMacHaveAppearance()
- || (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.
- *
- *----------------------------------------------------------------------
- */
-
-static 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, haveText = 0;
-
- if (mePtr->image != NULL) {
- Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr);
- haveImage = 1;
- } else if (mePtr->bitmapPtr != NULL) {
- Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
- Tk_SizeOfBitmap(menuPtr->display, bitmap, widthPtr, heightPtr);
- haveImage = 1;
- } else {
- *heightPtr = 0;
- *widthPtr = 0;
- }
-
- if (haveImage && (mePtr->compound == COMPOUND_NONE)) {
- /* We don't care about the text in this case */
- } else {
- /* Either it is compound or we don't have an image */
- if (mePtr->labelPtr != NULL) {
- Tcl_DString itemTextDString;
- int textWidth;
- GetEntryText(mePtr, &itemTextDString);
- textWidth = Tk_TextWidth(tkfont,
- Tcl_DStringValue(&itemTextDString),
- Tcl_DStringLength(&itemTextDString));
- Tcl_DStringFree(&itemTextDString);
-
- if ((mePtr->compound != COMPOUND_NONE) && haveImage) {
- switch ((enum compound) mePtr->compound) {
- case COMPOUND_TOP:
- case COMPOUND_BOTTOM: {
- if (textWidth > *widthPtr) {
- *widthPtr = textWidth;
- }
- /* Add text and padding */
- *heightPtr += fmPtr->linespace + 2;
- break;
- }
- case COMPOUND_LEFT:
- case COMPOUND_RIGHT: {
- if (fmPtr->linespace > *heightPtr) {
- *heightPtr = fmPtr->linespace;
- }
- /* Add text and padding */
- *widthPtr += textWidth + 2;
- break;
- }
- case COMPOUND_CENTER: {
- if (fmPtr->linespace > *heightPtr) {
- *heightPtr = fmPtr->linespace;
- }
- if (textWidth > *widthPtr) {
- *widthPtr = textWidth;
- }
- break;
- }
- case COMPOUND_NONE: {break;}
- }
- } else {
- /* We don't have an image or we're not compound */
- *heightPtr = fmPtr->linespace;
- *widthPtr = textWidth;
- }
- } else {
- /* An empty entry still has this height */
- *heightPtr = fmPtr->linespace;
- }
- }
- *heightPtr += 1;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * 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.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-MenuSelectEvent(
- TkMenu *menuPtr) /* the menu we have selected. */
-{
- XVirtualEvent event;
- Point where;
-
- 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();
-
- GetMouse(&where);
- event.x_root = where.h;
- event.y_root = where.v;
- event.state = TkMacButtonKeyState();
- event.same_screen = true;
- event.name = Tk_GetUid("MenuSelect");
- Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * 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);
- MenuSelectEvent(menuPtr);
- 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);
- }
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * InvalidateMDEFRgns --
- *
- * Invalidates the regions covered by menus that did redrawing and
- * might be damaged.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Generates Mac update events for affected windows.
- *
- *----------------------------------------------------------------------
- */
-
-void
-InvalidateMDEFRgns(void)
-{
- GDHandle saveDevice;
- GWorldPtr saveWorld, destPort;
- Point scratch;
- MacDrawable *macDraw;
- TkMacWindowList *listPtr;
-
- if (totalMenuRgn == NULL) {
- return;
- }
-
- GetGWorld(&saveWorld, &saveDevice);
- for (listPtr = tkMacWindowListPtr ; listPtr != NULL;
- listPtr = listPtr->nextPtr) {
- macDraw = (MacDrawable *) Tk_WindowId(listPtr->winPtr);
- if (macDraw->flags & TK_DRAWN_UNDER_MENU) {
- destPort = TkMacGetDrawablePort(Tk_WindowId(listPtr->winPtr));
- SetGWorld(destPort, NULL);
- scratch.h = scratch.v = 0;
- GlobalToLocal(&scratch);
- OffsetRgn(totalMenuRgn, scratch.v, scratch.h);
- InvalRgn(totalMenuRgn);
- OffsetRgn(totalMenuRgn, -scratch.v, -scratch.h);
- macDraw->flags &= ~TK_DRAWN_UNDER_MENU;
- }
- }
-
- SetGWorld(saveWorld, saveDevice);
- SetEmptyRgn(totalMenuRgn);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkMacClearMenubarActive --
- *
- * Recursively clears the active entry in the current menubar hierarchy.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Generates <<MenuSelect>> virtual events.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TkMacClearMenubarActive(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);
- }
- }
- }
- }
- InvalidateMDEFRgns();
- FixMDEF();
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * 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. */
- char *menuName) /* The name of the menu to
- * reconfigure. */
-{
- /*
- * Nothing to do.
- */
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FixMDEF --
- *
- * Loads the MDEF and blasts our routine descriptor into it.
- * We have to set up the MDEF. This is pretty slimy. The real MDEF
- * resource is 68K code. All this code does is call another procedure.
- * When the application in launched, a dummy value for the procedure
- * is compiled into the MDEF. We are going to replace that dummy
- * value with a routine descriptor. When the routine descriptor
- * is invoked, the globals and everything will be setup, and we
- * can do what we need. This will not work from 68K or CFM 68k
- * currently, so we will conditional compile this until we
- * figure it out.
- *
- * Results:
- * Returns the MDEF handle.
- *
- * Side effects:
- * The MDEF is read in and massaged.
- *
- *----------------------------------------------------------------------
- */
-
-#if __MWERKS__ != 0x2400
-#define MDEF_PROC_OFFSET 0x24
-#else
-#define MDEF_PROC_OFFSET 0x20
-#endif
-
-static Handle
-FixMDEF(void)
-{
-#if GENERATINGCFM
- Handle MDEFHandle = GetResource('MDEF', 591);
- Handle SICNHandle = GetResource('SICN', SICN_RESOURCE_NUMBER);
- if ((MDEFHandle != NULL) && (SICNHandle != NULL)) {
- HLock(MDEFHandle);
- HLock(SICNHandle);
- if (menuDefProc == NULL) {
- menuDefProc = TkNewMenuDefProc(MenuDefProc);
- }
- memmove((void *) (((long) (*MDEFHandle)) + MDEF_PROC_OFFSET), &menuDefProc, 4);
- return MDEFHandle;
- } else {
- return NULL;
- }
-#else
- return NULL;
-#endif
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkpMenuInit --
- *
- * Initializes Mac-specific menu data.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Allocates a hash table.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TkpMenuInit(void)
-{
- lastMenuID = 256;
- Tcl_InitHashTable(&commandTable, TCL_ONE_WORD_KEYS);
- currentMenuBarOwner = NULL;
- tearoffStruct.menuPtr = NULL;
- currentAppleMenuID = 0;
- currentHelpMenuID = 0;
- currentMenuBarInterp = NULL;
- currentMenuBarName = NULL;
- windowListPtr = NULL;
-
- /*
- * Get the GC that we will use as the sign to the font
- * routines that they should not muck with the foreground color...
- */
-
- if (TkMacHaveAppearance() > 1) {
- XGCValues tmpValues;
- TkColor *tmpColorPtr;
-
- tmpColorPtr = TkpGetColor(NULL, "systemAppearanceColor");
- tmpValues.foreground = tmpColorPtr->color.pixel;
- tmpValues.background = tmpColorPtr->color.pixel;
- ckfree((char *) tmpColorPtr);
-
- tkThemeMenuItemDrawingUPP = NewMenuItemDrawingProc(tkThemeMenuItemDrawingProc);
- }
- FixMDEF();
-
- Tcl_ExternalToUtf(NULL, NULL, "\311", /* Š */
- -1, 0, NULL, elipsisString,
- TCL_UTF_MAX + 1, NULL, NULL, NULL);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkpMenuThreadInit --
- *
- * Does platform-specific initialization of thread-specific
- * menu state.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TkpMenuThreadInit()
-{
- /*
- * 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
-TkMacPreprocessMenu()
-{
- TkMenuReferences *mbRefPtr;
- int code;
-
- if ((currentMenuBarName != NULL) && (currentMenuBarInterp != NULL)) {
- mbRefPtr = TkFindMenuReferences(currentMenuBarInterp,
- currentMenuBarName);
- if ((mbRefPtr != NULL) && (mbRefPtr->menuPtr != NULL)) {
- Tcl_Preserve((ClientData)currentMenuBarInterp);
- code = TkPreprocessMenu(mbRefPtr->menuPtr->masterMenuPtr);
- if ((code != TCL_OK) && (code != TCL_CONTINUE)
- && (code != TCL_BREAK)) {
- Tcl_AddErrorInfo(currentMenuBarInterp,
- "\n (menu preprocess)");
- Tcl_BackgroundError(currentMenuBarInterp);
- }
- Tcl_Release((ClientData)currentMenuBarInterp);
- }
- }
-}