head	1.22;
access;
symbols
	core-8-4-19:1.21
	core-8-4-18:1.21
	core-8-4-17:1.21
	core-8-4-16:1.21
	core-8-4-15:1.21
	core-8-4-14:1.21
	core-8-4-13:1.21
	core-8-4-12:1.21
	core-8-4-11:1.21
	core-8-4-10:1.21
	core-8-4-9-branch:1.21.0.6
	core-8-4-9:1.21
	core-8-4-8:1.21
	core-8-4-7:1.21
	core-8-5-a1:1.21
	core-8-4-6:1.21
	core-8-4-5:1.21
	mistachkin-dev-branch:1.21.0.4
	core-8-4-4:1.21
	core-8-4-3:1.21
	core-8-4-branch:1.21.0.2
	core-8-4-2:1.21
	core-8-4-1:1.21
	core-8-3-5:1.18.2.2
	core-8-4-0:1.21
	macosx-8-4-merge-2002-08-31-trunk:1.21
	macosx-8-4-premerge-2002-08-31-branch:1.20.2.3
	macosx-8-4-premerge-2002-08-31-trunk:1.21
	macosx-8-4-merge-2002-08-30-branch:1.20.2.3
	macosx-8-4-merge-2002-08-30-trunk:1.21
	macosx-8-4-merge-2002-08-20-branch:1.20.2.3
	macosx-8-4-merge-2002-08-20-trunk:1.21
	core-8-4-b2:1.21
	core-8-4-b1:1.21
	macosx-premerge-6-9-02:1.20.2.2
	core-8-4-a4:1.21
	core-8-3-4:1.18.2.2
	macosx-8-4-branch:1.20.0.2
	macosx-8-4-branchpoint:1.20
	core-8-4-a3:1.19
	core-8-3-3:1.18.2.1
	dgp-privates-into-namespace:1.18.0.6
	tclpro-1-5-0:1.18
	core-8-4-win-speedup:1.18.0.4
	core-8-4-a2:1.18
	tclpro-1-4-1:1.18
	tclpro-1-4-0:1.18
	core-8-3-2:1.18
	ajuba-ajuba2-2-1-base:1.18
	ajuba-ajuba2-2-0:1.18
	core-8-4-a1:1.18
	core-8-3-1-branch:1.18.0.2
	core-8-3-1:1.18
	scriptics-sc-2-0-b5:1.18
	scriptics-sc-2-0-fixed:1.18
	scriptics-sc-2-0-b2:1.18
	scriptics-sc-2-0-b1:1.18
	core-8-3-0:1.18
	core-8-3-b2:1.17
	core-8-3-b1:1.17
	scriptics-sc-1-1:1.13
	scriptics-sc-1-1-b1:1.13
	core-8-2-3:1.13
	scriptics-sc-1-1-branch:1.13.0.6
	scriptics-sc-1-1-base:1.13
	scriptics-sc-1-0:1.13
	scriptics-sc-1-0-branch:1.13.0.4
	scriptics-sc-1-0-base:1.13
	core-8-2-2:1.13
	core-8-2-1:1.13
	scriptics-bc-1-0-b1:1.13
	core-8-2-1-branch:1.13.0.2
	scriptics-tclpro-1-3-0:1.13
	core-8-2-0:1.13
	core-8-2-b3-branch:1.12.0.2
	core-8-2-b3-base:1.12
	scriptics-tclpro-1-3-b4:1.10
	core-8-2-b2:1.10
	scriptics-tclpro-1-3-b3:1.10
	core-8-2-b1:1.10
	scriptics-tclpro-1-3-b2:1.8
	merge-to-mainline-5/21/99:1.8
	scriptics-tclpro-1-3-b2-branch:1.8.0.2
	core-8-1-1:1.8
	scriptics-tclpro-1-3-b1:1.8
	core-8-1-1-base:1.8
	core-8-1-0:1.8
	merge-to-mainline-4-29-99:1.8
	merge-to-mainline-4-23-99:1.8
	core-8-1-branch-old:1.1.0.4
	core-8-0-6-branch:1.7.0.2
	core-8-0-6-base:1.7
	core-8-0-5:1.6.2.1
	core-8-1-b3:1.1.4.7
	core-8-1-b2:1.1.4.7
	dev-8-1-stubs-branch:1.1.4.6.0.2
	dev-stubs-branch:1.6.0.4
	scriptics-tclpro-1-2:1.6
	scriptics-tclpro-1-2-b2:1.6
	core-8-1-merge-2/10/99:1.6
	core-8-0-5-branch:1.6.0.2
	core-8-0-5-base:1.6
	scriptics-tclpro-1-2-b1:1.6
	scriptics-tclpro-1-2-a1:1.6
	core-8-1-b1:1.1.4.4
	core-8-0-4:1.6
	core-8-1-a2:1.1.4.1
	core-8-0-2:1.1
	core-8-0-3:1.5;
locks; strict;
comment	@ * @;


1.22
date	2004.03.17.18.15.46;	author das;	state dead;
branches;
next	1.21;

1.21
date	2001.11.23.02.06.07;	author das;	state Exp;
branches;
next	1.20;

1.20
date	2001.10.12.13.30.31;	author tmh;	state Exp;
branches
	1.20.2.1;
next	1.19;

1.19
date	2001.08.01.16.21.11;	author dgp;	state Exp;
branches;
next	1.18;

1.18
date	2000.02.10.08.55.47;	author jingham;	state Exp;
branches
	1.18.2.1
	1.18.4.1
	1.18.6.1;
next	1.17;

1.17
date	99.12.16.21.58.02;	author hobbs;	state Exp;
branches;
next	1.16;

1.16
date	99.12.07.03.51.10;	author hobbs;	state Exp;
branches;
next	1.15;

1.15
date	99.12.07.03.09.58;	author hobbs;	state Exp;
branches;
next	1.14;

1.14
date	99.12.07.03.04.51;	author hobbs;	state Exp;
branches;
next	1.13;

1.13
date	99.08.13.08.07.02;	author jingham;	state Exp;
branches;
next	1.12;

1.12
date	99.08.07.18.54.37;	author jingham;	state Exp;
branches;
next	1.11;

1.11
date	99.08.05.06.19.52;	author jingham;	state Exp;
branches;
next	1.10;

1.10
date	99.06.16.05.36.46;	author jingham;	state Exp;
branches;
next	1.9;

1.9
date	99.05.22.06.33.19;	author jingham;	state Exp;
branches;
next	1.8;

1.8
date	99.04.16.01.51.31;	author stanton;	state Exp;
branches;
next	1.7;

1.7
date	99.04.16.01.25.54;	author stanton;	state Exp;
branches;
next	1.6;

1.6
date	98.11.11.17.30.44;	author jingham;	state Exp;
branches
	1.6.2.1;
next	1.5;

1.5
date	98.09.14.18.23.37;	author stanton;	state Exp;
branches;
next	1.4;

1.4
date	98.08.13.13.36.35;	author welch;	state Exp;
branches;
next	1.3;

1.3
date	98.08.12.11.14.35;	author welch;	state Exp;
branches;
next	1.2;

1.2
date	98.06.27.18.07.11;	author welch;	state Exp;
branches;
next	1.1;

1.1
date	98.04.01.09.57.02;	author rjohnson;	state Exp;
branches
	1.1.4.1;
next	;

1.1.4.1
date	98.09.29.00.25.40;	author stanton;	state Exp;
branches;
next	1.1.4.2;

1.1.4.2
date	98.09.30.02.18.11;	author stanton;	state Exp;
branches;
next	1.1.4.3;

1.1.4.3
date	98.11.24.21.42.44;	author stanton;	state Exp;
branches;
next	1.1.4.4;

1.1.4.4
date	98.11.25.21.16.36;	author stanton;	state Exp;
branches;
next	1.1.4.5;

1.1.4.5
date	99.01.07.02.42.54;	author lfb;	state Exp;
branches;
next	1.1.4.6;

1.1.4.6
date	99.02.16.11.39.34;	author lfb;	state Exp;
branches;
next	1.1.4.7;

1.1.4.7
date	99.03.10.18.28.13;	author redman;	state Exp;
branches;
next	;

1.6.2.1
date	99.03.22.06.44.10;	author jingham;	state Exp;
branches;
next	;

1.18.2.1
date	2001.04.04.21.39.49;	author hobbs;	state Exp;
branches;
next	1.18.2.2;

1.18.2.2
date	2001.10.17.19.29.51;	author das;	state Exp;
branches;
next	;

1.18.4.1
date	2002.04.02.20.57.54;	author hobbs;	state Exp;
branches;
next	;

1.18.6.1
date	2001.02.28.23.29.56;	author dgp;	state Exp;
branches;
next	;

1.20.2.1
date	2002.02.05.02.25.17;	author wolfsuit;	state Exp;
branches;
next	1.20.2.2;

1.20.2.2
date	2002.02.06.07.02.04;	author wolfsuit;	state Exp;
branches;
next	1.20.2.3;

1.20.2.3
date	2002.06.10.05.38.24;	author wolfsuit;	state Exp;
branches;
next	;


desc
@@


1.22
log
@Removed support for Mac OS Classic platform [Patch 918139]
@
text
@/* 
 * 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);
        }
    }
}
@


1.21
log
@	**  upport to 8.4 of mac code changes for 8.3.3 & various new
	**  changes for 8.4, some already backported to 8.3.4 (patch #435660)

	see ChangeLog for details
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.20 2001/10/12 13:30:31 tmh Exp $
@


1.20
log
@implementation of TIP 63 (accepted) -compound option to menu items.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.19 2001/08/01 16:21:11 dgp Exp $
d181 1
a181 1
				/* The UTF representation of the elipsis (ƒ) 
d532 1
a532 1
#ifdef GENERATINGCFM
d690 1
a690 1
 *	between "..." and "ƒ".
d755 1
a755 1
 * 	'¥' - Mac Bullet character		(\245)
d758 1
a758 1
 * 	'Ñ' = Mac Long dash ("em dash")	(\321)
d1226 1
a1226 1
    	AddResMenu(macMenuHdl, 'DRVR');
d4465 6
d4474 1
a4474 1
#ifdef GENERATINGCFM
d4483 1
a4483 1
    	memmove((void *) (((long) (*MDEFHandle)) + 0x24), &menuDefProc, 4);
d4540 1
a4540 1
    Tcl_ExternalToUtf(NULL, NULL, "\311", /* É */
