Use menu descriptors instead of tags to locate menu items

This commit is contained in:
Bjorn Winckler
2008-05-31 21:47:30 +02:00
parent fdc64858c5
commit a588fc3e33
5 changed files with 414 additions and 239 deletions
+1 -9
View File
@@ -57,6 +57,7 @@
- (NSConnection *)connection;
- (NSDictionary *)actionDict;
- (void)queueMessage:(int)msgid properties:(NSDictionary *)props;
- (BOOL)checkin;
- (BOOL)openVimWindow;
- (void)clearAll;
@@ -84,15 +85,6 @@
saving:(int)saving;
- (int)presentDialogWithType:(int)type title:(char *)title message:(char *)msg
buttons:(char *)btns textField:(char *)txtfield;
- (void)addMenuWithTag:(int)tag parent:(int)parentTag name:(char *)name
atIndex:(int)index;
- (void)addMenuItemWithTag:(int)tag parent:(int)parentTag name:(char *)name
tip:(char *)tip icon:(char *)icon
keyEquivalent:(int)key modifiers:(int)mods
action:(char *)action isAlternate:(int)isAlt
atIndex:(int)index;
- (void)removeMenuItemWithTag:(int)tag;
- (void)enableMenuItemWithTag:(int)tag state:(int)enabled;
- (void)showPopupMenuWithName:(char *)name atMouseLocation:(BOOL)mouse;
- (void)showToolbar:(int)enable flags:(int)flags;
- (void)createScrollbarWithIdentifier:(long)ident type:(int)type;
+16 -163
View File
@@ -51,10 +51,12 @@ static unsigned MMServerMax = 1000;
// TODO: Move to separate file.
static int eventModifierFlagsToVimModMask(int modifierFlags);
static int vimModMaskToEventModifierFlags(int mods);
static int eventModifierFlagsToVimMouseModMask(int modifierFlags);
static int eventButtonNumberToVimMouseButton(int buttonNumber);
static int specialKeyToNSKey(int key);
// In gui_macvim.m
vimmenu_T *menu_for_descriptor(NSArray *desc);
enum {
MMBlinkStateNone = 0,
@@ -76,6 +78,7 @@ static NSString *MMSymlinkWarningString =
@interface MMBackend (Private)
- (void)queueVimStateMessage;
- (void)processInputQueue;
@@ -226,6 +229,11 @@ static NSString *MMSymlinkWarningString =
return actionDict;
}
- (void)queueMessage:(int)msgid properties:(NSDictionary *)props
{
[self queueMessage:msgid data:[props dictionaryAsData]];
}
- (BOOL)checkin
{
if (![self connection]) {
@@ -740,78 +748,6 @@ static NSString *MMSymlinkWarningString =
return retval;
}
- (void)addMenuWithTag:(int)tag parent:(int)parentTag name:(char *)name
atIndex:(int)index
{
//NSLog(@"addMenuWithTag:%d parent:%d name:%s atIndex:%d", tag, parentTag,
// name, index);
int namelen = name ? strlen(name) : 0;
NSMutableData *data = [NSMutableData data];
[data appendBytes:&tag length:sizeof(int)];
[data appendBytes:&parentTag length:sizeof(int)];
[data appendBytes:&namelen length:sizeof(int)];
if (namelen > 0) [data appendBytes:name length:namelen];
[data appendBytes:&index length:sizeof(int)];
[self queueMessage:AddMenuMsgID data:data];
}
- (void)addMenuItemWithTag:(int)tag parent:(int)parentTag name:(char *)name
tip:(char *)tip icon:(char *)icon
keyEquivalent:(int)key modifiers:(int)mods
action:(char *)action isAlternate:(int)isAlt
atIndex:(int)index
{
//NSLog(@"addMenuItemWithTag:%d parent:%d name:%s tip:%s atIndex:%d", tag,
// parentTag, name, tip, index);
int namelen = name ? strlen(name) : 0;
int tiplen = tip ? strlen(tip) : 0;
int iconlen = icon ? strlen(icon) : 0;
int eventFlags = vimModMaskToEventModifierFlags(mods);
int actionlen = action ? strlen(action) : 0;
NSMutableData *data = [NSMutableData data];
key = specialKeyToNSKey(key);
[data appendBytes:&tag length:sizeof(int)];
[data appendBytes:&parentTag length:sizeof(int)];
[data appendBytes:&namelen length:sizeof(int)];
if (namelen > 0) [data appendBytes:name length:namelen];
[data appendBytes:&tiplen length:sizeof(int)];
if (tiplen > 0) [data appendBytes:tip length:tiplen];
[data appendBytes:&iconlen length:sizeof(int)];
if (iconlen > 0) [data appendBytes:icon length:iconlen];
[data appendBytes:&actionlen length:sizeof(int)];
if (actionlen > 0) [data appendBytes:action length:actionlen];
[data appendBytes:&index length:sizeof(int)];
[data appendBytes:&key length:sizeof(int)];
[data appendBytes:&eventFlags length:sizeof(int)];
[data appendBytes:&isAlt length:sizeof(int)];
[self queueMessage:AddMenuItemMsgID data:data];
}
- (void)removeMenuItemWithTag:(int)tag
{
NSMutableData *data = [NSMutableData data];
[data appendBytes:&tag length:sizeof(int)];
[self queueMessage:RemoveMenuItemMsgID data:data];
}
- (void)enableMenuItemWithTag:(int)tag state:(int)enabled
{
NSMutableData *data = [NSMutableData data];
[data appendBytes:&tag length:sizeof(int)];
[data appendBytes:&enabled length:sizeof(int)];
[self queueMessage:EnableMenuItemMsgID data:data];
}
- (void)showPopupMenuWithName:(char *)name atMouseLocation:(BOOL)mouse
{
int len = strlen(name);
@@ -1659,14 +1595,12 @@ static NSString *MMSymlinkWarningString =
//NSLog(@"[VimTask] Resizing shell to %dx%d.", cols, rows);
gui_resize_shell(cols, rows);
} else if (ExecuteMenuMsgID == msgid) {
if (!data) return;
const void *bytes = [data bytes];
int tag = *((int*)bytes); bytes += sizeof(int);
vimmenu_T *menu = (vimmenu_T*)tag;
// TODO! Make sure 'menu' is a valid menu pointer!
if (menu) {
gui_menu_cb(menu);
NSDictionary *attrs = [NSDictionary dictionaryWithData:data];
if (attrs) {
NSArray *desc = [attrs objectForKey:@"descriptor"];
vimmenu_T *menu = menu_for_descriptor(desc);
if (menu)
gui_menu_cb(menu);
}
} else if (ToggleToolbarMsgID == msgid) {
[self handleToggleToolbar];
@@ -2475,22 +2409,6 @@ static int eventModifierFlagsToVimModMask(int modifierFlags)
return modMask;
}
static int vimModMaskToEventModifierFlags(int mods)
{
int flags = 0;
if (mods & MOD_MASK_SHIFT)
flags |= NSShiftKeyMask;
if (mods & MOD_MASK_CTRL)
flags |= NSControlKeyMask;
if (mods & MOD_MASK_ALT)
flags |= NSAlternateKeyMask;
if (mods & MOD_MASK_CMD)
flags |= NSCommandKeyMask;
return flags;
}
static int eventModifierFlagsToVimMouseModMask(int modifierFlags)
{
int modMask = 0;
@@ -2512,68 +2430,3 @@ static int eventButtonNumberToVimMouseButton(int buttonNumber)
return (buttonNumber >= 0 && buttonNumber < 3)
? mouseButton[buttonNumber] : -1;
}
static int specialKeyToNSKey(int key)
{
if (!IS_SPECIAL(key))
return key;
static struct {
int special;
int nskey;
} sp2ns[] = {
{ K_UP, NSUpArrowFunctionKey },
{ K_DOWN, NSDownArrowFunctionKey },
{ K_LEFT, NSLeftArrowFunctionKey },
{ K_RIGHT, NSRightArrowFunctionKey },
{ K_F1, NSF1FunctionKey },
{ K_F2, NSF2FunctionKey },
{ K_F3, NSF3FunctionKey },
{ K_F4, NSF4FunctionKey },
{ K_F5, NSF5FunctionKey },
{ K_F6, NSF6FunctionKey },
{ K_F7, NSF7FunctionKey },
{ K_F8, NSF8FunctionKey },
{ K_F9, NSF9FunctionKey },
{ K_F10, NSF10FunctionKey },
{ K_F11, NSF11FunctionKey },
{ K_F12, NSF12FunctionKey },
{ K_F13, NSF13FunctionKey },
{ K_F14, NSF14FunctionKey },
{ K_F15, NSF15FunctionKey },
{ K_F16, NSF16FunctionKey },
{ K_F17, NSF17FunctionKey },
{ K_F18, NSF18FunctionKey },
{ K_F19, NSF19FunctionKey },
{ K_F20, NSF20FunctionKey },
{ K_F21, NSF21FunctionKey },
{ K_F22, NSF22FunctionKey },
{ K_F23, NSF23FunctionKey },
{ K_F24, NSF24FunctionKey },
{ K_F25, NSF25FunctionKey },
{ K_F26, NSF26FunctionKey },
{ K_F27, NSF27FunctionKey },
{ K_F28, NSF28FunctionKey },
{ K_F29, NSF29FunctionKey },
{ K_F30, NSF30FunctionKey },
{ K_F31, NSF31FunctionKey },
{ K_F32, NSF32FunctionKey },
{ K_F33, NSF33FunctionKey },
{ K_F34, NSF34FunctionKey },
{ K_F35, NSF35FunctionKey },
{ K_DEL, NSBackspaceCharacter },
{ K_BS, NSDeleteCharacter },
{ K_HOME, NSHomeFunctionKey },
{ K_END, NSEndFunctionKey },
{ K_PAGEUP, NSPageUpFunctionKey },
{ K_PAGEDOWN, NSPageDownFunctionKey }
};
int i;
for (i = 0; i < sizeof(sp2ns)/sizeof(sp2ns[0]); ++i) {
if (sp2ns[i].special == key)
return sp2ns[i].nskey;
}
return 0;
}
+194 -21
View File
@@ -64,18 +64,21 @@ static NSTimeInterval MMResendInterval = 0.5;
- (NSMenuItem *)recurseMenuItemForTag:(int)tag rootMenu:(NSMenu *)root;
- (NSMenuItem *)menuItemForTag:(int)tag;
- (NSMenu *)menuForTag:(int)tag;
- (NSMenu *)parentMenuForDescriptor:(NSArray *)desc;
- (NSMenu *)topLevelMenuForTitle:(NSString *)title;
- (void)addMenuWithTag:(int)tag parent:(int)parentTag title:(NSString *)title
atIndex:(int)idx;
- (void)addMenuItemWithTag:(int)tag parent:(NSMenu *)parent
title:(NSString *)title tip:(NSString *)tip
keyEquivalent:(int)key modifiers:(int)mask
action:(NSString *)action isAlternate:(int)isAlt
atIndex:(int)idx;
- (void)addMenuWithDescriptor:(NSArray *)desc atIndex:(int)index;
- (void)addMenuItemWithDescriptor:(NSArray *)desc
atIndex:(int)index
tip:(NSString *)tip
icon:(NSString *)icon
keyEquivalent:(NSString *)keyEquivalent
modifierMask:(int)modifierMask
action:(NSString *)action
isAlternate:(BOOL)isAlternate;
- (NSToolbarItem *)toolbarItemForTag:(int)tag index:(int *)index;
- (void)addToolbarItemToDictionaryWithTag:(int)tag label:(NSString *)title
- (void)addToolbarItemToDictionaryWithLabel:(NSString *)title
toolTip:(NSString *)tip icon:(NSString *)icon;
- (void)addToolbarItemWithTag:(int)tag label:(NSString *)label
- (void)addToolbarItemWithLabel:(NSString *)label
tip:(NSString *)tip icon:(NSString *)icon
atIndex:(int)idx;
- (void)connectionDidDie:(NSNotification *)notification;
@@ -656,6 +659,7 @@ static NSTimeInterval MMResendInterval = 0.5;
[string release];
} else if (AddMenuMsgID == msgid) {
#if 0
NSString *title = nil;
const void *bytes = [data bytes];
int tag = *((int*)bytes); bytes += sizeof(int);
@@ -688,7 +692,13 @@ static NSTimeInterval MMResendInterval = 0.5;
}
[title release];
#else
NSDictionary *attrs = [NSDictionary dictionaryWithData:data];
[self addMenuWithDescriptor:[attrs objectForKey:@"descriptor"]
atIndex:[[attrs objectForKey:@"index"] intValue]];
#endif
} else if (AddMenuItemMsgID == msgid) {
#if 0
NSString *title = nil, *tip = nil, *icon = nil, *action = nil;
const void *bytes = [data bytes];
int tag = *((int*)bytes); bytes += sizeof(int);
@@ -740,7 +750,19 @@ static NSTimeInterval MMResendInterval = 0.5;
[tip release];
[icon release];
[action release];
#else
NSDictionary *attrs = [NSDictionary dictionaryWithData:data];
[self addMenuItemWithDescriptor:[attrs objectForKey:@"descriptor"]
atIndex:[[attrs objectForKey:@"index"] intValue]
tip:[attrs objectForKey:@"tip"]
icon:[attrs objectForKey:@"icon"]
keyEquivalent:[attrs objectForKey:@"keyEquivalent"]
modifierMask:[[attrs objectForKey:@"modifierMask"] intValue]
action:[attrs objectForKey:@"action"]
isAlternate:[[attrs objectForKey:@"isAlternate"] boolValue]];
#endif
} else if (RemoveMenuItemMsgID == msgid) {
#if 0
const void *bytes = [data bytes];
int tag = *((int*)bytes); bytes += sizeof(int);
@@ -767,7 +789,9 @@ static NSTimeInterval MMResendInterval = 0.5;
// Reset cached menu, just to be on the safe side.
lastMenuSearched = nil;
#endif
} else if (EnableMenuItemMsgID == msgid) {
#if 0
const void *bytes = [data bytes];
int tag = *((int*)bytes); bytes += sizeof(int);
int state = *((int*)bytes); bytes += sizeof(int);
@@ -777,6 +801,7 @@ static NSTimeInterval MMResendInterval = 0.5;
item = [self menuItemForTag:tag];
[item setEnabled:state];
#endif
} else if (ShowToolbarMsgID == msgid) {
const void *bytes = [data bytes];
int enable = *((int*)bytes); bytes += sizeof(int);
@@ -1052,6 +1077,36 @@ static NSTimeInterval MMResendInterval = 0.5;
return [[self menuItemForTag:tag] submenu];
}
- (NSMenu *)parentMenuForDescriptor:(NSArray *)desc
{
if (!(desc && [desc count] > 0)) return nil;
NSString *rootName = [desc objectAtIndex:0];
NSArray *rootItems = [rootName hasPrefix:@"PopUp"] ? popupMenuItems
: mainMenuItems;
NSMenu *menu = nil;
int i, count = [rootItems count];
for (i = 0; i < count; ++i) {
NSMenuItem *item = [rootItems objectAtIndex:i];
if ([[item title] isEqual:rootName]) {
menu = [item submenu];
break;
}
}
if (!menu) return nil;
count = [desc count] - 1;
for (i = 1; i < count; ++i) {
NSMenuItem *item = [menu itemWithTitle:[desc objectAtIndex:i]];
menu = [item submenu];
if (!menu) return nil;
}
return menu;
}
- (NSMenu *)topLevelMenuForTitle:(NSString *)title
{
// Search only the top-level menus.
@@ -1073,9 +1128,9 @@ static NSTimeInterval MMResendInterval = 0.5;
return nil;
}
- (void)addMenuWithTag:(int)tag parent:(int)parentTag title:(NSString *)title
atIndex:(int)idx
- (void)addMenuWithDescriptor:(NSArray *)desc atIndex:(int)idx
{
#if 0
NSMenu *parent = [self menuForTag:parentTag];
NSMenuItem *item = [[NSMenuItem alloc] init];
NSMenu *menu = [[NSMenu alloc] initWithTitle:title];
@@ -1105,14 +1160,73 @@ static NSTimeInterval MMResendInterval = 0.5;
[item release];
[menu release];
#else
if (!(desc && [desc count] > 0)) return;
NSString *rootName = [desc objectAtIndex:0];
if ([rootName isEqual:@"ToolBar"]) {
// The toolbar only has one menu, we take this as a hint to create a
// toolbar, then we return.
if (!toolbar) {
// NOTE! Each toolbar must have a unique identifier, else each
// window will have the same toolbar.
NSString *ident = [NSString stringWithFormat:@"%d", (int)self];
toolbar = [[NSToolbar alloc] initWithIdentifier:ident];
[toolbar setShowsBaselineSeparator:NO];
[toolbar setDelegate:self];
[toolbar setDisplayMode:NSToolbarDisplayModeIconOnly];
[toolbar setSizeMode:NSToolbarSizeModeSmall];
[windowController setToolbar:toolbar];
}
return;
}
// This is either a main menu item or a popup menu item.
NSString *title = [desc lastObject];
NSMenuItem *item = [[NSMenuItem alloc] init];
NSMenu *menu = [[NSMenu alloc] initWithTitle:title];
[menu setAutoenablesItems:NO];
[item setTitle:title];
[item setSubmenu:menu];
NSMenu *parent = [self parentMenuForDescriptor:desc];
if (parent) {
if ([parent numberOfItems] <= idx) {
[parent addItem:item];
} else {
[parent insertItem:item atIndex:idx];
}
} else {
BOOL isPopup = [rootName hasPrefix:@"PopUp"];
NSMutableArray *items = isPopup ? popupMenuItems : mainMenuItems;
if ([items count] <= idx) {
[items addObject:item];
} else {
[items insertObject:item atIndex:idx];
}
shouldUpdateMainMenu = !isPopup;
}
[item release];
[menu release];
#endif
}
- (void)addMenuItemWithTag:(int)tag parent:(NSMenu *)parent
title:(NSString *)title tip:(NSString *)tip
keyEquivalent:(int)key modifiers:(int)mask
action:(NSString *)action isAlternate:(int)isAlt
atIndex:(int)idx
- (void)addMenuItemWithDescriptor:(NSArray *)desc
atIndex:(int)idx
tip:(NSString *)tip
icon:(NSString *)icon
keyEquivalent:(NSString *)keyEquivalent
modifierMask:(int)modifierMask
action:(NSString *)action
isAlternate:(BOOL)isAlternate
{
#if 0
if (parent) {
NSMenuItem *item = nil;
if (!title || ([title hasPrefix:@"-"] && [title hasSuffix:@"-"])) {
@@ -1160,6 +1274,66 @@ static NSTimeInterval MMResendInterval = 0.5;
} else {
NSLog(@"WARNING: Menu item '%@' (tag=%d) has no parent.", title, tag);
}
#else
if (!(desc && [desc count] > 1)) return;
NSString *title = [desc lastObject];
NSString *rootName = [desc objectAtIndex:0];
if ([rootName isEqual:@"ToolBar"]) {
if (toolbar)
[self addToolbarItemWithLabel:title tip:tip icon:icon atIndex:idx];
return;
}
NSMenu *parent = [self parentMenuForDescriptor:desc];
if (!parent) {
NSLog(@"WARNING: Menu item '%@' has no parent",
[desc componentsJoinedByString:@"->"]);
return;
}
NSMenuItem *item = nil;
if (!title || ([title hasPrefix:@"-"] && [title hasSuffix:@"-"])) {
item = [NSMenuItem separatorItem];
} else {
item = [[[NSMenuItem alloc] init] autorelease];
[item setTitle:title];
if ([action isEqualToString:@"recentFilesDummy:"]) {
// Remove the recent files menu item from its current menu
// and put it in the current file menu. See -[MMAppController
// applicationWillFinishLaunching for more information.
//[[recentFilesMenuItem menu] removeItem:recentFilesMenuItem];
//item = recentFilesMenuItem;
recentFilesDummy = [item retain];
} else {
// TODO: Check that 'action' is a valid action (nothing will
// happen if it isn't, but it would be nice with a warning).
if ([action length] > 0)
[item setAction:NSSelectorFromString(action)];
else
[item setAction:@selector(vimMenuItemAction:)];
if ([tip length] > 0) [item setToolTip:tip];
if ([keyEquivalent length] > 0) {
[item setKeyEquivalent:keyEquivalent];
[item setKeyEquivalentModifierMask:modifierMask];
}
[item setAlternate:isAlternate];
}
}
// NOTE! The tag is used to idenfity which menu items were
// added by Vim (tag != 0) and which were added by the AppKit
// (tag == 0).
[item setTag:-1];
if ([parent numberOfItems] <= idx) {
[parent addItem:item];
} else {
[parent insertItem:item atIndex:idx];
}
#endif
}
- (NSToolbarItem *)toolbarItemForTag:(int)tag index:(int *)index
@@ -1179,7 +1353,7 @@ static NSTimeInterval MMResendInterval = 0.5;
return nil;
}
- (void)addToolbarItemToDictionaryWithTag:(int)tag label:(NSString *)title
- (void)addToolbarItemToDictionaryWithLabel:(NSString *)title
toolTip:(NSString *)tip icon:(NSString *)icon
{
// If the item corresponds to a separator then do nothing, since it is
@@ -1190,7 +1364,7 @@ static NSTimeInterval MMResendInterval = 0.5;
return;
NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:title];
[item setTag:tag];
[item setTag:-1];
[item setLabel:title];
[item setToolTip:tip];
[item setAction:@selector(vimMenuItemAction:)];
@@ -1213,7 +1387,7 @@ static NSTimeInterval MMResendInterval = 0.5;
[item release];
}
- (void)addToolbarItemWithTag:(int)tag label:(NSString *)label tip:(NSString
- (void)addToolbarItemWithLabel:(NSString *)label tip:(NSString
*)tip icon:(NSString *)icon atIndex:(int)idx
{
if (!toolbar) return;
@@ -1234,8 +1408,7 @@ static NSTimeInterval MMResendInterval = 0.5;
}
}
[self addToolbarItemToDictionaryWithTag:tag label:label toolTip:tip
icon:icon];
[self addToolbarItemToDictionaryWithLabel:label toolTip:tip icon:icon];
int maxIdx = [[toolbar items] count];
if (maxIdx < idx) idx = maxIdx;
+18 -4
View File
@@ -614,12 +614,26 @@
- (IBAction)vimMenuItemAction:(id)sender
{
int tag = [sender tag];
if (![sender isKindOfClass:[NSMenuItem class]]) return;
NSMutableData *data = [NSMutableData data];
[data appendBytes:&tag length:sizeof(int)];
// TODO: Make into category on NSMenuItem which returns descriptor.
NSMenuItem *item = (NSMenuItem*)sender;
NSMutableArray *desc = [NSMutableArray arrayWithObject:[item title]];
[vimController sendMessage:ExecuteMenuMsgID data:data];
NSMenu *menu = [item menu];
while (menu) {
[desc insertObject:[menu title] atIndex:0];
menu = [menu supermenu];
}
// The "MainMenu" item is part of the Cocoa menu and should not be part of
// the descriptor.
if ([[desc objectAtIndex:0] isEqual:@"MainMenu"])
[desc removeObjectAtIndex:0];
NSDictionary *attrs = [NSDictionary dictionaryWithObject:desc
forKey:@"descriptor"];
[vimController sendMessage:ExecuteMenuMsgID data:[attrs dictionaryAsData]];
}
+185 -42
View File
@@ -32,6 +32,15 @@ static float MMMaxFontSize = 100.0f;
static NSFont *gui_macvim_font_with_name(char_u *name);
static int specialKeyToNSKey(int key);
static int vimModMaskToEventModifierFlags(int mods);
NSArray *descriptor_for_menu(vimmenu_T *menu);
vimmenu_T *menu_for_descriptor(NSArray *desc);
@interface NSString (VimStrings)
+ (id)stringWithVimString:(char_u *)s;
@end
@@ -606,6 +615,46 @@ clip_mch_set_selection(VimClipboard *cbd)
// -- Menu ------------------------------------------------------------------
NSArray *
descriptor_for_menu(vimmenu_T *menu)
{
if (!menu) return nil;
NSMutableArray *desc = [NSMutableArray array];
while (menu) {
NSString *name = [NSString stringWithVimString:menu->dname];
[desc insertObject:name atIndex:0];
menu = menu->parent;
}
return desc;
}
vimmenu_T *
menu_for_descriptor(NSArray *desc)
{
if (!(desc && [desc count] > 0)) return NULL;
vimmenu_T *menu = root_menu;
int i, count = [desc count];
for (i = 0; i < count; ++i) {
NSString *component = [desc objectAtIndex:i];
while (menu) {
NSString *name = [NSString stringWithVimString:menu->dname];
if ([component isEqual:name]) {
if (i+1 == count)
return menu; // Matched all components, so return menu
menu = menu->children;
break;
}
menu = menu->next;
}
}
return NULL;
}
/*
* Add a sub menu to the menu bar.
*/
@@ -628,9 +677,12 @@ gui_mch_add_menu(vimmenu_T *menu, int idx)
dname = CONVERT_TO_UTF8(dname);
#endif
[[MMBackend sharedInstance]
addMenuWithTag:(int)menu parent:parent name:(char*)dname
atIndex:idx];
NSArray *desc = descriptor_for_menu(menu);
[[MMBackend sharedInstance] queueMessage:AddMenuMsgID properties:
[NSDictionary dictionaryWithObjectsAndKeys:
desc, @"descriptor",
[NSNumber numberWithInt:idx], @"index",
nil]];
#ifdef FEAT_MBYTE
CONVERT_TO_UTF8_FREE(dname);
@@ -649,40 +701,24 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx)
char_u *icon = menu->iconfile ? menu->iconfile :
menu->iconidx >= 0 ? menu->dname :
NULL;
//char *name = menu_is_separator(menu->name) ? NULL : (char*)menu->dname;
char_u *name = menu->dname;
char_u *tip = menu->strings[MENU_INDEX_TIP]
? menu->strings[MENU_INDEX_TIP] : menu->actext;
char_u *map_str = menu->strings[MENU_INDEX_NORMAL];
char_u *mac_action = menu->mac_action;
NSArray *desc = descriptor_for_menu(menu);
NSString *keyEquivalent = [NSString stringWithFormat:@"%C",
specialKeyToNSKey(menu->mac_key)];
int modifierMask = vimModMaskToEventModifierFlags(menu->mac_mods);
#ifdef FEAT_MBYTE
icon = CONVERT_TO_UTF8(icon);
name = CONVERT_TO_UTF8(name);
tip = CONVERT_TO_UTF8(tip);
map_str = CONVERT_TO_UTF8(map_str);
mac_action = CONVERT_TO_UTF8(mac_action);
#endif
[[MMBackend sharedInstance]
addMenuItemWithTag:(int)menu
parent:(int)menu->parent
name:(char*)name
tip:(char*)tip
icon:(char*)icon
keyEquivalent:menu->mac_key
modifiers:menu->mac_mods
action:(char*)mac_action
isAlternate:menu->mac_alternate
atIndex:idx];
#ifdef FEAT_MBYTE
CONVERT_TO_UTF8_FREE(icon);
CONVERT_TO_UTF8_FREE(name);
CONVERT_TO_UTF8_FREE(tip);
CONVERT_TO_UTF8_FREE(map_str);
CONVERT_TO_UTF8_FREE(mac_action);
#endif
[[MMBackend sharedInstance] queueMessage:AddMenuItemMsgID properties:
[NSDictionary dictionaryWithObjectsAndKeys:
desc, @"descriptor",
[NSNumber numberWithInt:idx], @"index",
[NSString stringWithVimString:tip], @"tip",
[NSString stringWithVimString:icon], @"icon",
keyEquivalent, @"keyEquivalent",
[NSNumber numberWithInt:modifierMask], @"modifierMask",
[NSString stringWithVimString:menu->mac_action], @"action",
[NSNumber numberWithBool:menu->mac_alternate], @"isAlternate",
nil]];
}
@@ -692,7 +728,9 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx)
void
gui_mch_destroy_menu(vimmenu_T *menu)
{
[[MMBackend sharedInstance] removeMenuItemWithTag:(int)menu];
NSArray *desc = descriptor_for_menu(menu);
[[MMBackend sharedInstance] queueMessage:RemoveMenuItemMsgID properties:
[NSDictionary dictionaryWithObject:desc forKey:@"descriptor"]];
}
@@ -705,12 +743,12 @@ gui_mch_menu_grey(vimmenu_T *menu, int grey)
/* Only update menu if the 'grey' state has changed to avoid having to pass
* lots of unnecessary data to MacVim. (Skipping this test makes MacVim
* pause noticably on mode changes. */
if (menu->was_grey != grey)
{
menu->was_grey = grey;
[[MMBackend sharedInstance]
enableMenuItemWithTag:(int)menu state:!grey];
}
if (menu->was_grey != grey) return;
menu->was_grey = grey;
[[MMBackend sharedInstance] queueMessage:EnableMenuItemMsgID properties:
[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:!grey]
forKey:@"enable"]];
}
@@ -732,6 +770,7 @@ gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
void
gui_mch_show_popupmenu(vimmenu_T *menu)
{
#if 0
char_u *name = menu->name;
#ifdef FEAT_MBYTE
name = CONVERT_TO_UTF8(name);
@@ -743,7 +782,7 @@ gui_mch_show_popupmenu(vimmenu_T *menu)
#ifdef FEAT_MBYTE
CONVERT_TO_UTF8_FREE(name);
#endif
#endif
}
@@ -753,6 +792,7 @@ gui_mch_show_popupmenu(vimmenu_T *menu)
void
gui_make_popup(char_u *path_name, int mouse_pos)
{
#if 0
#ifdef FEAT_MBYTE
path_name = CONVERT_TO_UTF8(path_name);
#endif
@@ -763,6 +803,7 @@ gui_make_popup(char_u *path_name, int mouse_pos)
#ifdef FEAT_MBYTE
CONVERT_TO_UTF8_FREE(path_name);
#endif
#endif
}
@@ -1886,3 +1927,105 @@ is_valid_macaction(char_u *action)
return isValid;
}
static int specialKeyToNSKey(int key)
{
if (!IS_SPECIAL(key))
return key;
static struct {
int special;
int nskey;
} sp2ns[] = {
{ K_UP, NSUpArrowFunctionKey },
{ K_DOWN, NSDownArrowFunctionKey },
{ K_LEFT, NSLeftArrowFunctionKey },
{ K_RIGHT, NSRightArrowFunctionKey },
{ K_F1, NSF1FunctionKey },
{ K_F2, NSF2FunctionKey },
{ K_F3, NSF3FunctionKey },
{ K_F4, NSF4FunctionKey },
{ K_F5, NSF5FunctionKey },
{ K_F6, NSF6FunctionKey },
{ K_F7, NSF7FunctionKey },
{ K_F8, NSF8FunctionKey },
{ K_F9, NSF9FunctionKey },
{ K_F10, NSF10FunctionKey },
{ K_F11, NSF11FunctionKey },
{ K_F12, NSF12FunctionKey },
{ K_F13, NSF13FunctionKey },
{ K_F14, NSF14FunctionKey },
{ K_F15, NSF15FunctionKey },
{ K_F16, NSF16FunctionKey },
{ K_F17, NSF17FunctionKey },
{ K_F18, NSF18FunctionKey },
{ K_F19, NSF19FunctionKey },
{ K_F20, NSF20FunctionKey },
{ K_F21, NSF21FunctionKey },
{ K_F22, NSF22FunctionKey },
{ K_F23, NSF23FunctionKey },
{ K_F24, NSF24FunctionKey },
{ K_F25, NSF25FunctionKey },
{ K_F26, NSF26FunctionKey },
{ K_F27, NSF27FunctionKey },
{ K_F28, NSF28FunctionKey },
{ K_F29, NSF29FunctionKey },
{ K_F30, NSF30FunctionKey },
{ K_F31, NSF31FunctionKey },
{ K_F32, NSF32FunctionKey },
{ K_F33, NSF33FunctionKey },
{ K_F34, NSF34FunctionKey },
{ K_F35, NSF35FunctionKey },
{ K_DEL, NSBackspaceCharacter },
{ K_BS, NSDeleteCharacter },
{ K_HOME, NSHomeFunctionKey },
{ K_END, NSEndFunctionKey },
{ K_PAGEUP, NSPageUpFunctionKey },
{ K_PAGEDOWN, NSPageDownFunctionKey }
};
int i;
for (i = 0; i < sizeof(sp2ns)/sizeof(sp2ns[0]); ++i) {
if (sp2ns[i].special == key)
return sp2ns[i].nskey;
}
return 0;
}
static int vimModMaskToEventModifierFlags(int mods)
{
int flags = 0;
if (mods & MOD_MASK_SHIFT)
flags |= NSShiftKeyMask;
if (mods & MOD_MASK_CTRL)
flags |= NSControlKeyMask;
if (mods & MOD_MASK_ALT)
flags |= NSAlternateKeyMask;
if (mods & MOD_MASK_CMD)
flags |= NSCommandKeyMask;
return flags;
}
@implementation NSString (VimStrings)
+ (id)stringWithVimString:(char_u *)s
{
if (s) {
#ifdef FEAT_MBYTE
s = CONVERT_TO_UTF8(s);
#endif
NSString *string = [NSString stringWithUTF8String:(char*)s];
#ifdef FEAT_MBYTE
CONVERT_TO_UTF8_FREE(s);
#endif
return string;
}
return [NSString string];
}
@end