/* INCLUDES ******************************************************************/
-#include "user32.h"
-#include <ctype.h>
-#include <string.h>
-#include <draw.h>
-#include <window.h>
-#include <strpool.h>
-#include <user32/callback.h>
-#include "user32/regcontrol.h"
-#include "../controls/controls.h"
-
+#include <user32.h>
#define NDEBUG
#include <debug.h>
(0 != ((MenuInfo)->Flags & MF_POPUP) && 0 != ((MenuInfo)->Flags & MF_SYSMENU))
#define IS_MAGIC_ITEM(Bmp) ((int) Bmp <12)
-
+
#define MENU_BAR_ITEMS_SPACE (12)
#define SEPARATOR_HEIGHT (5)
#define MENU_TAB_SPACE (8)
/* INTERNAL FUNCTIONS ********************************************************/
-/* Rip the fun and easy to use and fun WINE unicode string manipulation routines.
- * Of course I didnt copy the ASM code because we want this to be portable
+/* Rip the fun and easy to use and fun WINE unicode string manipulation routines.
+ * Of course I didnt copy the ASM code because we want this to be portable
* and it needs to go away.
*/
{
MenuInfo->cbSize = sizeof(ROSMENUINFO);
MenuInfo->fMask = MIM_BACKGROUND | MIM_HELPID | MIM_MAXHEIGHT | MIM_MENUDATA | MIM_STYLE;
-
+
return NtUserMenuInfo(Menu, MenuInfo, FALSE);
}
{
MenuInfo->cbSize = sizeof(ROSMENUINFO);
MenuInfo->fMask = MIM_BACKGROUND | MIM_HELPID | MIM_MAXHEIGHT | MIM_MENUDATA | MIM_STYLE;
-
+
return NtUserMenuInfo(MenuInfo->Self, MenuInfo, TRUE);
}
ItemInfo->fMask = MIIM_BITMAP | MIIM_CHECKMARKS | MIIM_DATA | MIIM_FTYPE
| MIIM_ID | MIIM_STATE | MIIM_STRING | MIIM_SUBMENU | MIIM_TYPE;
-
+
Ret = NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, TRUE);
return Ret;
MenuInit(VOID)
{
NONCLIENTMETRICSW ncm;
-
+
/* get the menu font */
if(!hMenuFont || !hMenuFontBold)
{
DbgPrint("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n");
return FALSE;
}
-
+
hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont);
if(hMenuFont == NULL)
{
DbgPrint("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n");
return FALSE;
}
-
+
ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000);
hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont);
if(hMenuFontBold == NULL)
{
DbgPrint("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n");
+ DeleteObject(hMenuFont);
+ hMenuFont = NULL;
return FALSE;
}
}
}
+VOID
+MenuCleanup(VOID)
+{
+ if (hMenuFont)
+ {
+ DeleteObject(hMenuFont);
+ hMenuFont = NULL;
+ }
+
+ if (hMenuFontBold)
+ {
+ DeleteObject(hMenuFontBold);
+ hMenuFontBold = NULL;
+ }
+}
+
+
+
/***********************************************************************
* MenuCalcItemSize
*
i = -1;
}
else
- {
- i = MenuInfo->FocusedItem;
+ {
+ i = MenuInfo->FocusedItem;
}
do
{
EnableMenuItem(Menu, SC_CLOSE, MF_GRAYED);
}
-
+
/* Set default menu item */
if(Style & WS_MINIMIZE)
{
#if 0
mii.cbSize = sizeof(MENUITEMINFOW);
mii.fMask = MIIM_STATE;
- if((DefItem != SC_CLOSE) && GetMenuItemInfoW(Menu, DefItem, FALSE, &mii) &&
+ if((DefItem != SC_CLOSE) && GetMenuItemInfoW(Menu, DefItem, FALSE, &mii) &&
(mii.fState & (MFS_GRAYED | MFS_DISABLED)))
{
DefItem = SC_CLOSE;
case WM_SYSKEYDOWN:
switch (Msg.wParam)
{
+ DbgPrint("Menu.c WM_SYSKEYDOWN wPram %d\n",Msg.wParam);
case VK_MENU:
fEndMenu = TRUE;
break;
+ case VK_LMENU:
+ fEndMenu = TRUE;
+ break;
}
break; /* WM_SYSKEYDOWN */
Mt.TrackFlags &= ~TF_SKIPREMOVE;
}
}
-
+
NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, NULL);
SetCapture(NULL); /* release the capture */
UINT_PTR uIDNewItem,
LPCSTR lpNewItem)
{
- return(InsertMenuA(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem,
+ return(InsertMenuA(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem,
lpNewItem));
}
UINT_PTR uIDNewItem,
LPCWSTR lpNewItem)
{
- return(InsertMenuW(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem,
+ return(InsertMenuW(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem,
lpNewItem));
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL STDCALL
CheckMenuRadioItem(HMENU hmenu,
UINT idCheck,
UINT uFlags)
{
+ ROSMENUINFO mi;
+ PROSMENUITEMINFO Items;
+ int i;
+ BOOL ret = FALSE;
+
+ mi.cbSize = sizeof(MENUINFO);
+
UNIMPLEMENTED;
- return FALSE;
+
+ if(idFirst > idLast) return ret;
+
+ if(!NtUserMenuInfo(hmenu, &mi, FALSE)) return ret;
+
+ if(MenuGetAllRosMenuItemInfo(mi.Self, &Items) <= 0) return ret;
+
+ for (i = 0 ; i < mi.MenuItemCount; i++)
+ {
+ if (0 != (Items[i].fType & MF_MENUBARBREAK)) break;
+ if ( i >= idFirst && i <= idLast )
+ {
+ if ( i == idCheck)
+ {
+ Items[i].fType |= MFT_RADIOCHECK;
+ Items[i].fState |= MFS_CHECKED;
+ }
+ else
+ {
+ Items[i].fType &= ~MFT_RADIOCHECK;
+ Items[i].fState &= ~MFS_CHECKED;
+ }
+ if(!MenuSetRosMenuItemInfo(mi.Self, i ,&Items[i]))
+ break;
+ }
+ if ( i == mi.MenuItemCount) ret = TRUE;
+ }
+ MenuCleanupRosMenuItemInfo(Items);
+ return ret;
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL STDCALL
DrawMenuBar(HWND hWnd)
{
- UNIMPLEMENTED
- /* FIXME - return NtUserCallHwndLock(hWnd, 0x55); */
- return FALSE;
+ return (BOOL)NtUserCallHwndLock(hWnd, HWNDLOCK_ROUTINE_DRAWMENUBAR);
}
LONG STDCALL
GetMenuCheckMarkDimensions(VOID)
{
- return(MAKELONG(GetSystemMetrics(SM_CXMENUCHECK),
+ return(MAKELONG(GetSystemMetrics(SM_CXMENUCHECK),
GetSystemMetrics(SM_CYMENUCHECK)));
}
{
ROSMENUINFO mi;
BOOL res = FALSE;
-
+
if(!lpcmi || (lpcmi->cbSize != sizeof(MENUINFO)))
return FALSE;
-
+
RtlZeroMemory(&mi, sizeof(MENUINFO));
mi.cbSize = sizeof(MENUINFO);
mi.fMask = lpcmi->fMask;
-
+
res = NtUserMenuInfo(hmenu, &mi, FALSE);
-
+
memcpy(lpcmi, &mi, sizeof(MENUINFO));
return res;
}
int nPos)
{
ROSMENUITEMINFO mii;
-
+
mii.cbSize = sizeof(MENUITEMINFOW);
mii.fMask = MIIM_ID | MIIM_SUBMENU;
-
+
if (! NtUserMenuItemInfo(hMenu, nPos, MF_BYPOSITION, &mii, FALSE))
{
return -1;
}
-
+
if (NULL != mii.hSubMenu)
{
return -1;
{
return -1;
}
-
+
return mii.wID;
}
if (miiW.dwTypeData == NULL)
return FALSE;
}
-
+
if (!NtUserMenuItemInfo(Menu, Item, ByPosition, (PROSMENUITEMINFO)&miiW, FALSE))
{
HeapFree(GetProcessHeap(), 0, miiW.dwTypeData);
}
RtlCopyMemory(mii, &miiW, miiW.cbSize);
- mii->dwTypeData = AnsiBuffer;
-
+ if (AnsiBuffer)
+ {
+ mii->dwTypeData = AnsiBuffer;
+ mii->cch = strlen(AnsiBuffer);
+ }
return TRUE;
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL STDCALL
GetMenuItemRect(HWND hWnd,
UINT uItem,
LPRECT lprcItem)
{
- UNIMPLEMENTED;
- return(FALSE);
+ return NtUserGetMenuItemRect( hWnd, hMenu, uItem, lprcItem);
}
mii.cbSize = sizeof(MENUITEMINFOW);
mii.fMask = MIIM_STATE | MIIM_TYPE | MIIM_SUBMENU;
mii.dwTypeData = NULL;
-
+
SetLastError(0);
if(NtUserMenuItemInfo(hMenu, uId, uFlags, &mii, FALSE))
{
return (UINT) -1;
}
nSubItems = MenuInfo.MenuItemCount;
-
+
/* FIXME - ported from wine, does that work (0xff)? */
if(GetLastError() != ERROR_INVALID_MENU_HANDLE)
return (nSubItems << 8) | ((mii.fState | mii.fType) & 0xff);
return (UINT)-1; /* Invalid submenu */
}
-
+
/* FIXME - ported from wine, does that work? */
return (mii.fType | mii.fState);
}
-
+
return (UINT)-1;
}
/*
- * @unimplemented
+ * @implemented
*/
int
STDCALL
int nMaxCount,
UINT uFlag)
{
- UNIMPLEMENTED;
- return 0;
+ MENUITEMINFOA mii;
+ mii.dwTypeData = lpString;
+ mii.fMask = MIIM_STRING;
+ mii.fType = MF_STRING;
+ mii.cbSize = sizeof(MENUITEMINFOA);
+ mii.cch = nMaxCount;
+
+ if(!(GetMenuItemInfoA( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&mii)))
+ return 0;
+ else
+ return mii.cch;
}
/*
- * @unimplemented
+ * @implemented
*/
int
STDCALL
int nMaxCount,
UINT uFlag)
{
- UNIMPLEMENTED;
- return 0;
+ MENUITEMINFOW miiW;
+ miiW.dwTypeData = lpString;
+ miiW.fMask = MIIM_STRING;
+ miiW.cbSize = sizeof(MENUITEMINFOW);
+ miiW.cch = nMaxCount;
+
+ if(!(GetMenuItemInfoW( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&miiW)))
+ return 0;
+ else
+ return miiW.cch;
}
mii.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
mii.fType = 0;
mii.fState = MFS_ENABLED;
-
+
if(uFlags & MF_BITMAP)
{
mii.fType |= MFT_BITMAP;
mii.dwTypeData = (LPSTR)lpNewItem;
mii.cch = (NULL == lpNewItem ? 0 : strlen(lpNewItem));
}
-
+
if(uFlags & MF_RIGHTJUSTIFY)
{
mii.fType |= MFT_RIGHTJUSTIFY;
{
mii.fState |= MFS_GRAYED;
}
-
+
if(uFlags & MF_POPUP)
{
mii.fType |= MF_POPUP;
mii.fMask |= MIIM_ID;
mii.wID = (UINT)uIDNewItem;
}
- return InsertMenuItemA(hMenu, uPosition, (BOOL)!(MF_BYPOSITION & uFlags), &mii);
+ return InsertMenuItemA(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii);
}
BOOL CleanHeap = FALSE;
NTSTATUS Status;
- if((lpmii->cbSize == sizeof(MENUITEMINFOA)) ||
+ if((lpmii->cbSize == sizeof(MENUITEMINFOA)) ||
(lpmii->cbSize == sizeof(MENUITEMINFOA) - sizeof(HBITMAP)))
{
RtlMoveMemory ( &mi, lpmii, lpmii->cbSize );
/* copy the text string */
- if((mi.fMask & (MIIM_TYPE | MIIM_STRING)) &&
+ if((mi.fMask & (MIIM_TYPE | MIIM_STRING)) &&
(MENU_ITEM_TYPE(mi.fType) == MF_STRING) && mi.dwTypeData)
{
Status = RtlCreateUnicodeStringFromAsciiz(&MenuText, (LPSTR)mi.dwTypeData);
if a bad user passes bad data, we crash his process instead of the
entire kernel */
- if((lpmii->cbSize == sizeof(MENUITEMINFOW)) ||
+ if((lpmii->cbSize == sizeof(MENUITEMINFOW)) ||
(lpmii->cbSize == sizeof(MENUITEMINFOW) - sizeof(HBITMAP)))
{
memcpy(&mi, lpmii, lpmii->cbSize);
-
+
/* copy the text string */
- if((mi.fMask & (MIIM_TYPE | MIIM_STRING)) &&
+ if((mi.fMask & (MIIM_TYPE | MIIM_STRING)) &&
(MENU_ITEM_TYPE(mi.fType) == MF_STRING) &&
mi.dwTypeData != NULL)
{
mi.dwTypeData = MenuText.Buffer;
mi.cch = MenuText.Length / sizeof(WCHAR);
};
-
+
res = NtUserInsertMenuItem(hMenu, uItem, fByPosition, &mi);
}
return res;
mii.dwTypeData = (LPWSTR)lpNewItem;
mii.cch = (NULL == lpNewItem ? 0 : wcslen(lpNewItem));
}
-
+
if(uFlags & MF_RIGHTJUSTIFY)
{
mii.fType |= MFT_RIGHTJUSTIFY;
{
mii.fState |= MFS_GRAYED;
}
-
+
if(uFlags & MF_POPUP)
{
mii.fType |= MF_POPUP;
mii.fMask |= MIIM_ID;
mii.wID = (UINT)uIDNewItem;
}
- return InsertMenuItemW(hMenu, uPosition, (BOOL)!(MF_BYPOSITION & uFlags), &mii);
+ return InsertMenuItemW(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii);
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL
STDCALL
UINT_PTR uIDNewItem,
LPCSTR lpNewItem)
{
+ MENUITEMINFOA mii;
+ memset( &mii, 0, sizeof(mii) );
+ mii.cbSize = sizeof(MENUITEMINFOA);
+ mii.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
+ mii.fType = 0;
+ mii.fState = MFS_ENABLED;
+
UNIMPLEMENTED;
- return FALSE;
+
+ if(!GetMenuItemInfoA( hMnu,
+ uPosition,
+ (BOOL)(MF_BYPOSITION & uFlags),
+ &mii)) return FALSE;
+
+ if(uFlags & MF_BITMAP)
+ {
+ mii.fType |= MFT_BITMAP;
+ mii.fMask |= MIIM_BITMAP;
+ mii.hbmpItem = (HBITMAP) lpNewItem;
+ }
+ else if(uFlags & MF_OWNERDRAW)
+ {
+ mii.fType |= MFT_OWNERDRAW;
+ mii.fMask |= MIIM_DATA;
+ mii.dwItemData = (DWORD) lpNewItem;
+ }
+ else /* Default action MF_STRING. */
+ {
+ if(mii.dwTypeData != NULL)
+ {
+ HeapFree(GetProcessHeap(),0, mii.dwTypeData);
+ }
+ /* Item beginning with a backspace is a help item */
+ if (*lpNewItem == '\b')
+ {
+ mii.fType |= MF_HELP;
+ lpNewItem++;
+ }
+ mii.fMask |= MIIM_TYPE;
+ mii.dwTypeData = (LPSTR)lpNewItem;
+ mii.cch = (NULL == lpNewItem ? 0 : strlen(lpNewItem));
+ }
+
+ if(uFlags & MF_RIGHTJUSTIFY)
+ {
+ mii.fType |= MFT_RIGHTJUSTIFY;
+ }
+ if(uFlags & MF_MENUBREAK)
+ {
+ mii.fType |= MFT_MENUBREAK;
+ }
+ if(uFlags & MF_MENUBARBREAK)
+ {
+ mii.fType |= MFT_MENUBARBREAK;
+ }
+ if(uFlags & MF_DISABLED)
+ {
+ mii.fState |= MFS_DISABLED;
+ }
+ if(uFlags & MF_GRAYED)
+ {
+ mii.fState |= MFS_GRAYED;
+ }
+
+ if ((mii.fType & MF_POPUP) && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem))
+ NtUserDestroyMenu( mii.hSubMenu ); /* ModifyMenu() spec */
+
+ if(uFlags & MF_POPUP)
+ {
+ mii.fType |= MF_POPUP;
+ mii.fMask |= MIIM_SUBMENU;
+ mii.hSubMenu = (HMENU)uIDNewItem;
+ }
+ else
+ {
+ mii.fMask |= MIIM_ID;
+ mii.wID = (UINT)uIDNewItem;
+ }
+
+ return SetMenuItemInfoA( hMnu,
+ uPosition,
+ (BOOL)(MF_BYPOSITION & uFlags),
+ &mii);
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL
STDCALL
UINT_PTR uIDNewItem,
LPCWSTR lpNewItem)
{
+ MENUITEMINFOW mii;
+ memset ( &mii, 0, sizeof(mii) );
+ mii.cbSize = sizeof(MENUITEMINFOW);
+ mii.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
+ mii.fState = MFS_ENABLED;
+
UNIMPLEMENTED;
- return FALSE;
+
+ if(!NtUserMenuItemInfo( hMnu,
+ uPosition,
+ (BOOL)(MF_BYPOSITION & uFlags),
+ (PROSMENUITEMINFO) &mii,
+ FALSE)) return FALSE;
+
+ if(uFlags & MF_BITMAP)
+ {
+ mii.fType |= MFT_BITMAP;
+ mii.fMask |= MIIM_BITMAP;
+ mii.hbmpItem = (HBITMAP) lpNewItem;
+ }
+ else if(uFlags & MF_OWNERDRAW)
+ {
+ mii.fType |= MFT_OWNERDRAW;
+ mii.fMask |= MIIM_DATA;
+ mii.dwItemData = (DWORD) lpNewItem;
+ }
+ else
+ {
+ /*if(mii.dwTypeData != NULL)
+ {
+ HeapFree(GetProcessHeap(),0, mii.dwTypeData);
+ }*/
+ if (*lpNewItem == '\b')
+ {
+ mii.fType |= MF_HELP;
+ lpNewItem++;
+ }
+ mii.fMask |= MIIM_TYPE;
+ mii.dwTypeData = (LPWSTR)lpNewItem;
+ mii.cch = (NULL == lpNewItem ? 0 : wcslen(lpNewItem));
+ }
+
+ if(uFlags & MF_RIGHTJUSTIFY)
+ {
+ mii.fType |= MFT_RIGHTJUSTIFY;
+ }
+ if(uFlags & MF_MENUBREAK)
+ {
+ mii.fType |= MFT_MENUBREAK;
+ }
+ if(uFlags & MF_MENUBARBREAK)
+ {
+ mii.fType |= MFT_MENUBARBREAK;
+ }
+ if(uFlags & MF_DISABLED)
+ {
+ mii.fState |= MFS_DISABLED;
+ }
+ if(uFlags & MF_GRAYED)
+ {
+ mii.fState |= MFS_GRAYED;
+ }
+
+ if ((mii.fType & MF_POPUP) && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem))
+ NtUserDestroyMenu( mii.hSubMenu );
+
+ if(uFlags & MF_POPUP)
+ {
+ mii.fType |= MF_POPUP;
+ mii.fMask |= MIIM_SUBMENU;
+ mii.hSubMenu = (HMENU)uIDNewItem;
+ }
+ else
+ {
+ mii.fMask |= MIIM_ID;
+ mii.wID = (UINT)uIDNewItem;
+ }
+
+ return SetMenuItemInfoW( hMnu,
+ uPosition,
+ (BOOL)(MF_BYPOSITION & uFlags),
+ &mii);
}
BOOL res = FALSE;
if(lpcmi->cbSize != sizeof(MENUINFO))
return res;
-
+
memcpy(&mi, lpcmi, sizeof(MENUINFO));
return NtUserMenuInfo(hmenu, &mi, TRUE);
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL
STDCALL
HBITMAP hBitmapUnchecked,
HBITMAP hBitmapChecked)
{
- UNIMPLEMENTED;
- return FALSE;
+ ROSMENUITEMINFO uItem;
+
+ if(!(NtUserMenuItemInfo(hMenu, uPosition,
+ (BOOL)(MF_BYPOSITION & uFlags), &uItem, FALSE))) return FALSE;
+
+ if (!hBitmapChecked && !hBitmapUnchecked)
+ {
+ uItem.fState &= ~MF_USECHECKBITMAPS;
+ }
+ else /* Install new bitmaps */
+ {
+ uItem.hbmpChecked = hBitmapChecked;
+ uItem.hbmpUnchecked = hBitmapUnchecked;
+ uItem.fState |= MF_USECHECKBITMAPS;
+ }
+ return NtUserMenuItemInfo(hMenu, uPosition,
+ (BOOL)(MF_BYPOSITION & uFlags), &uItem, TRUE);
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL
STDCALL
/*
- * @unimplemented
+ * @implemented
*/
BOOL
STDCALL
MENUITEMINFOW MenuItemInfoW;
RtlCopyMemory(&MenuItemInfoW, lpmii, min(lpmii->cbSize, sizeof(MENUITEMINFOW)));
- MenuItemInfoW.cch = wcslen(MenuItemInfoW.dwTypeData);
+ if (0 != (MenuItemInfoW.fMask & MIIM_STRING))
+ {
+ MenuItemInfoW.cch = wcslen(MenuItemInfoW.dwTypeData);
+ }
return NtUserMenuItemInfo(hMenu, uItem, fByPosition,
(PROSMENUITEMINFO)&MenuItemInfoW, TRUE);
BOOL
STDCALL
SetSystemMenu (
- HWND hwnd,
+ HWND hwnd,
HMENU hMenu)
{
if(!hwnd)
ROSMENUINFO mi;
mi.cbSize = sizeof(ROSMENUINFO);
mi.fMask = MIM_HELPID;
-
+
if(NtUserMenuInfo(hmenu, &mi, FALSE))
{
return mi.dwContextHelpID;
{
case MF_APPEND :
return AppendMenuW(hMenu, flags &~ MF_APPEND, cmdInsert, lpszNewItem);
-
+
case MF_DELETE :
return DeleteMenu(hMenu, cmd, flags &~ MF_DELETE);
{
case MF_APPEND :
return AppendMenuA(hMenu, flags &~ MF_APPEND, cmdInsert, lpszNewItem);
-
+
case MF_DELETE :
return DeleteMenu(hMenu, cmd, flags &~ MF_DELETE);