@


1.20.2.1
log
@Merge with current TOT
Added support for the wm stackorder command
Fixed crash when selecting Menu items in the Application menu that we didn't
put there.
Added first bits of the use of CG for low-level drawing.  The line-drawing works,
the rest doesn't yet.  You have to set the file static useCGDrawing to 1 and
rebuild to activate this code.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.20 2001/10/12 13:30:31 tmh Exp $
d181 1
a181 1
				/* The UTF representation of the elipsis (Š) 
d532 1
a532 1
#if GENERATINGCFM
d690 1
a690 1
 *	between "..." and "Š".
d755 1
a755 1
 * 	'€' - Mac Bullet character		(\245)
d758 1
a758 1
 * 	'‹' = Mac Long dash ("em dash")	(\321)
d1226 1
a1226 1
    	AppendResMenu(macMenuHdl, 'DRVR');
a4464 6
#if __MWERKS__ != 0x2400
#define MDEF_PROC_OFFSET 0x24
#else
#define MDEF_PROC_OFFSET 0x20
#endif

d4468 1
a4468 1
#if GENERATINGCFM
d4477 1
a4477 1
    	memmove((void *) (((long) (*MDEFHandle)) + MDEF_PROC_OFFSET), &menuDefProc, 4);
d4534 1
a4534 1
    Tcl_ExternalToUtf(NULL, NULL, "\311", /* Š */
@


1.20.2.2
log
@Fix bug #513222.  We were acting on the menu after the post event without
checking to see whether the menu event had deleted the menu.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id$
d1408 2
a1410 10
        /*
         * Be careful, here.  The command executed in handling the menu event
         * could destroy the window.  Don't try to do anything with it then.
         */
        
        if (menuPtr->tkwin) {
	    InvalidateMDEFRgns();
	    RecursivelyClearActiveMenu(menuPtr);
	}

@


1.20.2.3
log
@Merging with TOT as of 06/09/2002.
@
text
@a1407 2
	InvalidateMDEFRgns();
	RecursivelyClearActiveMenu(menuPtr);
d1409 10
@


1.19
log
@	Merged changes from feature branch dgp-privates-into-namespace,
	implementing TIP 44.  All Tk commands and variables matching
	tk[A-Z]* are now in the ::tk namespace.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.18 2000/02/10 08:55:47 jingham Exp $
d15 1
a16 1
#include "tkMenu.h"
d710 1
a710 1
    } else if (mePtr->imagePtr != NULL) {
d712 1
a712 1
    } else if (mePtr->bitmapPtr != NULL) {
a3947 1
    int baseline;
d3951 4
d3957 77
a4033 1
     * Draw label or bitmap or image for entry.
a4035 1
    baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
d4041 2
a4042 2
		    imageWidth, imageHeight, d, leftEdge,
	            (int) (y + (mePtr->height - imageHeight)/2));
d4045 2
a4046 2
		    imageHeight, d, leftEdge,
		    (int) (y + (mePtr->height - imageHeight)/2));
a4048 1
    	int width, height;
a4049 2
        Tk_SizeOfBitmap(menuPtr->display,
	        bitmap, &width, &height);
