Skip to content
Snippets Groups Projects
menu.c 63.2 KiB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
/*
 *        Menus functions
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
static char RCSId[] = "$Id$";
Alexandre Julliard's avatar
Alexandre Julliard committed
static char Copyright[] = "Copyright  Martin Ayotte, 1993";
Alexandre Julliard's avatar
Alexandre Julliard committed

Alexandre Julliard's avatar
Alexandre Julliard committed
/*
Alexandre Julliard's avatar
Alexandre Julliard committed
#define DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
*/
Alexandre Julliard's avatar
Alexandre Julliard committed

Alexandre Julliard's avatar
Alexandre Julliard committed
#include <stdlib.h>
#include <stdio.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
#include "windows.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
#include "sysmetrics.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
#include "prototypes.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
#include "menu.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
#include "user.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
#include "heap.h"
#include "win.h"

Alexandre Julliard's avatar
Alexandre Julliard committed
#define SC_ABOUTWINE    	SC_SCREENSAVE+1
#define SC_SYSMENU			SC_SCREENSAVE+2
#define SC_ABOUTWINEDLG		SC_SCREENSAVE+3
Alexandre Julliard's avatar
Alexandre Julliard committed

extern HINSTANCE hSysRes;
HMENU	hSysMenu = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
HBITMAP hStdCheck = 0;
HBITMAP hStdMnArrow = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
static BOOL	MenuHasFocus = FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed

Alexandre Julliard's avatar
Alexandre Julliard committed
LPPOPUPMENU PopupMenuGetStorageHeader(HWND hwnd);
LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop, 
		    BOOL suppress_draw);
