blob: d3b303637e37403291655ff40eaa7a76c13da6e2 [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"
21#include "wingdi.h"
Francois Boisvert85dd9fc1999-02-17 12:50:11 +000022#include "wine/winbase16.h"
Michael Veksler3fbb8dc1999-02-21 18:23:26 +000023#include "wine/winuser16.h"
Alexandre Julliard072dfb52000-09-25 23:30:56 +000024#include "wine/winestring.h"
Jeremy Whited3e22d92000-02-10 19:03:02 +000025#include "win.h"
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000026#include "task.h"
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000027#include "heap.h"
Francois Boisvert197a8e11999-02-13 09:10:17 +000028#include "menu.h"
Alexandre Julliardc6c09441997-01-12 18:32:19 +000029#include "nonclient.h"
Alexandre Julliard1f579291994-05-25 16:25:21 +000030#include "user.h"
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +000031#include "message.h"
Patrik Stridvall6cc47d42000-03-08 18:26:56 +000032#include "queue.h"
Alexandre Julliardd37eb361997-07-20 16:23:21 +000033#include "tweak.h"
Aric Stewartc946b1c2000-10-24 21:28:19 +000034#include "wine/unicode.h"
Marcus Meissnerd5e7c791998-12-09 11:06:00 +000035
Alexandre Julliard9fe7a251999-05-14 08:17:14 +000036#include "debugtools.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000037
Dmitry Timoshkovef559322000-10-26 21:47:20 +000038DEFAULT_DEBUG_CHANNEL(menu);
39DECLARE_DEBUG_CHANNEL(accel);
Alexandre Julliardd37eb361997-07-20 16:23:21 +000040
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000041/* internal popup menu window messages */
42
43#define MM_SETMENUHANDLE (WM_USER + 0)
44#define MM_GETMENUHANDLE (WM_USER + 1)
45
Alexandre Julliard2d93d001996-05-21 15:01:41 +000046/* Menu item structure */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000047typedef struct {
48 /* ----------- MENUITEMINFO Stuff ----------- */
Juergen Schmied78513941999-04-18 14:40:32 +000049 UINT fType; /* Item type. */
Alexandre Julliarda3960291999-02-26 11:11:13 +000050 UINT fState; /* Item state. */
51 UINT wID; /* Item id. */
52 HMENU hSubMenu; /* Pop-up menu. */
Juergen Schmied78513941999-04-18 14:40:32 +000053 HBITMAP hCheckBit; /* Bitmap when checked. */
Alexandre Julliarda3960291999-02-26 11:11:13 +000054 HBITMAP hUnCheckBit; /* Bitmap when unchecked. */
Aric Stewartc946b1c2000-10-24 21:28:19 +000055 LPWSTR text; /* Item text or bitmap handle. */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000056 DWORD dwItemData; /* Application defined. */
Juergen Schmied78513941999-04-18 14:40:32 +000057 DWORD dwTypeData; /* depends on fMask */
58 HBITMAP hbmpItem; /* bitmap in win98 style menus */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000059 /* ----------- Wine stuff ----------- */
Juergen Schmied78513941999-04-18 14:40:32 +000060 RECT rect; /* Item area (relative to menu window) */
61 UINT xTab; /* X position of text after Tab */
Alexandre Julliard2d93d001996-05-21 15:01:41 +000062} MENUITEM;
63
64/* Popup menu structure */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000065typedef struct {
Alexandre Julliard2d93d001996-05-21 15:01:41 +000066 WORD wFlags; /* Menu flags (MF_POPUP, MF_SYSMENU) */
67 WORD wMagic; /* Magic number */
Alexandre Julliardbf9130a1996-10-13 17:45:47 +000068 HQUEUE16 hTaskQ; /* Task queue for this menu */
Alexandre Julliard2d93d001996-05-21 15:01:41 +000069 WORD Width; /* Width of the whole menu */
70 WORD Height; /* Height of the whole menu */
71 WORD nItems; /* Number of items in the menu */
Juergen Schmied78513941999-04-18 14:40:32 +000072 HWND hWnd; /* Window containing the menu */
73 MENUITEM *items; /* Array of menu items */
74 UINT FocusedItem; /* Currently focused item */
Juergen Schmied466a6521999-05-02 11:21:08 +000075 HWND hwndOwner; /* window receiving the messages for ownerdraw */
Pascal Lessard2eb0a301999-09-03 16:38:52 +000076 BOOL bTimeToHide; /* Request hiding when receiving a second click in the top-level menu item */
Juergen Schmied78513941999-04-18 14:40:32 +000077 /* ------------ MENUINFO members ------ */
78 DWORD dwStyle; /* Extended mennu style */
79 UINT cyMax; /* max hight of the whole menu, 0 is screen hight */
80 HBRUSH hbrBack; /* brush for menu background */
81 DWORD dwContextHelpID;
82 DWORD dwMenuData; /* application defined value */
Pascal Lessardd814bb61999-07-31 13:02:02 +000083 HMENU hSysMenuOwner; /* Handle to the dummy sys menu holder */
Alexandre Julliard2d93d001996-05-21 15:01:41 +000084} POPUPMENU, *LPPOPUPMENU;
85
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000086/* internal flags for menu tracking */
87
88#define TF_ENDMENU 0x0001
89#define TF_SUSPENDPOPUP 0x0002
90#define TF_SKIPREMOVE 0x0004
91
92typedef struct
93{
Alexandre Julliarda3960291999-02-26 11:11:13 +000094 UINT trackFlags;
95 HMENU hCurrentMenu; /* current submenu (can be equal to hTopMenu)*/
96 HMENU hTopMenu; /* initial menu */
97 HWND hOwnerWnd; /* where notifications are sent */
98 POINT pt;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000099} MTRACKER;
100
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000101#define MENU_MAGIC 0x554d /* 'MU' */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000102#define IS_A_MENU(pmenu) ((pmenu) && (pmenu)->wMagic == MENU_MAGIC)
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000103
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000104#define ITEM_PREV -1
105#define ITEM_NEXT 1
106
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000107 /* Internal MENU_TrackMenu() flags */
108#define TPM_INTERNAL 0xF0000000
109#define TPM_ENTERIDLEEX 0x80000000 /* set owner window for WM_ENTERIDLE */
110#define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */
Francois Boisvert85dd9fc1999-02-17 12:50:11 +0000111#define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */
Alexandre Julliardf7207251994-07-23 07:57:48 +0000112
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000113 /* popup menu shade thickness */
114#define POPUP_XSHADE 4
115#define POPUP_YSHADE 4
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000116
Alexandre Julliardf7207251994-07-23 07:57:48 +0000117 /* Space between 2 menu bar items */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000118#define MENU_BAR_ITEMS_SPACE 12
Alexandre Julliardf7207251994-07-23 07:57:48 +0000119
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000120 /* Minimum width of a tab character */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000121#define MENU_TAB_SPACE 8
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000122
Alexandre Julliardf7207251994-07-23 07:57:48 +0000123 /* Height of a separator item */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000124#define SEPARATOR_HEIGHT 5
Alexandre Julliardf7207251994-07-23 07:57:48 +0000125
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000126 /* (other menu->FocusedItem values give the position of the focused item) */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000127#define NO_SELECTED_ITEM 0xffff
Alexandre Julliardcdd09231994-01-12 11:12:51 +0000128
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000129#define MENU_ITEM_TYPE(flags) \
130 ((flags) & (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR))
131
132#define IS_STRING_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_STRING)
Juergen Schmied78513941999-04-18 14:40:32 +0000133#define IS_BITMAP_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_BITMAP)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000134
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000135#define IS_SYSTEM_MENU(menu) \
136 (!((menu)->wFlags & MF_POPUP) && (menu)->wFlags & MF_SYSMENU)
Juergen Schmied78513941999-04-18 14:40:32 +0000137
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000138#define IS_SYSTEM_POPUP(menu) \
139 ((menu)->wFlags & MF_POPUP && (menu)->wFlags & MF_SYSMENU)
140
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000141#define TYPE_MASK (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
142 MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
143 MFT_RIGHTORDER | MFT_RIGHTJUSTIFY | \
144 MF_POPUP | MF_SYSMENU | MF_HELP)
145#define STATE_MASK (~TYPE_MASK)
146
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000147 /* Dimension of the menu bitmaps */
148static WORD check_bitmap_width = 0, check_bitmap_height = 0;
149static WORD arrow_bitmap_width = 0, arrow_bitmap_height = 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000150
Alexandre Julliarda3960291999-02-26 11:11:13 +0000151static HBITMAP hStdRadioCheck = 0;
152static HBITMAP hStdCheck = 0;
153static HBITMAP hStdMnArrow = 0;
Francois Boisvert8b391741999-02-09 14:09:55 +0000154
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +0000155/* Minimze/restore/close buttons to be inserted in menubar */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000156static HBITMAP hBmpMinimize = 0;
157static HBITMAP hBmpMinimizeD = 0;
158static HBITMAP hBmpMaximize = 0;
159static HBITMAP hBmpMaximizeD = 0;
160static HBITMAP hBmpClose = 0;
161static HBITMAP hBmpCloseD = 0;
Francois Boisvert308c6af1999-02-18 10:37:17 +0000162
Francois Boisvert8b391741999-02-09 14:09:55 +0000163
Juergen Schmied78513941999-04-18 14:40:32 +0000164static HBRUSH hShadeBrush = 0;
165static HFONT hMenuFont = 0;
Juergen Schmied466a6521999-05-02 11:21:08 +0000166static HFONT hMenuFontBold = 0;
Juergen Schmied78513941999-04-18 14:40:32 +0000167
Alexandre Julliarda3960291999-02-26 11:11:13 +0000168static HMENU MENU_DefSysPopup = 0; /* Default system menu popup */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000169
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000170/* Use global popup window because there's no way 2 menus can
171 * be tracked at the same time. */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000172
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000173static WND* pTopPopupWnd = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000174static UINT uSubPWndLevel = 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000175
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000176 /* Flag set by EndMenu() to force an exit from menu tracking */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000177static BOOL fEndMenu = FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000178
179
180/***********************************************************************
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000181 * debug_print_menuitem
182 *
183 * Print a menuitem in readable form.
184 */
185
Alexandre Julliard03468f71998-02-15 19:40:49 +0000186#define debug_print_menuitem(pre, mp, post) \
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000187 if(!TRACE_ON(menu)) ; else do_debug_print_menuitem(pre, mp, post)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000188
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000189#define MENUOUT(text) \
Alexandre Julliard15de6151999-08-04 12:22:42 +0000190 DPRINTF("%s%s", (count++ ? "," : ""), (text))
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000191
192#define MENUFLAG(bit,text) \
193 do { \
194 if (flags & (bit)) { flags &= ~(bit); MENUOUT ((text)); } \
195 } while (0)
196
Alexandre Julliard03468f71998-02-15 19:40:49 +0000197static void do_debug_print_menuitem(const char *prefix, MENUITEM * mp,
198 const char *postfix)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000199{
Alexandre Julliard15de6151999-08-04 12:22:42 +0000200 TRACE("%s ", prefix);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000201 if (mp) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000202 UINT flags = mp->fType;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000203 int typ = MENU_ITEM_TYPE(flags);
Alexandre Julliard15de6151999-08-04 12:22:42 +0000204 DPRINTF( "{ ID=0x%x", mp->wID);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000205 if (flags & MF_POPUP)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000206 DPRINTF( ", Sub=0x%x", mp->hSubMenu);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000207 if (flags) {
208 int count = 0;
Alexandre Julliard15de6151999-08-04 12:22:42 +0000209 DPRINTF( ", Typ=");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000210 if (typ == MFT_STRING)
211 /* Nothing */ ;
212 else if (typ == MFT_SEPARATOR)
213 MENUOUT("sep");
214 else if (typ == MFT_OWNERDRAW)
215 MENUOUT("own");
216 else if (typ == MFT_BITMAP)
217 MENUOUT("bit");
218 else
219 MENUOUT("???");
220 flags -= typ;
221
222 MENUFLAG(MF_POPUP, "pop");
223 MENUFLAG(MFT_MENUBARBREAK, "barbrk");
224 MENUFLAG(MFT_MENUBREAK, "brk");
225 MENUFLAG(MFT_RADIOCHECK, "radio");
226 MENUFLAG(MFT_RIGHTORDER, "rorder");
227 MENUFLAG(MF_SYSMENU, "sys");
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +0000228 MENUFLAG(MFT_RIGHTJUSTIFY, "right"); /* same as MF_HELP */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000229
230 if (flags)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000231 DPRINTF( "+0x%x", flags);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000232 }
233 flags = mp->fState;
234 if (flags) {
235 int count = 0;
Alexandre Julliard15de6151999-08-04 12:22:42 +0000236 DPRINTF( ", State=");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000237 MENUFLAG(MFS_GRAYED, "grey");
Juergen Schmied466a6521999-05-02 11:21:08 +0000238 MENUFLAG(MFS_DEFAULT, "default");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000239 MENUFLAG(MFS_DISABLED, "dis");
240 MENUFLAG(MFS_CHECKED, "check");
241 MENUFLAG(MFS_HILITE, "hi");
242 MENUFLAG(MF_USECHECKBITMAPS, "usebit");
243 MENUFLAG(MF_MOUSESELECT, "mouse");
244 if (flags)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000245 DPRINTF( "+0x%x", flags);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000246 }
247 if (mp->hCheckBit)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000248 DPRINTF( ", Chk=0x%x", mp->hCheckBit);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000249 if (mp->hUnCheckBit)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000250 DPRINTF( ", Unc=0x%x", mp->hUnCheckBit);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000251
252 if (typ == MFT_STRING) {
253 if (mp->text)
Aric Stewartc946b1c2000-10-24 21:28:19 +0000254 DPRINTF( ", Text=\"%s\"", debugstr_w(mp->text));
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000255 else
Alexandre Julliard15de6151999-08-04 12:22:42 +0000256 DPRINTF( ", Text=Null");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000257 } else if (mp->text == NULL)
258 /* Nothing */ ;
259 else
Alexandre Julliard15de6151999-08-04 12:22:42 +0000260 DPRINTF( ", Text=%p", mp->text);
Juergen Schmied7abca951999-04-11 17:02:30 +0000261 if (mp->dwItemData)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000262 DPRINTF( ", ItemData=0x%08lx", mp->dwItemData);
263 DPRINTF( " }");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000264 } else {
Alexandre Julliard15de6151999-08-04 12:22:42 +0000265 DPRINTF( "NULL");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000266 }
Alexandre Julliard03468f71998-02-15 19:40:49 +0000267
Alexandre Julliard15de6151999-08-04 12:22:42 +0000268 DPRINTF(" %s\n", postfix);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000269}
270
271#undef MENUOUT
272#undef MENUFLAG
273
Gerard Patel3e629742000-01-17 22:22:16 +0000274
275/***********************************************************************
276 * MENU_GetMenu
277 *
278 * Validate the given menu handle and returns the menu structure pointer.
279 */
280POPUPMENU *MENU_GetMenu(HMENU hMenu)
281{
282 POPUPMENU *menu;
283 menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(hMenu);
284 if (!IS_A_MENU(menu))
285 {
Gerard Patelc6369b02000-05-14 22:52:52 +0000286 WARN("invalid menu handle=%x, ptr=%p, magic=%x\n", hMenu, menu, menu? menu->wMagic:0);
Gerard Patel3e629742000-01-17 22:22:16 +0000287 menu = NULL;
288 }
289 return menu;
290}
291
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000292/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000293 * MENU_CopySysPopup
294 *
295 * Return the default system menu.
296 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000297static HMENU MENU_CopySysPopup(void)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000298{
Bertho Stultiensd1895a71999-04-25 18:31:35 +0000299 HMENU hMenu = LoadMenuA(GetModuleHandleA("USER32"), "SYSMENU");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000300
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000301 if( hMenu ) {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000302 POPUPMENU* menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(hMenu);
303 menu->wFlags |= MF_SYSMENU | MF_POPUP;
Juergen Schmied49251861999-05-13 18:42:03 +0000304 SetMenuDefaultItem(hMenu, SC_CLOSE, FALSE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000305 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000306 else {
307 hMenu = 0;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000308 ERR("Unable to load default system menu\n" );
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000309 }
310
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000311 TRACE("returning %x.\n", hMenu );
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000312
313 return hMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000314}
315
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000316/***********************************************************************
317 * MENU_GetTopPopupWnd()
318 *
319 * Return the locked pointer pTopPopupWnd.
320 */
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000321static WND *MENU_GetTopPopupWnd()
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000322{
323 return WIN_LockWndPtr(pTopPopupWnd);
324}
325/***********************************************************************
326 * MENU_ReleaseTopPopupWnd()
327 *
328 * Realease the locked pointer pTopPopupWnd.
329 */
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000330static void MENU_ReleaseTopPopupWnd()
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000331{
332 WIN_ReleaseWndPtr(pTopPopupWnd);
333}
334/***********************************************************************
335 * MENU_DestroyTopPopupWnd()
336 *
337 * Destroy the locked pointer pTopPopupWnd.
338 */
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000339static void MENU_DestroyTopPopupWnd()
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000340{
341 WND *tmpWnd = pTopPopupWnd;
342 pTopPopupWnd = NULL;
343 WIN_ReleaseWndPtr(tmpWnd);
344}
345
346
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000347
348/**********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000349 * MENU_GetSysMenu
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000350 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000351 * Create a copy of the system menu. System menu in Windows is
352 * a special menu-bar with the single entry - system menu popup.
353 * This popup is presented to the outside world as a "system menu".
354 * However, the real system menu handle is sometimes seen in the
355 * WM_MENUSELECT paramemters (and Word 6 likes it this way).
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000356 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000357HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu )
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000358{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000359 HMENU hMenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000360
Alexandre Julliarda3960291999-02-26 11:11:13 +0000361 if ((hMenu = CreateMenu()))
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000362 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000363 POPUPMENU *menu = (POPUPMENU*) USER_HEAP_LIN_ADDR(hMenu);
364 menu->wFlags = MF_SYSMENU;
365 menu->hWnd = hWnd;
366
Alexandre Julliarda3960291999-02-26 11:11:13 +0000367 if (hPopupMenu == (HMENU)(-1))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000368 hPopupMenu = MENU_CopySysPopup();
369 else if( !hPopupMenu ) hPopupMenu = MENU_DefSysPopup;
370
371 if (hPopupMenu)
372 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000373 InsertMenuA( hMenu, -1, MF_SYSMENU | MF_POPUP | MF_BYPOSITION, hPopupMenu, NULL );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000374
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000375 menu->items[0].fType = MF_SYSMENU | MF_POPUP;
376 menu->items[0].fState = 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000377 menu = (POPUPMENU*) USER_HEAP_LIN_ADDR(hPopupMenu);
378 menu->wFlags |= MF_SYSMENU;
379
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000380 TRACE("GetSysMenu hMenu=%04x (%04x)\n", hMenu, hPopupMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000381 return hMenu;
382 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000383 DestroyMenu( hMenu );
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000384 }
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000385 ERR("failed to load system menu!\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000386 return 0;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000387}
388
389
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000390/***********************************************************************
391 * MENU_Init
392 *
393 * Menus initialisation.
394 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000395BOOL MENU_Init()
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000396{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000397 HBITMAP hBitmap;
Juergen Schmied78513941999-04-18 14:40:32 +0000398 NONCLIENTMETRICSA ncm;
399
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000400 static unsigned char shade_bits[16] = { 0x55, 0, 0xAA, 0,
401 0x55, 0, 0xAA, 0,
402 0x55, 0, 0xAA, 0,
403 0x55, 0, 0xAA, 0 };
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000404
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000405 /* Load menu bitmaps */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000406 hStdCheck = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_CHECK));
407 hStdRadioCheck = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_RADIOCHECK));
408 hStdMnArrow = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_MNARROW));
Francois Boisvert8b391741999-02-09 14:09:55 +0000409 /* Load system buttons bitmaps */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000410 hBmpMinimize = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_REDUCE));
411 hBmpMinimizeD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_REDUCED));
412 hBmpMaximize = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_RESTORE));
413 hBmpMaximizeD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_RESTORED));
414 hBmpClose = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_CLOSE));
415 hBmpCloseD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_CLOSED));
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000416
417 if (hStdCheck)
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000418 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000419 BITMAP bm;
420 GetObjectA( hStdCheck, sizeof(bm), &bm );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000421 check_bitmap_width = bm.bmWidth;
422 check_bitmap_height = bm.bmHeight;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000423 } else
424 return FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000425
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000426 /* Assume that radio checks have the same size as regular check. */
427 if (!hStdRadioCheck)
428 return FALSE;
429
430 if (hStdMnArrow)
Juergen Schmied78513941999-04-18 14:40:32 +0000431 {
432 BITMAP bm;
433 GetObjectA( hStdMnArrow, sizeof(bm), &bm );
434 arrow_bitmap_width = bm.bmWidth;
435 arrow_bitmap_height = bm.bmHeight;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000436 } else
Juergen Schmied78513941999-04-18 14:40:32 +0000437 return FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000438
Juergen Schmied78513941999-04-18 14:40:32 +0000439 if (! (hBitmap = CreateBitmap( 8, 8, 1, 1, shade_bits)))
440 return FALSE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000441
Juergen Schmied78513941999-04-18 14:40:32 +0000442 if(!(hShadeBrush = CreatePatternBrush( hBitmap )))
443 return FALSE;
444
445 DeleteObject( hBitmap );
446 if (!(MENU_DefSysPopup = MENU_CopySysPopup()))
447 return FALSE;
448
449 ncm.cbSize = sizeof (NONCLIENTMETRICSA);
450 if (!(SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &ncm, 0)))
451 return FALSE;
452
453 if (!(hMenuFont = CreateFontIndirectA( &ncm.lfMenuFont )))
454 return FALSE;
455
Juergen Schmied466a6521999-05-02 11:21:08 +0000456 ncm.lfMenuFont.lfWeight += 300;
457 if ( ncm.lfMenuFont.lfWeight > 1000)
458 ncm.lfMenuFont.lfWeight = 1000;
459
460 if (!(hMenuFontBold = CreateFontIndirectA( &ncm.lfMenuFont )))
461 return FALSE;
462
Juergen Schmied78513941999-04-18 14:40:32 +0000463 return TRUE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000464}
465
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000466/***********************************************************************
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000467 * MENU_InitSysMenuPopup
468 *
469 * Grey the appropriate items in System menu.
470 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000471static void MENU_InitSysMenuPopup( HMENU hmenu, DWORD style, DWORD clsStyle )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000472{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000473 BOOL gray;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000474
475 gray = !(style & WS_THICKFRAME) || (style & (WS_MAXIMIZE | WS_MINIMIZE));
Alexandre Julliarda3960291999-02-26 11:11:13 +0000476 EnableMenuItem( hmenu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000477 gray = ((style & WS_MAXIMIZE) != 0);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000478 EnableMenuItem( hmenu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000479 gray = !(style & WS_MINIMIZEBOX) || (style & WS_MINIMIZE);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000480 EnableMenuItem( hmenu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000481 gray = !(style & WS_MAXIMIZEBOX) || (style & WS_MAXIMIZE);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000482 EnableMenuItem( hmenu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000483 gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE));
Alexandre Julliarda3960291999-02-26 11:11:13 +0000484 EnableMenuItem( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000485 gray = (clsStyle & CS_NOCLOSE) != 0;
Pascal Lessardd814bb61999-07-31 13:02:02 +0000486
487 /* The menu item must keep its state if it's disabled */
488 if(gray)
489 EnableMenuItem( hmenu, SC_CLOSE, MF_GRAYED);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000490}
491
492
Alexandre Julliard641ee761997-08-04 16:34:36 +0000493/******************************************************************************
494 *
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000495 * UINT MENU_GetStartOfNextColumn(
496 * HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000497 *
498 *****************************************************************************/
499
Alexandre Julliarda3960291999-02-26 11:11:13 +0000500static UINT MENU_GetStartOfNextColumn(
501 HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000502{
503 POPUPMENU *menu = (POPUPMENU *)USER_HEAP_LIN_ADDR(hMenu);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000504 UINT i = menu->FocusedItem + 1;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000505
506 if(!menu)
507 return NO_SELECTED_ITEM;
508
509 if( i == NO_SELECTED_ITEM )
510 return i;
511
512 for( ; i < menu->nItems; ++i ) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000513 if (menu->items[i].fType & MF_MENUBARBREAK)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000514 return i;
515 }
516
517 return NO_SELECTED_ITEM;
518}
519
520
521/******************************************************************************
522 *
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000523 * UINT MENU_GetStartOfPrevColumn(
524 * HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000525 *
526 *****************************************************************************/
527
Alexandre Julliarda3960291999-02-26 11:11:13 +0000528static UINT MENU_GetStartOfPrevColumn(
529 HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000530{
531 POPUPMENU const *menu = (POPUPMENU *)USER_HEAP_LIN_ADDR(hMenu);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000532 UINT i;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000533
534 if( !menu )
535 return NO_SELECTED_ITEM;
536
537 if( menu->FocusedItem == 0 || menu->FocusedItem == NO_SELECTED_ITEM )
538 return NO_SELECTED_ITEM;
539
540 /* Find the start of the column */
541
542 for(i = menu->FocusedItem; i != 0 &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000543 !(menu->items[i].fType & MF_MENUBARBREAK);
Alexandre Julliard641ee761997-08-04 16:34:36 +0000544 --i); /* empty */
545
546 if(i == 0)
547 return NO_SELECTED_ITEM;
548
549 for(--i; i != 0; --i) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000550 if (menu->items[i].fType & MF_MENUBARBREAK)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000551 break;
552 }
553
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000554 TRACE("ret %d.\n", i );
Alexandre Julliard641ee761997-08-04 16:34:36 +0000555
556 return i;
557}
558
559
560
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000561/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000562 * MENU_FindItem
563 *
564 * Find a menu item. Return a pointer on the item, and modifies *hmenu
565 * in case the item was in a sub-menu.
566 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000567static MENUITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000568{
569 POPUPMENU *menu;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000570 UINT i;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000571
Gerard Patel3e629742000-01-17 22:22:16 +0000572 if (((*hmenu)==0xffff) || (!(menu = MENU_GetMenu(*hmenu)))) return NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000573 if (wFlags & MF_BYPOSITION)
574 {
575 if (*nPos >= menu->nItems) return NULL;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000576 return &menu->items[*nPos];
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000577 }
578 else
579 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000580 MENUITEM *item = menu->items;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000581 for (i = 0; i < menu->nItems; i++, item++)
582 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000583 if (item->wID == *nPos)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000584 {
585 *nPos = i;
586 return item;
587 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000588 else if (item->fType & MF_POPUP)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000589 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000590 HMENU hsubmenu = item->hSubMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000591 MENUITEM *subitem = MENU_FindItem( &hsubmenu, nPos, wFlags );
592 if (subitem)
593 {
594 *hmenu = hsubmenu;
595 return subitem;
596 }
597 }
598 }
599 }
600 return NULL;
601}
602
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000603/***********************************************************************
Rein Klazes80c924f1999-12-12 19:40:46 +0000604 * MENU_FindSubMenu
605 *
606 * Find a Sub menu. Return the position of the submenu, and modifies
607 * *hmenu in case it is found in another sub-menu.
608 * If the submenu cannot be found, NO_SELECTED_ITEM is returned.
609 */
610UINT MENU_FindSubMenu( HMENU *hmenu, HMENU hSubTarget )
611{
612 POPUPMENU *menu;
613 UINT i;
614 MENUITEM *item;
615 if (((*hmenu)==0xffff) ||
Gerard Patel3e629742000-01-17 22:22:16 +0000616 (!(menu = MENU_GetMenu(*hmenu))))
Rein Klazes80c924f1999-12-12 19:40:46 +0000617 return NO_SELECTED_ITEM;
618 item = menu->items;
619 for (i = 0; i < menu->nItems; i++, item++) {
620 if(!(item->fType & MF_POPUP)) continue;
621 if (item->hSubMenu == hSubTarget) {
622 return i;
623 }
624 else {
625 HMENU hsubmenu = item->hSubMenu;
626 UINT pos = MENU_FindSubMenu( &hsubmenu, hSubTarget );
627 if (pos != NO_SELECTED_ITEM) {
628 *hmenu = hsubmenu;
629 return pos;
630 }
631 }
632 }
633 return NO_SELECTED_ITEM;
634}
635
636/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000637 * MENU_FreeItemData
638 */
639static void MENU_FreeItemData( MENUITEM* item )
640{
641 /* delete text */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000642 if (IS_STRING_ITEM(item->fType) && item->text)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000643 HeapFree( SystemHeap, 0, item->text );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000644}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000645
646/***********************************************************************
647 * MENU_FindItemByCoords
648 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000649 * Find the item at the specified coordinates (screen coords). Does
650 * not work for child windows and therefore should not be called for
651 * an arbitrary system menu.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000652 */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000653static MENUITEM *MENU_FindItemByCoords( POPUPMENU *menu,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000654 POINT pt, UINT *pos )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000655{
656 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000657 UINT i;
Marcus Meissnerac593bb1999-03-17 15:18:28 +0000658 RECT wrect;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000659
Marcus Meissnerac593bb1999-03-17 15:18:28 +0000660 if (!GetWindowRect(menu->hWnd,&wrect)) return NULL;
661 pt.x -= wrect.left;pt.y -= wrect.top;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000662 item = menu->items;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000663 for (i = 0; i < menu->nItems; i++, item++)
664 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000665 if ((pt.x >= item->rect.left) && (pt.x < item->rect.right) &&
666 (pt.y >= item->rect.top) && (pt.y < item->rect.bottom))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000667 {
668 if (pos) *pos = i;
669 return item;
670 }
671 }
672 return NULL;
673}
674
675
676/***********************************************************************
677 * MENU_FindItemByKey
678 *
679 * Find the menu item selected by a key press.
680 * Return item id, -1 if none, -2 if we should close the menu.
681 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000682static UINT MENU_FindItemByKey( HWND hwndOwner, HMENU hmenu,
683 UINT key, BOOL forceMenuChar )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000684{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000685 TRACE("\tlooking for '%c' in [%04x]\n", (char)key, (UINT16)hmenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000686
Alexandre Julliarda3960291999-02-26 11:11:13 +0000687 if (!IsMenu( hmenu ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000688 {
689 WND* w = WIN_FindWndPtr(hwndOwner);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000690 hmenu = GetSubMenu(w->hSysMenu, 0);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000691 WIN_ReleaseWndPtr(w);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000692 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000693
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000694 if (hmenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000695 {
Gerard Patel3e629742000-01-17 22:22:16 +0000696 POPUPMENU *menu = MENU_GetMenu( hmenu );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000697 MENUITEM *item = menu->items;
698 LONG menuchar;
699
700 if( !forceMenuChar )
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000701 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000702 UINT i;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000703
704 key = toupper(key);
705 for (i = 0; i < menu->nItems; i++, item++)
706 {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000707 if (item->text && (IS_STRING_ITEM(item->fType)))
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000708 {
Aric Stewartc946b1c2000-10-24 21:28:19 +0000709 WCHAR *p = item->text - 2;
Norman Stevensa83d0651998-10-12 07:25:35 +0000710 do
711 {
Aric Stewartc946b1c2000-10-24 21:28:19 +0000712 p = strchrW (p + 2, '&');
Norman Stevensa83d0651998-10-12 07:25:35 +0000713 }
714 while (p != NULL && p [1] == '&');
715 if (p && (toupper(p[1]) == key)) return i;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000716 }
717 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000718 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000719 menuchar = SendMessageA( hwndOwner, WM_MENUCHAR,
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000720 MAKEWPARAM( key, menu->wFlags ), hmenu );
721 if (HIWORD(menuchar) == 2) return LOWORD(menuchar);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000722 if (HIWORD(menuchar) == 1) return (UINT)(-2);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000723 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000724 return (UINT)(-1);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000725}
Francois Boisvert8b391741999-02-09 14:09:55 +0000726/***********************************************************************
727 * MENU_LoadMagicItem
728 *
729 * Load the bitmap associated with the magic menu item and its style
730 */
Alexandre Julliarddba420a1994-02-02 06:48:31 +0000731
Juergen Schmied78513941999-04-18 14:40:32 +0000732static HBITMAP MENU_LoadMagicItem(UINT id, BOOL hilite, DWORD dwItemData)
Francois Boisvert8b391741999-02-09 14:09:55 +0000733{
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +0000734 /*
735 * Magic menu item id's section
736 * These magic id's are used by windows to insert "standard" mdi
737 * buttons (minimize,restore,close) on menu. Under windows,
738 * these magic id's make sure the right things appear when those
739 * bitmap buttons are pressed/selected/released.
740 */
Francois Boisvert8b391741999-02-09 14:09:55 +0000741
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +0000742 switch(id & 0xffff)
Juergen Schmied78513941999-04-18 14:40:32 +0000743 { case HBMMENU_SYSTEM:
744 return (dwItemData) ?
745 (HBITMAP)dwItemData :
746 (hilite ? hBmpMinimizeD : hBmpMinimize);
747 case HBMMENU_MBAR_RESTORE:
748 return (hilite ? hBmpMaximizeD: hBmpMaximize);
749 case HBMMENU_MBAR_MINIMIZE:
750 return (hilite ? hBmpMinimizeD : hBmpMinimize);
751 case HBMMENU_MBAR_CLOSE:
752 return (hilite ? hBmpCloseD : hBmpClose);
753 case HBMMENU_CALLBACK:
754 case HBMMENU_MBAR_CLOSE_D:
755 case HBMMENU_MBAR_MINIMIZE_D:
756 case HBMMENU_POPUP_CLOSE:
757 case HBMMENU_POPUP_RESTORE:
758 case HBMMENU_POPUP_MAXIMIZE:
759 case HBMMENU_POPUP_MINIMIZE:
760 default:
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000761 FIXME("Magic 0x%08x not implemented\n", id);
Juergen Schmied78513941999-04-18 14:40:32 +0000762 return 0;
Francois Boisvert8b391741999-02-09 14:09:55 +0000763 }
764
765}
Alexandre Julliardf7207251994-07-23 07:57:48 +0000766
767/***********************************************************************
768 * MENU_CalcItemSize
769 *
770 * Calculate the size of the menu item and store it in lpitem->rect.
771 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000772static void MENU_CalcItemSize( HDC hdc, MENUITEM *lpitem, HWND hwndOwner,
773 INT orgX, INT orgY, BOOL menuBar )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000774{
Aric Stewartc946b1c2000-10-24 21:28:19 +0000775 WCHAR *p;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000776
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000777 TRACE("dc=0x%04x owner=0x%04x (%d,%d)\n", hdc, hwndOwner, orgX, orgY);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000778 debug_print_menuitem("MENU_CalcItemSize: menuitem:", lpitem,
779 (menuBar ? " (MenuBar)" : ""));
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000780
Alexandre Julliarda3960291999-02-26 11:11:13 +0000781 SetRect( &lpitem->rect, orgX, orgY, orgX, orgY );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000782
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000783 if (lpitem->fType & MF_OWNERDRAW)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000784 {
Ken Thomases130f0d82000-05-10 21:38:37 +0000785 /*
786 ** Experimentation under Windows reveals that an owner-drawn
787 ** menu is expected to return the size of the content part of
788 ** the menu item, not including the checkmark nor the submenu
789 ** arrow. Windows adds those values itself and returns the
790 ** enlarged rectangle on subsequent WM_DRAWITEM messages.
791 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000792 MEASUREITEMSTRUCT mis;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000793 mis.CtlType = ODT_MENU;
Juergen Schmied7abca951999-04-11 17:02:30 +0000794 mis.CtlID = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000795 mis.itemID = lpitem->wID;
Juergen Schmied7abca951999-04-11 17:02:30 +0000796 mis.itemData = (DWORD)lpitem->dwItemData;
797 mis.itemHeight = 0;
798 mis.itemWidth = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000799 SendMessageA( hwndOwner, WM_MEASUREITEM, 0, (LPARAM)&mis );
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000800 lpitem->rect.right += mis.itemWidth;
Aric Stewart70cc1692000-05-10 21:54:07 +0000801
802 if (menuBar)
803 {
804 lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
805
806
807 /* under at least win95 you seem to be given a standard
808 height for the menu and the height value is ignored */
809
810 if (TWEAK_WineLook == WIN31_LOOK)
811 lpitem->rect.bottom += GetSystemMetrics(SM_CYMENU);
812 else
813 lpitem->rect.bottom += GetSystemMetrics(SM_CYMENU)-1;
814 }
815 else
816 lpitem->rect.bottom += mis.itemHeight;
817
818 TRACE("id=%04x size=%dx%d\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000819 lpitem->wID, mis.itemWidth, mis.itemHeight);
Ken Thomases130f0d82000-05-10 21:38:37 +0000820 /* Fall through to get check/arrow width calculation. */
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000821 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000822
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000823 if (lpitem->fType & MF_SEPARATOR)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000824 {
825 lpitem->rect.bottom += SEPARATOR_HEIGHT;
826 return;
827 }
828
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000829 if (!menuBar)
830 {
831 lpitem->rect.right += 2 * check_bitmap_width;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000832 if (lpitem->fType & MF_POPUP)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000833 lpitem->rect.right += arrow_bitmap_width;
834 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000835
Ken Thomases130f0d82000-05-10 21:38:37 +0000836 if (lpitem->fType & MF_OWNERDRAW)
837 return;
838
Juergen Schmied78513941999-04-18 14:40:32 +0000839 if (IS_BITMAP_ITEM(lpitem->fType))
Alexandre Julliardf7207251994-07-23 07:57:48 +0000840 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000841 BITMAP bm;
Juergen Schmied78513941999-04-18 14:40:32 +0000842 HBITMAP resBmp = 0;
Francois Boisvert8b391741999-02-09 14:09:55 +0000843
Patrik Stridvall1bb94031999-05-08 15:47:44 +0000844 /* Check if there is a magic menu item associated with this item */
Juergen Schmied78513941999-04-18 14:40:32 +0000845 if((LOWORD((int)lpitem->text))<12)
846 {
847 resBmp = MENU_LoadMagicItem((int)lpitem->text, (lpitem->fType & MF_HILITE),
848 lpitem->dwItemData);
Francois Boisvert8b391741999-02-09 14:09:55 +0000849 }
850 else
Alexandre Julliarda3960291999-02-26 11:11:13 +0000851 resBmp = (HBITMAP)lpitem->text;
Francois Boisvert8b391741999-02-09 14:09:55 +0000852
Alexandre Julliarda3960291999-02-26 11:11:13 +0000853 if (GetObjectA(resBmp, sizeof(bm), &bm ))
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000854 {
855 lpitem->rect.right += bm.bmWidth;
856 lpitem->rect.bottom += bm.bmHeight;
Francois Gouget75f9e642000-11-06 05:25:29 +0000857 if (TWEAK_WineLook == WIN98_LOOK) {
858 /* Leave space for the sunken border */
859 lpitem->rect.right += 2;
860 lpitem->rect.bottom += 2;
861 }
Francois Boisvert8b391741999-02-09 14:09:55 +0000862
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000863 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000864 }
865
Juergen Schmied78513941999-04-18 14:40:32 +0000866
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000867 /* If we get here, then it must be a text item */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000868 if (IS_STRING_ITEM( lpitem->fType ))
Juergen Schmied78513941999-04-18 14:40:32 +0000869 { SIZE size;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000870
Aric Stewartc946b1c2000-10-24 21:28:19 +0000871 GetTextExtentPoint32W(hdc, lpitem->text, strlenW(lpitem->text), &size);
Juergen Schmied78513941999-04-18 14:40:32 +0000872
873 lpitem->rect.right += size.cx;
874 if (TWEAK_WineLook == WIN31_LOOK)
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000875 lpitem->rect.bottom += max( size.cy, GetSystemMetrics(SM_CYMENU) );
Juergen Schmied78513941999-04-18 14:40:32 +0000876 else
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000877 lpitem->rect.bottom += max(size.cy, GetSystemMetrics(SM_CYMENU)-1);
Juergen Schmied78513941999-04-18 14:40:32 +0000878 lpitem->xTab = 0;
879
880 if (menuBar)
881 {
882 lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
883 }
Aric Stewartc946b1c2000-10-24 21:28:19 +0000884 else if ((p = strchrW( lpitem->text, '\t' )) != NULL)
Juergen Schmied78513941999-04-18 14:40:32 +0000885 {
886 /* Item contains a tab (only meaningful in popup menus) */
Aric Stewartc946b1c2000-10-24 21:28:19 +0000887 GetTextExtentPoint32W(hdc, lpitem->text, (int)(p - lpitem->text) , &size);
Juergen Schmied78513941999-04-18 14:40:32 +0000888 lpitem->xTab = check_bitmap_width + MENU_TAB_SPACE + size.cx;
889 lpitem->rect.right += MENU_TAB_SPACE;
890 }
891 else
892 {
Aric Stewartc946b1c2000-10-24 21:28:19 +0000893 if (strchrW( lpitem->text, '\b' ))
Juergen Schmied78513941999-04-18 14:40:32 +0000894 lpitem->rect.right += MENU_TAB_SPACE;
895 lpitem->xTab = lpitem->rect.right - check_bitmap_width
896 - arrow_bitmap_width;
897 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000898 }
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000899 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 +0000900}
901
902
903/***********************************************************************
904 * MENU_PopupMenuCalcSize
905 *
906 * Calculate the size of a popup menu.
907 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000908static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND hwndOwner )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000909{
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000910 MENUITEM *lpitem;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000911 HDC hdc;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000912 int start, i;
913 int orgX, orgY, maxX, maxTab, maxTabWidth;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000914
Alexandre Julliardf7207251994-07-23 07:57:48 +0000915 lppop->Width = lppop->Height = 0;
916 if (lppop->nItems == 0) return;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000917 hdc = GetDC( 0 );
Juergen Schmied78513941999-04-18 14:40:32 +0000918
919 SelectObject( hdc, hMenuFont);
920
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000921 start = 0;
Francois Gouget75f9e642000-11-06 05:25:29 +0000922 maxX = (TWEAK_WineLook == WIN31_LOOK) ? GetSystemMetrics(SM_CXBORDER) : 2+1 ;
Juergen Schmied466a6521999-05-02 11:21:08 +0000923
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000924 while (start < lppop->nItems)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000925 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000926 lpitem = &lppop->items[start];
Alexandre Julliardf7207251994-07-23 07:57:48 +0000927 orgX = maxX;
Marcus Meissnerddca3151999-05-22 11:33:23 +0000928 orgY = (TWEAK_WineLook == WIN31_LOOK) ? GetSystemMetrics(SM_CYBORDER) : 2;
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +0000929
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000930 maxTab = maxTabWidth = 0;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000931
932 /* Parse items until column break or end of menu */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000933 for (i = start; i < lppop->nItems; i++, lpitem++)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000934 {
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000935 if ((i != start) &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000936 (lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000937
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000938 MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, FALSE );
Pascal Lessard47274231999-02-13 12:21:46 +0000939
Juergen Schmied466a6521999-05-02 11:21:08 +0000940 if (lpitem->fType & MF_MENUBARBREAK) orgX++;
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000941 maxX = max( maxX, lpitem->rect.right );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000942 orgY = lpitem->rect.bottom;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000943 if (IS_STRING_ITEM(lpitem->fType) && lpitem->xTab)
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000944 {
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000945 maxTab = max( maxTab, lpitem->xTab );
946 maxTabWidth = max(maxTabWidth,lpitem->rect.right-lpitem->xTab);
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000947 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000948 }
949
950 /* Finish the column (set all items to the largest width found) */
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000951 maxX = max( maxX, maxTab + maxTabWidth );
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000952 for (lpitem = &lppop->items[start]; start < i; start++, lpitem++)
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000953 {
954 lpitem->rect.right = maxX;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000955 if (IS_STRING_ITEM(lpitem->fType) && lpitem->xTab)
Juergen Schmied466a6521999-05-02 11:21:08 +0000956 lpitem->xTab = maxTab;
957
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000958 }
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000959 lppop->Height = max( lppop->Height, orgY );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000960 }
961
962 lppop->Width = maxX;
Juergen Schmied466a6521999-05-02 11:21:08 +0000963
964 /* space for 3d border */
965 if(TWEAK_WineLook > WIN31_LOOK)
966 {
967 lppop->Height += 2;
968 lppop->Width += 2;
969 }
970
Alexandre Julliarda3960291999-02-26 11:11:13 +0000971 ReleaseDC( 0, hdc );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000972}
973
974
975/***********************************************************************
976 * MENU_MenuBarCalcSize
977 *
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000978 * FIXME: Word 6 implements its own MDI and its own 'close window' bitmap
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000979 * height is off by 1 pixel which causes lengthy window relocations when
980 * active document window is maximized/restored.
981 *
Alexandre Julliardf7207251994-07-23 07:57:48 +0000982 * Calculate the size of the menu bar.
983 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000984static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect,
985 LPPOPUPMENU lppop, HWND hwndOwner )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000986{
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000987 MENUITEM *lpitem;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000988 int start, i, orgX, orgY, maxY, helpPos;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000989
990 if ((lprect == NULL) || (lppop == NULL)) return;
991 if (lppop->nItems == 0) return;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000992 TRACE("left=%d top=%d right=%d bottom=%d\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000993 lprect->left, lprect->top, lprect->right, lprect->bottom);
Alexandre Julliardf7207251994-07-23 07:57:48 +0000994 lppop->Width = lprect->right - lprect->left;
995 lppop->Height = 0;
Francois Gouget75f9e642000-11-06 05:25:29 +0000996 maxY = lprect->top+1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000997 start = 0;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000998 helpPos = -1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000999 while (start < lppop->nItems)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001000 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001001 lpitem = &lppop->items[start];
Alexandre Julliardf7207251994-07-23 07:57:48 +00001002 orgX = lprect->left;
1003 orgY = maxY;
1004
1005 /* Parse items until line break or end of menu */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001006 for (i = start; i < lppop->nItems; i++, lpitem++)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001007 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001008 if ((helpPos == -1) && (lpitem->fType & MF_HELP)) helpPos = i;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001009 if ((i != start) &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001010 (lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001011
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001012 TRACE("calling MENU_CalcItemSize org=(%d, %d)\n",
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001013 orgX, orgY );
Alexandre Julliard03468f71998-02-15 19:40:49 +00001014 debug_print_menuitem (" item: ", lpitem, "");
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001015 MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, TRUE );
Pascal Lessard47274231999-02-13 12:21:46 +00001016
Alexandre Julliardf7207251994-07-23 07:57:48 +00001017 if (lpitem->rect.right > lprect->right)
1018 {
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001019 if (i != start) break;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001020 else lpitem->rect.right = lprect->right;
1021 }
Francois Gouget6d77d3a2000-03-25 21:44:35 +00001022 maxY = max( maxY, lpitem->rect.bottom );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001023 orgX = lpitem->rect.right;
1024 }
1025
1026 /* Finish the line (set all items to the largest height found) */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001027 while (start < i) lppop->items[start++].rect.bottom = maxY;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001028 }
1029
1030 lprect->bottom = maxY;
1031 lppop->Height = lprect->bottom - lprect->top;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001032
Francois Gouget93fd46a2000-10-23 00:37:49 +00001033 if (TWEAK_WineLook == WIN31_LOOK) {
1034 /* Flush right all magic items and items between the MF_HELP and */
1035 /* the last item (if several lines, only move the last line) */
1036 lpitem = &lppop->items[lppop->nItems-1];
1037 orgY = lpitem->rect.top;
1038 orgX = lprect->right;
1039 for (i = lppop->nItems - 1; i >= helpPos; i--, lpitem--) {
1040 if ( !IS_BITMAP_ITEM(lpitem->fType) && ((helpPos==-1) || (helpPos>i) ))
1041 break; /* done */
1042 if (lpitem->rect.top != orgY) break; /* Other line */
1043 if (lpitem->rect.right >= orgX) break; /* Too far right already */
1044 lpitem->rect.left += orgX - lpitem->rect.right;
1045 lpitem->rect.right = orgX;
1046 orgX = lpitem->rect.left;
1047 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001048 }
Alexandre Julliardf7207251994-07-23 07:57:48 +00001049}
1050
Alexandre Julliardf7207251994-07-23 07:57:48 +00001051/***********************************************************************
1052 * MENU_DrawMenuItem
1053 *
1054 * Draw a single menu item.
1055 */
Juergen Schmied78513941999-04-18 14:40:32 +00001056static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, MENUITEM *lpitem,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001057 UINT height, BOOL menuBar, UINT odaction )
Alexandre Julliardf7207251994-07-23 07:57:48 +00001058{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001059 RECT rect;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001060
Alexandre Julliard03468f71998-02-15 19:40:49 +00001061 debug_print_menuitem("MENU_DrawMenuItem: ", lpitem, "");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001062
1063 if (lpitem->fType & MF_SYSMENU)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001064 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001065 if( !IsIconic(hwnd) ) {
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001066 if (TWEAK_WineLook > WIN31_LOOK)
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001067 NC_DrawSysButton95( hwnd, hdc,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001068 lpitem->fState &
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001069 (MF_HILITE | MF_MOUSESELECT) );
1070 else
1071 NC_DrawSysButton( hwnd, hdc,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001072 lpitem->fState &
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001073 (MF_HILITE | MF_MOUSESELECT) );
1074 }
1075
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001076 return;
1077 }
1078
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001079 if (lpitem->fType & MF_OWNERDRAW)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001080 {
Ken Thomases130f0d82000-05-10 21:38:37 +00001081 /*
1082 ** Experimentation under Windows reveals that an owner-drawn
1083 ** menu is given the rectangle which includes the space it requested
1084 ** in its response to WM_MEASUREITEM _plus_ width for a checkmark
1085 ** and a popup-menu arrow. This is the value of lpitem->rect.
1086 ** Windows will leave all drawing to the application except for
1087 ** the popup-menu arrow. Windows always draws that itself, after
1088 ** the menu owner has finished drawing.
1089 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001090 DRAWITEMSTRUCT dis;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001091
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001092 dis.CtlType = ODT_MENU;
Juergen Schmied7abca951999-04-11 17:02:30 +00001093 dis.CtlID = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001094 dis.itemID = lpitem->wID;
Juergen Schmied7abca951999-04-11 17:02:30 +00001095 dis.itemData = (DWORD)lpitem->dwItemData;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001096 dis.itemState = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001097 if (lpitem->fState & MF_CHECKED) dis.itemState |= ODS_CHECKED;
1098 if (lpitem->fState & MF_GRAYED) dis.itemState |= ODS_GRAYED;
1099 if (lpitem->fState & MF_HILITE) dis.itemState |= ODS_SELECTED;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001100 dis.itemAction = odaction; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */
Juergen Schmied78513941999-04-18 14:40:32 +00001101 dis.hwndItem = hmenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001102 dis.hDC = hdc;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001103 dis.rcItem = lpitem->rect;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001104 TRACE("Ownerdraw: owner=%04x itemID=%d, itemState=%d, itemAction=%d, "
Juergen Schmied78513941999-04-18 14:40:32 +00001105 "hwndItem=%04x, hdc=%04x, rcItem={%d,%d,%d,%d}\n", hwndOwner,
1106 dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
1107 dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right,
1108 dis.rcItem.bottom);
1109 SendMessageA( hwndOwner, WM_DRAWITEM, 0, (LPARAM)&dis );
Ken Thomases130f0d82000-05-10 21:38:37 +00001110 /* Fall through to draw popup-menu arrow */
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001111 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001112
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001113 TRACE("rect={%d,%d,%d,%d}\n", lpitem->rect.left, lpitem->rect.top,
Juergen Schmied78513941999-04-18 14:40:32 +00001114 lpitem->rect.right,lpitem->rect.bottom);
1115
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001116 if (menuBar && (lpitem->fType & MF_SEPARATOR)) return;
Juergen Schmied78513941999-04-18 14:40:32 +00001117
Alexandre Julliardf7207251994-07-23 07:57:48 +00001118 rect = lpitem->rect;
1119
Ken Thomases130f0d82000-05-10 21:38:37 +00001120 if (!(lpitem->fType & MF_OWNERDRAW))
1121 {
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001122 if (lpitem->fState & MF_HILITE)
1123 {
1124 if(TWEAK_WineLook == WIN98_LOOK)
1125 {
1126 if(menuBar)
1127 DrawEdge(hdc, &rect, BDR_SUNKENOUTER, BF_RECT);
1128 else
1129 FillRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
1130 }
1131 else /* Not Win98 Look */
1132 {
1133 if(!IS_BITMAP_ITEM(lpitem->fType))
1134 FillRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
1135 }
1136 }
Ken Thomases130f0d82000-05-10 21:38:37 +00001137 else
1138 FillRect( hdc, &rect, GetSysColorBrush(COLOR_MENU) );
1139 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001140
Alexandre Julliarda3960291999-02-26 11:11:13 +00001141 SetBkMode( hdc, TRANSPARENT );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001142
Ken Thomases130f0d82000-05-10 21:38:37 +00001143 if (!(lpitem->fType & MF_OWNERDRAW))
Alexandre Julliardf7207251994-07-23 07:57:48 +00001144 {
Ken Thomases130f0d82000-05-10 21:38:37 +00001145 /* vertical separator */
1146 if (!menuBar && (lpitem->fType & MF_MENUBARBREAK))
1147 {
1148 if (TWEAK_WineLook > WIN31_LOOK)
1149 {
1150 RECT rc = rect;
1151 rc.top = 3;
1152 rc.bottom = height - 3;
1153 DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT);
1154 }
1155 else
1156 {
1157 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001158 MoveToEx( hdc, rect.left, 0, NULL );
Ken Thomases130f0d82000-05-10 21:38:37 +00001159 LineTo( hdc, rect.left, height );
1160 }
1161 }
Juergen Schmied78513941999-04-18 14:40:32 +00001162
Ken Thomases130f0d82000-05-10 21:38:37 +00001163 /* horizontal separator */
1164 if (lpitem->fType & MF_SEPARATOR)
1165 {
1166 if (TWEAK_WineLook > WIN31_LOOK)
1167 {
1168 RECT rc = rect;
1169 rc.left++;
1170 rc.right--;
1171 rc.top += SEPARATOR_HEIGHT / 2;
1172 DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP);
1173 }
1174 else
1175 {
1176 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001177 MoveToEx( hdc, rect.left, rect.top + SEPARATOR_HEIGHT/2, NULL );
Ken Thomases130f0d82000-05-10 21:38:37 +00001178 LineTo( hdc, rect.right, rect.top + SEPARATOR_HEIGHT/2 );
1179 }
1180 return;
1181 }
Alexandre Julliardf7207251994-07-23 07:57:48 +00001182 }
1183
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001184 /* Setup colors */
1185
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001186 if (lpitem->fState & MF_HILITE)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001187 {
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001188 if(TWEAK_WineLook == WIN98_LOOK)
1189 {
1190 if(menuBar)
1191 SetTextColor(hdc, GetSysColor(COLOR_MENUTEXT));
1192 else
1193 {
1194 if(lpitem->fState & MF_GRAYED)
1195 SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
1196 else
1197 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1198 }
1199 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
1200 }
1201 else /* Not Win98 Look */
1202 {
1203 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1204 if(!IS_BITMAP_ITEM(lpitem->fType))
1205 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
1206 else
1207 SetBkColor(hdc, GetSysColor(COLOR_MENU));
1208 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001209 }
1210 else
1211 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001212 if (lpitem->fState & MF_GRAYED)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001213 SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001214 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001215 SetTextColor( hdc, GetSysColor( COLOR_MENUTEXT ) );
1216 SetBkColor( hdc, GetSysColor( COLOR_MENU ) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001217 }
1218
Juergen Schmied78513941999-04-18 14:40:32 +00001219 /* helper lines for debugging */
1220/* FrameRect(hdc, &rect, GetStockObject(BLACK_BRUSH));
1221 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001222 MoveToEx( hdc, rect.left, (rect.top + rect.bottom)/2, NULL );
Juergen Schmied78513941999-04-18 14:40:32 +00001223 LineTo( hdc, rect.right, (rect.top + rect.bottom)/2 );
1224*/
1225
Alexandre Julliardf7207251994-07-23 07:57:48 +00001226 if (!menuBar)
1227 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001228 INT y = rect.top + rect.bottom;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001229
Ken Thomases130f0d82000-05-10 21:38:37 +00001230 if (!(lpitem->fType & MF_OWNERDRAW))
1231 {
1232 /* Draw the check mark
1233 *
1234 * FIXME:
1235 * Custom checkmark bitmaps are monochrome but not always 1bpp.
1236 */
Alexandre Julliardf7207251994-07-23 07:57:48 +00001237
Ken Thomases130f0d82000-05-10 21:38:37 +00001238 if (lpitem->fState & MF_CHECKED)
1239 {
1240 HBITMAP bm = lpitem->hCheckBit ? lpitem->hCheckBit :
1241 ((lpitem->fType & MFT_RADIOCHECK) ? hStdRadioCheck : hStdCheck);
1242 HDC hdcMem = CreateCompatibleDC( hdc );
Huw D M Davies2d617be1998-12-08 09:14:09 +00001243
Ken Thomases130f0d82000-05-10 21:38:37 +00001244 SelectObject( hdcMem, bm );
1245 BitBlt( hdc, rect.left, (y - check_bitmap_height) / 2,
1246 check_bitmap_width, check_bitmap_height,
1247 hdcMem, 0, 0, SRCCOPY );
1248 DeleteDC( hdcMem );
1249 }
1250 else if (lpitem->hUnCheckBit)
1251 {
1252 HDC hdcMem = CreateCompatibleDC( hdc );
Huw D M Davies2d617be1998-12-08 09:14:09 +00001253
Ken Thomases130f0d82000-05-10 21:38:37 +00001254 SelectObject( hdcMem, lpitem->hUnCheckBit );
1255 BitBlt( hdc, rect.left, (y - check_bitmap_height) / 2,
1256 check_bitmap_width, check_bitmap_height,
1257 hdcMem, 0, 0, SRCCOPY );
1258 DeleteDC( hdcMem );
1259 }
1260 }
Juergen Schmied78513941999-04-18 14:40:32 +00001261
Alexandre Julliardf7207251994-07-23 07:57:48 +00001262 /* Draw the popup-menu arrow */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001263 if (lpitem->fType & MF_POPUP)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001264 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001265 HDC hdcMem = CreateCompatibleDC( hdc );
Ken Thomases130f0d82000-05-10 21:38:37 +00001266 HBITMAP hOrigBitmap;
Huw D M Davies2d617be1998-12-08 09:14:09 +00001267
Ken Thomases130f0d82000-05-10 21:38:37 +00001268 hOrigBitmap = SelectObject( hdcMem, hStdMnArrow );
Juergen Schmied78513941999-04-18 14:40:32 +00001269 BitBlt( hdc, rect.right - arrow_bitmap_width - 1,
Huw D M Davies2d617be1998-12-08 09:14:09 +00001270 (y - arrow_bitmap_height) / 2,
1271 arrow_bitmap_width, arrow_bitmap_height,
1272 hdcMem, 0, 0, SRCCOPY );
Ken Thomases130f0d82000-05-10 21:38:37 +00001273 SelectObject( hdcMem, hOrigBitmap );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001274 DeleteDC( hdcMem );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001275 }
1276
1277 rect.left += check_bitmap_width;
1278 rect.right -= arrow_bitmap_width;
1279 }
1280
Ken Thomases130f0d82000-05-10 21:38:37 +00001281 /* Done for owner-drawn */
1282 if (lpitem->fType & MF_OWNERDRAW)
1283 return;
1284
Juergen Schmied78513941999-04-18 14:40:32 +00001285 /* Draw the item text or bitmap */
1286 if (IS_BITMAP_ITEM(lpitem->fType))
1287 { int top;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001288
Alexandre Julliarda3960291999-02-26 11:11:13 +00001289 HBITMAP resBmp = 0;
Francois Boisvert8b391741999-02-09 14:09:55 +00001290
Alexandre Julliarda3960291999-02-26 11:11:13 +00001291 HDC hdcMem = CreateCompatibleDC( hdc );
Huw D M Davies2d617be1998-12-08 09:14:09 +00001292
Patrik Stridvall1bb94031999-05-08 15:47:44 +00001293 /*
1294 * Check if there is a magic menu item associated with this item
1295 * and load the appropriate bitmap
1296 */
Juergen Schmied78513941999-04-18 14:40:32 +00001297 if((LOWORD((int)lpitem->text)) < 12)
1298 {
1299 resBmp = MENU_LoadMagicItem((int)lpitem->text, (lpitem->fState & MF_HILITE),
1300 lpitem->dwItemData);
Francois Boisvert8b391741999-02-09 14:09:55 +00001301 }
1302 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001303 resBmp = (HBITMAP)lpitem->text;
Juergen Schmied78513941999-04-18 14:40:32 +00001304
1305 if (resBmp)
1306 {
1307 BITMAP bm;
1308 GetObjectA( resBmp, sizeof(bm), &bm );
1309
1310 SelectObject(hdcMem,resBmp );
1311
1312 /* handle fontsize > bitmap_height */
1313 top = ((rect.bottom-rect.top)>bm.bmHeight) ?
1314 rect.top+(rect.bottom-rect.top-bm.bmHeight)/2 : rect.top;
1315
1316 BitBlt( hdc, rect.left, top, rect.right - rect.left,
Dmitry Timoshkovd0ff2ec2000-11-01 02:11:41 +00001317 rect.bottom - rect.top, hdcMem, 0, 0,
Dmitry Timoshkovd5e15d32000-11-02 20:08:34 +00001318 ((lpitem->fState & MF_HILITE) && !((LOWORD((DWORD)lpitem->text)) < 12)) ? NOTSRCCOPY : SRCCOPY );
Juergen Schmied78513941999-04-18 14:40:32 +00001319 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001320 DeleteDC( hdcMem );
Juergen Schmied78513941999-04-18 14:40:32 +00001321
Alexandre Julliardf7207251994-07-23 07:57:48 +00001322 return;
Francois Boisvert8b391741999-02-09 14:09:55 +00001323
Alexandre Julliardf7207251994-07-23 07:57:48 +00001324 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001325 /* No bitmap - process text if present */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001326 else if (IS_STRING_ITEM(lpitem->fType))
Alexandre Julliardf7207251994-07-23 07:57:48 +00001327 {
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001328 register int i;
Juergen Schmied466a6521999-05-02 11:21:08 +00001329 HFONT hfontOld = 0;
1330
Juergen Schmied78513941999-04-18 14:40:32 +00001331 UINT uFormat = (menuBar) ?
1332 DT_CENTER | DT_VCENTER | DT_SINGLELINE :
1333 DT_LEFT | DT_VCENTER | DT_SINGLELINE;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001334
Juergen Schmied466a6521999-05-02 11:21:08 +00001335 if ( lpitem->fState & MFS_DEFAULT )
1336 {
1337 hfontOld = SelectObject( hdc, hMenuFontBold);
1338 }
1339
Alexandre Julliardf7207251994-07-23 07:57:48 +00001340 if (menuBar)
1341 {
1342 rect.left += MENU_BAR_ITEMS_SPACE / 2;
1343 rect.right -= MENU_BAR_ITEMS_SPACE / 2;
Aric Stewartc946b1c2000-10-24 21:28:19 +00001344 i = strlenW( lpitem->text );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001345 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001346 else
Alexandre Julliardf7207251994-07-23 07:57:48 +00001347 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001348 for (i = 0; lpitem->text[i]; i++)
Juergen Schmied466a6521999-05-02 11:21:08 +00001349 if ((lpitem->text[i] == '\t') || (lpitem->text[i] == '\b'))
1350 break;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001351 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001352
Juergen Schmied466a6521999-05-02 11:21:08 +00001353 if( !(TWEAK_WineLook == WIN31_LOOK) && (lpitem->fState & MF_GRAYED))
Juergen Schmied78513941999-04-18 14:40:32 +00001354 {
Juergen Schmied466a6521999-05-02 11:21:08 +00001355 if (!(lpitem->fState & MF_HILITE) )
Juergen Schmied78513941999-04-18 14:40:32 +00001356 {
Juergen Schmied466a6521999-05-02 11:21:08 +00001357 ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001358 SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
Aric Stewartc946b1c2000-10-24 21:28:19 +00001359 DrawTextW( hdc, lpitem->text, i, &rect, uFormat );
Juergen Schmied466a6521999-05-02 11:21:08 +00001360 --rect.left; --rect.top; --rect.right; --rect.bottom;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001361 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001362 SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001363 }
Juergen Schmied466a6521999-05-02 11:21:08 +00001364
Aric Stewartc946b1c2000-10-24 21:28:19 +00001365 DrawTextW( hdc, lpitem->text, i, &rect, uFormat);
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001366
Juergen Schmied466a6521999-05-02 11:21:08 +00001367 /* paint the shortcut text */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001368 if (lpitem->text[i]) /* There's a tab or flush-right char */
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001369 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001370 if (lpitem->text[i] == '\t')
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001371 {
1372 rect.left = lpitem->xTab;
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +00001373 uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001374 }
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +00001375 else
1376 {
1377 uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
1378 }
1379
Juergen Schmied466a6521999-05-02 11:21:08 +00001380 if( !(TWEAK_WineLook == WIN31_LOOK) && (lpitem->fState & MF_GRAYED))
1381 {
1382 if (!(lpitem->fState & MF_HILITE) )
1383 {
1384 ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
1385 SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
Aric Stewartc946b1c2000-10-24 21:28:19 +00001386 DrawTextW( hdc, lpitem->text + i + 1, -1, &rect, uFormat );
Juergen Schmied466a6521999-05-02 11:21:08 +00001387 --rect.left; --rect.top; --rect.right; --rect.bottom;
1388 }
1389 SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
1390 }
Aric Stewartc946b1c2000-10-24 21:28:19 +00001391 DrawTextW( hdc, lpitem->text + i + 1, -1, &rect, uFormat );
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001392 }
Juergen Schmied466a6521999-05-02 11:21:08 +00001393
1394 if (hfontOld)
1395 SelectObject (hdc, hfontOld);
Alexandre Julliardf7207251994-07-23 07:57:48 +00001396 }
1397}
1398
1399
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001400/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001401 * MENU_DrawPopupMenu
1402 *
1403 * Paint a popup menu.
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001404 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001405static void MENU_DrawPopupMenu( HWND hwnd, HDC hdc, HMENU hmenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001406{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001407 HBRUSH hPrevBrush = 0;
1408 RECT rect;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001409
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001410 TRACE("wnd=0x%04x dc=0x%04x menu=0x%04x\n", hwnd, hdc, hmenu);
Juergen Schmied78513941999-04-18 14:40:32 +00001411
Alexandre Julliarda3960291999-02-26 11:11:13 +00001412 GetClientRect( hwnd, &rect );
Alexandre Julliard641ee761997-08-04 16:34:36 +00001413
Alex Korobka44a1b591999-04-01 12:03:52 +00001414 if(TWEAK_WineLook == WIN31_LOOK)
1415 {
Marcus Meissnerddca3151999-05-22 11:33:23 +00001416 rect.bottom -= POPUP_YSHADE * GetSystemMetrics(SM_CYBORDER);
1417 rect.right -= POPUP_XSHADE * GetSystemMetrics(SM_CXBORDER);
Alex Korobka44a1b591999-04-01 12:03:52 +00001418 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001419
Juergen Schmied78513941999-04-18 14:40:32 +00001420 if((hPrevBrush = SelectObject( hdc, GetSysColorBrush(COLOR_MENU) ))
1421 && (SelectObject( hdc, hMenuFont)))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001422 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001423 HPEN hPrevPen;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001424
Alexandre Julliarda3960291999-02-26 11:11:13 +00001425 Rectangle( hdc, rect.left, rect.top, rect.right, rect.bottom );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001426
Alexandre Julliarda3960291999-02-26 11:11:13 +00001427 hPrevPen = SelectObject( hdc, GetStockObject( NULL_PEN ) );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001428 if( hPrevPen )
1429 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001430 INT ropPrev, i;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001431 POPUPMENU *menu;
1432
1433 /* draw 3-d shade */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001434 if(TWEAK_WineLook == WIN31_LOOK) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001435 SelectObject( hdc, hShadeBrush );
1436 SetBkMode( hdc, TRANSPARENT );
1437 ropPrev = SetROP2( hdc, R2_MASKPEN );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001438
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001439 i = rect.right; /* why SetBrushOrg() doesn't? */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001440 PatBlt( hdc, i & 0xfffffffe,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001441 rect.top + POPUP_YSHADE*GetSystemMetrics(SM_CYBORDER),
1442 i%2 + POPUP_XSHADE*GetSystemMetrics(SM_CXBORDER),
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001443 rect.bottom - rect.top, 0x00a000c9 );
1444 i = rect.bottom;
Marcus Meissnerddca3151999-05-22 11:33:23 +00001445 PatBlt( hdc, rect.left + POPUP_XSHADE*GetSystemMetrics(SM_CXBORDER),
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001446 i & 0xfffffffe,rect.right - rect.left,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001447 i%2 + POPUP_YSHADE*GetSystemMetrics(SM_CYBORDER), 0x00a000c9 );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001448 SelectObject( hdc, hPrevPen );
1449 SelectObject( hdc, hPrevBrush );
1450 SetROP2( hdc, ropPrev );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001451 }
1452 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001453 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001454
1455 /* draw menu items */
1456
Gerard Patel3e629742000-01-17 22:22:16 +00001457 menu = MENU_GetMenu( hmenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001458 if (menu && menu->nItems)
1459 {
1460 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001461 UINT u;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001462
1463 for (u = menu->nItems, item = menu->items; u > 0; u--, item++)
Juergen Schmied78513941999-04-18 14:40:32 +00001464 MENU_DrawMenuItem( hwnd, hmenu, menu->hwndOwner, hdc, item,
1465 menu->Height, FALSE, ODA_DRAWENTIRE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001466
1467 }
Juergen Schmied78513941999-04-18 14:40:32 +00001468 } else
1469 {
1470 SelectObject( hdc, hPrevBrush );
1471 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001472 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001473}
1474
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001475/***********************************************************************
1476 * MENU_DrawMenuBar
1477 *
1478 * Paint a menu bar. Returns the height of the menu bar.
Juergen Schmied78513941999-04-18 14:40:32 +00001479 * called from [windows/nonclient.c]
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001480 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001481UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd,
1482 BOOL suppress_draw)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001483{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001484 LPPOPUPMENU lppop;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001485 UINT i,retvalue;
Juergen Schmied78513941999-04-18 14:40:32 +00001486 HFONT hfontOld = 0;
1487
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001488 WND *wndPtr = WIN_FindWndPtr( hwnd );
1489
Gerard Patel3e629742000-01-17 22:22:16 +00001490 lppop = MENU_GetMenu ((HMENU)wndPtr->wIDmenu );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001491 if (lppop == NULL || lprect == NULL)
1492 {
Marcus Meissnerddca3151999-05-22 11:33:23 +00001493 retvalue = GetSystemMetrics(SM_CYMENU);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001494 goto END;
1495 }
Juergen Schmied78513941999-04-18 14:40:32 +00001496
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001497 TRACE("(%04x, %p, %p)\n", hDC, lprect, lppop);
Juergen Schmied78513941999-04-18 14:40:32 +00001498
1499 hfontOld = SelectObject( hDC, hMenuFont);
1500
1501 if (lppop->Height == 0)
1502 MENU_MenuBarCalcSize(hDC, lprect, lppop, hwnd);
1503
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001504 lprect->bottom = lprect->top + lppop->Height;
Juergen Schmied78513941999-04-18 14:40:32 +00001505
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001506 if (suppress_draw)
1507 {
1508 retvalue = lppop->Height;
1509 goto END;
1510 }
Juergen Schmied78513941999-04-18 14:40:32 +00001511
Alexandre Julliarda3960291999-02-26 11:11:13 +00001512 FillRect(hDC, lprect, GetSysColorBrush(COLOR_MENU) );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001513
Juergen Schmied78513941999-04-18 14:40:32 +00001514 if (TWEAK_WineLook == WIN31_LOOK)
1515 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001516 SelectObject( hDC, GetSysColorPen(COLOR_WINDOWFRAME) );
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001517 MoveToEx( hDC, lprect->left, lprect->bottom, NULL );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001518 LineTo( hDC, lprect->right, lprect->bottom );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001519 }
Juergen Schmied78513941999-04-18 14:40:32 +00001520 else
1521 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001522 SelectObject( hDC, GetSysColorPen(COLOR_3DFACE));
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001523 MoveToEx( hDC, lprect->left, lprect->bottom, NULL );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001524 LineTo( hDC, lprect->right, lprect->bottom );
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001525 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001526
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001527 if (lppop->nItems == 0)
1528 {
Marcus Meissnerddca3151999-05-22 11:33:23 +00001529 retvalue = GetSystemMetrics(SM_CYMENU);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001530 goto END;
1531 }
Juergen Schmied78513941999-04-18 14:40:32 +00001532
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001533 for (i = 0; i < lppop->nItems; i++)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001534 {
Aric Stewart70cc1692000-05-10 21:54:07 +00001535 MENU_DrawMenuItem( hwnd, (HMENU)wndPtr->wIDmenu, hwnd,
Juergen Schmied78513941999-04-18 14:40:32 +00001536 hDC, &lppop->items[i], lppop->Height, TRUE, ODA_DRAWENTIRE );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001537 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001538 retvalue = lppop->Height;
Juergen Schmied78513941999-04-18 14:40:32 +00001539
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001540END:
Juergen Schmied78513941999-04-18 14:40:32 +00001541 if (hfontOld)
1542 SelectObject (hDC, hfontOld);
1543
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001544 WIN_ReleaseWndPtr(wndPtr);
1545 return retvalue;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001546}
1547
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001548/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001549 * MENU_PatchResidentPopup
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001550 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001551BOOL MENU_PatchResidentPopup( HQUEUE16 checkQueue, WND* checkWnd )
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001552{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001553 WND *pTPWnd = MENU_GetTopPopupWnd();
1554
1555 if( pTPWnd )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001556 {
1557 HTASK16 hTask = 0;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001558
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001559 TRACE("patching resident popup: %04x %04x [%04x %04x]\n",
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001560 checkQueue, checkWnd ? checkWnd->hwndSelf : 0, pTPWnd->hmemTaskQ,
1561 pTPWnd->owner ? pTPWnd->owner->hwndSelf : 0);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001562
Alexandre Julliard77b99181997-09-14 17:17:23 +00001563 switch( checkQueue )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001564 {
Alexandre Julliard77b99181997-09-14 17:17:23 +00001565 case 0: /* checkWnd is the new popup owner */
1566 if( checkWnd )
1567 {
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001568 pTPWnd->owner = checkWnd;
1569 if( pTPWnd->hmemTaskQ != checkWnd->hmemTaskQ )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001570 hTask = QUEUE_GetQueueTask( checkWnd->hmemTaskQ );
1571 }
1572 break;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001573
Alexandre Julliard77b99181997-09-14 17:17:23 +00001574 case 0xFFFF: /* checkWnd is destroyed */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001575 if( pTPWnd->owner == checkWnd )
1576 pTPWnd->owner = NULL;
1577 MENU_ReleaseTopPopupWnd();
Alexandre Julliard77b99181997-09-14 17:17:23 +00001578 return TRUE;
1579
1580 default: /* checkQueue is exiting */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001581 if( pTPWnd->hmemTaskQ == checkQueue )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001582 {
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001583 hTask = QUEUE_GetQueueTask( pTPWnd->hmemTaskQ );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001584 hTask = TASK_GetNextTask( hTask );
1585 }
1586 break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001587 }
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001588
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001589 if( hTask )
1590 {
1591 TDB* task = (TDB*)GlobalLock16( hTask );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001592 if( task )
1593 {
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001594 pTPWnd->hInstance = task->hInstance;
1595 pTPWnd->hmemTaskQ = task->hQueue;
1596 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001597 return TRUE;
1598 }
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001599 else WARN("failed to patch resident popup.\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001600 }
1601 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001602 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001603 return FALSE;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001604}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001605
1606/***********************************************************************
1607 * MENU_ShowPopup
1608 *
1609 * Display a popup menu.
1610 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001611static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id,
1612 INT x, INT y, INT xanchor, INT yanchor )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001613{
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001614 POPUPMENU *menu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001615 WND *wndOwner = NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001616
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001617 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 +00001618 hwndOwner, hmenu, id, x, y, xanchor, yanchor);
1619
Gerard Patel3e629742000-01-17 22:22:16 +00001620 if (!(menu = MENU_GetMenu( hmenu ))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001621 if (menu->FocusedItem != NO_SELECTED_ITEM)
1622 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001623 menu->items[menu->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001624 menu->FocusedItem = NO_SELECTED_ITEM;
1625 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001626
Juergen Schmied78513941999-04-18 14:40:32 +00001627 /* store the owner for DrawItem*/
1628 menu->hwndOwner = hwndOwner;
1629
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001630 if( (wndOwner = WIN_FindWndPtr( hwndOwner )) )
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001631 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001632 UINT width, height;
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001633
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001634 MENU_PopupMenuCalcSize( menu, hwndOwner );
1635
1636 /* adjust popup menu pos so that it fits within the desktop */
1637
Marcus Meissnerddca3151999-05-22 11:33:23 +00001638 width = menu->Width + GetSystemMetrics(SM_CXBORDER);
1639 height = menu->Height + GetSystemMetrics(SM_CYBORDER);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001640
Marcus Meissnerddca3151999-05-22 11:33:23 +00001641 if( x + width > GetSystemMetrics(SM_CXSCREEN ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001642 {
1643 if( xanchor )
1644 x -= width - xanchor;
Marcus Meissnerddca3151999-05-22 11:33:23 +00001645 if( x + width > GetSystemMetrics(SM_CXSCREEN))
1646 x = GetSystemMetrics(SM_CXSCREEN) - width;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001647 }
1648 if( x < 0 ) x = 0;
1649
Marcus Meissnerddca3151999-05-22 11:33:23 +00001650 if( y + height > GetSystemMetrics(SM_CYSCREEN ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001651 {
1652 if( yanchor )
1653 y -= height + yanchor;
Marcus Meissnerddca3151999-05-22 11:33:23 +00001654 if( y + height > GetSystemMetrics(SM_CYSCREEN ))
1655 y = GetSystemMetrics(SM_CYSCREEN) - height;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001656 }
1657 if( y < 0 ) y = 0;
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001658
Alex Korobka44a1b591999-04-01 12:03:52 +00001659 if( TWEAK_WineLook == WIN31_LOOK )
1660 {
Marcus Meissnerddca3151999-05-22 11:33:23 +00001661 width += POPUP_XSHADE * GetSystemMetrics(SM_CXBORDER); /* add space for shading */
1662 height += POPUP_YSHADE * GetSystemMetrics(SM_CYBORDER);
Alex Korobka44a1b591999-04-01 12:03:52 +00001663 }
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001664
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001665 /* NOTE: In Windows, top menu popup is not owned. */
1666 if (!pTopPopupWnd) /* create top level popup menu window */
1667 {
1668 assert( uSubPWndLevel == 0 );
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001669
Alexandre Julliarda3960291999-02-26 11:11:13 +00001670 pTopPopupWnd = WIN_FindWndPtr(CreateWindowA( POPUPMENU_CLASS_ATOM, NULL,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001671 WS_POPUP, x, y, width, height,
1672 hwndOwner, 0, wndOwner->hInstance,
1673 (LPVOID)hmenu ));
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001674 if (!pTopPopupWnd)
1675 {
1676 WIN_ReleaseWndPtr(wndOwner);
1677 return FALSE;
1678 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001679 menu->hWnd = pTopPopupWnd->hwndSelf;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001680 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001681 }
1682 else
1683 if( uSubPWndLevel )
1684 {
1685 /* create a new window for the submenu */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001686
Alexandre Julliarda3960291999-02-26 11:11:13 +00001687 menu->hWnd = CreateWindowA( POPUPMENU_CLASS_ATOM, NULL,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001688 WS_POPUP, x, y, width, height,
Juergen Schmied78513941999-04-18 14:40:32 +00001689 hwndOwner, 0, wndOwner->hInstance,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001690 (LPVOID)hmenu );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001691 if( !menu->hWnd )
1692 {
1693 WIN_ReleaseWndPtr(wndOwner);
1694 return FALSE;
1695 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001696 }
1697 else /* top level popup menu window already exists */
1698 {
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001699 WND *pTPWnd = MENU_GetTopPopupWnd();
1700 menu->hWnd = pTPWnd->hwndSelf;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001701
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001702 MENU_PatchResidentPopup( 0, wndOwner );
Juergen Schmied78513941999-04-18 14:40:32 +00001703 SendMessageA( pTPWnd->hwndSelf, MM_SETMENUHANDLE, (WPARAM16)hmenu, 0L);
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001704
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001705 /* adjust its size */
1706
Alexandre Julliarda3960291999-02-26 11:11:13 +00001707 SetWindowPos( menu->hWnd, 0, x, y, width, height,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001708 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001709 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001710 }
1711
1712 uSubPWndLevel++; /* menu level counter */
1713
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001714 /* Display the window */
1715
Alexandre Julliarda3960291999-02-26 11:11:13 +00001716 SetWindowPos( menu->hWnd, HWND_TOP, 0, 0, 0, 0,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001717 SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001718 UpdateWindow( menu->hWnd );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001719 WIN_ReleaseWndPtr(wndOwner);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001720 return TRUE;
1721 }
1722 return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001723}
1724
1725
1726/***********************************************************************
1727 * MENU_SelectItem
1728 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001729static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, UINT wIndex,
Rein Klazes80c924f1999-12-12 19:40:46 +00001730 BOOL sendMenuSelect, HMENU topmenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001731{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001732 LPPOPUPMENU lppop;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001733 HDC hdc;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001734
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001735 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 +00001736
Gerard Patel3e629742000-01-17 22:22:16 +00001737 lppop = MENU_GetMenu( hmenu );
1738 if ((!lppop) || (!lppop->nItems)) return;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001739
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001740 if (lppop->FocusedItem == wIndex) return;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001741 if (lppop->wFlags & MF_POPUP) hdc = GetDC( lppop->hWnd );
1742 else hdc = GetDCEx( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW);
Alexandre Julliardf7207251994-07-23 07:57:48 +00001743
Juergen Schmied78513941999-04-18 14:40:32 +00001744 SelectObject( hdc, hMenuFont);
1745
Alexandre Julliardf7207251994-07-23 07:57:48 +00001746 /* Clear previous highlighted item */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001747 if (lppop->FocusedItem != NO_SELECTED_ITEM)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001748 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001749 lppop->items[lppop->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
Juergen Schmied78513941999-04-18 14:40:32 +00001750 MENU_DrawMenuItem(lppop->hWnd, hmenu, hwndOwner, hdc,&lppop->items[lppop->FocusedItem],
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001751 lppop->Height, !(lppop->wFlags & MF_POPUP),
1752 ODA_SELECT );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001753 }
1754
1755 /* Highlight new item (if any) */
1756 lppop->FocusedItem = wIndex;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001757 if (lppop->FocusedItem != NO_SELECTED_ITEM)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001758 {
Rein Klazes80c924f1999-12-12 19:40:46 +00001759 if(!(lppop->items[wIndex].fType & MF_SEPARATOR)) {
1760 lppop->items[wIndex].fState |= MF_HILITE;
1761 MENU_DrawMenuItem( lppop->hWnd, hmenu, hwndOwner, hdc,
1762 &lppop->items[wIndex], lppop->Height,
1763 !(lppop->wFlags & MF_POPUP), ODA_SELECT );
1764 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001765 if (sendMenuSelect)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001766 {
1767 MENUITEM *ip = &lppop->items[lppop->FocusedItem];
Juergen Schmied78513941999-04-18 14:40:32 +00001768 SendMessageA( hwndOwner, WM_MENUSELECT,
Rein Klazes80c924f1999-12-12 19:40:46 +00001769 MAKELONG(ip->fType & MF_POPUP ? wIndex: ip->wID,
1770 ip->fType | ip->fState | MF_MOUSESELECT |
1771 (lppop->wFlags & MF_SYSMENU)), hmenu);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001772 }
Alexandre Julliardf7207251994-07-23 07:57:48 +00001773 }
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001774 else if (sendMenuSelect) {
Rein Klazes80c924f1999-12-12 19:40:46 +00001775 if(topmenu){
1776 int pos;
1777 if((pos=MENU_FindSubMenu(&topmenu, hmenu))!=NO_SELECTED_ITEM){
1778 POPUPMENU *ptm = (POPUPMENU *) USER_HEAP_LIN_ADDR( topmenu );
1779 MENUITEM *ip = &ptm->items[pos];
1780 SendMessageA( hwndOwner, WM_MENUSELECT, MAKELONG(pos,
1781 ip->fType | ip->fState | MF_MOUSESELECT |
1782 (ptm->wFlags & MF_SYSMENU)), topmenu);
1783 }
1784 }
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001785 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001786 ReleaseDC( lppop->hWnd, hdc );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001787}
1788
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001789
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001790/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001791 * MENU_MoveSelection
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001792 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001793 * Moves currently selected item according to the offset parameter.
1794 * If there is no selection then it should select the last item if
1795 * offset is ITEM_PREV or the first item if offset is ITEM_NEXT.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001796 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001797static void MENU_MoveSelection( HWND hwndOwner, HMENU hmenu, INT offset )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001798{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001799 INT i;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001800 POPUPMENU *menu;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001801
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001802 TRACE("hwnd=0x%04x hmenu=0x%04x off=0x%04x\n", hwndOwner, hmenu, offset);
Juergen Schmied466a6521999-05-02 11:21:08 +00001803
Gerard Patel3e629742000-01-17 22:22:16 +00001804 menu = MENU_GetMenu( hmenu );
1805 if ((!menu) || (!menu->items)) return;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001806
1807 if ( menu->FocusedItem != NO_SELECTED_ITEM )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001808 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001809 if( menu->nItems == 1 ) return; else
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001810 for (i = menu->FocusedItem + offset ; i >= 0 && i < menu->nItems
1811 ; i += offset)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001812 if (!(menu->items[i].fType & MF_SEPARATOR))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001813 {
Rein Klazes80c924f1999-12-12 19:40:46 +00001814 MENU_SelectItem( hwndOwner, hmenu, i, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001815 return;
1816 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001817 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001818
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001819 for ( i = (offset > 0) ? 0 : menu->nItems - 1;
1820 i >= 0 && i < menu->nItems ; i += offset)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001821 if (!(menu->items[i].fType & MF_SEPARATOR))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001822 {
Rein Klazes80c924f1999-12-12 19:40:46 +00001823 MENU_SelectItem( hwndOwner, hmenu, i, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001824 return;
1825 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001826}
1827
1828
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001829/**********************************************************************
1830 * MENU_SetItemData
1831 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001832 * Set an item flags, id and text ptr. Called by InsertMenu() and
1833 * ModifyMenu().
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001834 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001835static BOOL MENU_SetItemData( MENUITEM *item, UINT flags, UINT id,
Aric Stewartc946b1c2000-10-24 21:28:19 +00001836 LPCWSTR str )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001837{
Aric Stewartc946b1c2000-10-24 21:28:19 +00001838 LPWSTR prevText = IS_STRING_ITEM(item->fType) ? item->text : NULL;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001839
Alexandre Julliard03468f71998-02-15 19:40:49 +00001840 debug_print_menuitem("MENU_SetItemData from: ", item, "");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001841
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001842 if (IS_STRING_ITEM(flags))
1843 {
Alexandre Julliard491502b1997-11-01 19:08:16 +00001844 if (!str || !*str)
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001845 {
1846 flags |= MF_SEPARATOR;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001847 item->text = NULL;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001848 }
1849 else
1850 {
Aric Stewartc946b1c2000-10-24 21:28:19 +00001851 LPWSTR text;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001852 /* Item beginning with a backspace is a help item */
1853 if (*str == '\b')
1854 {
1855 flags |= MF_HELP;
1856 str++;
1857 }
Aric Stewartc946b1c2000-10-24 21:28:19 +00001858 if (!(text = HEAP_strdupW( SystemHeap, 0, str ))) return FALSE;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001859 item->text = text;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001860 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001861 }
Juergen Schmied78513941999-04-18 14:40:32 +00001862 else if (IS_BITMAP_ITEM(flags))
Aric Stewartc946b1c2000-10-24 21:28:19 +00001863 item->text = (LPWSTR)(HBITMAP)LOWORD(str);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001864 else item->text = NULL;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001865
Alexandre Julliarda845b881998-06-01 10:44:35 +00001866 if (flags & MF_OWNERDRAW)
1867 item->dwItemData = (DWORD)str;
1868 else
1869 item->dwItemData = 0;
1870
Alexandre Julliard02e90081998-01-04 17:49:09 +00001871 if ((item->fType & MF_POPUP) && (flags & MF_POPUP) && (item->hSubMenu != id) )
Alexandre Julliarda3960291999-02-26 11:11:13 +00001872 DestroyMenu( item->hSubMenu ); /* ModifyMenu() spec */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001873
1874 if (flags & MF_POPUP)
1875 {
Gerard Patel3e629742000-01-17 22:22:16 +00001876 POPUPMENU *menu = MENU_GetMenu((UINT16)id);
1877 if (menu) menu->wFlags |= MF_POPUP;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001878 else
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001879 {
1880 item->wID = 0;
1881 item->hSubMenu = 0;
1882 item->fType = 0;
1883 item->fState = 0;
1884 return FALSE;
1885 }
Alexandre Julliard02e90081998-01-04 17:49:09 +00001886 }
1887
1888 item->wID = id;
1889 if (flags & MF_POPUP)
1890 item->hSubMenu = id;
1891
1892 if ((item->fType & MF_POPUP) && !(flags & MF_POPUP) )
1893 flags |= MF_POPUP; /* keep popup */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001894
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001895 item->fType = flags & TYPE_MASK;
1896 item->fState = (flags & STATE_MASK) &
1897 ~(MF_HILITE | MF_MOUSESELECT | MF_BYPOSITION);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001898
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001899
1900 /* Don't call SetRectEmpty here! */
1901
1902
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001903 if (prevText) HeapFree( SystemHeap, 0, prevText );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001904
Alexandre Julliard03468f71998-02-15 19:40:49 +00001905 debug_print_menuitem("MENU_SetItemData to : ", item, "");
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001906 return TRUE;
1907}
1908
1909
1910/**********************************************************************
1911 * MENU_InsertItem
1912 *
1913 * Insert a new item into a menu.
1914 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001915static MENUITEM *MENU_InsertItem( HMENU hMenu, UINT pos, UINT flags )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001916{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001917 MENUITEM *newItems;
1918 POPUPMENU *menu;
1919
Gerard Patel3e629742000-01-17 22:22:16 +00001920 if (!(menu = MENU_GetMenu(hMenu)))
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001921 return NULL;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001922
1923 /* Find where to insert new item */
1924
Gerard Patelc6369b02000-05-14 22:52:52 +00001925 if (flags & MF_BYPOSITION) {
1926 if (pos > menu->nItems)
1927 pos = menu->nItems;
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00001928 } else {
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001929 if (!MENU_FindItem( &hMenu, &pos, flags ))
Gerard Patelc6369b02000-05-14 22:52:52 +00001930 pos = menu->nItems;
1931 else {
1932 if (!(menu = MENU_GetMenu( hMenu )))
1933 return NULL;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001934 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001935 }
1936
1937 /* Create new items array */
1938
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001939 newItems = HeapAlloc( SystemHeap, 0, sizeof(MENUITEM) * (menu->nItems+1) );
1940 if (!newItems)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001941 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001942 WARN("allocation failed\n" );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001943 return NULL;
1944 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001945 if (menu->nItems > 0)
1946 {
1947 /* Copy the old array into the new */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001948 if (pos > 0) memcpy( newItems, menu->items, pos * sizeof(MENUITEM) );
1949 if (pos < menu->nItems) memcpy( &newItems[pos+1], &menu->items[pos],
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001950 (menu->nItems-pos)*sizeof(MENUITEM) );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001951 HeapFree( SystemHeap, 0, menu->items );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001952 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001953 menu->items = newItems;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001954 menu->nItems++;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001955 memset( &newItems[pos], 0, sizeof(*newItems) );
Gerard Patel6df06941999-09-28 13:05:54 +00001956 menu->Height = 0; /* force size recalculate */
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001957 return &newItems[pos];
1958}
1959
1960
1961/**********************************************************************
1962 * MENU_ParseResource
1963 *
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001964 * Parse a standard menu resource and add items to the menu.
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001965 * Return a pointer to the end of the resource.
1966 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001967static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001968{
1969 WORD flags, id = 0;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001970 LPCSTR str;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001971
1972 do
1973 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001974 flags = GET_WORD(res);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001975 res += sizeof(WORD);
1976 if (!(flags & MF_POPUP))
1977 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001978 id = GET_WORD(res);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001979 res += sizeof(WORD);
1980 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001981 if (!IS_STRING_ITEM(flags))
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001982 ERR("not a string item %04x\n", flags );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001983 str = res;
1984 if (!unicode) res += strlen(str) + 1;
Aric Stewartc946b1c2000-10-24 21:28:19 +00001985 else res += (strlenW((LPCWSTR)str) + 1) * sizeof(WCHAR);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001986 if (flags & MF_POPUP)
1987 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001988 HMENU hSubMenu = CreatePopupMenu();
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001989 if (!hSubMenu) return NULL;
1990 if (!(res = MENU_ParseResource( res, hSubMenu, unicode )))
1991 return NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001992 if (!unicode) AppendMenuA( hMenu, flags, (UINT)hSubMenu, str );
1993 else AppendMenuW( hMenu, flags, (UINT)hSubMenu, (LPCWSTR)str );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001994 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001995 else /* Not a popup */
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001996 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001997 if (!unicode) AppendMenuA( hMenu, flags, id, *str ? str : NULL );
1998 else AppendMenuW( hMenu, flags, id,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001999 *(LPCWSTR)str ? (LPCWSTR)str : NULL );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00002000 }
2001 } while (!(flags & MF_END));
2002 return res;
2003}
2004
2005
Alexandre Julliard641ee761997-08-04 16:34:36 +00002006/**********************************************************************
2007 * MENUEX_ParseResource
2008 *
2009 * Parse an extended menu resource and add items to the menu.
2010 * Return a pointer to the end of the resource.
2011 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002012static LPCSTR MENUEX_ParseResource( LPCSTR res, HMENU hMenu)
Alexandre Julliard641ee761997-08-04 16:34:36 +00002013{
Alexandre Julliard641ee761997-08-04 16:34:36 +00002014 WORD resinfo;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002015 do {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002016 MENUITEMINFOW mii;
Alexandre Julliard641ee761997-08-04 16:34:36 +00002017
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002018 mii.cbSize = sizeof(mii);
2019 mii.fMask = MIIM_STATE | MIIM_ID | MIIM_TYPE;
2020 mii.fType = GET_DWORD(res);
Alexandre Julliard641ee761997-08-04 16:34:36 +00002021 res += sizeof(DWORD);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002022 mii.fState = GET_DWORD(res);
Alexandre Julliard641ee761997-08-04 16:34:36 +00002023 res += sizeof(DWORD);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002024 mii.wID = GET_DWORD(res);
Alexandre Julliard641ee761997-08-04 16:34:36 +00002025 res += sizeof(DWORD);
2026 resinfo = GET_WORD(res); /* FIXME: for 16-bit apps this is a byte. */
2027 res += sizeof(WORD);
2028 /* Align the text on a word boundary. */
2029 res += (~((int)res - 1)) & 1;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002030 mii.dwTypeData = (LPWSTR) res;
Aric Stewartc946b1c2000-10-24 21:28:19 +00002031 res += (1 + strlenW(mii.dwTypeData)) * sizeof(WCHAR);
Alexandre Julliard641ee761997-08-04 16:34:36 +00002032 /* Align the following fields on a dword boundary. */
2033 res += (~((int)res - 1)) & 3;
2034
2035 /* FIXME: This is inefficient and cannot be optimised away by gcc. */
2036 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002037 LPSTR newstr = HEAP_strdupWtoA(GetProcessHeap(),
2038 0, mii.dwTypeData);
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002039 TRACE("Menu item: [%08x,%08x,%04x,%04x,%s]\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002040 mii.fType, mii.fState, mii.wID, resinfo, newstr);
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002041 HeapFree( GetProcessHeap(), 0, newstr );
Alexandre Julliard641ee761997-08-04 16:34:36 +00002042 }
2043
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002044 if (resinfo & 1) { /* Pop-up? */
Marcus Meissnerde43ef41999-02-28 19:56:59 +00002045 /* DWORD helpid = GET_DWORD(res); FIXME: use this. */
Alexandre Julliard641ee761997-08-04 16:34:36 +00002046 res += sizeof(DWORD);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002047 mii.hSubMenu = CreatePopupMenu();
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002048 if (!mii.hSubMenu)
2049 return NULL;
2050 if (!(res = MENUEX_ParseResource(res, mii.hSubMenu))) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002051 DestroyMenu(mii.hSubMenu);
Alexandre Julliard641ee761997-08-04 16:34:36 +00002052 return NULL;
Alexandre Julliard641ee761997-08-04 16:34:36 +00002053 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002054 mii.fMask |= MIIM_SUBMENU;
2055 mii.fType |= MF_POPUP;
Alexandre Julliard641ee761997-08-04 16:34:36 +00002056 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002057 InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii);
Alexandre Julliard641ee761997-08-04 16:34:36 +00002058 } while (!(resinfo & MF_END));
2059 return res;
2060}
2061
2062
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002063/***********************************************************************
2064 * MENU_GetSubPopup
2065 *
2066 * Return the handle of the selected sub-popup menu (if any).
2067 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002068static HMENU MENU_GetSubPopup( HMENU hmenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002069{
2070 POPUPMENU *menu;
2071 MENUITEM *item;
2072
Gerard Patel3e629742000-01-17 22:22:16 +00002073 menu = MENU_GetMenu( hmenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002074
Gerard Patel3e629742000-01-17 22:22:16 +00002075 if ((!menu) || (menu->FocusedItem == NO_SELECTED_ITEM)) return 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002076
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002077 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002078 if ((item->fType & MF_POPUP) && (item->fState & MF_MOUSESELECT))
2079 return item->hSubMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002080 return 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002081}
2082
2083
2084/***********************************************************************
2085 * MENU_HideSubPopups
2086 *
2087 * Hide the sub-popup menus of this menu.
2088 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002089static void MENU_HideSubPopups( HWND hwndOwner, HMENU hmenu,
2090 BOOL sendMenuSelect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002091{
Gerard Patel3e629742000-01-17 22:22:16 +00002092 POPUPMENU *menu = MENU_GetMenu( hmenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002093
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002094 TRACE("owner=0x%04x hmenu=0x%04x 0x%04x\n", hwndOwner, hmenu, sendMenuSelect);
Juergen Schmied466a6521999-05-02 11:21:08 +00002095
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002096 if (menu && uSubPWndLevel)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002097 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002098 HMENU hsubmenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002099 POPUPMENU *submenu;
2100 MENUITEM *item;
2101
2102 if (menu->FocusedItem != NO_SELECTED_ITEM)
2103 {
2104 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002105 if (!(item->fType & MF_POPUP) ||
2106 !(item->fState & MF_MOUSESELECT)) return;
2107 item->fState &= ~MF_MOUSESELECT;
2108 hsubmenu = item->hSubMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002109 } else return;
2110
Gerard Patel3e629742000-01-17 22:22:16 +00002111 submenu = MENU_GetMenu( hsubmenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002112 MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00002113 MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002114
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002115 if (submenu->hWnd == MENU_GetTopPopupWnd()->hwndSelf )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002116 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002117 ShowWindow( submenu->hWnd, SW_HIDE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002118 uSubPWndLevel = 0;
2119 }
2120 else
2121 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002122 DestroyWindow( submenu->hWnd );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002123 submenu->hWnd = 0;
2124 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002125 MENU_ReleaseTopPopupWnd();
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002126 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002127}
2128
2129
2130/***********************************************************************
2131 * MENU_ShowSubPopup
2132 *
2133 * Display the sub-menu of the selected item of this menu.
2134 * Return the handle of the submenu, or hmenu if no submenu to display.
2135 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002136static HMENU MENU_ShowSubPopup( HWND hwndOwner, HMENU hmenu,
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002137 BOOL selectFirst, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002138{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002139 RECT rect;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002140 POPUPMENU *menu;
2141 MENUITEM *item;
2142 WND *wndPtr;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002143 HDC hdc;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002144
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002145 TRACE("owner=0x%04x hmenu=0x%04x 0x%04x\n", hwndOwner, hmenu, selectFirst);
Juergen Schmied466a6521999-05-02 11:21:08 +00002146
Gerard Patel3e629742000-01-17 22:22:16 +00002147 if (!(menu = MENU_GetMenu( hmenu ))) return hmenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002148
2149 if (!(wndPtr = WIN_FindWndPtr( menu->hWnd )) ||
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002150 (menu->FocusedItem == NO_SELECTED_ITEM))
2151 {
2152 WIN_ReleaseWndPtr(wndPtr);
2153 return hmenu;
2154 }
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 if (!(item->fType & MF_POPUP) ||
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002158 (item->fState & (MF_GRAYED | MF_DISABLED)))
2159 {
2160 WIN_ReleaseWndPtr(wndPtr);
2161 return hmenu;
2162 }
Alexandre Julliard02e90081998-01-04 17:49:09 +00002163
2164 /* message must be send before using item,
2165 because nearly everything may by changed by the application ! */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002166
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002167 /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
2168 if (!(wFlags & TPM_NONOTIFY))
2169 SendMessageA( hwndOwner, WM_INITMENUPOPUP, item->hSubMenu,
Alexandre Julliard02e90081998-01-04 17:49:09 +00002170 MAKELONG( menu->FocusedItem, IS_SYSTEM_MENU(menu) ));
2171
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002172 item = &menu->items[menu->FocusedItem];
2173 rect = item->rect;
2174
Alexandre Julliard02e90081998-01-04 17:49:09 +00002175 /* correct item if modified as a reaction to WM_INITMENUPOPUP-message */
2176 if (!(item->fState & MF_HILITE))
2177 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002178 if (menu->wFlags & MF_POPUP) hdc = GetDC( menu->hWnd );
2179 else hdc = GetDCEx( menu->hWnd, 0, DCX_CACHE | DCX_WINDOW);
Juergen Schmied78513941999-04-18 14:40:32 +00002180
2181 SelectObject( hdc, hMenuFont);
2182
Alexandre Julliard02e90081998-01-04 17:49:09 +00002183 item->fState |= MF_HILITE;
Juergen Schmied78513941999-04-18 14:40:32 +00002184 MENU_DrawMenuItem( menu->hWnd, hmenu, hwndOwner, hdc, item, menu->Height, !(menu->wFlags & MF_POPUP), ODA_DRAWENTIRE );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002185 ReleaseDC( menu->hWnd, hdc );
Alexandre Julliard02e90081998-01-04 17:49:09 +00002186 }
2187 if (!item->rect.top && !item->rect.left && !item->rect.bottom && !item->rect.right)
2188 item->rect = rect;
2189
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002190 item->fState |= MF_MOUSESELECT;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002191
2192 if (IS_SYSTEM_MENU(menu))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002193 {
Patrik Stridvall4bf33541999-06-12 14:52:15 +00002194 MENU_InitSysMenuPopup(item->hSubMenu, wndPtr->dwStyle, GetClassLongA(wndPtr->hwndSelf, GCL_STYLE));
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002195
2196 NC_GetSysPopupPos( wndPtr, &rect );
2197 rect.top = rect.bottom;
Marcus Meissnerddca3151999-05-22 11:33:23 +00002198 rect.right = GetSystemMetrics(SM_CXSIZE);
2199 rect.bottom = GetSystemMetrics(SM_CYSIZE);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002200 }
2201 else
2202 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002203 if (menu->wFlags & MF_POPUP)
2204 {
Ken Thomases130f0d82000-05-10 21:38:37 +00002205 rect.left = wndPtr->rectWindow.left + item->rect.right - GetSystemMetrics(SM_CXBORDER);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002206 rect.top = wndPtr->rectWindow.top + item->rect.top;
Ken Thomases130f0d82000-05-10 21:38:37 +00002207 rect.right = item->rect.left - item->rect.right + GetSystemMetrics(SM_CXBORDER);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002208 rect.bottom = item->rect.top - item->rect.bottom;
2209 }
2210 else
2211 {
2212 rect.left = wndPtr->rectWindow.left + item->rect.left;
2213 rect.top = wndPtr->rectWindow.top + item->rect.bottom;
2214 rect.right = item->rect.right - item->rect.left;
2215 rect.bottom = item->rect.bottom - item->rect.top;
2216 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002217 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002218
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002219 MENU_ShowPopup( hwndOwner, item->hSubMenu, menu->FocusedItem,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002220 rect.left, rect.top, rect.right, rect.bottom );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002221 if (selectFirst)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002222 MENU_MoveSelection( hwndOwner, item->hSubMenu, ITEM_NEXT );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002223 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002224 return item->hSubMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002225}
2226
Ulrich Czekalla33026a22000-02-26 19:13:44 +00002227
2228
2229/**********************************************************************
2230 * MENU_IsMenuActive
2231 */
2232BOOL MENU_IsMenuActive(void)
2233{
2234 return pTopPopupWnd && (pTopPopupWnd->dwStyle & WS_VISIBLE);
2235}
2236
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002237/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002238 * MENU_PtMenu
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002239 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002240 * Walks menu chain trying to find a menu pt maps to.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002241 */
Alexandre Julliard83f52d12000-09-26 22:20:14 +00002242static HMENU MENU_PtMenu( HMENU hMenu, POINT pt )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002243{
Gerard Patel3e629742000-01-17 22:22:16 +00002244 POPUPMENU *menu = MENU_GetMenu( hMenu );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002245 register UINT ht = menu->FocusedItem;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002246
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002247 /* try subpopup first (if any) */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002248 ht = (ht != NO_SELECTED_ITEM &&
2249 (menu->items[ht].fType & MF_POPUP) &&
2250 (menu->items[ht].fState & MF_MOUSESELECT))
Alexandre Julliarda3960291999-02-26 11:11:13 +00002251 ? (UINT) MENU_PtMenu(menu->items[ht].hSubMenu, pt) : 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002252
2253 if( !ht ) /* check the current window (avoiding WM_HITTEST) */
2254 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002255 ht = (UINT)NC_HandleNCHitTest( menu->hWnd, pt );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002256 if( menu->wFlags & MF_POPUP )
Alexandre Julliarda3960291999-02-26 11:11:13 +00002257 ht = (ht != (UINT)HTNOWHERE &&
2258 ht != (UINT)HTERROR) ? (UINT)hMenu : 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002259 else
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002260 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002261 WND* wndPtr = WIN_FindWndPtr(menu->hWnd);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002262
Alexandre Julliarda3960291999-02-26 11:11:13 +00002263 ht = ( ht == HTSYSMENU ) ? (UINT)(wndPtr->hSysMenu)
2264 : ( ht == HTMENU ) ? (UINT)(wndPtr->wIDmenu) : 0;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002265 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002266 }
2267 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002268 return (HMENU)ht;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002269}
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002270
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002271/***********************************************************************
2272 * MENU_ExecFocusedItem
2273 *
2274 * Execute a menu item (for instance when user pressed Enter).
Karl Lessard13409b31999-09-28 16:24:58 +00002275 * Return the wID of the executed item. Otherwise, -1 indicating
Andreas Mohr2e011a52000-06-01 23:28:25 +00002276 * that no menu item was executed;
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002277 * Have to receive the flags for the TrackPopupMenu options to avoid
2278 * sending unwanted message.
2279 *
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002280 */
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002281static INT MENU_ExecFocusedItem( MTRACKER* pmt, HMENU hMenu, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002282{
2283 MENUITEM *item;
Gerard Patel3e629742000-01-17 22:22:16 +00002284 POPUPMENU *menu = MENU_GetMenu( hMenu );
Juergen Schmied466a6521999-05-02 11:21:08 +00002285
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002286 TRACE("%p hmenu=0x%04x\n", pmt, hMenu);
Juergen Schmied466a6521999-05-02 11:21:08 +00002287
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002288 if (!menu || !menu->nItems ||
Karl Lessard13409b31999-09-28 16:24:58 +00002289 (menu->FocusedItem == NO_SELECTED_ITEM)) return -1;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002290
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002291 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002292
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002293 TRACE("%08x %08x %08x\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002294 hMenu, item->wID, item->hSubMenu);
2295
2296 if (!(item->fType & MF_POPUP))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002297 {
Francois Gouget93fd46a2000-10-23 00:37:49 +00002298 if (!(item->fState & (MF_GRAYED | MF_DISABLED)) && !(item->fType & MF_SEPARATOR))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002299 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002300 /* If TPM_RETURNCMD is set you return the id, but
2301 do not send a message to the owner */
2302 if(!(wFlags & TPM_RETURNCMD))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002303 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002304 if( menu->wFlags & MF_SYSMENU )
2305 PostMessageA( pmt->hOwnerWnd, WM_SYSCOMMAND, item->wID,
2306 MAKELPARAM((INT16)pmt->pt.x, (INT16)pmt->pt.y) );
2307 else
2308 PostMessageA( pmt->hOwnerWnd, WM_COMMAND, item->wID, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002309 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002310 return item->wID;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002311 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002312 }
2313 else
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002314 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hMenu, TRUE, wFlags);
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002315
Karl Lessard13409b31999-09-28 16:24:58 +00002316 return -1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002317}
2318
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002319/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002320 * MENU_SwitchTracking
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002321 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002322 * Helper function for menu navigation routines.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002323 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002324static void MENU_SwitchTracking( MTRACKER* pmt, HMENU hPtMenu, UINT id )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002325{
Gerard Patel3e629742000-01-17 22:22:16 +00002326 POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
2327 POPUPMENU *topmenu = MENU_GetMenu( pmt->hTopMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002328
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002329 TRACE("%p hmenu=0x%04x 0x%04x\n", pmt, hPtMenu, id);
Juergen Schmied466a6521999-05-02 11:21:08 +00002330
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002331 if( pmt->hTopMenu != hPtMenu &&
2332 !((ptmenu->wFlags | topmenu->wFlags) & MF_POPUP) )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002333 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002334 /* both are top level menus (system and menu-bar) */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002335 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00002336 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM, FALSE, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002337 pmt->hTopMenu = hPtMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002338 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002339 else MENU_HideSubPopups( pmt->hOwnerWnd, hPtMenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00002340 MENU_SelectItem( pmt->hOwnerWnd, hPtMenu, id, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002341}
2342
2343
2344/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002345 * MENU_ButtonDown
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002346 *
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002347 * Return TRUE if we can go on with menu tracking.
2348 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002349static BOOL MENU_ButtonDown( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002350{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002351 TRACE("%p hmenu=0x%04x\n", pmt, hPtMenu);
Juergen Schmied466a6521999-05-02 11:21:08 +00002352
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002353 if (hPtMenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002354 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002355 UINT id = 0;
Gerard Patel3e629742000-01-17 22:22:16 +00002356 POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002357 MENUITEM *item;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002358
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002359 if( IS_SYSTEM_MENU(ptmenu) )
2360 item = ptmenu->items;
2361 else
2362 item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002363
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002364 if( item )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002365 {
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002366 if( ptmenu->FocusedItem != id )
2367 MENU_SwitchTracking( pmt, hPtMenu, id );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002368
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002369 /* If the popup menu is not already "popped" */
2370 if(!(item->fState & MF_MOUSESELECT ))
Pascal Lessard07c447f1999-09-19 12:03:25 +00002371 {
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002372 pmt->hCurrentMenu = MENU_ShowSubPopup( pmt->hOwnerWnd, hPtMenu, FALSE, wFlags );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002373
Pascal Lessard07c447f1999-09-19 12:03:25 +00002374 /* In win31, a newly popped menu always remain opened for the next buttonup */
2375 if(TWEAK_WineLook == WIN31_LOOK)
2376 ptmenu->bTimeToHide = FALSE;
2377 }
2378
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002379 return TRUE;
2380 }
Pascal Lessard445c9101999-09-20 18:27:14 +00002381 /* Else the click was on the menu bar, finish the tracking */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002382 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002383 return FALSE;
2384}
2385
2386/***********************************************************************
2387 * MENU_ButtonUp
2388 *
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002389 * Return the value of MENU_ExecFocusedItem if
2390 * the selected item was not a popup. Else open the popup.
Karl Lessard13409b31999-09-28 16:24:58 +00002391 * A -1 return value indicates that we go on with menu tracking.
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002392 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002393 */
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002394static INT MENU_ButtonUp( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002395{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002396 TRACE("%p hmenu=0x%04x\n", pmt, hPtMenu);
Juergen Schmied466a6521999-05-02 11:21:08 +00002397
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002398 if (hPtMenu)
2399 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002400 UINT id = 0;
Gerard Patel3e629742000-01-17 22:22:16 +00002401 POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002402 MENUITEM *item;
2403
2404 if( IS_SYSTEM_MENU(ptmenu) )
2405 item = ptmenu->items;
2406 else
2407 item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
2408
Alexandre Julliard491502b1997-11-01 19:08:16 +00002409 if( item && (ptmenu->FocusedItem == id ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002410 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002411 if( !(item->fType & MF_POPUP) )
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002412 return MENU_ExecFocusedItem( pmt, hPtMenu, wFlags);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002413
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002414 /* If we are dealing with the top-level menu and that this */
2415 /* is a click on an already "poppped" item */
2416 /* Stop the menu tracking and close the opened submenus */
2417 if((pmt->hTopMenu == hPtMenu) && (ptmenu->bTimeToHide == TRUE))
Karl Lessard13409b31999-09-28 16:24:58 +00002418 return 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002419 }
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002420 ptmenu->bTimeToHide = TRUE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002421 }
Karl Lessard13409b31999-09-28 16:24:58 +00002422 return -1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002423}
2424
2425
2426/***********************************************************************
2427 * MENU_MouseMove
2428 *
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002429 * Return TRUE if we can go on with menu tracking.
2430 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002431static BOOL MENU_MouseMove( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002432{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002433 UINT id = NO_SELECTED_ITEM;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002434 POPUPMENU *ptmenu = NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002435
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002436 if( hPtMenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002437 {
Gerard Patel3e629742000-01-17 22:22:16 +00002438 ptmenu = MENU_GetMenu( hPtMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002439 if( IS_SYSTEM_MENU(ptmenu) )
2440 id = 0;
2441 else
2442 MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
2443 }
2444
2445 if( id == NO_SELECTED_ITEM )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002446 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002447 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002448 NO_SELECTED_ITEM, TRUE, pmt->hTopMenu);
2449
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002450 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002451 else if( ptmenu->FocusedItem != id )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002452 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002453 MENU_SwitchTracking( pmt, hPtMenu, id );
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002454 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hPtMenu, FALSE, wFlags);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002455 }
2456 return TRUE;
2457}
2458
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002459
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002460/***********************************************************************
2461 * MENU_DoNextMenu
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002462 *
2463 * NOTE: WM_NEXTMENU documented in Win32 is a bit different.
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002464 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002465static LRESULT MENU_DoNextMenu( MTRACKER* pmt, UINT vk )
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002466{
Gerard Patel3e629742000-01-17 22:22:16 +00002467 POPUPMENU *menu = MENU_GetMenu( pmt->hTopMenu );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002468
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002469 if( (vk == VK_LEFT && menu->FocusedItem == 0 ) ||
2470 (vk == VK_RIGHT && menu->FocusedItem == menu->nItems - 1))
2471 {
2472 WND* wndPtr;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002473 HMENU hNewMenu;
2474 HWND hNewWnd;
2475 UINT id = 0;
Juergen Schmied78513941999-04-18 14:40:32 +00002476 LRESULT l = SendMessageA( pmt->hOwnerWnd, WM_NEXTMENU, vk,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002477 (IS_SYSTEM_MENU(menu)) ? GetSubMenu16(pmt->hTopMenu,0) : pmt->hTopMenu );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002478
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002479 TRACE("%04x [%04x] -> %04x [%04x]\n",
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002480 (UINT16)pmt->hCurrentMenu, (UINT16)pmt->hOwnerWnd, LOWORD(l), HIWORD(l) );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002481
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002482 if( l == 0 )
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002483 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002484 wndPtr = WIN_FindWndPtr(pmt->hOwnerWnd);
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002485
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002486 hNewWnd = pmt->hOwnerWnd;
2487 if( IS_SYSTEM_MENU(menu) )
2488 {
2489 /* switch to the menu bar */
2490
2491 if( wndPtr->dwStyle & WS_CHILD || !wndPtr->wIDmenu )
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002492 {
2493 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002494 return FALSE;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002495 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002496
2497 hNewMenu = wndPtr->wIDmenu;
2498 if( vk == VK_LEFT )
2499 {
Gerard Patel3e629742000-01-17 22:22:16 +00002500 menu = MENU_GetMenu( hNewMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002501 id = menu->nItems - 1;
2502 }
2503 }
2504 else if( wndPtr->dwStyle & WS_SYSMENU )
2505 {
2506 /* switch to the system menu */
2507 hNewMenu = wndPtr->hSysMenu;
2508 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002509 else
2510 {
2511 WIN_ReleaseWndPtr(wndPtr);
2512 return FALSE;
2513 }
2514 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002515 }
2516 else /* application returned a new menu to switch to */
2517 {
2518 hNewMenu = LOWORD(l); hNewWnd = HIWORD(l);
2519
Alexandre Julliarda3960291999-02-26 11:11:13 +00002520 if( IsMenu(hNewMenu) && IsWindow(hNewWnd) )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002521 {
2522 wndPtr = WIN_FindWndPtr(hNewWnd);
2523
2524 if( wndPtr->dwStyle & WS_SYSMENU &&
2525 GetSubMenu16(wndPtr->hSysMenu, 0) == hNewMenu )
2526 {
2527 /* get the real system menu */
2528 hNewMenu = wndPtr->hSysMenu;
2529 }
2530 else if( wndPtr->dwStyle & WS_CHILD || wndPtr->wIDmenu != hNewMenu )
2531 {
2532 /* FIXME: Not sure what to do here, perhaps,
2533 * try to track hNewMenu as a popup? */
2534
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002535 TRACE(" -- got confused.\n");
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002536 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002537 return FALSE;
2538 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002539 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002540 }
2541 else return FALSE;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002542 }
2543
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002544 if( hNewMenu != pmt->hTopMenu )
2545 {
Rein Klazes80c924f1999-12-12 19:40:46 +00002546 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM,
2547 FALSE, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002548 if( pmt->hCurrentMenu != pmt->hTopMenu )
2549 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
2550 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002551
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002552 if( hNewWnd != pmt->hOwnerWnd )
2553 {
2554 ReleaseCapture();
2555 pmt->hOwnerWnd = hNewWnd;
2556 EVENT_Capture( pmt->hOwnerWnd, HTMENU );
2557 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002558
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002559 pmt->hTopMenu = pmt->hCurrentMenu = hNewMenu; /* all subpopups are hidden */
Rein Klazes80c924f1999-12-12 19:40:46 +00002560 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, id, TRUE, 0 );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002561
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002562 return TRUE;
2563 }
2564 return FALSE;
2565}
2566
2567/***********************************************************************
2568 * MENU_SuspendPopup
2569 *
2570 * The idea is not to show the popup if the next input message is
2571 * going to hide it anyway.
2572 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002573static BOOL MENU_SuspendPopup( MTRACKER* pmt, UINT16 uMsg )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002574{
Juergen Schmied78513941999-04-18 14:40:32 +00002575 MSG msg;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002576
2577 msg.hwnd = pmt->hOwnerWnd;
2578
Juergen Schmied78513941999-04-18 14:40:32 +00002579 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002580 pmt->trackFlags |= TF_SKIPREMOVE;
2581
2582 switch( uMsg )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002583 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002584 case WM_KEYDOWN:
Juergen Schmied78513941999-04-18 14:40:32 +00002585 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002586 if( msg.message == WM_KEYUP || msg.message == WM_PAINT )
2587 {
Juergen Schmied78513941999-04-18 14:40:32 +00002588 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE);
2589 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002590 if( msg.message == WM_KEYDOWN &&
2591 (msg.wParam == VK_LEFT || msg.wParam == VK_RIGHT))
2592 {
2593 pmt->trackFlags |= TF_SUSPENDPOPUP;
2594 return TRUE;
2595 }
2596 }
2597 break;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002598 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002599
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002600 /* failures go through this */
2601 pmt->trackFlags &= ~TF_SUSPENDPOPUP;
2602 return FALSE;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002603}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002604
2605/***********************************************************************
2606 * MENU_KeyLeft
2607 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002608 * Handle a VK_LEFT key event in a menu.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002609 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002610static void MENU_KeyLeft( MTRACKER* pmt, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002611{
2612 POPUPMENU *menu;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002613 HMENU hmenutmp, hmenuprev;
2614 UINT prevcol;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002615
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002616 hmenuprev = hmenutmp = pmt->hTopMenu;
Gerard Patel3e629742000-01-17 22:22:16 +00002617 menu = MENU_GetMenu( hmenutmp );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002618
Alexandre Julliard641ee761997-08-04 16:34:36 +00002619 /* Try to move 1 column left (if possible) */
2620 if( (prevcol = MENU_GetStartOfPrevColumn( pmt->hCurrentMenu )) !=
2621 NO_SELECTED_ITEM ) {
2622
2623 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002624 prevcol, TRUE, 0 );
Alexandre Julliard641ee761997-08-04 16:34:36 +00002625 return;
2626 }
2627
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002628 /* close topmost popup */
2629 while (hmenutmp != pmt->hCurrentMenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002630 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002631 hmenuprev = hmenutmp;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002632 hmenutmp = MENU_GetSubPopup( hmenuprev );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002633 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002634
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002635 MENU_HideSubPopups( pmt->hOwnerWnd, hmenuprev, TRUE );
2636 pmt->hCurrentMenu = hmenuprev;
2637
2638 if ( (hmenuprev == pmt->hTopMenu) && !(menu->wFlags & MF_POPUP) )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002639 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002640 /* move menu bar selection if no more popups are left */
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002641
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002642 if( !MENU_DoNextMenu( pmt, VK_LEFT) )
2643 MENU_MoveSelection( pmt->hOwnerWnd, pmt->hTopMenu, ITEM_PREV );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002644
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002645 if ( hmenuprev != hmenutmp || pmt->trackFlags & TF_SUSPENDPOPUP )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002646 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002647 /* A sublevel menu was displayed - display the next one
2648 * unless there is another displacement coming up */
2649
2650 if( !MENU_SuspendPopup( pmt, WM_KEYDOWN ) )
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002651 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd,
2652 pmt->hTopMenu, TRUE, wFlags);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002653 }
2654 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002655}
2656
2657
2658/***********************************************************************
2659 * MENU_KeyRight
2660 *
2661 * Handle a VK_RIGHT key event in a menu.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002662 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002663static void MENU_KeyRight( MTRACKER* pmt, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002664{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002665 HMENU hmenutmp;
Gerard Patel3e629742000-01-17 22:22:16 +00002666 POPUPMENU *menu = MENU_GetMenu( pmt->hTopMenu );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002667 UINT nextcol;
Alexandre Julliard641ee761997-08-04 16:34:36 +00002668
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002669 TRACE("MENU_KeyRight called, cur %x (%s), top %x (%s).\n",
Alexandre Julliard641ee761997-08-04 16:34:36 +00002670 pmt->hCurrentMenu,
Aric Stewartc946b1c2000-10-24 21:28:19 +00002671 debugstr_w((MENU_GetMenu(pmt->hCurrentMenu))->
2672 items[0].text),
2673 pmt->hTopMenu, debugstr_w(menu->items[0].text) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002674
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002675 if ( (menu->wFlags & MF_POPUP) || (pmt->hCurrentMenu != pmt->hTopMenu))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002676 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002677 /* If already displaying a popup, try to display sub-popup */
2678
2679 hmenutmp = pmt->hCurrentMenu;
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002680 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hmenutmp, TRUE, wFlags);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002681
2682 /* if subpopup was displayed then we are done */
2683 if (hmenutmp != pmt->hCurrentMenu) return;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002684 }
2685
Alexandre Julliard641ee761997-08-04 16:34:36 +00002686 /* Check to see if there's another column */
2687 if( (nextcol = MENU_GetStartOfNextColumn( pmt->hCurrentMenu )) !=
2688 NO_SELECTED_ITEM ) {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002689 TRACE("Going to %d.\n", nextcol );
Alexandre Julliard641ee761997-08-04 16:34:36 +00002690 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002691 nextcol, TRUE, 0 );
Alexandre Julliard641ee761997-08-04 16:34:36 +00002692 return;
2693 }
2694
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002695 if (!(menu->wFlags & MF_POPUP)) /* menu bar tracking */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002696 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002697 if( pmt->hCurrentMenu != pmt->hTopMenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002698 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002699 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
2700 hmenutmp = pmt->hCurrentMenu = pmt->hTopMenu;
2701 } else hmenutmp = 0;
2702
2703 /* try to move to the next item */
2704 if( !MENU_DoNextMenu( pmt, VK_RIGHT) )
2705 MENU_MoveSelection( pmt->hOwnerWnd, pmt->hTopMenu, ITEM_NEXT );
2706
2707 if( hmenutmp || pmt->trackFlags & TF_SUSPENDPOPUP )
2708 if( !MENU_SuspendPopup(pmt, WM_KEYDOWN) )
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002709 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd,
2710 pmt->hTopMenu, TRUE, wFlags);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002711 }
2712}
2713
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002714/***********************************************************************
2715 * MENU_TrackMenu
2716 *
2717 * Menu tracking code.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002718 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002719static INT MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y,
2720 HWND hwnd, const RECT *lprect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002721{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002722 MSG msg;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002723 POPUPMENU *menu;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002724 BOOL fRemove;
Karl Lessard13409b31999-09-28 16:24:58 +00002725 INT executedMenuId = -1;
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +00002726 MTRACKER mt;
Francis Beaudet7ed1af31999-08-15 16:58:03 +00002727 BOOL enterIdleSent = FALSE;
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +00002728
2729 mt.trackFlags = 0;
2730 mt.hCurrentMenu = hmenu;
2731 mt.hTopMenu = hmenu;
2732 mt.hOwnerWnd = hwnd;
2733 mt.pt.x = x;
2734 mt.pt.y = y;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002735
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002736 TRACE("hmenu=0x%04x flags=0x%08x (%d,%d) hwnd=0x%04x (%d,%d)-(%d,%d)\n",
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00002737 hmenu, wFlags, x, y, hwnd, (lprect) ? lprect->left : 0, (lprect) ? lprect->top : 0,
2738 (lprect) ? lprect->right : 0, (lprect) ? lprect->bottom : 0);
Juergen Schmied78513941999-04-18 14:40:32 +00002739
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002740 fEndMenu = FALSE;
Gerard Patel3e629742000-01-17 22:22:16 +00002741 if (!(menu = MENU_GetMenu( hmenu ))) return FALSE;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002742
Pascal Lessardae6de762000-01-09 02:38:02 +00002743 if (wFlags & TPM_BUTTONDOWN)
2744 {
2745 /* Get the result in order to start the tracking or not */
2746 fRemove = MENU_ButtonDown( &mt, hmenu, wFlags );
2747 fEndMenu = !fRemove;
2748 }
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002749
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002750 EVENT_Capture( mt.hOwnerWnd, HTMENU );
2751
2752 while (!fEndMenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002753 {
Gerard Patel3e629742000-01-17 22:22:16 +00002754 menu = MENU_GetMenu( mt.hCurrentMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002755 msg.hwnd = (wFlags & TPM_ENTERIDLEEX && menu->wFlags & MF_POPUP) ? menu->hWnd : 0;
2756
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002757 /* we have to keep the message in the queue until it's
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002758 * clear that menu loop is not over yet. */
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002759
Ulrich Weigand2faf2cf1999-12-10 03:47:13 +00002760 if (!MSG_InternalGetMessage( QMSG_WIN32A, &msg, msg.hwnd, mt.hOwnerWnd,
Francis Beaudet7ed1af31999-08-15 16:58:03 +00002761 MSGF_MENU, PM_NOREMOVE, !enterIdleSent, &enterIdleSent )) break;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002762
Rob Farnumb2007932000-05-23 23:34:17 +00002763 /* check if EndMenu() tried to cancel us, by posting this message */
2764 if(msg.message == WM_CANCELMODE)
2765 {
2766 /* we are now out of the loop */
2767 fEndMenu = TRUE;
2768
2769 /* remove the message from the queue */
2770 PeekMessageA( &msg, 0, msg.message, msg.message, PM_REMOVE );
2771
2772 /* break out of internal loop, ala ESCAPE */
2773 break;
2774 }
2775
Alexandre Julliarda3960291999-02-26 11:11:13 +00002776 TranslateMessage( &msg );
Stephane Lussierb3a99de1999-02-09 15:35:12 +00002777 mt.pt = msg.pt;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002778
Francis Beaudet7ed1af31999-08-15 16:58:03 +00002779 if ( (msg.hwnd==menu->hWnd) || (msg.message!=WM_TIMER) )
2780 enterIdleSent=FALSE;
2781
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002782 fRemove = FALSE;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002783 if ((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002784 {
Louis Philippe Gagnon9cdd22c2000-11-27 22:39:35 +00002785 /*
2786 * use the mouse coordinates in lParam instead of those in the MSG
2787 * struct to properly handle synthetic messages. lParam coords are
2788 * relative to client area, so they must be converted; since they can
2789 * be negative, we must use SLOWORD/SHIWORD instead of LOWORD/HIWORD.
2790 */
2791 mt.pt.x = SLOWORD(msg.lParam);
2792 mt.pt.y = SHIWORD(msg.lParam);
2793 ClientToScreen(msg.hwnd,&mt.pt);
2794
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002795 /* Find a menu for this mouse event */
Louis Philippe Gagnon9cdd22c2000-11-27 22:39:35 +00002796 hmenu = MENU_PtMenu( mt.hTopMenu, mt.pt );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002797
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002798 switch(msg.message)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002799 {
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002800 /* no WM_NC... messages in captured state */
2801
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002802 case WM_RBUTTONDBLCLK:
2803 case WM_RBUTTONDOWN:
2804 if (!(wFlags & TPM_RIGHTBUTTON)) break;
2805 /* fall through */
2806 case WM_LBUTTONDBLCLK:
2807 case WM_LBUTTONDOWN:
Karl Lessard4a0a7df1999-11-07 05:17:10 +00002808 /* If the message belongs to the menu, removes it from the queue */
2809 /* Else, end menu tracking */
2810 fRemove = MENU_ButtonDown( &mt, hmenu, wFlags );
2811 fEndMenu = !fRemove;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002812 break;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002813
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002814 case WM_RBUTTONUP:
2815 if (!(wFlags & TPM_RIGHTBUTTON)) break;
2816 /* fall through */
2817 case WM_LBUTTONUP:
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002818 /* Check if a menu was selected by the mouse */
2819 if (hmenu)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002820 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002821 executedMenuId = MENU_ButtonUp( &mt, hmenu, wFlags);
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002822
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002823 /* End the loop if executedMenuId is an item ID */
Karl Lessard13409b31999-09-28 16:24:58 +00002824 /* or if the job was done (executedMenuId = 0). */
2825 fEndMenu = fRemove = (executedMenuId != -1);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002826 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002827 /* No menu was selected by the mouse */
2828 /* if the function was called by TrackPopupMenu, continue
2829 with the menu tracking. If not, stop it */
2830 else
2831 fEndMenu = ((wFlags & TPM_POPUPMENU) ? FALSE : TRUE);
2832
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002833 break;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002834
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002835 case WM_MOUSEMOVE:
Alexandre Julliard8da12c41999-01-17 16:55:11 +00002836 /* In win95 winelook, the selected menu item must be changed every time the
2837 mouse moves. In Win31 winelook, the mouse button has to be held down */
2838
2839 if ( (TWEAK_WineLook > WIN31_LOOK) ||
2840 ( (msg.wParam & MK_LBUTTON) ||
2841 ((wFlags & TPM_RIGHTBUTTON) && (msg.wParam & MK_RBUTTON))) )
2842
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002843 fEndMenu |= !MENU_MouseMove( &mt, hmenu, wFlags );
Alexandre Julliard8da12c41999-01-17 16:55:11 +00002844
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002845 } /* switch(msg.message) - mouse */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002846 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002847 else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002848 {
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002849 fRemove = TRUE; /* Keyboard messages are always removed */
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002850 switch(msg.message)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002851 {
2852 case WM_KEYDOWN:
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002853 switch(msg.wParam)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002854 {
2855 case VK_HOME:
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002856 case VK_END:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002857 MENU_SelectItem( mt.hOwnerWnd, mt.hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002858 NO_SELECTED_ITEM, FALSE, 0 );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002859 /* fall through */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002860 case VK_UP:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002861 MENU_MoveSelection( mt.hOwnerWnd, mt.hCurrentMenu,
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002862 (msg.wParam == VK_HOME)? ITEM_NEXT : ITEM_PREV );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002863 break;
2864
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002865 case VK_DOWN: /* If on menu bar, pull-down the menu */
2866
Gerard Patel3e629742000-01-17 22:22:16 +00002867 menu = MENU_GetMenu( mt.hCurrentMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002868 if (!(menu->wFlags & MF_POPUP))
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002869 mt.hCurrentMenu = MENU_ShowSubPopup(mt.hOwnerWnd, mt.hTopMenu, TRUE, wFlags);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002870 else /* otherwise try to move selection */
2871 MENU_MoveSelection( mt.hOwnerWnd, mt.hCurrentMenu, ITEM_NEXT );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002872 break;
2873
2874 case VK_LEFT:
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002875 MENU_KeyLeft( &mt, wFlags );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002876 break;
2877
2878 case VK_RIGHT:
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002879 MENU_KeyRight( &mt, wFlags );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002880 break;
2881
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002882 case VK_ESCAPE:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002883 fEndMenu = TRUE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002884 break;
2885
Ulrich Czekalla33026a22000-02-26 19:13:44 +00002886 case VK_F1:
2887 {
2888 HELPINFO hi;
2889 hi.cbSize = sizeof(HELPINFO);
2890 hi.iContextType = HELPINFO_MENUITEM;
2891 if (menu->FocusedItem == NO_SELECTED_ITEM)
2892 hi.iCtrlId = 0;
2893 else
2894 hi.iCtrlId = menu->items[menu->FocusedItem].wID;
2895 hi.hItemHandle = hmenu;
2896 hi.dwContextId = menu->dwContextHelpID;
2897 hi.MousePos = msg.pt;
2898 SendMessageA(hwnd, WM_HELP, 0, (LPARAM)&hi);
2899 break;
2900 }
2901
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002902 default:
2903 break;
2904 }
2905 break; /* WM_KEYDOWN */
2906
2907 case WM_SYSKEYDOWN:
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002908 switch(msg.wParam)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002909 {
2910 case VK_MENU:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002911 fEndMenu = TRUE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002912 break;
2913
2914 }
2915 break; /* WM_SYSKEYDOWN */
2916
2917 case WM_CHAR:
2918 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002919 UINT pos;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002920
Norman Stevensa83d0651998-10-12 07:25:35 +00002921 if (msg.wParam == '\r' || msg.wParam == ' ')
2922 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002923 executedMenuId = MENU_ExecFocusedItem(&mt,mt.hCurrentMenu, wFlags);
Karl Lessard13409b31999-09-28 16:24:58 +00002924 fEndMenu = (executedMenuId != -1);
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002925
Norman Stevensa83d0651998-10-12 07:25:35 +00002926 break;
2927 }
2928
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002929 /* Hack to avoid control chars. */
2930 /* We will find a better way real soon... */
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002931 if ((msg.wParam <= 32) || (msg.wParam >= 127)) break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002932
2933 pos = MENU_FindItemByKey( mt.hOwnerWnd, mt.hCurrentMenu,
Stephane Lussierb3a99de1999-02-09 15:35:12 +00002934 LOWORD(msg.wParam), FALSE );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002935 if (pos == (UINT)-2) fEndMenu = TRUE;
2936 else if (pos == (UINT)-1) MessageBeep(0);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002937 else
2938 {
Rein Klazes80c924f1999-12-12 19:40:46 +00002939 MENU_SelectItem( mt.hOwnerWnd, mt.hCurrentMenu, pos,
2940 TRUE, 0 );
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002941 executedMenuId = MENU_ExecFocusedItem(&mt,mt.hCurrentMenu, wFlags);
Karl Lessard13409b31999-09-28 16:24:58 +00002942 fEndMenu = (executedMenuId != -1);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002943 }
2944 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002945 break;
2946 } /* switch(msg.message) - kbd */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002947 }
2948 else
2949 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002950 DispatchMessageA( &msg );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002951 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002952
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002953 if (!fEndMenu) fRemove = TRUE;
2954
2955 /* finally remove message from the queue */
2956
2957 if (fRemove && !(mt.trackFlags & TF_SKIPREMOVE) )
Alexandre Julliarda3960291999-02-26 11:11:13 +00002958 PeekMessageA( &msg, 0, msg.message, msg.message, PM_REMOVE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002959 else mt.trackFlags &= ~TF_SKIPREMOVE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002960 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002961
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002962 ReleaseCapture();
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00002963
Guy Albertellif12b70a2000-05-11 00:06:11 +00002964 /* If dropdown is still painted and the close box is clicked on
2965 then the menu will be destroyed as part of the DispatchMessage above.
2966 This will then invalidate the menu handle in mt.hTopMenu. We should
2967 check for this first. */
2968 if( IsMenu( mt.hTopMenu ) )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002969 {
Guy Albertellif12b70a2000-05-11 00:06:11 +00002970 menu = MENU_GetMenu( mt.hTopMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002971
Guy Albertellif12b70a2000-05-11 00:06:11 +00002972 if( IsWindow( mt.hOwnerWnd ) )
2973 {
2974 MENU_HideSubPopups( mt.hOwnerWnd, mt.hTopMenu, FALSE );
2975
2976 if (menu && menu->wFlags & MF_POPUP)
2977 {
2978 ShowWindow( menu->hWnd, SW_HIDE );
2979 uSubPWndLevel = 0;
2980 }
2981 MENU_SelectItem( mt.hOwnerWnd, mt.hTopMenu, NO_SELECTED_ITEM, FALSE, 0 );
2982 SendMessageA( mt.hOwnerWnd, WM_MENUSELECT, MAKELONG(0,0xffff), 0 );
2983 }
2984
2985 /* Reset the variable for hiding menu */
2986 if( menu ) menu->bTimeToHide = FALSE;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002987 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002988
Juergen Schmied371c4201999-10-13 12:27:44 +00002989 /* The return value is only used by TrackPopupMenu */
2990 return ((executedMenuId != -1) ? executedMenuId : 0);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002991}
2992
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002993/***********************************************************************
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002994 * MENU_InitTracking
2995 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002996static BOOL MENU_InitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT wFlags)
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002997{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002998 TRACE("hwnd=0x%04x hmenu=0x%04x\n", hWnd, hMenu);
Juergen Schmied78513941999-04-18 14:40:32 +00002999
Alexandre Julliarda3960291999-02-26 11:11:13 +00003000 HideCaret(0);
Abey Georgeb59d4bc1999-09-22 15:10:42 +00003001
3002 /* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */
3003 if (!(wFlags & TPM_NONOTIFY))
3004 SendMessageA( hWnd, WM_ENTERMENULOOP, bPopup, 0 );
3005
Juergen Schmied78513941999-04-18 14:40:32 +00003006 SendMessageA( hWnd, WM_SETCURSOR, hWnd, HTCAPTION );
Abey Georgeb59d4bc1999-09-22 15:10:42 +00003007
3008 if (!(wFlags & TPM_NONOTIFY))
3009 SendMessageA( hWnd, WM_INITMENU, hMenu, 0 );
3010
Juergen Schmied78513941999-04-18 14:40:32 +00003011 return TRUE;
3012}
3013/***********************************************************************
3014 * MENU_ExitTracking
3015 */
3016static BOOL MENU_ExitTracking(HWND hWnd)
3017{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003018 TRACE("hwnd=0x%04x\n", hWnd);
Juergen Schmied78513941999-04-18 14:40:32 +00003019
3020 SendMessageA( hWnd, WM_EXITMENULOOP, 0, 0 );
3021 ShowCaret(0);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003022 return TRUE;
3023}
3024
3025/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003026 * MENU_TrackMouseMenuBar
3027 *
3028 * Menu-bar tracking upon a mouse event. Called from NC_HandleSysCommand().
3029 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003030void MENU_TrackMouseMenuBar( WND* wndPtr, INT ht, POINT pt )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003031{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003032 HWND hWnd = wndPtr->hwndSelf;
3033 HMENU hMenu = (ht == HTSYSMENU) ? wndPtr->hSysMenu : wndPtr->wIDmenu;
Abey Georgeb59d4bc1999-09-22 15:10:42 +00003034 UINT wFlags = TPM_ENTERIDLEEX | TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003035
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003036 TRACE("pwnd=%p ht=0x%04x (%ld,%ld)\n", wndPtr, ht, pt.x, pt.y);
Juergen Schmied78513941999-04-18 14:40:32 +00003037
Alexandre Julliarda3960291999-02-26 11:11:13 +00003038 if (IsMenu(hMenu))
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003039 {
Abey Georgeb59d4bc1999-09-22 15:10:42 +00003040 MENU_InitTracking( hWnd, hMenu, FALSE, wFlags );
3041 MENU_TrackMenu( hMenu, wFlags, pt.x, pt.y, hWnd, NULL );
Juergen Schmied78513941999-04-18 14:40:32 +00003042 MENU_ExitTracking(hWnd);
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003043 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003044}
3045
3046
3047/***********************************************************************
3048 * MENU_TrackKbdMenuBar
3049 *
3050 * Menu-bar tracking upon a keyboard event. Called from NC_HandleSysCommand().
3051 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003052void MENU_TrackKbdMenuBar( WND* wndPtr, UINT wParam, INT vkey)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003053{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003054 UINT uItem = NO_SELECTED_ITEM;
3055 HMENU hTrackMenu;
Abey Georgeb59d4bc1999-09-22 15:10:42 +00003056 UINT wFlags = TPM_ENTERIDLEEX | TPM_LEFTALIGN | TPM_LEFTBUTTON;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003057
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003058 /* find window that has a menu */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003059
Pierre Mageau891d4d21999-10-23 20:05:04 +00003060 while( wndPtr->dwStyle & WS_CHILD)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003061 if( !(wndPtr = wndPtr->parent) ) return;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003062
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003063 /* check if we have to track a system menu */
3064
3065 if( (wndPtr->dwStyle & (WS_CHILD | WS_MINIMIZE)) ||
3066 !wndPtr->wIDmenu || vkey == VK_SPACE )
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003067 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003068 if( !(wndPtr->dwStyle & WS_SYSMENU) ) return;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003069 hTrackMenu = wndPtr->hSysMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003070 uItem = 0;
3071 wParam |= HTSYSMENU; /* prevent item lookup */
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003072 }
3073 else
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003074 hTrackMenu = wndPtr->wIDmenu;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003075
Alexandre Julliarda3960291999-02-26 11:11:13 +00003076 if (IsMenu( hTrackMenu ))
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003077 {
Abey Georgeb59d4bc1999-09-22 15:10:42 +00003078 MENU_InitTracking( wndPtr->hwndSelf, hTrackMenu, FALSE, wFlags );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003079
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003080 if( vkey && vkey != VK_SPACE )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003081 {
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003082 uItem = MENU_FindItemByKey( wndPtr->hwndSelf, hTrackMenu,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003083 vkey, (wParam & HTSYSMENU) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003084 if( uItem >= (UINT)(-2) )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003085 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003086 if( uItem == (UINT)(-1) ) MessageBeep(0);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003087 hTrackMenu = 0;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003088 }
3089 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003090
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003091 if( hTrackMenu )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003092 {
Rein Klazes80c924f1999-12-12 19:40:46 +00003093 MENU_SelectItem( wndPtr->hwndSelf, hTrackMenu, uItem, TRUE, 0 );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003094
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003095 if( uItem == NO_SELECTED_ITEM )
3096 MENU_MoveSelection( wndPtr->hwndSelf, hTrackMenu, ITEM_NEXT );
3097 else if( vkey )
Juergen Schmied78513941999-04-18 14:40:32 +00003098 PostMessageA( wndPtr->hwndSelf, WM_KEYDOWN, VK_DOWN, 0L );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003099
Abey Georgeb59d4bc1999-09-22 15:10:42 +00003100 MENU_TrackMenu( hTrackMenu, wFlags, 0, 0, wndPtr->hwndSelf, NULL );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003101 }
Juergen Schmied78513941999-04-18 14:40:32 +00003102
3103 MENU_ExitTracking (wndPtr->hwndSelf);
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003104 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003105}
3106
3107
3108/**********************************************************************
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003109 * TrackPopupMenu16 (USER.416)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003110 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003111BOOL16 WINAPI TrackPopupMenu16( HMENU16 hMenu, UINT16 wFlags, INT16 x, INT16 y,
3112 INT16 nReserved, HWND16 hWnd, const RECT16 *lpRect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003113{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003114 RECT r;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003115 if (lpRect)
3116 CONV_RECT16TO32( lpRect, &r );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003117 return TrackPopupMenu( hMenu, wFlags, x, y, nReserved, hWnd,
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003118 lpRect ? &r : NULL );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003119}
3120
3121
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003122/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00003123 * TrackPopupMenu (USER32.549)
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003124 *
3125 * Like the win32 API, the function return the command ID only if the
3126 * flag TPM_RETURNCMD is on.
3127 *
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003128 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003129BOOL WINAPI TrackPopupMenu( HMENU hMenu, UINT wFlags, INT x, INT y,
3130 INT nReserved, HWND hWnd, const RECT *lpRect )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003131{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003132 BOOL ret = FALSE;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003133
Abey Georgeb59d4bc1999-09-22 15:10:42 +00003134 MENU_InitTracking(hWnd, hMenu, TRUE, wFlags);
3135
3136 /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
3137 if (!(wFlags & TPM_NONOTIFY))
3138 SendMessageA( hWnd, WM_INITMENUPOPUP, hMenu, 0);
3139
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003140 if (MENU_ShowPopup( hWnd, hMenu, 0, x, y, 0, 0 ))
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00003141 ret = MENU_TrackMenu( hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd, lpRect );
Juergen Schmied78513941999-04-18 14:40:32 +00003142 MENU_ExitTracking(hWnd);
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003143
3144 if( (!(wFlags & TPM_RETURNCMD)) && (ret != FALSE) )
3145 ret = 1;
3146
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003147 return ret;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003148}
3149
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003150/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003151 * TrackPopupMenuEx (USER32.550)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003152 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003153BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y,
3154 HWND hWnd, LPTPMPARAMS lpTpm )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003155{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003156 FIXME("not fully implemented\n" );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003157 return TrackPopupMenu( hMenu, wFlags, x, y, 0, hWnd,
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003158 lpTpm ? &lpTpm->rcExclude : NULL );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003159}
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003160
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003161/***********************************************************************
3162 * PopupMenuWndProc
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003163 *
3164 * NOTE: Windows has totally different (and undocumented) popup wndproc.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003165 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003166LRESULT WINAPI PopupMenuWndProc( HWND hwnd, UINT message, WPARAM wParam,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003167 LPARAM lParam )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003168{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003169 WND* wndPtr = WIN_FindWndPtr(hwnd);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003170 LRESULT retvalue;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003171
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003172 TRACE("hwnd=0x%04x msg=0x%04x wp=0x%04x lp=0x%08lx\n",
Juergen Schmied78513941999-04-18 14:40:32 +00003173 hwnd, message, wParam, lParam);
3174
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003175 switch(message)
3176 {
3177 case WM_CREATE:
3178 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003179 CREATESTRUCTA *cs = (CREATESTRUCTA*)lParam;
3180 SetWindowLongA( hwnd, 0, (LONG)cs->lpCreateParams );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003181 retvalue = 0;
3182 goto END;
Alexandre Julliardf7207251994-07-23 07:57:48 +00003183 }
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003184
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003185 case WM_MOUSEACTIVATE: /* We don't want to be activated */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003186 retvalue = MA_NOACTIVATE;
3187 goto END;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003188
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003189 case WM_PAINT:
3190 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003191 PAINTSTRUCT ps;
3192 BeginPaint( hwnd, &ps );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003193 MENU_DrawPopupMenu( hwnd, ps.hdc,
Alexandre Julliarda3960291999-02-26 11:11:13 +00003194 (HMENU)GetWindowLongA( hwnd, 0 ) );
3195 EndPaint( hwnd, &ps );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003196 retvalue = 0;
3197 goto END;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003198 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003199 case WM_ERASEBKGND:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003200 retvalue = 1;
3201 goto END;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003202
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00003203 case WM_DESTROY:
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00003204
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003205 /* zero out global pointer in case resident popup window
3206 * was somehow destroyed. */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00003207
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003208 if(MENU_GetTopPopupWnd() )
Alexandre Julliard54c27111998-03-29 19:44:57 +00003209 {
3210 if( hwnd == pTopPopupWnd->hwndSelf )
3211 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003212 ERR("resident popup destroyed!\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003213
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003214 MENU_DestroyTopPopupWnd();
Alexandre Julliard54c27111998-03-29 19:44:57 +00003215 uSubPWndLevel = 0;
3216 }
3217 else
3218 uSubPWndLevel--;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003219 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003220 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003221 break;
3222
3223 case WM_SHOWWINDOW:
3224
3225 if( wParam )
3226 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003227 if( !(*(HMENU*)wndPtr->wExtra) )
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003228 ERR("no menu to display\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003229 }
3230 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00003231 *(HMENU*)wndPtr->wExtra = 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003232 break;
3233
3234 case MM_SETMENUHANDLE:
3235
Alexandre Julliarda3960291999-02-26 11:11:13 +00003236 *(HMENU*)wndPtr->wExtra = (HMENU)wParam;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00003237 break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003238
3239 case MM_GETMENUHANDLE:
3240
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003241 retvalue = *(HMENU*)wndPtr->wExtra;
3242 goto END;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003243
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003244 default:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003245 retvalue = DefWindowProcA( hwnd, message, wParam, lParam );
3246 goto END;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003247 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003248 retvalue = 0;
3249END:
3250 WIN_ReleaseWndPtr(wndPtr);
3251 return retvalue;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003252}
3253
3254
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00003255/***********************************************************************
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003256 * MENU_GetMenuBarHeight
3257 *
3258 * Compute the size of the menu bar height. Used by NC_HandleNCCalcSize().
3259 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003260UINT MENU_GetMenuBarHeight( HWND hwnd, UINT menubarWidth,
3261 INT orgX, INT orgY )
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003262{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003263 HDC hdc;
3264 RECT rectBar;
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003265 WND *wndPtr;
3266 LPPOPUPMENU lppop;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003267 UINT retvalue;
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003268
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003269 TRACE("HWND 0x%x, width %d, at (%d, %d).\n",
Juergen Schmied78513941999-04-18 14:40:32 +00003270 hwnd, menubarWidth, orgX, orgY );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00003271
Juergen Schmied78513941999-04-18 14:40:32 +00003272 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
3273 return 0;
3274
Gerard Patel3e629742000-01-17 22:22:16 +00003275 if (!(lppop = MENU_GetMenu((HMENU16)wndPtr->wIDmenu)))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003276 {
Juergen Schmied78513941999-04-18 14:40:32 +00003277 WIN_ReleaseWndPtr(wndPtr);
3278 return 0;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003279 }
Juergen Schmied78513941999-04-18 14:40:32 +00003280
Alexandre Julliarda3960291999-02-26 11:11:13 +00003281 hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_WINDOW );
Juergen Schmied78513941999-04-18 14:40:32 +00003282 SelectObject( hdc, hMenuFont);
Marcus Meissnerddca3151999-05-22 11:33:23 +00003283 SetRect(&rectBar, orgX, orgY, orgX+menubarWidth, orgY+GetSystemMetrics(SM_CYMENU));
Juergen Schmied78513941999-04-18 14:40:32 +00003284 MENU_MenuBarCalcSize( hdc, &rectBar, lppop, hwnd );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003285 ReleaseDC( hwnd, hdc );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003286 retvalue = lppop->Height;
3287 WIN_ReleaseWndPtr(wndPtr);
3288 return retvalue;
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003289}
3290
3291
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003292/*******************************************************************
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003293 * ChangeMenu16 (USER.153)
Alexandre Julliard401710d1993-09-04 10:09:32 +00003294 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003295BOOL16 WINAPI ChangeMenu16( HMENU16 hMenu, UINT16 pos, SEGPTR data,
3296 UINT16 id, UINT16 flags )
Alexandre Julliard401710d1993-09-04 10:09:32 +00003297{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003298 TRACE("menu=%04x pos=%d data=%08lx id=%04x flags=%04x\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +00003299 hMenu, pos, (DWORD)data, id, flags );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003300 if (flags & MF_APPEND) return AppendMenu16( hMenu, flags & ~MF_APPEND,
3301 id, data );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003302
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003303 /* FIXME: Word passes the item id in 'pos' and 0 or 0xffff as id */
3304 /* for MF_DELETE. We should check the parameters for all others */
3305 /* MF_* actions also (anybody got a doc on ChangeMenu?). */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003306
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003307 if (flags & MF_DELETE) return DeleteMenu16(hMenu, pos, flags & ~MF_DELETE);
3308 if (flags & MF_CHANGE) return ModifyMenu16(hMenu, pos, flags & ~MF_CHANGE,
3309 id, data );
3310 if (flags & MF_REMOVE) return RemoveMenu16(hMenu,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003311 flags & MF_BYPOSITION ? pos : id,
3312 flags & ~MF_REMOVE );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003313 /* Default: MF_INSERT */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003314 return InsertMenu16( hMenu, pos, flags, id, data );
3315}
3316
3317
3318/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003319 * ChangeMenuA (USER32.23)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003320 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003321BOOL WINAPI ChangeMenuA( HMENU hMenu, UINT pos, LPCSTR data,
3322 UINT id, UINT flags )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003323{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003324 TRACE("menu=%08x pos=%d data=%08lx id=%08x flags=%08x\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003325 hMenu, pos, (DWORD)data, id, flags );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003326 if (flags & MF_APPEND) return AppendMenuA( hMenu, flags & ~MF_APPEND,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003327 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003328 if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
3329 if (flags & MF_CHANGE) return ModifyMenuA(hMenu, pos, flags & ~MF_CHANGE,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003330 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003331 if (flags & MF_REMOVE) return RemoveMenu( hMenu,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003332 flags & MF_BYPOSITION ? pos : id,
3333 flags & ~MF_REMOVE );
3334 /* Default: MF_INSERT */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003335 return InsertMenuA( hMenu, pos, flags, id, data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003336}
3337
3338
3339/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003340 * ChangeMenuW (USER32.24)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003341 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003342BOOL WINAPI ChangeMenuW( HMENU hMenu, UINT pos, LPCWSTR data,
3343 UINT id, UINT flags )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003344{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003345 TRACE("menu=%08x pos=%d data=%08lx id=%08x flags=%08x\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003346 hMenu, pos, (DWORD)data, id, flags );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003347 if (flags & MF_APPEND) return AppendMenuW( hMenu, flags & ~MF_APPEND,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003348 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003349 if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
3350 if (flags & MF_CHANGE) return ModifyMenuW(hMenu, pos, flags & ~MF_CHANGE,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003351 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003352 if (flags & MF_REMOVE) return RemoveMenu( hMenu,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003353 flags & MF_BYPOSITION ? pos : id,
3354 flags & ~MF_REMOVE );
3355 /* Default: MF_INSERT */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003356 return InsertMenuW( hMenu, pos, flags, id, data );
Alexandre Julliard401710d1993-09-04 10:09:32 +00003357}
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003358
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003359
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003360/*******************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003361 * CheckMenuItem16 (USER.154)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003362 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003363BOOL16 WINAPI CheckMenuItem16( HMENU16 hMenu, UINT16 id, UINT16 flags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003364{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003365 return (BOOL16)CheckMenuItem( hMenu, id, flags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003366}
3367
3368
3369/*******************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00003370 * CheckMenuItem (USER32.46)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003371 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003372DWORD WINAPI CheckMenuItem( HMENU hMenu, UINT id, UINT flags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003373{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003374 MENUITEM *item;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003375 DWORD ret;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003376
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003377 TRACE("menu=%04x id=%04x flags=%04x\n", hMenu, id, flags );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003378 if (!(item = MENU_FindItem( &hMenu, &id, flags ))) return -1;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003379 ret = item->fState & MF_CHECKED;
3380 if (flags & MF_CHECKED) item->fState |= MF_CHECKED;
3381 else item->fState &= ~MF_CHECKED;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003382 return ret;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003383}
3384
3385
3386/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003387 * EnableMenuItem16 (USER.155)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003388 */
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003389UINT16 WINAPI EnableMenuItem16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003390{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003391 return EnableMenuItem( hMenu, wItemID, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003392}
3393
3394
3395/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003396 * EnableMenuItem (USER32.170)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003397 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003398UINT WINAPI EnableMenuItem( HMENU hMenu, UINT wItemID, UINT wFlags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003399{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003400 UINT oldflags;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003401 MENUITEM *item;
Pascal Lessardd814bb61999-07-31 13:02:02 +00003402 POPUPMENU *menu;
Alexandre Julliardf7207251994-07-23 07:57:48 +00003403
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003404 TRACE("(%04x, %04X, %04X) !\n",
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003405 hMenu, wItemID, wFlags);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003406
Pascal Lessardd814bb61999-07-31 13:02:02 +00003407 /* Get the Popupmenu to access the owner menu */
Gerard Patel3e629742000-01-17 22:22:16 +00003408 if (!(menu = MENU_GetMenu(hMenu)))
Pascal Lessardd814bb61999-07-31 13:02:02 +00003409 return (UINT)-1;
3410
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003411 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags )))
Alexandre Julliarda3960291999-02-26 11:11:13 +00003412 return (UINT)-1;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003413
3414 oldflags = item->fState & (MF_GRAYED | MF_DISABLED);
3415 item->fState ^= (oldflags ^ wFlags) & (MF_GRAYED | MF_DISABLED);
Pascal Lessardd814bb61999-07-31 13:02:02 +00003416
3417 /* In win95 if the close item in the system menu change update the close button */
3418 if (TWEAK_WineLook == WIN95_LOOK)
3419 if((item->wID == SC_CLOSE) && (oldflags != wFlags))
3420 {
3421 if (menu->hSysMenuOwner != 0)
3422 {
3423 POPUPMENU* parentMenu;
3424
3425 /* Get the parent menu to access*/
Gerard Patel3e629742000-01-17 22:22:16 +00003426 if (!(parentMenu = MENU_GetMenu(menu->hSysMenuOwner)))
Pascal Lessardd814bb61999-07-31 13:02:02 +00003427 return (UINT)-1;
3428
3429 /* Refresh the frame to reflect the change*/
3430 SetWindowPos(parentMenu->hWnd, 0, 0, 0, 0, 0,
Stephane Lussiera833f631999-08-21 14:46:06 +00003431 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
Pascal Lessardd814bb61999-07-31 13:02:02 +00003432 }
3433 }
3434
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003435 return oldflags;
Alexandre Julliard1f579291994-05-25 16:25:21 +00003436}
3437
3438
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00003439/*******************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003440 * GetMenuString16 (USER.161)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003441 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003442INT16 WINAPI GetMenuString16( HMENU16 hMenu, UINT16 wItemID,
3443 LPSTR str, INT16 nMaxSiz, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003444{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003445 return GetMenuStringA( hMenu, wItemID, str, nMaxSiz, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003446}
3447
3448
3449/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003450 * GetMenuStringA (USER32.268)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003451 */
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00003452INT WINAPI GetMenuStringA(
3453 HMENU hMenu, /* [in] menuhandle */
3454 UINT wItemID, /* [in] menu item (dep. on wFlags) */
3455 LPSTR str, /* [out] outbuffer. If NULL, func returns entry length*/
3456 INT nMaxSiz, /* [in] length of buffer. if 0, func returns entry len*/
3457 UINT wFlags /* [in] MF_ flags */
3458) {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003459 MENUITEM *item;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00003460
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003461 TRACE("menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00003462 hMenu, wItemID, str, nMaxSiz, wFlags );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003463 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003464 if (!IS_STRING_ITEM(item->fType)) return 0;
Aric Stewartc946b1c2000-10-24 21:28:19 +00003465 if (!str || !nMaxSiz) return strlenW(item->text);
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00003466 str[0] = '\0';
Aric Stewartc946b1c2000-10-24 21:28:19 +00003467 lstrcpynWtoA( str, item->text, nMaxSiz );
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003468 TRACE("returning '%s'\n", str );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003469 return strlen(str);
Alexandre Julliard1f579291994-05-25 16:25:21 +00003470}
3471
3472
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003473/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003474 * GetMenuStringW (USER32.269)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003475 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003476INT WINAPI GetMenuStringW( HMENU hMenu, UINT wItemID,
3477 LPWSTR str, INT nMaxSiz, UINT wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003478{
3479 MENUITEM *item;
3480
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003481 TRACE("menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003482 hMenu, wItemID, str, nMaxSiz, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003483 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003484 if (!IS_STRING_ITEM(item->fType)) return 0;
Aric Stewartc946b1c2000-10-24 21:28:19 +00003485 if (!str || !nMaxSiz) return strlenW(item->text);
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00003486 str[0] = '\0';
Aric Stewartc946b1c2000-10-24 21:28:19 +00003487 lstrcpynW( str, item->text, nMaxSiz );
3488 return strlenW(str);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003489}
3490
3491
3492/**********************************************************************
3493 * HiliteMenuItem16 (USER.162)
3494 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003495BOOL16 WINAPI HiliteMenuItem16( HWND16 hWnd, HMENU16 hMenu, UINT16 wItemID,
3496 UINT16 wHilite )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003497{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003498 return HiliteMenuItem( hWnd, hMenu, wItemID, wHilite );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003499}
3500
3501
3502/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003503 * HiliteMenuItem (USER32.318)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003504 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003505BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
3506 UINT wHilite )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003507{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003508 LPPOPUPMENU menu;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003509 TRACE("(%04x, %04x, %04x, %04x);\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +00003510 hWnd, hMenu, wItemID, wHilite);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003511 if (!MENU_FindItem( &hMenu, &wItemID, wHilite )) return FALSE;
Gerard Patel3e629742000-01-17 22:22:16 +00003512 if (!(menu = MENU_GetMenu(hMenu))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003513 if (menu->FocusedItem == wItemID) return TRUE;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003514 MENU_HideSubPopups( hWnd, hMenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00003515 MENU_SelectItem( hWnd, hMenu, wItemID, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003516 return TRUE;
Alexandre Julliard1f579291994-05-25 16:25:21 +00003517}
3518
3519
3520/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003521 * GetMenuState16 (USER.250)
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00003522 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003523UINT16 WINAPI GetMenuState16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003524{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003525 return GetMenuState( hMenu, wItemID, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003526}
3527
3528
3529/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00003530 * GetMenuState (USER32.267)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003531 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003532UINT WINAPI GetMenuState( HMENU hMenu, UINT wItemID, UINT wFlags )
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00003533{
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003534 MENUITEM *item;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003535 TRACE("(menu=%04x, id=%04x, flags=%04x);\n",
Alexandre Julliardaca05781994-10-17 18:12:41 +00003536 hMenu, wItemID, wFlags);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003537 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return -1;
Alexandre Julliard03468f71998-02-15 19:40:49 +00003538 debug_print_menuitem (" item: ", item, "");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003539 if (item->fType & MF_POPUP)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003540 {
Gerard Patel3e629742000-01-17 22:22:16 +00003541 POPUPMENU *menu = MENU_GetMenu( item->hSubMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003542 if (!menu) return -1;
Alexandre Julliard829fe321998-07-26 14:27:39 +00003543 else return (menu->nItems << 8) | ((item->fState|item->fType) & 0xff);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003544 }
Alexandre Julliard889f7421997-04-15 17:19:52 +00003545 else
Alexandre Julliard491502b1997-11-01 19:08:16 +00003546 {
Alexandre Julliard829fe321998-07-26 14:27:39 +00003547 /* We used to (from way back then) mask the result to 0xff. */
3548 /* I don't know why and it seems wrong as the documented */
3549 /* return flag MF_SEPARATOR is outside that mask. */
3550 return (item->fType | item->fState);
Alexandre Julliard491502b1997-11-01 19:08:16 +00003551 }
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00003552}
3553
3554
3555/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003556 * GetMenuItemCount16 (USER.263)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003557 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003558INT16 WINAPI GetMenuItemCount16( HMENU16 hMenu )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003559{
Gerard Patel3e629742000-01-17 22:22:16 +00003560 LPPOPUPMENU menu = MENU_GetMenu(hMenu);
3561 if (!menu) return -1;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003562 TRACE("(%04x) returning %d\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003563 hMenu, menu->nItems );
3564 return menu->nItems;
Alexandre Julliard1f579291994-05-25 16:25:21 +00003565}
3566
3567
3568/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003569 * GetMenuItemCount (USER32.262)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003570 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003571INT WINAPI GetMenuItemCount( HMENU hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003572{
Gerard Patel3e629742000-01-17 22:22:16 +00003573 LPPOPUPMENU menu = MENU_GetMenu(hMenu);
3574 if (!menu) return -1;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003575 TRACE("(%04x) returning %d\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003576 hMenu, menu->nItems );
3577 return menu->nItems;
3578}
3579
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003580/**********************************************************************
3581 * GetMenuItemID16 (USER.264)
3582 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003583UINT16 WINAPI GetMenuItemID16( HMENU16 hMenu, INT16 nPos )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003584{
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003585 return (UINT16) GetMenuItemID (hMenu, nPos);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003586}
3587
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003588/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003589 * GetMenuItemID (USER32.263)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003590 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003591UINT WINAPI GetMenuItemID( HMENU hMenu, INT nPos )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003592{
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003593 MENUITEM * lpmi;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003594
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003595 if (!(lpmi = MENU_FindItem(&hMenu,&nPos,MF_BYPOSITION))) return 0;
3596 if (lpmi->fType & MF_POPUP) return -1;
3597 return lpmi->wID;
3598
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003599}
3600
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003601/*******************************************************************
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003602 * InsertMenu16 (USER.410)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003603 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003604BOOL16 WINAPI InsertMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags,
3605 UINT16 id, SEGPTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003606{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003607 UINT pos32 = (UINT)pos;
3608 if ((pos == (UINT16)-1) && (flags & MF_BYPOSITION)) pos32 = (UINT)-1;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003609 if (IS_STRING_ITEM(flags) && data)
Alexandre Julliarda3960291999-02-26 11:11:13 +00003610 return InsertMenuA( hMenu, pos32, flags, id,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003611 (LPSTR)PTR_SEG_TO_LIN(data) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003612 return InsertMenuA( hMenu, pos32, flags, id, (LPSTR)data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003613}
3614
3615
3616/*******************************************************************
Aric Stewartc946b1c2000-10-24 21:28:19 +00003617 * InsertMenuW (USER32.325)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003618 */
Aric Stewartc946b1c2000-10-24 21:28:19 +00003619BOOL WINAPI InsertMenuW( HMENU hMenu, UINT pos, UINT flags,
3620 UINT id, LPCWSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003621{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003622 MENUITEM *item;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00003623
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003624 if (IS_STRING_ITEM(flags) && str)
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003625 TRACE("hMenu %04x, pos %d, flags %08x, "
Alexandre Julliardd37eb361997-07-20 16:23:21 +00003626 "id %04x, str '%s'\n",
Aric Stewartc946b1c2000-10-24 21:28:19 +00003627 hMenu, pos, flags, id, debugstr_w(str) );
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003628 else TRACE("hMenu %04x, pos %d, flags %08x, "
Alexandre Julliardd37eb361997-07-20 16:23:21 +00003629 "id %04x, str %08lx (not a string)\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003630 hMenu, pos, flags, id, (DWORD)str );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003631
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003632 if (!(item = MENU_InsertItem( hMenu, pos, flags ))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003633
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003634 if (!(MENU_SetItemData( item, flags, id, str )))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003635 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003636 RemoveMenu( hMenu, pos, flags );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00003637 return FALSE;
3638 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003639
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003640 if (flags & MF_POPUP) /* Set the MF_POPUP flag on the popup-menu */
Gerard Patel3e629742000-01-17 22:22:16 +00003641 (MENU_GetMenu((HMENU16)id))->wFlags |= MF_POPUP;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003642
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003643 item->hCheckBit = item->hUnCheckBit = 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003644 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003645}
3646
3647
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003648/*******************************************************************
Aric Stewartc946b1c2000-10-24 21:28:19 +00003649 * InsertMenuA (USER32.322)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003650 */
Aric Stewartc946b1c2000-10-24 21:28:19 +00003651BOOL WINAPI InsertMenuA( HMENU hMenu, UINT pos, UINT flags,
3652 UINT id, LPCSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003653{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003654 BOOL ret;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003655
3656 if (IS_STRING_ITEM(flags) && str)
3657 {
Aric Stewartc946b1c2000-10-24 21:28:19 +00003658 LPWSTR newstr = HEAP_strdupAtoW( GetProcessHeap(), 0, str );
3659 ret = InsertMenuW( hMenu, pos, flags, id, newstr );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003660 HeapFree( GetProcessHeap(), 0, newstr );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003661 return ret;
3662 }
Aric Stewartc946b1c2000-10-24 21:28:19 +00003663 else return InsertMenuW( hMenu, pos, flags, id, (LPCWSTR)str );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003664}
3665
3666
3667/*******************************************************************
3668 * AppendMenu16 (USER.411)
3669 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003670BOOL16 WINAPI AppendMenu16(HMENU16 hMenu, UINT16 flags, UINT16 id, SEGPTR data)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003671{
3672 return InsertMenu16( hMenu, -1, flags | MF_BYPOSITION, id, data );
3673}
3674
3675
3676/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003677 * AppendMenuA (USER32.5)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003678 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003679BOOL WINAPI AppendMenuA( HMENU hMenu, UINT flags,
3680 UINT id, LPCSTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003681{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003682 return InsertMenuA( hMenu, -1, flags | MF_BYPOSITION, id, data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003683}
3684
3685
3686/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003687 * AppendMenuW (USER32.6)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003688 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003689BOOL WINAPI AppendMenuW( HMENU hMenu, UINT flags,
3690 UINT id, LPCWSTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003691{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003692 return InsertMenuW( hMenu, -1, flags | MF_BYPOSITION, id, data );
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003693}
3694
3695
3696/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003697 * RemoveMenu16 (USER.412)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003698 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003699BOOL16 WINAPI RemoveMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003700{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003701 return RemoveMenu( hMenu, nPos, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003702}
3703
3704
3705/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00003706 * RemoveMenu (USER32.441)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003707 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003708BOOL WINAPI RemoveMenu( HMENU hMenu, UINT nPos, UINT wFlags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003709{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003710 LPPOPUPMENU menu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003711 MENUITEM *item;
3712
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003713 TRACE("(menu=%04x pos=%04x flags=%04x)\n",hMenu, nPos, wFlags);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003714 if (!(item = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
Gerard Patel3e629742000-01-17 22:22:16 +00003715 if (!(menu = MENU_GetMenu(hMenu))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003716
3717 /* Remove item */
3718
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003719 MENU_FreeItemData( item );
3720
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003721 if (--menu->nItems == 0)
3722 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003723 HeapFree( SystemHeap, 0, menu->items );
3724 menu->items = NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003725 }
3726 else
3727 {
3728 while(nPos < menu->nItems)
3729 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003730 *item = *(item+1);
3731 item++;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003732 nPos++;
3733 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003734 menu->items = HeapReAlloc( SystemHeap, 0, menu->items,
3735 menu->nItems * sizeof(MENUITEM) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003736 }
3737 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003738}
3739
3740
3741/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003742 * DeleteMenu16 (USER.413)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003743 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003744BOOL16 WINAPI DeleteMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003745{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003746 return DeleteMenu( hMenu, nPos, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003747}
3748
3749
3750/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003751 * DeleteMenu (USER32.129)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003752 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003753BOOL WINAPI DeleteMenu( HMENU hMenu, UINT nPos, UINT wFlags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003754{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003755 MENUITEM *item = MENU_FindItem( &hMenu, &nPos, wFlags );
3756 if (!item) return FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003757 if (item->fType & MF_POPUP) DestroyMenu( item->hSubMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003758 /* nPos is now the position of the item */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003759 RemoveMenu( hMenu, nPos, wFlags | MF_BYPOSITION );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003760 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003761}
3762
3763
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003764/*******************************************************************
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003765 * ModifyMenu16 (USER.414)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003766 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003767BOOL16 WINAPI ModifyMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags,
3768 UINT16 id, SEGPTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003769{
3770 if (IS_STRING_ITEM(flags))
Alexandre Julliarda3960291999-02-26 11:11:13 +00003771 return ModifyMenuA( hMenu, pos, flags, id,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003772 (LPSTR)PTR_SEG_TO_LIN(data) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003773 return ModifyMenuA( hMenu, pos, flags, id, (LPSTR)data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003774}
3775
3776
3777/*******************************************************************
Aric Stewartc946b1c2000-10-24 21:28:19 +00003778 * ModifyMenuW (USER32.398)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003779 */
Aric Stewartc946b1c2000-10-24 21:28:19 +00003780BOOL WINAPI ModifyMenuW( HMENU hMenu, UINT pos, UINT flags,
3781 UINT id, LPCWSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003782{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003783 MENUITEM *item;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003784
3785 if (IS_STRING_ITEM(flags))
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00003786 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003787 TRACE("%04x %d %04x %04x '%s'\n",
Aric Stewartc946b1c2000-10-24 21:28:19 +00003788 hMenu, pos, flags, id, str ? debugstr_w(str) : "#NULL#" );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003789 if (!str) return FALSE;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00003790 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003791 else
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003792 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003793 TRACE("%04x %d %04x %04x %08lx\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003794 hMenu, pos, flags, id, (DWORD)str );
3795 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003796
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003797 if (!(item = MENU_FindItem( &hMenu, &pos, flags ))) return FALSE;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003798 return MENU_SetItemData( item, flags, id, str );
3799}
3800
3801
3802/*******************************************************************
Aric Stewartc946b1c2000-10-24 21:28:19 +00003803 * ModifyMenuA (USER32.397)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003804 */
Aric Stewartc946b1c2000-10-24 21:28:19 +00003805BOOL WINAPI ModifyMenuA( HMENU hMenu, UINT pos, UINT flags,
3806 UINT id, LPCSTR str )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003807{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003808 BOOL ret;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003809
3810 if (IS_STRING_ITEM(flags) && str)
3811 {
Aric Stewartc946b1c2000-10-24 21:28:19 +00003812 LPWSTR newstr = HEAP_strdupAtoW( GetProcessHeap(), 0, str );
3813 ret = ModifyMenuW( hMenu, pos, flags, id, newstr );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003814 HeapFree( GetProcessHeap(), 0, newstr );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003815 return ret;
3816 }
Aric Stewartc946b1c2000-10-24 21:28:19 +00003817 else return ModifyMenuW( hMenu, pos, flags, id, (LPCWSTR)str );
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003818}
3819
3820
3821/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003822 * CreatePopupMenu16 (USER.415)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003823 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003824HMENU16 WINAPI CreatePopupMenu16(void)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003825{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003826 return CreatePopupMenu();
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003827}
3828
3829
3830/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003831 * CreatePopupMenu (USER32.82)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003832 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003833HMENU WINAPI CreatePopupMenu(void)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003834{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003835 HMENU hmenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003836 POPUPMENU *menu;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003837
Alexandre Julliarda3960291999-02-26 11:11:13 +00003838 if (!(hmenu = CreateMenu())) return 0;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00003839 menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003840 menu->wFlags |= MF_POPUP;
Pascal Lessard2eb0a301999-09-03 16:38:52 +00003841 menu->bTimeToHide = FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003842 return hmenu;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003843}
3844
3845
3846/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003847 * GetMenuCheckMarkDimensions (USER.417) (USER32.258)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003848 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003849DWORD WINAPI GetMenuCheckMarkDimensions(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003850{
Alexandre Julliardf7207251994-07-23 07:57:48 +00003851 return MAKELONG( check_bitmap_width, check_bitmap_height );
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003852}
3853
3854
3855/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003856 * SetMenuItemBitmaps16 (USER.418)
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003857 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003858BOOL16 WINAPI SetMenuItemBitmaps16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags,
3859 HBITMAP16 hNewUnCheck, HBITMAP16 hNewCheck)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003860{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003861 return SetMenuItemBitmaps( hMenu, nPos, wFlags, hNewUnCheck, hNewCheck );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003862}
3863
3864
3865/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003866 * SetMenuItemBitmaps (USER32.490)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003867 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003868BOOL WINAPI SetMenuItemBitmaps( HMENU hMenu, UINT nPos, UINT wFlags,
3869 HBITMAP hNewUnCheck, HBITMAP hNewCheck)
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003870{
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003871 MENUITEM *item;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003872 TRACE("(%04x, %04x, %04x, %04x, %04x)\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003873 hMenu, nPos, wFlags, hNewCheck, hNewUnCheck);
3874 if (!(item = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003875
3876 if (!hNewCheck && !hNewUnCheck)
3877 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003878 item->fState &= ~MF_USECHECKBITMAPS;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003879 }
3880 else /* Install new bitmaps */
3881 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003882 item->hCheckBit = hNewCheck;
3883 item->hUnCheckBit = hNewUnCheck;
3884 item->fState |= MF_USECHECKBITMAPS;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003885 }
3886 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003887}
3888
3889
3890/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003891 * CreateMenu16 (USER.151)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003892 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003893HMENU16 WINAPI CreateMenu16(void)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003894{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003895 return CreateMenu();
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003896}
3897
3898
3899/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00003900 * CreateMenu (USER32.81)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003901 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003902HMENU WINAPI CreateMenu(void)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003903{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003904 HMENU hMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003905 LPPOPUPMENU menu;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003906 if (!(hMenu = USER_HEAP_ALLOC( sizeof(POPUPMENU) ))) return 0;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00003907 menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
Juergen Schmied78513941999-04-18 14:40:32 +00003908
3909 ZeroMemory(menu, sizeof(POPUPMENU));
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003910 menu->wMagic = MENU_MAGIC;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003911 menu->FocusedItem = NO_SELECTED_ITEM;
Pascal Lessard2eb0a301999-09-03 16:38:52 +00003912 menu->bTimeToHide = FALSE;
Juergen Schmied78513941999-04-18 14:40:32 +00003913
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003914 TRACE("return %04x\n", hMenu );
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003915
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003916 return hMenu;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003917}
3918
3919
3920/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003921 * DestroyMenu16 (USER.152)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003922 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003923BOOL16 WINAPI DestroyMenu16( HMENU16 hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003924{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003925 return DestroyMenu( hMenu );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003926}
3927
3928
3929/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003930 * DestroyMenu (USER32.134)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003931 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003932BOOL WINAPI DestroyMenu( HMENU hMenu )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003933{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003934 TRACE("(%04x)\n", hMenu);
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003935
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003936 /* Silently ignore attempts to destroy default system popup */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003937
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003938 if (hMenu && hMenu != MENU_DefSysPopup)
Alexandre Julliardff8331e1995-09-18 11:19:54 +00003939 {
Gerard Patel3e629742000-01-17 22:22:16 +00003940 LPPOPUPMENU lppop = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003941 WND *pTPWnd = MENU_GetTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003942
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003943 if( pTPWnd && (hMenu == *(HMENU*)pTPWnd->wExtra) )
3944 *(UINT*)pTPWnd->wExtra = 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003945
Gerard Patel3e629742000-01-17 22:22:16 +00003946 if (!IS_A_MENU(lppop)) lppop = NULL;
3947 if ( lppop )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003948 {
3949 lppop->wMagic = 0; /* Mark it as destroyed */
3950
3951 if ((lppop->wFlags & MF_POPUP) && lppop->hWnd &&
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003952 (!pTPWnd || (lppop->hWnd != pTPWnd->hwndSelf)))
Alexandre Julliarda3960291999-02-26 11:11:13 +00003953 DestroyWindow( lppop->hWnd );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003954
3955 if (lppop->items) /* recursively destroy submenus */
3956 {
3957 int i;
3958 MENUITEM *item = lppop->items;
3959 for (i = lppop->nItems; i > 0; i--, item++)
3960 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003961 if (item->fType & MF_POPUP) DestroyMenu(item->hSubMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003962 MENU_FreeItemData( item );
3963 }
3964 HeapFree( SystemHeap, 0, lppop->items );
3965 }
3966 USER_HEAP_FREE( hMenu );
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +00003967 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003968 }
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +00003969 else
3970 {
3971 MENU_ReleaseTopPopupWnd();
3972 return FALSE;
3973 }
Alexandre Julliardff8331e1995-09-18 11:19:54 +00003974 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003975 return (hMenu != MENU_DefSysPopup);
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003976}
3977
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003978
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003979/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003980 * GetSystemMenu16 (USER.156)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003981 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003982HMENU16 WINAPI GetSystemMenu16( HWND16 hWnd, BOOL16 bRevert )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003983{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003984 return GetSystemMenu( hWnd, bRevert );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003985}
3986
3987
3988/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003989 * GetSystemMenu (USER32.291)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003990 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003991HMENU WINAPI GetSystemMenu( HWND hWnd, BOOL bRevert )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003992{
Alexandre Julliardb7258be1995-09-01 15:57:28 +00003993 WND *wndPtr = WIN_FindWndPtr( hWnd );
Eric Pouech562309a1999-08-21 12:59:44 +00003994 HMENU retvalue = 0;
Alexandre Julliardb7258be1995-09-01 15:57:28 +00003995
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003996 if (wndPtr)
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003997 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003998 if( wndPtr->hSysMenu )
3999 {
4000 if( bRevert )
4001 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004002 DestroyMenu(wndPtr->hSysMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004003 wndPtr->hSysMenu = 0;
4004 }
4005 else
4006 {
Gerard Patel3e629742000-01-17 22:22:16 +00004007 POPUPMENU *menu = MENU_GetMenu( wndPtr->hSysMenu );
4008 if( menu )
Eric Pouech562309a1999-08-21 12:59:44 +00004009 {
4010 if( menu->nItems > 0 && menu->items[0].hSubMenu == MENU_DefSysPopup )
4011 menu->items[0].hSubMenu = MENU_CopySysPopup();
4012 }
4013 else
4014 {
4015 WARN("Current sys-menu (%04x) of wnd %04x is broken\n",
4016 wndPtr->hSysMenu, hWnd);
4017 wndPtr->hSysMenu = 0;
4018 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004019 }
4020 }
4021
4022 if(!wndPtr->hSysMenu && (wndPtr->dwStyle & WS_SYSMENU) )
Alexandre Julliarda3960291999-02-26 11:11:13 +00004023 wndPtr->hSysMenu = MENU_GetSysMenu( hWnd, (HMENU)(-1) );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004024
4025 if( wndPtr->hSysMenu )
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004026 {
Eric Pouech562309a1999-08-21 12:59:44 +00004027 POPUPMENU *menu;
4028 retvalue = GetSubMenu16(wndPtr->hSysMenu, 0);
Pascal Lessardd814bb61999-07-31 13:02:02 +00004029
4030 /* Store the dummy sysmenu handle to facilitate the refresh */
4031 /* of the close button if the SC_CLOSE item change */
Gerard Patel3e629742000-01-17 22:22:16 +00004032 menu = MENU_GetMenu(retvalue);
4033 if ( menu )
Eric Pouech562309a1999-08-21 12:59:44 +00004034 menu->hSysMenuOwner = wndPtr->hSysMenu;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004035 }
4036 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00004037 }
Francois Jacques20af4c32000-06-18 17:17:54 +00004038 return bRevert ? 0 : retvalue;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004039}
4040
Alexandre Julliard7e56f681996-01-31 19:02:28 +00004041
4042/*******************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004043 * SetSystemMenu16 (USER.280)
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00004044 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004045BOOL16 WINAPI SetSystemMenu16( HWND16 hwnd, HMENU16 hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004046{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004047 return SetSystemMenu( hwnd, hMenu );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004048}
4049
4050
4051/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004052 * SetSystemMenu (USER32.508)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004053 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004054BOOL WINAPI SetSystemMenu( HWND hwnd, HMENU hMenu )
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00004055{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004056 WND *wndPtr = WIN_FindWndPtr(hwnd);
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00004057
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004058 if (wndPtr)
4059 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004060 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004061 wndPtr->hSysMenu = MENU_GetSysMenu( hwnd, hMenu );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004062 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004063 return TRUE;
4064 }
4065 return FALSE;
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00004066}
4067
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004068
4069/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004070 * GetMenu16 (USER.157)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004071 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004072HMENU16 WINAPI GetMenu16( HWND16 hWnd )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004073{
Richard Cohen56753621999-09-19 14:08:13 +00004074 return (HMENU16)GetMenu(hWnd);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004075}
4076
4077
4078/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004079 * GetMenu (USER32.257)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004080 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004081HMENU WINAPI GetMenu( HWND hWnd )
Dmitry Timoshkovfbb2c9b2000-09-09 19:38:34 +00004082{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004083 HMENU retvalue;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004084 WND * wndPtr = WIN_FindWndPtr(hWnd);
Dmitry Timoshkovfbb2c9b2000-09-09 19:38:34 +00004085
4086 if (!wndPtr) return 0;
4087
4088 retvalue = (HMENU)wndPtr->wIDmenu;
4089 TRACE("for %swindow %04x returning %04x\n",
4090 (wndPtr->dwStyle & WS_CHILD) ? "child " : "", hWnd, retvalue);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004091 WIN_ReleaseWndPtr(wndPtr);
4092 return retvalue;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004093}
4094
4095
4096/**********************************************************************
4097 * SetMenu16 (USER.158)
4098 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004099BOOL16 WINAPI SetMenu16( HWND16 hWnd, HMENU16 hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004100{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004101 return SetMenu( hWnd, hMenu );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004102}
4103
4104
4105/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004106 * SetMenu (USER32.487)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004107 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004108BOOL WINAPI SetMenu( HWND hWnd, HMENU hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004109{
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004110 WND * wndPtr = WIN_FindWndPtr(hWnd);
Andreas Mohr6f07e8a2000-09-19 02:38:11 +00004111 BOOL res = FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004112
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004113 TRACE("(%04x, %04x);\n", hWnd, hMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004114
Richard Cohen56753621999-09-19 14:08:13 +00004115 if (hMenu && !IsMenu(hMenu))
4116 {
4117 WARN("hMenu is not a menu handle\n");
Andreas Mohr6f07e8a2000-09-19 02:38:11 +00004118 goto exit;
Richard Cohen56753621999-09-19 14:08:13 +00004119 }
Richard Cohen56753621999-09-19 14:08:13 +00004120
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004121 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD))
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004122 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004123 if (GetCapture() == hWnd) ReleaseCapture();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004124
Alexandre Julliarda3960291999-02-26 11:11:13 +00004125 wndPtr->wIDmenu = (UINT)hMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004126 if (hMenu != 0)
4127 {
4128 LPPOPUPMENU lpmenu;
4129
Gerard Patel3e629742000-01-17 22:22:16 +00004130 if (!(lpmenu = MENU_GetMenu(hMenu)))
Andreas Mohr6f07e8a2000-09-19 02:38:11 +00004131 goto exit;
4132
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004133 lpmenu->hWnd = hWnd;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004134 lpmenu->Height = 0; /* Make sure we recalculate the size */
4135 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00004136 if (IsWindowVisible(hWnd))
4137 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
Alexandre Julliard01d63461997-01-20 19:43:45 +00004138 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
Andreas Mohr6f07e8a2000-09-19 02:38:11 +00004139 res = TRUE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004140 }
Andreas Mohr6f07e8a2000-09-19 02:38:11 +00004141exit:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004142 WIN_ReleaseWndPtr(wndPtr);
Andreas Mohr6f07e8a2000-09-19 02:38:11 +00004143 return res;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004144}
4145
4146
Alexandre Julliardd18872d1994-05-11 12:18:19 +00004147
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004148/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004149 * GetSubMenu16 (USER.159)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004150 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004151HMENU16 WINAPI GetSubMenu16( HMENU16 hMenu, INT16 nPos )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004152{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004153 return GetSubMenu( hMenu, nPos );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004154}
4155
4156
4157/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004158 * GetSubMenu (USER32.288)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004159 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004160HMENU WINAPI GetSubMenu( HMENU hMenu, INT nPos )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004161{
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00004162 MENUITEM * lpmi;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004163
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00004164 if (!(lpmi = MENU_FindItem(&hMenu,&nPos,MF_BYPOSITION))) return 0;
4165 if (!(lpmi->fType & MF_POPUP)) return 0;
4166 return lpmi->hSubMenu;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004167}
4168
4169
4170/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004171 * DrawMenuBar16 (USER.160)
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004172 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004173void WINAPI DrawMenuBar16( HWND16 hWnd )
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004174{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004175 DrawMenuBar( hWnd );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004176}
Alexandre Julliardf7207251994-07-23 07:57:48 +00004177
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004178
4179/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004180 * DrawMenuBar (USER32.161)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004181 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004182BOOL WINAPI DrawMenuBar( HWND hWnd )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004183{
4184 LPPOPUPMENU lppop;
4185 WND *wndPtr = WIN_FindWndPtr(hWnd);
4186 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && wndPtr->wIDmenu)
4187 {
Gerard Patel3e629742000-01-17 22:22:16 +00004188 lppop = MENU_GetMenu((HMENU16)wndPtr->wIDmenu);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004189 if (lppop == NULL)
4190 {
4191 WIN_ReleaseWndPtr(wndPtr);
4192 return FALSE;
4193 }
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004194
4195 lppop->Height = 0; /* Make sure we call MENU_MenuBarCalcSize */
Juergen Schmied78513941999-04-18 14:40:32 +00004196 lppop->hwndOwner = hWnd;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004197 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
Alexandre Julliard01d63461997-01-20 19:43:45 +00004198 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004199 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004200 return TRUE;
4201 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004202 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004203 return FALSE;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004204}
4205
4206
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004207/***********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00004208 * EndMenu (USER.187) (USER32.175)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004209 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004210void WINAPI EndMenu(void)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004211{
Rob Farnumb2007932000-05-23 23:34:17 +00004212 /* if we are in the menu code, and it is active */
4213 if (fEndMenu == FALSE && MENU_IsMenuActive())
4214 {
4215 /* terminate the menu handling code */
4216 fEndMenu = TRUE;
Alex Korobka4f1ac051999-03-28 09:37:57 +00004217
Rob Farnumb2007932000-05-23 23:34:17 +00004218 /* needs to be posted to wakeup the internal menu handler */
4219 /* which will now terminate the menu, in the event that */
4220 /* the main window was minimized, or lost focus, so we */
4221 /* don't end up with an orphaned menu */
4222 PostMessageA( pTopPopupWnd->hwndSelf, WM_CANCELMODE, 0, 0);
4223 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004224}
4225
4226
4227/***********************************************************************
4228 * LookupMenuHandle (USER.217)
4229 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004230HMENU16 WINAPI LookupMenuHandle16( HMENU16 hmenu, INT16 id )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004231{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004232 HMENU hmenu32 = hmenu;
4233 UINT id32 = id;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004234 if (!MENU_FindItem( &hmenu32, &id32, MF_BYCOMMAND )) return 0;
4235 else return hmenu32;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004236}
4237
4238
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004239/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004240 * LoadMenu16 (USER.150)
Alexandre Julliard594997c1995-04-30 10:05:20 +00004241 */
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004242HMENU16 WINAPI LoadMenu16( HINSTANCE16 instance, LPCSTR name )
Alexandre Julliard594997c1995-04-30 10:05:20 +00004243{
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004244 HRSRC16 hRsrc;
4245 HGLOBAL16 handle;
4246 HMENU16 hMenu;
Alexandre Julliard594997c1995-04-30 10:05:20 +00004247
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004248 TRACE("(%04x,%s)\n", instance, debugres_a(name) );
4249
Alexandre Julliard594997c1995-04-30 10:05:20 +00004250 if (HIWORD(name))
4251 {
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004252 if (name[0] == '#') name = (LPCSTR)atoi( name + 1 );
Alexandre Julliard594997c1995-04-30 10:05:20 +00004253 }
Alexandre Julliard594997c1995-04-30 10:05:20 +00004254
4255 if (!name) return 0;
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004256
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00004257 /* check for Win32 module */
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004258 if (HIWORD(instance)) return LoadMenuA( instance, name );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00004259 instance = GetExePtr( instance );
Alexandre Julliard594997c1995-04-30 10:05:20 +00004260
Alexandre Julliardac7efef2000-11-27 21:54:01 +00004261 if (!(hRsrc = FindResource16( instance, name, RT_MENUA ))) return 0;
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004262 if (!(handle = LoadResource16( instance, hRsrc ))) return 0;
4263 hMenu = LoadMenuIndirect16(LockResource16(handle));
4264 FreeResource16( handle );
Alexandre Julliard594997c1995-04-30 10:05:20 +00004265 return hMenu;
4266}
4267
4268
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004269/*****************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004270 * LoadMenuA (USER32.370)
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004271 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004272HMENU WINAPI LoadMenuA( HINSTANCE instance, LPCSTR name )
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004273{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004274 HRSRC hrsrc = FindResourceA( instance, name, RT_MENUA );
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004275 if (!hrsrc) return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004276 return LoadMenuIndirectA( (LPCVOID)LoadResource( instance, hrsrc ));
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004277}
4278
4279
4280/*****************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004281 * LoadMenuW (USER32.373)
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004282 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004283HMENU WINAPI LoadMenuW( HINSTANCE instance, LPCWSTR name )
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004284{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004285 HRSRC hrsrc = FindResourceW( instance, name, RT_MENUW );
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004286 if (!hrsrc) return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004287 return LoadMenuIndirectW( (LPCVOID)LoadResource( instance, hrsrc ));
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004288}
4289
4290
Alexandre Julliard594997c1995-04-30 10:05:20 +00004291/**********************************************************************
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004292 * LoadMenuIndirect16 (USER.220)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00004293 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004294HMENU16 WINAPI LoadMenuIndirect16( LPCVOID template )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00004295{
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00004296 HMENU16 hMenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004297 WORD version, offset;
4298 LPCSTR p = (LPCSTR)template;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00004299
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004300 TRACE("(%p)\n", template );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004301 version = GET_WORD(p);
4302 p += sizeof(WORD);
4303 if (version)
4304 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004305 WARN("version must be 0 for Win16\n" );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004306 return 0;
4307 }
4308 offset = GET_WORD(p);
4309 p += sizeof(WORD) + offset;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004310 if (!(hMenu = CreateMenu())) return 0;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004311 if (!MENU_ParseResource( p, hMenu, FALSE ))
Alexandre Julliard7e56f681996-01-31 19:02:28 +00004312 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004313 DestroyMenu( hMenu );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004314 return 0;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00004315 }
4316 return hMenu;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004317}
4318
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004319
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004320/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004321 * LoadMenuIndirectA (USER32.371)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004322 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004323HMENU WINAPI LoadMenuIndirectA( LPCVOID template )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004324{
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00004325 HMENU16 hMenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004326 WORD version, offset;
4327 LPCSTR p = (LPCSTR)template;
4328
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004329 TRACE("%p\n", template );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004330 version = GET_WORD(p);
4331 p += sizeof(WORD);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004332 switch (version)
4333 {
4334 case 0:
4335 offset = GET_WORD(p);
4336 p += sizeof(WORD) + offset;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004337 if (!(hMenu = CreateMenu())) return 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004338 if (!MENU_ParseResource( p, hMenu, TRUE ))
4339 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004340 DestroyMenu( hMenu );
Alexandre Julliard641ee761997-08-04 16:34:36 +00004341 return 0;
4342 }
4343 return hMenu;
4344 case 1:
4345 offset = GET_WORD(p);
4346 p += sizeof(WORD) + offset;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004347 if (!(hMenu = CreateMenu())) return 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004348 if (!MENUEX_ParseResource( p, hMenu))
4349 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004350 DestroyMenu( hMenu );
Alexandre Julliard641ee761997-08-04 16:34:36 +00004351 return 0;
4352 }
4353 return hMenu;
4354 default:
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004355 ERR("version %d not supported.\n", version);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004356 return 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004357 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004358}
4359
4360
4361/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004362 * LoadMenuIndirectW (USER32.372)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004363 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004364HMENU WINAPI LoadMenuIndirectW( LPCVOID template )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004365{
4366 /* FIXME: is there anything different between A and W? */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004367 return LoadMenuIndirectA( template );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004368}
4369
4370
4371/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004372 * IsMenu16 (USER.358)
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004373 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004374BOOL16 WINAPI IsMenu16( HMENU16 hmenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004375{
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004376 LPPOPUPMENU menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hmenu);
4377 return IS_A_MENU(menu);
4378}
4379
4380
4381/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004382 * IsMenu (USER32.346)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004383 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004384BOOL WINAPI IsMenu(HMENU hmenu)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004385{
4386 LPPOPUPMENU menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hmenu);
4387 return IS_A_MENU(menu);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004388}
4389
Alexandre Julliard641ee761997-08-04 16:34:36 +00004390/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004391 * GetMenuItemInfo_common
Alexandre Julliard641ee761997-08-04 16:34:36 +00004392 */
4393
Juergen Schmied78513941999-04-18 14:40:32 +00004394static BOOL GetMenuItemInfo_common ( HMENU hmenu, UINT item, BOOL bypos,
Aric Stewartc946b1c2000-10-24 21:28:19 +00004395 LPMENUITEMINFOW lpmii, BOOL unicode)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004396{
Juergen Schmied78513941999-04-18 14:40:32 +00004397 MENUITEM *menu = MENU_FindItem (&hmenu, &item, bypos? MF_BYPOSITION : 0);
4398
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004399 debug_print_menuitem("GetMenuItemInfo_common: ", menu, "");
Juergen Schmied78513941999-04-18 14:40:32 +00004400
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004401 if (!menu)
4402 return FALSE;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004403
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004404 if (lpmii->fMask & MIIM_TYPE) {
4405 lpmii->fType = menu->fType;
4406 switch (MENU_ITEM_TYPE(menu->fType)) {
Huw D M Davies2d6eaba2000-03-24 19:48:53 +00004407 case MF_STRING:
4408 if (menu->text) {
Aric Stewartc946b1c2000-10-24 21:28:19 +00004409 int len = strlenW(menu->text);
Huw D M Davies2d6eaba2000-03-24 19:48:53 +00004410 if(lpmii->dwTypeData && lpmii->cch) {
4411 if (unicode)
Aric Stewartc946b1c2000-10-24 21:28:19 +00004412 lstrcpynW(lpmii->dwTypeData, menu->text,
Huw D M Davies2d6eaba2000-03-24 19:48:53 +00004413 lpmii->cch);
4414 else
Aric Stewartc946b1c2000-10-24 21:28:19 +00004415 lstrcpynWtoA((LPSTR)lpmii->dwTypeData, menu->text, lpmii->cch);
Huw D M Davies2d6eaba2000-03-24 19:48:53 +00004416 /* if we've copied a substring we return its length */
4417 if(lpmii->cch <= len)
4418 lpmii->cch--;
4419 } else /* return length of string */
4420 lpmii->cch = len;
4421 }
4422 break;
4423 case MF_OWNERDRAW:
4424 case MF_BITMAP:
4425 lpmii->dwTypeData = menu->text;
4426 /* fall through */
4427 default:
4428 lpmii->cch = 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004429 }
Alexandre Julliard641ee761997-08-04 16:34:36 +00004430 }
Juergen Schmied78513941999-04-18 14:40:32 +00004431
4432 if (lpmii->fMask & MIIM_STRING) {
Huw D M Davies2d6eaba2000-03-24 19:48:53 +00004433 if(lpmii->dwTypeData && lpmii->cch) {
4434 if (unicode)
Aric Stewartc946b1c2000-10-24 21:28:19 +00004435 lstrcpynW((LPWSTR) lpmii->dwTypeData, menu->text,
Huw D M Davies2d6eaba2000-03-24 19:48:53 +00004436 lpmii->cch);
4437 else
Aric Stewartc946b1c2000-10-24 21:28:19 +00004438 lstrcpynWtoA((LPSTR)lpmii->dwTypeData, menu->text, lpmii->cch);
Juergen Schmied78513941999-04-18 14:40:32 +00004439 }
Aric Stewartc946b1c2000-10-24 21:28:19 +00004440 lpmii->cch = strlenW(menu->text);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004441 }
Juergen Schmied78513941999-04-18 14:40:32 +00004442
4443 if (lpmii->fMask & MIIM_FTYPE)
4444 lpmii->fType = menu->fType;
4445
4446 if (lpmii->fMask & MIIM_BITMAP)
4447 lpmii->hbmpItem = menu->hbmpItem;
4448
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004449 if (lpmii->fMask & MIIM_STATE)
4450 lpmii->fState = menu->fState;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004451
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004452 if (lpmii->fMask & MIIM_ID)
4453 lpmii->wID = menu->wID;
4454
4455 if (lpmii->fMask & MIIM_SUBMENU)
4456 lpmii->hSubMenu = menu->hSubMenu;
4457
4458 if (lpmii->fMask & MIIM_CHECKMARKS) {
4459 lpmii->hbmpChecked = menu->hCheckBit;
4460 lpmii->hbmpUnchecked = menu->hUnCheckBit;
4461 }
4462 if (lpmii->fMask & MIIM_DATA)
4463 lpmii->dwItemData = menu->dwItemData;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004464
4465 return TRUE;
4466}
4467
4468/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004469 * GetMenuItemInfoA (USER32.264)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004470 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004471BOOL WINAPI GetMenuItemInfoA( HMENU hmenu, UINT item, BOOL bypos,
4472 LPMENUITEMINFOA lpmii)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004473{
Aric Stewartc946b1c2000-10-24 21:28:19 +00004474 return GetMenuItemInfo_common (hmenu, item, bypos,
4475 (LPMENUITEMINFOW)lpmii, FALSE);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004476}
4477
4478/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004479 * GetMenuItemInfoW (USER32.265)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004480 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004481BOOL WINAPI GetMenuItemInfoW( HMENU hmenu, UINT item, BOOL bypos,
4482 LPMENUITEMINFOW lpmii)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004483{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004484 return GetMenuItemInfo_common (hmenu, item, bypos,
Aric Stewartc946b1c2000-10-24 21:28:19 +00004485 lpmii, TRUE);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004486}
4487
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004488/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004489 * SetMenuItemInfo_common
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004490 */
4491
Alexandre Julliarda3960291999-02-26 11:11:13 +00004492static BOOL SetMenuItemInfo_common(MENUITEM * menu,
Aric Stewartc946b1c2000-10-24 21:28:19 +00004493 const MENUITEMINFOW *lpmii,
Alexandre Julliarda3960291999-02-26 11:11:13 +00004494 BOOL unicode)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004495{
4496 if (!menu) return FALSE;
4497
Juergen Schmied78513941999-04-18 14:40:32 +00004498 if (lpmii->fMask & MIIM_TYPE ) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004499 /* Get rid of old string. */
Juergen Schmied78513941999-04-18 14:40:32 +00004500 if ( IS_STRING_ITEM(menu->fType) && menu->text) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004501 HeapFree(SystemHeap, 0, menu->text);
Juergen Schmied78513941999-04-18 14:40:32 +00004502 menu->text = NULL;
4503 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004504
Juergen Schmied78513941999-04-18 14:40:32 +00004505 /* make only MENU_ITEM_TYPE bits in menu->fType equal lpmii->fType */
4506 menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
4507 menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
Paul Millar39da2221999-04-11 12:08:42 +00004508
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004509 menu->text = lpmii->dwTypeData;
Juergen Schmied78513941999-04-18 14:40:32 +00004510
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004511 if (IS_STRING_ITEM(menu->fType) && menu->text) {
Juergen Schmied78513941999-04-18 14:40:32 +00004512 if (unicode)
Aric Stewartc946b1c2000-10-24 21:28:19 +00004513 menu->text = HEAP_strdupW(SystemHeap, 0, lpmii->dwTypeData);
Juergen Schmied78513941999-04-18 14:40:32 +00004514 else
Aric Stewartc946b1c2000-10-24 21:28:19 +00004515 menu->text = HEAP_strdupAtoW(SystemHeap, 0, (LPSTR)lpmii->dwTypeData);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004516 }
4517 }
Juergen Schmied78513941999-04-18 14:40:32 +00004518
4519 if (lpmii->fMask & MIIM_FTYPE ) {
4520 /* free the string when the type is changing */
4521 if ( (!IS_STRING_ITEM(lpmii->fType)) && IS_STRING_ITEM(menu->fType) && menu->text) {
4522 HeapFree(SystemHeap, 0, menu->text);
4523 menu->text = NULL;
4524 }
4525 menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
4526 menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
4527 }
4528
4529 if (lpmii->fMask & MIIM_STRING ) {
4530 /* free the string when used */
4531 if ( IS_STRING_ITEM(menu->fType) && menu->text) {
4532 HeapFree(SystemHeap, 0, menu->text);
4533 if (unicode)
Aric Stewartc946b1c2000-10-24 21:28:19 +00004534 menu->text = HEAP_strdupW(SystemHeap, 0, lpmii->dwTypeData);
Juergen Schmied78513941999-04-18 14:40:32 +00004535 else
Aric Stewartc946b1c2000-10-24 21:28:19 +00004536 menu->text = HEAP_strdupAtoW(SystemHeap, 0, (LPSTR) lpmii->dwTypeData);
Juergen Schmied78513941999-04-18 14:40:32 +00004537 }
4538 }
4539
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004540 if (lpmii->fMask & MIIM_STATE)
Juergen Schmied466a6521999-05-02 11:21:08 +00004541 {
4542 /* fixme: MFS_DEFAULT do we have to reset the other menu items? */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004543 menu->fState = lpmii->fState;
Juergen Schmied466a6521999-05-02 11:21:08 +00004544 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004545
4546 if (lpmii->fMask & MIIM_ID)
4547 menu->wID = lpmii->wID;
4548
Alexandre Julliarda0d77311998-09-13 16:32:00 +00004549 if (lpmii->fMask & MIIM_SUBMENU) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004550 menu->hSubMenu = lpmii->hSubMenu;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00004551 if (menu->hSubMenu) {
Gerard Patel3e629742000-01-17 22:22:16 +00004552 POPUPMENU *subMenu = MENU_GetMenu((UINT16)menu->hSubMenu);
4553 if (subMenu) {
Alexandre Julliarda0d77311998-09-13 16:32:00 +00004554 subMenu->wFlags |= MF_POPUP;
4555 menu->fType |= MF_POPUP;
4556 }
4557 else
4558 /* FIXME: Return an error ? */
4559 menu->fType &= ~MF_POPUP;
4560 }
4561 else
4562 menu->fType &= ~MF_POPUP;
4563 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004564
4565 if (lpmii->fMask & MIIM_CHECKMARKS)
4566 {
Susan Farleyf1d467a2000-05-12 21:59:31 +00004567 if (lpmii->fType & MFT_RADIOCHECK)
4568 menu->fType |= MFT_RADIOCHECK;
4569
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004570 menu->hCheckBit = lpmii->hbmpChecked;
4571 menu->hUnCheckBit = lpmii->hbmpUnchecked;
4572 }
4573 if (lpmii->fMask & MIIM_DATA)
4574 menu->dwItemData = lpmii->dwItemData;
4575
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004576 debug_print_menuitem("SetMenuItemInfo_common: ", menu, "");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004577 return TRUE;
4578}
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004579
4580/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004581 * SetMenuItemInfoA (USER32.491)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004582 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004583BOOL WINAPI SetMenuItemInfoA(HMENU hmenu, UINT item, BOOL bypos,
4584 const MENUITEMINFOA *lpmii)
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004585{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004586 return SetMenuItemInfo_common(MENU_FindItem(&hmenu, &item, bypos? MF_BYPOSITION : 0),
Aric Stewartc946b1c2000-10-24 21:28:19 +00004587 (const MENUITEMINFOW *)lpmii, FALSE);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004588}
4589
4590/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004591 * SetMenuItemInfoW (USER32.492)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004592 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004593BOOL WINAPI SetMenuItemInfoW(HMENU hmenu, UINT item, BOOL bypos,
4594 const MENUITEMINFOW *lpmii)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004595{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004596 return SetMenuItemInfo_common(MENU_FindItem(&hmenu, &item, bypos? MF_BYPOSITION : 0),
Aric Stewartc946b1c2000-10-24 21:28:19 +00004597 lpmii, TRUE);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004598}
4599
4600/**********************************************************************
Juergen Schmied466a6521999-05-02 11:21:08 +00004601 * SetMenuDefaultItem (USER32.489)
4602 *
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004603 */
Juergen Schmied466a6521999-05-02 11:21:08 +00004604BOOL WINAPI SetMenuDefaultItem(HMENU hmenu, UINT uItem, UINT bypos)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004605{
Juergen Schmied466a6521999-05-02 11:21:08 +00004606 UINT i;
4607 POPUPMENU *menu;
4608 MENUITEM *item;
4609
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004610 TRACE("(0x%x,%d,%d)\n", hmenu, uItem, bypos);
Alexandre Julliarda845b881998-06-01 10:44:35 +00004611
Gerard Patel3e629742000-01-17 22:22:16 +00004612 if (!(menu = MENU_GetMenu(hmenu))) return FALSE;
Alexandre Julliarda845b881998-06-01 10:44:35 +00004613
Juergen Schmied466a6521999-05-02 11:21:08 +00004614 /* reset all default-item flags */
4615 item = menu->items;
4616 for (i = 0; i < menu->nItems; i++, item++)
4617 {
4618 item->fState &= ~MFS_DEFAULT;
4619 }
4620
4621 /* no default item */
4622 if ( -1 == uItem)
4623 {
4624 return TRUE;
4625 }
Alexandre Julliarda845b881998-06-01 10:44:35 +00004626
Juergen Schmied466a6521999-05-02 11:21:08 +00004627 item = menu->items;
4628 if ( bypos )
4629 {
4630 if ( uItem >= menu->nItems ) return FALSE;
4631 item[uItem].fState |= MFS_DEFAULT;
4632 return TRUE;
4633 }
4634 else
4635 {
4636 for (i = 0; i < menu->nItems; i++, item++)
4637 {
4638 if (item->wID == uItem)
4639 {
4640 item->fState |= MFS_DEFAULT;
4641 return TRUE;
4642 }
4643 }
4644
4645 }
4646 return FALSE;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004647}
4648
Alexandre Julliarda845b881998-06-01 10:44:35 +00004649/**********************************************************************
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00004650 * GetMenuDefaultItem (USER32.260)
Alexandre Julliarda845b881998-06-01 10:44:35 +00004651 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004652UINT WINAPI GetMenuDefaultItem(HMENU hmenu, UINT bypos, UINT flags)
Alexandre Julliarda845b881998-06-01 10:44:35 +00004653{
Juergen Schmied466a6521999-05-02 11:21:08 +00004654 POPUPMENU *menu;
4655 MENUITEM * item;
4656 UINT i = 0;
Alexandre Julliarda845b881998-06-01 10:44:35 +00004657
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004658 TRACE("(0x%x,%d,%d)\n", hmenu, bypos, flags);
Alexandre Julliarda845b881998-06-01 10:44:35 +00004659
Gerard Patel3e629742000-01-17 22:22:16 +00004660 if (!(menu = MENU_GetMenu(hmenu))) return -1;
Juergen Schmied466a6521999-05-02 11:21:08 +00004661
4662 /* find default item */
4663 item = menu->items;
Juergen Schmied49251861999-05-13 18:42:03 +00004664
4665 /* empty menu */
4666 if (! item) return -1;
4667
Juergen Schmied466a6521999-05-02 11:21:08 +00004668 while ( !( item->fState & MFS_DEFAULT ) )
4669 {
4670 i++; item++;
4671 if (i >= menu->nItems ) return -1;
4672 }
4673
4674 /* default: don't return disabled items */
4675 if ( (!(GMDI_USEDISABLED & flags)) && (item->fState & MFS_DISABLED )) return -1;
4676
4677 /* search rekursiv when needed */
4678 if ( (item->fType & MF_POPUP) && (flags & GMDI_GOINTOPOPUPS) )
4679 {
4680 UINT ret;
4681 ret = GetMenuDefaultItem( item->hSubMenu, bypos, flags );
4682 if ( -1 != ret ) return ret;
4683
4684 /* when item not found in submenu, return the popup item */
4685 }
4686 return ( bypos ) ? i : item->wID;
4687
Alexandre Julliarda845b881998-06-01 10:44:35 +00004688}
4689
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004690/*******************************************************************
4691 * InsertMenuItem16 (USER.441)
4692 *
4693 * FIXME: untested
4694 */
4695BOOL16 WINAPI InsertMenuItem16( HMENU16 hmenu, UINT16 pos, BOOL16 byposition,
4696 const MENUITEMINFO16 *mii )
4697{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004698 MENUITEMINFOA miia;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004699
4700 miia.cbSize = sizeof(miia);
4701 miia.fMask = mii->fMask;
Alexandre Julliard77b99181997-09-14 17:17:23 +00004702 miia.dwTypeData = mii->dwTypeData;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004703 miia.fType = mii->fType;
4704 miia.fState = mii->fState;
4705 miia.wID = mii->wID;
4706 miia.hSubMenu = mii->hSubMenu;
4707 miia.hbmpChecked = mii->hbmpChecked;
4708 miia.hbmpUnchecked = mii->hbmpUnchecked;
4709 miia.dwItemData = mii->dwItemData;
4710 miia.cch = mii->cch;
4711 if (IS_STRING_ITEM(miia.fType))
4712 miia.dwTypeData = PTR_SEG_TO_LIN(miia.dwTypeData);
Alexandre Julliarda3960291999-02-26 11:11:13 +00004713 return InsertMenuItemA( hmenu, pos, byposition, &miia );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004714}
4715
4716
4717/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004718 * InsertMenuItemA (USER32.323)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004719 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004720BOOL WINAPI InsertMenuItemA(HMENU hMenu, UINT uItem, BOOL bypos,
4721 const MENUITEMINFOA *lpmii)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004722{
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00004723 MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
Aric Stewartc946b1c2000-10-24 21:28:19 +00004724 return SetMenuItemInfo_common(item, (const MENUITEMINFOW *)lpmii, FALSE);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004725}
4726
4727
4728/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004729 * InsertMenuItemW (USER32.324)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004730 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004731BOOL WINAPI InsertMenuItemW(HMENU hMenu, UINT uItem, BOOL bypos,
4732 const MENUITEMINFOW *lpmii)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004733{
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00004734 MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
Aric Stewartc946b1c2000-10-24 21:28:19 +00004735 return SetMenuItemInfo_common(item, lpmii, TRUE);
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004736}
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004737
4738/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004739 * CheckMenuRadioItem (USER32.47)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004740 */
4741
Alexandre Julliarda3960291999-02-26 11:11:13 +00004742BOOL WINAPI CheckMenuRadioItem(HMENU hMenu,
4743 UINT first, UINT last, UINT check,
4744 UINT bypos)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004745{
4746 MENUITEM *mifirst, *milast, *micheck;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004747 HMENU mfirst = hMenu, mlast = hMenu, mcheck = hMenu;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004748
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004749 TRACE("ox%x: %d-%d, check %d, bypos=%d\n",
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00004750 hMenu, first, last, check, bypos);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004751
4752 mifirst = MENU_FindItem (&mfirst, &first, bypos);
4753 milast = MENU_FindItem (&mlast, &last, bypos);
4754 micheck = MENU_FindItem (&mcheck, &check, bypos);
4755
4756 if (mifirst == NULL || milast == NULL || micheck == NULL ||
4757 mifirst > milast || mfirst != mlast || mfirst != mcheck ||
4758 micheck > milast || micheck < mifirst)
4759 return FALSE;
4760
4761 while (mifirst <= milast)
4762 {
4763 if (mifirst == micheck)
4764 {
4765 mifirst->fType |= MFT_RADIOCHECK;
4766 mifirst->fState |= MFS_CHECKED;
4767 } else {
4768 mifirst->fType &= ~MFT_RADIOCHECK;
4769 mifirst->fState &= ~MFS_CHECKED;
4770 }
4771 mifirst++;
4772 }
4773
4774 return TRUE;
4775}
4776
4777/**********************************************************************
4778 * CheckMenuRadioItem16 (not a Windows API)
4779 */
4780
4781BOOL16 WINAPI CheckMenuRadioItem16(HMENU16 hMenu,
4782 UINT16 first, UINT16 last, UINT16 check,
4783 BOOL16 bypos)
4784{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004785 return CheckMenuRadioItem (hMenu, first, last, check, bypos);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004786}
4787
4788/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004789 * GetMenuItemRect (USER32.266)
Pascal Lessard47274231999-02-13 12:21:46 +00004790 *
4791 * ATTENTION: Here, the returned values in rect are the screen
4792 * coordinates of the item just like if the menu was
4793 * always on the upper left side of the application.
4794 *
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004795 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004796BOOL WINAPI GetMenuItemRect (HWND hwnd, HMENU hMenu, UINT uItem,
4797 LPRECT rect)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004798{
Pascal Lessard47274231999-02-13 12:21:46 +00004799 POPUPMENU *itemMenu;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004800 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004801 HWND referenceHwnd;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004802
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004803 TRACE("(0x%x,0x%x,%d,%p)\n", hwnd, hMenu, uItem, rect);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004804
4805 item = MENU_FindItem (&hMenu, &uItem, MF_BYPOSITION);
Pascal Lessard47274231999-02-13 12:21:46 +00004806 referenceHwnd = hwnd;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004807
Pascal Lessard47274231999-02-13 12:21:46 +00004808 if(!hwnd)
4809 {
Gerard Patel3e629742000-01-17 22:22:16 +00004810 itemMenu = MENU_GetMenu(hMenu);
Pascal Lessard47274231999-02-13 12:21:46 +00004811 if (itemMenu == NULL)
4812 return FALSE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004813
Marcus Meissnerac593bb1999-03-17 15:18:28 +00004814 if(itemMenu->hWnd == 0)
Pascal Lessard47274231999-02-13 12:21:46 +00004815 return FALSE;
4816 referenceHwnd = itemMenu->hWnd;
4817 }
4818
4819 if ((rect == NULL) || (item == NULL))
4820 return FALSE;
4821
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004822 *rect = item->rect;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004823
Alexandre Julliarda3960291999-02-26 11:11:13 +00004824 MapWindowPoints(referenceHwnd, 0, (LPPOINT)rect, 2);
Pascal Lessard47274231999-02-13 12:21:46 +00004825
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004826 return TRUE;
4827}
4828
4829/**********************************************************************
4830 * GetMenuItemRect16 (USER.665)
4831 */
4832
4833BOOL16 WINAPI GetMenuItemRect16 (HWND16 hwnd, HMENU16 hMenu, UINT16 uItem,
4834 LPRECT16 rect)
4835{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004836 RECT r32;
4837 BOOL res;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004838
4839 if (!rect) return FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004840 res = GetMenuItemRect (hwnd, hMenu, uItem, &r32);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004841 CONV_RECT32TO16 (&r32, rect);
4842 return res;
4843}
Paul Quinn1beaae51998-12-15 15:38:36 +00004844
4845/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004846 * SetMenuInfo
4847 *
4848 * FIXME
4849 * MIM_APPLYTOSUBMENUS
4850 * actually use the items to draw the menu
4851 */
4852BOOL WINAPI SetMenuInfo (HMENU hMenu, LPCMENUINFO lpmi)
4853{
4854 POPUPMENU *menu;
4855
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004856 TRACE("(0x%04x %p)\n", hMenu, lpmi);
Juergen Schmied78513941999-04-18 14:40:32 +00004857
Gerard Patel3e629742000-01-17 22:22:16 +00004858 if (lpmi && (lpmi->cbSize==sizeof(MENUINFO)) && (menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004859 {
4860
4861 if (lpmi->fMask & MIM_BACKGROUND)
4862 menu->hbrBack = lpmi->hbrBack;
4863
4864 if (lpmi->fMask & MIM_HELPID)
4865 menu->dwContextHelpID = lpmi->dwContextHelpID;
4866
4867 if (lpmi->fMask & MIM_MAXHEIGHT)
4868 menu->cyMax = lpmi->cyMax;
4869
4870 if (lpmi->fMask & MIM_MENUDATA)
4871 menu->dwMenuData = lpmi->dwMenuData;
4872
4873 if (lpmi->fMask & MIM_STYLE)
4874 menu->dwStyle = lpmi->dwStyle;
4875
4876 return TRUE;
4877 }
4878 return FALSE;
4879}
4880
4881/**********************************************************************
4882 * GetMenuInfo
4883 *
4884 * NOTES
4885 * win98/NT5.0
4886 *
4887 */
4888BOOL WINAPI GetMenuInfo (HMENU hMenu, LPMENUINFO lpmi)
4889{ POPUPMENU *menu;
4890
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004891 TRACE("(0x%04x %p)\n", hMenu, lpmi);
Juergen Schmied78513941999-04-18 14:40:32 +00004892
Gerard Patel3e629742000-01-17 22:22:16 +00004893 if (lpmi && (menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004894 {
4895
4896 if (lpmi->fMask & MIM_BACKGROUND)
4897 lpmi->hbrBack = menu->hbrBack;
4898
4899 if (lpmi->fMask & MIM_HELPID)
4900 lpmi->dwContextHelpID = menu->dwContextHelpID;
4901
4902 if (lpmi->fMask & MIM_MAXHEIGHT)
4903 lpmi->cyMax = menu->cyMax;
4904
4905 if (lpmi->fMask & MIM_MENUDATA)
4906 lpmi->dwMenuData = menu->dwMenuData;
4907
4908 if (lpmi->fMask & MIM_STYLE)
4909 lpmi->dwStyle = menu->dwStyle;
4910
4911 return TRUE;
4912 }
4913 return FALSE;
4914}
4915
4916/**********************************************************************
Paul Quinn1beaae51998-12-15 15:38:36 +00004917 * SetMenuContextHelpId16 (USER.384)
4918 */
Juergen Schmied78513941999-04-18 14:40:32 +00004919BOOL16 WINAPI SetMenuContextHelpId16( HMENU16 hMenu, DWORD dwContextHelpID)
Paul Quinn1beaae51998-12-15 15:38:36 +00004920{
Juergen Schmied78513941999-04-18 14:40:32 +00004921 return SetMenuContextHelpId( hMenu, dwContextHelpID );
Paul Quinn1beaae51998-12-15 15:38:36 +00004922}
4923
4924
4925/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004926 * SetMenuContextHelpId (USER32.488)
Paul Quinn1beaae51998-12-15 15:38:36 +00004927 */
Juergen Schmied78513941999-04-18 14:40:32 +00004928BOOL WINAPI SetMenuContextHelpId( HMENU hMenu, DWORD dwContextHelpID)
Paul Quinn1beaae51998-12-15 15:38:36 +00004929{
Juergen Schmied78513941999-04-18 14:40:32 +00004930 LPPOPUPMENU menu;
4931
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004932 TRACE("(0x%04x 0x%08lx)\n", hMenu, dwContextHelpID);
Juergen Schmied78513941999-04-18 14:40:32 +00004933
Gerard Patel3e629742000-01-17 22:22:16 +00004934 if ((menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004935 {
4936 menu->dwContextHelpID = dwContextHelpID;
4937 return TRUE;
4938 }
4939 return FALSE;
Paul Quinn1beaae51998-12-15 15:38:36 +00004940}
4941
4942/**********************************************************************
4943 * GetMenuContextHelpId16 (USER.385)
4944 */
4945DWORD WINAPI GetMenuContextHelpId16( HMENU16 hMenu )
4946{
Juergen Schmied78513941999-04-18 14:40:32 +00004947 return GetMenuContextHelpId( hMenu );
Paul Quinn1beaae51998-12-15 15:38:36 +00004948}
4949
4950/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004951 * GetMenuContextHelpId (USER32.488)
Paul Quinn1beaae51998-12-15 15:38:36 +00004952 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004953DWORD WINAPI GetMenuContextHelpId( HMENU hMenu )
Paul Quinn1beaae51998-12-15 15:38:36 +00004954{
Juergen Schmied78513941999-04-18 14:40:32 +00004955 LPPOPUPMENU menu;
4956
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004957 TRACE("(0x%04x)\n", hMenu);
Juergen Schmied78513941999-04-18 14:40:32 +00004958
Gerard Patel3e629742000-01-17 22:22:16 +00004959 if ((menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004960 {
4961 return menu->dwContextHelpID;
4962 }
4963 return 0;
Paul Quinn1beaae51998-12-15 15:38:36 +00004964}
Eric Pouech0c62bf01999-09-13 15:11:35 +00004965
4966/**********************************************************************
4967 * MenuItemFromPoint (USER32.387)
4968 */
4969UINT WINAPI MenuItemFromPoint(HWND hWnd, HMENU hMenu, POINT ptScreen)
4970{
4971 FIXME("(0x%04x,0x%04x,(%ld,%ld)):stub\n",
4972 hWnd, hMenu, ptScreen.x, ptScreen.y);
4973 return 0;
4974}
Dmitry Timoshkovef559322000-10-26 21:47:20 +00004975
4976
4977/**********************************************************************
4978 * translate_accelerator
4979 */
4980static BOOL translate_accelerator( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam,
4981 BYTE fVirt, WORD key, WORD cmd )
4982{
4983 UINT mesg = 0;
4984
4985 if (wParam != key) return FALSE;
4986
4987 if (message == WM_CHAR)
4988 {
4989 if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) )
4990 {
4991 TRACE_(accel)("found accel for WM_CHAR: ('%c')\n", wParam & 0xff);
4992 goto found;
4993 }
4994 }
4995 else
4996 {
4997 if(fVirt & FVIRTKEY)
4998 {
4999 INT mask = 0;
5000 TRACE_(accel)("found accel for virt_key %04x (scan %04x)\n",
5001 wParam, 0xff & HIWORD(lParam));
5002 if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT;
5003 if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL;
5004 if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT;
5005 if(mask == (fVirt & (FSHIFT | FCONTROL | FALT))) goto found;
5006 TRACE_(accel)(", but incorrect SHIFT/CTRL/ALT-state\n");
5007 }
5008 else
5009 {
5010 if (!(lParam & 0x01000000)) /* no special_key */
5011 {
5012 if ((fVirt & FALT) && (lParam & 0x20000000))
5013 { /* ^^ ALT pressed */
5014 TRACE_(accel)("found accel for Alt-%c\n", wParam & 0xff);
5015 goto found;
5016 }
5017 }
5018 }
5019 }
5020 return FALSE;
5021
5022 found:
5023 if (message == WM_KEYUP || message == WM_SYSKEYUP)
5024 mesg = 1;
5025 else if (GetCapture())
5026 mesg = 2;
5027 else if (!IsWindowEnabled(hWnd))
5028 mesg = 3;
5029 else
5030 {
5031 HMENU hMenu, hSubMenu, hSysMenu;
5032 UINT uSysStat = (UINT)-1, uStat = (UINT)-1, nPos;
5033 WND* wndPtr = WIN_FindWndPtr(hWnd);
5034
5035 hMenu = (wndPtr->dwStyle & WS_CHILD) ? 0 : (HMENU)wndPtr->wIDmenu;
5036 hSysMenu = wndPtr->hSysMenu;
5037 WIN_ReleaseWndPtr(wndPtr);
5038
5039 /* find menu item and ask application to initialize it */
5040 /* 1. in the system menu */
5041 hSubMenu = hSysMenu;
5042 nPos = cmd;
5043 if(MENU_FindItem(&hSubMenu, &nPos, MF_BYCOMMAND))
5044 {
5045 SendMessageA(hWnd, WM_INITMENU, (WPARAM)hSysMenu, 0L);
5046 if(hSubMenu != hSysMenu)
5047 {
5048 nPos = MENU_FindSubMenu(&hSysMenu, hSubMenu);
5049 TRACE_(accel)("hSysMenu = %04x, hSubMenu = %04x, nPos = %d\n", hSysMenu, hSubMenu, nPos);
5050 SendMessageA(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, TRUE));
5051 }
5052 uSysStat = GetMenuState(GetSubMenu(hSysMenu, 0), cmd, MF_BYCOMMAND);
5053 }
5054 else /* 2. in the window's menu */
5055 {
5056 hSubMenu = hMenu;
5057 nPos = cmd;
5058 if(MENU_FindItem(&hSubMenu, &nPos, MF_BYCOMMAND))
5059 {
5060 SendMessageA(hWnd, WM_INITMENU, (WPARAM)hMenu, 0L);
5061 if(hSubMenu != hMenu)
5062 {
5063 nPos = MENU_FindSubMenu(&hMenu, hSubMenu);
5064 TRACE_(accel)("hMenu = %04x, hSubMenu = %04x, nPos = %d\n", hMenu, hSubMenu, nPos);
5065 SendMessageA(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, FALSE));
5066 }
5067 uStat = GetMenuState(hMenu, cmd, MF_BYCOMMAND);
5068 }
5069 }
5070
5071 if (uSysStat != (UINT)-1)
5072 {
5073 if (uSysStat & (MF_DISABLED|MF_GRAYED))
5074 mesg=4;
5075 else
5076 mesg=WM_SYSCOMMAND;
5077 }
5078 else
5079 {
5080 if (uStat != (UINT)-1)
5081 {
5082 if (IsIconic(hWnd))
5083 mesg=5;
5084 else
5085 {
5086 if (uStat & (MF_DISABLED|MF_GRAYED))
5087 mesg=6;
5088 else
5089 mesg=WM_COMMAND;
5090 }
5091 }
5092 else
5093 mesg=WM_COMMAND;
5094 }
5095 }
5096
5097 if( mesg==WM_COMMAND )
5098 {
5099 TRACE_(accel)(", sending WM_COMMAND, wParam=%0x\n", 0x10000 | cmd);
5100 SendMessageA(hWnd, mesg, 0x10000 | cmd, 0L);
5101 }
5102 else if( mesg==WM_SYSCOMMAND )
5103 {
5104 TRACE_(accel)(", sending WM_SYSCOMMAND, wParam=%0x\n", cmd);
5105 SendMessageA(hWnd, mesg, cmd, 0x00010000L);
5106 }
5107 else
5108 {
5109 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
5110 * #0: unknown (please report!)
5111 * #1: for WM_KEYUP,WM_SYSKEYUP
5112 * #2: mouse is captured
5113 * #3: window is disabled
5114 * #4: it's a disabled system menu option
5115 * #5: it's a menu option, but window is iconic
5116 * #6: it's a menu option, but disabled
5117 */
5118 TRACE_(accel)(", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg);
5119 if(mesg==0)
5120 ERR_(accel)(" unknown reason - please report!");
5121 }
5122 return TRUE;
5123}
5124
5125/**********************************************************************
5126 * TranslateAccelerator (USER32.551)(USER32.552)(USER32.553)
5127 */
5128INT WINAPI TranslateAccelerator( HWND hWnd, HACCEL hAccel, LPMSG msg )
5129{
5130 /* YES, Accel16! */
5131 LPACCEL16 lpAccelTbl;
5132 int i;
5133
5134 if (msg == NULL)
5135 {
5136 WARN_(accel)("msg null; should hang here to be win compatible\n");
5137 return 0;
5138 }
5139 if (!hAccel || !(lpAccelTbl = (LPACCEL16) LockResource16(hAccel)))
5140 {
5141 WARN_(accel)("invalid accel handle=%x\n", hAccel);
5142 return 0;
5143 }
5144 if ((msg->message != WM_KEYDOWN &&
5145 msg->message != WM_KEYUP &&
5146 msg->message != WM_SYSKEYDOWN &&
5147 msg->message != WM_SYSKEYUP &&
5148 msg->message != WM_CHAR)) return 0;
5149
5150 TRACE_(accel)("TranslateAccelerators hAccel=%04x, hWnd=%04x,"
5151 "msg->hwnd=%04x, msg->message=%04x, wParam=%08x, lParam=%lx\n",
5152 hAccel,hWnd,msg->hwnd,msg->message,msg->wParam,msg->lParam);
5153
5154 i = 0;
5155 do
5156 {
5157 if (translate_accelerator( hWnd, msg->message, msg->wParam, msg->lParam,
5158 lpAccelTbl[i].fVirt, lpAccelTbl[i].key, lpAccelTbl[i].cmd))
5159 return 1;
5160 } while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
5161 WARN_(accel)("couldn't translate accelerator key\n");
5162 return 0;
5163}
5164
5165
5166/**********************************************************************
5167 * TranslateAccelerator16 (USER.178)
5168 */
5169INT16 WINAPI TranslateAccelerator16( HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg )
5170{
5171 LPACCEL16 lpAccelTbl;
5172 int i;
5173
5174 if (msg == NULL)
5175 {
5176 WARN_(accel)("msg null; should hang here to be win compatible\n");
5177 return 0;
5178 }
5179 if (!hAccel || !(lpAccelTbl = (LPACCEL16) LockResource16(hAccel)))
5180 {
5181 WARN_(accel)("invalid accel handle=%x\n", hAccel);
5182 return 0;
5183 }
5184 if ((msg->message != WM_KEYDOWN &&
5185 msg->message != WM_KEYUP &&
5186 msg->message != WM_SYSKEYDOWN &&
5187 msg->message != WM_SYSKEYUP &&
5188 msg->message != WM_CHAR)) return 0;
5189
5190 TRACE_(accel)("TranslateAccelerators hAccel=%04x, hWnd=%04x,"
5191 "msg->hwnd=%04x, msg->message=%04x, wParam=%04x, lParam=%lx\n",
5192 hAccel,hWnd,msg->hwnd,msg->message,msg->wParam,msg->lParam);
5193
5194 i = 0;
5195 do
5196 {
5197 if (translate_accelerator( hWnd, msg->message, msg->wParam, msg->lParam,
5198 lpAccelTbl[i].fVirt, lpAccelTbl[i].key, lpAccelTbl[i].cmd ))
5199 return 1;
5200 } while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
5201 WARN_(accel)("couldn't translate accelerator key\n");
5202 return 0;
5203}