d4051 5
a4055 3
    		(unsigned) width, (unsigned) height, leftEdge,
	    	(int) (y + (mePtr->height - height)/2), 1);
    } else {
d4058 1
d4068 2
a4069 1
	    MoveTo((short) leftEdge, (short) baseline);
d4093 2
a4094 2
		    leftEdge,
		    (int) (y + (mePtr->height - imageHeight)/2),
d4172 1
d4176 1
d4180 1
d4182 3
a4184 1
    	*heightPtr = fmPtr->linespace;
d4186 4
d4192 1
a4192 1
    	    
d4194 1
a4194 1
    	    *widthPtr = Tk_TextWidth(tkfont, 
d4198 32
d4231 7
a4237 1
    	    *widthPtr = 0;
@


1.18
log
@Add support for Appearance Manager 1.2 Floating windows, and the new window classes in unsupported1
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.17 1999/12/16 21:58:02 hobbs Exp $
d3343 1
a3343 1
    	    Tcl_DStringAppendElement(&tearoffCmdStr, "tkTearOffMenu");
@


1.18.4.1
log
@sync with head
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.21 2001/11/23 02:06:07 das Exp $
d15 1
a16 1
#include "tkMenuButton.h"
d181 1
a181 1
				/* The UTF representation of the elipsis (Š) 
d532 1
a532 1
#if GENERATINGCFM
d690 1
a690 1
 *	between "..." and "Š".
d710 1
a710 1
    } else if ((mePtr->imagePtr != NULL) && (mePtr->compound == COMPOUND_NONE)) {
d712 1
a712 1
    } else if ((mePtr->bitmapPtr != NULL) && (mePtr->compound == COMPOUND_NONE)) {
d755 1
a755 1
 * 	'€' - Mac Bullet character		(\245)
d758 1
a758 1
 * 	'‹' = Mac Long dash ("em dash")	(\321)
d1226 1
a1226 1
    	AppendResMenu(macMenuHdl, 'DRVR');
d3343 1
a3343 1
    	    Tcl_DStringAppendElement(&tearoffCmdStr, "tk::TearOffMenu");
d3948 1
a3951 80
    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;
    }
d3954 1
a3954 1
     * Draw label and/or bitmap or image for entry.
d3957 1
d3963 2
a3964 2
		    imageWidth, imageHeight, d, leftEdge + imageXOffset,
		    (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset));
d3967 2
a3968 2
		    imageHeight, d, leftEdge + imageXOffset,
		    (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset));
d3971 1
d3973 2
d3976 3
a3978 5
		(unsigned) imageWidth, (unsigned) imageHeight, 
		leftEdge + imageXOffset,
		(int) (y + (mePtr->height - imageHeight)/2 + imageYOffset), 1);
    }
    if ((mePtr->compound != COMPOUND_NONE) || !haveImage) {
a3980 1
	    int baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
d3990 1
a3990 2
	    MoveTo((short) leftEdge + textXOffset, 
		   (short) baseline + textYOffset);
d4014 2
a4015 2
		    leftEdge + imageXOffset,
		    (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset),
a4092 1
    int haveImage = 0, haveText = 0;
a4095 1
	haveImage = 1;
a4098 1
	haveImage = 1;
d4100 1
a4100 3
	*heightPtr = 0;
	*widthPtr = 0;
    }
a4101 4
    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 */
d4104 1
a4104 1
	    int textWidth;
d4106 1
a4106 1
	    textWidth = Tk_TextWidth(tkfont, 
a4109 32
	
	    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;}
		}
d4111 1
a4111 7
		/* 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;
a4338 6
#if __MWERKS__ != 0x2400
#define MDEF_PROC_OFFSET 0x24
#else
#define MDEF_PROC_OFFSET 0x20
#endif

d4342 1
a4342 1
#if GENERATINGCFM
d4351 1
a4351 1
    	memmove((void *) (((long) (*MDEFHandle)) + MDEF_PROC_OFFSET), &menuDefProc, 4);
d4408 1
a4408 1
    Tcl_ExternalToUtf(NULL, NULL, "\311", /* Š */
@


1.18.2.1
log
@	* generic/tkInt.decls: removed superfluous declarations.
	* generic/tkIntDecls.h:
	* generic/tkIntPlatDecls.h:
	* generic/tkMain.c: include unistd.h for mac.
	* generic/tkPointer.c: include tkMacInt.h for mac.
	* generic/tkStubInit.c:
	* generic/tkStubLib.c:
	* mac/MW_TkHeader.pch:
	* mac/MW_TkOldImgHeader.h:
	* mac/MW_TkTestHeader.pch:
	* mac/tclets.r:
	* mac/tkMac.h:
	* mac/tkMacAppearanceStubs.c:
	* mac/tkMacApplication.r:
	* mac/tkMacButton.c:
	* mac/tkMacDialog.c: support for -filetypes
	* mac/tkMacFont.c:
	* mac/tkMacInt.h:
	* mac/tkMacLibrary.r:
	* mac/tkMacMDEF.r:
	* mac/tkMacMenu.c:
	* mac/tkMacMenus.c:
	* mac/tkMacPort.h:
	* mac/tkMacResource.r:
	* mac/tkMacScrlbr.c: improved scrollbar code
	* mac/tkMacWindowMgr.c: added control of floating windows
	* mac/tkMacWm.c: improved use of precompiled headers, better
	support for Appearance Manager, change copyrights, resource files,
	use DLLIMPORT/DLLEXPORT, comment corrections.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.18 2000/02/10 08:55:47 jingham Exp $
d181 1
a181 1
				/* The UTF representation of the elipsis (Š) 
d532 1
a532 1
#if GENERATINGCFM
d690 1
a690 1
 *	between "..." and "Š".
d755 1
a755 1
 * 	'€' - Mac Bullet character		(\245)
d758 1
a758 1
 * 	'‹' = Mac Long dash ("em dash")	(\321)
d1226 1
a1226 1
    	AppendResMenu(macMenuHdl, 'DRVR');
a4338 6
#if __MWERKS__ < 0x2400
#define MDEF_PROC_OFFSET 0x24
#else
#define MDEF_PROC_OFFSET 0x20
#endif

d4342 1
a4342 1
#if GENERATINGCFM
d4351 1
a4351 1
    	memmove((void *) (((long) (*MDEFHandle)) + MDEF_PROC_OFFSET), &menuDefProc, 4);
d4408 1
a4408 1
    Tcl_ExternalToUtf(NULL, NULL, "\311", /* Š */
@


1.18.2.2
log
@Backport of some mac specific changes added to 8.4 since 8.3.3
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.18.2.1 2001/04/04 21:39:49 hobbs Exp $
d4339 1
a4339 1
#if __MWERKS__ != 0x2400
@


1.18.6.1
log
@2001-02-28  Don Porter  <dgp@@users.sourceforge.net>

        BRANCH dgp-privates-into-namespace:  Feature branch to move all
        of Tk's private commands and variable into the ::tk namespace
        and its children.

        * doc/tkvars.n:  Documented private variable tkPriv renamed tk::Priv.

        * generic/tkBind.c:
        * generic/tkMenu.c:
        * generic/tkTextDisp.c:
        * library/bgerror.tcl:
        * library/button.tcl:
        * library/choosedir.tcl:
        * library/clrpick.tcl:
        * library/comdlg.tcl:
        * library/console.tcl:
        * library/dialog.tcl:
        * library/entry.tcl:
        * library/focus.tcl:
        * library/listbox.tcl:
        * library/menu.tcl:
        * library/msgbox.tcl:
        * library/optMenu.tcl:
        * library/palette.tcl:
        * library/scale.tcl:
        * library/scrlbar.tcl:
        * library/spinbox.tcl:
        * library/tclIndex:
        * library/tearoff.tcl:
        * library/text.tcl:
        * library/tk.tcl:
        * library/tkfbox.tcl:
        * library/xmfbox.tcl:
        * mac/tkMacMenu.c:
        * tests/clrpick.test:
        * tests/filebox.test:
        * tests/macMenu.test:
        * tests/menu.test:
        * tests/menuDraw.test:
        * tests/msgbox.test:
        * tests/text.test:
        * tests/textDisp.test:
        * tests/unixMenu.test:
        * tests/winMenu.test:
        * tests/xmfbox.test:
        * unix/tkUnixDialog.c:  All Tk commands matching ::tk[A-Z]* and
        all Tk private variables in the global namespace were renamed to
        live in the namespace ::tk or one of its children.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.18 2000/02/10 08:55:47 jingham Exp $
d3343 1
a3343 1
    	    Tcl_DStringAppendElement(&tearoffCmdStr, "tk::TearOffMenu");
@


1.17
log
@	* mac/tkMacMenu.c: finished bug 3075 by changing the char values of
	what was checked (verified correctness on Mac).
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.16 1999/12/07 03:51:10 hobbs Exp $
d1884 1
d1886 7
a1892 1
    if ((macWindowPtr == NULL) || (macWindowPtr != FrontWindow())) {
@


1.16
log
@added TkMacPreprocessMenu
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.15 1999/12/07 03:09:58 hobbs Exp $
d754 5
a758 5
 * 	'' - Check mark character	(\022)
 * 	'´' - Bullet character	(\264 or \245 ??)
 * 	'' - Filled diamond		(\023)
 * 	'×' - Hollow diamond		(\327)
 * 	'„' = Long dash ("em dash")	(\204 or \321 ??)
d784 2
a785 2
    } else if (!TkMacIsCharacterMissing(tkfont, '\264')) {
    	markChar = '´';	/* Bullet */
d790 2
a791 2
    } else if (!TkMacIsCharacterMissing(tkfont, '\204')) {
    	markChar = '\204';	/* Lond Dash */
@


1.15
log
@added TkpPreprocessMenu (commited before saving one last file...)
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.14 1999/12/07 03:04:51 hobbs Exp $
d4207 2
a4208 1
InvalidateMDEFRgns(void) {
d4256 2
a4257 1
TkMacClearMenubarActive(void) {
d4448 1
a4448 1
TkpPreprocessMacMenu()
d4450 2
a4451 1
    TkMenuReferences *menuBarRefPtr;
d4453 2
a4454 2
    if ( currentMenuBarName != NULL ) {
        menuBarRefPtr = TkFindMenuReferences(currentMenuBarInterp,
d4456 10
a4465 2
        if ( (menuBarRefPtr != NULL) && (menuBarRefPtr->menuPtr != NULL) ) {
	    TkPreprocessMenu(menuBarRefPtr->menuPtr->masterMenuPtr);
@


1.14
log
@	* mac/tkMacFont.c:
	* mac/tkMacMenu.c:
	* mac/tkMacWindowMgr.c: fixed greyed out menu items, handling of
	... elipsis, font mapping problem, and enabled generated menu
	posting [Bug: 3705]
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.13 1999/08/13 08:07:02 jingham Exp $
d4427 30
@


1.13
log
@Fix a bug where the background of the menu can be wrong on Appearances that use pixmaps for the background of the menu.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.12 1999/08/07 18:54:37 jingham Exp $
a714 1
    
d718 1
a718 1
	 
d725 2
a726 2
    	
	for (i = 0; i < length; text++, i++) {
d732 1
d754 5
a758 5
 * 	'' - Check mark character
 * 	'´' - Bullet character
 * 	'' - Filled diamond
 * 	'×' - Hollow diamond
 * 	'„' = Long dash ("em dash")
d782 10
a791 10
    if (!TkMacIsCharacterMissing(tkfont, '')) {
    	markChar = '';
    } else if (!TkMacIsCharacterMissing(tkfont, '´')) {
    	markChar = '´';
    } else if (!TkMacIsCharacterMissing(tkfont, '')) {
    	markChar = '';
    } else if (!TkMacIsCharacterMissing(tkfont, '×')) {
    	markChar = '×';
    } else if (!TkMacIsCharacterMissing(tkfont, '„')) {
    	markChar = '„';
d793 1
a793 1
    	markChar = '-';
d795 1
a795 1
    	markChar = '';
d1064 1
a1064 1
    
d1178 2
a1179 2
    	    	    && (ENTRY_COMMAND_ACCEL 
    	    	    == (mePtr->entryFlags & ENTRY_ACCEL_MASK))) {
d1181 1
a1181 1
	    	SetItemCmd(macMenuHdl, index, accel[((EntryGeometry *)
a3576 1
    int state;
d3607 1
a3607 1
	if (((parentDisabled || (state == ENTRY_DISABLED)))
d4380 1
a4380 1
    
d4385 1
a4385 1
    
d4399 2
a4400 2
    
    Tcl_ExternalToUtf(NULL, NULL, "É", -1, 0, NULL, elipsisString,
@


1.12
log
@Fix a typo from the 8.0 -> 8.1 conversion of the Menu code.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.11 1999/08/05 06:19:52 jingham Exp $
d3974 1
a3974 1
    	    Tcl_DString itemTextDString;
d3977 14
a3990 1
	    Tk_DrawChars(menuPtr->display, d, gc,
d3993 2
a3994 1
		    leftEdge, baseline);
@


1.11
log
@Fix a typo left over from the conversion of the Menu code from 8.0 to 8.1.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.10 1999/06/16 05:36:46 jingham Exp $
d3577 1
d3608 1
a3608 1
	if (((parentDisabled || (mePtr->state == ENTRY_DISABLED)))
@


1.10
log
@Fix a bug in the region calculation for popup menus which would cause the popup to get posted in the wrong place if the menu was going to stick off the bottom of the screen.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.9 1999/05/22 06:33:19 jingham Exp $
a3576 1
    int state;
d3607 1
a3607 1
	if (((parentDisabled || (state == ENTRY_DISABLED)))
@


1.9
log
@Changes needed to get Tk8.1 to compile with stubs on the Mac
Also copied over some changes from Tk8.0.5 to support themed menus.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.8 1999/04/16 01:51:31 stanton Exp $
d18 1
d3163 1
d3168 18
a3185 2
	    	if (menuRectPtr->top + menuPtr->totalHeight > maxMenuHeight) {
	    	    menuRectPtr->top -= maxMenuHeight - menuPtr->totalHeight;
d3198 2
@


1.8
log
@* Merged 8.1 branch into the main trunk
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id$
d14 5
a26 1
#undef Status
a27 4
#include "tkMenu.h"
#include "tkMacInt.h"
#include "tkMenuButton.h"
#include "tkColor.h"
a220 5
static GC     appearanceGC = NULL; /* The fake appearance GC.  If you
				      pass the foreground of this to TkMacSetColor, 
				      it will return false, so you will know 
				      not to set the foreground color */
					  
d261 1
a261 1
static void		FixMDEF _ANSI_ARGS_((void));
a1062 1
    int state;
d1474 1
a1474 1
EXTERN void
d2384 1
a2384 1
	if (TkSetMacColor(gc->foreground, &foreColor) == true) {
d2388 1
a2388 1
	if (TkSetMacColor(gc->background, &backColor) == true) {
d2577 1
d2580 1
d2807 2
a2808 2
	    	    &foreColor) == true) {
	    	if (!TkMacHaveAppearance()) {
d2810 1
a2810 1
	    	}
d2813 2
a2814 2
	    	    &backColor) == true) {
	    	if (!TkMacHaveAppearance()) {
d2816 1
a2816 1
	    	}
d3548 1
a3548 1
    GC gc, indicatorGC;
d3550 2
d3553 1
a3553 1
    CONST Tk_FontMetrics *fmPtr;
a3554 1
    int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0;
a3567 4
	    if ((TkMacHaveAppearance() > 1) && (menuPtr->menuType != TEAROFF_MENU)) {
	        SetThemeTextColor(kThemeSelectedMenuItemTextColor,32,true);
	        gc = appearanceGC;
	    } else {
a3568 1
	    }
a3591 4
	        if ((TkMacHaveAppearance() > 1) && (mePtr->bitmap == NULL)) {
	            SetThemeTextColor(kThemeDisabledMenuItemTextColor,32,true);
	            gc = appearanceGC;
	        } else {
a3593 1
	    }
d3597 1
a3597 6
	        if ((TkMacHaveAppearance() > 1) && (mePtr->bitmap == NULL)) {
	            SetThemeTextColor(kThemeActiveMenuItemTextColor,32,true);
	            gc = appearanceGC;
	        } else {
		    gc = menuPtr->textGC;
	        }
a3925 1
    int state;
d4015 2
a4016 2
		    && (mePtr->activeBorder != NULL)) 
            || ((mePtr->state != ENTRY_ACTIVE) && (mePtr->border != NULL))) {
a4359 1
        appearanceGC = XCreateGC(NULL, NULL, GCForeground | GCBackground, &tmpValues);
@


1.7
log
@* Merged changes from 8.0.5:
    - Updated for Mac release
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.6 1998/11/11 17:30:44 jingham Exp $
d57 1
a57 1
#define SICN_RESOURCE_NUMBER		128
d179 3
d198 2
a199 1
static TkMenuDefUPP menuDefProc;/* The routine descriptor to the MDEF proc.
d221 5
d266 3
a268 1
static Handle		FixMDEF _ANSI_ARGS_((void));
d313 2
d346 1
a346 1
    short macID)			/* The id to take out of the table */
d457 1
d693 2
a694 1
 *	handled specially.
d708 2
a709 1
    Str255 itemText)		/* The pascal string containing the text */
d711 1
d713 6
a718 6
	strcpy((char *)itemText, (const char *)"\p(Tear-off)");
    } else if (mePtr->imageString != NULL) {
	strcpy((char *)itemText, (const char *)"\p(Image)");
    } else if (mePtr->bitmap != None) {
	strcpy((char *)itemText, (const char *)"\p(Pixmap)");
    } else if (mePtr->label == NULL || mePtr->labelLength == 0) {
d724 1
a724 1
	strcpy((char *)itemText, (const char *)"\p ");
d726 3
a728 1
    	char *text = mePtr->label;
d731 1
a731 2
    	itemText[0] = 0;
    	for (i = 1; (*text != '\0') && (i <= 230); i++, text++) {
d735 7
a741 4
    	    	itemText[i] = 'É';
    	    	text += 2;
    	    } else {
    	    	itemText[i] = *text;
a742 1
    	    itemText[0] += 1;
d759 1
a759 1
 * 	'¥' - Bullet character
d762 1
a762 1
 * 	'Ñ' = Long dash ("em dash")
d780 5
a784 2
    Tk_Font tkfont = (mePtr->tkfont == NULL) ? mePtr->menuPtr->tkfont
    	    : mePtr->tkfont;
d788 2
a789 2
    } else if (!TkMacIsCharacterMissing(tkfont, '¥')) {
    	markChar = '¥';
d794 2
a795 2
    } else if (!TkMacIsCharacterMissing(tkfont, 'Ñ')) {
    	markChar = 'Ñ';
d842 7
a848 8
     
    if (((mePtr->type == RADIO_BUTTON_ENTRY) 
    	    || (mePtr->type == CHECK_BUTTON_ENTRY))
    	    && (mePtr->indicatorOn)
    	    && (mePtr->entryFlags & ENTRY_SELECTED)) {
    	markChar = FindMarkCharacter(mePtr);
    } else {
        markChar = 0;
d875 1
a875 1
    char *title)		/* The C string to set the title to. */
d879 2
d917 1
a917 1
 *	interp->result contains an error message.
d957 1
a957 1
    	    	    SetMenuTitle(childMenuHdl, mePtr->label);
d973 3
a975 1
	char *accelString = mePtr->accel;
d1021 1
a1021 1
		= ((long) accelString - (long) mePtr->accel);
d1068 1
d1072 5
a1076 2
    	if (strcmp(Tk_PathName(menuPtr->tkwin), mePtr->name) == 0) {
    	    if (mePtr->state == tkDisabledUid) {
d1105 10
a1114 1
	    GetEntryText(mePtr, itemText);
d1117 1
d1123 1
a1123 1
	    if (parentDisabled || (mePtr->state == tkDisabledUid)) {
d1137 2
a1138 2
		    	& ENTRY_SELECTED) && (mePtr->indicatorOn));
		if ((mePtr->indicatorOn)
d1185 3
a1187 3
	    	SetItemCmd(macMenuHdl, index, mePtr
			->accel[((EntryGeometry *)mePtr->platformEntryData)
	    		->accelTextStart]);
d1629 3
a1631 3
        } else {		    
	    if (menuBarPtr->tearOff != menuPtr->tearOff) {
	    	if (menuBarPtr->tearOff) {
d1679 1
a1679 1
	    	    if (menuBarPtr->entries[i]->state == tkDisabledUid) {
d1722 1
a1722 1
	    	    	if (menuBarPtr->entries[i]->state == tkDisabledUid) {
d1777 2
a1778 1
	    	macMenuHdl = ((MacMenu *) cascadeMenuPtr->platformData)->menuHdl;
d1819 2
a1820 1
	    	macMenuHdl = ((MacMenu *) cascadeMenuPtr->platformData)->menuHdl;
d1930 2
a1931 1
	    	    menuName = Tk_PathName(listPtr->menuPtr->masterMenuPtr->tkwin);
d2133 2
d2137 1
a2137 2
    	    *textWidthPtr = Tk_TextWidth(tkfont, mePtr->accel,
    	    	    mePtr->accelLength);
d2141 1
a2141 2
    	    	int width = Tk_TextWidth(tkfont, mePtr->accel,
    	    		mePtr->accelLength);
d2166 1
a2166 1
    	    	    *textWidthPtr += Tk_TextWidth(tkfont, mePtr->accel 
d2276 21
a2296 15
    if (((mePtr->type == CHECK_BUTTON_ENTRY) || 
    	    (mePtr->type == RADIO_BUTTON_ENTRY))
	    && (mePtr->indicatorOn)
    	    && (mePtr->entryFlags & ENTRY_SELECTED)) {
	int baseline;
	short markShort;
	char markChar;
    
    	baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
    	GetItemMark(((MacMenu *) menuPtr->platformData)->menuHdl,
    		mePtr->index + 1, &markShort);
        if (markShort != 0) {
            markChar = (char) markShort;
            Tk_DrawChars(menuPtr->display, d, gc, tkfont, &markChar, 1,
            	    x + 2, baseline);
d2390 1
a2390 1
	if (TkSetMacColor(gc->foreground, &foreColor)) {
d2394 1
a2394 1
	if (TkSetMacColor(gc->background, &backColor)) {
d2448 4
d2465 1
a2465 1
		points[0].x = width - menuPtr->activeBorderWidth
d2480 3
d2487 1
a2487 1
	    Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel,
d2499 1
a2499 1
	    Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel 
a2582 1
    
a2584 1
    
d2626 1
a2626 1
    Tk_Font tkfont;
d2760 2
a2761 1
	    Tk_GetFontMetrics(menuPtr->tkfont, &fontMetrics);    	    
d2772 1
a2772 1
    	    	if (mePtr->tkfont == NULL) {
d2774 1
a2774 1
    	    	    tkfont = menuPtr->tkfont;
d2776 1
a2776 1
    	    	    tkfont = mePtr->tkfont;
d2811 2
a2812 2
	    	    &foreColor)) {
	    	/* if (!TkMacHaveAppearance()) { */
d2814 1
a2814 1
	    	/* } */
d2817 2
a2818 2
	    	    &backColor)) {
	    	/* if (!TkMacHaveAppearance()) { */
d2820 1
a2820 1
	    	/* } */
d2845 1
a2845 1
	    	        	|| (mePtr->state == tkDisabledUid)) {
d2856 7
a2862 4
				if (strcmp(cascadeEntryPtr->name,
					Tk_PathName(menuPtr->tkwin)) == 0) {
				    if (cascadeEntryPtr->state
					    == tkDisabledUid) {
d2916 7
a2922 1
		    tkfont = mePtr->tkfont ? mePtr->tkfont : menuPtr->tkfont;
d2936 1
a2936 1
		    if (mePtr->state != tkDisabledUid) {
d2939 7
a2945 1
		    tkfont = mePtr->tkfont ? mePtr->tkfont : menuPtr->tkfont;
d2960 1
a2960 1
		if (mePtr->state != tkDisabledUid) {
d2973 2
a2974 1
	    	if (!hasTopScroll && ((globalsPtr->menuTop + scrollAmt) < menuRectPtr->top)) {
d3006 1
d3021 2
a3022 1
	    	Tk_GetFontMetrics(menuPtr->tkfont, &fontMetrics);    	    
d3032 1
a3032 1
    	    	    if (mePtr->tkfont == NULL) {
d3034 1
a3034 1
    	    	    	tkfont = menuPtr->tkfont;
d3036 2
a3037 1
    	    	    	tkfont = mePtr->tkfont;
d3067 1
d3069 7
a3075 3
    	    	    	strcmp(parentEntryPtr->name,
			Tk_PathName(menuPtr->tkwin)) == 0;
		        parentEntryPtr = parentEntryPtr->nextCascadePtr) {
d3079 1
a3079 1
			    parentEntryPtr->index);
d3083 1
a3083 1
	    if (menuPtr->tearOff) {
d3234 1
a3234 1
        if (mePtr->state == tkActiveUid) {
d3236 1
a3236 1
        } else if (mePtr->state == tkDisabledUid) {
d3312 1
a3312 1
    	char intString[20];
d3422 1
d3434 1
d3441 1
a3441 1
	Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 2, 1,
d3560 1
d3568 1
a3568 2
    if ((mePtr->state == tkActiveUid)
	    && !strictMotif) {
d3571 4
d3576 1
d3585 5
a3589 3
    	    if (strcmp(cascadeEntryPtr->name, 
    	    	    Tk_PathName(menuPtr->tkwin)) == 0) {
    	    	if (cascadeEntryPtr->state == tkDisabledUid) {
d3596 2
a3597 2
	if (((parentDisabled || (mePtr->state == tkDisabledUid)))
		&& (menuPtr->disabledFg != NULL)) {
d3600 4
d3606 1
d3610 4
d3615 1
d3624 4
a3627 5
	    
    bgBorder = mePtr->border;
    if (bgBorder == NULL) {
	bgBorder = menuPtr->border;
    }
d3631 3
a3633 4
	activeBorder = mePtr->activeBorder;
	if (activeBorder == NULL) {
	    activeBorder = menuPtr->activeBorder;
	}
d3636 1
a3636 1
    if (mePtr->tkfont == NULL) {
d3639 1
a3639 1
	tkfont = mePtr->tkfont;
d3695 1
a3695 1
    Tk_Font tkfont;
d3701 1
a3701 1
    int entryWidth, maxIndicatorSpace;
d3709 5
a3713 1
    x = y = menuPtr->borderWidth;
d3731 2
a3732 1
    Tk_GetFontMetrics(menuPtr->tkfont, &menuMetrics);
d3736 3
a3738 4
    	tkfont = mePtr->tkfont;
    	if (tkfont == NULL) {
    	    tkfont = menuPtr->tkfont;
    	    fmPtr = &menuMetrics;
d3740 1
d3756 1
a3756 1
			+ 2 * menuPtr->activeBorderWidth;
d3771 1
a3771 1
	    x += maxIndicatorSpace + maxWidth + 2 * menuPtr->borderWidth;
d3777 1
a3777 1
	    y = menuPtr->borderWidth;
a3788 1
	    
d3808 2
a3809 2
	    	nonAccelMargin = mePtr->hideMargin ? 0 
	    		: Tk_TextWidth(tkfont, "m", 1);
d3861 1
a3861 1
	    mePtr->height += 2 * menuPtr->activeBorderWidth;
d3864 1
a3864 1
	y += menuPtr->entries[i]->height + menuPtr->borderWidth;
d3876 1
a3876 1
		+ 2 * menuPtr->activeBorderWidth;
d3892 2
a3893 2
	    + 2 * menuPtr->activeBorderWidth + menuPtr->borderWidth;
    windowHeight += menuPtr->borderWidth;
d3944 1
d3963 1
a3963 1
    } else if (mePtr->bitmap != None) {
d3965 1
a3965 1

d3967 3
a3969 4
	        mePtr->bitmap, &width, &height);
    	XCopyPlane(menuPtr->display,
	    	mePtr->bitmap, d,
	    	gc, 0, 0, (unsigned) width, (unsigned) height, leftEdge,
d3973 1
a3973 1
    	    Str255 itemText;
d3975 1
a3975 1
    	    GetEntryText(mePtr, itemText);
d3977 2
a3978 1
		    tkfont, (char *) itemText + 1, itemText[0],
d3980 1
a3980 2
/*	    TkpDrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y,
		    width, height);*/
d3984 2
a3985 2
    if (mePtr->state == tkDisabledUid) {
	if (menuPtr->disabledFg == NULL) {
d4033 4
a4036 3
            || ((mePtr->state == tkActiveUid) && (mePtr->activeBorder != NULL)) 
            || ((mePtr->state != tkActiveUid) && (mePtr->border != NULL))) {
        if (mePtr->state == tkActiveUid) {
d4075 3
a4077 2
    } else if (mePtr->bitmap != (Pixmap) NULL) {
    	Tk_SizeOfBitmap(menuPtr->display, mePtr->bitmap, widthPtr, heightPtr);
d4081 2
a4082 2
    	if (mePtr->label != NULL) {
    	    Str255 itemText;
d4084 5
a4088 3
    	    GetEntryText(mePtr, itemText);
    	    *widthPtr = Tk_TextWidth(tkfont, (char *) itemText + 1,
		    itemText[0]);
d4349 1
a4349 1
 *	Allcates a hash table.
d4379 1
d4386 28
@


1.6
log
@Make the Macintosh Menu's adopt the current Theme Appearance if the Appearance extension (version 1.0.1 or later) is installed
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.5 1998/09/14 18:23:37 stanton Exp $
a216 5
static GC     appearanceGC = NULL; /* The fake appearance GC.  If you
				      pass the foreground of this to TkMacSetColor, 
				      it will return false, so you will know 
				      not to set the foreground color */
					  
d2341 1
a2341 1
	if (TkSetMacColor(gc->foreground, &foreColor) == true) {
d2345 1
a2345 1
	if (TkSetMacColor(gc->background, &backColor) == true) {
d2756 2
a2757 2
	    	    &foreColor) == true) {
	    	if (!TkMacHaveAppearance()) {
d2759 1
a2759 1
	    	}
d2762 2
a2763 2
	    	    &backColor) == true) {
	    	if (!TkMacHaveAppearance()) {
d2765 1
a2765 1
	    	}
a3489 4
	    if ((TkMacHaveAppearance() > 1) && (menuPtr->menuType != TEAROFF_MENU)) {
	        SetThemeTextColor(kThemeSelectedMenuItemTextColor,32,true);
	        gc = appearanceGC;
	    } else {
a3490 1
	    }
a3511 4
	        if ((TkMacHaveAppearance() > 1) && (mePtr->bitmap == NULL)) {
	            SetThemeTextColor(kThemeDisabledMenuItemTextColor,32,true);
	            gc = appearanceGC;
	        } else {
a3513 1
	    }
a3516 4
	        if ((TkMacHaveAppearance() > 1) && (mePtr->bitmap == NULL)) {
	            SetThemeTextColor(kThemeActiveMenuItemTextColor,32,true);
	            gc = appearanceGC;
	        } else {
a3517 1
	        }
a4274 1
        appearanceGC = XCreateGC(NULL, NULL, GCForeground | GCBackground, &tmpValues);
@


1.6.2.1
log
@Got rid of the AppearanceGC, and rely on the tkColor to not set menu foregrounds.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.6 1998/11/11 17:30:44 jingham Exp $
d217 5
d2346 1
a2346 1
	if (TkSetMacColor(gc->foreground, &foreColor)) {
d2350 1
a2350 1
	if (TkSetMacColor(gc->background, &backColor)) {
d2761 2
a2762 2
	    	    &foreColor)) {
	    	/* if (!TkMacHaveAppearance()) { */
d2764 1
a2764 1
	    	/* } */
d2767 2
a2768 2
	    	    &backColor)) {
	    	/* if (!TkMacHaveAppearance()) { */
d2770 1
a2770 1
	    	/* } */
d3495 4
d3500 1
d3522 4
d3528 1
d3532 4
d3537 1
d4295 1
@


1.5
log
@Replaced SCCS strings, fixed binary files
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id$
d21 1
d27 1
d38 6
d214 8
d230 2
d307 7
d1122 4
d1130 1
d2195 10
a2204 2
    *widthPtr = 0;
    *heightPtr = fmPtr->linespace;
d2260 40
d2405 5
d2428 1
d2516 9
a2524 1
    
d2538 1
d2657 20
a2679 1
    	    GetGWorld(&macMDEFDrawable.portPtr, &device);
d2721 1
a2721 1
	 	ClipRect(&menuClipRect);
d2730 7
a2736 6
    	    	TkpDrawMenuEntry(mePtr, (Drawable) &macMDEFDrawable,
    	    		tkfont, fmPtr, menuRectPtr->left + mePtr->x, 
    	    		globalsPtr->menuTop + mePtr->y,
    	    		(mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
    	    		menuPtr->totalWidth - mePtr->x : mePtr->width,
    	    		menuPtr->entries[i]->height, 0, 1);
d2762 3
a2764 1
	    	RGBForeColor(&foreColor);
d2768 3
a2770 1
	    	RGBBackColor(&backColor);
d2865 7
a2871 7
		    TkpDrawMenuEntry(mePtr, (Drawable) &macMDEFDrawable,
			    tkfont, &fontMetrics, 
			    menuRectPtr->left + mePtr->x,
		    	    globalsPtr->menuTop + mePtr->y,
		    	    (mePtr->entryFlags & ENTRY_LAST_COLUMN)
		    	    ? menuPtr->totalWidth - mePtr->x
		    	    : mePtr->width, mePtr->height, 0, 1);
d2882 7
a2888 8
		    TkpDrawMenuEntry(mePtr, (Drawable) &macMDEFDrawable,
		    	    tkfont, &fontMetrics, 
		    	    menuRectPtr->left + mePtr->x,
		    	    globalsPtr->menuTop + mePtr->y,
		    	    (mePtr->entryFlags & ENTRY_LAST_COLUMN)
		    	    ? menuPtr->totalWidth - mePtr->x
		    	    : mePtr->width, mePtr->height, 
		    	    0, 1);
d2972 7
a2978 6
    	    	    TkpDrawMenuEntry(mePtr, (Drawable) &macMDEFDrawable,
    	    		    tkfont, fmPtr, menuRectPtr->left + mePtr->x, 
    	    		    globalsPtr->menuTop + mePtr->y,
    	    		    (mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
    	    		    menuPtr->totalWidth - mePtr->x : mePtr->width,
    	    		    menuPtr->entries[i]->height, 0, 1);
d3117 102
d3349 1
a3349 1
    if ((menuPtr->menuType != MASTER_MENU) || (GetResource('MDEF', 591) != NULL)) {
d3487 2
d3495 6
a3500 1
	    gc = menuPtr->activeGC;
d3522 4
d3528 1
d3532 6
a3537 1
		gc = menuPtr->textGC;
d3539 1
a3539 1
	}
d3541 1
d3592 1
d3906 4
a3909 2
	    XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
		    (unsigned) width, (unsigned) height);
d3925 3
a3927 1
 *	This procedure draws the background part of a menu.
d3951 9
a3959 2
    if (mePtr->state == tkActiveUid) {
	bgBorder = activeBorder;
a3960 2
    Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder,
    	    x, y, width, height, 0, TK_RELIEF_FLAT);
d4166 1
a4166 2
    	    for (menuPtr = menuBarRefPtr->menuPtr->masterMenuPtr; 
                    menuPtr != NULL;
d4282 18
@


1.4
log
@Updates from Jim Ingham
@
text
@d11 1
a11 1
 * SCCS: @@(#) tkMacMenu.c 1.107 97/11/20 18:33:09
@


1.3
log
@Updates from Jim Ingham
@
text
@d244 1
a244 1
static void		FixMDEF _ANSI_ARGS_((void));
d504 2
a505 3
        Handle mdefProc = GetResource('MDEF', 591);
        Handle sicnHandle = GetResource('SICN', SICN_RESOURCE_NUMBER);
	if ((mdefProc != NULL) && (sicnHandle != NULL)) {
d3919 2
a3920 1
    	    for (menuPtr = menuBarRefPtr->menuPtr->masterMenuPtr; menuPtr != NULL;
d3978 1
a3978 1
 *	None.
d3981 1
a3981 1
 *	Allcates a hash table.
d3986 1
a3986 1
static void
d3994 4
a3997 2
    	HLock(MDEFHandle);
    	menuDefProc = TkNewMenuDefProc(MenuDefProc);
d3999 3
d4003 2
@


1.2
log
@plugin updates
@
text
@d3993 1
a3993 1
        MoveHHi(MDEFHandle);
@


1.1
log
@Initial revision
@
text
@d142 2
d1401 25
d1449 8
d4029 2
@


1.1.4.1
log
@initial tk8.1a2 version
@
text
@d11 1
a11 1
 * SCCS: @@(#) tkMacMenu.c 1.111 98/01/21 22:04:59
d21 2
d25 1
a25 3
#include "tkMenubutton.h"
#undef Status
#include <Devices.h>
d49 1
a49 1
#define SICN_RESOURCE_NUMBER	128
a141 2
static int gNoTkMenus = 0;      /* This is used by Tk_MacTurnOffMenus as the
                                 * flag that Tk is not to draw any menus. */
a168 3
static char elipsisString[TCL_UTF_MAX + 1];
				/* The UTF representation of the elipsis (ƒ) 
				 * character. */
d185 1
a185 2
static TkMenuDefUPP menuDefProc = NULL ;
                                /* The routine descriptor to the MDEF proc.
a242 2
static void		GetEntryText _ANSI_ARGS_((TkMenuEntry *mePtr,
			    Tcl_DString *dStringPtr));
a286 2
static void		SetMenuTitle _ANSI_ARGS_((MenuHandle menuHdl,
			    Tcl_Obj *titlePtr));
d311 1
a311 1
    short macID)		/* The id to take out of the table */
a421 1
    	Tcl_ResetResult(interp);
d658 1
a658 2
 *	handled specially. This is primarily used to do a substitution
 *	between "..." and "ƒ".
d672 1
a672 2
    Tcl_DString *dStringPtr)	/* The DString to put the text into. This
    				 * will be initialized by this routine. */
a673 1
    Tcl_DStringInit(dStringPtr);
d675 6
a680 6
    	Tcl_DStringAppend(dStringPtr, "(Tear-off)", -1);
    } else if (mePtr->imagePtr != NULL) {
    	Tcl_DStringAppend(dStringPtr, "(Image)", -1);
    } else if (mePtr->bitmapPtr != NULL) {
    	Tcl_DStringAppend(dStringPtr, "(Pixmap)", -1);
    } else if (mePtr->labelPtr == NULL || mePtr->labelLength == 0) {
d686 1
a686 1
	Tcl_DStringAppend(dStringPtr, " ", -1);
d688 1
a688 3
    	int length;
    	char *text = Tcl_GetStringFromObj(mePtr->labelPtr, &length);
    	char *dStringText;
d691 2
a692 1
	for (i = 0; i < length; text++, i++) {
d696 4
a699 7
    	    	Tcl_DStringAppend(dStringPtr, elipsisString, -1);
    	    	i += strlen(elipsisString) - 1;
   	    } else {
    	    	Tcl_DStringSetLength(dStringPtr,
			Tcl_DStringLength(dStringPtr) + 1);
    	    	dStringText = Tcl_DStringValue(dStringPtr);
    	    	dStringText[i] = *text;
d701 1
d718 1
a718 1
 * 	'´' - Bullet character
d721 1
a721 1
 * 	'„' = Long dash ("em dash")
d739 2
a740 5
    Tk_Font tkfont;

    tkfont = Tk_GetFontFromObj(mePtr->menuPtr->tkwin,
    	    (mePtr->fontPtr == NULL) ? mePtr->menuPtr->fontPtr
	    : mePtr->fontPtr);
d744 2
a745 2
    } else if (!TkMacIsCharacterMissing(tkfont, '´')) {
    	markChar = '´';
d750 2
a751 2
    } else if (!TkMacIsCharacterMissing(tkfont, '„')) {
    	markChar = '„';
a783 1
    int indicatorOn;
d798 8
a805 8
    
    markChar = 0;
    if ((mePtr->type == RADIO_BUTTON_ENTRY) 
    	    || (mePtr->type == CHECK_BUTTON_ENTRY)) {
    	Tcl_GetBooleanFromObj(NULL, mePtr->indicatorOnPtr, &indicatorOn);
    	if (indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED)) {
    	    markChar = FindMarkCharacter(mePtr);
    	}
d832 1
a832 1
    Tcl_Obj *titlePtr)	/* The C string to set the title to. */
a835 2
    char *title = (titlePtr == NULL) ? ""
    	    : Tcl_GetStringFromObj(titlePtr, NULL);
d872 1
a872 1
 *	the interp's result contains an error message.
d912 1
a912 1
    	    	    SetMenuTitle(childMenuHdl, mePtr->labelPtr);
d928 1
a928 3
	char *accelString = (mePtr->accelPtr == NULL) ? ""
		: Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
	char *accel = accelString;
d974 1
a974 1
		= ((long) accelString - (long) accel);
a1020 1
    int state;
d1024 2
a1025 7
    	char *name = (mePtr->namePtr == NULL) ? ""
    		: Tcl_GetStringFromObj(mePtr->namePtr, NULL);
    	
    	if (strcmp(Tk_PathName(menuPtr->tkwin), name) == 0) {
	    Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings,
		    NULL, 0, &state);
    	    if (state == ENTRY_DISABLED) {
d1054 1
a1054 10
    	    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;
	    
a1056 1
	    Tcl_DStringFree(&itemTextDString);
d1062 1
a1062 3
	    Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings,
		    NULL, 0, &state);
	    if (parentDisabled || (state == ENTRY_DISABLED)) {
a1074 4
		int indicatorOn;
		
		Tcl_GetBooleanFromObj(NULL, mePtr->indicatorOnPtr,
			&indicatorOn);
d1076 2
a1077 2
		    	& ENTRY_SELECTED) && (indicatorOn));
		if ((indicatorOn)
d1119 3
a1121 3
    	    	char *accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
	    	SetItemCmd(macMenuHdl, index, accel[((EntryGeometry *)
	    		mePtr->platformEntryData)->accelTextStart]);
a1398 25
 * 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.
 *
 *----------------------------------------------------------------------
 */

EXTERN void
Tk_MacTurnOffMenus()
{
    gNoTkMenus = 1;
}

/*
 *----------------------------------------------------------------------
 *
 * 
a1421 8
     * If we have been turned off, exit.
     */
     
    if (gNoTkMenus) {
        return;
    }
    
    /*
d1530 3
a1532 8
        } else {
            int menuBarTearoff, menuTearoff;
            
            Tcl_GetBooleanFromObj(NULL, menuBarPtr->tearoffPtr,
		    &menuBarTearoff);
            Tcl_GetBooleanFromObj(NULL, menuPtr->tearoffPtr, &menuTearoff);
	    if (menuBarTearoff != menuTearoff) {
	    	if (menuBarTearoff) {
d1580 1
a1580 6
	    	    int state;
	    	    
		    Tcl_GetIndexFromObj(NULL,
			    menuBarPtr->entries[i]->statePtr, 
		    	    tkMenuStateStrings, NULL, 0, &state);
	    	    if (state == ENTRY_DISABLED) {
a1615 2
			int state;
			
d1623 1
a1623 4
		    	Tcl_GetIndexFromObj(NULL, 
		    		menuBarPtr->entries[i]->statePtr, 
		    		tkMenuStateStrings, NULL, 0, &state);
	    	    	if (state == ENTRY_DISABLED) {
d1678 1
a1678 2
	    	macMenuHdl =
		        ((MacMenu *) cascadeMenuPtr->platformData)->menuHdl;
d1719 1
a1719 2
	    	macMenuHdl =
		        ((MacMenu *) cascadeMenuPtr->platformData)->menuHdl;
d1829 1
a1829 2
	    	    menuName = Tk_PathName(listPtr->menuPtr->masterMenuPtr
			    ->tkwin);
a2030 2
    	char *accel = (mePtr->accelPtr == NULL) ? ""
    		: Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
d2033 2
a2034 1
    	    *textWidthPtr = Tk_TextWidth(tkfont, accel, mePtr->accelLength);
d2038 2
a2039 1
    	    	int width = Tk_TextWidth(tkfont, accel,	mePtr->accelLength);
d2064 1
a2064 1
    	    	    *textWidthPtr += Tk_TextWidth(tkfont, accel 
d2166 15
a2180 25
    if ((mePtr->type == CHECK_BUTTON_ENTRY) || 
    	    (mePtr->type == RADIO_BUTTON_ENTRY)) {
    	int indicatorOn;
    	
    	Tcl_GetBooleanFromObj(NULL, mePtr->indicatorOnPtr, &indicatorOn);
    	
    	if ((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);
            }
a2291 4
    int activeBorderWidth;
    
    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,
    	    &activeBorderWidth);
d2300 1
a2300 1
		points[0].x = width - activeBorderWidth
a2313 3
    	char *accel;
    	
    	accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
d2318 1
a2318 1
	    Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
d2330 1
a2330 1
	    Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel 
d2406 1
d2409 1
d2450 1
a2450 1
    Tk_Font tkfont, menuFont;
d2565 1
a2565 2
	    menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
	    Tk_GetFontMetrics(menuFont, &fontMetrics);    	    
d2576 1
a2576 1
    	    	if (mePtr->fontPtr == NULL) {
d2578 1
a2578 1
    	    	    tkfont = menuFont;
d2580 1
a2580 1
		    tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
d2601 1
a2601 1
    	    int hasTopScroll, hasBottomScroll, tearoff;
a2642 4
	    	    	int state;
	    	    	
		    	Tcl_GetIndexFromObj(NULL, mePtr->statePtr, 
		    		tkMenuStateStrings, NULL, 0, &state);
d2644 1
a2644 1
	    	        	|| (state == ENTRY_DISABLED)) {
d2655 4
a2658 11
	    	            	char *name;
	    	            	
	    	            	name = Tcl_GetStringFromObj(
	    	            		cascadeEntryPtr->namePtr, NULL);
				if (strcmp(name, Tk_PathName(menuPtr->tkwin)) 
					== 0) {
	    			    Tcl_GetIndexFromObj(NULL, 
	    			    	    cascadeEntryPtr->statePtr, 
	    			    	    tkMenuStateStrings, NULL, 0,
					    &state);
				    if (state == ENTRY_DISABLED) {
a2709 2
		int state;
		
d2712 1
a2712 7
		    if (mePtr->fontPtr == NULL) {
			tkfont = Tk_GetFontFromObj(menuPtr->tkwin, 
				menuPtr->fontPtr);
		    } else {
			tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
				mePtr->fontPtr);
		    }
d2726 1
a2726 3
	    	    Tcl_GetIndexFromObj(NULL, mePtr->statePtr, 
	    	    	    tkMenuStateStrings, NULL, 0, &state);
		    if (state != ENTRY_DISABLED) {
d2729 1
a2729 7
		    if (mePtr->fontPtr == NULL) {
			tkfont = Tk_GetFontFromObj(menuPtr->tkwin, 
				menuPtr->fontPtr);
		    } else {
			tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
				mePtr->fontPtr);
		    }
d2745 1
a2745 3
	    	Tcl_GetIndexFromObj(NULL, mePtr->statePtr,
			tkMenuStateStrings, NULL, 0, &state);
		if (state != ENTRY_DISABLED) {
d2758 1
a2758 2
	    	if (!hasTopScroll && ((globalsPtr->menuTop + scrollAmt)
			< menuRectPtr->top)) {
a2789 1
	    	Tk_Font menuFont;
d2804 1
a2804 2
		menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
	    	Tk_GetFontMetrics(menuFont, &fontMetrics);    	    
d2814 1
a2814 1
    	    	    if (mePtr->fontPtr == NULL) {
d2816 1
a2816 1
    	    	    	tkfont = menuFont;
d2818 1
a2818 2
			tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
				mePtr->fontPtr);
a2846 1
    	    	char *name;
d2848 3
a2850 7
    	    	        parentEntryPtr != NULL
    	    	    	; parentEntryPtr = parentEntryPtr->nextCascadePtr) {
		    name = Tcl_GetStringFromObj(parentEntryPtr->namePtr,
			    NULL);
		    if (strcmp(name, Tk_PathName(menuPtr->tkwin)) != 0) {
		        break;
		    }
d2854 1
a2854 1
    	    	    	    parentEntryPtr->index);
d2858 1
a2858 2
    	    Tcl_GetBooleanFromObj(NULL, menuPtr->tearoffPtr, &tearoff);
	    if (tearoff) {
d2985 1
a2985 1
    	char intString[TCL_INTEGER_SPACE];
a3094 1
    Tk_3DBorder border;
d3096 1
a3096 2
    if ((menuPtr->menuType != MASTER_MENU)
	    || (GetResource('MDEF', 591) != NULL)) {
a3105 1
    border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
d3112 1
a3112 1
	Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,
a3230 1
    int state;
d3236 2
a3237 3
    Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings, NULL,
	    0, &state);
    if ((state == ENTRY_ACTIVE) && !strictMotif) {
d3249 3
a3251 9
    	    char *name = (cascadeEntryPtr->namePtr == NULL) ? ""
    	    	    : Tcl_GetStringFromObj(cascadeEntryPtr->namePtr, NULL);
    	 
    	    if (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) {
    	    	int cascadeState;
    	    	
    	    	Tcl_GetIndexFromObj(NULL, cascadeEntryPtr->statePtr, 
    	    		tkMenuStateStrings, NULL, 0, &cascadeState);
    	    	if (cascadeState == ENTRY_DISABLED) {
d3258 2
a3259 2
	if (((parentDisabled || (state == ENTRY_DISABLED)))
		&& (menuPtr->disabledFgPtr != NULL)) {
d3275 5
a3279 4

    bgBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
	    (mePtr->borderPtr == NULL)
	    ? menuPtr->borderPtr : mePtr->borderPtr);
d3283 4
a3286 3
	activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
	    (mePtr->activeBorderPtr == NULL)
	    ? menuPtr->activeBorderPtr : mePtr->activeBorderPtr);
d3289 1
a3289 1
    if (mePtr->fontPtr == NULL) {
d3292 1
a3292 1
	tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
a3312 2
    	int hideMargin;
    	
d3317 1
a3317 2
	Tcl_GetBooleanFromObj(NULL, mePtr->hideMarginPtr, &hideMargin);
	if (!hideMargin) {
d3347 1
a3347 1
    Tk_Font tkfont, menuFont;
d3353 1
a3353 1
    int entryWidth, maxIndicatorSpace, borderWidth, activeBorderWidth;
d3361 1
a3361 5
    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
    	    &borderWidth);
    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,
    	    &activeBorderWidth);
    x = y = borderWidth;
d3379 1
a3379 2
    menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
    Tk_GetFontMetrics(menuFont, &menuMetrics);
a3381 2
    	int columnBreak;
    	
d3383 4
a3386 3
    	if (mePtr->fontPtr == NULL) {
	    tkfont = menuFont;
	    fmPtr = &menuMetrics;
a3387 1
	    tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
d3392 1
a3392 2
    	Tcl_GetBooleanFromObj(NULL, mePtr->columnBreakPtr, &columnBreak);
	if ((i > 0) && columnBreak) {
d3403 1
a3403 1
			+ 2 * activeBorderWidth;
d3418 1
a3418 1
	    x += maxIndicatorSpace + maxWidth + 2 * borderWidth;
d3424 1
a3424 1
	    y = borderWidth;
a3435 3
	    int hideMargin;
	    	
	    Tcl_GetBooleanFromObj(NULL, mePtr->hideMarginPtr, &hideMargin);
d3456 1
a3456 1
	    	nonAccelMargin = hideMargin ? 0 
d3469 1
a3469 1
	    if (!(hideMargin)) {
d3509 1
a3509 1
	    mePtr->height += 2 * activeBorderWidth;
d3512 1
a3512 1
	y += menuPtr->entries[i]->height + borderWidth;
d3524 1
a3524 1
		+ 2 * activeBorderWidth;
d3540 2
a3541 2
	    + 2 * activeBorderWidth + borderWidth;
    windowHeight += borderWidth;
a3591 1
    int state;
d3610 1
a3610 1
    } else if (mePtr->bitmapPtr != NULL) {
d3612 1
a3612 1
    	Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
d3614 4
a3617 3
	        bitmap, &width, &height);
    	XCopyPlane(menuPtr->display, bitmap, d, gc, 0, 0, 
    		(unsigned) width, (unsigned) height, leftEdge,
d3621 1
a3621 1
    	    Tcl_DString itemTextDString;
d3623 1
a3623 1
    	    GetEntryText(mePtr, &itemTextDString);
d3625 1
a3625 2
		    tkfont, Tcl_DStringValue(&itemTextDString), 
		    Tcl_DStringLength(&itemTextDString),
d3627 2
a3628 1
	    Tcl_DStringFree(&itemTextDString);
d3632 2
a3633 4
    Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings, NULL,
	    0, &state);
    if (state == ENTRY_DISABLED) {
	if (menuPtr->disabledFgPtr == NULL) {
d3675 1
a3675 5
    int state;
    
    Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings, NULL,
	    0, &state);
    if (state == ENTRY_ACTIVE) {
d3713 2
a3714 3
    } else if (mePtr->bitmapPtr != NULL) {
    	Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
    	Tk_SizeOfBitmap(menuPtr->display, bitmap, widthPtr, heightPtr);
d3718 2
a3719 2
    	if (mePtr->labelPtr != NULL) {
    	    Tcl_DString itemTextDString;
d3721 3
a3723 5
    	    GetEntryText(mePtr, &itemTextDString);
    	    *widthPtr = Tk_TextWidth(tkfont, 
    	    	    Tcl_DStringValue(&itemTextDString),
    	    	    Tcl_DStringLength(&itemTextDString));
    	    Tcl_DStringFree(&itemTextDString);
d3885 1
a3885 2
    	    for (menuPtr = menuBarRefPtr->menuPtr->masterMenuPtr;
		    menuPtr != NULL;
d3960 1
a3960 3
    	if ( menuDefProc == NULL) {
	    menuDefProc = TkNewMenuDefProc(MenuDefProc);
	}
a3962 1
        
d3977 1
a3977 1
 *	Allocates a hash table.
a3993 5
    FixMDEF();

    
    Tcl_ExternalToUtf(NULL, NULL, "É", -1, 0, NULL, elipsisString,
	    TCL_UTF_MAX + 1, NULL, NULL, NULL);
@


1.1.4.2
log
@Merged 8.0.3 changes into 8.1
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.5 1998/09/14 18:23:37 stanton Exp $
d513 3
a515 2
        Handle mdefProc = FixMDEF();
        if ((mdefProc != NULL)) {
d4070 2
a4071 2
    	    for (menuPtr = menuBarRefPtr->menuPtr->masterMenuPtr; 
                    menuPtr != NULL;
d4129 1
a4129 1
 *	Returns the MDEF handle.
d4132 1
a4132 1
 *	The MDEF is read in and massaged.
d4137 1
a4137 1
static Handle
d4144 4
a4147 4
        HLock(MDEFHandle);
    	HLock(SICNHandle);
	if (menuDefProc == NULL) {
    	    menuDefProc = TkNewMenuDefProc(MenuDefProc);
a4149 3
        return MDEFHandle;
    } else {
        return NULL;
d4151 1
a4151 2
#else
    return NULL;
@


1.1.4.3
log
@* tkMacMenu.c, tkUnixMenu.c, tkWinMenu.c, tkMenuDraw.c, tkMenu.h,
* tkMenu.c: Backed out the previous fix for bug 620 and
eliminated a bunch of code that created unnecessary objects.
Changed back to using internal types instead of objects for many
configuration options.  There are many more fixes like this that
could be made, but some require a little restructuring of the
code. In any case the leaks are fixed and there is a lot less
allocation happening. [Bug: 620]
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.1.4.2 1998/09/30 02:18:11 stanton Exp $
d803 1
d822 2
a823 1
    	if (mePtr->indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED)) {
d1053 3
a1055 1
    	    if (mePtr->state == ENTRY_DISABLED) {
d1102 3
a1104 1
	    if (parentDisabled || (mePtr->state == ENTRY_DISABLED)) {
d1117 4
d1122 2
a1123 2
		    	& ENTRY_SELECTED) && mePtr->indicatorOn);
		if (mePtr->indicatorOn
d1610 7
a1616 2
	    if (menuBarPtr->tearoff != menuPtr->tearoff) {
	    	if (menuBarPtr->tearoff) {
d1664 6
a1669 1
	    	    if (menuBarPtr->entries[i]->state == ENTRY_DISABLED) {
d1705 2
d1714 4
a1717 1
	    	    	if (menuBarPtr->entries[i]->state == ENTRY_DISABLED) {
d2265 5
a2269 1
    	if (mePtr->indicatorOn
d2714 1
a2714 1
    	    int hasTopScroll, hasBottomScroll;
d2756 4
d2761 1
a2761 1
	    	        	|| (mePtr->state == ENTRY_DISABLED)) {
d2778 5
a2782 1
				    if (cascadeEntryPtr->state == ENTRY_DISABLED) {
d2834 2
d2858 3
a2860 1
		    if (mePtr->state != ENTRY_DISABLED) {
d2885 3
a2887 1
		if (mePtr->state != ENTRY_DISABLED) {
d3009 2
a3010 1
	    if (menuPtr->tearoff) {
d3392 3
a3394 1
    if ((mePtr->state == ENTRY_ACTIVE) && !strictMotif) {
d3410 5
a3414 1
    	    	if (cascadeEntryPtr->state == ENTRY_DISABLED) {
d3474 2
d3480 2
a3481 1
	if (!mePtr->hideMargin) {
d3551 2
d3563 2
a3564 1
	if ((i > 0) && mePtr->columnBreak) {
d3608 4
d3631 2
a3632 2
	    	nonAccelMargin = mePtr->hideMargin ? 0
		    : Tk_TextWidth(tkfont, "m", 1);
d3644 1
a3644 1
	    if (!(mePtr->hideMargin)) {
d3807 3
a3809 1
    if (mePtr->state == ENTRY_DISABLED) {
d3852 5
a3856 1
    if (mePtr->state == ENTRY_ACTIVE) {
@


1.1.4.4
log
@* integrated tk8.0.4 changes.

* generic/tkBind.c: fixed deletion order bug where a crash would
result if a binding deleted "."
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.1.4.3 1998/11/24 21:42:44 stanton Exp $
d21 3
a23 1
#include <Appearance.h>
a25 4
#include "tkMenu.h"
#include "tkMacInt.h"
#include "tkMenuButton.h"
#include "tkColor.h"
a35 6
typedef struct MenuEntryUserData {
    Drawable mdefDrawable;
    TkMenuEntry *mePtr;
    Tk_Font tkfont;
    Tk_FontMetrics *fmPtr;
} MenuEntryUserData;
a209 8
static MenuItemDrawingUPP tkThemeMenuItemDrawingUPP; 
				/* Points to the UPP for theme Item drawing. */

static GC     appearanceGC = NULL; /* The fake appearance GC.  If you
				      pass the foreground of this to TkMacSetColor, 
				      it will return false, so you will know 
				      not to set the foreground color */
					  
a217 2
static void 		DrawMenuBackground _ANSI_ARGS_((
    			    Rect *menuRectPtr, Drawable d, ThemeMenuType type));
a296 7
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));
a1131 4
		        if (TkMacHaveAppearance() > 1) {
		            SetMenuItemHierarchicalID(macMenuHdl, base + index,
				    (*childMenuHdl)->menuID);
		        } else {
a1135 1
	    	    }
d2203 2
a2204 10
    if (TkMacHaveAppearance() > 1) {
        SInt16 outHeight;
        
        GetThemeMenuSeparatorHeight(&outHeight);
        *widthPtr = 0;
        *heightPtr = outHeight;
    } else {
        *widthPtr = 0;
        *heightPtr = fmPtr->linespace;
    }
a2265 40
 * 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;
    }
}

/*
 *----------------------------------------------------------------------
 *
a2374 5
        /*
         * Under Appearance, we let the Appearance Manager draw the icon
         */
         
        if (!TkMacHaveAppearance()) {
a2392 1
	}
d2483 1
a2483 9
    if (TkMacHaveAppearance() > 1) {
        Rect r;
        r.top = y;
        r.left = x;
        r.bottom = y + height;
        r.right = x + width;
         
        DrawThemeMenuSeparator(&r);
    } else {
a2494 1
}
a2612 20
	     * 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);
	    }
	    
	    /*
d2616 1
d2659 1
a2659 1
	 	/* ClipRect(&menuClipRect); */
d2668 6
a2673 7
    	    	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);
d2699 1
a2699 3
	    	if (!TkMacHaveAppearance()) {
	    	    RGBForeColor(&foreColor);
	    	}
d2703 1
a2703 3
	    	if (!TkMacHaveAppearance()) {
	    	    RGBBackColor(&backColor);
	    	}
d2807 7
a2813 7
    	    	    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);
d2830 8
a2837 7
    	    	    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);
d2925 6
a2930 7
    	    	    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);
a3073 102
 *   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 == tkActiveUid) {
            theState = kThemeMenuSelected;
        } else if (mePtr->state == tkDisabledUid) {
    	    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);

}

/*
 *----------------------------------------------------------------------
 *
d3205 2
a3206 1
    if ((menuPtr->menuType != MASTER_MENU) || (FixMDEF() != NULL)) {
a3345 2
     * Under Appearance, we pass a null (appearanceGC) to tell 
     * ourselves not to change whatever color the appearance manager has set.
d3351 1
a3351 6
	    if ((TkMacHaveAppearance() > 1) && (menuPtr->menuType != TEAROFF_MENU)) {
	        SetThemeTextColor(kThemeSelectedMenuItemTextColor,32,true);
	        gc = appearanceGC;
	    } else {
	        gc = menuPtr->activeGC;
	    }
a3374 4
	        if ((TkMacHaveAppearance() > 1) && (mePtr->bitmap == NULL)) {
	            SetThemeTextColor(kThemeDisabledMenuItemTextColor,32,true);
	            gc = appearanceGC;
	        } else {
a3376 1
	    }
d3380 1
a3380 6
	        if ((TkMacHaveAppearance() > 1) && (mePtr->bitmap == NULL)) {
	            SetThemeTextColor(kThemeActiveMenuItemTextColor,32,true);
	            gc = appearanceGC;
	        } else {
		    gc = menuPtr->textGC;
	        }
d3382 1
a3382 1
        }
a3383 1
    
a3431 1
    
d3749 2
a3750 4
	    if (!TkMacHaveAppearance()) {
	        XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
		        (unsigned) width, (unsigned) height);
	    }
d3766 1
a3766 3
 *	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...
d3790 2
a3791 10
    if (!TkMacHaveAppearance()
            || (menuPtr->menuType == TEAROFF_MENU)
            || ((mePtr->state == ENTRY_ACTIVE)
		    && (mePtr->activeBorder != NULL)) 
            || ((mePtr->state != ENTRY_ACTIVE) && (mePtr->border != NULL))) {
        if (mePtr->state == ENTRY_ACTIVE) {
	    bgBorder = activeBorder;
        }
        Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder,
    	        x, y, width, height, 0, TK_RELIEF_FLAT);
d3793 2
d4003 2
a4004 1
    	    for (menuPtr = menuBarRefPtr->menuPtr->masterMenuPtr; menuPtr != NULL;
a4119 18
    
    /*
     * 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;
        appearanceGC = XCreateGC(NULL, NULL, GCForeground | GCBackground, &tmpValues);
        ckfree((char *) tmpColorPtr);
        
        tkThemeMenuItemDrawingUPP = NewMenuItemDrawingProc(tkThemeMenuItemDrawingProc);				
    }
@


1.1.4.5
log
@Removed perky gloabal Tk_Uids causing concurrency problems.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.1.4.4 1998/11/25 21:16:36 stanton Exp $
d3234 1
a3234 1
        if (mePtr->state == TK_STATE_ACTIVE) {
d3236 1
a3236 1
        } else if (mePtr->state == TK_STATE_DISABLED) {
@


1.1.4.6
log
@Eliminated last stronghold of static data in the Tk core...until the next one.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.1.4.5 1999/01/07 02:42:54 lfb Exp $
d3234 1
a3234 1
        if (mePtr->state == ENTRY_ACTIVE) {
d3236 1
a3236 1
        } else if (mePtr->state == ENTRY_DISABLED) {
@


1.1.4.7
log
@Add TkpMenuThreadInit, which is a noop function.
@
text
@d11 1
a11 1
 * RCS: @@(#) $Id: tkMacMenu.c,v 1.1.4.6 1999/02/16 11:39:34 lfb Exp $
a4388 25
}

/*
 *----------------------------------------------------------------------
 *
 * TkpMenuThreadInit --
 *
 *	Does platform-specific initialization of thread-specific
 *      menu state.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkpMenuThreadInit()
{
    /*
     * Nothing to do.
     */
@


