Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Tree: 9e886ff077
Fetching contributors…

Cannot retrieve contributors at this time

1758 lines (1575 sloc) 46.792 kB
/*
* tkMacOSXMenu.c --
*
* This module implements the Mac-platform specific features of menus.
*
* Copyright (c) 1996-1997 by Sun Microsystems, Inc.
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
* Copyright (c) 2012 Adrian Robert.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tkMacOSXPrivate.h"
#include "tkMenubutton.h"
#include "tkMenu.h"
#include "tkColor.h"
#include "tkFont.h"
#include "tkMacOSXWm.h"
#include "tkMacOSXDebug.h"
/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_MENUS
#endif
*/
#define ENTRY_HELP_MENU ENTRY_PLATFORM_FLAG1
#define ENTRY_APPLE_MENU ENTRY_PLATFORM_FLAG2
#define ENTRY_WINDOWS_MENU ENTRY_PLATFORM_FLAG3
#define sl(s) ((int) (sizeof(s "") - 1))
#define SPECIALMENU(n, f) {.name = "." #n, .len = sl(#n) + 1, \
.flag = ENTRY_##f##_MENU }
static const struct {
const char *name; const size_t len; const int flag;
} specialMenus[] = {
SPECIALMENU(help, HELP),
SPECIALMENU(apple, APPLE),
SPECIALMENU(window, WINDOWS),
{NULL}
};
#undef SPECIALMENU
#define MODIFIER(n, f) {.name = #n, .len = sl(#n), .mask = f }
static const struct {
const char *name; const size_t len; const NSUInteger mask;
} modifiers[] = {
MODIFIER(Control, NSControlKeyMask),
MODIFIER(Ctrl, NSControlKeyMask),
MODIFIER(Option, NSAlternateKeyMask),
MODIFIER(Opt, NSAlternateKeyMask),
MODIFIER(Alt, NSAlternateKeyMask),
MODIFIER(Shift, NSShiftKeyMask),
MODIFIER(Command, NSCommandKeyMask),
MODIFIER(Cmd, NSCommandKeyMask),
MODIFIER(Meta, NSCommandKeyMask),
{NULL}
};
#undef MODIFIER
#define ACCEL(n, c) {.name = #n, .len = sl(#n), .ch = c }
static const struct {
const char *name; const size_t len; const UniChar ch;
} specialAccelerators[] = {
ACCEL(PageUp, NSPageUpFunctionKey),
ACCEL(PageDown, NSPageDownFunctionKey),
ACCEL(Left, NSLeftArrowFunctionKey),
ACCEL(Right, NSRightArrowFunctionKey),
ACCEL(Up, NSUpArrowFunctionKey),
ACCEL(Down, NSDownArrowFunctionKey),
ACCEL(Escape, 0x001b),
ACCEL(Clear, NSClearDisplayFunctionKey),
ACCEL(Enter, NSEnterCharacter),
ACCEL(Backspace, NSBackspaceCharacter),
ACCEL(Space, ' '),
ACCEL(Tab, NSTabCharacter),
ACCEL(BackTab, NSBackTabCharacter),
ACCEL(Delete, NSDeleteCharacter),
ACCEL(Home, NSHomeFunctionKey),
ACCEL(End, NSEndFunctionKey),
ACCEL(Return, NSCarriageReturnCharacter),
ACCEL(Help, NSHelpFunctionKey),
ACCEL(Power, 0x233d),
ACCEL(Eject, 0xf804),
{NULL}
};
#undef ACCEL
#undef sl
static int gNoTkMenus = 0; /* This is used by Tk_MacOSXTurnOffMenus as
* the flag that Tk is not to draw any
* menus. */
static int inPostMenu = 0;
static unsigned long defaultBg = 0, defaultFg = 0;
static SInt32 menuMarkColumnWidth = 0, menuIconTrailingEdgeMargin = 0;
static SInt32 menuTextLeadingEdgeMargin = 0, menuTextTrailingEdgeMargin = 0;
static SInt16 menuItemExtraHeight = 0, menuItemExtraWidth = 0;
static SInt16 menuSeparatorHeight = 0;
static void CheckForSpecialMenu(TkMenu *menuPtr);
static NSString *ParseAccelerator(const char *accel, NSUInteger *maskPtr);
static int GenerateMenuSelectEvent(TKMenu *menu, NSMenuItem *menuItem);
static void MenuSelectEvent(TkMenu *menuPtr);
static void RecursivelyClearActiveMenu(TkMenu *menuPtr);
static int ModifierCharWidth(Tk_Font tkfont);
#pragma mark TKMenu
@interface TKMenu(TKMenuPrivate)
- (id) initWithTkMenu: (TkMenu *) tkMenu;
- (TkMenu *) tkMenu;
- (int) tkIndexOfItem: (NSMenuItem *) menuItem;
- (void) insertItem: (NSMenuItem *) newItem atTkIndex: (NSInteger) index;
@end
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
#define TKMenu_NSMenuDelegate <NSMenuDelegate>
#else
#define TKMenu_NSMenuDelegate
#endif
@interface TKMenu(TKMenuDelegate) TKMenu_NSMenuDelegate
@end
@implementation TKMenu
- (void) setSpecial: (NSUInteger) special
{
NSAssert(!_tkSpecial, @"Cannot change specialness of a special menu");
_tkSpecial = special;
}
- (BOOL) isSpecial: (NSUInteger) special
{
return (_tkSpecial == special);
}
@end
@implementation TKMenu(TKMenuPrivate)
- (id) initWithTitle: (NSString *) aTitle
{
self = [super initWithTitle:aTitle];
if (self) {
_tkMenu = NULL;
_tkOffset = 0;
_tkItemCount = 0;
_tkSpecial = 0;
[self setDelegate:self];
}
return self;
}
- (id) initWithTkMenu: (TkMenu *) tkMenu
{
NSString *title = [[NSString alloc] initWithUTF8String:
Tk_PathName(tkMenu->tkwin)];
self = [self initWithTitle:title];
[title release];
if (self) {
_tkMenu = tkMenu;
}
return self;
}
- (id) copyWithZone: (NSZone *) zone
{
TKMenu *copy = [super copyWithZone:zone];
NSAssert(_tkMenu == nil, @"Cannot copy tkMenu");
copy->_tkMenu = _tkMenu;
copy->_tkOffset = _tkOffset;
copy->_tkItemCount = _tkItemCount;
copy->_tkSpecial = _tkSpecial;
return copy;
}
- (TkMenu *) tkMenu
{
return _tkMenu;
}
- (int) tkIndexOfItem: (NSMenuItem *) menuItem
{
return [self indexOfItem:menuItem] - _tkOffset;
}
- (void) insertItem: (NSMenuItem *) newItem atTkIndex: (NSInteger) index
{
[super insertItem:newItem atIndex:index + _tkOffset];
_tkItemCount++;
}
- (void) insertItem: (NSMenuItem *) newItem atIndex: (NSInteger) index
{
if (_tkMenu && index >= 0) {
if ((NSUInteger)index <= _tkOffset) {
_tkOffset++;
} else {
NSAssert((NSUInteger)index >= _tkItemCount + _tkOffset,
@"Cannot insert in the middle of Tk menu");
}
}
[super insertItem:newItem atIndex:index];
}
- (void) removeItemAtIndex: (NSInteger) index
{
if (_tkMenu && index >= 0) {
if ((NSUInteger)index < _tkOffset) {
_tkOffset--;
} else if ((NSUInteger)index < _tkItemCount + _tkOffset) {
_tkItemCount--;
}
}
[super removeItemAtIndex:index];
}
- (NSMenuItem *) newTkMenuItem: (TkMenuEntry *) mePtr
{
NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:@""
action:@selector(tkMenuItemInvoke:) keyEquivalent:@""];
[menuItem setTarget:self];
[menuItem setTag:(NSInteger)mePtr];
return menuItem;
}
@end
@implementation TKMenu(TKMenuActions)
// target methods
- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
{
return [menuItem isEnabled];
}
- (void) tkMenuItemInvoke: (id) sender
{
/*
* With the delegate matching key equivalents, when a menu action is sent
* in response to a key equivalent, sender is the whole menu and not the
* the specific menu item, use this to ignore key equivalents for our
* menus (as Tk handles them directly via bindings).
*/
if ([sender isKindOfClass:[NSMenuItem class]]) {
NSMenuItem *menuItem = (NSMenuItem *)sender;
TkMenu *menuPtr = (TkMenu *)_tkMenu;
TkMenuEntry *mePtr = (TkMenuEntry *)[menuItem tag];
if (menuPtr && mePtr) {
Tcl_Interp *interp = menuPtr->interp;
/*Add time for errors to fire if necessary. This is sub-optimal but avoids issues with Tcl/Cocoa event loop integration.*/
Tcl_Sleep(100);
Tcl_Preserve(interp);
Tcl_Preserve(menuPtr);
int result = TkInvokeMenu(interp, menuPtr, mePtr->index);
if (result != TCL_OK && result != TCL_CONTINUE &&
result != TCL_BREAK) {
Tcl_AddErrorInfo(interp, "\n (menu invoke)");
Tcl_BackgroundException(interp, result);
}
Tcl_Release(menuPtr);
Tcl_Release(interp);
}
}
}
@end
@implementation TKMenu(TKMenuDelegate)
#define keyEquivModifiersMatch(km, m) (( \
((km) & NSCommandKeyMask) != ((m) & NSCommandKeyMask) || \
((km) & NSAlternateKeyMask) != ((m) & NSAlternateKeyMask) || \
((km) & NSControlKeyMask) != ((m) & NSControlKeyMask) || \
(((km) & NSShiftKeyMask) != ((m) & NSShiftKeyMask) && \
((m) & NSFunctionKeyMask))) ? NO : YES)
- (BOOL) menuHasKeyEquivalent: (NSMenu *) menu forEvent: (NSEvent *) event
target: (id *) target action: (SEL *) action
{
/*Use lowercaseString to keep "shift" from firing twice if bound to different procedure.*/
NSString *key = [[event charactersIgnoringModifiers] lowercaseString];
NSUInteger modifiers = [event modifierFlags] &
NSDeviceIndependentModifierFlagsMask;
if (modifiers == (NSCommandKeyMask | NSShiftKeyMask) &&
[key compare:@"?"] == NSOrderedSame) {
return NO;
}
// For command key, take input manager's word so things
// like dvorak / qwerty layout work.
if (([event modifierFlags] & NSCommandKeyMask) == NSCommandKeyMask) {
key = [event characters];
}
NSArray *itemArray = [self itemArray];
for (NSMenuItem *item in itemArray) {
if ([item isEnabled] && [[item keyEquivalent] compare:key] ==
NSOrderedSame) {
NSUInteger keyEquivModifiers = [item keyEquivalentModifierMask];
if (keyEquivModifiersMatch(keyEquivModifiers, modifiers)) {
*target = [item target];
*action = [item action];
return YES;
}
}
}
return NO;
}
- (void) menuWillOpen: (NSMenu *) menu
{
if (_tkMenu) {
//RecursivelyClearActiveMenu(_tkMenu);
GenerateMenuSelectEvent((TKMenu *)[self supermenu],
[self itemInSupermenu]);
}
}
- (void) menuDidClose: (NSMenu *) menu
{
if (_tkMenu) {
RecursivelyClearActiveMenu(_tkMenu);
}
}
- (void) menu: (NSMenu *) menu willHighlightItem: (NSMenuItem *) item
{
if (_tkMenu) {
GenerateMenuSelectEvent(self, item);
}
}
- (void) menuNeedsUpdate: (NSMenu *) menu
{
TkMenu *menuPtr = (TkMenu *) _tkMenu;
if (menuPtr) {
Tcl_Interp *interp = menuPtr->interp;
Tcl_Preserve(interp);
Tcl_Preserve(menuPtr);
int result = TkPostCommand(_tkMenu);
if (result!=TCL_OK && result!=TCL_CONTINUE && result!=TCL_BREAK) {
Tcl_AddErrorInfo(interp, "\n (menu preprocess)");
Tcl_BackgroundException(interp, result);
}
Tcl_Release(menuPtr);
Tcl_Release(interp);
}
}
@end
#pragma mark TKApplication(TKMenu)
@interface NSApplication(TKMenu)
- (void) setAppleMenu: (NSMenu *) menu;
@end
@implementation TKApplication(TKMenu)
- (void) menuBeginTracking: (NSNotification *) notification
{
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
//TkMacOSXClearMenubarActive();
//TkMacOSXPreprocessMenu();
}
- (void) menuEndTracking: (NSNotification *) notification
{
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
if (!inPostMenu) {
TkMacOSXClearMenubarActive();
}
}
- (void) tkSetMainMenu: (TKMenu *) menu
{
if (gNoTkMenus) {
return;
}
TKMenu *applicationMenu = nil;
if (menu) {
NSMenuItem *applicationMenuItem = [menu numberOfItems] ?
[menu itemAtIndex:0] : nil;
if (![menu isSpecial:tkMainMenu]) {
TkMenuEntry *mePtr = (TkMenuEntry *)[applicationMenuItem tag];
if (!mePtr || !(mePtr->entryFlags & ENTRY_APPLE_MENU)) {
applicationMenuItem = [NSMenuItem itemWithSubmenu:
[[_defaultApplicationMenu copy] autorelease]];
[menu insertItem:applicationMenuItem atIndex:0];
}
[menu setSpecial:tkMainMenu];
}
applicationMenu = (TKMenu *)[applicationMenuItem submenu];
if (![applicationMenu isSpecial:tkApplicationMenu]) {
for (NSMenuItem *item in _defaultApplicationMenuItems) {
[applicationMenu addItem:[[item copy] autorelease]];
}
[applicationMenu setSpecial:tkApplicationMenu];
}
NSArray *itemArray = [menu itemArray];
for (NSMenuItem *item in itemArray) {
TkMenuEntry *mePtr = (TkMenuEntry *)[item tag];
TKMenu *submenu = (TKMenu *)[item submenu];
if (mePtr && submenu) {
if ((mePtr->entryFlags & ENTRY_WINDOWS_MENU) &&
![submenu isSpecial:tkWindowsMenu]) {
NSInteger index = 0;
for (NSMenuItem *i in _defaultWindowsMenuItems) {
[submenu insertItem:[[i copy] autorelease] atIndex:
index++];
}
[self setWindowsMenu:submenu];
[submenu setSpecial:tkWindowsMenu];
} else if ((mePtr->entryFlags & ENTRY_HELP_MENU) &&
![submenu isSpecial:tkHelpMenu]) {
NSInteger index = 0;
for (NSMenuItem *i in _defaultHelpMenuItems) {
[submenu insertItem:[[i copy] autorelease] atIndex:
index++];
}
[submenu setSpecial:tkHelpMenu];
}
}
}
} else {
menu = _defaultMainMenu;
applicationMenu = _defaultApplicationMenu;
}
NSMenuItem *servicesMenuItem =
[applicationMenu itemWithTitle:@"Services"];
if (servicesMenuItem && [servicesMenuItem submenu] != _servicesMenu) {
[[_servicesMenu itemInSupermenu] setSubmenu:nil];
[servicesMenuItem setSubmenu:_servicesMenu];
}
[self setAppleMenu:applicationMenu];
[self setMainMenu:menu];
}
@end
#pragma mark -
/*
*----------------------------------------------------------------------
*
* TkpNewMenu --
*
* Gets a new blank menu. Only the platform specific options are filled
* in.
*
* Results:
* Returns a standard Tcl error.
*
* Side effects:
* Allocates a NSMenu and puts it into the platformData field of the
* menuPtr.
*
*----------------------------------------------------------------------
*/
int
TkpNewMenu(
TkMenu *menuPtr) /* The common structure we are making the
* platform structure for. */
{
TKMenu *menu = [[TKMenu alloc] initWithTkMenu:menuPtr];
menuPtr->platformData = (TkMenuPlatformData)
TkMacOSXMakeUncollectable(menu);
CheckForSpecialMenu(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 */
{
TkMacOSXMakeCollectableAndRelease(menuPtr->platformData);
}
/*
*----------------------------------------------------------------------
*
* 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.
*
* 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 */
{
TKMenu *menu = (TKMenu *) mePtr->menuPtr->platformData;
NSMenuItem *menuItem;
if (mePtr->type == SEPARATOR_ENTRY || mePtr->type == TEAROFF_ENTRY) {
menuItem = [[NSMenuItem separatorItem] retain];
} else {
menuItem = [menu newTkMenuItem:mePtr];
}
mePtr->platformEntryData = (TkMenuPlatformEntryData)
TkMacOSXMakeUncollectable(menuItem);
/*
* Caller TkMenuEntry() already did this same insertion into the generic
* TkMenu so we just match it for the platform menu.
*/
[menu insertItem:menuItem atTkIndex:mePtr->index];
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TkpConfigureMenuEntry --
*
* Processes configurations for menu entries.
*
* Results:
* Returns standard TCL result. If TCL_ERROR is returned, then the
* interp's result contains an error message.
*
* Side effects:
* Configuration information get set for mePtr; old resources get freed,
* if any need it.
*
*----------------------------------------------------------------------
*/
int
TkpConfigureMenuEntry(
TkMenuEntry *mePtr) /* Information about menu entry; may or may
* not already have values for some fields. */
{
NSMenuItem *menuItem = (NSMenuItem *) mePtr->platformEntryData;
NSString *title = @"";
NSAttributedString *attributedTitle = nil;
NSImage *image = nil;
NSString *keyEquivalent = @"";
NSUInteger modifierMask = NSCommandKeyMask;
NSMenu *submenu = nil;
NSDictionary *attributes;
int imageWidth, imageHeight;
GC gc = (mePtr->textGC ? mePtr->textGC : mePtr->menuPtr->textGC);
Tcl_Obj *fontPtr = (mePtr->fontPtr ? mePtr->fontPtr :
mePtr->menuPtr->fontPtr);
if (mePtr->image) {
Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);
image = TkMacOSXGetNSImageWithTkImage(mePtr->menuPtr->display,
mePtr->image, imageWidth, imageHeight);
} else if (mePtr->bitmapPtr != None) {
Pixmap bitmap = Tk_GetBitmapFromObj(mePtr->menuPtr->tkwin,
mePtr->bitmapPtr);
Tk_SizeOfBitmap(mePtr->menuPtr->display, bitmap, &imageWidth,
&imageHeight);
image = TkMacOSXGetNSImageWithBitmap(mePtr->menuPtr->display, bitmap,
gc, imageWidth, imageHeight);
}
[menuItem setImage:image];
if ((!image || mePtr->compound != COMPOUND_NONE) && mePtr->labelPtr &&
mePtr->labelLength) {
title = [[[NSString alloc] initWithBytes:Tcl_GetString(mePtr->labelPtr)
length:mePtr->labelLength encoding:NSUTF8StringEncoding]
autorelease];
if ([title hasSuffix:@"..."]) {
title = [NSString stringWithFormat:@"%@%C",
[title substringToIndex:[title length] - 3], 0x2026];
}
}
[menuItem setTitle:title];
if (strcmp(Tcl_GetString(fontPtr), "menu") || gc->foreground != defaultFg
|| gc->background != defaultBg) {
attributes = TkMacOSXNSFontAttributesForFont(Tk_GetFontFromObj(
mePtr->menuPtr->tkwin, fontPtr));
if (gc->foreground != defaultFg || gc->background != defaultBg) {
NSColor *color = TkMacOSXGetNSColor(gc,
gc->foreground!=defaultFg? gc->foreground:gc->background);
attributes = [[attributes mutableCopy] autorelease];
[(NSMutableDictionary *)attributes setObject:color
forKey:NSForegroundColorAttributeName];
}
if (attributes) {
attributedTitle = [[[NSAttributedString alloc]
initWithString:title attributes:attributes] autorelease];
}
}
[menuItem setAttributedTitle:attributedTitle];
[menuItem setEnabled:!(mePtr->state == ENTRY_DISABLED)];
[menuItem setState:((mePtr->type == CHECK_BUTTON_ENTRY ||
mePtr->type == RADIO_BUTTON_ENTRY) && mePtr->indicatorOn &&
(mePtr->entryFlags & ENTRY_SELECTED) ? NSOnState : NSOffState)];
if (mePtr->type != CASCADE_ENTRY && mePtr->accelPtr && mePtr->accelLength) {
keyEquivalent = ParseAccelerator(Tcl_GetString(mePtr->accelPtr),
&modifierMask);
}
[menuItem setKeyEquivalent:keyEquivalent];
[menuItem setKeyEquivalentModifierMask:modifierMask];
if (mePtr->type == CASCADE_ENTRY && mePtr->namePtr) {
TkMenuReferences *menuRefPtr;
menuRefPtr = TkFindMenuReferencesObj(mePtr->menuPtr->interp,
mePtr->namePtr);
if (menuRefPtr && menuRefPtr->menuPtr) {
CheckForSpecialMenu(menuRefPtr->menuPtr);
submenu = (TKMenu *) menuRefPtr->menuPtr->platformData;
if ([submenu supermenu] && [menuItem submenu] != submenu) {
/*
* This happens during a clone, where the parent menu is
* cloned before its children, so just ignore this temprary
* setting, it will be changed shortly (c.f. tkMenu.c
* CloneMenu())
*/
submenu = nil;
} else {
[submenu setTitle:title];
if ([menuItem isEnabled]) {
/* This menuItem might have been previously disabled (XXX:
track this), which would have disabled entries; we must
re-enable the entries here. */
int i = 0;
NSArray *itemArray = [submenu itemArray];
for (NSMenuItem *item in itemArray) {
TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i];
[item setEnabled: !(submePtr->state == ENTRY_DISABLED)];
i++;
}
}
}
}
}
[menuItem setSubmenu:submenu];
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TkpDestroyMenuEntry --
*
* Cleans up platform-specific menu entry items.
*
* Results:
* None
*
* Side effects:
* All platform-specific allocations are freed up.
*
*----------------------------------------------------------------------
*/
void
TkpDestroyMenuEntry(
TkMenuEntry *mePtr)
{
if (mePtr->platformEntryData && mePtr->menuPtr->platformData) {
TKMenu *menu = (TKMenu *) mePtr->menuPtr->platformData;
NSMenuItem *menuItem = (NSMenuItem *) mePtr->platformEntryData;
NSInteger index = [menu indexOfItem:menuItem];
if (index > -1) {
[menu removeItemAtIndex:index];
}
}
TkMacOSXMakeCollectableAndRelease(mePtr->platformEntryData);
}
/*
*----------------------------------------------------------------------
*
* 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 */
{
NSWindow *win = [NSApp keyWindow];
if (!win) {
return TCL_ERROR;
}
inPostMenu = 1;
int oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);
NSView *view = [win contentView];
NSRect frame = NSMakeRect(x + 9, tkMacOSXZeroScreenHeight - y - 9, 1, 1);
frame.origin = [view convertPoint:
[win convertScreenToBase:frame.origin] fromView:nil];
NSMenu *menu = (NSMenu *) menuPtr->platformData;
NSPopUpButtonCell *popUpButtonCell = [[NSPopUpButtonCell alloc]
initTextCell:@"" pullsDown:NO];
[popUpButtonCell setAltersStateOfSelectedItem:NO];
[popUpButtonCell setMenu:menu];
[popUpButtonCell selectItem:nil];
[popUpButtonCell performClickWithFrame:frame inView:view];
[popUpButtonCell release];
Tcl_SetServiceMode(oldMode);
inPostMenu = 0;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* 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 */
{
TkWindow *winPtr = (TkWindow *) tkwin;
if (winPtr->wmInfoPtr) {
winPtr->wmInfoPtr->menuPtr = menuPtr;
}
}
/*
*----------------------------------------------------------------------
*
* TkpSetMainMenubar --
*
* Puts the menu associated with a window into the menubar. Should only
* be called when the window is in front.
*
* Results:
* None.
*
* Side effects:
* The menubar is changed.
*
*----------------------------------------------------------------------
*/
void
TkpSetMainMenubar(
Tcl_Interp *interp, /* The interpreter of the application */
Tk_Window tkwin, /* The frame we are setting up */
const char *menuName) /* The name of the menu to put in front. If
* NULL, use the default menu bar. */
{
static Tcl_Interp *currentInterp = NULL;
TKMenu *menu = nil;
if (menuName) {
TkWindow *winPtr = (TkWindow *) tkwin;
if (winPtr->wmInfoPtr && winPtr->wmInfoPtr->menuPtr &&
winPtr->wmInfoPtr->menuPtr->masterMenuPtr &&
winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin &&
!strcmp(menuName, Tk_PathName(
winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin))) {
menu = (TKMenu *) winPtr->wmInfoPtr->menuPtr->platformData;
} else {
TkMenuReferences *menuRefPtr = TkFindMenuReferences(interp,
menuName);
if (menuRefPtr && menuRefPtr->menuPtr &&
menuRefPtr->menuPtr->platformData) {
menu = (TKMenu *) menuRefPtr->menuPtr->platformData;
}
}
}
if (menu || interp != currentInterp) {
[NSApp tkSetMainMenu:menu];
}
currentInterp = interp;
}
/*
*----------------------------------------------------------------------
*
* CheckForSpecialMenu --
*
* Given a menu, check to see whether or not it is a cascade in a menubar
* with one of the special names .apple, .help or .window If it is, the
* entry that points to this menu will be marked.
*
* Results:
* None.
*
* Side effects:
* Will set entryFlags appropriately.
*
*----------------------------------------------------------------------
*/
static void
CheckForSpecialMenu(
TkMenu *menuPtr) /* The menu we are checking */
{
if (!menuPtr->masterMenuPtr->tkwin) {
return;
}
for (TkMenuEntry *cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
cascadeEntryPtr;
cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
if (cascadeEntryPtr->menuPtr->menuType == MENUBAR
&& cascadeEntryPtr->menuPtr->masterMenuPtr->tkwin) {
TkMenu *masterMenuPtr = cascadeEntryPtr->menuPtr->masterMenuPtr;
int i = 0;
Tcl_DString ds;
Tcl_DStringInit(&ds);
Tcl_DStringAppend(&ds, Tk_PathName(masterMenuPtr->tkwin), -1);
while (specialMenus[i].name) {
Tcl_DStringAppend(&ds, specialMenus[i].name,
specialMenus[i].len);
if (strcmp(Tcl_DStringValue(&ds),
Tk_PathName(menuPtr->masterMenuPtr->tkwin)) == 0) {
cascadeEntryPtr->entryFlags |= specialMenus[i].flag;
} else {
cascadeEntryPtr->entryFlags &= ~specialMenus[i].flag;
}
Tcl_DStringSetLength(&ds, Tcl_DStringLength(&ds) -
specialMenus[i].len);
i++;
}
Tcl_DStringFree(&ds);
}
}
}
/*
*----------------------------------------------------------------------
*
* ParseAccelerator --
*
* Parse accelerator string.
*
* Results:
* Accelerator string & flags.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static NSString *
ParseAccelerator(
const char *accel,
NSUInteger *maskPtr)
{
unichar ch = 0;
size_t len;
int i;
*maskPtr = 0;
while (1) {
i = 0;
while (modifiers[i].name) {
int l = modifiers[i].len;
if (!strncasecmp(accel, modifiers[i].name, l) &&
(accel[l] == '-' || accel[l] == '+')) {
*maskPtr |= modifiers[i].mask;
accel += l+1;
break;
}
i++;
}
if (!modifiers[i].name || !*accel) {
break;
}
}
len = strlen(accel);
if (len > 1) {
i = 0;
if (accel[0] == 'F' && len < 4 && accel[1] > '0' && accel[1] <= '9') {
int fkey = accel[1] - '0';
if (len == 3) {
if (accel[2] >= '0' && accel[2] <= '9') {
fkey = 10 * fkey + (accel[2] - '0');
} else {
fkey = 0;
}
}
if (fkey >= 1 && fkey <= 15) {
ch = NSF1FunctionKey + fkey - 1;
}
} else while (specialAccelerators[i].name) {
if (accel[0] == specialAccelerators[i].name[0] &&
len == specialAccelerators[i].len && !strncasecmp(accel,
specialAccelerators[i].name, specialAccelerators[i].len)) {
ch = specialAccelerators[i].ch;
break;
}
i++;
}
}
if (ch) {
return [[[NSString alloc] initWithCharacters:&ch length:1] autorelease];
} else {
return [[[[NSString alloc] initWithUTF8String:accel] autorelease]
lowercaseString];
}
}
/*
*--------------------------------------------------------------
*
* ModifierCharWidth --
*
* Helper mesuring width of command char in given font.
*
* Results:
* Width of command char.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
static int
ModifierCharWidth(
Tk_Font tkfont)
{
static NSString *cmdChar = nil;
if (!cmdChar) {
unichar cmd = kCommandUnicode;
cmdChar = [[NSString alloc] initWithCharacters:&cmd length:1];
}
return [cmdChar sizeWithAttributes:
TkMacOSXNSFontAttributesForFont(tkfont)].width;
}
/*
*--------------------------------------------------------------
*
* 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 modifierCharWidth, menuModifierCharWidth;
int x, y, modifierWidth, labelWidth, indicatorSpace;
int windowWidth, windowHeight, accelWidth;
int i, j, lastColumnBreak, maxWidth;
int entryWidth, maxIndicatorSpace, borderWidth, activeBorderWidth;
TkMenuEntry *mePtr, *columnEntryPtr;
int haveAccel = 0;
if (menuPtr->tkwin == NULL) {
return;
}
Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
&borderWidth);
Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,
&activeBorderWidth);
x = y = borderWidth;
windowHeight = maxWidth = lastColumnBreak = 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);
menuModifierCharWidth = ModifierCharWidth(menuFont);
for (i = 0; i < menuPtr->numEntries; i++) {
mePtr = menuPtr->entries[i];
if (mePtr->type == CASCADE_ENTRY || mePtr->accelLength > 0) {
haveAccel = 1;
break;
}
}
for (i = 0; i < menuPtr->numEntries; i++) {
mePtr = menuPtr->entries[i];
if (mePtr->fontPtr == NULL) {
tkfont = menuFont;
fmPtr = &menuMetrics;
modifierCharWidth = menuModifierCharWidth;
} else {
tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
Tk_GetFontMetrics(tkfont, &entryMetrics);
fmPtr = &entryMetrics;
modifierCharWidth = ModifierCharWidth(tkfont);
}
if ((i > 0) && mePtr->columnBreak) {
if (maxIndicatorSpace != 0) {
maxIndicatorSpace += 2;
}
for (j = lastColumnBreak; j < i; j++) {
columnEntryPtr = menuPtr->entries[j];
columnEntryPtr->indicatorSpace = maxIndicatorSpace;
columnEntryPtr->width = maxIndicatorSpace + maxWidth
+ 2 * activeBorderWidth;
columnEntryPtr->x = x;
columnEntryPtr->entryFlags &= ~ENTRY_LAST_COLUMN;
}
x += maxIndicatorSpace + maxWidth + 2 * borderWidth;
maxWidth = maxIndicatorSpace = 0;
lastColumnBreak = i;
y = borderWidth;
}
accelWidth = modifierWidth = indicatorSpace = 0;
if (mePtr->type == SEPARATOR_ENTRY || mePtr->type == TEAROFF_ENTRY) {
mePtr->height = menuSeparatorHeight;
} 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.
*/
NSMenuItem *menuItem = (NSMenuItem *) mePtr->platformEntryData;
int haveImage = 0, width = 0, height = 0;
if (mePtr->image) {
Tk_SizeOfImage(mePtr->image, &width, &height);
haveImage = 1;
} else if (mePtr->bitmapPtr) {
Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin,
mePtr->bitmapPtr);
Tk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height);
haveImage = 1;
}
if (!haveImage || (mePtr->compound != COMPOUND_NONE)) {
NSAttributedString *attrTitle = [menuItem attributedTitle];
NSSize size;
if (attrTitle) {
size = [attrTitle size];
} else {
size = [[menuItem title] sizeWithAttributes:
TkMacOSXNSFontAttributesForFont(tkfont)];
}
size.width += menuTextLeadingEdgeMargin +
menuTextTrailingEdgeMargin;
if (size.height < fmPtr->linespace) {
size.height = fmPtr->linespace;
}
if (haveImage && (mePtr->compound != COMPOUND_NONE)) {
int margin = width + menuIconTrailingEdgeMargin;
if (margin > menuTextLeadingEdgeMargin) {
margin = menuTextLeadingEdgeMargin;
}
width += size.width + menuIconTrailingEdgeMargin - margin;
if (size.height > height) {
height = size.height;
}
} else {
width = size.width;
height = size.height;
}
}
labelWidth = width + menuItemExtraWidth;
mePtr->height = height + menuItemExtraHeight;
if (mePtr->type == CASCADE_ENTRY) {
modifierWidth = modifierCharWidth;
} else if (mePtr->accelLength == 0) {
if (haveAccel && !mePtr->hideMargin) {
modifierWidth = modifierCharWidth;
}
} else {
NSUInteger modifMask = [menuItem keyEquivalentModifierMask];
int i = 0;
while (modifiers[i].name) {
if (modifMask & modifiers[i].mask) {
modifMask &= ~modifiers[i].mask;
modifierWidth += modifierCharWidth;
}
i++;
}
accelWidth = [[menuItem keyEquivalent] sizeWithAttributes:
TkMacOSXNSFontAttributesForFont(tkfont)].width;
}
if (!mePtr->hideMargin) {
indicatorSpace = menuMarkColumnWidth;
}
if (indicatorSpace > maxIndicatorSpace) {
maxIndicatorSpace = indicatorSpace;
}
entryWidth = labelWidth + modifierWidth + accelWidth;
if (entryWidth > maxWidth) {
maxWidth = 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];
columnEntryPtr->indicatorSpace = maxIndicatorSpace;
columnEntryPtr->width = maxIndicatorSpace + maxWidth
+ 2 * activeBorderWidth;
columnEntryPtr->x = x;
columnEntryPtr->entryFlags |= ENTRY_LAST_COLUMN;
}
windowWidth = x + maxIndicatorSpace + maxWidth
+ 2 * activeBorderWidth + borderWidth;
windowHeight += borderWidth;
if (windowWidth <= 0) {
windowWidth = 1;
}
if (windowHeight <= 0) {
windowHeight = 1;
}
menuPtr->totalWidth = windowWidth;
menuPtr->totalHeight = windowHeight;
}
/*
*----------------------------------------------------------------------
*
* GenerateMenuSelectEvent --
*
* Respond to a menu item being selected.
*
* Results:
* True if event(s) are generated - false otherwise.
*
* Side effects:
* Places a virtual event on the event queue.
*
*----------------------------------------------------------------------
*/
int
GenerateMenuSelectEvent(
TKMenu *menu,
NSMenuItem *menuItem)
{
TkMenu *menuPtr = [menu tkMenu];
if (menuPtr) {
int index = [menu tkIndexOfItem:menuItem];
if (index < 0 || index >= menuPtr->numEntries ||
(menuPtr->entries[index])->state == ENTRY_DISABLED) {
TkActivateMenuEntry(menuPtr, -1);
} else {
TkActivateMenuEntry(menuPtr, index);
MenuSelectEvent(menuPtr);
return true;
}
}
return false;
}
/*
*----------------------------------------------------------------------
*
* MenuSelectEvent --
*
* Generates a "MenuSelect" virtual event. This can be used to do
* context-sensitive menu help.
*
* Results:
* None.
*
* Side effects:
* Places a virtual event on the event queue.
*
*----------------------------------------------------------------------
*/
void
MenuSelectEvent(
TkMenu *menuPtr) /* the menu we have selected. */
{
XVirtualEvent event;
bzero(&event, sizeof(XVirtualEvent));
event.type = VirtualEvent;
event.serial = LastKnownRequestProcessed(menuPtr->display);
event.send_event = false;
event.display = menuPtr->display;
event.event = Tk_WindowId(menuPtr->tkwin);
event.root = XRootWindow(menuPtr->display, 0);
event.subwindow = None;
event.time = TkpGetMS();
XQueryPointer(NULL, None, NULL, NULL, &event.x_root, &event.y_root, NULL,
NULL, &event.state);
event.same_screen = true;
event.name = Tk_GetUid("MenuSelect");
Tk_MakeWindowExist(menuPtr->tkwin);
if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
Tk_HandleEvent((XEvent *) &event);
} else {
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;
TkActivateMenuEntry(menuPtr, -1);
for (i = 0; i < menuPtr->numEntries; i++) {
TkMenuEntry *mePtr = menuPtr->entries[i];
if (mePtr->type == CASCADE_ENTRY
&& (mePtr->childMenuRefPtr != NULL)
&& (mePtr->childMenuRefPtr->menuPtr != NULL)) {
RecursivelyClearActiveMenu(mePtr->childMenuRefPtr->menuPtr);
}
}
}
/*
*----------------------------------------------------------------------
*
* TkMacOSXClearMenubarActive --
*
* Recursively clears the active entry in the current menubar hierarchy.
*
* Results:
* None.
*
* Side effects:
* Generates <<MenuSelect>> virtual events.
*
*----------------------------------------------------------------------
*/
void
TkMacOSXClearMenubarActive(void)
{
NSMenu *mainMenu = [NSApp mainMenu];
if (mainMenu && [mainMenu isKindOfClass:[TKMenu class]]) {
TkMenu *menuPtr = [(TKMenu *) mainMenu tkMenu];
if (menuPtr && menuPtr->numEntries && menuPtr->entries) {
RecursivelyClearActiveMenu(menuPtr);
}
}
}
/*
*----------------------------------------------------------------------
*
* Tk_MacOSXTurnOffMenus --
*
* Turns off all the menu drawing code. This is more than just disabling
* the "menu" command, this means that Tk will NEVER touch the menubar.
* It is needed in the Plugin, where Tk does not own the menubar.
*
* Results:
* None.
*
* Side effects:
* A flag is set which will disable all menu drawing.
*
*----------------------------------------------------------------------
*/
void
Tk_MacOSXTurnOffMenus(void)
{
gNoTkMenus = 1;
}
/*
*----------------------------------------------------------------------
*
* TkpMenuInit --
*
* Initializes Mac-specific menu data.
*
* Results:
* None.
*
* Side effects:
* Allocates a hash table.
*
*----------------------------------------------------------------------
*/
void
TkpMenuInit(void)
{
TkColor *tkColPtr;
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
#define observe(n, s) \
[nc addObserver:NSApp selector:@selector(s) name:(n) object:nil]
observe(NSMenuDidBeginTrackingNotification, menuBeginTracking:);
observe(NSMenuDidEndTrackingNotification, menuEndTracking:);
#undef observe
[NSMenuItem setUsesUserKeyEquivalents:NO];
tkColPtr = TkpGetColor(None, DEF_MENU_BG_COLOR);
defaultBg = tkColPtr->color.pixel;
ckfree(tkColPtr);
tkColPtr = TkpGetColor(None, DEF_MENU_FG);
defaultFg = tkColPtr->color.pixel;
ckfree(tkColPtr);
ChkErr(GetThemeMetric, kThemeMetricMenuMarkColumnWidth,
&menuMarkColumnWidth);
ChkErr(GetThemeMetric, kThemeMetricMenuTextLeadingEdgeMargin,
&menuTextLeadingEdgeMargin);
ChkErr(GetThemeMetric, kThemeMetricMenuTextTrailingEdgeMargin,
&menuTextTrailingEdgeMargin);
ChkErr(GetThemeMetric, kThemeMetricMenuIconTrailingEdgeMargin,
&menuIconTrailingEdgeMargin);
ChkErr(GetThemeMenuItemExtra, kThemeMenuItemPlain, &menuItemExtraHeight,
&menuItemExtraWidth);
ChkErr(GetThemeMenuSeparatorHeight, &menuSeparatorHeight);
}
#pragma mark -
#pragma mark NOPs
/*
*----------------------------------------------------------------------
*
* TkpMenuThreadInit --
*
* Does platform-specific initialization of thread-specific menu state.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
TkpMenuThreadInit(void)
{
/*
* Nothing to do.
*/
}
/*
*----------------------------------------------------------------------
*
* TkpMenuNotifyToplevelCreate --
*
* This routine reconfigures the menu and the clones indicated by
* menuName because a toplevel has been created and any system menus need
* to be created. Only applicable to Windows.
*
* Results:
* None.
*
* Side effects:
* An idle handler is set up to do the reconfiguration.
*
*----------------------------------------------------------------------
*/
void
TkpMenuNotifyToplevelCreate(
Tcl_Interp *interp, /* The interp the menu lives in. */
const char *menuName) /* The name of the menu to reconfigure. */
{
/*
* Nothing to do.
*/
}
/*
*--------------------------------------------------------------
*
* TkpInitializeMenuBindings --
*
* For every interp, initializes the bindings for Windows menus. Does
* nothing on Mac or XWindows.
*
* Results:
* None.
*
* Side effects:
* C-level bindings are setup for the interp which will handle Alt-key
* sequences for menus without beeping or interfering with user-defined
* Alt-key bindings.
*
*--------------------------------------------------------------
*/
void
TkpInitializeMenuBindings(
Tcl_Interp *interp, /* The interpreter to set. */
Tk_BindingTable bindingTable)
/* The table to add to. */
{
/*
* Nothing to do.
*/
}
/*
*--------------------------------------------------------------
*
* TkpComputeMenubarGeometry --
*
* This procedure is invoked to recompute the size and layout of a menu
* that is a menubar clone.
*
* Results:
* None.
*
* Side effects:
* Fields of menu entries are changed to reflect their current positions,
* and the size of the menu window itself may be changed.
*
*--------------------------------------------------------------
*/
void
TkpComputeMenubarGeometry(
TkMenu *menuPtr) /* Structure describing menu. */
{
TkpComputeStandardMenuGeometry(menuPtr);
}
/*
*----------------------------------------------------------------------
*
* 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. */
{
}
#pragma mark Obsolete
/*
*----------------------------------------------------------------------
*
* TkMacOSXPreprocessMenu --
*
* Handle preprocessing of menubar if it exists.
*
* Results:
* None.
*
* Side effects:
* All post commands for the current menubar get executed.
*
*----------------------------------------------------------------------
*/
void
TkMacOSXPreprocessMenu(void)
{
}
/*
*----------------------------------------------------------------------
*
* TkMacOSXUseID --
*
* Take the ID out of the available list for new menus. Used by the
* default menu bar's menus so that they do not get created at the tk
* level. See TkMacOSXGetNewMenuID for more information.
*
* Results:
* Returns TCL_OK if the id was not in use. Returns TCL_ERROR if the id
* was in use.
*
* Side effects:
* A hash table entry in the command table is created with a NULL value.
*
*----------------------------------------------------------------------
*/
int
TkMacOSXUseMenuID(
short macID) /* The id to take out of the table */
{
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TkMacOSXDispatchMenuEvent --
*
* Given a menu id and an item, dispatches the command associated with
* it.
*
* Results:
* None.
*
* Side effects:
* Commands for the event are scheduled for execution at idle time.
*
*----------------------------------------------------------------------
*/
int
TkMacOSXDispatchMenuEvent(
int menuID, /* The menu id of the menu we are invoking */
int index) /* The one-based index of the item that was
* selected. */
{
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* TkMacOSXHandleTearoffMenu() --
*
* This routine sees if the MDEF has set a menu and a mouse position for
* tearing off and makes a tearoff menu if it has.
*
* Results:
* menuPtr->interp will have the result of the tearoff command.
*
* Side effects:
* A new tearoff menu is created if it is supposed to be.
*
*----------------------------------------------------------------------
*/
void
TkMacOSXHandleTearoffMenu(void)
{
/*
* Obsolete: Nothing to do.
*/
}
/*
*----------------------------------------------------------------------
*
* TkMacOSXSetHelpMenuItemCount --
*
* Has to be called after the first call to InsertMenu. Sets up the
* global variable for the number of items in the unmodified help menu.
* NB. Nobody uses this any more, since you can get the number of system
* help items from HMGetHelpMenu trivially. But it is in the stubs
* table...
*
* Results:
* None.
*
* Side effects:
* Nothing.
*
*----------------------------------------------------------------------
*/
void
TkMacOSXSetHelpMenuItemCount(void)
{
}
/*
*----------------------------------------------------------------------
*
* TkMacOSXMenuClick --
*
* Prepares a menubar for MenuSelect or MenuKey.
*
* Results:
* None.
*
* Side effects:
* Any pending configurations of the menubar are completed.
*
*----------------------------------------------------------------------
*/
void
TkMacOSXMenuClick(void)
{
}
/*
* Local Variables:
* mode: objc
* c-basic-offset: 4
* fill-column: 79
* coding: utf-8
* End:
*/
Jump to Line
Something went wrong with that request. Please try again.