Alexandre Julliard's avatar
Alexandre Julliard committed
BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
Alexandre Julliard's avatar
Alexandre Julliard committed
void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y);
Alexandre Julliard's avatar
Alexandre Julliard committed
void StdDrawPopupMenu(HWND hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
void ResetHiliteFlags(LPPOPUPMENU lppop);
BOOL ExecFocusedMenuItem(HWND hWnd, LPPOPUPMENU lppop);
void MenuItemSelect(HWND hWnd, LPPOPUPMENU lppop, WORD wIndex);
Alexandre Julliard's avatar
Alexandre Julliard committed
LPMENUITEM MenuFindItem(LPPOPUPMENU lppop, int x, int y, WORD *lpRet);
LPMENUITEM MenuFindItemBySelKey(LPPOPUPMENU lppop, WORD key, WORD *lpRet);
Alexandre Julliard's avatar
Alexandre Julliard committed
BOOL ActivateMenuBarFocus(HWND hWnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
BOOL MenuFocusLoop(HWND hWnd, LPPOPUPMENU lpmenu);
Alexandre Julliard's avatar
Alexandre Julliard committed
void PopupMenuCalcSize(HWND hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
void MenuBarCalcSize(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop);
Alexandre Julliard's avatar
Alexandre Julliard committed
LPMENUITEM FindMenuItem(HMENU hMenu, WORD nPos, WORD wFlags);
Alexandre Julliard's avatar
Alexandre Julliard committed
LPMENUITEM GetMenuItemPtr(LPPOPUPMENU menu, WORD nPos);
Alexandre Julliard's avatar
Alexandre Julliard committed
WORD GetSelectionKey(LPSTR str);
LPSTR GetShortCutString(LPSTR str);
WORD GetShortCutPos(LPSTR str);
BOOL HideAllSubPopupMenu(LPPOPUPMENU menu);
Alexandre Julliard's avatar
Alexandre Julliard committed
void InitStdBitmaps();
Alexandre Julliard's avatar
Alexandre Julliard committed
HMENU CopySysMenu();
Alexandre Julliard's avatar
Alexandre Julliard committed
WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu);
void SetMenuLogicalParent(HMENU hMenu, HWND hWnd);
Alexandre Julliard's avatar
Alexandre Julliard committed

Alexandre Julliard's avatar
Alexandre Julliard committed
BOOL FAR PASCAL AboutWine_Proc(HWND hDlg, WORD msg, WORD wParam, LONG lParam);

Alexandre Julliard's avatar
Alexandre Julliard committed
/***********************************************************************
 *           PopupMenuWndProc
 */
LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
{    
Alexandre Julliard's avatar
Alexandre Julliard committed
	CREATESTRUCT *createStruct;
	WORD	wRet;
	short	x, y;
	WND  	*wndPtr;
	LPPOPUPMENU lppop, lppop2;
	LPMENUITEM	lpitem, lpitem2;
	HMENU	hSubMenu;
	RECT	rect;
	HDC		hDC;
	PAINTSTRUCT ps;
	switch(message) {
	case WM_CREATE:
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
		printf("PopupMenu WM_CREATE lParam=%08X !\n", lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
		createStruct = (CREATESTRUCT *)lParam;
		lppop = (LPPOPUPMENU)createStruct->lpCreateParams;
		if (lppop == NULL) break;
		wndPtr = WIN_FindWndPtr(hwnd);
		*((LPPOPUPMENU *)&wndPtr->wExtra[1]) = lppop;
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
		printf("PopupMenu WM_CREATE lppop=%08X !\n", lppop);
Alexandre Julliard's avatar
Alexandre Julliard committed
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
		InitStdBitmaps();
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
		printf("PopupMenu End of WM_CREATE !\n");
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
		return 0;
	case WM_DESTROY:
		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
		printf("PopupMenu WM_DESTROY %lX !\n", lppop);
Alexandre Julliard's avatar
Alexandre Julliard committed
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
		return 0;
	case WM_COMMAND:
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
		printf("PopupMenuWndProc // WM_COMMAND received !\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
		if (lppop == NULL) break;
		if (lppop->SysFlag) {
			MenuHasFocus = FALSE;
			if (wParam == SC_ABOUTWINE) {
				printf("SysMenu // Show 'About Wine ...' !\n");
/*				DialogBox(hSysRes, MAKEINTRESOURCE(SC_ABOUTWINEDLG), */
				DialogBox(hSysRes, MAKEINTRESOURCE(2), 
					GetParent(hwnd), (FARPROC)AboutWine_Proc);
				}
Alexandre Julliard's avatar
Alexandre Julliard committed
			else {
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
				printf("PopupMenuWndProc // push to Owner WM_SYSCOMMAND !\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
				PostMessage(lppop->ownerWnd, WM_SYSCOMMAND, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
				}
Alexandre Julliard's avatar
Alexandre Julliard committed
			break;
			}
#ifdef DEBUG_MENU
		printf("PopupMenuWndProc // push to Owner WM_COMMAND !\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
		MenuHasFocus = FALSE;
		PostMessage(lppop->hWndParent, WM_COMMAND, wParam, lParam);
		break;
	case WM_SHOWWINDOW:
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
		printf("PopupMenuWndProc // WM_SHOWWINDOW received !\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
		if (lppop == NULL) break;
		if (wParam == 0 && lParam == 0L) {
			HideAllSubPopupMenu(lppop);
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
			printf("PopupMenuWndProc hWnd=%04X WM_SHOWWINDOW -> HIDE!\n", hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
			if (lppop->SysFlag) MenuHasFocus = FALSE;
			SetFocus(lppop->hWndPrev);
Alexandre Julliard's avatar
Alexandre Julliard committed
			if (GetCapture() != 0) ReleaseCapture(); 
Alexandre Julliard's avatar
Alexandre Julliard committed
			break;
			}
		lppop->FocusedItem = (WORD)-1;
		if (!lppop->BarFlag) {
			PopupMenuCalcSize(hwnd);
			ResetHiliteFlags(lppop);
#ifdef DEBUG_MENU
			printf("PopupMenuWndProc hWnd=%04X WM_SHOWWINDOW Width=%d Height=%d !\n", 
									hwnd, lppop->Width, lppop->Height);
#endif
			SetWindowPos(hwnd, 0, 0, 0, lppop->Width + 2, lppop->Height, 
Alexandre Julliard's avatar
Alexandre Julliard committed
									SWP_NOZORDER | SWP_NOMOVE);
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
			printf("PopupMenuWndProc // End of WM_SHOWWINDOW !\n");
#endif
			}
Alexandre Julliard's avatar
Alexandre Julliard committed
    	break;
Alexandre Julliard's avatar
Alexandre Julliard committed
	case WM_LBUTTONDOWN:
		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
		if (lppop == NULL) break;
		SetCapture(hwnd); 
		MenuButtonDown(hwnd, lppop, LOWORD(lParam), HIWORD(lParam));
Alexandre Julliard's avatar
Alexandre Julliard committed
		break;
Alexandre Julliard's avatar
Alexandre Julliard committed
	case WM_LBUTTONUP:
		lppop = PopupMenuGetStorageHeader(hwnd);
		if (lppop == NULL) break;
		ReleaseCapture(); 
		MenuButtonUp(hwnd, lppop, LOWORD(lParam), HIWORD(lParam));
Alexandre Julliard's avatar
Alexandre Julliard committed
		break;
Alexandre Julliard's avatar
Alexandre Julliard committed
	case WM_MOUSEMOVE:
		lppop = PopupMenuGetStorageHeader(hwnd);
		if (lppop == NULL) break;
		MenuMouseMove(hwnd, lppop, wParam, LOWORD(lParam), HIWORD(lParam));
Alexandre Julliard's avatar
Alexandre Julliard committed
		break;
Alexandre Julliard's avatar
Alexandre Julliard committed

	case WM_KEYUP:
#ifdef DEBUG_MENU
		printf("PopupMenuWndProc hWnd=%04X WM_KEYUP w=%04X l=%08X !\n", 
												hwnd, wParam, lParam);
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
		break;
Alexandre Julliard's avatar
Alexandre Julliard committed
	case WM_KEYDOWN:
#ifdef DEBUG_MENU
		printf("PopupMenuWndProc hWnd=%04X WM_KEYDOWN w=%04X l=%08X !\n", 
												hwnd, wParam, lParam);
#endif
		if (lParam < 0L) break;
		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
		if (lppop == NULL) break;
		switch(wParam) {
			case VK_HOME:
				if (lppop->FocusedItem == 0) break;
				MenuItemSelect(hwnd, lppop, 0);
				break;
			case VK_UP:
				if (lppop->BarFlag) break;
				if (lppop->FocusedItem < 1) break;
				MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
				break;
			case VK_DOWN:
				if (lppop->BarFlag) goto ProceedSPACE;
				if (lppop->FocusedItem == (WORD)-1) {
					MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
					break;
					}
				if (lppop->FocusedItem >= lppop->nItems - 1) break;
				MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
				break;
			case VK_LEFT:
				if (lppop->SysFlag != 0) {
					ShowWindow(hwnd, SW_HIDE);
					hwnd = lppop->hWndParent;
					lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
					printf("VK_LEFT // try to put focus on MenuBar %08X !\n", lppop);
Alexandre Julliard's avatar
Alexandre Julliard committed
					if (lppop == NULL) break;
					MenuItemSelect(hwnd, lppop, lppop->nItems - 1);
				    break;
					}
				if (lppop->BarFlag) {
					if (lppop->FocusedItem < 1) {
						MenuItemSelect(hwnd, lppop, -1);
						NC_TrackSysMenu(hwnd);
						break;
						}
					if (HideAllSubPopupMenu(lppop)) {
						MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
						goto ProceedSPACE;
						}
					}
			    if (lppop->hWndParent != 0) {
					PostMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam);
				    break;
				    }
				MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
				break;
			case VK_RIGHT:
				if (lppop->SysFlag != 0) {
					ShowWindow(hwnd, SW_HIDE);
					hwnd = lppop->hWndParent;
					lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
					printf("VK_RIGHT // try to put focus on MenuBar %08X !\n", lppop);
Alexandre Julliard's avatar
Alexandre Julliard committed
					if (lppop == NULL) break;
					MenuItemSelect(hwnd, lppop, 0);
				    break;
					}
				if (lppop->BarFlag) {
					if (lppop->FocusedItem >= lppop->nItems - 1) {
						MenuItemSelect(hwnd, lppop, -1);
						NC_TrackSysMenu(hwnd);
						break;
						}
					if (HideAllSubPopupMenu(lppop)) {
						MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
						goto ProceedSPACE;
						}
					}
			    if (lppop->hWndParent != 0) {
					PostMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam);
				    break;
				    }
				MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
				break;
			default:
				break;
Alexandre Julliard's avatar
Alexandre Julliard committed
			}
Alexandre Julliard's avatar
Alexandre Julliard committed
			break;
	case WM_CHAR:
#ifdef DEBUG_MENU
		printf("PopupMenuWndProc hWnd=%04X WM_CHAR wParam=%04X !\n", hwnd, wParam);
#endif
		if (lParam < 0L) break;
Alexandre Julliard's avatar
Alexandre Julliard committed
		hwnd = GetFocus();
Alexandre Julliard's avatar
Alexandre Julliard committed
		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
		if (lppop == NULL) break;
Alexandre Julliard's avatar
Alexandre Julliard committed
		switch(wParam) {
Alexandre Julliard's avatar
Alexandre Julliard committed
			case VK_RETURN:
			case VK_SPACE:
ProceedSPACE:	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
				ExecFocusedMenuItem(hwnd, lppop);
				break;
Alexandre Julliard's avatar
Alexandre Julliard committed
			case VK_ESCAPE:
				if (lppop->BarFlag) {
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
					printf("VK_ESCAPE // Unselect all MenuBar's Items !\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
					if (lppop->FocusedItem != (WORD)-1)
						MenuItemSelect(hwnd, lppop, -1);
					}
				if (lppop->SysFlag) {
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
					printf("VK_ESCAPE // SysMenu !\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
					ShowWindow(hwnd, SW_HIDE);
					break;
					}
				if (lppop->hWndParent != 0) {
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
					printf("VK_ESCAPE // Hide only SubPopup !\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
					lppop2 = PopupMenuGetWindowAndStorage(lppop->hWndParent, &wndPtr);
					if (lppop2 == NULL) break;
					HideAllSubPopupMenu(lppop2);
					break;
					}
				else {
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
					printf("VK_ESCAPE // Hide Root Popup !\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
					ShowWindow(hwnd, SW_HIDE);
					MenuHasFocus = FALSE;
					}
				break;
			default:
				if (wParam >= 'a' && wParam <= 'z') wParam -= 'a' - 'A';
				lpitem = MenuFindItemBySelKey(lppop, wParam, &wRet);
				if (lpitem != NULL) {
				    printf("ShortKey Found  wRet=%d !\n", wRet);
					MenuItemSelect(hwnd, lppop, wRet);
					lppop->FocusedItem = wRet;
					goto ProceedSPACE;
					}
			    printf("ShortKey Not Found wParam=%04X wRet=%d lpitem=%08X !\n",
					wParam, wRet, lpitem);
				if (lppop->hWndParent != (HWND)NULL)
					SendMessage(lppop->hWndParent, WM_MENUCHAR, wParam, 
						MAKELONG(0, 0));
				else 
					SendMessage(lppop->ownerWnd, WM_MENUCHAR, wParam, 
						MAKELONG(0, 0));
				break;
Alexandre Julliard's avatar
Alexandre Julliard committed
			}
Alexandre Julliard's avatar
Alexandre Julliard committed
		break;
Alexandre Julliard's avatar
Alexandre Julliard committed
	case WM_PAINT:
#ifdef DEBUG_MENU
		printf("PopupMenuWndProc // WM_PAINT received !\n");
#endif
		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
		if (lppop == NULL) break;
		if (!lppop->BarFlag) {
			PopupMenuCalcSize(hwnd);
			StdDrawPopupMenu(hwnd);
			}
Alexandre Julliard's avatar
Alexandre Julliard committed
		break;
Alexandre Julliard's avatar
Alexandre Julliard committed
	default:
		return DefWindowProc(hwnd, message, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
BOOL ExecFocusedMenuItem(HWND hWnd, LPPOPUPMENU lppop)
Alexandre Julliard's avatar
Alexandre Julliard committed
{
Alexandre Julliard's avatar
Alexandre Julliard committed
	short	x, y;
	LPPOPUPMENU lppop2;
	LPMENUITEM	lpitem;
	HMENU	hSubMenu;
	RECT	rect;
	lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
Alexandre Julliard's avatar
Alexandre Julliard committed
	if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
Alexandre Julliard's avatar
Alexandre Julliard committed
		hSubMenu = (HMENU)lpitem->item_id;
		lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
		if (lppop2 == NULL) return FALSE;
		lppop2->hWndParent = hWnd;
		GetClientRect(hWnd, &rect);
		if (lppop->BarFlag) {
			GetWindowRect(hWnd, &rect);
			y = rect.top + lppop->rect.bottom;
			TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
				rect.left + lpitem->rect.left, 
				y, 0, lppop->ownerWnd, (LPRECT)NULL);
			}
		else {
			x = lppop->rect.right;
			GetWindowRect(hWnd, &rect);
			x += rect.left;
			TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
				x, rect.top + lpitem->rect.top,
				0, lppop->ownerWnd, (LPRECT)NULL);
			}
		GlobalUnlock(hSubMenu);
		return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
	if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
		((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
		MenuHasFocus = FALSE;
		if (lppop->BarFlag) {
			PostMessage(lppop->ownerWnd, WM_COMMAND, lpitem->item_id, 0L);
			}
		else {
			ShowWindow(lppop->hWnd, SW_HIDE);
			SendMessage(lppop->hWnd, WM_COMMAND, lpitem->item_id, 0L);
			}
Alexandre Julliard's avatar
Alexandre Julliard committed
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
	return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y)
Alexandre Julliard's avatar
Alexandre Julliard committed
{
Alexandre Julliard's avatar
Alexandre Julliard committed
	HDC		hDC;
	LPMENUITEM	lpitem, lpitem2;
	RECT	rect;
	HMENU	hSubMenu;
	WORD	wRet;
	LPPOPUPMENU lppop2;
	if (lppop == NULL) return;
	lpitem = MenuFindItem(lppop, x, y, &wRet);
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
	printf("MenuButtonDown hWnd=%04X x=%d y=%d // wRet=%d lpitem=%08X !\n", 
											hWnd, x, y, wRet, lpitem);
Alexandre Julliard's avatar
Alexandre Julliard committed
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
	if (lpitem != NULL) {
Alexandre Julliard's avatar
Alexandre Julliard committed
		if (lppop->FocusedItem != (WORD)-1 && wRet == lppop->FocusedItem) {
			lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem);
			if ((lpitem2->item_flags & MF_POPUP) == MF_POPUP) {
				hSubMenu = (HMENU)lpitem2->item_id;
				lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
				if (lppop2 == NULL) return FALSE;
				if (IsWindowVisible(lppop2->hWnd)) {
					ShowWindow(lppop2->hWnd, SW_HIDE);
					return TRUE;
					}
				}
			}
Alexandre Julliard's avatar
Alexandre Julliard committed
		MenuItemSelect(hWnd, lppop, wRet);
		if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
			hSubMenu = (HMENU)lpitem->item_id;
			lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
Alexandre Julliard's avatar
Alexandre Julliard committed
			if (lppop2 == NULL) return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
			lppop2->hWndParent = hWnd;
			if (lppop->BarFlag) {
				GetWindowRect(hWnd, &rect);
				y = rect.top + lppop->rect.bottom;
				ReleaseCapture(); 
				if (MenuHasFocus) {
					TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
						rect.left + lpitem->rect.left, 
						y, 0, lppop->ownerWnd, (LPRECT)NULL);
					}
				else {
					MenuHasFocus = TRUE;
					TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
						rect.left + lpitem->rect.left, 
						y, 0, lppop->ownerWnd, (LPRECT)NULL);
					MenuHasFocus = FALSE;
					MenuFocusLoop(hWnd, lppop);
					return TRUE;
					}
				}
			else {
				x = lppop->rect.right;
				GetWindowRect(hWnd, &rect);
				x += rect.left;
				TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
					x, rect.top + lpitem->rect.top,
					0, lppop->ownerWnd, (LPRECT)NULL);
				}
			GlobalUnlock(hSubMenu);
Alexandre Julliard's avatar
Alexandre Julliard committed
			return TRUE;
			}
		if (lppop->BarFlag && !MenuHasFocus) {
			MenuFocusLoop(hWnd, lppop);
Alexandre Julliard's avatar
Alexandre Julliard committed
			}
		return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
	printf("MenuButtonDown // x=%d y=%d // Not Found !\n", x, y);
Alexandre Julliard's avatar
Alexandre Julliard committed
	if (GetCapture() != 0) ReleaseCapture(); 
Alexandre Julliard's avatar
Alexandre Julliard committed
	MenuHasFocus = FALSE;
	ShowWindow(lppop->hWnd, SW_HIDE);
	return FALSE;
}



void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y)
{
	HDC		hDC;
	LPMENUITEM	lpitem, lpitem2;
	RECT	rect;
	HMENU	hSubMenu;
	WORD	wRet;
	LPPOPUPMENU lppop2;
	if (lppop == NULL) return;
	lpitem = MenuFindItem(lppop, x, y, &wRet);
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
	printf("MenuButtonUp // x=%d y=%d // wRet=%d lpitem=%08X !\n", 
											x, y, wRet, lpitem);
Alexandre Julliard's avatar
Alexandre Julliard committed
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
	if (lpitem != NULL) {
		if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
			return;
Alexandre Julliard's avatar
Alexandre Julliard committed
			}
Alexandre Julliard's avatar
Alexandre Julliard committed
		if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
			((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
			MenuHasFocus = FALSE;
			if (lppop->BarFlag) {
				PostMessage(lppop->ownerWnd, WM_COMMAND, lpitem->item_id, 0L);
				}
			else {
				ShowWindow(lppop->hWnd, SW_HIDE);
				SendMessage(lppop->hWnd, WM_COMMAND, lpitem->item_id, 0L);
				}
			return;
Alexandre Julliard's avatar
Alexandre Julliard committed
	if (lppop->FocusedItem != (WORD)-1) {
		MenuItemSelect(hWnd, lppop, lppop->FocusedItem);
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
}



void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y)
{
Alexandre Julliard's avatar
Alexandre Julliard committed
    HDC		hDC;
    RECT	rect;
    HMENU	hSubMenu;
    LPMENUITEM	lpitem, lpitem2;
    LPPOPUPMENU lppop2;
    WORD	wRet;

    if (GetKeyState(VK_LBUTTON)	!= 0) 
    {
	lpitem = MenuFindItem(lppop, x, y, &wRet);
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
	printf("MenuMouseMove // x=%d y=%d // wRet=%d lpitem=%08X !\n", 
	       x, y, wRet, lpitem);
#endif
	if ((lpitem != NULL) && (lppop->FocusedItem != wRet)) 
	{
	    lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem);
	    hDC = GetWindowDC(hWnd);
	    if ((lpitem2 != NULL ) &&
		(lpitem2->item_flags & MF_POPUP) == MF_POPUP) 
	    {
		HideAllSubPopupMenu(lppop);
	    }
	    MenuItemSelect(hWnd, lppop, wRet);
	    if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) 
	    {
		hSubMenu = (HMENU)lpitem->item_id;
		lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
		if (lppop2 == NULL) 
		{
		    ReleaseDC(hWnd, hDC);
		    return;
		}
		if (lppop->BarFlag) 
		{
		    lppop2->hWndParent = hWnd;
		    GetWindowRect(hWnd, &rect);
		    rect.top += lppop->rect.bottom;
		    TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
				   rect.left + lpitem->rect.left, rect.top, 
				   0, lppop->ownerWnd, (LPRECT)NULL);
Alexandre Julliard's avatar
Alexandre Julliard committed
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
		GlobalUnlock(hSubMenu);
	    }
	    ReleaseDC(hWnd, hDC);
	}
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
}


void ResetHiliteFlags(LPPOPUPMENU lppop)
{
	LPMENUITEM lpitem;
	int		i;
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
	printf("ResetHiliteFlags lppop=%08X\n", lppop);
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
	if (lppop == NULL) return;
	lpitem = lppop->firstItem;
	for(i = 0; i < lppop->nItems; i++) {
		if (lpitem == NULL) return;
Alexandre Julliard's avatar
Alexandre Julliard committed
		lpitem->item_flags &= 0xFFFF ^ MF_HILITE;
Alexandre Julliard's avatar
Alexandre Julliard committed
		lpitem = (LPMENUITEM)lpitem->next;
		}
}


void MenuItemSelect0(HWND hWnd, LPPOPUPMENU lppop, 
				LPMENUITEM lpitem, WORD wIndex)
{
Alexandre Julliard's avatar
Alexandre Julliard committed
    LPMENUITEM lpprev;
    
    if (lppop == NULL) 
	return;
    if (lppop->FocusedItem != (WORD)-1) 
    {
	lpprev = GetMenuItemPtr(lppop, lppop->FocusedItem);
	if (lpprev != NULL) 
	{
	    lpprev->item_flags &= MF_HILITE ^ 0xFFFF;
	    if ((lpprev->item_flags & MF_POPUP) == MF_POPUP)
		HideAllSubPopupMenu(lppop);
	    if (lppop->BarFlag)
		DrawMenuBar(hWnd);
	    else 
	    {
		InvalidateRect(hWnd, &lpprev->rect, TRUE);
		UpdateWindow(hWnd);
	    }
	}
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
    lppop->FocusedItem = wIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
    if (lpitem == NULL || wIndex == (WORD)-1) 
    {
	ResetHiliteFlags(lppop);
	if (lppop->BarFlag) DrawMenuBar(hWnd);
    }
    else 
    {
	lpitem->item_flags |= MF_HILITE;
	if (lppop->BarFlag)
	    DrawMenuBar(hWnd);
	else 
	{
	    InvalidateRect(hWnd, &lpitem->rect, TRUE);
	    UpdateWindow(hWnd);
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
	SendMessage(hWnd, WM_MENUSELECT, lpitem->item_id, 
Alexandre Julliard's avatar
Alexandre Julliard committed
		    MAKELONG(0, lpitem->item_flags));
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
void MenuItemSelect(HWND hWnd, LPPOPUPMENU lppop, WORD wIndex)
{
	LPMENUITEM lpitem;
    lpitem = GetMenuItemPtr(lppop, wIndex);
	MenuItemSelect0(hWnd, lppop, lpitem, wIndex);
}

Alexandre Julliard's avatar
Alexandre Julliard committed

LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr)
{
    WND  *Ptr;
    LPPOPUPMENU lppop;
    *(wndPtr) = Ptr = WIN_FindWndPtr(hwnd);
    if (Ptr == 0) {
Alexandre Julliard's avatar
Alexandre Julliard committed
    	printf("PopupMenuGetWindowAndStorage // Bad Window handle !\n");
    	return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
    	}
    lppop = *((LPPOPUPMENU *)&Ptr->wExtra[1]);
Alexandre Julliard's avatar
Alexandre Julliard committed
	if (lppop == NULL) {
		lppop = (LPPOPUPMENU) GlobalLock(Ptr->wIDmenu);
		if (lppop == NULL) {
			printf("PopupMenuGetWindowAndStorage // Bad Menu Handle !\n");
	    	return NULL;
			}
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
    return lppop;
}


LPPOPUPMENU PopupMenuGetStorageHeader(HWND hwnd)
{
    WND  *Ptr;
    LPPOPUPMENU lppop;
    Ptr = WIN_FindWndPtr(hwnd);
    if (Ptr == 0) {
    	printf("Bad Window handle on PopupMenu !\n");
    	return 0;
    	}
    lppop = *((LPPOPUPMENU *)&Ptr->wExtra[1]);
    return lppop;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
void SetMenuLogicalParent(HMENU hMenu, HWND hWnd)
{
    LPPOPUPMENU lppop;
    lppop = (LPPOPUPMENU)GlobalLock(hMenu);
    lppop->hWndParent = hWnd;
Alexandre Julliard's avatar
Alexandre Julliard committed
    GlobalUnlock(hMenu);
Alexandre Julliard's avatar
Alexandre Julliard committed
void StdDrawPopupMenu(HWND hwnd)
{
Alexandre Julliard's avatar
Alexandre Julliard committed
	WND 	*wndPtr;
	LPPOPUPMENU lppop;
	LPMENUITEM 	lpitem;
	PAINTSTRUCT ps;
	HBRUSH 	hBrush;
	HPEN	hOldPen;
	HWND	hWndParent;
	HDC 	hDC, hMemDC;
	RECT 	rect, rect2, rect3;
	DWORD	OldTextColor;
	int		OldBkMode;
	HFONT	hOldFont;
	HBITMAP	hBitMap;
	BITMAP	bm;
	UINT  	i, x;
	hDC = BeginPaint(hwnd, &ps);
	if (!IsWindowVisible(hwnd)) {
		EndPaint(hwnd, &ps);
		return;
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
	InitStdBitmaps();
Alexandre Julliard's avatar
Alexandre Julliard committed
	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
	if (lppop == NULL) goto EndOfPaint;
	hBrush = GetStockObject(WHITE_BRUSH);
	GetClientRect(hwnd, &rect);
	GetClientRect(hwnd, &rect2);
	FillRect(hDC, &rect, hBrush);
	FrameRect(hDC, &rect, GetStockObject(BLACK_BRUSH));
	if (lppop->nItems == 0) goto EndOfPaint;
	lpitem = lppop->firstItem;
	if (lpitem == NULL) goto EndOfPaint;
	for(i = 0; i < lppop->nItems; i++) {
Alexandre Julliard's avatar
Alexandre Julliard committed
	CopyRect(&rect2, &lpitem->rect);
Alexandre Julliard's avatar
Alexandre Julliard committed
	if ((lpitem->item_flags & MF_SEPARATOR) == MF_SEPARATOR) {
Alexandre Julliard's avatar
Alexandre Julliard committed
		hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN));
		MoveTo(hDC, rect2.left, rect2.top + 1);
		LineTo(hDC, rect2.right, rect2.top + 1);
		SelectObject(hDC, hOldPen);
Alexandre Julliard's avatar
Alexandre Julliard committed
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
	if ((lpitem->item_flags & MF_CHECKED) == MF_CHECKED) {
Alexandre Julliard's avatar
Alexandre Julliard committed
		hMemDC = CreateCompatibleDC(hDC);
Alexandre Julliard's avatar
Alexandre Julliard committed
		if (lpitem->hCheckBit == 0) {
			SelectObject(hMemDC, hStdCheck);
			GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
			}
		else {
			SelectObject(hMemDC, lpitem->hCheckBit);
			GetObject(lpitem->hCheckBit, sizeof(BITMAP), (LPSTR)&bm);
			}
Alexandre Julliard's avatar
Alexandre Julliard committed
		BitBlt(hDC, rect2.left, rect2.top + 1,
Alexandre Julliard's avatar
Alexandre Julliard committed
		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
Alexandre Julliard's avatar
Alexandre Julliard committed
		DeleteDC(hMemDC);
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
	else {
		if (lpitem->hUnCheckBit != 0) {
			hMemDC = CreateCompatibleDC(hDC);
			SelectObject(hMemDC, lpitem->hUnCheckBit);
			GetObject(lpitem->hUnCheckBit, sizeof(BITMAP), (LPSTR)&bm);
			BitBlt(hDC, rect2.left, rect2.top + 1,
			bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
			DeleteDC(hMemDC);
			}
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
	if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
Alexandre Julliard's avatar
Alexandre Julliard committed
		hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
		rect2.left += lppop->CheckWidth;
		hMemDC = CreateCompatibleDC(hDC);
		SelectObject(hMemDC, hBitMap);
		GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
		printf("StdDrawPopupMenu // MF_BITMAP hBit=%04X w=%d h=%d\n",
				hBitMap, bm.bmWidth, bm.bmHeight);
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
		BitBlt(hDC, rect2.left, rect2.top,
Alexandre Julliard's avatar
Alexandre Julliard committed
				bm.bmWidth, bm.bmHeight, 
				hMemDC, 0, 0, SRCCOPY);
Alexandre Julliard's avatar
Alexandre Julliard committed
		DeleteDC(hMemDC);
		if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
			InvertRect(hDC, &lpitem->rect);
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
	if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
Alexandre Julliard's avatar
Alexandre Julliard committed
		((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
		((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
		hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
		OldBkMode = SetBkMode(hDC, TRANSPARENT);
		if ((lpitem->item_flags & MF_DISABLED) == MF_DISABLED)
			OldTextColor = SetTextColor(hDC, 0x00C0C0C0L);
		else {
			if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
				OldTextColor = SetTextColor(hDC, 0x00FFFFFFL);
			else
				OldTextColor = SetTextColor(hDC, 0x00000000L);
			}
		CopyRect(&rect3, &lpitem->rect);
		if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
			FillRect(hDC, &rect3, GetStockObject(BLACK_BRUSH));
		InflateRect(&rect3, 0, -2);
		rect3.left += lppop->CheckWidth;
Alexandre Julliard's avatar
Alexandre Julliard committed
		hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN));
Alexandre Julliard's avatar
Alexandre Julliard committed
		if ((x = GetShortCutPos(lpitem->item_text)) != (WORD)-1) {
			DrawText(hDC, lpitem->item_text, x, &rect3, 
				DT_LEFT | DT_VCENTER | DT_SINGLELINE);
			DrawText(hDC, &lpitem->item_text[x], -1, &rect3, 
				DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
			} 
Alexandre Julliard's avatar
Alexandre Julliard committed
	    else
Alexandre Julliard's avatar
Alexandre Julliard committed
			DrawText(hDC, lpitem->item_text, -1, &rect3, 
				DT_LEFT | DT_VCENTER | DT_SINGLELINE);
Alexandre Julliard's avatar
Alexandre Julliard committed
		SelectObject(hDC, hOldPen);
Alexandre Julliard's avatar
Alexandre Julliard committed
		SetTextColor(hDC, OldTextColor);
		SetBkMode(hDC, OldBkMode);
		SelectObject(hDC, hOldFont);
		CopyRect(&rect2, &lpitem->rect);
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
	if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
Alexandre Julliard's avatar
Alexandre Julliard committed
		CopyRect(&rect3, &lpitem->rect);
		rect3.left = rect3.right - lppop->PopWidth;
		hMemDC = CreateCompatibleDC(hDC);
		SelectObject(hMemDC, hStdMnArrow);
		GetObject(hStdMnArrow, sizeof(BITMAP), (LPSTR)&bm);
		BitBlt(hDC, rect3.left, rect3.top + 1,
Alexandre Julliard's avatar
Alexandre Julliard committed
		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
Alexandre Julliard's avatar
Alexandre Julliard committed
		DeleteDC(hMemDC);
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
	if (lpitem->next == NULL) goto EndOfPaint;
	lpitem = (LPMENUITEM)lpitem->next;
Alexandre Julliard's avatar
Alexandre Julliard committed
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
EndOfPaint:
Alexandre Julliard's avatar
Alexandre Julliard committed
	EndPaint( hwnd, &ps );
Alexandre Julliard's avatar
Alexandre Julliard committed
void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop, 
		    BOOL suppress_draw)
Alexandre Julliard's avatar
Alexandre Julliard committed
{
Alexandre Julliard's avatar
Alexandre Julliard committed
	LPMENUITEM 	lpitem;
	HBRUSH 	hBrush;
	HPEN	hOldPen;
	HDC 	hMemDC;
	RECT 	rect, rect2, rect3;
	HFONT	hOldFont;
	DWORD	OldTextColor;
	int		OldBkMode;
	HBITMAP	hBitMap;
	BITMAP	bm;
	UINT  	i, textwidth;
	if (lppop == NULL || lprect == NULL) return;
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
Alexandre Julliard's avatar
Alexandre Julliard committed
	printf("StdDrawMenuBar(%04X, %08X, %08X); !\n", hDC, lprect, lppop);
#endif
	MenuBarCalcSize(hDC, lprect, lppop);
Alexandre Julliard's avatar
Alexandre Julliard committed
	if (suppress_draw) return;
Alexandre Julliard's avatar
Alexandre Julliard committed
	hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
Alexandre Julliard's avatar
Alexandre Julliard committed
	hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN));
Alexandre Julliard's avatar
Alexandre Julliard committed
	hBrush = GetStockObject(WHITE_BRUSH);
	CopyRect(&rect, lprect);
	FillRect(hDC, &rect, hBrush);
	FrameRect(hDC, &rect, GetStockObject(BLACK_BRUSH));
	if (lppop->nItems == 0) goto EndOfPaint;
	lpitem = lppop->firstItem;
	if (lpitem == NULL) goto EndOfPaint;
	for(i = 0; i < lppop->nItems; i++) {
		CopyRect(&rect2, &lpitem->rect);
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
		printf("StdDrawMenuBar // start left=%d\n", rect2.left);
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
		if ((lpitem->item_flags & MF_CHECKED) == MF_CHECKED) {
			hMemDC = CreateCompatibleDC(hDC);
			if (lpitem->hCheckBit == 0) {
				SelectObject(hMemDC, hStdCheck);
				GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
				}
			else {
				SelectObject(hMemDC, lpitem->hCheckBit);
				GetObject(lpitem->hCheckBit, sizeof(BITMAP), (LPSTR)&bm);
				}
			BitBlt(hDC, rect2.left, rect2.top + 1,
Alexandre Julliard's avatar
Alexandre Julliard committed
				bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
			rect2.left += bm.bmWidth;
#ifdef DEBUG_MENU
			printf("StdDrawMenuBar // MF_CHECKED bm.bmWidth=%d\n", bm.bmWidth);
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
			DeleteDC(hMemDC);
			}
		else {
			if (lpitem->hUnCheckBit != 0) {
				hMemDC = CreateCompatibleDC(hDC);
				SelectObject(hMemDC, lpitem->hUnCheckBit);
				GetObject(lpitem->hUnCheckBit, sizeof(BITMAP), (LPSTR)&bm);
				BitBlt(hDC, rect2.left, rect2.top + 1,
					bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
Alexandre Julliard's avatar
Alexandre Julliard committed
				rect2.left += bm.bmWidth;
#ifdef DEBUG_MENU
				printf("StdDrawMenuBar // MF_UNCHECKED bm.bmWidth=%d\n", bm.bmWidth);
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
				DeleteDC(hMemDC);
				}
			}
		if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
			hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
			hMemDC = CreateCompatibleDC(hDC);
			SelectObject(hMemDC, hBitMap);
			GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
			printf("StdDrawMenuBar // MF_BITMAP hBit=%04X w=%d h=%d\n",
					hBitMap, bm.bmWidth, bm.bmHeight);
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
			BitBlt(hDC, rect2.left, rect2.top,
Alexandre Julliard's avatar
Alexandre Julliard committed
						bm.bmWidth, bm.bmHeight, 
						hMemDC, 0, 0, SRCCOPY);
Alexandre Julliard's avatar
Alexandre Julliard committed
			DeleteDC(hMemDC);
			}
		if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
			((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
			((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
			hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
			OldBkMode = SetBkMode(hDC, TRANSPARENT);
			if ((lpitem->item_flags & MF_DISABLED) == MF_DISABLED)
				OldTextColor = SetTextColor(hDC, 0x00C0C0C0L);
			else {
				if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
					OldTextColor = SetTextColor(hDC, 0x00FFFFFFL);
				else
					OldTextColor = SetTextColor(hDC, 0x00000000L);
				}
			if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
				FillRect(hDC, &rect2, GetStockObject(BLACK_BRUSH));
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENU
			printf("StdDrawMenuBar // rect2.left=%d\n", rect2.left);
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
			DrawText(hDC, lpitem->item_text, -1, &rect2, 
				DT_LEFT | DT_VCENTER | DT_SINGLELINE);
			SetTextColor(hDC, OldTextColor);
			SetBkMode(hDC, OldBkMode);
			SelectObject(hDC, hOldFont);
			}
		if (lpitem->next == NULL) goto EndOfPaint;
		lpitem = (LPMENUITEM)lpitem->next;
Alexandre Julliard's avatar
Alexandre Julliard committed
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
EndOfPaint:
Alexandre Julliard's avatar
Alexandre Julliard committed
	SelectObject(hDC, hOldPen);
Alexandre Julliard's avatar
Alexandre Julliard committed
	SelectObject(hDC, hOldFont);
Alexandre Julliard's avatar
Alexandre Julliard committed
} 
Alexandre Julliard's avatar
Alexandre Julliard committed
LPMENUITEM MenuFindItem(LPPOPUPMENU lppop, int x, int y, WORD *lpRet)
Alexandre Julliard's avatar
Alexandre Julliard committed
{
Alexandre Julliard's avatar
Alexandre Julliard committed
	LPMENUITEM 	lpitem;
	UINT  	i;
	if (lpRet != NULL) *lpRet = 0;
	if (lppop == NULL) return NULL;
	if (lppop->nItems == 0) return NULL;
	lpitem = lppop->firstItem;
	for(i = 0; i < lppop->nItems; i++) {
		if (lpitem == NULL) return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENUFINDITEM
Alexandre Julliard's avatar
Alexandre Julliard committed
		printf("FindItem // left=%d top=%d right=%d bottom=%d\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
		lpitem->rect.left, lpitem->rect.top, 
		lpitem->rect.right, lpitem->rect.bottom);
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
		if (x > lpitem->rect.left && x < lpitem->rect.right && 
			y > lpitem->rect.top && y < lpitem->rect.bottom) {
			if (lpRet != NULL) *lpRet = i;
			return lpitem;
			}
		lpitem = (LPMENUITEM)lpitem->next;
		}
	return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
LPMENUITEM MenuFindItemBySelKey(LPPOPUPMENU lppop, WORD key, WORD *lpRet)
Alexandre Julliard's avatar
Alexandre Julliard committed
{
Alexandre Julliard's avatar
Alexandre Julliard committed
	LPMENUITEM 	lpitem;
	UINT  	i;
	if (lppop == NULL) return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed

Alexandre Julliard's avatar
Alexandre Julliard committed
	if (lppop->nItems == 0) return NULL;
	lpitem = lppop->firstItem;
	for(i = 0; i < lppop->nItems; i++) {
		if (lpitem == NULL) return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENUFINDITEM
Alexandre Julliard's avatar
Alexandre Julliard committed
		printf("FindItemBySelKey // key=%04X lpitem->sel_key=%04X\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
										key, lpitem->sel_key);
Alexandre Julliard's avatar
Alexandre Julliard committed
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
		if (key == lpitem->sel_key) {
			if (lpRet != NULL) *lpRet = i;
			return lpitem;
			}
		lpitem = (LPMENUITEM)lpitem->next;
		}
	return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
void PopupMenuCalcSize(HWND hwnd)
{
Alexandre Julliard's avatar
Alexandre Julliard committed
	WND 	*wndPtr;
	LPPOPUPMENU lppop;
	LPMENUITEM 	lpitem;
	HDC		hDC;
	RECT 	rect;
	HBITMAP	hBitMap;
	BITMAP	bm;
	HFONT	hOldFont;
	UINT  	i, OldWidth, TempWidth;
	DWORD	dwRet;
Alexandre Julliard's avatar
Alexandre Julliard committed
#ifdef DEBUG_MENUCALC
	printf("PopupMenuCalcSize hWnd=%04X !\n", hWnd);
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
	InitStdBitmaps();
Alexandre Julliard's avatar
Alexandre Julliard committed
	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
	if (lppop == NULL) return;
	if (lppop->nItems == 0) return;
	hDC = GetDC(hwnd);