blob: 0072421e59df12963e2da8107e57f2a5668e3a08 [file] [log] [blame]
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001/*
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00002 * Menu functions
3 *
4 * Copyright 1993 Martin Ayotte
5 * Copyright 1994 Alexandre Julliard
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00006 * Copyright 1997 Morten Welinder
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00007 */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00008
9/*
10 * Note: the style MF_MOUSESELECT is used to mark popup items that
11 * have been selected, i.e. their popup menu is currently displayed.
12 * This is probably not the meaning this style has in MS-Windows.
13 */
Alexandre Julliard401710d1993-09-04 10:09:32 +000014
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000015#include <assert.h>
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +000016#include <ctype.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000017#include <stdlib.h>
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +000018#include <string.h>
Francois Boisvert85dd9fc1999-02-17 12:50:11 +000019
Jeremy Whited3e22d92000-02-10 19:03:02 +000020#include "windef.h"
Alexandre Julliard24a62ab2000-11-28 22:40:56 +000021#include "winnls.h"
Jeremy Whited3e22d92000-02-10 19:03:02 +000022#include "wingdi.h"
Francois Boisvert85dd9fc1999-02-17 12:50:11 +000023#include "wine/winbase16.h"
Michael Veksler3fbb8dc1999-02-21 18:23:26 +000024#include "wine/winuser16.h"
Alexandre Julliard24a62ab2000-11-28 22:40:56 +000025#include "wine/unicode.h"
Andreas Mohra6d83eb2000-12-27 04:02:46 +000026#include "wine/port.h"
Jeremy Whited3e22d92000-02-10 19:03:02 +000027#include "win.h"
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000028#include "heap.h"
Alexandre Julliard91222da2000-12-10 23:01:33 +000029#include "controls.h"
Alexandre Julliardc6c09441997-01-12 18:32:19 +000030#include "nonclient.h"
Alexandre Julliard1f579291994-05-25 16:25:21 +000031#include "user.h"
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +000032#include "message.h"
Marcus Meissnerd5e7c791998-12-09 11:06:00 +000033
Alexandre Julliard9fe7a251999-05-14 08:17:14 +000034#include "debugtools.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000035
Dmitry Timoshkovef559322000-10-26 21:47:20 +000036DEFAULT_DEBUG_CHANNEL(menu);
37DECLARE_DEBUG_CHANNEL(accel);
Alexandre Julliardd37eb361997-07-20 16:23:21 +000038
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000039/* internal popup menu window messages */
40
41#define MM_SETMENUHANDLE (WM_USER + 0)
42#define MM_GETMENUHANDLE (WM_USER + 1)
43
Alexandre Julliard2d93d001996-05-21 15:01:41 +000044/* Menu item structure */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000045typedef struct {
46 /* ----------- MENUITEMINFO Stuff ----------- */
Juergen Schmied78513941999-04-18 14:40:32 +000047 UINT fType; /* Item type. */
Alexandre Julliarda3960291999-02-26 11:11:13 +000048 UINT fState; /* Item state. */
49 UINT wID; /* Item id. */
50 HMENU hSubMenu; /* Pop-up menu. */
Juergen Schmied78513941999-04-18 14:40:32 +000051 HBITMAP hCheckBit; /* Bitmap when checked. */
Alexandre Julliarda3960291999-02-26 11:11:13 +000052 HBITMAP hUnCheckBit; /* Bitmap when unchecked. */
Aric Stewartc946b1c2000-10-24 21:28:19 +000053 LPWSTR text; /* Item text or bitmap handle. */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000054 DWORD dwItemData; /* Application defined. */
Juergen Schmied78513941999-04-18 14:40:32 +000055 DWORD dwTypeData; /* depends on fMask */
56 HBITMAP hbmpItem; /* bitmap in win98 style menus */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000057 /* ----------- Wine stuff ----------- */
Juergen Schmied78513941999-04-18 14:40:32 +000058 RECT rect; /* Item area (relative to menu window) */
59 UINT xTab; /* X position of text after Tab */
Alexandre Julliard2d93d001996-05-21 15:01:41 +000060} MENUITEM;
61
62/* Popup menu structure */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000063typedef struct {
Alexandre Julliard2d93d001996-05-21 15:01:41 +000064 WORD wFlags; /* Menu flags (MF_POPUP, MF_SYSMENU) */
65 WORD wMagic; /* Magic number */
Alexandre Julliard2d93d001996-05-21 15:01:41 +000066 WORD Width; /* Width of the whole menu */
67 WORD Height; /* Height of the whole menu */
Alexandre Julliarde60ccd12001-05-11 20:05:42 +000068 UINT nItems; /* Number of items in the menu */
Juergen Schmied78513941999-04-18 14:40:32 +000069 HWND hWnd; /* Window containing the menu */
70 MENUITEM *items; /* Array of menu items */
71 UINT FocusedItem; /* Currently focused item */
Juergen Schmied466a6521999-05-02 11:21:08 +000072 HWND hwndOwner; /* window receiving the messages for ownerdraw */
Pascal Lessard2eb0a301999-09-03 16:38:52 +000073 BOOL bTimeToHide; /* Request hiding when receiving a second click in the top-level menu item */
Juergen Schmied78513941999-04-18 14:40:32 +000074 /* ------------ MENUINFO members ------ */
75 DWORD dwStyle; /* Extended mennu style */
76 UINT cyMax; /* max hight of the whole menu, 0 is screen hight */
77 HBRUSH hbrBack; /* brush for menu background */
78 DWORD dwContextHelpID;
79 DWORD dwMenuData; /* application defined value */
Pascal Lessardd814bb61999-07-31 13:02:02 +000080 HMENU hSysMenuOwner; /* Handle to the dummy sys menu holder */
Alexandre Julliard2d93d001996-05-21 15:01:41 +000081} POPUPMENU, *LPPOPUPMENU;
82
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000083/* internal flags for menu tracking */
84
85#define TF_ENDMENU 0x0001
86#define TF_SUSPENDPOPUP 0x0002
87#define TF_SKIPREMOVE 0x0004
88
89typedef struct
90{
Alexandre Julliarda3960291999-02-26 11:11:13 +000091 UINT trackFlags;
92 HMENU hCurrentMenu; /* current submenu (can be equal to hTopMenu)*/
93 HMENU hTopMenu; /* initial menu */
94 HWND hOwnerWnd; /* where notifications are sent */
95 POINT pt;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000096} MTRACKER;
97
Alexandre Julliard2d93d001996-05-21 15:01:41 +000098#define MENU_MAGIC 0x554d /* 'MU' */
99
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000100#define ITEM_PREV -1
101#define ITEM_NEXT 1
102
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000103 /* Internal MENU_TrackMenu() flags */
104#define TPM_INTERNAL 0xF0000000
105#define TPM_ENTERIDLEEX 0x80000000 /* set owner window for WM_ENTERIDLE */
106#define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */
Francois Boisvert85dd9fc1999-02-17 12:50:11 +0000107#define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */
Alexandre Julliardf7207251994-07-23 07:57:48 +0000108
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000109 /* popup menu shade thickness */
110#define POPUP_XSHADE 4
111#define POPUP_YSHADE 4
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000112
Alexandre Julliardf7207251994-07-23 07:57:48 +0000113 /* Space between 2 menu bar items */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000114#define MENU_BAR_ITEMS_SPACE 12
Alexandre Julliardf7207251994-07-23 07:57:48 +0000115
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000116 /* Minimum width of a tab character */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000117#define MENU_TAB_SPACE 8
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000118
Alexandre Julliardf7207251994-07-23 07:57:48 +0000119 /* Height of a separator item */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000120#define SEPARATOR_HEIGHT 5
Alexandre Julliardf7207251994-07-23 07:57:48 +0000121
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000122 /* (other menu->FocusedItem values give the position of the focused item) */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000123#define NO_SELECTED_ITEM 0xffff
Alexandre Julliardcdd09231994-01-12 11:12:51 +0000124
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000125#define MENU_ITEM_TYPE(flags) \
126 ((flags) & (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR))
127
128#define IS_STRING_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_STRING)
Juergen Schmied78513941999-04-18 14:40:32 +0000129#define IS_BITMAP_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_BITMAP)
François Gouget75b278e2001-01-06 01:45:51 +0000130#define IS_MAGIC_ITEM(text) (LOWORD((int)text)<12)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000131
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000132#define IS_SYSTEM_MENU(menu) \
133 (!((menu)->wFlags & MF_POPUP) && (menu)->wFlags & MF_SYSMENU)
Juergen Schmied78513941999-04-18 14:40:32 +0000134
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000135#define IS_SYSTEM_POPUP(menu) \
136 ((menu)->wFlags & MF_POPUP && (menu)->wFlags & MF_SYSMENU)
137
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000138#define TYPE_MASK (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
139 MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
140 MFT_RIGHTORDER | MFT_RIGHTJUSTIFY | \
141 MF_POPUP | MF_SYSMENU | MF_HELP)
142#define STATE_MASK (~TYPE_MASK)
143
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000144 /* Dimension of the menu bitmaps */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000145static WORD arrow_bitmap_width = 0, arrow_bitmap_height = 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000146
Alexandre Julliarda3960291999-02-26 11:11:13 +0000147static HBITMAP hStdMnArrow = 0;
Francois Boisvert8b391741999-02-09 14:09:55 +0000148
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +0000149/* Minimze/restore/close buttons to be inserted in menubar */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000150static HBITMAP hBmpMinimize = 0;
151static HBITMAP hBmpMinimizeD = 0;
152static HBITMAP hBmpMaximize = 0;
153static HBITMAP hBmpMaximizeD = 0;
154static HBITMAP hBmpClose = 0;
155static HBITMAP hBmpCloseD = 0;
Francois Boisvert308c6af1999-02-18 10:37:17 +0000156
Francois Boisvert8b391741999-02-09 14:09:55 +0000157
Juergen Schmied78513941999-04-18 14:40:32 +0000158static HBRUSH hShadeBrush = 0;
159static HFONT hMenuFont = 0;
Juergen Schmied466a6521999-05-02 11:21:08 +0000160static HFONT hMenuFontBold = 0;
Juergen Schmied78513941999-04-18 14:40:32 +0000161
Alexandre Julliarda3960291999-02-26 11:11:13 +0000162static HMENU MENU_DefSysPopup = 0; /* Default system menu popup */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000163
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000164/* Use global popup window because there's no way 2 menus can
165 * be tracked at the same time. */
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000166static HWND top_popup;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000167
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000168 /* Flag set by EndMenu() to force an exit from menu tracking */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000169static BOOL fEndMenu = FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000170
Alexandre Julliard91222da2000-12-10 23:01:33 +0000171static LRESULT WINAPI PopupMenuWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
172
173
174/*********************************************************************
175 * menu class descriptor
176 */
177const struct builtin_class_descr MENU_builtin_class =
178{
179 POPUPMENU_CLASS_ATOM, /* name */
180 CS_GLOBALCLASS | CS_SAVEBITS, /* style */
181 NULL, /* procA (winproc is Unicode only) */
182 PopupMenuWndProc, /* procW */
183 sizeof(HMENU), /* extra */
184 IDC_ARROWA, /* cursor */
185 COLOR_MENU+1 /* brush */
186};
187
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000188
189/***********************************************************************
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000190 * debug_print_menuitem
191 *
192 * Print a menuitem in readable form.
193 */
194
Alexandre Julliard03468f71998-02-15 19:40:49 +0000195#define debug_print_menuitem(pre, mp, post) \
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000196 if(!TRACE_ON(menu)) ; else do_debug_print_menuitem(pre, mp, post)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000197
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000198#define MENUOUT(text) \
Alexandre Julliard15de6151999-08-04 12:22:42 +0000199 DPRINTF("%s%s", (count++ ? "," : ""), (text))
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000200
201#define MENUFLAG(bit,text) \
202 do { \
203 if (flags & (bit)) { flags &= ~(bit); MENUOUT ((text)); } \
204 } while (0)
205
Alexandre Julliard03468f71998-02-15 19:40:49 +0000206static void do_debug_print_menuitem(const char *prefix, MENUITEM * mp,
207 const char *postfix)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000208{
Alexandre Julliard15de6151999-08-04 12:22:42 +0000209 TRACE("%s ", prefix);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000210 if (mp) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000211 UINT flags = mp->fType;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000212 int typ = MENU_ITEM_TYPE(flags);
Alexandre Julliard15de6151999-08-04 12:22:42 +0000213 DPRINTF( "{ ID=0x%x", mp->wID);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000214 if (flags & MF_POPUP)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000215 DPRINTF( ", Sub=0x%x", mp->hSubMenu);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000216 if (flags) {
217 int count = 0;
Alexandre Julliard15de6151999-08-04 12:22:42 +0000218 DPRINTF( ", Typ=");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000219 if (typ == MFT_STRING)
220 /* Nothing */ ;
221 else if (typ == MFT_SEPARATOR)
222 MENUOUT("sep");
223 else if (typ == MFT_OWNERDRAW)
224 MENUOUT("own");
225 else if (typ == MFT_BITMAP)
226 MENUOUT("bit");
227 else
228 MENUOUT("???");
229 flags -= typ;
230
231 MENUFLAG(MF_POPUP, "pop");
232 MENUFLAG(MFT_MENUBARBREAK, "barbrk");
233 MENUFLAG(MFT_MENUBREAK, "brk");
234 MENUFLAG(MFT_RADIOCHECK, "radio");
235 MENUFLAG(MFT_RIGHTORDER, "rorder");
236 MENUFLAG(MF_SYSMENU, "sys");
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +0000237 MENUFLAG(MFT_RIGHTJUSTIFY, "right"); /* same as MF_HELP */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000238
239 if (flags)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000240 DPRINTF( "+0x%x", flags);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000241 }
242 flags = mp->fState;
243 if (flags) {
244 int count = 0;
Alexandre Julliard15de6151999-08-04 12:22:42 +0000245 DPRINTF( ", State=");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000246 MENUFLAG(MFS_GRAYED, "grey");
Juergen Schmied466a6521999-05-02 11:21:08 +0000247 MENUFLAG(MFS_DEFAULT, "default");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000248 MENUFLAG(MFS_DISABLED, "dis");
249 MENUFLAG(MFS_CHECKED, "check");
250 MENUFLAG(MFS_HILITE, "hi");
251 MENUFLAG(MF_USECHECKBITMAPS, "usebit");
252 MENUFLAG(MF_MOUSESELECT, "mouse");
253 if (flags)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000254 DPRINTF( "+0x%x", flags);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000255 }
256 if (mp->hCheckBit)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000257 DPRINTF( ", Chk=0x%x", mp->hCheckBit);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000258 if (mp->hUnCheckBit)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000259 DPRINTF( ", Unc=0x%x", mp->hUnCheckBit);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000260
261 if (typ == MFT_STRING) {
262 if (mp->text)
François Gougetb99367e2001-02-14 21:42:10 +0000263 DPRINTF( ", Text=%s", debugstr_w(mp->text));
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000264 else
Alexandre Julliard15de6151999-08-04 12:22:42 +0000265 DPRINTF( ", Text=Null");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000266 } else if (mp->text == NULL)
267 /* Nothing */ ;
268 else
Alexandre Julliard15de6151999-08-04 12:22:42 +0000269 DPRINTF( ", Text=%p", mp->text);
Juergen Schmied7abca951999-04-11 17:02:30 +0000270 if (mp->dwItemData)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000271 DPRINTF( ", ItemData=0x%08lx", mp->dwItemData);
272 DPRINTF( " }");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000273 } else {
Alexandre Julliard15de6151999-08-04 12:22:42 +0000274 DPRINTF( "NULL");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000275 }
Alexandre Julliard03468f71998-02-15 19:40:49 +0000276
Alexandre Julliard15de6151999-08-04 12:22:42 +0000277 DPRINTF(" %s\n", postfix);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000278}
279
280#undef MENUOUT
281#undef MENUFLAG
282
Gerard Patel3e629742000-01-17 22:22:16 +0000283
284/***********************************************************************
285 * MENU_GetMenu
286 *
287 * Validate the given menu handle and returns the menu structure pointer.
288 */
289POPUPMENU *MENU_GetMenu(HMENU hMenu)
290{
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000291 POPUPMENU *menu = USER_HEAP_LIN_ADDR(hMenu);
292 if (!menu || menu->wMagic != MENU_MAGIC)
Gerard Patel3e629742000-01-17 22:22:16 +0000293 {
Gerard Patelc6369b02000-05-14 22:52:52 +0000294 WARN("invalid menu handle=%x, ptr=%p, magic=%x\n", hMenu, menu, menu? menu->wMagic:0);
Gerard Patel3e629742000-01-17 22:22:16 +0000295 menu = NULL;
296 }
297 return menu;
298}
299
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000300/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000301 * MENU_CopySysPopup
302 *
303 * Return the default system menu.
304 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000305static HMENU MENU_CopySysPopup(void)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000306{
Bertho Stultiensd1895a71999-04-25 18:31:35 +0000307 HMENU hMenu = LoadMenuA(GetModuleHandleA("USER32"), "SYSMENU");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000308
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000309 if( hMenu ) {
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000310 POPUPMENU* menu = MENU_GetMenu(hMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000311 menu->wFlags |= MF_SYSMENU | MF_POPUP;
Juergen Schmied49251861999-05-13 18:42:03 +0000312 SetMenuDefaultItem(hMenu, SC_CLOSE, FALSE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000313 }
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000314 else
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000315 ERR("Unable to load default system menu\n" );
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000316
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000317 TRACE("returning %x.\n", hMenu );
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000318
319 return hMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000320}
321
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000322
323/**********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000324 * MENU_GetSysMenu
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000325 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000326 * Create a copy of the system menu. System menu in Windows is
Andreas Mohra6d83eb2000-12-27 04:02:46 +0000327 * a special menu bar with the single entry - system menu popup.
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000328 * This popup is presented to the outside world as a "system menu".
329 * However, the real system menu handle is sometimes seen in the
Andreas Mohra6d83eb2000-12-27 04:02:46 +0000330 * WM_MENUSELECT parameters (and Word 6 likes it this way).
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000331 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000332HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu )
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000333{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000334 HMENU hMenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000335
Alexandre Julliarda3960291999-02-26 11:11:13 +0000336 if ((hMenu = CreateMenu()))
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000337 {
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000338 POPUPMENU *menu = MENU_GetMenu(hMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000339 menu->wFlags = MF_SYSMENU;
340 menu->hWnd = hWnd;
341
Alexandre Julliarda3960291999-02-26 11:11:13 +0000342 if (hPopupMenu == (HMENU)(-1))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000343 hPopupMenu = MENU_CopySysPopup();
344 else if( !hPopupMenu ) hPopupMenu = MENU_DefSysPopup;
345
346 if (hPopupMenu)
347 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000348 InsertMenuA( hMenu, -1, MF_SYSMENU | MF_POPUP | MF_BYPOSITION, hPopupMenu, NULL );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000349
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000350 menu->items[0].fType = MF_SYSMENU | MF_POPUP;
351 menu->items[0].fState = 0;
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000352 if ((menu = MENU_GetMenu(hPopupMenu))) menu->wFlags |= MF_SYSMENU;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000353
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000354 TRACE("GetSysMenu hMenu=%04x (%04x)\n", hMenu, hPopupMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000355 return hMenu;
356 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000357 DestroyMenu( hMenu );
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000358 }
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000359 ERR("failed to load system menu!\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000360 return 0;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000361}
362
363
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000364/***********************************************************************
365 * MENU_Init
366 *
367 * Menus initialisation.
368 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000369BOOL MENU_Init()
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000370{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000371 HBITMAP hBitmap;
Juergen Schmied78513941999-04-18 14:40:32 +0000372 NONCLIENTMETRICSA ncm;
373
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000374 static unsigned char shade_bits[16] = { 0x55, 0, 0xAA, 0,
375 0x55, 0, 0xAA, 0,
376 0x55, 0, 0xAA, 0,
377 0x55, 0, 0xAA, 0 };
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000378
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000379 /* Load menu bitmaps */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000380 hStdMnArrow = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_MNARROW));
Francois Boisvert8b391741999-02-09 14:09:55 +0000381 /* Load system buttons bitmaps */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000382 hBmpMinimize = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_REDUCE));
383 hBmpMinimizeD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_REDUCED));
384 hBmpMaximize = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_RESTORE));
385 hBmpMaximizeD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_RESTORED));
386 hBmpClose = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_CLOSE));
387 hBmpCloseD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_CLOSED));
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000388
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000389 if (hStdMnArrow)
Juergen Schmied78513941999-04-18 14:40:32 +0000390 {
391 BITMAP bm;
392 GetObjectA( hStdMnArrow, sizeof(bm), &bm );
393 arrow_bitmap_width = bm.bmWidth;
394 arrow_bitmap_height = bm.bmHeight;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000395 } else
Juergen Schmied78513941999-04-18 14:40:32 +0000396 return FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000397
Juergen Schmied78513941999-04-18 14:40:32 +0000398 if (! (hBitmap = CreateBitmap( 8, 8, 1, 1, shade_bits)))
399 return FALSE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000400
Juergen Schmied78513941999-04-18 14:40:32 +0000401 if(!(hShadeBrush = CreatePatternBrush( hBitmap )))
402 return FALSE;
403
404 DeleteObject( hBitmap );
405 if (!(MENU_DefSysPopup = MENU_CopySysPopup()))
406 return FALSE;
407
408 ncm.cbSize = sizeof (NONCLIENTMETRICSA);
409 if (!(SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &ncm, 0)))
410 return FALSE;
411
412 if (!(hMenuFont = CreateFontIndirectA( &ncm.lfMenuFont )))
413 return FALSE;
414
Juergen Schmied466a6521999-05-02 11:21:08 +0000415 ncm.lfMenuFont.lfWeight += 300;
416 if ( ncm.lfMenuFont.lfWeight > 1000)
417 ncm.lfMenuFont.lfWeight = 1000;
418
419 if (!(hMenuFontBold = CreateFontIndirectA( &ncm.lfMenuFont )))
420 return FALSE;
421
Juergen Schmied78513941999-04-18 14:40:32 +0000422 return TRUE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000423}
424
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000425/***********************************************************************
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000426 * MENU_InitSysMenuPopup
427 *
428 * Grey the appropriate items in System menu.
429 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000430static void MENU_InitSysMenuPopup( HMENU hmenu, DWORD style, DWORD clsStyle )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000431{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000432 BOOL gray;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000433
434 gray = !(style & WS_THICKFRAME) || (style & (WS_MAXIMIZE | WS_MINIMIZE));
Alexandre Julliarda3960291999-02-26 11:11:13 +0000435 EnableMenuItem( hmenu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000436 gray = ((style & WS_MAXIMIZE) != 0);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000437 EnableMenuItem( hmenu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000438 gray = !(style & WS_MINIMIZEBOX) || (style & WS_MINIMIZE);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000439 EnableMenuItem( hmenu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000440 gray = !(style & WS_MAXIMIZEBOX) || (style & WS_MAXIMIZE);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000441 EnableMenuItem( hmenu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000442 gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE));
Alexandre Julliarda3960291999-02-26 11:11:13 +0000443 EnableMenuItem( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000444 gray = (clsStyle & CS_NOCLOSE) != 0;
Pascal Lessardd814bb61999-07-31 13:02:02 +0000445
446 /* The menu item must keep its state if it's disabled */
447 if(gray)
448 EnableMenuItem( hmenu, SC_CLOSE, MF_GRAYED);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000449}
450
451
Alexandre Julliard641ee761997-08-04 16:34:36 +0000452/******************************************************************************
453 *
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000454 * UINT MENU_GetStartOfNextColumn(
455 * HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000456 *
457 *****************************************************************************/
458
Alexandre Julliarda3960291999-02-26 11:11:13 +0000459static UINT MENU_GetStartOfNextColumn(
460 HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000461{
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000462 POPUPMENU *menu = MENU_GetMenu(hMenu);
463 UINT i;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000464
465 if(!menu)
466 return NO_SELECTED_ITEM;
467
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000468 i = menu->FocusedItem + 1;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000469 if( i == NO_SELECTED_ITEM )
470 return i;
471
472 for( ; i < menu->nItems; ++i ) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000473 if (menu->items[i].fType & MF_MENUBARBREAK)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000474 return i;
475 }
476
477 return NO_SELECTED_ITEM;
478}
479
480
481/******************************************************************************
482 *
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000483 * UINT MENU_GetStartOfPrevColumn(
484 * HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000485 *
486 *****************************************************************************/
487
Alexandre Julliarda3960291999-02-26 11:11:13 +0000488static UINT MENU_GetStartOfPrevColumn(
489 HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000490{
Alexandre Julliarde60ccd12001-05-11 20:05:42 +0000491 POPUPMENU *menu = MENU_GetMenu(hMenu);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000492 UINT i;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000493
494 if( !menu )
495 return NO_SELECTED_ITEM;
496
497 if( menu->FocusedItem == 0 || menu->FocusedItem == NO_SELECTED_ITEM )
498 return NO_SELECTED_ITEM;
499
500 /* Find the start of the column */
501
502 for(i = menu->FocusedItem; i != 0 &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000503 !(menu->items[i].fType & MF_MENUBARBREAK);
Alexandre Julliard641ee761997-08-04 16:34:36 +0000504 --i); /* empty */
505
506 if(i == 0)
507 return NO_SELECTED_ITEM;
508
509 for(--i; i != 0; --i) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000510 if (menu->items[i].fType & MF_MENUBARBREAK)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000511 break;
512 }
513
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000514 TRACE("ret %d.\n", i );
Alexandre Julliard641ee761997-08-04 16:34:36 +0000515
516 return i;
517}
518
519
520
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000521/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000522 * MENU_FindItem
523 *
524 * Find a menu item. Return a pointer on the item, and modifies *hmenu
525 * in case the item was in a sub-menu.
526 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000527static MENUITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000528{
529 POPUPMENU *menu;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000530 UINT i;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000531
Gerard Patel3e629742000-01-17 22:22:16 +0000532 if (((*hmenu)==0xffff) || (!(menu = MENU_GetMenu(*hmenu)))) return NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000533 if (wFlags & MF_BYPOSITION)
534 {
535 if (*nPos >= menu->nItems) return NULL;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000536 return &menu->items[*nPos];
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000537 }
538 else
539 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000540 MENUITEM *item = menu->items;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000541 for (i = 0; i < menu->nItems; i++, item++)
542 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000543 if (item->wID == *nPos)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000544 {
545 *nPos = i;
546 return item;
547 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000548 else if (item->fType & MF_POPUP)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000549 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000550 HMENU hsubmenu = item->hSubMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000551 MENUITEM *subitem = MENU_FindItem( &hsubmenu, nPos, wFlags );
552 if (subitem)
553 {
554 *hmenu = hsubmenu;
555 return subitem;
556 }
557 }
558 }
559 }
560 return NULL;
561}
562
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000563/***********************************************************************
Rein Klazes80c924f1999-12-12 19:40:46 +0000564 * MENU_FindSubMenu
565 *
566 * Find a Sub menu. Return the position of the submenu, and modifies
567 * *hmenu in case it is found in another sub-menu.
568 * If the submenu cannot be found, NO_SELECTED_ITEM is returned.
569 */
570UINT MENU_FindSubMenu( HMENU *hmenu, HMENU hSubTarget )
571{
572 POPUPMENU *menu;
573 UINT i;
574 MENUITEM *item;
575 if (((*hmenu)==0xffff) ||
Gerard Patel3e629742000-01-17 22:22:16 +0000576 (!(menu = MENU_GetMenu(*hmenu))))
Rein Klazes80c924f1999-12-12 19:40:46 +0000577 return NO_SELECTED_ITEM;
578 item = menu->items;
579 for (i = 0; i < menu->nItems; i++, item++) {
580 if(!(item->fType & MF_POPUP)) continue;
581 if (item->hSubMenu == hSubTarget) {
582 return i;
583 }
584 else {
585 HMENU hsubmenu = item->hSubMenu;
586 UINT pos = MENU_FindSubMenu( &hsubmenu, hSubTarget );
587 if (pos != NO_SELECTED_ITEM) {
588 *hmenu = hsubmenu;
589 return pos;
590 }
591 }
592 }
593 return NO_SELECTED_ITEM;
594}
595
596/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000597 * MENU_FreeItemData
598 */
599static void MENU_FreeItemData( MENUITEM* item )
600{
601 /* delete text */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000602 if (IS_STRING_ITEM(item->fType) && item->text)
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000603 HeapFree( GetProcessHeap(), 0, item->text );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000604}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000605
606/***********************************************************************
607 * MENU_FindItemByCoords
608 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000609 * Find the item at the specified coordinates (screen coords). Does
610 * not work for child windows and therefore should not be called for
611 * an arbitrary system menu.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000612 */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000613static MENUITEM *MENU_FindItemByCoords( POPUPMENU *menu,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000614 POINT pt, UINT *pos )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000615{
616 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000617 UINT i;
Marcus Meissnerac593bb1999-03-17 15:18:28 +0000618 RECT wrect;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000619
Marcus Meissnerac593bb1999-03-17 15:18:28 +0000620 if (!GetWindowRect(menu->hWnd,&wrect)) return NULL;
621 pt.x -= wrect.left;pt.y -= wrect.top;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000622 item = menu->items;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000623 for (i = 0; i < menu->nItems; i++, item++)
624 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000625 if ((pt.x >= item->rect.left) && (pt.x < item->rect.right) &&
626 (pt.y >= item->rect.top) && (pt.y < item->rect.bottom))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000627 {
628 if (pos) *pos = i;
629 return item;
630 }
631 }
632 return NULL;
633}
634
635
636/***********************************************************************
637 * MENU_FindItemByKey
638 *
639 * Find the menu item selected by a key press.
640 * Return item id, -1 if none, -2 if we should close the menu.
641 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000642static UINT MENU_FindItemByKey( HWND hwndOwner, HMENU hmenu,
643 UINT key, BOOL forceMenuChar )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000644{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000645 TRACE("\tlooking for '%c' in [%04x]\n", (char)key, (UINT16)hmenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000646
Alexandre Julliarda3960291999-02-26 11:11:13 +0000647 if (!IsMenu( hmenu ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000648 {
649 WND* w = WIN_FindWndPtr(hwndOwner);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000650 hmenu = GetSubMenu(w->hSysMenu, 0);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000651 WIN_ReleaseWndPtr(w);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000652 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000653
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000654 if (hmenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000655 {
Gerard Patel3e629742000-01-17 22:22:16 +0000656 POPUPMENU *menu = MENU_GetMenu( hmenu );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000657 MENUITEM *item = menu->items;
658 LONG menuchar;
659
660 if( !forceMenuChar )
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000661 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000662 UINT i;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000663
664 key = toupper(key);
665 for (i = 0; i < menu->nItems; i++, item++)
666 {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000667 if (item->text && (IS_STRING_ITEM(item->fType)))
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000668 {
Aric Stewartc946b1c2000-10-24 21:28:19 +0000669 WCHAR *p = item->text - 2;
Norman Stevensa83d0651998-10-12 07:25:35 +0000670 do
671 {
Aric Stewartc946b1c2000-10-24 21:28:19 +0000672 p = strchrW (p + 2, '&');
Norman Stevensa83d0651998-10-12 07:25:35 +0000673 }
674 while (p != NULL && p [1] == '&');
675 if (p && (toupper(p[1]) == key)) return i;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000676 }
677 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000678 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000679 menuchar = SendMessageA( hwndOwner, WM_MENUCHAR,
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000680 MAKEWPARAM( key, menu->wFlags ), hmenu );
681 if (HIWORD(menuchar) == 2) return LOWORD(menuchar);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000682 if (HIWORD(menuchar) == 1) return (UINT)(-2);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000683 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000684 return (UINT)(-1);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000685}
Francois Boisvert8b391741999-02-09 14:09:55 +0000686/***********************************************************************
687 * MENU_LoadMagicItem
688 *
689 * Load the bitmap associated with the magic menu item and its style
690 */
Alexandre Julliarddba420a1994-02-02 06:48:31 +0000691
Juergen Schmied78513941999-04-18 14:40:32 +0000692static HBITMAP MENU_LoadMagicItem(UINT id, BOOL hilite, DWORD dwItemData)
Francois Boisvert8b391741999-02-09 14:09:55 +0000693{
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +0000694 /*
695 * Magic menu item id's section
696 * These magic id's are used by windows to insert "standard" mdi
697 * buttons (minimize,restore,close) on menu. Under windows,
698 * these magic id's make sure the right things appear when those
699 * bitmap buttons are pressed/selected/released.
700 */
Francois Boisvert8b391741999-02-09 14:09:55 +0000701
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +0000702 switch(id & 0xffff)
Juergen Schmied78513941999-04-18 14:40:32 +0000703 { case HBMMENU_SYSTEM:
704 return (dwItemData) ?
705 (HBITMAP)dwItemData :
706 (hilite ? hBmpMinimizeD : hBmpMinimize);
707 case HBMMENU_MBAR_RESTORE:
708 return (hilite ? hBmpMaximizeD: hBmpMaximize);
709 case HBMMENU_MBAR_MINIMIZE:
710 return (hilite ? hBmpMinimizeD : hBmpMinimize);
711 case HBMMENU_MBAR_CLOSE:
712 return (hilite ? hBmpCloseD : hBmpClose);
713 case HBMMENU_CALLBACK:
714 case HBMMENU_MBAR_CLOSE_D:
715 case HBMMENU_MBAR_MINIMIZE_D:
716 case HBMMENU_POPUP_CLOSE:
717 case HBMMENU_POPUP_RESTORE:
718 case HBMMENU_POPUP_MAXIMIZE:
719 case HBMMENU_POPUP_MINIMIZE:
720 default:
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000721 FIXME("Magic 0x%08x not implemented\n", id);
Juergen Schmied78513941999-04-18 14:40:32 +0000722 return 0;
Francois Boisvert8b391741999-02-09 14:09:55 +0000723 }
724
725}
Alexandre Julliardf7207251994-07-23 07:57:48 +0000726
727/***********************************************************************
728 * MENU_CalcItemSize
729 *
730 * Calculate the size of the menu item and store it in lpitem->rect.
731 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000732static void MENU_CalcItemSize( HDC hdc, MENUITEM *lpitem, HWND hwndOwner,
733 INT orgX, INT orgY, BOOL menuBar )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000734{
Aric Stewartc946b1c2000-10-24 21:28:19 +0000735 WCHAR *p;
Alexandre Julliardc1d35cc2001-01-24 19:47:57 +0000736 UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000737
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000738 TRACE("dc=0x%04x owner=0x%04x (%d,%d)\n", hdc, hwndOwner, orgX, orgY);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000739 debug_print_menuitem("MENU_CalcItemSize: menuitem:", lpitem,
740 (menuBar ? " (MenuBar)" : ""));
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000741
Alexandre Julliarda3960291999-02-26 11:11:13 +0000742 SetRect( &lpitem->rect, orgX, orgY, orgX, orgY );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000743
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000744 if (lpitem->fType & MF_OWNERDRAW)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000745 {
Ken Thomases130f0d82000-05-10 21:38:37 +0000746 /*
747 ** Experimentation under Windows reveals that an owner-drawn
748 ** menu is expected to return the size of the content part of
749 ** the menu item, not including the checkmark nor the submenu
750 ** arrow. Windows adds those values itself and returns the
751 ** enlarged rectangle on subsequent WM_DRAWITEM messages.
752 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000753 MEASUREITEMSTRUCT mis;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000754 mis.CtlType = ODT_MENU;
Juergen Schmied7abca951999-04-11 17:02:30 +0000755 mis.CtlID = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000756 mis.itemID = lpitem->wID;
Juergen Schmied7abca951999-04-11 17:02:30 +0000757 mis.itemData = (DWORD)lpitem->dwItemData;
758 mis.itemHeight = 0;
759 mis.itemWidth = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000760 SendMessageA( hwndOwner, WM_MEASUREITEM, 0, (LPARAM)&mis );
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000761 lpitem->rect.right += mis.itemWidth;
Aric Stewart70cc1692000-05-10 21:54:07 +0000762
763 if (menuBar)
764 {
765 lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
766
767
768 /* under at least win95 you seem to be given a standard
769 height for the menu and the height value is ignored */
770
771 if (TWEAK_WineLook == WIN31_LOOK)
772 lpitem->rect.bottom += GetSystemMetrics(SM_CYMENU);
773 else
774 lpitem->rect.bottom += GetSystemMetrics(SM_CYMENU)-1;
775 }
776 else
777 lpitem->rect.bottom += mis.itemHeight;
778
779 TRACE("id=%04x size=%dx%d\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000780 lpitem->wID, mis.itemWidth, mis.itemHeight);
Ken Thomases130f0d82000-05-10 21:38:37 +0000781 /* Fall through to get check/arrow width calculation. */
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000782 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000783
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000784 if (lpitem->fType & MF_SEPARATOR)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000785 {
786 lpitem->rect.bottom += SEPARATOR_HEIGHT;
787 return;
788 }
789
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000790 if (!menuBar)
791 {
792 lpitem->rect.right += 2 * check_bitmap_width;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000793 if (lpitem->fType & MF_POPUP)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000794 lpitem->rect.right += arrow_bitmap_width;
795 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000796
Ken Thomases130f0d82000-05-10 21:38:37 +0000797 if (lpitem->fType & MF_OWNERDRAW)
798 return;
799
Juergen Schmied78513941999-04-18 14:40:32 +0000800 if (IS_BITMAP_ITEM(lpitem->fType))
Alexandre Julliardf7207251994-07-23 07:57:48 +0000801 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000802 BITMAP bm;
Juergen Schmied78513941999-04-18 14:40:32 +0000803 HBITMAP resBmp = 0;
Francois Boisvert8b391741999-02-09 14:09:55 +0000804
Patrik Stridvall1bb94031999-05-08 15:47:44 +0000805 /* Check if there is a magic menu item associated with this item */
François Gouget75b278e2001-01-06 01:45:51 +0000806 if (IS_MAGIC_ITEM(lpitem->text))
Juergen Schmied78513941999-04-18 14:40:32 +0000807 {
808 resBmp = MENU_LoadMagicItem((int)lpitem->text, (lpitem->fType & MF_HILITE),
809 lpitem->dwItemData);
Francois Boisvert8b391741999-02-09 14:09:55 +0000810 }
811 else
Alexandre Julliarda3960291999-02-26 11:11:13 +0000812 resBmp = (HBITMAP)lpitem->text;
Francois Boisvert8b391741999-02-09 14:09:55 +0000813
Alexandre Julliarda3960291999-02-26 11:11:13 +0000814 if (GetObjectA(resBmp, sizeof(bm), &bm ))
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000815 {
816 lpitem->rect.right += bm.bmWidth;
817 lpitem->rect.bottom += bm.bmHeight;
Francois Gouget75f9e642000-11-06 05:25:29 +0000818 if (TWEAK_WineLook == WIN98_LOOK) {
819 /* Leave space for the sunken border */
820 lpitem->rect.right += 2;
821 lpitem->rect.bottom += 2;
822 }
Francois Boisvert8b391741999-02-09 14:09:55 +0000823
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000824 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000825 }
826
Juergen Schmied78513941999-04-18 14:40:32 +0000827
Gerard Patel2482ef32001-03-19 19:16:21 +0000828 /* it must be a text item - unless it's the system menu */
829 if (!(lpitem->fType & MF_SYSMENU) && IS_STRING_ITEM( lpitem->fType ))
Juergen Schmied78513941999-04-18 14:40:32 +0000830 { SIZE size;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000831
Aric Stewartc946b1c2000-10-24 21:28:19 +0000832 GetTextExtentPoint32W(hdc, lpitem->text, strlenW(lpitem->text), &size);
Juergen Schmied78513941999-04-18 14:40:32 +0000833
834 lpitem->rect.right += size.cx;
835 if (TWEAK_WineLook == WIN31_LOOK)
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000836 lpitem->rect.bottom += max( size.cy, GetSystemMetrics(SM_CYMENU) );
Juergen Schmied78513941999-04-18 14:40:32 +0000837 else
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000838 lpitem->rect.bottom += max(size.cy, GetSystemMetrics(SM_CYMENU)-1);
Juergen Schmied78513941999-04-18 14:40:32 +0000839 lpitem->xTab = 0;
840
841 if (menuBar)
842 {
843 lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
844 }
Aric Stewartc946b1c2000-10-24 21:28:19 +0000845 else if ((p = strchrW( lpitem->text, '\t' )) != NULL)
Juergen Schmied78513941999-04-18 14:40:32 +0000846 {
847 /* Item contains a tab (only meaningful in popup menus) */
Aric Stewartc946b1c2000-10-24 21:28:19 +0000848 GetTextExtentPoint32W(hdc, lpitem->text, (int)(p - lpitem->text) , &size);
Juergen Schmied78513941999-04-18 14:40:32 +0000849 lpitem->xTab = check_bitmap_width + MENU_TAB_SPACE + size.cx;
850 lpitem->rect.right += MENU_TAB_SPACE;
851 }
852 else
853 {
Aric Stewartc946b1c2000-10-24 21:28:19 +0000854 if (strchrW( lpitem->text, '\b' ))
Juergen Schmied78513941999-04-18 14:40:32 +0000855 lpitem->rect.right += MENU_TAB_SPACE;
856 lpitem->xTab = lpitem->rect.right - check_bitmap_width
857 - arrow_bitmap_width;
858 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000859 }
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000860 TRACE("(%d,%d)-(%d,%d)\n", lpitem->rect.left, lpitem->rect.top, lpitem->rect.right, lpitem->rect.bottom);
Alexandre Julliardf7207251994-07-23 07:57:48 +0000861}
862
863
864/***********************************************************************
865 * MENU_PopupMenuCalcSize
866 *
867 * Calculate the size of a popup menu.
868 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000869static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND hwndOwner )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000870{
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000871 MENUITEM *lpitem;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000872 HDC hdc;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000873 int start, i;
874 int orgX, orgY, maxX, maxTab, maxTabWidth;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000875
Alexandre Julliardf7207251994-07-23 07:57:48 +0000876 lppop->Width = lppop->Height = 0;
877 if (lppop->nItems == 0) return;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000878 hdc = GetDC( 0 );
Juergen Schmied78513941999-04-18 14:40:32 +0000879
880 SelectObject( hdc, hMenuFont);
881
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000882 start = 0;
Francois Gouget75f9e642000-11-06 05:25:29 +0000883 maxX = (TWEAK_WineLook == WIN31_LOOK) ? GetSystemMetrics(SM_CXBORDER) : 2+1 ;
Juergen Schmied466a6521999-05-02 11:21:08 +0000884
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000885 while (start < lppop->nItems)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000886 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000887 lpitem = &lppop->items[start];
Alexandre Julliardf7207251994-07-23 07:57:48 +0000888 orgX = maxX;
Marcus Meissnerddca3151999-05-22 11:33:23 +0000889 orgY = (TWEAK_WineLook == WIN31_LOOK) ? GetSystemMetrics(SM_CYBORDER) : 2;
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +0000890
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000891 maxTab = maxTabWidth = 0;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000892
893 /* Parse items until column break or end of menu */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000894 for (i = start; i < lppop->nItems; i++, lpitem++)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000895 {
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000896 if ((i != start) &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000897 (lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000898
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000899 MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, FALSE );
Pascal Lessard47274231999-02-13 12:21:46 +0000900
Juergen Schmied466a6521999-05-02 11:21:08 +0000901 if (lpitem->fType & MF_MENUBARBREAK) orgX++;
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000902 maxX = max( maxX, lpitem->rect.right );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000903 orgY = lpitem->rect.bottom;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000904 if (IS_STRING_ITEM(lpitem->fType) && lpitem->xTab)
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000905 {
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000906 maxTab = max( maxTab, lpitem->xTab );
907 maxTabWidth = max(maxTabWidth,lpitem->rect.right-lpitem->xTab);
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000908 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000909 }
910
911 /* Finish the column (set all items to the largest width found) */
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000912 maxX = max( maxX, maxTab + maxTabWidth );
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000913 for (lpitem = &lppop->items[start]; start < i; start++, lpitem++)
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000914 {
915 lpitem->rect.right = maxX;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000916 if (IS_STRING_ITEM(lpitem->fType) && lpitem->xTab)
Juergen Schmied466a6521999-05-02 11:21:08 +0000917 lpitem->xTab = maxTab;
918
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000919 }
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000920 lppop->Height = max( lppop->Height, orgY );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000921 }
922
923 lppop->Width = maxX;
Juergen Schmied466a6521999-05-02 11:21:08 +0000924
925 /* space for 3d border */
926 if(TWEAK_WineLook > WIN31_LOOK)
927 {
928 lppop->Height += 2;
929 lppop->Width += 2;
930 }
931
Alexandre Julliarda3960291999-02-26 11:11:13 +0000932 ReleaseDC( 0, hdc );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000933}
934
935
936/***********************************************************************
937 * MENU_MenuBarCalcSize
938 *
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000939 * FIXME: Word 6 implements its own MDI and its own 'close window' bitmap
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000940 * height is off by 1 pixel which causes lengthy window relocations when
941 * active document window is maximized/restored.
942 *
Alexandre Julliardf7207251994-07-23 07:57:48 +0000943 * Calculate the size of the menu bar.
944 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000945static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect,
946 LPPOPUPMENU lppop, HWND hwndOwner )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000947{
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000948 MENUITEM *lpitem;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000949 int start, i, orgX, orgY, maxY, helpPos;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000950
951 if ((lprect == NULL) || (lppop == NULL)) return;
952 if (lppop->nItems == 0) return;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000953 TRACE("left=%d top=%d right=%d bottom=%d\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000954 lprect->left, lprect->top, lprect->right, lprect->bottom);
Alexandre Julliardf7207251994-07-23 07:57:48 +0000955 lppop->Width = lprect->right - lprect->left;
956 lppop->Height = 0;
Francois Gouget75f9e642000-11-06 05:25:29 +0000957 maxY = lprect->top+1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000958 start = 0;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000959 helpPos = -1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000960 while (start < lppop->nItems)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000961 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000962 lpitem = &lppop->items[start];
Alexandre Julliardf7207251994-07-23 07:57:48 +0000963 orgX = lprect->left;
964 orgY = maxY;
965
966 /* Parse items until line break or end of menu */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000967 for (i = start; i < lppop->nItems; i++, lpitem++)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000968 {
Francois Gouget58182402001-01-04 20:56:43 +0000969 if ((helpPos == -1) && (lpitem->fType & MF_RIGHTJUSTIFY)) helpPos = i;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000970 if ((i != start) &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000971 (lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000972
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000973 TRACE("calling MENU_CalcItemSize org=(%d, %d)\n",
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000974 orgX, orgY );
Alexandre Julliard03468f71998-02-15 19:40:49 +0000975 debug_print_menuitem (" item: ", lpitem, "");
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000976 MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, TRUE );
Pascal Lessard47274231999-02-13 12:21:46 +0000977
Alexandre Julliardf7207251994-07-23 07:57:48 +0000978 if (lpitem->rect.right > lprect->right)
979 {
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000980 if (i != start) break;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000981 else lpitem->rect.right = lprect->right;
982 }
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000983 maxY = max( maxY, lpitem->rect.bottom );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000984 orgX = lpitem->rect.right;
985 }
986
987 /* Finish the line (set all items to the largest height found) */
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000988 while (start < i) lppop->items[start++].rect.bottom = maxY;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000989 }
990
991 lprect->bottom = maxY;
992 lppop->Height = lprect->bottom - lprect->top;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000993
Francois Gouget58182402001-01-04 20:56:43 +0000994 /* Flush right all items between the MF_RIGHTJUSTIFY and */
995 /* the last item (if several lines, only move the last line) */
996 lpitem = &lppop->items[lppop->nItems-1];
997 orgY = lpitem->rect.top;
998 orgX = lprect->right;
999 for (i = lppop->nItems - 1; i >= helpPos; i--, lpitem--) {
1000 if ( (helpPos==-1) || (helpPos>i) )
1001 break; /* done */
1002 if (lpitem->rect.top != orgY) break; /* Other line */
1003 if (lpitem->rect.right >= orgX) break; /* Too far right already */
1004 lpitem->rect.left += orgX - lpitem->rect.right;
1005 lpitem->rect.right = orgX;
1006 orgX = lpitem->rect.left;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001007 }
Alexandre Julliardf7207251994-07-23 07:57:48 +00001008}
1009
Alexandre Julliardf7207251994-07-23 07:57:48 +00001010/***********************************************************************
1011 * MENU_DrawMenuItem
1012 *
1013 * Draw a single menu item.
1014 */
Juergen Schmied78513941999-04-18 14:40:32 +00001015static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, MENUITEM *lpitem,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001016 UINT height, BOOL menuBar, UINT odaction )
Alexandre Julliardf7207251994-07-23 07:57:48 +00001017{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001018 RECT rect;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001019
Alexandre Julliard03468f71998-02-15 19:40:49 +00001020 debug_print_menuitem("MENU_DrawMenuItem: ", lpitem, "");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001021
1022 if (lpitem->fType & MF_SYSMENU)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001023 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001024 if( !IsIconic(hwnd) ) {
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001025 if (TWEAK_WineLook > WIN31_LOOK)
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001026 NC_DrawSysButton95( hwnd, hdc,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001027 lpitem->fState &
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001028 (MF_HILITE | MF_MOUSESELECT) );
1029 else
1030 NC_DrawSysButton( hwnd, hdc,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001031 lpitem->fState &
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001032 (MF_HILITE | MF_MOUSESELECT) );
1033 }
1034
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001035 return;
1036 }
1037
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001038 if (lpitem->fType & MF_OWNERDRAW)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001039 {
Ken Thomases130f0d82000-05-10 21:38:37 +00001040 /*
1041 ** Experimentation under Windows reveals that an owner-drawn
1042 ** menu is given the rectangle which includes the space it requested
1043 ** in its response to WM_MEASUREITEM _plus_ width for a checkmark
1044 ** and a popup-menu arrow. This is the value of lpitem->rect.
1045 ** Windows will leave all drawing to the application except for
1046 ** the popup-menu arrow. Windows always draws that itself, after
1047 ** the menu owner has finished drawing.
1048 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001049 DRAWITEMSTRUCT dis;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001050
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001051 dis.CtlType = ODT_MENU;
Juergen Schmied7abca951999-04-11 17:02:30 +00001052 dis.CtlID = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001053 dis.itemID = lpitem->wID;
Juergen Schmied7abca951999-04-11 17:02:30 +00001054 dis.itemData = (DWORD)lpitem->dwItemData;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001055 dis.itemState = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001056 if (lpitem->fState & MF_CHECKED) dis.itemState |= ODS_CHECKED;
1057 if (lpitem->fState & MF_GRAYED) dis.itemState |= ODS_GRAYED;
1058 if (lpitem->fState & MF_HILITE) dis.itemState |= ODS_SELECTED;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001059 dis.itemAction = odaction; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */
Juergen Schmied78513941999-04-18 14:40:32 +00001060 dis.hwndItem = hmenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001061 dis.hDC = hdc;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001062 dis.rcItem = lpitem->rect;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001063 TRACE("Ownerdraw: owner=%04x itemID=%d, itemState=%d, itemAction=%d, "
Juergen Schmied78513941999-04-18 14:40:32 +00001064 "hwndItem=%04x, hdc=%04x, rcItem={%d,%d,%d,%d}\n", hwndOwner,
1065 dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
1066 dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right,
1067 dis.rcItem.bottom);
1068 SendMessageA( hwndOwner, WM_DRAWITEM, 0, (LPARAM)&dis );
Ken Thomases130f0d82000-05-10 21:38:37 +00001069 /* Fall through to draw popup-menu arrow */
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001070 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001071
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001072 TRACE("rect={%d,%d,%d,%d}\n", lpitem->rect.left, lpitem->rect.top,
Juergen Schmied78513941999-04-18 14:40:32 +00001073 lpitem->rect.right,lpitem->rect.bottom);
1074
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001075 if (menuBar && (lpitem->fType & MF_SEPARATOR)) return;
Juergen Schmied78513941999-04-18 14:40:32 +00001076
Alexandre Julliardf7207251994-07-23 07:57:48 +00001077 rect = lpitem->rect;
1078
Ken Thomases130f0d82000-05-10 21:38:37 +00001079 if (!(lpitem->fType & MF_OWNERDRAW))
1080 {
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001081 if (lpitem->fState & MF_HILITE)
1082 {
1083 if(TWEAK_WineLook == WIN98_LOOK)
1084 {
1085 if(menuBar)
1086 DrawEdge(hdc, &rect, BDR_SUNKENOUTER, BF_RECT);
1087 else
1088 FillRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
1089 }
1090 else /* Not Win98 Look */
1091 {
1092 if(!IS_BITMAP_ITEM(lpitem->fType))
1093 FillRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
1094 }
1095 }
Ken Thomases130f0d82000-05-10 21:38:37 +00001096 else
1097 FillRect( hdc, &rect, GetSysColorBrush(COLOR_MENU) );
1098 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001099
Alexandre Julliarda3960291999-02-26 11:11:13 +00001100 SetBkMode( hdc, TRANSPARENT );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001101
Ken Thomases130f0d82000-05-10 21:38:37 +00001102 if (!(lpitem->fType & MF_OWNERDRAW))
Alexandre Julliardf7207251994-07-23 07:57:48 +00001103 {
Ken Thomases130f0d82000-05-10 21:38:37 +00001104 /* vertical separator */
1105 if (!menuBar && (lpitem->fType & MF_MENUBARBREAK))
1106 {
1107 if (TWEAK_WineLook > WIN31_LOOK)
1108 {
1109 RECT rc = rect;
1110 rc.top = 3;
1111 rc.bottom = height - 3;
1112 DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT);
1113 }
1114 else
1115 {
1116 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001117 MoveToEx( hdc, rect.left, 0, NULL );
Ken Thomases130f0d82000-05-10 21:38:37 +00001118 LineTo( hdc, rect.left, height );
1119 }
1120 }
Juergen Schmied78513941999-04-18 14:40:32 +00001121
Ken Thomases130f0d82000-05-10 21:38:37 +00001122 /* horizontal separator */
1123 if (lpitem->fType & MF_SEPARATOR)
1124 {
1125 if (TWEAK_WineLook > WIN31_LOOK)
1126 {
1127 RECT rc = rect;
1128 rc.left++;
1129 rc.right--;
1130 rc.top += SEPARATOR_HEIGHT / 2;
1131 DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP);
1132 }
1133 else
1134 {
1135 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001136 MoveToEx( hdc, rect.left, rect.top + SEPARATOR_HEIGHT/2, NULL );
Ken Thomases130f0d82000-05-10 21:38:37 +00001137 LineTo( hdc, rect.right, rect.top + SEPARATOR_HEIGHT/2 );
1138 }
1139 return;
1140 }
Alexandre Julliardf7207251994-07-23 07:57:48 +00001141 }
1142
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001143 /* Setup colors */
1144
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001145 if (lpitem->fState & MF_HILITE)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001146 {
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001147 if(TWEAK_WineLook == WIN98_LOOK)
1148 {
François Gouget75b278e2001-01-06 01:45:51 +00001149 if(menuBar) {
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001150 SetTextColor(hdc, GetSysColor(COLOR_MENUTEXT));
François Gouget75b278e2001-01-06 01:45:51 +00001151 SetBkColor(hdc, GetSysColor(COLOR_MENU));
1152 } else {
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001153 if(lpitem->fState & MF_GRAYED)
1154 SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
1155 else
1156 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
François Gouget75b278e2001-01-06 01:45:51 +00001157 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001158 }
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001159 }
1160 else /* Not Win98 Look */
1161 {
1162 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1163 if(!IS_BITMAP_ITEM(lpitem->fType))
1164 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001165 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001166 }
1167 else
1168 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001169 if (lpitem->fState & MF_GRAYED)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001170 SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001171 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001172 SetTextColor( hdc, GetSysColor( COLOR_MENUTEXT ) );
1173 SetBkColor( hdc, GetSysColor( COLOR_MENU ) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001174 }
1175
Juergen Schmied78513941999-04-18 14:40:32 +00001176 /* helper lines for debugging */
1177/* FrameRect(hdc, &rect, GetStockObject(BLACK_BRUSH));
1178 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001179 MoveToEx( hdc, rect.left, (rect.top + rect.bottom)/2, NULL );
Juergen Schmied78513941999-04-18 14:40:32 +00001180 LineTo( hdc, rect.right, (rect.top + rect.bottom)/2 );
1181*/
1182
Alexandre Julliardf7207251994-07-23 07:57:48 +00001183 if (!menuBar)
1184 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001185 INT y = rect.top + rect.bottom;
Alexandre Julliardc1d35cc2001-01-24 19:47:57 +00001186 UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
1187 UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001188
Ken Thomases130f0d82000-05-10 21:38:37 +00001189 if (!(lpitem->fType & MF_OWNERDRAW))
1190 {
1191 /* Draw the check mark
1192 *
1193 * FIXME:
1194 * Custom checkmark bitmaps are monochrome but not always 1bpp.
1195 */
Alexandre Julliardc1d35cc2001-01-24 19:47:57 +00001196 HBITMAP bm = (lpitem->fState & MF_CHECKED) ? lpitem->hCheckBit : lpitem->hUnCheckBit;
1197 if (bm) /* we have a custom bitmap */
1198 {
1199 HDC hdcMem = CreateCompatibleDC( hdc );
1200 SelectObject( hdcMem, bm );
1201 BitBlt( hdc, rect.left, (y - check_bitmap_height) / 2,
1202 check_bitmap_width, check_bitmap_height,
1203 hdcMem, 0, 0, SRCCOPY );
1204 DeleteDC( hdcMem );
1205 }
1206 else if (lpitem->fState & MF_CHECKED) /* standard bitmaps */
1207 {
1208 RECT r;
1209 HBITMAP bm = CreateBitmap( check_bitmap_width, check_bitmap_height, 1, 1, NULL );
1210 HDC hdcMem = CreateCompatibleDC( hdc );
1211 SelectObject( hdcMem, bm );
1212 SetRect( &r, 0, 0, check_bitmap_width, check_bitmap_height );
1213 DrawFrameControl( hdcMem, &r, DFC_MENU,
1214 (lpitem->fType & MFT_RADIOCHECK) ?
1215 DFCS_MENUBULLET : DFCS_MENUCHECK );
1216 BitBlt( hdc, rect.left, (y - r.bottom) / 2, r.right, r.bottom,
1217 hdcMem, 0, 0, SRCCOPY );
1218 DeleteDC( hdcMem );
1219 DeleteObject( bm );
1220 }
Ken Thomases130f0d82000-05-10 21:38:37 +00001221 }
Juergen Schmied78513941999-04-18 14:40:32 +00001222
Alexandre Julliardf7207251994-07-23 07:57:48 +00001223 /* Draw the popup-menu arrow */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001224 if (lpitem->fType & MF_POPUP)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001225 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001226 HDC hdcMem = CreateCompatibleDC( hdc );
Ken Thomases130f0d82000-05-10 21:38:37 +00001227 HBITMAP hOrigBitmap;
Huw D M Davies2d617be1998-12-08 09:14:09 +00001228
Ken Thomases130f0d82000-05-10 21:38:37 +00001229 hOrigBitmap = SelectObject( hdcMem, hStdMnArrow );
Juergen Schmied78513941999-04-18 14:40:32 +00001230 BitBlt( hdc, rect.right - arrow_bitmap_width - 1,
Huw D M Davies2d617be1998-12-08 09:14:09 +00001231 (y - arrow_bitmap_height) / 2,
1232 arrow_bitmap_width, arrow_bitmap_height,
1233 hdcMem, 0, 0, SRCCOPY );
Ken Thomases130f0d82000-05-10 21:38:37 +00001234 SelectObject( hdcMem, hOrigBitmap );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001235 DeleteDC( hdcMem );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001236 }
1237
1238 rect.left += check_bitmap_width;
1239 rect.right -= arrow_bitmap_width;
1240 }
1241
Ken Thomases130f0d82000-05-10 21:38:37 +00001242 /* Done for owner-drawn */
1243 if (lpitem->fType & MF_OWNERDRAW)
1244 return;
1245
Juergen Schmied78513941999-04-18 14:40:32 +00001246 /* Draw the item text or bitmap */
1247 if (IS_BITMAP_ITEM(lpitem->fType))
François Gouget75b278e2001-01-06 01:45:51 +00001248 {
1249 int left,top,w,h;
1250 DWORD rop;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001251
Alexandre Julliarda3960291999-02-26 11:11:13 +00001252 HBITMAP resBmp = 0;
Francois Boisvert8b391741999-02-09 14:09:55 +00001253
Alexandre Julliarda3960291999-02-26 11:11:13 +00001254 HDC hdcMem = CreateCompatibleDC( hdc );
Huw D M Davies2d617be1998-12-08 09:14:09 +00001255
Patrik Stridvall1bb94031999-05-08 15:47:44 +00001256 /*
1257 * Check if there is a magic menu item associated with this item
1258 * and load the appropriate bitmap
1259 */
François Gouget75b278e2001-01-06 01:45:51 +00001260 if (IS_MAGIC_ITEM(lpitem->text))
Juergen Schmied78513941999-04-18 14:40:32 +00001261 {
1262 resBmp = MENU_LoadMagicItem((int)lpitem->text, (lpitem->fState & MF_HILITE),
1263 lpitem->dwItemData);
Francois Boisvert8b391741999-02-09 14:09:55 +00001264 }
1265 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001266 resBmp = (HBITMAP)lpitem->text;
Juergen Schmied78513941999-04-18 14:40:32 +00001267
1268 if (resBmp)
1269 {
1270 BITMAP bm;
1271 GetObjectA( resBmp, sizeof(bm), &bm );
1272
1273 SelectObject(hdcMem,resBmp );
1274
Andreas Mohra6d83eb2000-12-27 04:02:46 +00001275 /* handle fontsize > bitmap_height */
François Gouget75b278e2001-01-06 01:45:51 +00001276 h=rect.bottom - rect.top;
1277 top = (h>bm.bmHeight) ?
1278 rect.top+(h-bm.bmHeight)/2 : rect.top;
1279 w=rect.right - rect.left;
1280 left=rect.left;
1281 if (TWEAK_WineLook == WIN95_LOOK) {
1282 rop=((lpitem->fState & MF_HILITE) && !IS_MAGIC_ITEM(lpitem->text)) ? NOTSRCCOPY : SRCCOPY;
1283 if ((lpitem->fState & MF_HILITE) && IS_BITMAP_ITEM(lpitem->fType))
1284 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
1285 } else {
1286 left++;
1287 w-=2;
1288 rop=((lpitem->fState & MF_HILITE) && !IS_MAGIC_ITEM(lpitem->text) && (!menuBar)) ? MERGEPAINT : SRCCOPY;
1289 }
1290 BitBlt( hdc, left, top, w,
1291 h, hdcMem, 0, 0,
1292 rop);
Juergen Schmied78513941999-04-18 14:40:32 +00001293 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001294 DeleteDC( hdcMem );
Juergen Schmied78513941999-04-18 14:40:32 +00001295
Alexandre Julliardf7207251994-07-23 07:57:48 +00001296 return;
Francois Boisvert8b391741999-02-09 14:09:55 +00001297
Alexandre Julliardf7207251994-07-23 07:57:48 +00001298 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001299 /* No bitmap - process text if present */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001300 else if (IS_STRING_ITEM(lpitem->fType))
Alexandre Julliardf7207251994-07-23 07:57:48 +00001301 {
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001302 register int i;
Juergen Schmied466a6521999-05-02 11:21:08 +00001303 HFONT hfontOld = 0;
1304
Juergen Schmied78513941999-04-18 14:40:32 +00001305 UINT uFormat = (menuBar) ?
1306 DT_CENTER | DT_VCENTER | DT_SINGLELINE :
1307 DT_LEFT | DT_VCENTER | DT_SINGLELINE;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001308
Juergen Schmied466a6521999-05-02 11:21:08 +00001309 if ( lpitem->fState & MFS_DEFAULT )
1310 {
1311 hfontOld = SelectObject( hdc, hMenuFontBold);
1312 }
1313
Alexandre Julliardf7207251994-07-23 07:57:48 +00001314 if (menuBar)
1315 {
1316 rect.left += MENU_BAR_ITEMS_SPACE / 2;
1317 rect.right -= MENU_BAR_ITEMS_SPACE / 2;
Aric Stewartc946b1c2000-10-24 21:28:19 +00001318 i = strlenW( lpitem->text );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001319 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001320 else
Alexandre Julliardf7207251994-07-23 07:57:48 +00001321 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001322 for (i = 0; lpitem->text[i]; i++)
Juergen Schmied466a6521999-05-02 11:21:08 +00001323 if ((lpitem->text[i] == '\t') || (lpitem->text[i] == '\b'))
1324 break;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001325 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001326
Juergen Schmied466a6521999-05-02 11:21:08 +00001327 if( !(TWEAK_WineLook == WIN31_LOOK) && (lpitem->fState & MF_GRAYED))
Juergen Schmied78513941999-04-18 14:40:32 +00001328 {
Juergen Schmied466a6521999-05-02 11:21:08 +00001329 if (!(lpitem->fState & MF_HILITE) )
Juergen Schmied78513941999-04-18 14:40:32 +00001330 {
Juergen Schmied466a6521999-05-02 11:21:08 +00001331 ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001332 SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
Aric Stewartc946b1c2000-10-24 21:28:19 +00001333 DrawTextW( hdc, lpitem->text, i, &rect, uFormat );
Juergen Schmied466a6521999-05-02 11:21:08 +00001334 --rect.left; --rect.top; --rect.right; --rect.bottom;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001335 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001336 SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001337 }
Juergen Schmied466a6521999-05-02 11:21:08 +00001338
Aric Stewartc946b1c2000-10-24 21:28:19 +00001339 DrawTextW( hdc, lpitem->text, i, &rect, uFormat);
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001340
Juergen Schmied466a6521999-05-02 11:21:08 +00001341 /* paint the shortcut text */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001342 if (lpitem->text[i]) /* There's a tab or flush-right char */
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001343 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001344 if (lpitem->text[i] == '\t')
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001345 {
1346 rect.left = lpitem->xTab;
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +00001347 uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001348 }
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +00001349 else
1350 {
1351 uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
1352 }
1353
Juergen Schmied466a6521999-05-02 11:21:08 +00001354 if( !(TWEAK_WineLook == WIN31_LOOK) && (lpitem->fState & MF_GRAYED))
1355 {
1356 if (!(lpitem->fState & MF_HILITE) )
1357 {
1358 ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
1359 SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
Aric Stewartc946b1c2000-10-24 21:28:19 +00001360 DrawTextW( hdc, lpitem->text + i + 1, -1, &rect, uFormat );
Juergen Schmied466a6521999-05-02 11:21:08 +00001361 --rect.left; --rect.top; --rect.right; --rect.bottom;
1362 }
1363 SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
1364 }
Aric Stewartc946b1c2000-10-24 21:28:19 +00001365 DrawTextW( hdc, lpitem->text + i + 1, -1, &rect, uFormat );
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001366 }
Juergen Schmied466a6521999-05-02 11:21:08 +00001367
1368 if (hfontOld)
1369 SelectObject (hdc, hfontOld);
Alexandre Julliardf7207251994-07-23 07:57:48 +00001370 }
1371}
1372
1373
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001374/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001375 * MENU_DrawPopupMenu
1376 *
1377 * Paint a popup menu.
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001378 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001379static void MENU_DrawPopupMenu( HWND hwnd, HDC hdc, HMENU hmenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001380{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001381 HBRUSH hPrevBrush = 0;
1382 RECT rect;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001383
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001384 TRACE("wnd=0x%04x dc=0x%04x menu=0x%04x\n", hwnd, hdc, hmenu);
Juergen Schmied78513941999-04-18 14:40:32 +00001385
Alexandre Julliarda3960291999-02-26 11:11:13 +00001386 GetClientRect( hwnd, &rect );
Alexandre Julliard641ee761997-08-04 16:34:36 +00001387
Alex Korobka44a1b591999-04-01 12:03:52 +00001388 if(TWEAK_WineLook == WIN31_LOOK)
1389 {
Marcus Meissnerddca3151999-05-22 11:33:23 +00001390 rect.bottom -= POPUP_YSHADE * GetSystemMetrics(SM_CYBORDER);
1391 rect.right -= POPUP_XSHADE * GetSystemMetrics(SM_CXBORDER);
Alex Korobka44a1b591999-04-01 12:03:52 +00001392 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001393
Juergen Schmied78513941999-04-18 14:40:32 +00001394 if((hPrevBrush = SelectObject( hdc, GetSysColorBrush(COLOR_MENU) ))
1395 && (SelectObject( hdc, hMenuFont)))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001396 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001397 HPEN hPrevPen;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001398
Alexandre Julliarda3960291999-02-26 11:11:13 +00001399 Rectangle( hdc, rect.left, rect.top, rect.right, rect.bottom );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001400
Alexandre Julliarda3960291999-02-26 11:11:13 +00001401 hPrevPen = SelectObject( hdc, GetStockObject( NULL_PEN ) );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001402 if( hPrevPen )
1403 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001404 INT ropPrev, i;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001405 POPUPMENU *menu;
1406
1407 /* draw 3-d shade */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001408 if(TWEAK_WineLook == WIN31_LOOK) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001409 SelectObject( hdc, hShadeBrush );
1410 SetBkMode( hdc, TRANSPARENT );
1411 ropPrev = SetROP2( hdc, R2_MASKPEN );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001412
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001413 i = rect.right; /* why SetBrushOrg() doesn't? */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001414 PatBlt( hdc, i & 0xfffffffe,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001415 rect.top + POPUP_YSHADE*GetSystemMetrics(SM_CYBORDER),
1416 i%2 + POPUP_XSHADE*GetSystemMetrics(SM_CXBORDER),
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001417 rect.bottom - rect.top, 0x00a000c9 );
1418 i = rect.bottom;
Marcus Meissnerddca3151999-05-22 11:33:23 +00001419 PatBlt( hdc, rect.left + POPUP_XSHADE*GetSystemMetrics(SM_CXBORDER),
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001420 i & 0xfffffffe,rect.right - rect.left,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001421 i%2 + POPUP_YSHADE*GetSystemMetrics(SM_CYBORDER), 0x00a000c9 );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001422 SelectObject( hdc, hPrevPen );
1423 SelectObject( hdc, hPrevBrush );
1424 SetROP2( hdc, ropPrev );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001425 }
1426 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001427 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001428
1429 /* draw menu items */
1430
Gerard Patel3e629742000-01-17 22:22:16 +00001431 menu = MENU_GetMenu( hmenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001432 if (menu && menu->nItems)
1433 {
1434 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001435 UINT u;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001436
1437 for (u = menu->nItems, item = menu->items; u > 0; u--, item++)
Juergen Schmied78513941999-04-18 14:40:32 +00001438 MENU_DrawMenuItem( hwnd, hmenu, menu->hwndOwner, hdc, item,
1439 menu->Height, FALSE, ODA_DRAWENTIRE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001440
1441 }
Juergen Schmied78513941999-04-18 14:40:32 +00001442 } else
1443 {
1444 SelectObject( hdc, hPrevBrush );
1445 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001446 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001447}
1448
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001449/***********************************************************************
1450 * MENU_DrawMenuBar
1451 *
1452 * Paint a menu bar. Returns the height of the menu bar.
Juergen Schmied78513941999-04-18 14:40:32 +00001453 * called from [windows/nonclient.c]
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001454 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001455UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd,
1456 BOOL suppress_draw)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001457{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001458 LPPOPUPMENU lppop;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001459 UINT i,retvalue;
Juergen Schmied78513941999-04-18 14:40:32 +00001460 HFONT hfontOld = 0;
1461
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001462 WND *wndPtr = WIN_FindWndPtr( hwnd );
1463
Gerard Patel3e629742000-01-17 22:22:16 +00001464 lppop = MENU_GetMenu ((HMENU)wndPtr->wIDmenu );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001465 if (lppop == NULL || lprect == NULL)
1466 {
Marcus Meissnerddca3151999-05-22 11:33:23 +00001467 retvalue = GetSystemMetrics(SM_CYMENU);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001468 goto END;
1469 }
Juergen Schmied78513941999-04-18 14:40:32 +00001470
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001471 TRACE("(%04x, %p, %p)\n", hDC, lprect, lppop);
Juergen Schmied78513941999-04-18 14:40:32 +00001472
1473 hfontOld = SelectObject( hDC, hMenuFont);
1474
1475 if (lppop->Height == 0)
1476 MENU_MenuBarCalcSize(hDC, lprect, lppop, hwnd);
1477
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001478 lprect->bottom = lprect->top + lppop->Height;
Juergen Schmied78513941999-04-18 14:40:32 +00001479
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001480 if (suppress_draw)
1481 {
1482 retvalue = lppop->Height;
1483 goto END;
1484 }
Juergen Schmied78513941999-04-18 14:40:32 +00001485
Alexandre Julliarda3960291999-02-26 11:11:13 +00001486 FillRect(hDC, lprect, GetSysColorBrush(COLOR_MENU) );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001487
Juergen Schmied78513941999-04-18 14:40:32 +00001488 if (TWEAK_WineLook == WIN31_LOOK)
1489 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001490 SelectObject( hDC, GetSysColorPen(COLOR_WINDOWFRAME) );
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001491 MoveToEx( hDC, lprect->left, lprect->bottom, NULL );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001492 LineTo( hDC, lprect->right, lprect->bottom );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001493 }
Juergen Schmied78513941999-04-18 14:40:32 +00001494 else
1495 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001496 SelectObject( hDC, GetSysColorPen(COLOR_3DFACE));
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001497 MoveToEx( hDC, lprect->left, lprect->bottom, NULL );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001498 LineTo( hDC, lprect->right, lprect->bottom );
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001499 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001500
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001501 if (lppop->nItems == 0)
1502 {
Marcus Meissnerddca3151999-05-22 11:33:23 +00001503 retvalue = GetSystemMetrics(SM_CYMENU);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001504 goto END;
1505 }
Juergen Schmied78513941999-04-18 14:40:32 +00001506
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001507 for (i = 0; i < lppop->nItems; i++)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001508 {
Aric Stewart70cc1692000-05-10 21:54:07 +00001509 MENU_DrawMenuItem( hwnd, (HMENU)wndPtr->wIDmenu, hwnd,
Juergen Schmied78513941999-04-18 14:40:32 +00001510 hDC, &lppop->items[i], lppop->Height, TRUE, ODA_DRAWENTIRE );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001511 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001512 retvalue = lppop->Height;
Juergen Schmied78513941999-04-18 14:40:32 +00001513
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001514END:
Juergen Schmied78513941999-04-18 14:40:32 +00001515 if (hfontOld)
1516 SelectObject (hDC, hfontOld);
1517
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001518 WIN_ReleaseWndPtr(wndPtr);
1519 return retvalue;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001520}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001521
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00001522
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001523/***********************************************************************
1524 * MENU_ShowPopup
1525 *
1526 * Display a popup menu.
1527 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001528static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id,
1529 INT x, INT y, INT xanchor, INT yanchor )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001530{
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001531 POPUPMENU *menu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001532 WND *wndOwner = NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001533
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001534 TRACE("owner=0x%04x hmenu=0x%04x id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n",
Juergen Schmied78513941999-04-18 14:40:32 +00001535 hwndOwner, hmenu, id, x, y, xanchor, yanchor);
1536
Gerard Patel3e629742000-01-17 22:22:16 +00001537 if (!(menu = MENU_GetMenu( hmenu ))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001538 if (menu->FocusedItem != NO_SELECTED_ITEM)
1539 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001540 menu->items[menu->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001541 menu->FocusedItem = NO_SELECTED_ITEM;
1542 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001543
Andreas Mohra6d83eb2000-12-27 04:02:46 +00001544 /* store the owner for DrawItem */
Juergen Schmied78513941999-04-18 14:40:32 +00001545 menu->hwndOwner = hwndOwner;
1546
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001547 if( (wndOwner = WIN_FindWndPtr( hwndOwner )) )
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001548 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001549 UINT width, height;
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001550
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001551 MENU_PopupMenuCalcSize( menu, hwndOwner );
1552
1553 /* adjust popup menu pos so that it fits within the desktop */
1554
Marcus Meissnerddca3151999-05-22 11:33:23 +00001555 width = menu->Width + GetSystemMetrics(SM_CXBORDER);
1556 height = menu->Height + GetSystemMetrics(SM_CYBORDER);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001557
Marcus Meissnerddca3151999-05-22 11:33:23 +00001558 if( x + width > GetSystemMetrics(SM_CXSCREEN ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001559 {
1560 if( xanchor )
1561 x -= width - xanchor;
Marcus Meissnerddca3151999-05-22 11:33:23 +00001562 if( x + width > GetSystemMetrics(SM_CXSCREEN))
1563 x = GetSystemMetrics(SM_CXSCREEN) - width;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001564 }
1565 if( x < 0 ) x = 0;
1566
Marcus Meissnerddca3151999-05-22 11:33:23 +00001567 if( y + height > GetSystemMetrics(SM_CYSCREEN ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001568 {
1569 if( yanchor )
1570 y -= height + yanchor;
Marcus Meissnerddca3151999-05-22 11:33:23 +00001571 if( y + height > GetSystemMetrics(SM_CYSCREEN ))
1572 y = GetSystemMetrics(SM_CYSCREEN) - height;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001573 }
1574 if( y < 0 ) y = 0;
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001575
Alex Korobka44a1b591999-04-01 12:03:52 +00001576 if( TWEAK_WineLook == WIN31_LOOK )
1577 {
Marcus Meissnerddca3151999-05-22 11:33:23 +00001578 width += POPUP_XSHADE * GetSystemMetrics(SM_CXBORDER); /* add space for shading */
1579 height += POPUP_YSHADE * GetSystemMetrics(SM_CYBORDER);
Alex Korobka44a1b591999-04-01 12:03:52 +00001580 }
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001581
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001582 /* NOTE: In Windows, top menu popup is not owned. */
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00001583 menu->hWnd = CreateWindowA( POPUPMENU_CLASS_ATOM, NULL,
1584 WS_POPUP, x, y, width, height,
1585 hwndOwner, 0, wndOwner->hInstance,
1586 (LPVOID)hmenu );
1587 if( !menu->hWnd )
1588 {
1589 WIN_ReleaseWndPtr(wndOwner);
1590 return FALSE;
1591 }
1592 if (!top_popup) top_popup = menu->hWnd;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001593
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001594 /* Display the window */
1595
Alexandre Julliarda3960291999-02-26 11:11:13 +00001596 SetWindowPos( menu->hWnd, HWND_TOP, 0, 0, 0, 0,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001597 SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001598 UpdateWindow( menu->hWnd );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001599 WIN_ReleaseWndPtr(wndOwner);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001600 return TRUE;
1601 }
1602 return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001603}
1604
1605
1606/***********************************************************************
1607 * MENU_SelectItem
1608 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001609static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, UINT wIndex,
Rein Klazes80c924f1999-12-12 19:40:46 +00001610 BOOL sendMenuSelect, HMENU topmenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001611{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001612 LPPOPUPMENU lppop;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001613 HDC hdc;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001614
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001615 TRACE("owner=0x%04x menu=0x%04x index=0x%04x select=0x%04x\n", hwndOwner, hmenu, wIndex, sendMenuSelect);
Juergen Schmied78513941999-04-18 14:40:32 +00001616
Gerard Patel3e629742000-01-17 22:22:16 +00001617 lppop = MENU_GetMenu( hmenu );
Gerard Patel8f79fdc2001-05-14 19:20:13 +00001618 if ((!lppop) || (!lppop->nItems) || (!lppop->hWnd)) return;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001619
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001620 if (lppop->FocusedItem == wIndex) return;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001621 if (lppop->wFlags & MF_POPUP) hdc = GetDC( lppop->hWnd );
1622 else hdc = GetDCEx( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW);
Alexandre Julliardf7207251994-07-23 07:57:48 +00001623
Juergen Schmied78513941999-04-18 14:40:32 +00001624 SelectObject( hdc, hMenuFont);
1625
Alexandre Julliardf7207251994-07-23 07:57:48 +00001626 /* Clear previous highlighted item */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001627 if (lppop->FocusedItem != NO_SELECTED_ITEM)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001628 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001629 lppop->items[lppop->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
Juergen Schmied78513941999-04-18 14:40:32 +00001630 MENU_DrawMenuItem(lppop->hWnd, hmenu, hwndOwner, hdc,&lppop->items[lppop->FocusedItem],
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001631 lppop->Height, !(lppop->wFlags & MF_POPUP),
1632 ODA_SELECT );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001633 }
1634
1635 /* Highlight new item (if any) */
1636 lppop->FocusedItem = wIndex;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001637 if (lppop->FocusedItem != NO_SELECTED_ITEM)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001638 {
Rein Klazes80c924f1999-12-12 19:40:46 +00001639 if(!(lppop->items[wIndex].fType & MF_SEPARATOR)) {
1640 lppop->items[wIndex].fState |= MF_HILITE;
1641 MENU_DrawMenuItem( lppop->hWnd, hmenu, hwndOwner, hdc,
1642 &lppop->items[wIndex], lppop->Height,
1643 !(lppop->wFlags & MF_POPUP), ODA_SELECT );
1644 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001645 if (sendMenuSelect)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001646 {
1647 MENUITEM *ip = &lppop->items[lppop->FocusedItem];
Juergen Schmied78513941999-04-18 14:40:32 +00001648 SendMessageA( hwndOwner, WM_MENUSELECT,
Rein Klazes80c924f1999-12-12 19:40:46 +00001649 MAKELONG(ip->fType & MF_POPUP ? wIndex: ip->wID,
1650 ip->fType | ip->fState | MF_MOUSESELECT |
1651 (lppop->wFlags & MF_SYSMENU)), hmenu);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001652 }
Alexandre Julliardf7207251994-07-23 07:57:48 +00001653 }
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001654 else if (sendMenuSelect) {
Rein Klazes80c924f1999-12-12 19:40:46 +00001655 if(topmenu){
1656 int pos;
1657 if((pos=MENU_FindSubMenu(&topmenu, hmenu))!=NO_SELECTED_ITEM){
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00001658 POPUPMENU *ptm = MENU_GetMenu( topmenu );
Rein Klazes80c924f1999-12-12 19:40:46 +00001659 MENUITEM *ip = &ptm->items[pos];
1660 SendMessageA( hwndOwner, WM_MENUSELECT, MAKELONG(pos,
1661 ip->fType | ip->fState | MF_MOUSESELECT |
1662 (ptm->wFlags & MF_SYSMENU)), topmenu);
1663 }
1664 }
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001665 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001666 ReleaseDC( lppop->hWnd, hdc );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001667}
1668
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001669
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001670/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001671 * MENU_MoveSelection
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001672 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001673 * Moves currently selected item according to the offset parameter.
1674 * If there is no selection then it should select the last item if
1675 * offset is ITEM_PREV or the first item if offset is ITEM_NEXT.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001676 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001677static void MENU_MoveSelection( HWND hwndOwner, HMENU hmenu, INT offset )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001678{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001679 INT i;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001680 POPUPMENU *menu;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001681
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001682 TRACE("hwnd=0x%04x hmenu=0x%04x off=0x%04x\n", hwndOwner, hmenu, offset);
Juergen Schmied466a6521999-05-02 11:21:08 +00001683
Gerard Patel3e629742000-01-17 22:22:16 +00001684 menu = MENU_GetMenu( hmenu );
1685 if ((!menu) || (!menu->items)) return;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001686
1687 if ( menu->FocusedItem != NO_SELECTED_ITEM )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001688 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001689 if( menu->nItems == 1 ) return; else
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001690 for (i = menu->FocusedItem + offset ; i >= 0 && i < menu->nItems
1691 ; i += offset)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001692 if (!(menu->items[i].fType & MF_SEPARATOR))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001693 {
Rein Klazes80c924f1999-12-12 19:40:46 +00001694 MENU_SelectItem( hwndOwner, hmenu, i, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001695 return;
1696 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001697 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001698
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001699 for ( i = (offset > 0) ? 0 : menu->nItems - 1;
1700 i >= 0 && i < menu->nItems ; i += offset)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001701 if (!(menu->items[i].fType & MF_SEPARATOR))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001702 {
Rein Klazes80c924f1999-12-12 19:40:46 +00001703 MENU_SelectItem( hwndOwner, hmenu, i, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001704 return;
1705 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001706}
1707
1708
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001709/**********************************************************************
1710 * MENU_SetItemData
1711 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001712 * Set an item flags, id and text ptr. Called by InsertMenu() and
1713 * ModifyMenu().
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001714 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001715static BOOL MENU_SetItemData( MENUITEM *item, UINT flags, UINT id,
Aric Stewartc946b1c2000-10-24 21:28:19 +00001716 LPCWSTR str )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001717{
Aric Stewartc946b1c2000-10-24 21:28:19 +00001718 LPWSTR prevText = IS_STRING_ITEM(item->fType) ? item->text : NULL;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001719
Alexandre Julliard03468f71998-02-15 19:40:49 +00001720 debug_print_menuitem("MENU_SetItemData from: ", item, "");
Gerard Patel2482ef32001-03-19 19:16:21 +00001721 TRACE("flags=%x str=%p\n", flags, str);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001722
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001723 if (IS_STRING_ITEM(flags))
1724 {
Dmitry Timoshkov9316fa32001-02-14 00:23:45 +00001725 if (!str)
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001726 {
1727 flags |= MF_SEPARATOR;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001728 item->text = NULL;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001729 }
1730 else
1731 {
Aric Stewartc946b1c2000-10-24 21:28:19 +00001732 LPWSTR text;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001733 /* Item beginning with a backspace is a help item */
1734 if (*str == '\b')
1735 {
1736 flags |= MF_HELP;
1737 str++;
1738 }
Alexandre Julliardda2892c2001-02-23 01:13:42 +00001739 if (!(text = HEAP_strdupW( GetProcessHeap(), 0, str ))) return FALSE;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001740 item->text = text;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001741 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001742 }
Juergen Schmied78513941999-04-18 14:40:32 +00001743 else if (IS_BITMAP_ITEM(flags))
Aric Stewartc946b1c2000-10-24 21:28:19 +00001744 item->text = (LPWSTR)(HBITMAP)LOWORD(str);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001745 else item->text = NULL;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001746
Alexandre Julliarda845b881998-06-01 10:44:35 +00001747 if (flags & MF_OWNERDRAW)
1748 item->dwItemData = (DWORD)str;
1749 else
1750 item->dwItemData = 0;
1751
Alexandre Julliard02e90081998-01-04 17:49:09 +00001752 if ((item->fType & MF_POPUP) && (flags & MF_POPUP) && (item->hSubMenu != id) )
Alexandre Julliarda3960291999-02-26 11:11:13 +00001753 DestroyMenu( item->hSubMenu ); /* ModifyMenu() spec */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001754
1755 if (flags & MF_POPUP)
1756 {
Gerard Patel3e629742000-01-17 22:22:16 +00001757 POPUPMENU *menu = MENU_GetMenu((UINT16)id);
1758 if (menu) menu->wFlags |= MF_POPUP;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001759 else
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001760 {
1761 item->wID = 0;
1762 item->hSubMenu = 0;
1763 item->fType = 0;
1764 item->fState = 0;
1765 return FALSE;
1766 }
Alexandre Julliard02e90081998-01-04 17:49:09 +00001767 }
1768
1769 item->wID = id;
1770 if (flags & MF_POPUP)
1771 item->hSubMenu = id;
1772
1773 if ((item->fType & MF_POPUP) && !(flags & MF_POPUP) )
1774 flags |= MF_POPUP; /* keep popup */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001775
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001776 item->fType = flags & TYPE_MASK;
1777 item->fState = (flags & STATE_MASK) &
1778 ~(MF_HILITE | MF_MOUSESELECT | MF_BYPOSITION);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001779
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001780
1781 /* Don't call SetRectEmpty here! */
1782
1783
Alexandre Julliardda2892c2001-02-23 01:13:42 +00001784 if (prevText) HeapFree( GetProcessHeap(), 0, prevText );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001785
Alexandre Julliard03468f71998-02-15 19:40:49 +00001786 debug_print_menuitem("MENU_SetItemData to : ", item, "");
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001787 return TRUE;
1788}
1789
1790
1791/**********************************************************************
1792 * MENU_InsertItem
1793 *
1794 * Insert a new item into a menu.
1795 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001796static MENUITEM *MENU_InsertItem( HMENU hMenu, UINT pos, UINT flags )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001797{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001798 MENUITEM *newItems;
1799 POPUPMENU *menu;
1800
Gerard Patel3e629742000-01-17 22:22:16 +00001801 if (!(menu = MENU_GetMenu(hMenu)))
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001802 return NULL;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001803
1804 /* Find where to insert new item */
1805
Gerard Patelc6369b02000-05-14 22:52:52 +00001806 if (flags & MF_BYPOSITION) {
1807 if (pos > menu->nItems)
1808 pos = menu->nItems;
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00001809 } else {
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001810 if (!MENU_FindItem( &hMenu, &pos, flags ))
Gerard Patelc6369b02000-05-14 22:52:52 +00001811 pos = menu->nItems;
1812 else {
1813 if (!(menu = MENU_GetMenu( hMenu )))
1814 return NULL;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001815 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001816 }
1817
1818 /* Create new items array */
1819
Alexandre Julliardda2892c2001-02-23 01:13:42 +00001820 newItems = HeapAlloc( GetProcessHeap(), 0, sizeof(MENUITEM) * (menu->nItems+1) );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001821 if (!newItems)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001822 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001823 WARN("allocation failed\n" );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001824 return NULL;
1825 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001826 if (menu->nItems > 0)
1827 {
Andreas Mohra6d83eb2000-12-27 04:02:46 +00001828 /* Copy the old array into the new one */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001829 if (pos > 0) memcpy( newItems, menu->items, pos * sizeof(MENUITEM) );
1830 if (pos < menu->nItems) memcpy( &newItems[pos+1], &menu->items[pos],
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001831 (menu->nItems-pos)*sizeof(MENUITEM) );
Alexandre Julliardda2892c2001-02-23 01:13:42 +00001832 HeapFree( GetProcessHeap(), 0, menu->items );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001833 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001834 menu->items = newItems;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001835 menu->nItems++;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001836 memset( &newItems[pos], 0, sizeof(*newItems) );
Gerard Patel6df06941999-09-28 13:05:54 +00001837 menu->Height = 0; /* force size recalculate */
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001838 return &newItems[pos];
1839}
1840
1841
1842/**********************************************************************
1843 * MENU_ParseResource
1844 *
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001845 * Parse a standard menu resource and add items to the menu.
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001846 * Return a pointer to the end of the resource.
1847 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001848static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001849{
1850 WORD flags, id = 0;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001851 LPCSTR str;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001852
1853 do
1854 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001855 flags = GET_WORD(res);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001856 res += sizeof(WORD);
1857 if (!(flags & MF_POPUP))
1858 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001859 id = GET_WORD(res);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001860 res += sizeof(WORD);
1861 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001862 if (!IS_STRING_ITEM(flags))
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001863 ERR("not a string item %04x\n", flags );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001864 str = res;
1865 if (!unicode) res += strlen(str) + 1;
Aric Stewartc946b1c2000-10-24 21:28:19 +00001866 else res += (strlenW((LPCWSTR)str) + 1) * sizeof(WCHAR);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001867 if (flags & MF_POPUP)
1868 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001869 HMENU hSubMenu = CreatePopupMenu();
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001870 if (!hSubMenu) return NULL;
1871 if (!(res = MENU_ParseResource( res, hSubMenu, unicode )))
1872 return NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001873 if (!unicode) AppendMenuA( hMenu, flags, (UINT)hSubMenu, str );
1874 else AppendMenuW( hMenu, flags, (UINT)hSubMenu, (LPCWSTR)str );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001875 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001876 else /* Not a popup */
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001877 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001878 if (!unicode) AppendMenuA( hMenu, flags, id, *str ? str : NULL );
1879 else AppendMenuW( hMenu, flags, id,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001880 *(LPCWSTR)str ? (LPCWSTR)str : NULL );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001881 }
1882 } while (!(flags & MF_END));
1883 return res;
1884}
1885
1886
Alexandre Julliard641ee761997-08-04 16:34:36 +00001887/**********************************************************************
1888 * MENUEX_ParseResource
1889 *
1890 * Parse an extended menu resource and add items to the menu.
1891 * Return a pointer to the end of the resource.
1892 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001893static LPCSTR MENUEX_ParseResource( LPCSTR res, HMENU hMenu)
Alexandre Julliard641ee761997-08-04 16:34:36 +00001894{
Alexandre Julliard641ee761997-08-04 16:34:36 +00001895 WORD resinfo;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001896 do {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001897 MENUITEMINFOW mii;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001898
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001899 mii.cbSize = sizeof(mii);
1900 mii.fMask = MIIM_STATE | MIIM_ID | MIIM_TYPE;
1901 mii.fType = GET_DWORD(res);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001902 res += sizeof(DWORD);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001903 mii.fState = GET_DWORD(res);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001904 res += sizeof(DWORD);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001905 mii.wID = GET_DWORD(res);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001906 res += sizeof(DWORD);
1907 resinfo = GET_WORD(res); /* FIXME: for 16-bit apps this is a byte. */
1908 res += sizeof(WORD);
1909 /* Align the text on a word boundary. */
1910 res += (~((int)res - 1)) & 1;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001911 mii.dwTypeData = (LPWSTR) res;
Aric Stewartc946b1c2000-10-24 21:28:19 +00001912 res += (1 + strlenW(mii.dwTypeData)) * sizeof(WCHAR);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001913 /* Align the following fields on a dword boundary. */
1914 res += (~((int)res - 1)) & 3;
1915
Alexandre Julliardda2892c2001-02-23 01:13:42 +00001916 TRACE("Menu item: [%08x,%08x,%04x,%04x,%s]\n",
1917 mii.fType, mii.fState, mii.wID, resinfo, debugstr_w(mii.dwTypeData));
Alexandre Julliard641ee761997-08-04 16:34:36 +00001918
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001919 if (resinfo & 1) { /* Pop-up? */
Marcus Meissnerde43ef41999-02-28 19:56:59 +00001920 /* DWORD helpid = GET_DWORD(res); FIXME: use this. */
Alexandre Julliard641ee761997-08-04 16:34:36 +00001921 res += sizeof(DWORD);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001922 mii.hSubMenu = CreatePopupMenu();
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001923 if (!mii.hSubMenu)
1924 return NULL;
1925 if (!(res = MENUEX_ParseResource(res, mii.hSubMenu))) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001926 DestroyMenu(mii.hSubMenu);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001927 return NULL;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001928 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001929 mii.fMask |= MIIM_SUBMENU;
1930 mii.fType |= MF_POPUP;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001931 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001932 InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001933 } while (!(resinfo & MF_END));
1934 return res;
1935}
1936
1937
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001938/***********************************************************************
1939 * MENU_GetSubPopup
1940 *
1941 * Return the handle of the selected sub-popup menu (if any).
1942 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001943static HMENU MENU_GetSubPopup( HMENU hmenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001944{
1945 POPUPMENU *menu;
1946 MENUITEM *item;
1947
Gerard Patel3e629742000-01-17 22:22:16 +00001948 menu = MENU_GetMenu( hmenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001949
Gerard Patel3e629742000-01-17 22:22:16 +00001950 if ((!menu) || (menu->FocusedItem == NO_SELECTED_ITEM)) return 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001951
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001952 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001953 if ((item->fType & MF_POPUP) && (item->fState & MF_MOUSESELECT))
1954 return item->hSubMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001955 return 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001956}
1957
1958
1959/***********************************************************************
1960 * MENU_HideSubPopups
1961 *
1962 * Hide the sub-popup menus of this menu.
1963 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001964static void MENU_HideSubPopups( HWND hwndOwner, HMENU hmenu,
1965 BOOL sendMenuSelect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001966{
Gerard Patel3e629742000-01-17 22:22:16 +00001967 POPUPMENU *menu = MENU_GetMenu( hmenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001968
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001969 TRACE("owner=0x%04x hmenu=0x%04x 0x%04x\n", hwndOwner, hmenu, sendMenuSelect);
Juergen Schmied466a6521999-05-02 11:21:08 +00001970
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00001971 if (menu && top_popup)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001972 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001973 HMENU hsubmenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001974 POPUPMENU *submenu;
1975 MENUITEM *item;
1976
1977 if (menu->FocusedItem != NO_SELECTED_ITEM)
1978 {
1979 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001980 if (!(item->fType & MF_POPUP) ||
1981 !(item->fState & MF_MOUSESELECT)) return;
1982 item->fState &= ~MF_MOUSESELECT;
1983 hsubmenu = item->hSubMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001984 } else return;
1985
Gerard Patel3e629742000-01-17 22:22:16 +00001986 submenu = MENU_GetMenu( hsubmenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001987 MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00001988 MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect, 0 );
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00001989 DestroyWindow( submenu->hWnd );
1990 submenu->hWnd = 0;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001991 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001992}
1993
1994
1995/***********************************************************************
1996 * MENU_ShowSubPopup
1997 *
1998 * Display the sub-menu of the selected item of this menu.
1999 * Return the handle of the submenu, or hmenu if no submenu to display.
2000 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002001static HMENU MENU_ShowSubPopup( HWND hwndOwner, HMENU hmenu,
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002002 BOOL selectFirst, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002003{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002004 RECT rect;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002005 POPUPMENU *menu;
2006 MENUITEM *item;
2007 WND *wndPtr;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002008 HDC hdc;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002009
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002010 TRACE("owner=0x%04x hmenu=0x%04x 0x%04x\n", hwndOwner, hmenu, selectFirst);
Juergen Schmied466a6521999-05-02 11:21:08 +00002011
Gerard Patel3e629742000-01-17 22:22:16 +00002012 if (!(menu = MENU_GetMenu( hmenu ))) return hmenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002013
2014 if (!(wndPtr = WIN_FindWndPtr( menu->hWnd )) ||
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002015 (menu->FocusedItem == NO_SELECTED_ITEM))
2016 {
2017 WIN_ReleaseWndPtr(wndPtr);
2018 return hmenu;
2019 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002020
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002021 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002022 if (!(item->fType & MF_POPUP) ||
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002023 (item->fState & (MF_GRAYED | MF_DISABLED)))
2024 {
2025 WIN_ReleaseWndPtr(wndPtr);
2026 return hmenu;
2027 }
Alexandre Julliard02e90081998-01-04 17:49:09 +00002028
Andreas Mohra6d83eb2000-12-27 04:02:46 +00002029 /* message must be sent before using item,
2030 because nearly everything may be changed by the application ! */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002031
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002032 /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
2033 if (!(wFlags & TPM_NONOTIFY))
2034 SendMessageA( hwndOwner, WM_INITMENUPOPUP, item->hSubMenu,
Alexandre Julliard02e90081998-01-04 17:49:09 +00002035 MAKELONG( menu->FocusedItem, IS_SYSTEM_MENU(menu) ));
2036
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002037 item = &menu->items[menu->FocusedItem];
2038 rect = item->rect;
2039
Andreas Mohra6d83eb2000-12-27 04:02:46 +00002040 /* correct item if modified as a reaction to WM_INITMENUPOPUP message */
Alexandre Julliard02e90081998-01-04 17:49:09 +00002041 if (!(item->fState & MF_HILITE))
2042 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002043 if (menu->wFlags & MF_POPUP) hdc = GetDC( menu->hWnd );
2044 else hdc = GetDCEx( menu->hWnd, 0, DCX_CACHE | DCX_WINDOW);
Juergen Schmied78513941999-04-18 14:40:32 +00002045
2046 SelectObject( hdc, hMenuFont);
2047
Alexandre Julliard02e90081998-01-04 17:49:09 +00002048 item->fState |= MF_HILITE;
Juergen Schmied78513941999-04-18 14:40:32 +00002049 MENU_DrawMenuItem( menu->hWnd, hmenu, hwndOwner, hdc, item, menu->Height, !(menu->wFlags & MF_POPUP), ODA_DRAWENTIRE );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002050 ReleaseDC( menu->hWnd, hdc );
Alexandre Julliard02e90081998-01-04 17:49:09 +00002051 }
2052 if (!item->rect.top && !item->rect.left && !item->rect.bottom && !item->rect.right)
2053 item->rect = rect;
2054
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002055 item->fState |= MF_MOUSESELECT;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002056
2057 if (IS_SYSTEM_MENU(menu))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002058 {
Patrik Stridvall4bf33541999-06-12 14:52:15 +00002059 MENU_InitSysMenuPopup(item->hSubMenu, wndPtr->dwStyle, GetClassLongA(wndPtr->hwndSelf, GCL_STYLE));
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002060
2061 NC_GetSysPopupPos( wndPtr, &rect );
2062 rect.top = rect.bottom;
Marcus Meissnerddca3151999-05-22 11:33:23 +00002063 rect.right = GetSystemMetrics(SM_CXSIZE);
2064 rect.bottom = GetSystemMetrics(SM_CYSIZE);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002065 }
2066 else
2067 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002068 if (menu->wFlags & MF_POPUP)
2069 {
Ken Thomases130f0d82000-05-10 21:38:37 +00002070 rect.left = wndPtr->rectWindow.left + item->rect.right - GetSystemMetrics(SM_CXBORDER);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002071 rect.top = wndPtr->rectWindow.top + item->rect.top;
Ken Thomases130f0d82000-05-10 21:38:37 +00002072 rect.right = item->rect.left - item->rect.right + GetSystemMetrics(SM_CXBORDER);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002073 rect.bottom = item->rect.top - item->rect.bottom;
2074 }
2075 else
2076 {
2077 rect.left = wndPtr->rectWindow.left + item->rect.left;
2078 rect.top = wndPtr->rectWindow.top + item->rect.bottom;
2079 rect.right = item->rect.right - item->rect.left;
2080 rect.bottom = item->rect.bottom - item->rect.top;
2081 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002082 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002083
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002084 MENU_ShowPopup( hwndOwner, item->hSubMenu, menu->FocusedItem,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002085 rect.left, rect.top, rect.right, rect.bottom );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002086 if (selectFirst)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002087 MENU_MoveSelection( hwndOwner, item->hSubMenu, ITEM_NEXT );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002088 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002089 return item->hSubMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002090}
2091
Ulrich Czekalla33026a22000-02-26 19:13:44 +00002092
2093
2094/**********************************************************************
2095 * MENU_IsMenuActive
2096 */
2097BOOL MENU_IsMenuActive(void)
2098{
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00002099 return (top_popup != 0);
Ulrich Czekalla33026a22000-02-26 19:13:44 +00002100}
2101
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002102/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002103 * MENU_PtMenu
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002104 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002105 * Walks menu chain trying to find a menu pt maps to.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002106 */
Alexandre Julliard83f52d12000-09-26 22:20:14 +00002107static HMENU MENU_PtMenu( HMENU hMenu, POINT pt )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002108{
Gerard Patel3e629742000-01-17 22:22:16 +00002109 POPUPMENU *menu = MENU_GetMenu( hMenu );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002110 register UINT ht = menu->FocusedItem;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002111
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002112 /* try subpopup first (if any) */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002113 ht = (ht != NO_SELECTED_ITEM &&
2114 (menu->items[ht].fType & MF_POPUP) &&
2115 (menu->items[ht].fState & MF_MOUSESELECT))
Alexandre Julliarda3960291999-02-26 11:11:13 +00002116 ? (UINT) MENU_PtMenu(menu->items[ht].hSubMenu, pt) : 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002117
2118 if( !ht ) /* check the current window (avoiding WM_HITTEST) */
2119 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002120 ht = (UINT)NC_HandleNCHitTest( menu->hWnd, pt );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002121 if( menu->wFlags & MF_POPUP )
Alexandre Julliarda3960291999-02-26 11:11:13 +00002122 ht = (ht != (UINT)HTNOWHERE &&
2123 ht != (UINT)HTERROR) ? (UINT)hMenu : 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002124 else
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002125 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002126 WND* wndPtr = WIN_FindWndPtr(menu->hWnd);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002127
Alexandre Julliarda3960291999-02-26 11:11:13 +00002128 ht = ( ht == HTSYSMENU ) ? (UINT)(wndPtr->hSysMenu)
2129 : ( ht == HTMENU ) ? (UINT)(wndPtr->wIDmenu) : 0;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002130 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002131 }
2132 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002133 return (HMENU)ht;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002134}
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002135
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002136/***********************************************************************
2137 * MENU_ExecFocusedItem
2138 *
2139 * Execute a menu item (for instance when user pressed Enter).
Karl Lessard13409b31999-09-28 16:24:58 +00002140 * Return the wID of the executed item. Otherwise, -1 indicating
Andreas Mohr2e011a52000-06-01 23:28:25 +00002141 * that no menu item was executed;
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002142 * Have to receive the flags for the TrackPopupMenu options to avoid
2143 * sending unwanted message.
2144 *
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002145 */
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002146static INT MENU_ExecFocusedItem( MTRACKER* pmt, HMENU hMenu, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002147{
2148 MENUITEM *item;
Gerard Patel3e629742000-01-17 22:22:16 +00002149 POPUPMENU *menu = MENU_GetMenu( hMenu );
Juergen Schmied466a6521999-05-02 11:21:08 +00002150
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002151 TRACE("%p hmenu=0x%04x\n", pmt, hMenu);
Juergen Schmied466a6521999-05-02 11:21:08 +00002152
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002153 if (!menu || !menu->nItems ||
Karl Lessard13409b31999-09-28 16:24:58 +00002154 (menu->FocusedItem == NO_SELECTED_ITEM)) return -1;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002155
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002156 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002157
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002158 TRACE("%08x %08x %08x\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002159 hMenu, item->wID, item->hSubMenu);
2160
2161 if (!(item->fType & MF_POPUP))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002162 {
Francois Gouget93fd46a2000-10-23 00:37:49 +00002163 if (!(item->fState & (MF_GRAYED | MF_DISABLED)) && !(item->fType & MF_SEPARATOR))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002164 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002165 /* If TPM_RETURNCMD is set you return the id, but
2166 do not send a message to the owner */
2167 if(!(wFlags & TPM_RETURNCMD))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002168 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002169 if( menu->wFlags & MF_SYSMENU )
2170 PostMessageA( pmt->hOwnerWnd, WM_SYSCOMMAND, item->wID,
2171 MAKELPARAM((INT16)pmt->pt.x, (INT16)pmt->pt.y) );
2172 else
2173 PostMessageA( pmt->hOwnerWnd, WM_COMMAND, item->wID, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002174 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002175 return item->wID;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002176 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002177 }
2178 else
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002179 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hMenu, TRUE, wFlags);
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002180
Karl Lessard13409b31999-09-28 16:24:58 +00002181 return -1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002182}
2183
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002184/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002185 * MENU_SwitchTracking
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002186 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002187 * Helper function for menu navigation routines.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002188 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002189static void MENU_SwitchTracking( MTRACKER* pmt, HMENU hPtMenu, UINT id )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002190{
Gerard Patel3e629742000-01-17 22:22:16 +00002191 POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
2192 POPUPMENU *topmenu = MENU_GetMenu( pmt->hTopMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002193
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002194 TRACE("%p hmenu=0x%04x 0x%04x\n", pmt, hPtMenu, id);
Juergen Schmied466a6521999-05-02 11:21:08 +00002195
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002196 if( pmt->hTopMenu != hPtMenu &&
2197 !((ptmenu->wFlags | topmenu->wFlags) & MF_POPUP) )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002198 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002199 /* both are top level menus (system and menu-bar) */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002200 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00002201 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM, FALSE, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002202 pmt->hTopMenu = hPtMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002203 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002204 else MENU_HideSubPopups( pmt->hOwnerWnd, hPtMenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00002205 MENU_SelectItem( pmt->hOwnerWnd, hPtMenu, id, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002206}
2207
2208
2209/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002210 * MENU_ButtonDown
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002211 *
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002212 * Return TRUE if we can go on with menu tracking.
2213 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002214static BOOL MENU_ButtonDown( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002215{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002216 TRACE("%p hmenu=0x%04x\n", pmt, hPtMenu);
Juergen Schmied466a6521999-05-02 11:21:08 +00002217
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002218 if (hPtMenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002219 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002220 UINT id = 0;
Gerard Patel3e629742000-01-17 22:22:16 +00002221 POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002222 MENUITEM *item;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002223
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002224 if( IS_SYSTEM_MENU(ptmenu) )
2225 item = ptmenu->items;
2226 else
2227 item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002228
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002229 if( item )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002230 {
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002231 if( ptmenu->FocusedItem != id )
2232 MENU_SwitchTracking( pmt, hPtMenu, id );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002233
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002234 /* If the popup menu is not already "popped" */
2235 if(!(item->fState & MF_MOUSESELECT ))
Pascal Lessard07c447f1999-09-19 12:03:25 +00002236 {
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002237 pmt->hCurrentMenu = MENU_ShowSubPopup( pmt->hOwnerWnd, hPtMenu, FALSE, wFlags );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002238
Andreas Mohra6d83eb2000-12-27 04:02:46 +00002239 /* In win31, a newly popped menu always remains opened for the next buttonup */
Pascal Lessard07c447f1999-09-19 12:03:25 +00002240 if(TWEAK_WineLook == WIN31_LOOK)
2241 ptmenu->bTimeToHide = FALSE;
2242 }
2243
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002244 return TRUE;
2245 }
Pascal Lessard445c9101999-09-20 18:27:14 +00002246 /* Else the click was on the menu bar, finish the tracking */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002247 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002248 return FALSE;
2249}
2250
2251/***********************************************************************
2252 * MENU_ButtonUp
2253 *
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002254 * Return the value of MENU_ExecFocusedItem if
2255 * the selected item was not a popup. Else open the popup.
Karl Lessard13409b31999-09-28 16:24:58 +00002256 * A -1 return value indicates that we go on with menu tracking.
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002257 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002258 */
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002259static INT MENU_ButtonUp( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002260{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002261 TRACE("%p hmenu=0x%04x\n", pmt, hPtMenu);
Juergen Schmied466a6521999-05-02 11:21:08 +00002262
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002263 if (hPtMenu)
2264 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002265 UINT id = 0;
Gerard Patel3e629742000-01-17 22:22:16 +00002266 POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002267 MENUITEM *item;
2268
2269 if( IS_SYSTEM_MENU(ptmenu) )
2270 item = ptmenu->items;
2271 else
2272 item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
2273
Alexandre Julliard491502b1997-11-01 19:08:16 +00002274 if( item && (ptmenu->FocusedItem == id ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002275 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002276 if( !(item->fType & MF_POPUP) )
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002277 return MENU_ExecFocusedItem( pmt, hPtMenu, wFlags);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002278
Andreas Mohra6d83eb2000-12-27 04:02:46 +00002279 /* If we are dealing with the top-level menu */
2280 /* and this is a click on an already "popped" item: */
2281 /* Stop the menu tracking and close the opened submenus */
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002282 if((pmt->hTopMenu == hPtMenu) && (ptmenu->bTimeToHide == TRUE))
Karl Lessard13409b31999-09-28 16:24:58 +00002283 return 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002284 }
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002285 ptmenu->bTimeToHide = TRUE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002286 }
Karl Lessard13409b31999-09-28 16:24:58 +00002287 return -1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002288}
2289
2290
2291/***********************************************************************
2292 * MENU_MouseMove
2293 *
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002294 * Return TRUE if we can go on with menu tracking.
2295 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002296static BOOL MENU_MouseMove( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002297{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002298 UINT id = NO_SELECTED_ITEM;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002299 POPUPMENU *ptmenu = NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002300
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002301 if( hPtMenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002302 {
Gerard Patel3e629742000-01-17 22:22:16 +00002303 ptmenu = MENU_GetMenu( hPtMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002304 if( IS_SYSTEM_MENU(ptmenu) )
2305 id = 0;
2306 else
2307 MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
2308 }
2309
2310 if( id == NO_SELECTED_ITEM )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002311 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002312 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002313 NO_SELECTED_ITEM, TRUE, pmt->hTopMenu);
2314
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002315 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002316 else if( ptmenu->FocusedItem != id )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002317 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002318 MENU_SwitchTracking( pmt, hPtMenu, id );
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002319 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hPtMenu, FALSE, wFlags);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002320 }
2321 return TRUE;
2322}
2323
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002324
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002325/***********************************************************************
2326 * MENU_DoNextMenu
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002327 *
2328 * NOTE: WM_NEXTMENU documented in Win32 is a bit different.
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002329 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002330static LRESULT MENU_DoNextMenu( MTRACKER* pmt, UINT vk )
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002331{
Gerard Patel3e629742000-01-17 22:22:16 +00002332 POPUPMENU *menu = MENU_GetMenu( pmt->hTopMenu );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002333
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002334 if( (vk == VK_LEFT && menu->FocusedItem == 0 ) ||
2335 (vk == VK_RIGHT && menu->FocusedItem == menu->nItems - 1))
2336 {
2337 WND* wndPtr;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002338 HMENU hNewMenu;
2339 HWND hNewWnd;
2340 UINT id = 0;
Juergen Schmied78513941999-04-18 14:40:32 +00002341 LRESULT l = SendMessageA( pmt->hOwnerWnd, WM_NEXTMENU, vk,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002342 (IS_SYSTEM_MENU(menu)) ? GetSubMenu16(pmt->hTopMenu,0) : pmt->hTopMenu );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002343
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002344 TRACE("%04x [%04x] -> %04x [%04x]\n",
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002345 (UINT16)pmt->hCurrentMenu, (UINT16)pmt->hOwnerWnd, LOWORD(l), HIWORD(l) );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002346
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002347 if( l == 0 )
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002348 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002349 wndPtr = WIN_FindWndPtr(pmt->hOwnerWnd);
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002350
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002351 hNewWnd = pmt->hOwnerWnd;
2352 if( IS_SYSTEM_MENU(menu) )
2353 {
2354 /* switch to the menu bar */
2355
2356 if( wndPtr->dwStyle & WS_CHILD || !wndPtr->wIDmenu )
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002357 {
2358 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002359 return FALSE;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002360 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002361
2362 hNewMenu = wndPtr->wIDmenu;
2363 if( vk == VK_LEFT )
2364 {
Gerard Patel3e629742000-01-17 22:22:16 +00002365 menu = MENU_GetMenu( hNewMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002366 id = menu->nItems - 1;
2367 }
2368 }
2369 else if( wndPtr->dwStyle & WS_SYSMENU )
2370 {
2371 /* switch to the system menu */
2372 hNewMenu = wndPtr->hSysMenu;
2373 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002374 else
2375 {
2376 WIN_ReleaseWndPtr(wndPtr);
2377 return FALSE;
2378 }
2379 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002380 }
2381 else /* application returned a new menu to switch to */
2382 {
2383 hNewMenu = LOWORD(l); hNewWnd = HIWORD(l);
2384
Alexandre Julliarda3960291999-02-26 11:11:13 +00002385 if( IsMenu(hNewMenu) && IsWindow(hNewWnd) )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002386 {
2387 wndPtr = WIN_FindWndPtr(hNewWnd);
2388
2389 if( wndPtr->dwStyle & WS_SYSMENU &&
2390 GetSubMenu16(wndPtr->hSysMenu, 0) == hNewMenu )
2391 {
2392 /* get the real system menu */
2393 hNewMenu = wndPtr->hSysMenu;
2394 }
2395 else if( wndPtr->dwStyle & WS_CHILD || wndPtr->wIDmenu != hNewMenu )
2396 {
Andreas Mohra6d83eb2000-12-27 04:02:46 +00002397 /* FIXME: Not sure what to do here;
2398 * perhaps try to track hNewMenu as a popup? */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002399
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002400 TRACE(" -- got confused.\n");
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002401 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002402 return FALSE;
2403 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002404 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002405 }
2406 else return FALSE;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002407 }
2408
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002409 if( hNewMenu != pmt->hTopMenu )
2410 {
Rein Klazes80c924f1999-12-12 19:40:46 +00002411 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM,
2412 FALSE, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002413 if( pmt->hCurrentMenu != pmt->hTopMenu )
2414 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
2415 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002416
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002417 if( hNewWnd != pmt->hOwnerWnd )
2418 {
2419 ReleaseCapture();
2420 pmt->hOwnerWnd = hNewWnd;
2421 EVENT_Capture( pmt->hOwnerWnd, HTMENU );
2422 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002423
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002424 pmt->hTopMenu = pmt->hCurrentMenu = hNewMenu; /* all subpopups are hidden */
Rein Klazes80c924f1999-12-12 19:40:46 +00002425 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, id, TRUE, 0 );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002426
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002427 return TRUE;
2428 }
2429 return FALSE;
2430}
2431
2432/***********************************************************************
2433 * MENU_SuspendPopup
2434 *
2435 * The idea is not to show the popup if the next input message is
2436 * going to hide it anyway.
2437 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002438static BOOL MENU_SuspendPopup( MTRACKER* pmt, UINT16 uMsg )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002439{
Juergen Schmied78513941999-04-18 14:40:32 +00002440 MSG msg;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002441
2442 msg.hwnd = pmt->hOwnerWnd;
2443
Juergen Schmied78513941999-04-18 14:40:32 +00002444 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002445 pmt->trackFlags |= TF_SKIPREMOVE;
2446
2447 switch( uMsg )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002448 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002449 case WM_KEYDOWN:
Juergen Schmied78513941999-04-18 14:40:32 +00002450 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002451 if( msg.message == WM_KEYUP || msg.message == WM_PAINT )
2452 {
Juergen Schmied78513941999-04-18 14:40:32 +00002453 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE);
2454 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002455 if( msg.message == WM_KEYDOWN &&
2456 (msg.wParam == VK_LEFT || msg.wParam == VK_RIGHT))
2457 {
2458 pmt->trackFlags |= TF_SUSPENDPOPUP;
2459 return TRUE;
2460 }
2461 }
2462 break;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002463 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002464
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002465 /* failures go through this */
2466 pmt->trackFlags &= ~TF_SUSPENDPOPUP;
2467 return FALSE;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002468}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002469
2470/***********************************************************************
Ulrich Czekalla18ce3882001-05-18 23:20:20 +00002471 * MENU_KeyEscape
2472 *
2473 * Handle a VK_ESCAPE key event in a menu.
2474 */
2475static BOOL MENU_KeyEscape(MTRACKER* pmt, UINT wFlags)
2476{
2477 BOOL bEndMenu = TRUE;
2478
2479 if (pmt->hCurrentMenu != pmt->hTopMenu)
2480 {
2481 POPUPMENU *menu = MENU_GetMenu(pmt->hCurrentMenu);
2482
2483 if (menu->wFlags & MF_POPUP)
2484 {
2485 HMENU hmenutmp, hmenuprev;
2486
2487 hmenuprev = hmenutmp = pmt->hTopMenu;
2488
2489 /* close topmost popup */
2490 while (hmenutmp != pmt->hCurrentMenu)
2491 {
2492 hmenuprev = hmenutmp;
2493 hmenutmp = MENU_GetSubPopup( hmenuprev );
2494 }
2495
2496 MENU_HideSubPopups( pmt->hOwnerWnd, hmenuprev, TRUE );
2497 pmt->hCurrentMenu = hmenuprev;
2498 bEndMenu = FALSE;
2499 }
2500 }
2501
2502 return bEndMenu;
2503}
2504
2505/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002506 * MENU_KeyLeft
2507 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002508 * Handle a VK_LEFT key event in a menu.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002509 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002510static void MENU_KeyLeft( MTRACKER* pmt, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002511{
2512 POPUPMENU *menu;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002513 HMENU hmenutmp, hmenuprev;
2514 UINT prevcol;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002515
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002516 hmenuprev = hmenutmp = pmt->hTopMenu;
Gerard Patel3e629742000-01-17 22:22:16 +00002517 menu = MENU_GetMenu( hmenutmp );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002518
Alexandre Julliard641ee761997-08-04 16:34:36 +00002519 /* Try to move 1 column left (if possible) */
2520 if( (prevcol = MENU_GetStartOfPrevColumn( pmt->hCurrentMenu )) !=
2521 NO_SELECTED_ITEM ) {
2522
2523 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002524 prevcol, TRUE, 0 );
Alexandre Julliard641ee761997-08-04 16:34:36 +00002525 return;
2526 }
2527
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002528 /* close topmost popup */
2529 while (hmenutmp != pmt->hCurrentMenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002530 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002531 hmenuprev = hmenutmp;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002532 hmenutmp = MENU_GetSubPopup( hmenuprev );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002533 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002534
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002535 MENU_HideSubPopups( pmt->hOwnerWnd, hmenuprev, TRUE );
2536 pmt->hCurrentMenu = hmenuprev;
2537
2538 if ( (hmenuprev == pmt->hTopMenu) && !(menu->wFlags & MF_POPUP) )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002539 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002540 /* move menu bar selection if no more popups are left */
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002541
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002542 if( !MENU_DoNextMenu( pmt, VK_LEFT) )
2543 MENU_MoveSelection( pmt->hOwnerWnd, pmt->hTopMenu, ITEM_PREV );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002544
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002545 if ( hmenuprev != hmenutmp || pmt->trackFlags & TF_SUSPENDPOPUP )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002546 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002547 /* A sublevel menu was displayed - display the next one
2548 * unless there is another displacement coming up */
2549
2550 if( !MENU_SuspendPopup( pmt, WM_KEYDOWN ) )
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002551 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd,
2552 pmt->hTopMenu, TRUE, wFlags);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002553 }
2554 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002555}
2556
2557
2558/***********************************************************************
2559 * MENU_KeyRight
2560 *
2561 * Handle a VK_RIGHT key event in a menu.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002562 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002563static void MENU_KeyRight( MTRACKER* pmt, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002564{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002565 HMENU hmenutmp;
Gerard Patel3e629742000-01-17 22:22:16 +00002566 POPUPMENU *menu = MENU_GetMenu( pmt->hTopMenu );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002567 UINT nextcol;
Alexandre Julliard641ee761997-08-04 16:34:36 +00002568
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002569 TRACE("MENU_KeyRight called, cur %x (%s), top %x (%s).\n",
Alexandre Julliard641ee761997-08-04 16:34:36 +00002570 pmt->hCurrentMenu,
Aric Stewartc946b1c2000-10-24 21:28:19 +00002571 debugstr_w((MENU_GetMenu(pmt->hCurrentMenu))->
2572 items[0].text),
2573 pmt->hTopMenu, debugstr_w(menu->items[0].text) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002574
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002575 if ( (menu->wFlags & MF_POPUP) || (pmt->hCurrentMenu != pmt->hTopMenu))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002576 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002577 /* If already displaying a popup, try to display sub-popup */
2578
2579 hmenutmp = pmt->hCurrentMenu;
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002580 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hmenutmp, TRUE, wFlags);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002581
2582 /* if subpopup was displayed then we are done */
2583 if (hmenutmp != pmt->hCurrentMenu) return;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002584 }
2585
Alexandre Julliard641ee761997-08-04 16:34:36 +00002586 /* Check to see if there's another column */
2587 if( (nextcol = MENU_GetStartOfNextColumn( pmt->hCurrentMenu )) !=
2588 NO_SELECTED_ITEM ) {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002589 TRACE("Going to %d.\n", nextcol );
Alexandre Julliard641ee761997-08-04 16:34:36 +00002590 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002591 nextcol, TRUE, 0 );
Alexandre Julliard641ee761997-08-04 16:34:36 +00002592 return;
2593 }
2594
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002595 if (!(menu->wFlags & MF_POPUP)) /* menu bar tracking */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002596 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002597 if( pmt->hCurrentMenu != pmt->hTopMenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002598 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002599 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
2600 hmenutmp = pmt->hCurrentMenu = pmt->hTopMenu;
2601 } else hmenutmp = 0;
2602
2603 /* try to move to the next item */
2604 if( !MENU_DoNextMenu( pmt, VK_RIGHT) )
2605 MENU_MoveSelection( pmt->hOwnerWnd, pmt->hTopMenu, ITEM_NEXT );
2606
2607 if( hmenutmp || pmt->trackFlags & TF_SUSPENDPOPUP )
2608 if( !MENU_SuspendPopup(pmt, WM_KEYDOWN) )
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002609 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd,
2610 pmt->hTopMenu, TRUE, wFlags);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002611 }
2612}
2613
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002614/***********************************************************************
2615 * MENU_TrackMenu
2616 *
2617 * Menu tracking code.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002618 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002619static INT MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y,
2620 HWND hwnd, const RECT *lprect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002621{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002622 MSG msg;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002623 POPUPMENU *menu;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002624 BOOL fRemove;
Karl Lessard13409b31999-09-28 16:24:58 +00002625 INT executedMenuId = -1;
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +00002626 MTRACKER mt;
Francis Beaudet7ed1af31999-08-15 16:58:03 +00002627 BOOL enterIdleSent = FALSE;
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +00002628
2629 mt.trackFlags = 0;
2630 mt.hCurrentMenu = hmenu;
2631 mt.hTopMenu = hmenu;
2632 mt.hOwnerWnd = hwnd;
2633 mt.pt.x = x;
2634 mt.pt.y = y;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002635
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002636 TRACE("hmenu=0x%04x flags=0x%08x (%d,%d) hwnd=0x%04x (%d,%d)-(%d,%d)\n",
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00002637 hmenu, wFlags, x, y, hwnd, (lprect) ? lprect->left : 0, (lprect) ? lprect->top : 0,
2638 (lprect) ? lprect->right : 0, (lprect) ? lprect->bottom : 0);
Juergen Schmied78513941999-04-18 14:40:32 +00002639
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002640 fEndMenu = FALSE;
Gerard Patel3e629742000-01-17 22:22:16 +00002641 if (!(menu = MENU_GetMenu( hmenu ))) return FALSE;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002642
Pascal Lessardae6de762000-01-09 02:38:02 +00002643 if (wFlags & TPM_BUTTONDOWN)
2644 {
2645 /* Get the result in order to start the tracking or not */
2646 fRemove = MENU_ButtonDown( &mt, hmenu, wFlags );
2647 fEndMenu = !fRemove;
2648 }
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002649
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002650 EVENT_Capture( mt.hOwnerWnd, HTMENU );
2651
2652 while (!fEndMenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002653 {
Gerard Patel3e629742000-01-17 22:22:16 +00002654 menu = MENU_GetMenu( mt.hCurrentMenu );
Marcus Meissner4a699392001-02-13 01:49:06 +00002655 if (!menu) /* sometimes happens if I do a window manager close */
2656 break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002657 msg.hwnd = (wFlags & TPM_ENTERIDLEEX && menu->wFlags & MF_POPUP) ? menu->hWnd : 0;
2658
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002659 /* we have to keep the message in the queue until it's
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002660 * clear that menu loop is not over yet. */
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002661
Alexandre Julliard3f039752001-04-12 21:09:03 +00002662 if (!MSG_InternalGetMessage( &msg, msg.hwnd, mt.hOwnerWnd, 0, 0,
Francis Beaudet7ed1af31999-08-15 16:58:03 +00002663 MSGF_MENU, PM_NOREMOVE, !enterIdleSent, &enterIdleSent )) break;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002664
Rob Farnumb2007932000-05-23 23:34:17 +00002665 /* check if EndMenu() tried to cancel us, by posting this message */
2666 if(msg.message == WM_CANCELMODE)
2667 {
2668 /* we are now out of the loop */
2669 fEndMenu = TRUE;
2670
2671 /* remove the message from the queue */
2672 PeekMessageA( &msg, 0, msg.message, msg.message, PM_REMOVE );
2673
2674 /* break out of internal loop, ala ESCAPE */
2675 break;
2676 }
2677
Alexandre Julliarda3960291999-02-26 11:11:13 +00002678 TranslateMessage( &msg );
Stephane Lussierb3a99de1999-02-09 15:35:12 +00002679 mt.pt = msg.pt;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002680
Francis Beaudet7ed1af31999-08-15 16:58:03 +00002681 if ( (msg.hwnd==menu->hWnd) || (msg.message!=WM_TIMER) )
2682 enterIdleSent=FALSE;
2683
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002684 fRemove = FALSE;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002685 if ((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002686 {
Louis Philippe Gagnon9cdd22c2000-11-27 22:39:35 +00002687 /*
2688 * use the mouse coordinates in lParam instead of those in the MSG
2689 * struct to properly handle synthetic messages. lParam coords are
2690 * relative to client area, so they must be converted; since they can
2691 * be negative, we must use SLOWORD/SHIWORD instead of LOWORD/HIWORD.
2692 */
2693 mt.pt.x = SLOWORD(msg.lParam);
2694 mt.pt.y = SHIWORD(msg.lParam);
2695 ClientToScreen(msg.hwnd,&mt.pt);
2696
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002697 /* Find a menu for this mouse event */
Louis Philippe Gagnon9cdd22c2000-11-27 22:39:35 +00002698 hmenu = MENU_PtMenu( mt.hTopMenu, mt.pt );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002699
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002700 switch(msg.message)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002701 {
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002702 /* no WM_NC... messages in captured state */
2703
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002704 case WM_RBUTTONDBLCLK:
2705 case WM_RBUTTONDOWN:
2706 if (!(wFlags & TPM_RIGHTBUTTON)) break;
2707 /* fall through */
2708 case WM_LBUTTONDBLCLK:
2709 case WM_LBUTTONDOWN:
Karl Lessard4a0a7df1999-11-07 05:17:10 +00002710 /* If the message belongs to the menu, removes it from the queue */
2711 /* Else, end menu tracking */
2712 fRemove = MENU_ButtonDown( &mt, hmenu, wFlags );
2713 fEndMenu = !fRemove;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002714 break;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002715
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002716 case WM_RBUTTONUP:
2717 if (!(wFlags & TPM_RIGHTBUTTON)) break;
2718 /* fall through */
2719 case WM_LBUTTONUP:
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002720 /* Check if a menu was selected by the mouse */
2721 if (hmenu)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002722 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002723 executedMenuId = MENU_ButtonUp( &mt, hmenu, wFlags);
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002724
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002725 /* End the loop if executedMenuId is an item ID */
Karl Lessard13409b31999-09-28 16:24:58 +00002726 /* or if the job was done (executedMenuId = 0). */
2727 fEndMenu = fRemove = (executedMenuId != -1);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002728 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002729 /* No menu was selected by the mouse */
2730 /* if the function was called by TrackPopupMenu, continue
2731 with the menu tracking. If not, stop it */
2732 else
2733 fEndMenu = ((wFlags & TPM_POPUPMENU) ? FALSE : TRUE);
2734
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002735 break;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002736
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002737 case WM_MOUSEMOVE:
Alexandre Julliard8da12c41999-01-17 16:55:11 +00002738 /* In win95 winelook, the selected menu item must be changed every time the
2739 mouse moves. In Win31 winelook, the mouse button has to be held down */
2740
2741 if ( (TWEAK_WineLook > WIN31_LOOK) ||
2742 ( (msg.wParam & MK_LBUTTON) ||
2743 ((wFlags & TPM_RIGHTBUTTON) && (msg.wParam & MK_RBUTTON))) )
2744
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002745 fEndMenu |= !MENU_MouseMove( &mt, hmenu, wFlags );
Alexandre Julliard8da12c41999-01-17 16:55:11 +00002746
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002747 } /* switch(msg.message) - mouse */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002748 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002749 else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002750 {
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002751 fRemove = TRUE; /* Keyboard messages are always removed */
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002752 switch(msg.message)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002753 {
2754 case WM_KEYDOWN:
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002755 switch(msg.wParam)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002756 {
2757 case VK_HOME:
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002758 case VK_END:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002759 MENU_SelectItem( mt.hOwnerWnd, mt.hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002760 NO_SELECTED_ITEM, FALSE, 0 );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002761 /* fall through */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002762 case VK_UP:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002763 MENU_MoveSelection( mt.hOwnerWnd, mt.hCurrentMenu,
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002764 (msg.wParam == VK_HOME)? ITEM_NEXT : ITEM_PREV );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002765 break;
2766
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002767 case VK_DOWN: /* If on menu bar, pull-down the menu */
2768
Gerard Patel3e629742000-01-17 22:22:16 +00002769 menu = MENU_GetMenu( mt.hCurrentMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002770 if (!(menu->wFlags & MF_POPUP))
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002771 mt.hCurrentMenu = MENU_ShowSubPopup(mt.hOwnerWnd, mt.hTopMenu, TRUE, wFlags);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002772 else /* otherwise try to move selection */
2773 MENU_MoveSelection( mt.hOwnerWnd, mt.hCurrentMenu, ITEM_NEXT );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002774 break;
2775
2776 case VK_LEFT:
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002777 MENU_KeyLeft( &mt, wFlags );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002778 break;
2779
2780 case VK_RIGHT:
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002781 MENU_KeyRight( &mt, wFlags );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002782 break;
2783
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002784 case VK_ESCAPE:
Ulrich Czekalla18ce3882001-05-18 23:20:20 +00002785 fEndMenu = MENU_KeyEscape(&mt, wFlags);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002786 break;
2787
Ulrich Czekalla33026a22000-02-26 19:13:44 +00002788 case VK_F1:
2789 {
2790 HELPINFO hi;
2791 hi.cbSize = sizeof(HELPINFO);
2792 hi.iContextType = HELPINFO_MENUITEM;
2793 if (menu->FocusedItem == NO_SELECTED_ITEM)
2794 hi.iCtrlId = 0;
2795 else
2796 hi.iCtrlId = menu->items[menu->FocusedItem].wID;
2797 hi.hItemHandle = hmenu;
2798 hi.dwContextId = menu->dwContextHelpID;
2799 hi.MousePos = msg.pt;
2800 SendMessageA(hwnd, WM_HELP, 0, (LPARAM)&hi);
2801 break;
2802 }
2803
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002804 default:
2805 break;
2806 }
2807 break; /* WM_KEYDOWN */
2808
2809 case WM_SYSKEYDOWN:
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002810 switch(msg.wParam)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002811 {
2812 case VK_MENU:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002813 fEndMenu = TRUE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002814 break;
2815
2816 }
2817 break; /* WM_SYSKEYDOWN */
2818
2819 case WM_CHAR:
2820 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002821 UINT pos;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002822
Norman Stevensa83d0651998-10-12 07:25:35 +00002823 if (msg.wParam == '\r' || msg.wParam == ' ')
2824 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002825 executedMenuId = MENU_ExecFocusedItem(&mt,mt.hCurrentMenu, wFlags);
Karl Lessard13409b31999-09-28 16:24:58 +00002826 fEndMenu = (executedMenuId != -1);
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002827
Norman Stevensa83d0651998-10-12 07:25:35 +00002828 break;
2829 }
2830
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002831 /* Hack to avoid control chars. */
2832 /* We will find a better way real soon... */
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002833 if ((msg.wParam <= 32) || (msg.wParam >= 127)) break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002834
2835 pos = MENU_FindItemByKey( mt.hOwnerWnd, mt.hCurrentMenu,
Stephane Lussierb3a99de1999-02-09 15:35:12 +00002836 LOWORD(msg.wParam), FALSE );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002837 if (pos == (UINT)-2) fEndMenu = TRUE;
2838 else if (pos == (UINT)-1) MessageBeep(0);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002839 else
2840 {
Rein Klazes80c924f1999-12-12 19:40:46 +00002841 MENU_SelectItem( mt.hOwnerWnd, mt.hCurrentMenu, pos,
2842 TRUE, 0 );
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002843 executedMenuId = MENU_ExecFocusedItem(&mt,mt.hCurrentMenu, wFlags);
Karl Lessard13409b31999-09-28 16:24:58 +00002844 fEndMenu = (executedMenuId != -1);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002845 }
2846 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002847 break;
2848 } /* switch(msg.message) - kbd */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002849 }
2850 else
2851 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002852 DispatchMessageA( &msg );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002853 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002854
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002855 if (!fEndMenu) fRemove = TRUE;
2856
2857 /* finally remove message from the queue */
2858
2859 if (fRemove && !(mt.trackFlags & TF_SKIPREMOVE) )
Alexandre Julliarda3960291999-02-26 11:11:13 +00002860 PeekMessageA( &msg, 0, msg.message, msg.message, PM_REMOVE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002861 else mt.trackFlags &= ~TF_SKIPREMOVE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002862 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002863
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002864 ReleaseCapture();
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00002865
Guy Albertellif12b70a2000-05-11 00:06:11 +00002866 /* If dropdown is still painted and the close box is clicked on
2867 then the menu will be destroyed as part of the DispatchMessage above.
2868 This will then invalidate the menu handle in mt.hTopMenu. We should
2869 check for this first. */
2870 if( IsMenu( mt.hTopMenu ) )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002871 {
Guy Albertellif12b70a2000-05-11 00:06:11 +00002872 menu = MENU_GetMenu( mt.hTopMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002873
Guy Albertellif12b70a2000-05-11 00:06:11 +00002874 if( IsWindow( mt.hOwnerWnd ) )
2875 {
2876 MENU_HideSubPopups( mt.hOwnerWnd, mt.hTopMenu, FALSE );
2877
2878 if (menu && menu->wFlags & MF_POPUP)
2879 {
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00002880 DestroyWindow( menu->hWnd );
2881 menu->hWnd = 0;
Guy Albertellif12b70a2000-05-11 00:06:11 +00002882 }
2883 MENU_SelectItem( mt.hOwnerWnd, mt.hTopMenu, NO_SELECTED_ITEM, FALSE, 0 );
2884 SendMessageA( mt.hOwnerWnd, WM_MENUSELECT, MAKELONG(0,0xffff), 0 );
2885 }
2886
2887 /* Reset the variable for hiding menu */
2888 if( menu ) menu->bTimeToHide = FALSE;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002889 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002890
Juergen Schmied371c4201999-10-13 12:27:44 +00002891 /* The return value is only used by TrackPopupMenu */
2892 return ((executedMenuId != -1) ? executedMenuId : 0);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002893}
2894
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002895/***********************************************************************
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002896 * MENU_InitTracking
2897 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002898static BOOL MENU_InitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT wFlags)
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002899{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002900 TRACE("hwnd=0x%04x hmenu=0x%04x\n", hWnd, hMenu);
Juergen Schmied78513941999-04-18 14:40:32 +00002901
Alexandre Julliarda3960291999-02-26 11:11:13 +00002902 HideCaret(0);
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002903
2904 /* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */
2905 if (!(wFlags & TPM_NONOTIFY))
2906 SendMessageA( hWnd, WM_ENTERMENULOOP, bPopup, 0 );
2907
Juergen Schmied78513941999-04-18 14:40:32 +00002908 SendMessageA( hWnd, WM_SETCURSOR, hWnd, HTCAPTION );
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002909
2910 if (!(wFlags & TPM_NONOTIFY))
Gerard Patelcf2ff272001-03-14 17:24:59 +00002911 {
2912 POPUPMENU *menu;
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002913 SendMessageA( hWnd, WM_INITMENU, hMenu, 0 );
Gerard Patelcf2ff272001-03-14 17:24:59 +00002914 if ((menu = MENU_GetMenu( hMenu )) && (!menu->Height))
2915 { /* app changed/recreated menu bar entries in WM_INITMENU
2916 Recalculate menu sizes else clicks will not work */
2917 RECT r;
2918 HDC hdc = GetDCEx( hWnd, 0, DCX_CACHE | DCX_WINDOW );
2919 SelectObject( hdc, hMenuFont);
2920 GetClientRect(hWnd, &r); /* probably too simple */
2921 MENU_MenuBarCalcSize( hdc, &r, menu, hWnd );
2922 ReleaseDC(hWnd, hdc);
2923 }
2924 }
Juergen Schmied78513941999-04-18 14:40:32 +00002925 return TRUE;
2926}
2927/***********************************************************************
2928 * MENU_ExitTracking
2929 */
2930static BOOL MENU_ExitTracking(HWND hWnd)
2931{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002932 TRACE("hwnd=0x%04x\n", hWnd);
Juergen Schmied78513941999-04-18 14:40:32 +00002933
2934 SendMessageA( hWnd, WM_EXITMENULOOP, 0, 0 );
2935 ShowCaret(0);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002936 return TRUE;
2937}
2938
2939/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002940 * MENU_TrackMouseMenuBar
2941 *
2942 * Menu-bar tracking upon a mouse event. Called from NC_HandleSysCommand().
2943 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002944void MENU_TrackMouseMenuBar( WND* wndPtr, INT ht, POINT pt )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002945{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002946 HWND hWnd = wndPtr->hwndSelf;
2947 HMENU hMenu = (ht == HTSYSMENU) ? wndPtr->hSysMenu : wndPtr->wIDmenu;
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002948 UINT wFlags = TPM_ENTERIDLEEX | TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002949
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002950 TRACE("pwnd=%p ht=0x%04x (%ld,%ld)\n", wndPtr, ht, pt.x, pt.y);
Juergen Schmied78513941999-04-18 14:40:32 +00002951
Alexandre Julliarda3960291999-02-26 11:11:13 +00002952 if (IsMenu(hMenu))
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002953 {
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002954 MENU_InitTracking( hWnd, hMenu, FALSE, wFlags );
2955 MENU_TrackMenu( hMenu, wFlags, pt.x, pt.y, hWnd, NULL );
Juergen Schmied78513941999-04-18 14:40:32 +00002956 MENU_ExitTracking(hWnd);
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002957 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002958}
2959
2960
2961/***********************************************************************
2962 * MENU_TrackKbdMenuBar
2963 *
2964 * Menu-bar tracking upon a keyboard event. Called from NC_HandleSysCommand().
2965 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002966void MENU_TrackKbdMenuBar( WND* wndPtr, UINT wParam, INT vkey)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002967{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002968 UINT uItem = NO_SELECTED_ITEM;
2969 HMENU hTrackMenu;
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002970 UINT wFlags = TPM_ENTERIDLEEX | TPM_LEFTALIGN | TPM_LEFTBUTTON;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002971
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002972 /* find window that has a menu */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002973
Pierre Mageau891d4d21999-10-23 20:05:04 +00002974 while( wndPtr->dwStyle & WS_CHILD)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002975 if( !(wndPtr = wndPtr->parent) ) return;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002976
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002977 /* check if we have to track a system menu */
2978
2979 if( (wndPtr->dwStyle & (WS_CHILD | WS_MINIMIZE)) ||
2980 !wndPtr->wIDmenu || vkey == VK_SPACE )
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002981 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002982 if( !(wndPtr->dwStyle & WS_SYSMENU) ) return;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002983 hTrackMenu = wndPtr->hSysMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002984 uItem = 0;
2985 wParam |= HTSYSMENU; /* prevent item lookup */
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002986 }
2987 else
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002988 hTrackMenu = wndPtr->wIDmenu;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002989
Alexandre Julliarda3960291999-02-26 11:11:13 +00002990 if (IsMenu( hTrackMenu ))
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002991 {
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002992 MENU_InitTracking( wndPtr->hwndSelf, hTrackMenu, FALSE, wFlags );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002993
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002994 if( vkey && vkey != VK_SPACE )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002995 {
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002996 uItem = MENU_FindItemByKey( wndPtr->hwndSelf, hTrackMenu,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002997 vkey, (wParam & HTSYSMENU) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002998 if( uItem >= (UINT)(-2) )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002999 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003000 if( uItem == (UINT)(-1) ) MessageBeep(0);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003001 hTrackMenu = 0;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003002 }
3003 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003004
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003005 if( hTrackMenu )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003006 {
Rein Klazes80c924f1999-12-12 19:40:46 +00003007 MENU_SelectItem( wndPtr->hwndSelf, hTrackMenu, uItem, TRUE, 0 );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003008
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003009 if( uItem == NO_SELECTED_ITEM )
3010 MENU_MoveSelection( wndPtr->hwndSelf, hTrackMenu, ITEM_NEXT );
3011 else if( vkey )
Juergen Schmied78513941999-04-18 14:40:32 +00003012 PostMessageA( wndPtr->hwndSelf, WM_KEYDOWN, VK_DOWN, 0L );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003013
Abey Georgeb59d4bc1999-09-22 15:10:42 +00003014 MENU_TrackMenu( hTrackMenu, wFlags, 0, 0, wndPtr->hwndSelf, NULL );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003015 }
Juergen Schmied78513941999-04-18 14:40:32 +00003016
3017 MENU_ExitTracking (wndPtr->hwndSelf);
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003018 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003019}
3020
3021
3022/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003023 * TrackPopupMenu (USER.416)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003024 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003025BOOL16 WINAPI TrackPopupMenu16( HMENU16 hMenu, UINT16 wFlags, INT16 x, INT16 y,
3026 INT16 nReserved, HWND16 hWnd, const RECT16 *lpRect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003027{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003028 RECT r;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003029 if (lpRect)
3030 CONV_RECT16TO32( lpRect, &r );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003031 return TrackPopupMenu( hMenu, wFlags, x, y, nReserved, hWnd,
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003032 lpRect ? &r : NULL );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003033}
3034
3035
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003036/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003037 * TrackPopupMenu (USER32.@)
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003038 *
3039 * Like the win32 API, the function return the command ID only if the
3040 * flag TPM_RETURNCMD is on.
3041 *
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003042 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003043BOOL WINAPI TrackPopupMenu( HMENU hMenu, UINT wFlags, INT x, INT y,
3044 INT nReserved, HWND hWnd, const RECT *lpRect )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003045{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003046 BOOL ret = FALSE;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003047
Abey Georgeb59d4bc1999-09-22 15:10:42 +00003048 MENU_InitTracking(hWnd, hMenu, TRUE, wFlags);
3049
3050 /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
3051 if (!(wFlags & TPM_NONOTIFY))
3052 SendMessageA( hWnd, WM_INITMENUPOPUP, hMenu, 0);
3053
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003054 if (MENU_ShowPopup( hWnd, hMenu, 0, x, y, 0, 0 ))
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00003055 ret = MENU_TrackMenu( hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd, lpRect );
Juergen Schmied78513941999-04-18 14:40:32 +00003056 MENU_ExitTracking(hWnd);
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003057
3058 if( (!(wFlags & TPM_RETURNCMD)) && (ret != FALSE) )
3059 ret = 1;
3060
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003061 return ret;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003062}
3063
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003064/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003065 * TrackPopupMenuEx (USER32.@)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003066 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003067BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y,
3068 HWND hWnd, LPTPMPARAMS lpTpm )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003069{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003070 FIXME("not fully implemented\n" );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003071 return TrackPopupMenu( hMenu, wFlags, x, y, 0, hWnd,
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003072 lpTpm ? &lpTpm->rcExclude : NULL );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003073}
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003074
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003075/***********************************************************************
3076 * PopupMenuWndProc
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003077 *
3078 * NOTE: Windows has totally different (and undocumented) popup wndproc.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003079 */
Alexandre Julliard91222da2000-12-10 23:01:33 +00003080static LRESULT WINAPI PopupMenuWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
3081{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003082 TRACE("hwnd=0x%04x msg=0x%04x wp=0x%04x lp=0x%08lx\n",
Juergen Schmied78513941999-04-18 14:40:32 +00003083 hwnd, message, wParam, lParam);
3084
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003085 switch(message)
3086 {
3087 case WM_CREATE:
3088 {
Alexandre Julliard91222da2000-12-10 23:01:33 +00003089 CREATESTRUCTW *cs = (CREATESTRUCTW*)lParam;
3090 SetWindowLongW( hwnd, 0, (LONG)cs->lpCreateParams );
3091 return 0;
Alexandre Julliardf7207251994-07-23 07:57:48 +00003092 }
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003093
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003094 case WM_MOUSEACTIVATE: /* We don't want to be activated */
Alexandre Julliard91222da2000-12-10 23:01:33 +00003095 return MA_NOACTIVATE;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003096
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003097 case WM_PAINT:
3098 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003099 PAINTSTRUCT ps;
3100 BeginPaint( hwnd, &ps );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003101 MENU_DrawPopupMenu( hwnd, ps.hdc,
Alexandre Julliarda3960291999-02-26 11:11:13 +00003102 (HMENU)GetWindowLongA( hwnd, 0 ) );
3103 EndPaint( hwnd, &ps );
Alexandre Julliard91222da2000-12-10 23:01:33 +00003104 return 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003105 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003106 case WM_ERASEBKGND:
Alexandre Julliard91222da2000-12-10 23:01:33 +00003107 return 1;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003108
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00003109 case WM_DESTROY:
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003110 /* zero out global pointer in case resident popup window was destroyed. */
3111 if (hwnd == top_popup) top_popup = 0;
3112 break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003113
3114 case WM_SHOWWINDOW:
3115
3116 if( wParam )
3117 {
Alexandre Julliard91222da2000-12-10 23:01:33 +00003118 if (!GetWindowLongW( hwnd, 0 )) ERR("no menu to display\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003119 }
3120 else
Alexandre Julliard91222da2000-12-10 23:01:33 +00003121 SetWindowLongW( hwnd, 0, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003122 break;
3123
3124 case MM_SETMENUHANDLE:
Alexandre Julliard91222da2000-12-10 23:01:33 +00003125 SetWindowLongW( hwnd, 0, wParam );
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00003126 break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003127
3128 case MM_GETMENUHANDLE:
Alexandre Julliard91222da2000-12-10 23:01:33 +00003129 return GetWindowLongW( hwnd, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003130
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003131 default:
Alexandre Julliard91222da2000-12-10 23:01:33 +00003132 return DefWindowProcW( hwnd, message, wParam, lParam );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003133 }
Alexandre Julliard91222da2000-12-10 23:01:33 +00003134 return 0;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003135}
3136
3137
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00003138/***********************************************************************
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003139 * MENU_GetMenuBarHeight
3140 *
3141 * Compute the size of the menu bar height. Used by NC_HandleNCCalcSize().
3142 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003143UINT MENU_GetMenuBarHeight( HWND hwnd, UINT menubarWidth,
3144 INT orgX, INT orgY )
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003145{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003146 HDC hdc;
3147 RECT rectBar;
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003148 WND *wndPtr;
3149 LPPOPUPMENU lppop;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003150 UINT retvalue;
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003151
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003152 TRACE("HWND 0x%x, width %d, at (%d, %d).\n",
Juergen Schmied78513941999-04-18 14:40:32 +00003153 hwnd, menubarWidth, orgX, orgY );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00003154
Juergen Schmied78513941999-04-18 14:40:32 +00003155 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
3156 return 0;
3157
Gerard Patel3e629742000-01-17 22:22:16 +00003158 if (!(lppop = MENU_GetMenu((HMENU16)wndPtr->wIDmenu)))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003159 {
Juergen Schmied78513941999-04-18 14:40:32 +00003160 WIN_ReleaseWndPtr(wndPtr);
3161 return 0;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003162 }
Juergen Schmied78513941999-04-18 14:40:32 +00003163
Alexandre Julliarda3960291999-02-26 11:11:13 +00003164 hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_WINDOW );
Juergen Schmied78513941999-04-18 14:40:32 +00003165 SelectObject( hdc, hMenuFont);
Marcus Meissnerddca3151999-05-22 11:33:23 +00003166 SetRect(&rectBar, orgX, orgY, orgX+menubarWidth, orgY+GetSystemMetrics(SM_CYMENU));
Juergen Schmied78513941999-04-18 14:40:32 +00003167 MENU_MenuBarCalcSize( hdc, &rectBar, lppop, hwnd );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003168 ReleaseDC( hwnd, hdc );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003169 retvalue = lppop->Height;
3170 WIN_ReleaseWndPtr(wndPtr);
3171 return retvalue;
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003172}
3173
3174
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003175/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003176 * ChangeMenu (USER.153)
Alexandre Julliard401710d1993-09-04 10:09:32 +00003177 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003178BOOL16 WINAPI ChangeMenu16( HMENU16 hMenu, UINT16 pos, SEGPTR data,
3179 UINT16 id, UINT16 flags )
Alexandre Julliard401710d1993-09-04 10:09:32 +00003180{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003181 TRACE("menu=%04x pos=%d data=%08lx id=%04x flags=%04x\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +00003182 hMenu, pos, (DWORD)data, id, flags );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003183 if (flags & MF_APPEND) return AppendMenu16( hMenu, flags & ~MF_APPEND,
3184 id, data );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003185
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003186 /* FIXME: Word passes the item id in 'pos' and 0 or 0xffff as id */
3187 /* for MF_DELETE. We should check the parameters for all others */
3188 /* MF_* actions also (anybody got a doc on ChangeMenu?). */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003189
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003190 if (flags & MF_DELETE) return DeleteMenu16(hMenu, pos, flags & ~MF_DELETE);
3191 if (flags & MF_CHANGE) return ModifyMenu16(hMenu, pos, flags & ~MF_CHANGE,
3192 id, data );
3193 if (flags & MF_REMOVE) return RemoveMenu16(hMenu,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003194 flags & MF_BYPOSITION ? pos : id,
3195 flags & ~MF_REMOVE );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003196 /* Default: MF_INSERT */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003197 return InsertMenu16( hMenu, pos, flags, id, data );
3198}
3199
3200
3201/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003202 * ChangeMenuA (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003203 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003204BOOL WINAPI ChangeMenuA( HMENU hMenu, UINT pos, LPCSTR data,
3205 UINT id, UINT flags )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003206{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003207 TRACE("menu=%08x pos=%d data=%08lx id=%08x flags=%08x\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003208 hMenu, pos, (DWORD)data, id, flags );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003209 if (flags & MF_APPEND) return AppendMenuA( hMenu, flags & ~MF_APPEND,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003210 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003211 if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
3212 if (flags & MF_CHANGE) return ModifyMenuA(hMenu, pos, flags & ~MF_CHANGE,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003213 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003214 if (flags & MF_REMOVE) return RemoveMenu( hMenu,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003215 flags & MF_BYPOSITION ? pos : id,
3216 flags & ~MF_REMOVE );
3217 /* Default: MF_INSERT */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003218 return InsertMenuA( hMenu, pos, flags, id, data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003219}
3220
3221
3222/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003223 * ChangeMenuW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003224 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003225BOOL WINAPI ChangeMenuW( HMENU hMenu, UINT pos, LPCWSTR data,
3226 UINT id, UINT flags )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003227{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003228 TRACE("menu=%08x pos=%d data=%08lx id=%08x flags=%08x\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003229 hMenu, pos, (DWORD)data, id, flags );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003230 if (flags & MF_APPEND) return AppendMenuW( hMenu, flags & ~MF_APPEND,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003231 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003232 if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
3233 if (flags & MF_CHANGE) return ModifyMenuW(hMenu, pos, flags & ~MF_CHANGE,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003234 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003235 if (flags & MF_REMOVE) return RemoveMenu( hMenu,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003236 flags & MF_BYPOSITION ? pos : id,
3237 flags & ~MF_REMOVE );
3238 /* Default: MF_INSERT */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003239 return InsertMenuW( hMenu, pos, flags, id, data );
Alexandre Julliard401710d1993-09-04 10:09:32 +00003240}
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003241
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003242
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003243/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003244 * CheckMenuItem (USER.154)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003245 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003246BOOL16 WINAPI CheckMenuItem16( HMENU16 hMenu, UINT16 id, UINT16 flags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003247{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003248 return (BOOL16)CheckMenuItem( hMenu, id, flags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003249}
3250
3251
3252/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003253 * CheckMenuItem (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003254 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003255DWORD WINAPI CheckMenuItem( HMENU hMenu, UINT id, UINT flags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003256{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003257 MENUITEM *item;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003258 DWORD ret;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003259
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003260 TRACE("menu=%04x id=%04x flags=%04x\n", hMenu, id, flags );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003261 if (!(item = MENU_FindItem( &hMenu, &id, flags ))) return -1;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003262 ret = item->fState & MF_CHECKED;
3263 if (flags & MF_CHECKED) item->fState |= MF_CHECKED;
3264 else item->fState &= ~MF_CHECKED;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003265 return ret;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003266}
3267
3268
3269/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003270 * EnableMenuItem (USER.155)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003271 */
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003272UINT16 WINAPI EnableMenuItem16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003273{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003274 return EnableMenuItem( hMenu, wItemID, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003275}
3276
3277
3278/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003279 * EnableMenuItem (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003280 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003281UINT WINAPI EnableMenuItem( HMENU hMenu, UINT wItemID, UINT wFlags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003282{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003283 UINT oldflags;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003284 MENUITEM *item;
Pascal Lessardd814bb61999-07-31 13:02:02 +00003285 POPUPMENU *menu;
Alexandre Julliardf7207251994-07-23 07:57:48 +00003286
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003287 TRACE("(%04x, %04X, %04X) !\n",
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003288 hMenu, wItemID, wFlags);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003289
Pascal Lessardd814bb61999-07-31 13:02:02 +00003290 /* Get the Popupmenu to access the owner menu */
Gerard Patel3e629742000-01-17 22:22:16 +00003291 if (!(menu = MENU_GetMenu(hMenu)))
Pascal Lessardd814bb61999-07-31 13:02:02 +00003292 return (UINT)-1;
3293
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003294 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags )))
Alexandre Julliarda3960291999-02-26 11:11:13 +00003295 return (UINT)-1;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003296
3297 oldflags = item->fState & (MF_GRAYED | MF_DISABLED);
3298 item->fState ^= (oldflags ^ wFlags) & (MF_GRAYED | MF_DISABLED);
Pascal Lessardd814bb61999-07-31 13:02:02 +00003299
3300 /* In win95 if the close item in the system menu change update the close button */
3301 if (TWEAK_WineLook == WIN95_LOOK)
3302 if((item->wID == SC_CLOSE) && (oldflags != wFlags))
3303 {
3304 if (menu->hSysMenuOwner != 0)
3305 {
3306 POPUPMENU* parentMenu;
3307
3308 /* Get the parent menu to access*/
Gerard Patel3e629742000-01-17 22:22:16 +00003309 if (!(parentMenu = MENU_GetMenu(menu->hSysMenuOwner)))
Pascal Lessardd814bb61999-07-31 13:02:02 +00003310 return (UINT)-1;
3311
3312 /* Refresh the frame to reflect the change*/
3313 SetWindowPos(parentMenu->hWnd, 0, 0, 0, 0, 0,
Stephane Lussiera833f631999-08-21 14:46:06 +00003314 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
Pascal Lessardd814bb61999-07-31 13:02:02 +00003315 }
3316 }
3317
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003318 return oldflags;
Alexandre Julliard1f579291994-05-25 16:25:21 +00003319}
3320
3321
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00003322/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003323 * GetMenuString (USER.161)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003324 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003325INT16 WINAPI GetMenuString16( HMENU16 hMenu, UINT16 wItemID,
3326 LPSTR str, INT16 nMaxSiz, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003327{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003328 return GetMenuStringA( hMenu, wItemID, str, nMaxSiz, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003329}
3330
3331
3332/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003333 * GetMenuStringA (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003334 */
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00003335INT WINAPI GetMenuStringA(
3336 HMENU hMenu, /* [in] menuhandle */
3337 UINT wItemID, /* [in] menu item (dep. on wFlags) */
3338 LPSTR str, /* [out] outbuffer. If NULL, func returns entry length*/
3339 INT nMaxSiz, /* [in] length of buffer. if 0, func returns entry len*/
3340 UINT wFlags /* [in] MF_ flags */
3341) {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003342 MENUITEM *item;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00003343
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003344 TRACE("menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00003345 hMenu, wItemID, str, nMaxSiz, wFlags );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003346 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003347 if (!IS_STRING_ITEM(item->fType)) return 0;
Aric Stewartc946b1c2000-10-24 21:28:19 +00003348 if (!str || !nMaxSiz) return strlenW(item->text);
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00003349 str[0] = '\0';
Alexandre Julliard24a62ab2000-11-28 22:40:56 +00003350 if (!WideCharToMultiByte( CP_ACP, 0, item->text, -1, str, nMaxSiz, NULL, NULL ))
3351 str[nMaxSiz-1] = 0;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003352 TRACE("returning '%s'\n", str );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003353 return strlen(str);
Alexandre Julliard1f579291994-05-25 16:25:21 +00003354}
3355
3356
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003357/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003358 * GetMenuStringW (USER32.@)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003359 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003360INT WINAPI GetMenuStringW( HMENU hMenu, UINT wItemID,
3361 LPWSTR str, INT nMaxSiz, UINT wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003362{
3363 MENUITEM *item;
3364
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003365 TRACE("menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003366 hMenu, wItemID, str, nMaxSiz, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003367 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003368 if (!IS_STRING_ITEM(item->fType)) return 0;
Aric Stewartc946b1c2000-10-24 21:28:19 +00003369 if (!str || !nMaxSiz) return strlenW(item->text);
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00003370 str[0] = '\0';
Aric Stewartc946b1c2000-10-24 21:28:19 +00003371 lstrcpynW( str, item->text, nMaxSiz );
3372 return strlenW(str);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003373}
3374
3375
3376/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003377 * HiliteMenuItem (USER.162)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003378 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003379BOOL16 WINAPI HiliteMenuItem16( HWND16 hWnd, HMENU16 hMenu, UINT16 wItemID,
3380 UINT16 wHilite )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003381{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003382 return HiliteMenuItem( hWnd, hMenu, wItemID, wHilite );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003383}
3384
3385
3386/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003387 * HiliteMenuItem (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003388 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003389BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
3390 UINT wHilite )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003391{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003392 LPPOPUPMENU menu;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003393 TRACE("(%04x, %04x, %04x, %04x);\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +00003394 hWnd, hMenu, wItemID, wHilite);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003395 if (!MENU_FindItem( &hMenu, &wItemID, wHilite )) return FALSE;
Gerard Patel3e629742000-01-17 22:22:16 +00003396 if (!(menu = MENU_GetMenu(hMenu))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003397 if (menu->FocusedItem == wItemID) return TRUE;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003398 MENU_HideSubPopups( hWnd, hMenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00003399 MENU_SelectItem( hWnd, hMenu, wItemID, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003400 return TRUE;
Alexandre Julliard1f579291994-05-25 16:25:21 +00003401}
3402
3403
3404/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003405 * GetMenuState (USER.250)
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00003406 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003407UINT16 WINAPI GetMenuState16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003408{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003409 return GetMenuState( hMenu, wItemID, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003410}
3411
3412
3413/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003414 * GetMenuState (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003415 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003416UINT WINAPI GetMenuState( HMENU hMenu, UINT wItemID, UINT wFlags )
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00003417{
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003418 MENUITEM *item;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003419 TRACE("(menu=%04x, id=%04x, flags=%04x);\n",
Alexandre Julliardaca05781994-10-17 18:12:41 +00003420 hMenu, wItemID, wFlags);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003421 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return -1;
Alexandre Julliard03468f71998-02-15 19:40:49 +00003422 debug_print_menuitem (" item: ", item, "");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003423 if (item->fType & MF_POPUP)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003424 {
Gerard Patel3e629742000-01-17 22:22:16 +00003425 POPUPMENU *menu = MENU_GetMenu( item->hSubMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003426 if (!menu) return -1;
Alexandre Julliard829fe321998-07-26 14:27:39 +00003427 else return (menu->nItems << 8) | ((item->fState|item->fType) & 0xff);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003428 }
Alexandre Julliard889f7421997-04-15 17:19:52 +00003429 else
Alexandre Julliard491502b1997-11-01 19:08:16 +00003430 {
Alexandre Julliard829fe321998-07-26 14:27:39 +00003431 /* We used to (from way back then) mask the result to 0xff. */
3432 /* I don't know why and it seems wrong as the documented */
3433 /* return flag MF_SEPARATOR is outside that mask. */
3434 return (item->fType | item->fState);
Alexandre Julliard491502b1997-11-01 19:08:16 +00003435 }
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00003436}
3437
3438
3439/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003440 * GetMenuItemCount (USER.263)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003441 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003442INT16 WINAPI GetMenuItemCount16( HMENU16 hMenu )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003443{
Gerard Patel3e629742000-01-17 22:22:16 +00003444 LPPOPUPMENU menu = MENU_GetMenu(hMenu);
3445 if (!menu) return -1;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003446 TRACE("(%04x) returning %d\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003447 hMenu, menu->nItems );
3448 return menu->nItems;
Alexandre Julliard1f579291994-05-25 16:25:21 +00003449}
3450
3451
3452/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003453 * GetMenuItemCount (USER32.@)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003454 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003455INT WINAPI GetMenuItemCount( HMENU hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003456{
Gerard Patel3e629742000-01-17 22:22:16 +00003457 LPPOPUPMENU menu = MENU_GetMenu(hMenu);
3458 if (!menu) return -1;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003459 TRACE("(%04x) returning %d\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003460 hMenu, menu->nItems );
3461 return menu->nItems;
3462}
3463
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003464/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003465 * GetMenuItemID (USER.264)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003466 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003467UINT16 WINAPI GetMenuItemID16( HMENU16 hMenu, INT16 nPos )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003468{
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003469 return (UINT16) GetMenuItemID (hMenu, nPos);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003470}
3471
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003472/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003473 * GetMenuItemID (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003474 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003475UINT WINAPI GetMenuItemID( HMENU hMenu, INT nPos )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003476{
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003477 MENUITEM * lpmi;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003478
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003479 if (!(lpmi = MENU_FindItem(&hMenu,&nPos,MF_BYPOSITION))) return 0;
3480 if (lpmi->fType & MF_POPUP) return -1;
3481 return lpmi->wID;
3482
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003483}
3484
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003485/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003486 * InsertMenu (USER.410)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003487 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003488BOOL16 WINAPI InsertMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags,
3489 UINT16 id, SEGPTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003490{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003491 UINT pos32 = (UINT)pos;
3492 if ((pos == (UINT16)-1) && (flags & MF_BYPOSITION)) pos32 = (UINT)-1;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003493 if (IS_STRING_ITEM(flags) && data)
Alexandre Julliard982a2232000-12-13 20:20:09 +00003494 return InsertMenuA( hMenu, pos32, flags, id, MapSL(data) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003495 return InsertMenuA( hMenu, pos32, flags, id, (LPSTR)data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003496}
3497
3498
3499/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003500 * InsertMenuW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003501 */
Aric Stewartc946b1c2000-10-24 21:28:19 +00003502BOOL WINAPI InsertMenuW( HMENU hMenu, UINT pos, UINT flags,
3503 UINT id, LPCWSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003504{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003505 MENUITEM *item;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00003506
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003507 if (IS_STRING_ITEM(flags) && str)
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003508 TRACE("hMenu %04x, pos %d, flags %08x, "
Francois Gougete76218d2001-05-09 17:31:31 +00003509 "id %04x, str %s\n",
Aric Stewartc946b1c2000-10-24 21:28:19 +00003510 hMenu, pos, flags, id, debugstr_w(str) );
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003511 else TRACE("hMenu %04x, pos %d, flags %08x, "
Alexandre Julliardd37eb361997-07-20 16:23:21 +00003512 "id %04x, str %08lx (not a string)\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003513 hMenu, pos, flags, id, (DWORD)str );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003514
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003515 if (!(item = MENU_InsertItem( hMenu, pos, flags ))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003516
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003517 if (!(MENU_SetItemData( item, flags, id, str )))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003518 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003519 RemoveMenu( hMenu, pos, flags );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00003520 return FALSE;
3521 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003522
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003523 if (flags & MF_POPUP) /* Set the MF_POPUP flag on the popup-menu */
Gerard Patel3e629742000-01-17 22:22:16 +00003524 (MENU_GetMenu((HMENU16)id))->wFlags |= MF_POPUP;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003525
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003526 item->hCheckBit = item->hUnCheckBit = 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003527 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003528}
3529
3530
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003531/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003532 * InsertMenuA (USER32.@)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003533 */
Aric Stewartc946b1c2000-10-24 21:28:19 +00003534BOOL WINAPI InsertMenuA( HMENU hMenu, UINT pos, UINT flags,
3535 UINT id, LPCSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003536{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003537 BOOL ret;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003538
3539 if (IS_STRING_ITEM(flags) && str)
3540 {
Aric Stewartc946b1c2000-10-24 21:28:19 +00003541 LPWSTR newstr = HEAP_strdupAtoW( GetProcessHeap(), 0, str );
3542 ret = InsertMenuW( hMenu, pos, flags, id, newstr );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003543 HeapFree( GetProcessHeap(), 0, newstr );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003544 return ret;
3545 }
Aric Stewartc946b1c2000-10-24 21:28:19 +00003546 else return InsertMenuW( hMenu, pos, flags, id, (LPCWSTR)str );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003547}
3548
3549
3550/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003551 * AppendMenu (USER.411)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003552 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003553BOOL16 WINAPI AppendMenu16(HMENU16 hMenu, UINT16 flags, UINT16 id, SEGPTR data)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003554{
3555 return InsertMenu16( hMenu, -1, flags | MF_BYPOSITION, id, data );
3556}
3557
3558
3559/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003560 * AppendMenuA (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003561 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003562BOOL WINAPI AppendMenuA( HMENU hMenu, UINT flags,
3563 UINT id, LPCSTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003564{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003565 return InsertMenuA( hMenu, -1, flags | MF_BYPOSITION, id, data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003566}
3567
3568
3569/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003570 * AppendMenuW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003571 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003572BOOL WINAPI AppendMenuW( HMENU hMenu, UINT flags,
3573 UINT id, LPCWSTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003574{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003575 return InsertMenuW( hMenu, -1, flags | MF_BYPOSITION, id, data );
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003576}
3577
3578
3579/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003580 * RemoveMenu (USER.412)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003581 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003582BOOL16 WINAPI RemoveMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003583{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003584 return RemoveMenu( hMenu, nPos, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003585}
3586
3587
3588/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003589 * RemoveMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003590 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003591BOOL WINAPI RemoveMenu( HMENU hMenu, UINT nPos, UINT wFlags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003592{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003593 LPPOPUPMENU menu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003594 MENUITEM *item;
3595
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003596 TRACE("(menu=%04x pos=%04x flags=%04x)\n",hMenu, nPos, wFlags);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003597 if (!(item = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
Gerard Patel3e629742000-01-17 22:22:16 +00003598 if (!(menu = MENU_GetMenu(hMenu))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003599
3600 /* Remove item */
3601
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003602 MENU_FreeItemData( item );
3603
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003604 if (--menu->nItems == 0)
3605 {
Alexandre Julliardda2892c2001-02-23 01:13:42 +00003606 HeapFree( GetProcessHeap(), 0, menu->items );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003607 menu->items = NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003608 }
3609 else
3610 {
3611 while(nPos < menu->nItems)
3612 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003613 *item = *(item+1);
3614 item++;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003615 nPos++;
3616 }
Alexandre Julliardda2892c2001-02-23 01:13:42 +00003617 menu->items = HeapReAlloc( GetProcessHeap(), 0, menu->items,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003618 menu->nItems * sizeof(MENUITEM) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003619 }
3620 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003621}
3622
3623
3624/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003625 * DeleteMenu (USER.413)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003626 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003627BOOL16 WINAPI DeleteMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003628{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003629 return DeleteMenu( hMenu, nPos, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003630}
3631
3632
3633/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003634 * DeleteMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003635 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003636BOOL WINAPI DeleteMenu( HMENU hMenu, UINT nPos, UINT wFlags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003637{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003638 MENUITEM *item = MENU_FindItem( &hMenu, &nPos, wFlags );
3639 if (!item) return FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003640 if (item->fType & MF_POPUP) DestroyMenu( item->hSubMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003641 /* nPos is now the position of the item */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003642 RemoveMenu( hMenu, nPos, wFlags | MF_BYPOSITION );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003643 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003644}
3645
3646
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003647/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003648 * ModifyMenu (USER.414)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003649 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003650BOOL16 WINAPI ModifyMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags,
3651 UINT16 id, SEGPTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003652{
3653 if (IS_STRING_ITEM(flags))
Alexandre Julliard982a2232000-12-13 20:20:09 +00003654 return ModifyMenuA( hMenu, pos, flags, id, MapSL(data) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003655 return ModifyMenuA( hMenu, pos, flags, id, (LPSTR)data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003656}
3657
3658
3659/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003660 * ModifyMenuW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003661 */
Aric Stewartc946b1c2000-10-24 21:28:19 +00003662BOOL WINAPI ModifyMenuW( HMENU hMenu, UINT pos, UINT flags,
3663 UINT id, LPCWSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003664{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003665 MENUITEM *item;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003666
3667 if (IS_STRING_ITEM(flags))
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00003668 {
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003669 TRACE("%04x %d %04x %04x %s\n",
3670 hMenu, pos, flags, id, debugstr_w(str) );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003671 if (!str) return FALSE;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00003672 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003673 else
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003674 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003675 TRACE("%04x %d %04x %04x %08lx\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003676 hMenu, pos, flags, id, (DWORD)str );
3677 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003678
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003679 if (!(item = MENU_FindItem( &hMenu, &pos, flags ))) return FALSE;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003680 return MENU_SetItemData( item, flags, id, str );
3681}
3682
3683
3684/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003685 * ModifyMenuA (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003686 */
Aric Stewartc946b1c2000-10-24 21:28:19 +00003687BOOL WINAPI ModifyMenuA( HMENU hMenu, UINT pos, UINT flags,
3688 UINT id, LPCSTR str )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003689{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003690 BOOL ret;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003691
3692 if (IS_STRING_ITEM(flags) && str)
3693 {
Aric Stewartc946b1c2000-10-24 21:28:19 +00003694 LPWSTR newstr = HEAP_strdupAtoW( GetProcessHeap(), 0, str );
3695 ret = ModifyMenuW( hMenu, pos, flags, id, newstr );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003696 HeapFree( GetProcessHeap(), 0, newstr );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003697 return ret;
3698 }
Aric Stewartc946b1c2000-10-24 21:28:19 +00003699 else return ModifyMenuW( hMenu, pos, flags, id, (LPCWSTR)str );
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003700}
3701
3702
3703/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003704 * CreatePopupMenu (USER.415)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003705 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003706HMENU16 WINAPI CreatePopupMenu16(void)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003707{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003708 return CreatePopupMenu();
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003709}
3710
3711
3712/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003713 * CreatePopupMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003714 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003715HMENU WINAPI CreatePopupMenu(void)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003716{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003717 HMENU hmenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003718 POPUPMENU *menu;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003719
Alexandre Julliarda3960291999-02-26 11:11:13 +00003720 if (!(hmenu = CreateMenu())) return 0;
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003721 menu = MENU_GetMenu( hmenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003722 menu->wFlags |= MF_POPUP;
Pascal Lessard2eb0a301999-09-03 16:38:52 +00003723 menu->bTimeToHide = FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003724 return hmenu;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003725}
3726
3727
3728/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003729 * GetMenuCheckMarkDimensions (USER.417) (USER32.@)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003730 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003731DWORD WINAPI GetMenuCheckMarkDimensions(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003732{
Alexandre Julliardc1d35cc2001-01-24 19:47:57 +00003733 return MAKELONG( GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK) );
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003734}
3735
3736
3737/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003738 * SetMenuItemBitmaps (USER.418)
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003739 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003740BOOL16 WINAPI SetMenuItemBitmaps16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags,
3741 HBITMAP16 hNewUnCheck, HBITMAP16 hNewCheck)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003742{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003743 return SetMenuItemBitmaps( hMenu, nPos, wFlags, hNewUnCheck, hNewCheck );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003744}
3745
3746
3747/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003748 * SetMenuItemBitmaps (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003749 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003750BOOL WINAPI SetMenuItemBitmaps( HMENU hMenu, UINT nPos, UINT wFlags,
3751 HBITMAP hNewUnCheck, HBITMAP hNewCheck)
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003752{
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003753 MENUITEM *item;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003754 TRACE("(%04x, %04x, %04x, %04x, %04x)\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003755 hMenu, nPos, wFlags, hNewCheck, hNewUnCheck);
3756 if (!(item = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003757
3758 if (!hNewCheck && !hNewUnCheck)
3759 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003760 item->fState &= ~MF_USECHECKBITMAPS;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003761 }
3762 else /* Install new bitmaps */
3763 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003764 item->hCheckBit = hNewCheck;
3765 item->hUnCheckBit = hNewUnCheck;
3766 item->fState |= MF_USECHECKBITMAPS;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003767 }
3768 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003769}
3770
3771
3772/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003773 * CreateMenu (USER.151)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003774 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003775HMENU16 WINAPI CreateMenu16(void)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003776{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003777 return CreateMenu();
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003778}
3779
3780
3781/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003782 * CreateMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003783 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003784HMENU WINAPI CreateMenu(void)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003785{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003786 HMENU hMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003787 LPPOPUPMENU menu;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003788 if (!(hMenu = USER_HEAP_ALLOC( sizeof(POPUPMENU) ))) return 0;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00003789 menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
Juergen Schmied78513941999-04-18 14:40:32 +00003790
3791 ZeroMemory(menu, sizeof(POPUPMENU));
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003792 menu->wMagic = MENU_MAGIC;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003793 menu->FocusedItem = NO_SELECTED_ITEM;
Pascal Lessard2eb0a301999-09-03 16:38:52 +00003794 menu->bTimeToHide = FALSE;
Juergen Schmied78513941999-04-18 14:40:32 +00003795
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003796 TRACE("return %04x\n", hMenu );
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003797
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003798 return hMenu;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003799}
3800
3801
3802/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003803 * DestroyMenu (USER.152)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003804 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003805BOOL16 WINAPI DestroyMenu16( HMENU16 hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003806{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003807 return DestroyMenu( hMenu );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003808}
3809
3810
3811/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003812 * DestroyMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003813 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003814BOOL WINAPI DestroyMenu( HMENU hMenu )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003815{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003816 TRACE("(%04x)\n", hMenu);
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003817
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003818 /* Silently ignore attempts to destroy default system popup */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003819
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003820 if (hMenu && hMenu != MENU_DefSysPopup)
Alexandre Julliardff8331e1995-09-18 11:19:54 +00003821 {
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003822 LPPOPUPMENU lppop = MENU_GetMenu(hMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003823
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003824 if (!lppop) return FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003825
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003826 lppop->wMagic = 0; /* Mark it as destroyed */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003827
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003828 if ((lppop->wFlags & MF_POPUP) && lppop->hWnd)
Gerard Patel8f79fdc2001-05-14 19:20:13 +00003829 {
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003830 DestroyWindow( lppop->hWnd );
Gerard Patel8f79fdc2001-05-14 19:20:13 +00003831 lppop->hWnd = 0;
3832 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003833
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003834 if (lppop->items) /* recursively destroy submenus */
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +00003835 {
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003836 int i;
3837 MENUITEM *item = lppop->items;
3838 for (i = lppop->nItems; i > 0; i--, item++)
3839 {
3840 if (item->fType & MF_POPUP) DestroyMenu(item->hSubMenu);
3841 MENU_FreeItemData( item );
3842 }
3843 HeapFree( GetProcessHeap(), 0, lppop->items );
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +00003844 }
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00003845 USER_HEAP_FREE( hMenu );
Alexandre Julliardff8331e1995-09-18 11:19:54 +00003846 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003847 return (hMenu != MENU_DefSysPopup);
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003848}
3849
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003850
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003851/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003852 * GetSystemMenu (USER.156)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003853 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003854HMENU16 WINAPI GetSystemMenu16( HWND16 hWnd, BOOL16 bRevert )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003855{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003856 return GetSystemMenu( hWnd, bRevert );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003857}
3858
3859
3860/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003861 * GetSystemMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003862 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003863HMENU WINAPI GetSystemMenu( HWND hWnd, BOOL bRevert )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003864{
Alexandre Julliardb7258be1995-09-01 15:57:28 +00003865 WND *wndPtr = WIN_FindWndPtr( hWnd );
Eric Pouech562309a1999-08-21 12:59:44 +00003866 HMENU retvalue = 0;
Alexandre Julliardb7258be1995-09-01 15:57:28 +00003867
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003868 if (wndPtr)
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003869 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003870 if( wndPtr->hSysMenu )
3871 {
3872 if( bRevert )
3873 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003874 DestroyMenu(wndPtr->hSysMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003875 wndPtr->hSysMenu = 0;
3876 }
3877 else
3878 {
Gerard Patel3e629742000-01-17 22:22:16 +00003879 POPUPMENU *menu = MENU_GetMenu( wndPtr->hSysMenu );
3880 if( menu )
Eric Pouech562309a1999-08-21 12:59:44 +00003881 {
3882 if( menu->nItems > 0 && menu->items[0].hSubMenu == MENU_DefSysPopup )
3883 menu->items[0].hSubMenu = MENU_CopySysPopup();
3884 }
3885 else
3886 {
3887 WARN("Current sys-menu (%04x) of wnd %04x is broken\n",
3888 wndPtr->hSysMenu, hWnd);
3889 wndPtr->hSysMenu = 0;
3890 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003891 }
3892 }
3893
3894 if(!wndPtr->hSysMenu && (wndPtr->dwStyle & WS_SYSMENU) )
Alexandre Julliarda3960291999-02-26 11:11:13 +00003895 wndPtr->hSysMenu = MENU_GetSysMenu( hWnd, (HMENU)(-1) );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003896
3897 if( wndPtr->hSysMenu )
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003898 {
Eric Pouech562309a1999-08-21 12:59:44 +00003899 POPUPMENU *menu;
3900 retvalue = GetSubMenu16(wndPtr->hSysMenu, 0);
Pascal Lessardd814bb61999-07-31 13:02:02 +00003901
3902 /* Store the dummy sysmenu handle to facilitate the refresh */
3903 /* of the close button if the SC_CLOSE item change */
Gerard Patel3e629742000-01-17 22:22:16 +00003904 menu = MENU_GetMenu(retvalue);
3905 if ( menu )
Eric Pouech562309a1999-08-21 12:59:44 +00003906 menu->hSysMenuOwner = wndPtr->hSysMenu;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003907 }
3908 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003909 }
Francois Jacques20af4c32000-06-18 17:17:54 +00003910 return bRevert ? 0 : retvalue;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003911}
3912
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003913
3914/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003915 * SetSystemMenu (USER.280)
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00003916 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003917BOOL16 WINAPI SetSystemMenu16( HWND16 hwnd, HMENU16 hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003918{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003919 return SetSystemMenu( hwnd, hMenu );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003920}
3921
3922
3923/*******************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003924 * SetSystemMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003925 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003926BOOL WINAPI SetSystemMenu( HWND hwnd, HMENU hMenu )
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00003927{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003928 WND *wndPtr = WIN_FindWndPtr(hwnd);
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00003929
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003930 if (wndPtr)
3931 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003932 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003933 wndPtr->hSysMenu = MENU_GetSysMenu( hwnd, hMenu );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003934 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003935 return TRUE;
3936 }
3937 return FALSE;
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00003938}
3939
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003940
3941/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003942 * GetMenu (USER.157)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003943 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003944HMENU16 WINAPI GetMenu16( HWND16 hWnd )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003945{
Richard Cohen56753621999-09-19 14:08:13 +00003946 return (HMENU16)GetMenu(hWnd);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003947}
3948
3949
3950/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003951 * GetMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003952 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003953HMENU WINAPI GetMenu( HWND hWnd )
Dmitry Timoshkovfbb2c9b2000-09-09 19:38:34 +00003954{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003955 HMENU retvalue;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003956 WND * wndPtr = WIN_FindWndPtr(hWnd);
Dmitry Timoshkovfbb2c9b2000-09-09 19:38:34 +00003957
3958 if (!wndPtr) return 0;
3959
3960 retvalue = (HMENU)wndPtr->wIDmenu;
3961 TRACE("for %swindow %04x returning %04x\n",
3962 (wndPtr->dwStyle & WS_CHILD) ? "child " : "", hWnd, retvalue);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003963 WIN_ReleaseWndPtr(wndPtr);
3964 return retvalue;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003965}
3966
3967
3968/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00003969 * SetMenu (USER.158)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003970 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003971BOOL16 WINAPI SetMenu16( HWND16 hWnd, HMENU16 hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003972{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003973 return SetMenu( hWnd, hMenu );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003974}
3975
3976
3977/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00003978 * SetMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003979 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003980BOOL WINAPI SetMenu( HWND hWnd, HMENU hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003981{
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003982 WND * wndPtr = WIN_FindWndPtr(hWnd);
Andreas Mohr6f07e8a2000-09-19 02:38:11 +00003983 BOOL res = FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003984
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003985 TRACE("(%04x, %04x);\n", hWnd, hMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003986
Richard Cohen56753621999-09-19 14:08:13 +00003987 if (hMenu && !IsMenu(hMenu))
3988 {
3989 WARN("hMenu is not a menu handle\n");
Andreas Mohr6f07e8a2000-09-19 02:38:11 +00003990 goto exit;
Richard Cohen56753621999-09-19 14:08:13 +00003991 }
Richard Cohen56753621999-09-19 14:08:13 +00003992
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003993 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD))
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003994 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003995 if (GetCapture() == hWnd) ReleaseCapture();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003996
Alexandre Julliarda3960291999-02-26 11:11:13 +00003997 wndPtr->wIDmenu = (UINT)hMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003998 if (hMenu != 0)
3999 {
4000 LPPOPUPMENU lpmenu;
4001
Gerard Patel3e629742000-01-17 22:22:16 +00004002 if (!(lpmenu = MENU_GetMenu(hMenu)))
Andreas Mohr6f07e8a2000-09-19 02:38:11 +00004003 goto exit;
4004
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004005 lpmenu->hWnd = hWnd;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004006 lpmenu->Height = 0; /* Make sure we recalculate the size */
4007 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00004008 if (IsWindowVisible(hWnd))
4009 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
Alexandre Julliard01d63461997-01-20 19:43:45 +00004010 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
Andreas Mohr6f07e8a2000-09-19 02:38:11 +00004011 res = TRUE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004012 }
Andreas Mohr6f07e8a2000-09-19 02:38:11 +00004013exit:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004014 WIN_ReleaseWndPtr(wndPtr);
Andreas Mohr6f07e8a2000-09-19 02:38:11 +00004015 return res;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004016}
4017
4018
Alexandre Julliardd18872d1994-05-11 12:18:19 +00004019
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004020/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004021 * GetSubMenu (USER.159)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004022 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004023HMENU16 WINAPI GetSubMenu16( HMENU16 hMenu, INT16 nPos )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004024{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004025 return GetSubMenu( hMenu, nPos );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004026}
4027
4028
4029/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004030 * GetSubMenu (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004031 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004032HMENU WINAPI GetSubMenu( HMENU hMenu, INT nPos )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004033{
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00004034 MENUITEM * lpmi;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004035
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00004036 if (!(lpmi = MENU_FindItem(&hMenu,&nPos,MF_BYPOSITION))) return 0;
4037 if (!(lpmi->fType & MF_POPUP)) return 0;
4038 return lpmi->hSubMenu;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004039}
4040
4041
4042/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004043 * DrawMenuBar (USER.160)
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004044 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004045void WINAPI DrawMenuBar16( HWND16 hWnd )
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004046{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004047 DrawMenuBar( hWnd );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004048}
Alexandre Julliardf7207251994-07-23 07:57:48 +00004049
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004050
4051/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004052 * DrawMenuBar (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004053 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004054BOOL WINAPI DrawMenuBar( HWND hWnd )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004055{
4056 LPPOPUPMENU lppop;
4057 WND *wndPtr = WIN_FindWndPtr(hWnd);
4058 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && wndPtr->wIDmenu)
4059 {
Gerard Patel3e629742000-01-17 22:22:16 +00004060 lppop = MENU_GetMenu((HMENU16)wndPtr->wIDmenu);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004061 if (lppop == NULL)
4062 {
4063 WIN_ReleaseWndPtr(wndPtr);
4064 return FALSE;
4065 }
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004066
4067 lppop->Height = 0; /* Make sure we call MENU_MenuBarCalcSize */
Juergen Schmied78513941999-04-18 14:40:32 +00004068 lppop->hwndOwner = hWnd;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004069 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
Alexandre Julliard01d63461997-01-20 19:43:45 +00004070 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004071 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004072 return TRUE;
4073 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004074 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004075 return FALSE;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004076}
4077
Eric Pouecha862f682001-02-26 22:33:29 +00004078/***********************************************************************
4079 * DrawMenuBarTemp (USER32.@)
4080 */
4081DWORD WINAPI DrawMenuBarTemp(DWORD p1, DWORD p2)
4082{
4083 FIXME("(%08lx %08lx): stub\n", p1, p2);
4084 return 0;
4085}
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004086
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004087/***********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004088 * EndMenu (USER.187) (USER32.@)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004089 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004090void WINAPI EndMenu(void)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004091{
Rob Farnumb2007932000-05-23 23:34:17 +00004092 /* if we are in the menu code, and it is active */
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00004093 if (!fEndMenu && top_popup)
Rob Farnumb2007932000-05-23 23:34:17 +00004094 {
4095 /* terminate the menu handling code */
4096 fEndMenu = TRUE;
Alex Korobka4f1ac051999-03-28 09:37:57 +00004097
Rob Farnumb2007932000-05-23 23:34:17 +00004098 /* needs to be posted to wakeup the internal menu handler */
4099 /* which will now terminate the menu, in the event that */
4100 /* the main window was minimized, or lost focus, so we */
4101 /* don't end up with an orphaned menu */
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00004102 PostMessageA( top_popup, WM_CANCELMODE, 0, 0);
Rob Farnumb2007932000-05-23 23:34:17 +00004103 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004104}
4105
4106
4107/***********************************************************************
4108 * LookupMenuHandle (USER.217)
4109 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004110HMENU16 WINAPI LookupMenuHandle16( HMENU16 hmenu, INT16 id )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004111{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004112 HMENU hmenu32 = hmenu;
4113 UINT id32 = id;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004114 if (!MENU_FindItem( &hmenu32, &id32, MF_BYCOMMAND )) return 0;
4115 else return hmenu32;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004116}
4117
4118
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004119/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004120 * LoadMenu (USER.150)
Alexandre Julliard594997c1995-04-30 10:05:20 +00004121 */
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004122HMENU16 WINAPI LoadMenu16( HINSTANCE16 instance, LPCSTR name )
Alexandre Julliard594997c1995-04-30 10:05:20 +00004123{
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004124 HRSRC16 hRsrc;
4125 HGLOBAL16 handle;
4126 HMENU16 hMenu;
Alexandre Julliard594997c1995-04-30 10:05:20 +00004127
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004128 TRACE("(%04x,%s)\n", instance, debugres_a(name) );
4129
Alexandre Julliard594997c1995-04-30 10:05:20 +00004130 if (HIWORD(name))
4131 {
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004132 if (name[0] == '#') name = (LPCSTR)atoi( name + 1 );
Alexandre Julliard594997c1995-04-30 10:05:20 +00004133 }
Alexandre Julliard594997c1995-04-30 10:05:20 +00004134
4135 if (!name) return 0;
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004136
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00004137 /* check for Win32 module */
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004138 if (HIWORD(instance)) return LoadMenuA( instance, name );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00004139 instance = GetExePtr( instance );
Alexandre Julliard594997c1995-04-30 10:05:20 +00004140
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004141 if (!(hRsrc = FindResource16( instance, name, RT_MENUA ))) return 0;
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004142 if (!(handle = LoadResource16( instance, hRsrc ))) return 0;
4143 hMenu = LoadMenuIndirect16(LockResource16(handle));
4144 FreeResource16( handle );
Alexandre Julliard594997c1995-04-30 10:05:20 +00004145 return hMenu;
4146}
4147
4148
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004149/*****************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004150 * LoadMenuA (USER32.@)
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004151 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004152HMENU WINAPI LoadMenuA( HINSTANCE instance, LPCSTR name )
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004153{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004154 HRSRC hrsrc = FindResourceA( instance, name, RT_MENUA );
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004155 if (!hrsrc) return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004156 return LoadMenuIndirectA( (LPCVOID)LoadResource( instance, hrsrc ));
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004157}
4158
4159
4160/*****************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004161 * LoadMenuW (USER32.@)
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004162 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004163HMENU WINAPI LoadMenuW( HINSTANCE instance, LPCWSTR name )
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004164{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004165 HRSRC hrsrc = FindResourceW( instance, name, RT_MENUW );
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004166 if (!hrsrc) return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004167 return LoadMenuIndirectW( (LPCVOID)LoadResource( instance, hrsrc ));
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004168}
4169
4170
Alexandre Julliard594997c1995-04-30 10:05:20 +00004171/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004172 * LoadMenuIndirect (USER.220)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00004173 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004174HMENU16 WINAPI LoadMenuIndirect16( LPCVOID template )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00004175{
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00004176 HMENU16 hMenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004177 WORD version, offset;
4178 LPCSTR p = (LPCSTR)template;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00004179
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004180 TRACE("(%p)\n", template );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004181 version = GET_WORD(p);
4182 p += sizeof(WORD);
4183 if (version)
4184 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004185 WARN("version must be 0 for Win16\n" );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004186 return 0;
4187 }
4188 offset = GET_WORD(p);
4189 p += sizeof(WORD) + offset;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004190 if (!(hMenu = CreateMenu())) return 0;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004191 if (!MENU_ParseResource( p, hMenu, FALSE ))
Alexandre Julliard7e56f681996-01-31 19:02:28 +00004192 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004193 DestroyMenu( hMenu );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004194 return 0;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00004195 }
4196 return hMenu;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004197}
4198
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004199
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004200/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004201 * LoadMenuIndirectA (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004202 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004203HMENU WINAPI LoadMenuIndirectA( LPCVOID template )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004204{
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00004205 HMENU16 hMenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004206 WORD version, offset;
4207 LPCSTR p = (LPCSTR)template;
4208
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004209 TRACE("%p\n", template );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004210 version = GET_WORD(p);
4211 p += sizeof(WORD);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004212 switch (version)
4213 {
4214 case 0:
4215 offset = GET_WORD(p);
4216 p += sizeof(WORD) + offset;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004217 if (!(hMenu = CreateMenu())) return 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004218 if (!MENU_ParseResource( p, hMenu, TRUE ))
4219 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004220 DestroyMenu( hMenu );
Alexandre Julliard641ee761997-08-04 16:34:36 +00004221 return 0;
4222 }
4223 return hMenu;
4224 case 1:
4225 offset = GET_WORD(p);
4226 p += sizeof(WORD) + offset;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004227 if (!(hMenu = CreateMenu())) return 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004228 if (!MENUEX_ParseResource( p, hMenu))
4229 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004230 DestroyMenu( hMenu );
Alexandre Julliard641ee761997-08-04 16:34:36 +00004231 return 0;
4232 }
4233 return hMenu;
4234 default:
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004235 ERR("version %d not supported.\n", version);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004236 return 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004237 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004238}
4239
4240
4241/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004242 * LoadMenuIndirectW (USER32.@)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004243 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004244HMENU WINAPI LoadMenuIndirectW( LPCVOID template )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004245{
4246 /* FIXME: is there anything different between A and W? */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004247 return LoadMenuIndirectA( template );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004248}
4249
4250
4251/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004252 * IsMenu (USER.358)
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004253 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004254BOOL16 WINAPI IsMenu16( HMENU16 hmenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004255{
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00004256 return IsMenu( hmenu );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004257}
4258
4259
4260/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004261 * IsMenu (USER32.@)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004262 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004263BOOL WINAPI IsMenu(HMENU hmenu)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004264{
Alexandre Julliarde60ccd12001-05-11 20:05:42 +00004265 LPPOPUPMENU menu = MENU_GetMenu(hmenu);
4266 return menu != NULL;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004267}
4268
Alexandre Julliard641ee761997-08-04 16:34:36 +00004269/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004270 * GetMenuItemInfo_common
Alexandre Julliard641ee761997-08-04 16:34:36 +00004271 */
4272
Juergen Schmied78513941999-04-18 14:40:32 +00004273static BOOL GetMenuItemInfo_common ( HMENU hmenu, UINT item, BOOL bypos,
Aric Stewartc946b1c2000-10-24 21:28:19 +00004274 LPMENUITEMINFOW lpmii, BOOL unicode)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004275{
Juergen Schmied78513941999-04-18 14:40:32 +00004276 MENUITEM *menu = MENU_FindItem (&hmenu, &item, bypos? MF_BYPOSITION : 0);
4277
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004278 debug_print_menuitem("GetMenuItemInfo_common: ", menu, "");
Juergen Schmied78513941999-04-18 14:40:32 +00004279
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004280 if (!menu)
4281 return FALSE;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004282
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004283 if (lpmii->fMask & MIIM_TYPE) {
4284 lpmii->fType = menu->fType;
4285 switch (MENU_ITEM_TYPE(menu->fType)) {
Huw D M Davies2d6eaba2000-03-24 19:48:53 +00004286 case MF_STRING:
Alexandre Julliard24a62ab2000-11-28 22:40:56 +00004287 break; /* will be done below */
Huw D M Davies2d6eaba2000-03-24 19:48:53 +00004288 case MF_OWNERDRAW:
4289 case MF_BITMAP:
4290 lpmii->dwTypeData = menu->text;
4291 /* fall through */
4292 default:
4293 lpmii->cch = 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004294 }
Alexandre Julliard641ee761997-08-04 16:34:36 +00004295 }
Juergen Schmied78513941999-04-18 14:40:32 +00004296
Alexandre Julliard24a62ab2000-11-28 22:40:56 +00004297 /* copy the text string */
4298 if ((lpmii->fMask & (MIIM_TYPE|MIIM_STRING)) &&
4299 (MENU_ITEM_TYPE(menu->fType) == MF_STRING) && menu->text)
4300 {
4301 int len;
4302 if (unicode)
4303 {
4304 len = strlenW(menu->text);
4305 if(lpmii->dwTypeData && lpmii->cch)
4306 lstrcpynW(lpmii->dwTypeData, menu->text, lpmii->cch);
4307 }
4308 else
4309 {
4310 len = WideCharToMultiByte( CP_ACP, 0, menu->text, -1, NULL, 0, NULL, NULL );
4311 if(lpmii->dwTypeData && lpmii->cch)
4312 if (!WideCharToMultiByte( CP_ACP, 0, menu->text, -1,
4313 (LPSTR)lpmii->dwTypeData, lpmii->cch, NULL, NULL ))
4314 ((LPSTR)lpmii->dwTypeData)[lpmii->cch-1] = 0;
4315 }
4316 /* if we've copied a substring we return its length */
4317 if(lpmii->dwTypeData && lpmii->cch)
4318 {
4319 if (lpmii->cch <= len) lpmii->cch--;
4320 }
4321 else /* return length of string */
4322 lpmii->cch = len;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004323 }
Juergen Schmied78513941999-04-18 14:40:32 +00004324
4325 if (lpmii->fMask & MIIM_FTYPE)
4326 lpmii->fType = menu->fType;
4327
4328 if (lpmii->fMask & MIIM_BITMAP)
4329 lpmii->hbmpItem = menu->hbmpItem;
4330
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004331 if (lpmii->fMask & MIIM_STATE)
4332 lpmii->fState = menu->fState;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004333
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004334 if (lpmii->fMask & MIIM_ID)
4335 lpmii->wID = menu->wID;
4336
4337 if (lpmii->fMask & MIIM_SUBMENU)
4338 lpmii->hSubMenu = menu->hSubMenu;
4339
4340 if (lpmii->fMask & MIIM_CHECKMARKS) {
4341 lpmii->hbmpChecked = menu->hCheckBit;
4342 lpmii->hbmpUnchecked = menu->hUnCheckBit;
4343 }
4344 if (lpmii->fMask & MIIM_DATA)
4345 lpmii->dwItemData = menu->dwItemData;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004346
4347 return TRUE;
4348}
4349
4350/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004351 * GetMenuItemInfoA (USER32.@)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004352 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004353BOOL WINAPI GetMenuItemInfoA( HMENU hmenu, UINT item, BOOL bypos,
4354 LPMENUITEMINFOA lpmii)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004355{
Aric Stewartc946b1c2000-10-24 21:28:19 +00004356 return GetMenuItemInfo_common (hmenu, item, bypos,
4357 (LPMENUITEMINFOW)lpmii, FALSE);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004358}
4359
4360/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004361 * GetMenuItemInfoW (USER32.@)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004362 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004363BOOL WINAPI GetMenuItemInfoW( HMENU hmenu, UINT item, BOOL bypos,
4364 LPMENUITEMINFOW lpmii)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004365{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004366 return GetMenuItemInfo_common (hmenu, item, bypos,
Aric Stewartc946b1c2000-10-24 21:28:19 +00004367 lpmii, TRUE);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004368}
4369
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004370/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004371 * SetMenuItemInfo_common
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004372 */
4373
Alexandre Julliarda3960291999-02-26 11:11:13 +00004374static BOOL SetMenuItemInfo_common(MENUITEM * menu,
Aric Stewartc946b1c2000-10-24 21:28:19 +00004375 const MENUITEMINFOW *lpmii,
Alexandre Julliarda3960291999-02-26 11:11:13 +00004376 BOOL unicode)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004377{
4378 if (!menu) return FALSE;
4379
Gerard Patel2482ef32001-03-19 19:16:21 +00004380 debug_print_menuitem("MENU_SetItemInfo_common from: ", menu, "");
4381
Juergen Schmied78513941999-04-18 14:40:32 +00004382 if (lpmii->fMask & MIIM_TYPE ) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004383 /* Get rid of old string. */
Juergen Schmied78513941999-04-18 14:40:32 +00004384 if ( IS_STRING_ITEM(menu->fType) && menu->text) {
Alexandre Julliardda2892c2001-02-23 01:13:42 +00004385 HeapFree(GetProcessHeap(), 0, menu->text);
Juergen Schmied78513941999-04-18 14:40:32 +00004386 menu->text = NULL;
4387 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004388
Juergen Schmied78513941999-04-18 14:40:32 +00004389 /* make only MENU_ITEM_TYPE bits in menu->fType equal lpmii->fType */
4390 menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
4391 menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
Paul Millar39da2221999-04-11 12:08:42 +00004392
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004393 menu->text = lpmii->dwTypeData;
Juergen Schmied78513941999-04-18 14:40:32 +00004394
Gerard Patel2482ef32001-03-19 19:16:21 +00004395 if (IS_STRING_ITEM(menu->fType)) {
4396 if (menu->text) {
4397 if (unicode)
4398 menu->text = HEAP_strdupW(GetProcessHeap(), 0, lpmii->dwTypeData);
4399 else
4400 menu->text = HEAP_strdupAtoW(GetProcessHeap(), 0, (LPSTR)lpmii->dwTypeData);
4401 }
4402 else
4403 menu->fType |= MF_SEPARATOR;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004404 }
4405 }
Juergen Schmied78513941999-04-18 14:40:32 +00004406
4407 if (lpmii->fMask & MIIM_FTYPE ) {
4408 /* free the string when the type is changing */
4409 if ( (!IS_STRING_ITEM(lpmii->fType)) && IS_STRING_ITEM(menu->fType) && menu->text) {
Alexandre Julliardda2892c2001-02-23 01:13:42 +00004410 HeapFree(GetProcessHeap(), 0, menu->text);
Juergen Schmied78513941999-04-18 14:40:32 +00004411 menu->text = NULL;
4412 }
4413 menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
4414 menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
Gerard Patel2482ef32001-03-19 19:16:21 +00004415 if ( IS_STRING_ITEM(menu->fType) && !menu->text )
4416 menu->fType |= MF_SEPARATOR;
Juergen Schmied78513941999-04-18 14:40:32 +00004417 }
4418
4419 if (lpmii->fMask & MIIM_STRING ) {
4420 /* free the string when used */
4421 if ( IS_STRING_ITEM(menu->fType) && menu->text) {
Alexandre Julliardda2892c2001-02-23 01:13:42 +00004422 HeapFree(GetProcessHeap(), 0, menu->text);
Gerard Patel2482ef32001-03-19 19:16:21 +00004423 if (lpmii->dwTypeData) {
4424 if (unicode)
4425 menu->text = HEAP_strdupW(GetProcessHeap(), 0, lpmii->dwTypeData);
4426 else
4427 menu->text = HEAP_strdupAtoW(GetProcessHeap(), 0, (LPSTR) lpmii->dwTypeData);
4428 }
4429 else
4430 menu->fType |= MF_SEPARATOR;
Juergen Schmied78513941999-04-18 14:40:32 +00004431 }
4432 }
4433
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004434 if (lpmii->fMask & MIIM_STATE)
Juergen Schmied466a6521999-05-02 11:21:08 +00004435 {
4436 /* fixme: MFS_DEFAULT do we have to reset the other menu items? */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004437 menu->fState = lpmii->fState;
Juergen Schmied466a6521999-05-02 11:21:08 +00004438 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004439
4440 if (lpmii->fMask & MIIM_ID)
4441 menu->wID = lpmii->wID;
4442
Alexandre Julliarda0d77311998-09-13 16:32:00 +00004443 if (lpmii->fMask & MIIM_SUBMENU) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004444 menu->hSubMenu = lpmii->hSubMenu;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00004445 if (menu->hSubMenu) {
Gerard Patel3e629742000-01-17 22:22:16 +00004446 POPUPMENU *subMenu = MENU_GetMenu((UINT16)menu->hSubMenu);
4447 if (subMenu) {
Alexandre Julliarda0d77311998-09-13 16:32:00 +00004448 subMenu->wFlags |= MF_POPUP;
4449 menu->fType |= MF_POPUP;
4450 }
4451 else
4452 /* FIXME: Return an error ? */
4453 menu->fType &= ~MF_POPUP;
4454 }
4455 else
4456 menu->fType &= ~MF_POPUP;
4457 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004458
4459 if (lpmii->fMask & MIIM_CHECKMARKS)
4460 {
Susan Farleyf1d467a2000-05-12 21:59:31 +00004461 if (lpmii->fType & MFT_RADIOCHECK)
4462 menu->fType |= MFT_RADIOCHECK;
4463
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004464 menu->hCheckBit = lpmii->hbmpChecked;
4465 menu->hUnCheckBit = lpmii->hbmpUnchecked;
4466 }
4467 if (lpmii->fMask & MIIM_DATA)
4468 menu->dwItemData = lpmii->dwItemData;
4469
Gerard Patel2482ef32001-03-19 19:16:21 +00004470 debug_print_menuitem("SetMenuItemInfo_common to : ", menu, "");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004471 return TRUE;
4472}
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004473
4474/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004475 * SetMenuItemInfoA (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004476 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004477BOOL WINAPI SetMenuItemInfoA(HMENU hmenu, UINT item, BOOL bypos,
4478 const MENUITEMINFOA *lpmii)
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004479{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004480 return SetMenuItemInfo_common(MENU_FindItem(&hmenu, &item, bypos? MF_BYPOSITION : 0),
Aric Stewartc946b1c2000-10-24 21:28:19 +00004481 (const MENUITEMINFOW *)lpmii, FALSE);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004482}
4483
4484/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004485 * SetMenuItemInfoW (USER32.@)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004486 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004487BOOL WINAPI SetMenuItemInfoW(HMENU hmenu, UINT item, BOOL bypos,
4488 const MENUITEMINFOW *lpmii)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004489{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004490 return SetMenuItemInfo_common(MENU_FindItem(&hmenu, &item, bypos? MF_BYPOSITION : 0),
Aric Stewartc946b1c2000-10-24 21:28:19 +00004491 lpmii, TRUE);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004492}
4493
4494/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004495 * SetMenuDefaultItem (USER32.@)
Juergen Schmied466a6521999-05-02 11:21:08 +00004496 *
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004497 */
Juergen Schmied466a6521999-05-02 11:21:08 +00004498BOOL WINAPI SetMenuDefaultItem(HMENU hmenu, UINT uItem, UINT bypos)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004499{
Juergen Schmied466a6521999-05-02 11:21:08 +00004500 UINT i;
4501 POPUPMENU *menu;
4502 MENUITEM *item;
4503
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004504 TRACE("(0x%x,%d,%d)\n", hmenu, uItem, bypos);
Alexandre Julliarda845b881998-06-01 10:44:35 +00004505
Gerard Patel3e629742000-01-17 22:22:16 +00004506 if (!(menu = MENU_GetMenu(hmenu))) return FALSE;
Alexandre Julliarda845b881998-06-01 10:44:35 +00004507
Juergen Schmied466a6521999-05-02 11:21:08 +00004508 /* reset all default-item flags */
4509 item = menu->items;
4510 for (i = 0; i < menu->nItems; i++, item++)
4511 {
4512 item->fState &= ~MFS_DEFAULT;
4513 }
4514
4515 /* no default item */
4516 if ( -1 == uItem)
4517 {
4518 return TRUE;
4519 }
Alexandre Julliarda845b881998-06-01 10:44:35 +00004520
Juergen Schmied466a6521999-05-02 11:21:08 +00004521 item = menu->items;
4522 if ( bypos )
4523 {
4524 if ( uItem >= menu->nItems ) return FALSE;
4525 item[uItem].fState |= MFS_DEFAULT;
4526 return TRUE;
4527 }
4528 else
4529 {
4530 for (i = 0; i < menu->nItems; i++, item++)
4531 {
4532 if (item->wID == uItem)
4533 {
4534 item->fState |= MFS_DEFAULT;
4535 return TRUE;
4536 }
4537 }
4538
4539 }
4540 return FALSE;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004541}
4542
Alexandre Julliarda845b881998-06-01 10:44:35 +00004543/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004544 * GetMenuDefaultItem (USER32.@)
Alexandre Julliarda845b881998-06-01 10:44:35 +00004545 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004546UINT WINAPI GetMenuDefaultItem(HMENU hmenu, UINT bypos, UINT flags)
Alexandre Julliarda845b881998-06-01 10:44:35 +00004547{
Juergen Schmied466a6521999-05-02 11:21:08 +00004548 POPUPMENU *menu;
4549 MENUITEM * item;
4550 UINT i = 0;
Alexandre Julliarda845b881998-06-01 10:44:35 +00004551
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004552 TRACE("(0x%x,%d,%d)\n", hmenu, bypos, flags);
Alexandre Julliarda845b881998-06-01 10:44:35 +00004553
Gerard Patel3e629742000-01-17 22:22:16 +00004554 if (!(menu = MENU_GetMenu(hmenu))) return -1;
Juergen Schmied466a6521999-05-02 11:21:08 +00004555
4556 /* find default item */
4557 item = menu->items;
Juergen Schmied49251861999-05-13 18:42:03 +00004558
4559 /* empty menu */
4560 if (! item) return -1;
4561
Juergen Schmied466a6521999-05-02 11:21:08 +00004562 while ( !( item->fState & MFS_DEFAULT ) )
4563 {
4564 i++; item++;
4565 if (i >= menu->nItems ) return -1;
4566 }
4567
4568 /* default: don't return disabled items */
4569 if ( (!(GMDI_USEDISABLED & flags)) && (item->fState & MFS_DISABLED )) return -1;
4570
4571 /* search rekursiv when needed */
4572 if ( (item->fType & MF_POPUP) && (flags & GMDI_GOINTOPOPUPS) )
4573 {
4574 UINT ret;
4575 ret = GetMenuDefaultItem( item->hSubMenu, bypos, flags );
4576 if ( -1 != ret ) return ret;
4577
4578 /* when item not found in submenu, return the popup item */
4579 }
4580 return ( bypos ) ? i : item->wID;
4581
Alexandre Julliarda845b881998-06-01 10:44:35 +00004582}
4583
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004584/*******************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004585 * InsertMenuItem (USER.441)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004586 *
4587 * FIXME: untested
4588 */
4589BOOL16 WINAPI InsertMenuItem16( HMENU16 hmenu, UINT16 pos, BOOL16 byposition,
4590 const MENUITEMINFO16 *mii )
4591{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004592 MENUITEMINFOA miia;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004593
4594 miia.cbSize = sizeof(miia);
4595 miia.fMask = mii->fMask;
Alexandre Julliard982a2232000-12-13 20:20:09 +00004596 miia.dwTypeData = (LPSTR)mii->dwTypeData;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004597 miia.fType = mii->fType;
4598 miia.fState = mii->fState;
4599 miia.wID = mii->wID;
4600 miia.hSubMenu = mii->hSubMenu;
4601 miia.hbmpChecked = mii->hbmpChecked;
4602 miia.hbmpUnchecked = mii->hbmpUnchecked;
4603 miia.dwItemData = mii->dwItemData;
4604 miia.cch = mii->cch;
4605 if (IS_STRING_ITEM(miia.fType))
Alexandre Julliard982a2232000-12-13 20:20:09 +00004606 miia.dwTypeData = MapSL(mii->dwTypeData);
Alexandre Julliarda3960291999-02-26 11:11:13 +00004607 return InsertMenuItemA( hmenu, pos, byposition, &miia );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004608}
4609
4610
4611/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004612 * InsertMenuItemA (USER32.@)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004613 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004614BOOL WINAPI InsertMenuItemA(HMENU hMenu, UINT uItem, BOOL bypos,
4615 const MENUITEMINFOA *lpmii)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004616{
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00004617 MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
Aric Stewartc946b1c2000-10-24 21:28:19 +00004618 return SetMenuItemInfo_common(item, (const MENUITEMINFOW *)lpmii, FALSE);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004619}
4620
4621
4622/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004623 * InsertMenuItemW (USER32.@)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004624 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004625BOOL WINAPI InsertMenuItemW(HMENU hMenu, UINT uItem, BOOL bypos,
4626 const MENUITEMINFOW *lpmii)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004627{
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00004628 MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
Aric Stewartc946b1c2000-10-24 21:28:19 +00004629 return SetMenuItemInfo_common(item, lpmii, TRUE);
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004630}
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004631
4632/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004633 * CheckMenuRadioItem (USER32.@)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004634 */
4635
Alexandre Julliarda3960291999-02-26 11:11:13 +00004636BOOL WINAPI CheckMenuRadioItem(HMENU hMenu,
4637 UINT first, UINT last, UINT check,
4638 UINT bypos)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004639{
4640 MENUITEM *mifirst, *milast, *micheck;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004641 HMENU mfirst = hMenu, mlast = hMenu, mcheck = hMenu;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004642
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004643 TRACE("ox%x: %d-%d, check %d, bypos=%d\n",
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00004644 hMenu, first, last, check, bypos);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004645
4646 mifirst = MENU_FindItem (&mfirst, &first, bypos);
4647 milast = MENU_FindItem (&mlast, &last, bypos);
4648 micheck = MENU_FindItem (&mcheck, &check, bypos);
4649
4650 if (mifirst == NULL || milast == NULL || micheck == NULL ||
4651 mifirst > milast || mfirst != mlast || mfirst != mcheck ||
4652 micheck > milast || micheck < mifirst)
4653 return FALSE;
4654
4655 while (mifirst <= milast)
4656 {
4657 if (mifirst == micheck)
4658 {
4659 mifirst->fType |= MFT_RADIOCHECK;
4660 mifirst->fState |= MFS_CHECKED;
4661 } else {
4662 mifirst->fType &= ~MFT_RADIOCHECK;
4663 mifirst->fState &= ~MFS_CHECKED;
4664 }
4665 mifirst++;
4666 }
4667
4668 return TRUE;
4669}
4670
4671/**********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00004672 * CheckMenuRadioItem (USER.666)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004673 */
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004674BOOL16 WINAPI CheckMenuRadioItem16(HMENU16 hMenu,
4675 UINT16 first, UINT16 last, UINT16 check,
4676 BOOL16 bypos)
4677{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004678 return CheckMenuRadioItem (hMenu, first, last, check, bypos);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004679}
4680
4681/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004682 * GetMenuItemRect (USER32.@)
Pascal Lessard47274231999-02-13 12:21:46 +00004683 *
4684 * ATTENTION: Here, the returned values in rect are the screen
4685 * coordinates of the item just like if the menu was
4686 * always on the upper left side of the application.
4687 *
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004688 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004689BOOL WINAPI GetMenuItemRect (HWND hwnd, HMENU hMenu, UINT uItem,
4690 LPRECT rect)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004691{
Pascal Lessard47274231999-02-13 12:21:46 +00004692 POPUPMENU *itemMenu;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004693 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004694 HWND referenceHwnd;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004695
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004696 TRACE("(0x%x,0x%x,%d,%p)\n", hwnd, hMenu, uItem, rect);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004697
4698 item = MENU_FindItem (&hMenu, &uItem, MF_BYPOSITION);
Pascal Lessard47274231999-02-13 12:21:46 +00004699 referenceHwnd = hwnd;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004700
Pascal Lessard47274231999-02-13 12:21:46 +00004701 if(!hwnd)
4702 {
Gerard Patel3e629742000-01-17 22:22:16 +00004703 itemMenu = MENU_GetMenu(hMenu);
Pascal Lessard47274231999-02-13 12:21:46 +00004704 if (itemMenu == NULL)
4705 return FALSE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004706
Marcus Meissnerac593bb1999-03-17 15:18:28 +00004707 if(itemMenu->hWnd == 0)
Pascal Lessard47274231999-02-13 12:21:46 +00004708 return FALSE;
4709 referenceHwnd = itemMenu->hWnd;
4710 }
4711
4712 if ((rect == NULL) || (item == NULL))
4713 return FALSE;
4714
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004715 *rect = item->rect;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004716
Alexandre Julliarda3960291999-02-26 11:11:13 +00004717 MapWindowPoints(referenceHwnd, 0, (LPPOINT)rect, 2);
Pascal Lessard47274231999-02-13 12:21:46 +00004718
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004719 return TRUE;
4720}
4721
4722/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004723 * GetMenuItemRect (USER.665)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004724 */
4725
4726BOOL16 WINAPI GetMenuItemRect16 (HWND16 hwnd, HMENU16 hMenu, UINT16 uItem,
4727 LPRECT16 rect)
4728{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004729 RECT r32;
4730 BOOL res;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004731
4732 if (!rect) return FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004733 res = GetMenuItemRect (hwnd, hMenu, uItem, &r32);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004734 CONV_RECT32TO16 (&r32, rect);
4735 return res;
4736}
Paul Quinn1beaae51998-12-15 15:38:36 +00004737
4738/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004739 * SetMenuInfo (USER32.@)
Juergen Schmied78513941999-04-18 14:40:32 +00004740 *
4741 * FIXME
4742 * MIM_APPLYTOSUBMENUS
4743 * actually use the items to draw the menu
4744 */
4745BOOL WINAPI SetMenuInfo (HMENU hMenu, LPCMENUINFO lpmi)
4746{
4747 POPUPMENU *menu;
4748
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004749 TRACE("(0x%04x %p)\n", hMenu, lpmi);
Juergen Schmied78513941999-04-18 14:40:32 +00004750
Gerard Patel3e629742000-01-17 22:22:16 +00004751 if (lpmi && (lpmi->cbSize==sizeof(MENUINFO)) && (menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004752 {
4753
4754 if (lpmi->fMask & MIM_BACKGROUND)
4755 menu->hbrBack = lpmi->hbrBack;
4756
4757 if (lpmi->fMask & MIM_HELPID)
4758 menu->dwContextHelpID = lpmi->dwContextHelpID;
4759
4760 if (lpmi->fMask & MIM_MAXHEIGHT)
4761 menu->cyMax = lpmi->cyMax;
4762
4763 if (lpmi->fMask & MIM_MENUDATA)
4764 menu->dwMenuData = lpmi->dwMenuData;
4765
4766 if (lpmi->fMask & MIM_STYLE)
4767 menu->dwStyle = lpmi->dwStyle;
4768
4769 return TRUE;
4770 }
4771 return FALSE;
4772}
4773
4774/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004775 * GetMenuInfo (USER32.@)
Juergen Schmied78513941999-04-18 14:40:32 +00004776 *
4777 * NOTES
4778 * win98/NT5.0
4779 *
4780 */
4781BOOL WINAPI GetMenuInfo (HMENU hMenu, LPMENUINFO lpmi)
4782{ POPUPMENU *menu;
4783
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004784 TRACE("(0x%04x %p)\n", hMenu, lpmi);
Juergen Schmied78513941999-04-18 14:40:32 +00004785
Gerard Patel3e629742000-01-17 22:22:16 +00004786 if (lpmi && (menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004787 {
4788
4789 if (lpmi->fMask & MIM_BACKGROUND)
4790 lpmi->hbrBack = menu->hbrBack;
4791
4792 if (lpmi->fMask & MIM_HELPID)
4793 lpmi->dwContextHelpID = menu->dwContextHelpID;
4794
4795 if (lpmi->fMask & MIM_MAXHEIGHT)
4796 lpmi->cyMax = menu->cyMax;
4797
4798 if (lpmi->fMask & MIM_MENUDATA)
4799 lpmi->dwMenuData = menu->dwMenuData;
4800
4801 if (lpmi->fMask & MIM_STYLE)
4802 lpmi->dwStyle = menu->dwStyle;
4803
4804 return TRUE;
4805 }
4806 return FALSE;
4807}
4808
4809/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004810 * SetMenuContextHelpId (USER.384)
Paul Quinn1beaae51998-12-15 15:38:36 +00004811 */
Juergen Schmied78513941999-04-18 14:40:32 +00004812BOOL16 WINAPI SetMenuContextHelpId16( HMENU16 hMenu, DWORD dwContextHelpID)
Paul Quinn1beaae51998-12-15 15:38:36 +00004813{
Juergen Schmied78513941999-04-18 14:40:32 +00004814 return SetMenuContextHelpId( hMenu, dwContextHelpID );
Paul Quinn1beaae51998-12-15 15:38:36 +00004815}
4816
4817
4818/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004819 * SetMenuContextHelpId (USER32.@)
Paul Quinn1beaae51998-12-15 15:38:36 +00004820 */
Juergen Schmied78513941999-04-18 14:40:32 +00004821BOOL WINAPI SetMenuContextHelpId( HMENU hMenu, DWORD dwContextHelpID)
Paul Quinn1beaae51998-12-15 15:38:36 +00004822{
Juergen Schmied78513941999-04-18 14:40:32 +00004823 LPPOPUPMENU menu;
4824
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004825 TRACE("(0x%04x 0x%08lx)\n", hMenu, dwContextHelpID);
Juergen Schmied78513941999-04-18 14:40:32 +00004826
Gerard Patel3e629742000-01-17 22:22:16 +00004827 if ((menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004828 {
4829 menu->dwContextHelpID = dwContextHelpID;
4830 return TRUE;
4831 }
4832 return FALSE;
Paul Quinn1beaae51998-12-15 15:38:36 +00004833}
4834
4835/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00004836 * GetMenuContextHelpId (USER.385)
Paul Quinn1beaae51998-12-15 15:38:36 +00004837 */
4838DWORD WINAPI GetMenuContextHelpId16( HMENU16 hMenu )
4839{
Juergen Schmied78513941999-04-18 14:40:32 +00004840 return GetMenuContextHelpId( hMenu );
Paul Quinn1beaae51998-12-15 15:38:36 +00004841}
4842
4843/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004844 * GetMenuContextHelpId (USER32.@)
Paul Quinn1beaae51998-12-15 15:38:36 +00004845 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004846DWORD WINAPI GetMenuContextHelpId( HMENU hMenu )
Paul Quinn1beaae51998-12-15 15:38:36 +00004847{
Juergen Schmied78513941999-04-18 14:40:32 +00004848 LPPOPUPMENU menu;
4849
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004850 TRACE("(0x%04x)\n", hMenu);
Juergen Schmied78513941999-04-18 14:40:32 +00004851
Gerard Patel3e629742000-01-17 22:22:16 +00004852 if ((menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004853 {
4854 return menu->dwContextHelpID;
4855 }
4856 return 0;
Paul Quinn1beaae51998-12-15 15:38:36 +00004857}
Eric Pouech0c62bf01999-09-13 15:11:35 +00004858
4859/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00004860 * MenuItemFromPoint (USER32.@)
Eric Pouech0c62bf01999-09-13 15:11:35 +00004861 */
4862UINT WINAPI MenuItemFromPoint(HWND hWnd, HMENU hMenu, POINT ptScreen)
4863{
4864 FIXME("(0x%04x,0x%04x,(%ld,%ld)):stub\n",
4865 hWnd, hMenu, ptScreen.x, ptScreen.y);
4866 return 0;
4867}
Dmitry Timoshkovef559322000-10-26 21:47:20 +00004868
4869
4870/**********************************************************************
4871 * translate_accelerator
4872 */
4873static BOOL translate_accelerator( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam,
4874 BYTE fVirt, WORD key, WORD cmd )
4875{
4876 UINT mesg = 0;
4877
4878 if (wParam != key) return FALSE;
4879
4880 if (message == WM_CHAR)
4881 {
4882 if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) )
4883 {
4884 TRACE_(accel)("found accel for WM_CHAR: ('%c')\n", wParam & 0xff);
4885 goto found;
4886 }
4887 }
4888 else
4889 {
4890 if(fVirt & FVIRTKEY)
4891 {
4892 INT mask = 0;
4893 TRACE_(accel)("found accel for virt_key %04x (scan %04x)\n",
4894 wParam, 0xff & HIWORD(lParam));
4895 if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
4896 if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
4897 if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT;
4898 if(mask == (fVirt & (FSHIFT | FCONTROL | FALT))) goto found;
4899 TRACE_(accel)(", but incorrect SHIFT/CTRL/ALT-state\n");
4900 }
4901 else
4902 {
4903 if (!(lParam & 0x01000000)) /* no special_key */
4904 {
4905 if ((fVirt & FALT) && (lParam & 0x20000000))
4906 { /* ^^ ALT pressed */
4907 TRACE_(accel)("found accel for Alt-%c\n", wParam & 0xff);
4908 goto found;
4909 }
4910 }
4911 }
4912 }
4913 return FALSE;
4914
4915 found:
4916 if (message == WM_KEYUP || message == WM_SYSKEYUP)
4917 mesg = 1;
4918 else if (GetCapture())
4919 mesg = 2;
4920 else if (!IsWindowEnabled(hWnd))
4921 mesg = 3;
4922 else
4923 {
4924 HMENU hMenu, hSubMenu, hSysMenu;
4925 UINT uSysStat = (UINT)-1, uStat = (UINT)-1, nPos;
4926 WND* wndPtr = WIN_FindWndPtr(hWnd);
4927
4928 hMenu = (wndPtr->dwStyle & WS_CHILD) ? 0 : (HMENU)wndPtr->wIDmenu;
4929 hSysMenu = wndPtr->hSysMenu;
4930 WIN_ReleaseWndPtr(wndPtr);
4931
4932 /* find menu item and ask application to initialize it */
4933 /* 1. in the system menu */
4934 hSubMenu = hSysMenu;
4935 nPos = cmd;
4936 if(MENU_FindItem(&hSubMenu, &nPos, MF_BYCOMMAND))
4937 {
4938 SendMessageA(hWnd, WM_INITMENU, (WPARAM)hSysMenu, 0L);
4939 if(hSubMenu != hSysMenu)
4940 {
4941 nPos = MENU_FindSubMenu(&hSysMenu, hSubMenu);
4942 TRACE_(accel)("hSysMenu = %04x, hSubMenu = %04x, nPos = %d\n", hSysMenu, hSubMenu, nPos);
4943 SendMessageA(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, TRUE));
4944 }
4945 uSysStat = GetMenuState(GetSubMenu(hSysMenu, 0), cmd, MF_BYCOMMAND);
4946 }
4947 else /* 2. in the window's menu */
4948 {
4949 hSubMenu = hMenu;
4950 nPos = cmd;
4951 if(MENU_FindItem(&hSubMenu, &nPos, MF_BYCOMMAND))
4952 {
4953 SendMessageA(hWnd, WM_INITMENU, (WPARAM)hMenu, 0L);
4954 if(hSubMenu != hMenu)
4955 {
4956 nPos = MENU_FindSubMenu(&hMenu, hSubMenu);
4957 TRACE_(accel)("hMenu = %04x, hSubMenu = %04x, nPos = %d\n", hMenu, hSubMenu, nPos);
4958 SendMessageA(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, FALSE));
4959 }
4960 uStat = GetMenuState(hMenu, cmd, MF_BYCOMMAND);
4961 }
4962 }
4963
4964 if (uSysStat != (UINT)-1)
4965 {
4966 if (uSysStat & (MF_DISABLED|MF_GRAYED))
4967 mesg=4;
4968 else
4969 mesg=WM_SYSCOMMAND;
4970 }
4971 else
4972 {
4973 if (uStat != (UINT)-1)
4974 {
4975 if (IsIconic(hWnd))
4976 mesg=5;
4977 else
4978 {
4979 if (uStat & (MF_DISABLED|MF_GRAYED))
4980 mesg=6;
4981 else
4982 mesg=WM_COMMAND;
4983 }
4984 }
4985 else
4986 mesg=WM_COMMAND;
4987 }
4988 }
4989
4990 if( mesg==WM_COMMAND )
4991 {
4992 TRACE_(accel)(", sending WM_COMMAND, wParam=%0x\n", 0x10000 | cmd);
4993 SendMessageA(hWnd, mesg, 0x10000 | cmd, 0L);
4994 }
4995 else if( mesg==WM_SYSCOMMAND )
4996 {
4997 TRACE_(accel)(", sending WM_SYSCOMMAND, wParam=%0x\n", cmd);
4998 SendMessageA(hWnd, mesg, cmd, 0x00010000L);
4999 }
5000 else
5001 {
5002 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
5003 * #0: unknown (please report!)
5004 * #1: for WM_KEYUP,WM_SYSKEYUP
5005 * #2: mouse is captured
5006 * #3: window is disabled
5007 * #4: it's a disabled system menu option
5008 * #5: it's a menu option, but window is iconic
5009 * #6: it's a menu option, but disabled
5010 */
5011 TRACE_(accel)(", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg);
5012 if(mesg==0)
5013 ERR_(accel)(" unknown reason - please report!");
5014 }
5015 return TRUE;
5016}
5017
5018/**********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00005019 * TranslateAccelerator (USER32.@)
Patrik Stridvall15a3b742001-04-27 18:03:51 +00005020 * TranslateAcceleratorW (USER32.@)
Dmitry Timoshkovef559322000-10-26 21:47:20 +00005021 */
5022INT WINAPI TranslateAccelerator( HWND hWnd, HACCEL hAccel, LPMSG msg )
5023{
5024 /* YES, Accel16! */
5025 LPACCEL16 lpAccelTbl;
5026 int i;
5027
5028 if (msg == NULL)
5029 {
5030 WARN_(accel)("msg null; should hang here to be win compatible\n");
5031 return 0;
5032 }
5033 if (!hAccel || !(lpAccelTbl = (LPACCEL16) LockResource16(hAccel)))
5034 {
5035 WARN_(accel)("invalid accel handle=%x\n", hAccel);
5036 return 0;
5037 }
5038 if ((msg->message != WM_KEYDOWN &&
5039 msg->message != WM_KEYUP &&
5040 msg->message != WM_SYSKEYDOWN &&
5041 msg->message != WM_SYSKEYUP &&
5042 msg->message != WM_CHAR)) return 0;
5043
5044 TRACE_(accel)("TranslateAccelerators hAccel=%04x, hWnd=%04x,"
5045 "msg->hwnd=%04x, msg->message=%04x, wParam=%08x, lParam=%lx\n",
5046 hAccel,hWnd,msg->hwnd,msg->message,msg->wParam,msg->lParam);
5047
5048 i = 0;
5049 do
5050 {
5051 if (translate_accelerator( hWnd, msg->message, msg->wParam, msg->lParam,
5052 lpAccelTbl[i].fVirt, lpAccelTbl[i].key, lpAccelTbl[i].cmd))
5053 return 1;
5054 } while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
5055 WARN_(accel)("couldn't translate accelerator key\n");
5056 return 0;
5057}
5058
5059
5060/**********************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +00005061 * TranslateAccelerator (USER.178)
Dmitry Timoshkovef559322000-10-26 21:47:20 +00005062 */
5063INT16 WINAPI TranslateAccelerator16( HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg )
5064{
5065 LPACCEL16 lpAccelTbl;
5066 int i;
5067
5068 if (msg == NULL)
5069 {
5070 WARN_(accel)("msg null; should hang here to be win compatible\n");
5071 return 0;
5072 }
5073 if (!hAccel || !(lpAccelTbl = (LPACCEL16) LockResource16(hAccel)))
5074 {
5075 WARN_(accel)("invalid accel handle=%x\n", hAccel);
5076 return 0;
5077 }
5078 if ((msg->message != WM_KEYDOWN &&
5079 msg->message != WM_KEYUP &&
5080 msg->message != WM_SYSKEYDOWN &&
5081 msg->message != WM_SYSKEYUP &&
5082 msg->message != WM_CHAR)) return 0;
5083
5084 TRACE_(accel)("TranslateAccelerators hAccel=%04x, hWnd=%04x,"
5085 "msg->hwnd=%04x, msg->message=%04x, wParam=%04x, lParam=%lx\n",
5086 hAccel,hWnd,msg->hwnd,msg->message,msg->wParam,msg->lParam);
5087
5088 i = 0;
5089 do
5090 {
5091 if (translate_accelerator( hWnd, msg->message, msg->wParam, msg->lParam,
5092 lpAccelTbl[i].fVirt, lpAccelTbl[i].key, lpAccelTbl[i].cmd ))
5093 return 1;
5094 } while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
5095 WARN_(accel)("couldn't translate accelerator key\n");
5096 return 0;
5097}