1 /* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
2 Copyright (C) 2006 and later, Cockos, Inc.
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
21 This file provides basic windows menu API to interface an NSMenu
25 #ifndef SWELL_PROVIDED_BY_APP
27 #import <Cocoa/Cocoa.h>
30 #include "swell-menugen.h"
32 #include "swell-internal.h"
35 static void __filtnametobuf(char *out, const char *in, int outsz)
37 while (*in && outsz>1)
39 if (*in == '\t') break;
52 bool SetMenuItemText(HMENU hMenu, int idx, int flag, const char *text)
54 NSMenu *menu=(NSMenu *)hMenu;
57 if (flag & MF_BYPOSITION) item=[menu itemAtIndex:idx];
58 else item =[menu itemWithTag:idx];
61 if (!(flag & MF_BYPOSITION))
63 const int n = (int) [menu numberOfItems];
64 for (int x = 0; x < n; x ++)
66 item=[menu itemAtIndex:x];
67 if (item && [item hasSubmenu])
69 NSMenu *m=[item submenu];
70 if (m && SetMenuItemText((HMENU)m,idx,flag,text)) return true;
77 __filtnametobuf(buf,text?text:"",sizeof(buf));
78 NSString *label=(NSString *)SWELL_CStringToCFString(buf);
80 [item setTitle:label];
81 if ([item hasSubmenu] && [item submenu]) [[item submenu] setTitle:label];
87 bool EnableMenuItem(HMENU hMenu, int idx, int en)
89 NSMenu *menu=(NSMenu *)hMenu;
92 if (en & MF_BYPOSITION) item=[menu itemAtIndex:idx];
93 else item =[menu itemWithTag:idx];
96 if (!(en & MF_BYPOSITION))
98 const int n=(int)[menu numberOfItems];
99 for (int x = 0; x < n; x ++)
101 item=[menu itemAtIndex:x];
102 if (item && [item hasSubmenu])
104 NSMenu *m=[item submenu];
105 if (m && EnableMenuItem((HMENU)m,idx,en)) return true;
111 [item setEnabled:((en&MF_GRAYED)?NO:YES)];
115 bool CheckMenuItem(HMENU hMenu, int idx, int chk)
117 NSMenu *menu=(NSMenu *)hMenu;
118 if (!menu) return false;
121 if (chk & MF_BYPOSITION) item=[menu itemAtIndex:idx];
122 else item =[menu itemWithTag:idx];
125 if (!(chk & MF_BYPOSITION))
127 const int n=(int)[menu numberOfItems];
128 for (int x = 0; x < n; x ++)
130 item=[menu itemAtIndex:x];
131 if (item && [item hasSubmenu])
133 NSMenu *m=[item submenu];
134 if (m && CheckMenuItem((HMENU)m,idx,chk)) return true;
140 [item setState:((chk&MF_CHECKED)?NSOnState:NSOffState)];
144 HMENU SWELL_GetCurrentMenu()
146 return (HMENU)[NSApp mainMenu];
149 extern int g_swell_terminating;
151 void SWELL_SetCurrentMenu(HMENU hmenu)
153 if (hmenu && [(id)hmenu isKindOfClass:[NSMenu class]])
155 if (!g_swell_terminating) [NSApp setMainMenu:(NSMenu *)hmenu];
159 HMENU GetSubMenu(HMENU hMenu, int pos)
161 NSMenu *menu=(NSMenu *)hMenu;
163 NSMenuItem *item=menu && pos >=0 && pos < [menu numberOfItems] ? [menu itemAtIndex:pos] : 0;
164 if (item && [item hasSubmenu]) return (HMENU)[item submenu];
168 int GetMenuItemCount(HMENU hMenu)
170 NSMenu *menu=(NSMenu *)hMenu;
171 return (int)[menu numberOfItems];
174 int GetMenuItemID(HMENU hMenu, int pos)
176 NSMenu *menu=(NSMenu *)hMenu;
177 if (pos < 0 || pos >= (int)[menu numberOfItems]) return 0;
179 NSMenuItem *item=[menu itemAtIndex:pos];
182 if ([item hasSubmenu]) return -1;
183 return (int)[item tag];
188 bool SetMenuItemModifier(HMENU hMenu, int idx, int flag, int code, unsigned int mask)
191 #if 0 // enable this once we make SWELL_KeyToASCII decent
193 int n1 = SWELL_KeyToASCII(code,flag,&n2);
201 NSMenu *menu=(NSMenu *)hMenu;
204 if (flag & MF_BYPOSITION) item=[menu itemAtIndex:idx];
205 else item =[menu itemWithTag:idx];
208 if (!(flag & MF_BYPOSITION))
210 const int n = (int)[menu numberOfItems];
211 for (int x = 0; x < n; x ++)
213 item=[menu itemAtIndex:x];
214 if (item && [item hasSubmenu])
216 NSMenu *m=[item submenu];
217 if (m && SetMenuItemModifier((HMENU)m,idx,flag,code,mask)) return true;
224 bool suppressShift = false;
225 unichar arrowKey = 0;
226 int codelow = code&127;
227 if ((code>='A' && code <='Z') ||
228 (code>='0' && code <= '9') ||
229 ( !(mask&FVIRTKEY) &&
245 if (!(mask & FSHIFT) && arrowKey < 256) arrowKey=tolower(arrowKey);
247 if (code>='A' && code<='Z') suppressShift=true;
249 else if (code >= VK_F1 && code <= VK_F24)
251 arrowKey = NSF1FunctionKey + code - VK_F1;
253 else switch (code&0xff)
255 #define DEFKP(wink,mack) case wink: arrowKey = mack; break;
256 DEFKP(VK_UP,NSUpArrowFunctionKey)
257 DEFKP(VK_DOWN,NSDownArrowFunctionKey)
258 DEFKP(VK_LEFT,NSLeftArrowFunctionKey)
259 DEFKP(VK_RIGHT,NSRightArrowFunctionKey)
260 DEFKP(VK_INSERT,NSInsertFunctionKey)
261 DEFKP(VK_DELETE,NSDeleteCharacter)
262 DEFKP(VK_BACK,NSBackspaceCharacter)
263 DEFKP(VK_HOME,NSHomeFunctionKey)
264 DEFKP(VK_END,NSEndFunctionKey)
265 DEFKP(VK_NEXT,NSPageDownFunctionKey)
266 DEFKP(VK_PRIOR,NSPageUpFunctionKey)
267 DEFKP(VK_SUBTRACT,'-')
270 unsigned int mask2=0;
271 if (mask&FALT) mask2|=NSAlternateKeyMask;
272 if (!suppressShift) if (mask&FSHIFT) mask2|=NSShiftKeyMask;
273 if (mask&FCONTROL) mask2|=NSCommandKeyMask;
274 if (mask&FLWIN) mask2|=NSControlKeyMask;
276 [item setKeyEquivalentModifierMask:mask2];
277 [item setKeyEquivalent:arrowKey?[NSString stringWithCharacters:&arrowKey length:1]:@""];
281 // #define SWELL_MENU_ACCOUNTING
283 #ifdef SWELL_MENU_ACCOUNTING
290 WDL_PtrList<menuTmp> allMenus;
293 @implementation SWELL_Menu
294 - (id)copyWithZone:(NSZone *)zone
296 id rv = [super copyWithZone:zone];
297 #ifdef SWELL_MENU_ACCOUNTING
300 menuTmp *mt = new menuTmp;
301 mt->menu=(NSMenu *)rv;
302 NSString *lbl = [(SWELL_Menu *)rv title];
306 NSLog(@"copy menu, new count=%d lbl=%@\n",allMenus.GetSize(),lbl);
313 #ifdef SWELL_MENU_ACCOUNTING
316 for(x=0;x<allMenus.GetSize();x++)
318 if (allMenus.Get(x)->menu == self)
320 NSLog(@"dealloc menu, found self %@\n",allMenus.Get(x)->lbl);
327 NSLog(@"dealloc menu, new count=%d %@\n",allMenus.GetSize(), [self title]);
330 NSLog(@"deleting unfound menu!!\n");
337 HMENU CreatePopupMenu()
339 return CreatePopupMenuEx(NULL);
341 HMENU CreatePopupMenuEx(const char *title)
347 __filtnametobuf(buf,title,sizeof(buf));
348 NSString *lbl=(NSString *)SWELL_CStringToCFString(buf);
349 m=[[SWELL_Menu alloc] initWithTitle:lbl];
350 #ifdef SWELL_MENU_ACCOUNTING
351 menuTmp *mt = new menuTmp;
356 NSLog(@"alloc menu, new count=%d lbl=%@\n",allMenus.GetSize(),lbl);
362 m=[[SWELL_Menu alloc] init];
363 #ifdef SWELL_MENU_ACCOUNTING
364 menuTmp *mt = new menuTmp;
368 NSLog(@"alloc menu, new count=%d lbl=%@\n",allMenus.GetSize(),@"<none>");
371 [m setAutoenablesItems:NO];
376 void DestroyMenu(HMENU hMenu)
380 SWELL_SetMenuDestination(hMenu,NULL);
381 NSMenu *m=(NSMenu *)hMenu;
388 int AddMenuItem(HMENU hMenu, int pos, const char *name, int tagid)
390 if (!hMenu) return -1;
391 NSMenu *m=(NSMenu *)hMenu;
392 NSString *label=(NSString *)SWELL_CStringToCFString(name);
393 NSMenuItem *item=[m insertItemWithTitle:label action:NULL keyEquivalent:@"" atIndex:pos];
396 [item setEnabled:YES];
400 bool DeleteMenu(HMENU hMenu, int idx, int flag)
402 if (!hMenu) return false;
403 NSMenu *m=(NSMenu *)hMenu;
404 NSMenuItem *item=NULL;
406 if (flag&MF_BYPOSITION)
408 if (idx >=0 && idx < [m numberOfItems])
409 item=[m itemAtIndex:idx];
410 if (!item) return false;
414 item=[m itemWithTag:idx];
417 const int n = (int) [m numberOfItems];
418 for (int x=0;x<n;x++)
420 item=[m itemAtIndex:x];
421 if (item && [item hasSubmenu])
423 if (DeleteMenu((HMENU)[item submenu],idx,flag)) return true;
430 if ([item hasSubmenu])
432 HMENU sm = (HMENU)[item submenu];
433 if (sm) SWELL_SetMenuDestination(sm,NULL);
434 [m setSubmenu:nil forItem:item];
441 BOOL SetMenuItemInfo(HMENU hMenu, int pos, BOOL byPos, MENUITEMINFO *mi)
443 if (!hMenu) return 0;
444 NSMenu *m=(NSMenu *)hMenu;
446 if (byPos) item=[m itemAtIndex:pos];
447 else item=[m itemWithTag:pos];
453 const int n = (int)[m numberOfItems];
454 for (int x = 0; x < n; x ++)
456 item=[m itemAtIndex:x];
457 if (item && [item hasSubmenu])
459 NSMenu *m1=[item submenu];
460 if (m1 && SetMenuItemInfo((HMENU)m1,pos,byPos,mi)) return true;
467 if (mi->fMask & MIIM_TYPE)
469 if (mi->fType == MFT_STRING && mi->dwTypeData)
472 __filtnametobuf(buf,mi->dwTypeData?mi->dwTypeData:"(null)",sizeof(buf));
473 NSString *label=(NSString *)SWELL_CStringToCFString(buf);
475 [item setTitle:label];
477 if ([item hasSubmenu])
479 NSMenu *subm=[item submenu];
480 if (subm) [subm setTitle:label];
486 if (mi->fMask & MIIM_SUBMENU)
488 NSMenu *oldMenu = [item hasSubmenu] ? [item submenu] : NULL;
489 NSMenu *newMenu = (NSMenu*)mi->hSubMenu;
490 if (oldMenu != newMenu)
492 if (oldMenu) [oldMenu retain]; // we do not destroy the old menu, caller responsibility
494 if (newMenu) [newMenu setTitle:[item title]];
495 [m setSubmenu:newMenu forItem:item];
496 if (newMenu) [newMenu release]; // let the parent menu free it
500 if (mi->fMask & MIIM_STATE)
502 [item setState:((mi->fState&MFS_CHECKED)?NSOnState:NSOffState)];
503 [item setEnabled:((mi->fState&MFS_GRAYED)?NO:YES)];
505 if (mi->fMask & MIIM_ID)
507 [item setTag:mi->wID];
509 if (mi->fMask & MIIM_DATA)
511 SWELL_DataHold* newh = [[SWELL_DataHold alloc] initWithVal:(void*)mi->dwItemData];
512 [item setRepresentedObject:newh];
519 BOOL GetMenuItemInfo(HMENU hMenu, int pos, BOOL byPos, MENUITEMINFO *mi)
521 if (!hMenu) return 0;
522 NSMenu *m=(NSMenu *)hMenu;
526 item=[m itemAtIndex:pos];
528 else item=[m itemWithTag:pos];
534 const int n = (int)[m numberOfItems];
535 for (int x = 0; x < n; x ++)
537 item=[m itemAtIndex:x];
538 if (item && [item hasSubmenu])
540 NSMenu *m1=[item submenu];
541 if (m1 && GetMenuItemInfo((HMENU)m1,pos,byPos,mi)) return true;
548 if (mi->fMask & MIIM_TYPE)
550 if ([item isSeparatorItem]) mi->fType = MFT_SEPARATOR;
553 mi->fType = MFT_STRING;
554 if (mi->dwTypeData && mi->cch)
557 SWELL_CFStringToCString([item title], (char *)mi->dwTypeData, mi->cch);
562 if (mi->fMask & MIIM_DATA)
564 SWELL_DataHold *h=[item representedObject];
565 mi->dwItemData = (INT_PTR)(h && [h isKindOfClass:[SWELL_DataHold class]]? [h getValue] : 0);
568 if (mi->fMask & MIIM_STATE)
571 if ([item state]) mi->fState|=MFS_CHECKED;
572 if (![item isEnabled]) mi->fState|=MFS_GRAYED;
575 if (mi->fMask & MIIM_ID)
577 mi->wID = (unsigned int)[item tag];
580 if(mi->fMask & MIIM_SUBMENU)
582 mi->hSubMenu = (HMENU) ([item hasSubmenu] ? [item submenu] : NULL);
589 void SWELL_InsertMenu(HMENU menu, int pos, unsigned int flag, UINT_PTR idx, const char *str)
591 MENUITEMINFO mi={sizeof(mi),MIIM_ID|MIIM_STATE|MIIM_TYPE,MFT_STRING,
592 (flag & ~MF_BYPOSITION),(flag&MF_POPUP) ? 0 : (unsigned int)idx,NULL,NULL,NULL,0,(char *)str};
596 mi.hSubMenu = (HMENU)idx;
597 mi.fMask |= MIIM_SUBMENU;
598 mi.fState &= ~MF_POPUP;
601 if (flag&MF_SEPARATOR)
604 mi.fType=MFT_SEPARATOR;
605 mi.fState &= ~MF_SEPARATOR;
611 mi.fState &= ~MF_BITMAP;
614 InsertMenuItem(menu,pos,(flag&MF_BYPOSITION) ? TRUE : FALSE, &mi);
618 void InsertMenuItem(HMENU hMenu, int pos, BOOL byPos, MENUITEMINFO *mi)
621 NSMenu *m=(NSMenu *)hMenu;
623 int ni = (int)[m numberOfItems];
627 pos = (int)[m indexOfItemWithTag:pos];
629 if (pos < 0 || pos > ni) pos=ni;
632 if (mi->fType == MFT_STRING)
635 __filtnametobuf(buf,mi->dwTypeData?mi->dwTypeData:"(null)",sizeof(buf));
636 label=(NSString *)SWELL_CStringToCFString(buf);
637 item=[m insertItemWithTitle:label action:NULL keyEquivalent:@"" atIndex:pos];
639 else if (mi->fType == MFT_BITMAP)
641 item=[m insertItemWithTitle:@"(no image)" action:NULL keyEquivalent:@"" atIndex:pos];
644 NSImage *i=(NSImage *)GetNSImageFromHICON((HICON)mi->dwTypeData);
654 item = [NSMenuItem separatorItem];
655 [m insertItem:item atIndex:pos];
658 if ((mi->fMask & MIIM_SUBMENU) && mi->hSubMenu)
660 if (label) [(NSMenu *)mi->hSubMenu setTitle:label];
661 [m setSubmenu:(NSMenu *)mi->hSubMenu forItem:item];
662 [((NSMenu *)mi->hSubMenu) release]; // let the parent menu free it
664 if (label) [label release];
666 if (!ni) [m setAutoenablesItems:NO];
667 [item setEnabled:YES];
669 if (mi->fMask & MIIM_STATE)
671 if (mi->fState&MFS_GRAYED)
673 [item setEnabled:NO];
675 if (mi->fState&MFS_CHECKED)
677 [item setState:NSOnState];
681 if (mi->fMask & MIIM_DATA)
683 SWELL_DataHold *h=[[SWELL_DataHold alloc] initWithVal:(void*)mi->dwItemData];
684 [item setRepresentedObject:h];
689 [item setRepresentedObject:nil];
692 if (mi->fMask & MIIM_ID)
694 [item setTag:mi->wID];
698 ni = (int)[m numberOfItems];
699 // try to find a valid action/target
700 for (i = 0; i < ni; i ++)
702 NSMenuItem *fi=[m itemAtIndex:i];
703 if (fi && fi != item)
705 SEL act = [fi action];
706 id tgt = [fi target];
709 if (act) [item setAction:act];
710 if (tgt) [item setTarget:tgt];
714 if (i == 5 && ni > 14) i = ni-6; // only look at first and last 6 items or so
720 @implementation SWELL_PopupMenuRecv
721 -(id) initWithWnd:(HWND)wnd
723 if ((self = [super init]))
731 -(void) onSwellCommand:(id)sender
733 int tag=(int) [sender tag];
743 - (void)menuNeedsUpdate:(NSMenu *)menu
747 SendMessage(cbwnd,WM_INITMENUPOPUP,(WPARAM)menu,0);
748 SWELL_SetMenuDestination((HMENU)menu,(HWND)self);
754 void SWELL_SetMenuDestination(HMENU menu, HWND hwnd)
756 if (!menu || (hwnd && ![(id)hwnd respondsToSelector:@selector(onSwellCommand:)])) return;
758 NSMenu *m=(NSMenu *)menu;
759 [m setDelegate:(id)hwnd];
760 const int n = (int)[m numberOfItems];
761 for (int x = 0; x < n; x++)
763 NSMenuItem *item=[m itemAtIndex:x];
766 if ([item hasSubmenu])
768 NSMenu *mm=[item submenu];
769 if (mm) SWELL_SetMenuDestination((HMENU)mm,hwnd);
775 [item setTarget:(id)hwnd];
776 if (hwnd) [item setAction:@selector(onSwellCommand:)];
783 int TrackPopupMenu(HMENU hMenu, int flags, int xpos, int ypos, int resvd, HWND hwnd, const RECT *r)
785 ReleaseCapture(); // match win32 -- TrackPopupMenu() ends any captures
788 NSMenu *m=(NSMenu *)hMenu;
789 NSView *v=(NSView *)hwnd;
790 if (v && [v isKindOfClass:[NSWindow class]]) v=[(NSWindow *)v contentView];
791 if (!v) v=[[NSApp mainWindow] contentView];
794 NSEvent *event = [NSApp currentEvent];
797 //create a new event at these coordinates, faking it
798 NSWindow *w = [v window];
799 NSPoint pt = NSMakePoint(xpos, ypos);
800 pt=[w convertScreenToBase:pt];
802 NSInteger wn = [w windowNumber]; // event ? [event windowNumber] : [w windowNumber];
803 NSTimeInterval ts = event ? [event timestamp] : 0;
804 NSGraphicsContext *gctx = event ? [event context] : 0;
805 event = [NSEvent otherEventWithType:NSApplicationDefined location:pt modifierFlags:0 timestamp:ts windowNumber:wn context:gctx subtype:0 data1:0 data2:0];
808 SWELL_PopupMenuRecv *recv = [[SWELL_PopupMenuRecv alloc] initWithWnd:((flags & TPM_NONOTIFY) ? 0 : hwnd)];
810 SWELL_SetMenuDestination((HMENU)m,(HWND)recv);
812 if (!(flags&TPM_NONOTIFY)&&hwnd)
814 SendMessage(hwnd,WM_INITMENUPOPUP,(WPARAM)m,0);
815 SWELL_SetMenuDestination((HMENU)m,(HWND)recv);
818 [NSMenu popUpContextMenu:m withEvent:event forView:v];
820 int ret=[recv isCommand];
821 SWELL_SetMenuDestination((HMENU)m,(HWND)NULL);
824 if (ret<=0) return 0;
826 if (flags & TPM_RETURNCMD) return ret;
828 if (hwnd) SendMessage(hwnd,WM_COMMAND,ret,0);
838 void SWELL_Menu_AddMenuItem(HMENU hMenu, const char *name, int idx, unsigned int flags)
840 MENUITEMINFO mi={sizeof(mi),MIIM_ID|MIIM_STATE|MIIM_TYPE,MFT_STRING,
841 (unsigned int) ((flags)?MFS_GRAYED:0),(unsigned int)idx,NULL,NULL,NULL,0,(char *)name};
844 mi.fType = MFT_SEPARATOR;
845 mi.fMask&=~(MIIM_STATE|MIIM_ID);
847 InsertMenuItem(hMenu,GetMenuItemCount(hMenu),TRUE,&mi);
850 int SWELL_GenerateMenuFromList(HMENU hMenu, const void *_list, int listsz)
852 SWELL_MenuGen_Entry *list = (SWELL_MenuGen_Entry *)_list;
853 const int l1=strlen(SWELL_MENUGEN_POPUP_PREFIX);
857 if (!list->name) SWELL_Menu_AddMenuItem(hMenu,NULL,-1,0);
858 else if (!strcmp(list->name,SWELL_MENUGEN_ENDPOPUP)) break;
859 else if (!strncmp(list->name,SWELL_MENUGEN_POPUP_PREFIX,l1))
861 MENUITEMINFO mi={sizeof(mi),MIIM_SUBMENU|MIIM_STATE|MIIM_TYPE,MFT_STRING,0,0,CreatePopupMenuEx(list->name+l1),NULL,NULL,0,(char *)list->name+l1};
862 cnt += SWELL_GenerateMenuFromList(mi.hSubMenu,list+1,listsz-1);
863 InsertMenuItem(hMenu,GetMenuItemCount(hMenu),TRUE,&mi);
865 else SWELL_Menu_AddMenuItem(hMenu,list->name,list->idx,list->flags);
870 return (int) (list + 1 - (SWELL_MenuGen_Entry *)_list);
874 SWELL_MenuResourceIndex *SWELL_curmodule_menuresource_head; // todo: move to per-module thingy
876 static SWELL_MenuResourceIndex *resById(SWELL_MenuResourceIndex *head, const char *resid)
878 SWELL_MenuResourceIndex *p=head;
881 if (p->resid == resid) return p;
887 HMENU SWELL_LoadMenu(SWELL_MenuResourceIndex *head, const char *resid)
889 SWELL_MenuResourceIndex *p;
891 if (!(p=resById(head,resid))) return 0;
892 HMENU hMenu=CreatePopupMenu();
893 if (hMenu) p->createFunc(hMenu);
897 HMENU SWELL_DuplicateMenu(HMENU menu)
900 NSMenu *ret = (NSMenu *)[(NSMenu *)menu copy];
904 BOOL SetMenu(HWND hwnd, HMENU menu)
906 if (!hwnd||![(id)hwnd respondsToSelector:@selector(swellSetMenu:)]) return FALSE;
907 if (g_swell_terminating) return FALSE;
909 [(id)hwnd swellSetMenu:(HMENU)menu];
910 NSWindow *nswnd = (NSWindow *)hwnd;
911 if ([nswnd isKindOfClass:[NSWindow class]] ||
912 ([nswnd isKindOfClass:[NSView class]] && (nswnd=[(NSView *)nswnd window]) && hwnd == (HWND)[nswnd contentView]))
914 if ([NSApp keyWindow]==nswnd &&
915 [NSApp mainMenu] != (NSMenu *)menu)
917 [NSApp setMainMenu:(NSMenu *)menu];
918 if (menu) SendMessage(hwnd,WM_INITMENUPOPUP,(WPARAM)menu,0); // find a better place for this! TODO !!!
925 HMENU GetMenu(HWND hwnd)
927 if (!hwnd) return NULL;
928 if ([(id)hwnd isKindOfClass:[NSWindow class]]) hwnd = (HWND)[(NSWindow *)hwnd contentView];
929 if ([(id)hwnd respondsToSelector:@selector(swellGetMenu)]) return (HMENU) [(id)hwnd swellGetMenu];
933 void DrawMenuBar(HWND hwnd)