30#define MM_SETMENUHANDLE (WM_USER + 0)
31#define MM_GETMENUHANDLE (WM_USER + 1)
35#define TF_ENDMENU 0x10000
36#define TF_SUSPENDPOPUP 0x20000
37#define TF_SKIPREMOVE 0x40000
43#define MAXMENUDEPTH 30
45#define MNS_STYLE_MASK (MNS_NOCHECK|MNS_MODELESS|MNS_DRAGDROP|MNS_AUTODISMISS|MNS_NOTIFYBYPOS|MNS_CHECKORBMP)
47#define MENUITEMINFO_TYPE_MASK \
48 (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
49 MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
50 MFT_RIGHTORDER | MFT_RIGHTJUSTIFY )
52#define TYPE_MASK (MENUITEMINFO_TYPE_MASK | MF_POPUP | MF_SYSMENU)
54#define STATE_MASK (~TYPE_MASK)
56#define MENUITEMINFO_STATE_MASK (STATE_MASK & ~(MF_BYPOSITION | MF_MOUSESELECT))
58#define MII_STATE_MASK (MFS_GRAYED|MFS_CHECKED|MFS_HILITE|MFS_DEFAULT)
60#define IS_SYSTEM_MENU(MenuInfo) \
61 (!!((MenuInfo)->fFlags & MNF_SYSMENU))
63#define IS_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1))
64#define IS_STRING_ITEM(flags) (MF_STRING == MENU_ITEM_TYPE(flags))
67#define MAX_MENU_ITEMS (0x4000)
68#define MAX_GOINTOSUBMENU (0x10)
71#define MENU_COL_SPACE 4
73#define MENU_ITEM_HBMP_SPACE (5)
74#define MENU_BAR_ITEMS_SPACE (12)
75#define SEPARATOR_HEIGHT (5)
76#define MENU_TAB_SPACE (8)
88#define TPM_INTERNAL 0xF0000000
89#define TPM_BUTTONDOWN 0x40000000
90#define TPM_POPUPMENU 0x20000000
95#define UpdateMenuItemState(state, change) \
97 if((change) & MF_GRAYED) { \
98 (state) |= MF_GRAYED; \
100 (state) &= ~MF_GRAYED; \
102 if((change) & MF_DISABLED) { \
103 (state) |= MF_DISABLED; \
105 (state) &= ~MF_DISABLED; \
107 if((change) & MFS_CHECKED) { \
108 (state) |= MFS_CHECKED; \
110 (state) &= ~MFS_CHECKED; \
112 if((change) & MFS_HILITE) { \
113 (state) |= MFS_HILITE; \
115 (state) &= ~MFS_HILITE; \
117 if((change) & MFS_DEFAULT) { \
118 (state) |= MFS_DEFAULT; \
120 (state) &= ~MFS_DEFAULT; \
122 if((change) & MF_MOUSESELECT) { \
123 (state) |= MF_MOUSESELECT; \
125 (state) &= ~MF_MOUSESELECT; \
183#define FreeMenuText(Menu,MenuItem) \
185 if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
186 (MenuItem)->lpstr.Length) { \
187 DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \
196 Menu->
head.cLockObj++;
207 if (!pMenu)
return NULL;
223 ERR(
"Run away LOOP!\n");
231 ERR(
"Menu is marked for destruction!\n");
280 SubMenu =
item->spSubMenu;
294 if (bRecurse && SubMenu)
338 ERR(
"FIXME Pop up menu window thing'ie\n");
351 TRACE(
"IntDestroyMenuObject %d\n",
ret);
361 NONCLIENTMETRICSW ncm;
366 ncm.cbSize =
sizeof(ncm);
369 ERR(
"MenuInit(): SystemParametersInfo(SPI_GETNONCLIENTMETRICS) failed!\n");
376 ERR(
"MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n");
383 ERR(
"MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n");
410 if (!pmenu)
return depth;
421 if( bdepth > subdepth) subdepth = bdepth;
491 for(--
i;
i != 0; --
i) {
511 UINT fallback_pos = 0;
514 if (!menu)
return NULL;
536 else if (
item->wID == *nPos)
543 else if (
item->wID == *nPos)
552 *nPos = fallback_pos;
572 if (!
item->spSubMenu)
576 if (
item->spSubMenu == SubTarget)
601 TRACE(
"(menu=%p pos=%04x flags=%04x)\n",pMenu, nPos,
wFlags);
607 if (bRecurse &&
item->spSubMenu)
619 while (nPos < pMenu->cItems)
651 if (submenu) *submenu = menu;
673 WARN(
"allocation failed\n" );
687 return &newItems[
pos];
703 if (MAX_MENU_ITEMS <= MenuObject->cItems)
709 SubMenu = MenuObject;
723 TRACE(
"IntInsertMenuItemToList = %u %i\n", uItem, (
BOOL)((
INT)uItem >= 0));
780 if(!NewMenuItem)
return FALSE;
786 MenuItem =
Source->rgItems;
787 for (
i = 0;
i <
Source->cItems;
i++, MenuItem++, NewMenuItem++)
791 NewMenuItem->
wID = MenuItem->
wID;
866 ERR(
"SetMenuFlagRtoL\n");
881 if(lpmi->
fMask & MIM_BACKGROUND)
883 if(lpmi->
fMask & MIM_HELPID)
885 if(lpmi->
fMask & MIM_MAXHEIGHT)
887 if(lpmi->
fMask & MIM_MENUDATA)
889 if(lpmi->
fMask & MIM_STYLE)
916 if(lpmi->
fMask & MIM_BACKGROUND)
918 if(lpmi->
fMask & MIM_HELPID)
920 if(lpmi->
fMask & MIM_MAXHEIGHT)
922 if(lpmi->
fMask & MIM_MENUDATA)
924 if(lpmi->
fMask & MIM_STYLE)
926 if(lpmi->
fMask & MIM_APPLYTOSUBMENUS)
932 if (
item->spSubMenu )
952 if ( lpmi->
fMask & MIM_STYLE)
986 lpmii->
wID = MenuItem->
wID;
1035 PMENU SubMenuObject;
1038 if(!MenuItem || !MenuObject || !lpmii)
1044 MenuItem->
fType &= ~MENUITEMINFO_TYPE_MASK;
1052 ERR(
"IntSetMenuItemInfo: Invalid combination of fMask bits used\n");
1087 MenuItem->
fState &= ~MFS_HBMMENUBMP;
1100 MenuItem->
wID = lpmii->
wID;
1121 if (MenuObject == SubMenuObject)
1124 ERR(
"Pop Up Menu Double Trouble!\n");
1129 if (!SubMenuObject)
return FALSE;
1135 ERR(
"Loop detected in menu hierarchy or maximum menu depth exceeded!\n");
1222 if (!(MenuItem =
MENU_FindItem( &MenuObject, &uIDEnableItem, uEnable )))
return (
UINT)-1;
1231 switch (MenuItem->
wID)
1264 if (!(MenuItem =
MENU_FindItem( &MenuObject, &uIDCheckItem, uCheck )))
return -1;
1279 if (!MenuItem)
return FALSE;
1282 for (
i = 0;
i < MenuObject->
cItems;
i++, MenuItem++)
1284 MenuItem->
fState &= ~MFS_DEFAULT;
1288 if(uItem == (
UINT)-1)
1292 MenuItem = MenuObject->
rgItems;
1301 for (
i = 0;
i < MenuObject->
cItems;
i++, MenuItem++)
1303 if (MenuItem->
wID == uItem)
1321 if (!MenuItem)
return -1;
1326 if (
i >= MenuObject->
cItems )
return -1;
1339 if ( -1 !=
ret )
return ret;
1343 return ( fByPos ) ?
i : MenuItem->
wID;
1420 ERR(
"Invalid popup magic bitmap %d\n", (
int)popupMagic);
1466 UINT arrow_bitmap_height;
1468 rect->top += arrow_bitmap_height - menu->
iTop;
1469 rect->bottom += arrow_bitmap_height - menu->
iTop;
1524 if (!menu)
return -1;
1541 TRACE(
"\tlooking for '%c' (0x%02x) in [%p]\n", (
char)
Key,
Key, menu );
1549 if ( !ForceMenuChar )
1566 while (
p !=
NULL &&
p [1] ==
'&');
1643 size->cx = bm.bmWidth;
1644 size->cy = bm.bmHeight;
1662 int bmp_xoffset = 0;
1684 ERR(
"Get Item Data from this Window!!!\n");
1687 ERR(
"Draw Bitmap\n");
1783 top = (
h>bm.bmHeight) ?
rect->top+(
h-bm.bmHeight)/2 :
rect->top;
1795 NtGdiBitBlt(
hdc,
left,
top,
w,
h,
hdcMem, bmp_xoffset, 0,
rop , 0, 0);
1830 UINT arrow_bitmap_width;
1834 TRACE(
"dc=%x owner=%x (%d,%d)\n",
hdc, pwndOwner, orgX, orgY);
1866 TRACE(
"MF_OWNERDRAW id=%04lx size=%dx%d cx %d cy %d\n",
1878 lpitem->
xItem = orgX;
1879 lpitem->
yItem = orgY;
1905 itemheight =
size.cy + 2;
1908 lpitem->
cxItem += 2 * check_bitmap_width;
1911 lpitem->
cxItem += arrow_bitmap_width;
1916 itemheight =
size.cy;
1924 else if (!menuBar) {
1926 lpitem->
cxItem += check_bitmap_width;
1929 lpitem->
cxItem += arrow_bitmap_width;
1936 LONG txtheight, txtwidth;
1967 lpitem->
dxTab += txtwidth;
1968 txtheight =
max( txtheight, tmpheight);
1975 lpitem->
dxTab += txtwidth;
1977 lpitem->
cxItem += 2 + txtwidth;
1978 itemheight =
max( itemheight,
1985 }
else if( menuBar) {
1988 lpitem->
cyItem += itemheight;
2001 return lppop->
cyMax;
2017 int orgX, orgY, maxX, maxTab, maxTabWidth, maxHeight;
2021 if (Menu->
cItems == 0)
return;
2032 while (start < Menu->cItems)
2040 maxTab = maxTabWidth = 0;
2052 maxTab =
max( maxTab, lpitem->
dxTab );
2059 maxX =
max( maxX, maxTab + maxTabWidth );
2064 lpitem->
dxTab = maxTab;
2080 if (Menu->
cyMenu >= maxHeight)
2082 Menu->
cyMenu = maxHeight;
2105 int orgX, orgY, maxY;
2107 if ((lprect ==
NULL) || (lppop ==
NULL))
return;
2108 if (lppop->
cItems == 0)
return;
2116 while (start < lppop->cItems)
2119 orgX = lprect->
left;
2129 TRACE(
"calling MENU_CalcItemSize org=(%d, %d)\n", orgX, orgY );
2134 if (lpitem->cxItem > lprect->
right)
2137 else lpitem->cxItem = lprect->
right;
2139 maxY =
max( maxY, lpitem->cyItem );
2140 orgX = lpitem->cxItem;
2153 lprect->
bottom = maxY + 1;
2158 if (helpPos == ~0
U)
return;
2160 orgY = lpitem->yItem;
2161 orgX = lprect->
right;
2162 for (
i = lppop->
cItems - 1;
i >= helpPos;
i--, lpitem--) {
2163 if (lpitem->yItem != orgY)
break;
2164 if (lpitem->cxItem >= orgX)
break;
2165 lpitem->xItem += orgX - lpitem->cxItem;
2166 lpitem->cxItem = orgX;
2167 orgX = lpitem->xItem;
2178 UINT arrow_bitmap_height;
2187 rect.bottom = arrow_bitmap_height;
2191 rect.top = lppop->
cyMenu - arrow_bitmap_height;
2211 UINT arrow_bitmap_width = 0;
2229 bkgnd = (menuBar && flat_menu) ? COLOR_MENUBAR :
COLOR_MENU;
2235 if(menuBar && !flat_menu) {
2294 TRACE(
"Ownerdraw: owner=%p itemID=%d, itemState=%d, itemAction=%d, "
2295 "hwndItem=%p, hdc=%p, rcItem={%ld,%ld,%ld,%ld}\n", Wnd,
2413 bmprc.right = bmprc.left + lpitem->
cxBmp;
2420 bmprc.bottom = bmprc.top + lpitem->
cyBmp;
2445 check_bitmap_width, check_bitmap_height,
2454 r.right =
r.left + check_bitmap_width;
2465 bmpRect.
left += check_bitmap_width + 2;
2477 rectTemp.
left = rectTemp.
right - check_bitmap_width;
2482 rect.left += check_bitmap_width;
2483 rect.right -= arrow_bitmap_width;
2485 else if( lpitem->
hbmp)
2496 UINT uFormat = menuBar ?
2550 if (!menuBar &&
L'\0' !=
Text[
i])
2604 TRACE(
"DPM wnd=%p dc=%p menu=%p\n", wnd,
hdc, menu);
2622 if (menu && menu->
cItems)
2674 ERR(
"Already in End loop\n");
2790 TRACE(
"owner=%p hmenu=%p\n", pWndOwner, menu);
2813 if( !pWndCreated )
return FALSE;
2820 pPopupMenu = ((
PMENUWND)pWndCreated)->ppopupmenu;
2846#define SHOW_DEBUGRECT 0
2904 if (pExclude->
bottom + height < monitor->rcMonitor.bottom)
2924 if (pExclude->
right + width < monitor->rcMonitor.right)
2949 TRACE(
"owner=%p menu=%p id=0x%04x x=0x%04x y=0x%04x\n",
2950 pwndOwner, menu,
id,
x,
y);
2960 DebugRect(pExclude,
RGB(255, 0, 0));
2971 if (
flags & TPM_LAYOUTRTL)
2988 DebugPoint(
x,
y,
RGB(0, 0, 255));
3000 if (x < monitor->rcMonitor.left)
3005 if (x < monitor->rcMonitor.left ||
x >= monitor->
rcMonitor.
right || bIsPopup)
3010 if (y < monitor->rcMonitor.top)
3014 if (y < monitor->rcMonitor.top ||
y >= monitor->
rcMonitor.
bottom || bIsPopup)
3041 UINT flag_mods[] = {
3070 DebugRect(&rr,
RGB(0, 255, 0));
3078 ERR(
"menu->hWnd bad hwnd %p\n",menu->
hWnd);
3111 UINT arrow_bitmap_height;
3118 rc.
top += arrow_bitmap_height;
3119 rc.
bottom -= arrow_bitmap_height;
3123 if (
item->cyItem > lppop->
iTop + nMaxHeight)
3125 lppop->
iTop =
item->cyItem - nMaxHeight;
3130 else if (
item->yItem < lppop->
iTop)
3150 TRACE(
"M_SI: owner=%p menu=%p index=0x%04x select=0x%04x\n", pwndOwner, menu, wIndex, sendMenuSelect);
3152 if (!menu || !menu->
cItems)
return;
3158 if (menu->
iItem == wIndex)
return;
3183 menu->
iItem = wIndex;
3197 ip->fType |
ip->fState |
3204 else if (sendMenuSelect)
3235 TRACE(
"pwnd=%x menu=%x off=0x%04x\n", pwndOwner, menu,
offset);
3237 if ((!menu) || (!menu->
rgItems))
return;
3254 i >= 0 && i < menu->cItems ;
i +=
offset)
3270 TRACE(
"owner=%x menu=%x 0x%04x\n", pWndOwner, Menu, SendMenuSelect);
3279 if (!(
Item->spSubMenu) ||
3286 if (
Item->spSubMenu)
3328 TRACE(
"owner=%x menu=%p 0x%04x\n", WndOwner, Menu, SelectFirst);
3330 if (!Menu)
return Menu;
3429 if(
Flags & TPM_LAYOUTRTL)
3438 if(
Flags & TPM_LAYOUTRTL)
3450 Flags &= (~TPM_VERTICAL);
3465 return Item->spSubMenu;
3482 TRACE(
"%p menu=%p\n", pmt, Menu);
3493 if (!(
Item->spSubMenu))
3535 TRACE(
"%x menu=%x 0x%04x\n", pmt, PtMenu,
Index);
3537 if ( pmt->
TopMenu != PtMenu &&
3560 TRACE(
"%x PtMenu=%p\n", pmt, PtMenu);
3579 if (PtMenu->
iItem !=
id)
3605 TRACE(
"%p pmenu=%x\n", pmt, PtMenu);
3624 if (!(
item->spSubMenu))
3627 if (ExecutedMenuId == -1 || ExecutedMenuId == -2)
return -1;
3628 return ExecutedMenuId;
3657 if (!menu)
return NULL;
3663 if ( pItem ) pItem = &pItem[menu->
iItem];
3725 return item->spSubMenu;
3751 while (i < pmt->TopMenu->cItems) {
3784 TRACE(
"%p [%p] -> %p [%p]\n",
3814 else hNewMenu =
NULL;
3837 WARN(
" -- got confused.\n");
3921 PMENU MenuPrev, MenuTmp;
3923 MenuPrev = MenuTmp = pmt->
TopMenu;
3948 PMENU MenuTmp, MenuPrev;
3951 MenuPrev = MenuTmp = pmt->
TopMenu;
3999 TRACE(
"MenuKeyRight called, cur %p, top %p.\n",