blob: 8766138c4b24645b13c1cf4b2f276a9d4f0fdeb2 [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"
Jeremy Whited3e22d92000-02-10 19:03:02 +000024#include "win.h"
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000025#include "task.h"
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000026#include "heap.h"
Francois Boisvert197a8e11999-02-13 09:10:17 +000027#include "menu.h"
Alexandre Julliardc6c09441997-01-12 18:32:19 +000028#include "nonclient.h"
Alexandre Julliard1f579291994-05-25 16:25:21 +000029#include "user.h"
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +000030#include "message.h"
Patrik Stridvall6cc47d42000-03-08 18:26:56 +000031#include "queue.h"
Alexandre Julliardd37eb361997-07-20 16:23:21 +000032#include "tweak.h"
Marcus Meissnerd5e7c791998-12-09 11:06:00 +000033
Alexandre Julliard9fe7a251999-05-14 08:17:14 +000034#include "debugtools.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000035
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000036DEFAULT_DEBUG_CHANNEL(menu)
37
Alexandre Julliardd37eb361997-07-20 16:23:21 +000038
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000039/* internal popup menu window messages */
40
41#define MM_SETMENUHANDLE (WM_USER + 0)
42#define MM_GETMENUHANDLE (WM_USER + 1)
43
Alexandre Julliard2d93d001996-05-21 15:01:41 +000044/* Menu item structure */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000045typedef struct {
46 /* ----------- MENUITEMINFO Stuff ----------- */
Juergen Schmied78513941999-04-18 14:40:32 +000047 UINT fType; /* Item type. */
Alexandre Julliarda3960291999-02-26 11:11:13 +000048 UINT fState; /* Item state. */
49 UINT wID; /* Item id. */
50 HMENU hSubMenu; /* Pop-up menu. */
Juergen Schmied78513941999-04-18 14:40:32 +000051 HBITMAP hCheckBit; /* Bitmap when checked. */
Alexandre Julliarda3960291999-02-26 11:11:13 +000052 HBITMAP hUnCheckBit; /* Bitmap when unchecked. */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000053 LPSTR text; /* Item text or bitmap handle. */
54 DWORD dwItemData; /* Application defined. */
Juergen Schmied78513941999-04-18 14:40:32 +000055 DWORD dwTypeData; /* depends on fMask */
56 HBITMAP hbmpItem; /* bitmap in win98 style menus */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000057 /* ----------- Wine stuff ----------- */
Juergen Schmied78513941999-04-18 14:40:32 +000058 RECT rect; /* Item area (relative to menu window) */
59 UINT xTab; /* X position of text after Tab */
Alexandre Julliard2d93d001996-05-21 15:01:41 +000060} MENUITEM;
61
62/* Popup menu structure */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000063typedef struct {
Alexandre Julliard2d93d001996-05-21 15:01:41 +000064 WORD wFlags; /* Menu flags (MF_POPUP, MF_SYSMENU) */
65 WORD wMagic; /* Magic number */
Alexandre Julliardbf9130a1996-10-13 17:45:47 +000066 HQUEUE16 hTaskQ; /* Task queue for this menu */
Alexandre Julliard2d93d001996-05-21 15:01:41 +000067 WORD Width; /* Width of the whole menu */
68 WORD Height; /* Height of the whole menu */
69 WORD nItems; /* Number of items in the menu */
Juergen Schmied78513941999-04-18 14:40:32 +000070 HWND hWnd; /* Window containing the menu */
71 MENUITEM *items; /* Array of menu items */
72 UINT FocusedItem; /* Currently focused item */
Juergen Schmied466a6521999-05-02 11:21:08 +000073 HWND hwndOwner; /* window receiving the messages for ownerdraw */
Pascal Lessard2eb0a301999-09-03 16:38:52 +000074 BOOL bTimeToHide; /* Request hiding when receiving a second click in the top-level menu item */
Juergen Schmied78513941999-04-18 14:40:32 +000075 /* ------------ MENUINFO members ------ */
76 DWORD dwStyle; /* Extended mennu style */
77 UINT cyMax; /* max hight of the whole menu, 0 is screen hight */
78 HBRUSH hbrBack; /* brush for menu background */
79 DWORD dwContextHelpID;
80 DWORD dwMenuData; /* application defined value */
Pascal Lessardd814bb61999-07-31 13:02:02 +000081 HMENU hSysMenuOwner; /* Handle to the dummy sys menu holder */
Alexandre Julliard2d93d001996-05-21 15:01:41 +000082} POPUPMENU, *LPPOPUPMENU;
83
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000084/* internal flags for menu tracking */
85
86#define TF_ENDMENU 0x0001
87#define TF_SUSPENDPOPUP 0x0002
88#define TF_SKIPREMOVE 0x0004
89
90typedef struct
91{
Alexandre Julliarda3960291999-02-26 11:11:13 +000092 UINT trackFlags;
93 HMENU hCurrentMenu; /* current submenu (can be equal to hTopMenu)*/
94 HMENU hTopMenu; /* initial menu */
95 HWND hOwnerWnd; /* where notifications are sent */
96 POINT pt;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000097} MTRACKER;
98
Alexandre Julliard2d93d001996-05-21 15:01:41 +000099#define MENU_MAGIC 0x554d /* 'MU' */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000100#define IS_A_MENU(pmenu) ((pmenu) && (pmenu)->wMagic == MENU_MAGIC)
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000101
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000102#define ITEM_PREV -1
103#define ITEM_NEXT 1
104
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000105 /* Internal MENU_TrackMenu() flags */
106#define TPM_INTERNAL 0xF0000000
107#define TPM_ENTERIDLEEX 0x80000000 /* set owner window for WM_ENTERIDLE */
108#define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */
Francois Boisvert85dd9fc1999-02-17 12:50:11 +0000109#define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */
Alexandre Julliardf7207251994-07-23 07:57:48 +0000110
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000111 /* popup menu shade thickness */
112#define POPUP_XSHADE 4
113#define POPUP_YSHADE 4
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000114
Alexandre Julliardf7207251994-07-23 07:57:48 +0000115 /* Space between 2 menu bar items */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000116#define MENU_BAR_ITEMS_SPACE 12
Alexandre Julliardf7207251994-07-23 07:57:48 +0000117
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000118 /* Minimum width of a tab character */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000119#define MENU_TAB_SPACE 8
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000120
Alexandre Julliardf7207251994-07-23 07:57:48 +0000121 /* Height of a separator item */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000122#define SEPARATOR_HEIGHT 5
Alexandre Julliardf7207251994-07-23 07:57:48 +0000123
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000124 /* (other menu->FocusedItem values give the position of the focused item) */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000125#define NO_SELECTED_ITEM 0xffff
Alexandre Julliardcdd09231994-01-12 11:12:51 +0000126
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000127#define MENU_ITEM_TYPE(flags) \
128 ((flags) & (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR))
129
130#define IS_STRING_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_STRING)
Juergen Schmied78513941999-04-18 14:40:32 +0000131#define IS_BITMAP_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_BITMAP)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000132
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000133#define IS_SYSTEM_MENU(menu) \
134 (!((menu)->wFlags & MF_POPUP) && (menu)->wFlags & MF_SYSMENU)
Juergen Schmied78513941999-04-18 14:40:32 +0000135
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000136#define IS_SYSTEM_POPUP(menu) \
137 ((menu)->wFlags & MF_POPUP && (menu)->wFlags & MF_SYSMENU)
138
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000139#define TYPE_MASK (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
140 MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
141 MFT_RIGHTORDER | MFT_RIGHTJUSTIFY | \
142 MF_POPUP | MF_SYSMENU | MF_HELP)
143#define STATE_MASK (~TYPE_MASK)
144
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000145 /* Dimension of the menu bitmaps */
146static WORD check_bitmap_width = 0, check_bitmap_height = 0;
147static WORD arrow_bitmap_width = 0, arrow_bitmap_height = 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000148
Alexandre Julliarda3960291999-02-26 11:11:13 +0000149static HBITMAP hStdRadioCheck = 0;
150static HBITMAP hStdCheck = 0;
151static HBITMAP hStdMnArrow = 0;
Francois Boisvert8b391741999-02-09 14:09:55 +0000152
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +0000153/* Minimze/restore/close buttons to be inserted in menubar */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000154static HBITMAP hBmpMinimize = 0;
155static HBITMAP hBmpMinimizeD = 0;
156static HBITMAP hBmpMaximize = 0;
157static HBITMAP hBmpMaximizeD = 0;
158static HBITMAP hBmpClose = 0;
159static HBITMAP hBmpCloseD = 0;
Francois Boisvert308c6af1999-02-18 10:37:17 +0000160
Francois Boisvert8b391741999-02-09 14:09:55 +0000161
Juergen Schmied78513941999-04-18 14:40:32 +0000162static HBRUSH hShadeBrush = 0;
163static HFONT hMenuFont = 0;
Juergen Schmied466a6521999-05-02 11:21:08 +0000164static HFONT hMenuFontBold = 0;
Juergen Schmied78513941999-04-18 14:40:32 +0000165
Alexandre Julliarda3960291999-02-26 11:11:13 +0000166static HMENU MENU_DefSysPopup = 0; /* Default system menu popup */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000167
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000168/* Use global popup window because there's no way 2 menus can
169 * be tracked at the same time. */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000170
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000171static WND* pTopPopupWnd = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000172static UINT uSubPWndLevel = 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000173
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000174 /* Flag set by EndMenu() to force an exit from menu tracking */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000175static BOOL fEndMenu = FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000176
177
178/***********************************************************************
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000179 * debug_print_menuitem
180 *
181 * Print a menuitem in readable form.
182 */
183
Alexandre Julliard03468f71998-02-15 19:40:49 +0000184#define debug_print_menuitem(pre, mp, post) \
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000185 if(!TRACE_ON(menu)) ; else do_debug_print_menuitem(pre, mp, post)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000186
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000187#define MENUOUT(text) \
Alexandre Julliard15de6151999-08-04 12:22:42 +0000188 DPRINTF("%s%s", (count++ ? "," : ""), (text))
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000189
190#define MENUFLAG(bit,text) \
191 do { \
192 if (flags & (bit)) { flags &= ~(bit); MENUOUT ((text)); } \
193 } while (0)
194
Alexandre Julliard03468f71998-02-15 19:40:49 +0000195static void do_debug_print_menuitem(const char *prefix, MENUITEM * mp,
196 const char *postfix)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000197{
Alexandre Julliard15de6151999-08-04 12:22:42 +0000198 TRACE("%s ", prefix);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000199 if (mp) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000200 UINT flags = mp->fType;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000201 int typ = MENU_ITEM_TYPE(flags);
Alexandre Julliard15de6151999-08-04 12:22:42 +0000202 DPRINTF( "{ ID=0x%x", mp->wID);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000203 if (flags & MF_POPUP)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000204 DPRINTF( ", Sub=0x%x", mp->hSubMenu);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000205 if (flags) {
206 int count = 0;
Alexandre Julliard15de6151999-08-04 12:22:42 +0000207 DPRINTF( ", Typ=");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000208 if (typ == MFT_STRING)
209 /* Nothing */ ;
210 else if (typ == MFT_SEPARATOR)
211 MENUOUT("sep");
212 else if (typ == MFT_OWNERDRAW)
213 MENUOUT("own");
214 else if (typ == MFT_BITMAP)
215 MENUOUT("bit");
216 else
217 MENUOUT("???");
218 flags -= typ;
219
220 MENUFLAG(MF_POPUP, "pop");
221 MENUFLAG(MFT_MENUBARBREAK, "barbrk");
222 MENUFLAG(MFT_MENUBREAK, "brk");
223 MENUFLAG(MFT_RADIOCHECK, "radio");
224 MENUFLAG(MFT_RIGHTORDER, "rorder");
225 MENUFLAG(MF_SYSMENU, "sys");
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +0000226 MENUFLAG(MFT_RIGHTJUSTIFY, "right"); /* same as MF_HELP */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000227
228 if (flags)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000229 DPRINTF( "+0x%x", flags);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000230 }
231 flags = mp->fState;
232 if (flags) {
233 int count = 0;
Alexandre Julliard15de6151999-08-04 12:22:42 +0000234 DPRINTF( ", State=");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000235 MENUFLAG(MFS_GRAYED, "grey");
Juergen Schmied466a6521999-05-02 11:21:08 +0000236 MENUFLAG(MFS_DEFAULT, "default");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000237 MENUFLAG(MFS_DISABLED, "dis");
238 MENUFLAG(MFS_CHECKED, "check");
239 MENUFLAG(MFS_HILITE, "hi");
240 MENUFLAG(MF_USECHECKBITMAPS, "usebit");
241 MENUFLAG(MF_MOUSESELECT, "mouse");
242 if (flags)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000243 DPRINTF( "+0x%x", flags);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000244 }
245 if (mp->hCheckBit)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000246 DPRINTF( ", Chk=0x%x", mp->hCheckBit);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000247 if (mp->hUnCheckBit)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000248 DPRINTF( ", Unc=0x%x", mp->hUnCheckBit);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000249
250 if (typ == MFT_STRING) {
251 if (mp->text)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000252 DPRINTF( ", Text=\"%s\"", mp->text);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000253 else
Alexandre Julliard15de6151999-08-04 12:22:42 +0000254 DPRINTF( ", Text=Null");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000255 } else if (mp->text == NULL)
256 /* Nothing */ ;
257 else
Alexandre Julliard15de6151999-08-04 12:22:42 +0000258 DPRINTF( ", Text=%p", mp->text);
Juergen Schmied7abca951999-04-11 17:02:30 +0000259 if (mp->dwItemData)
Alexandre Julliard15de6151999-08-04 12:22:42 +0000260 DPRINTF( ", ItemData=0x%08lx", mp->dwItemData);
261 DPRINTF( " }");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000262 } else {
Alexandre Julliard15de6151999-08-04 12:22:42 +0000263 DPRINTF( "NULL");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000264 }
Alexandre Julliard03468f71998-02-15 19:40:49 +0000265
Alexandre Julliard15de6151999-08-04 12:22:42 +0000266 DPRINTF(" %s\n", postfix);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000267}
268
269#undef MENUOUT
270#undef MENUFLAG
271
Gerard Patel3e629742000-01-17 22:22:16 +0000272
273/***********************************************************************
274 * MENU_GetMenu
275 *
276 * Validate the given menu handle and returns the menu structure pointer.
277 */
278POPUPMENU *MENU_GetMenu(HMENU hMenu)
279{
280 POPUPMENU *menu;
281 menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(hMenu);
282 if (!IS_A_MENU(menu))
283 {
Gerard Patelc6369b02000-05-14 22:52:52 +0000284 WARN("invalid menu handle=%x, ptr=%p, magic=%x\n", hMenu, menu, menu? menu->wMagic:0);
Gerard Patel3e629742000-01-17 22:22:16 +0000285 menu = NULL;
286 }
287 return menu;
288}
289
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000290/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000291 * MENU_CopySysPopup
292 *
293 * Return the default system menu.
294 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000295static HMENU MENU_CopySysPopup(void)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000296{
Bertho Stultiensd1895a71999-04-25 18:31:35 +0000297 HMENU hMenu = LoadMenuA(GetModuleHandleA("USER32"), "SYSMENU");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000298
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000299 if( hMenu ) {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000300 POPUPMENU* menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(hMenu);
301 menu->wFlags |= MF_SYSMENU | MF_POPUP;
Juergen Schmied49251861999-05-13 18:42:03 +0000302 SetMenuDefaultItem(hMenu, SC_CLOSE, FALSE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000303 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000304 else {
305 hMenu = 0;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000306 ERR("Unable to load default system menu\n" );
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000307 }
308
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000309 TRACE("returning %x.\n", hMenu );
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000310
311 return hMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000312}
313
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000314/***********************************************************************
315 * MENU_GetTopPopupWnd()
316 *
317 * Return the locked pointer pTopPopupWnd.
318 */
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000319static WND *MENU_GetTopPopupWnd()
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000320{
321 return WIN_LockWndPtr(pTopPopupWnd);
322}
323/***********************************************************************
324 * MENU_ReleaseTopPopupWnd()
325 *
326 * Realease the locked pointer pTopPopupWnd.
327 */
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000328static void MENU_ReleaseTopPopupWnd()
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000329{
330 WIN_ReleaseWndPtr(pTopPopupWnd);
331}
332/***********************************************************************
333 * MENU_DestroyTopPopupWnd()
334 *
335 * Destroy the locked pointer pTopPopupWnd.
336 */
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000337static void MENU_DestroyTopPopupWnd()
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000338{
339 WND *tmpWnd = pTopPopupWnd;
340 pTopPopupWnd = NULL;
341 WIN_ReleaseWndPtr(tmpWnd);
342}
343
344
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000345
346/**********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000347 * MENU_GetSysMenu
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000348 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000349 * Create a copy of the system menu. System menu in Windows is
350 * a special menu-bar with the single entry - system menu popup.
351 * This popup is presented to the outside world as a "system menu".
352 * However, the real system menu handle is sometimes seen in the
353 * WM_MENUSELECT paramemters (and Word 6 likes it this way).
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000354 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000355HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu )
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000356{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000357 HMENU hMenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000358
Alexandre Julliarda3960291999-02-26 11:11:13 +0000359 if ((hMenu = CreateMenu()))
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000360 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000361 POPUPMENU *menu = (POPUPMENU*) USER_HEAP_LIN_ADDR(hMenu);
362 menu->wFlags = MF_SYSMENU;
363 menu->hWnd = hWnd;
364
Alexandre Julliarda3960291999-02-26 11:11:13 +0000365 if (hPopupMenu == (HMENU)(-1))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000366 hPopupMenu = MENU_CopySysPopup();
367 else if( !hPopupMenu ) hPopupMenu = MENU_DefSysPopup;
368
369 if (hPopupMenu)
370 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000371 InsertMenuA( hMenu, -1, MF_SYSMENU | MF_POPUP | MF_BYPOSITION, hPopupMenu, NULL );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000372
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000373 menu->items[0].fType = MF_SYSMENU | MF_POPUP;
374 menu->items[0].fState = 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000375 menu = (POPUPMENU*) USER_HEAP_LIN_ADDR(hPopupMenu);
376 menu->wFlags |= MF_SYSMENU;
377
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000378 TRACE("GetSysMenu hMenu=%04x (%04x)\n", hMenu, hPopupMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000379 return hMenu;
380 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000381 DestroyMenu( hMenu );
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000382 }
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000383 ERR("failed to load system menu!\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000384 return 0;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000385}
386
387
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000388/***********************************************************************
389 * MENU_Init
390 *
391 * Menus initialisation.
392 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000393BOOL MENU_Init()
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000394{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000395 HBITMAP hBitmap;
Juergen Schmied78513941999-04-18 14:40:32 +0000396 NONCLIENTMETRICSA ncm;
397
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000398 static unsigned char shade_bits[16] = { 0x55, 0, 0xAA, 0,
399 0x55, 0, 0xAA, 0,
400 0x55, 0, 0xAA, 0,
401 0x55, 0, 0xAA, 0 };
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000402
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000403 /* Load menu bitmaps */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000404 hStdCheck = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_CHECK));
405 hStdRadioCheck = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_RADIOCHECK));
406 hStdMnArrow = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_MNARROW));
Francois Boisvert8b391741999-02-09 14:09:55 +0000407 /* Load system buttons bitmaps */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000408 hBmpMinimize = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_REDUCE));
409 hBmpMinimizeD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_REDUCED));
410 hBmpMaximize = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_RESTORE));
411 hBmpMaximizeD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_RESTORED));
412 hBmpClose = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_CLOSE));
413 hBmpCloseD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_CLOSED));
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000414
415 if (hStdCheck)
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000416 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000417 BITMAP bm;
418 GetObjectA( hStdCheck, sizeof(bm), &bm );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000419 check_bitmap_width = bm.bmWidth;
420 check_bitmap_height = bm.bmHeight;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000421 } else
422 return FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000423
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000424 /* Assume that radio checks have the same size as regular check. */
425 if (!hStdRadioCheck)
426 return FALSE;
427
428 if (hStdMnArrow)
Juergen Schmied78513941999-04-18 14:40:32 +0000429 {
430 BITMAP bm;
431 GetObjectA( hStdMnArrow, sizeof(bm), &bm );
432 arrow_bitmap_width = bm.bmWidth;
433 arrow_bitmap_height = bm.bmHeight;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000434 } else
Juergen Schmied78513941999-04-18 14:40:32 +0000435 return FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000436
Juergen Schmied78513941999-04-18 14:40:32 +0000437 if (! (hBitmap = CreateBitmap( 8, 8, 1, 1, shade_bits)))
438 return FALSE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000439
Juergen Schmied78513941999-04-18 14:40:32 +0000440 if(!(hShadeBrush = CreatePatternBrush( hBitmap )))
441 return FALSE;
442
443 DeleteObject( hBitmap );
444 if (!(MENU_DefSysPopup = MENU_CopySysPopup()))
445 return FALSE;
446
447 ncm.cbSize = sizeof (NONCLIENTMETRICSA);
448 if (!(SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &ncm, 0)))
449 return FALSE;
450
451 if (!(hMenuFont = CreateFontIndirectA( &ncm.lfMenuFont )))
452 return FALSE;
453
Juergen Schmied466a6521999-05-02 11:21:08 +0000454 ncm.lfMenuFont.lfWeight += 300;
455 if ( ncm.lfMenuFont.lfWeight > 1000)
456 ncm.lfMenuFont.lfWeight = 1000;
457
458 if (!(hMenuFontBold = CreateFontIndirectA( &ncm.lfMenuFont )))
459 return FALSE;
460
Juergen Schmied78513941999-04-18 14:40:32 +0000461 return TRUE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000462}
463
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000464/***********************************************************************
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000465 * MENU_InitSysMenuPopup
466 *
467 * Grey the appropriate items in System menu.
468 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000469static void MENU_InitSysMenuPopup( HMENU hmenu, DWORD style, DWORD clsStyle )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000470{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000471 BOOL gray;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000472
473 gray = !(style & WS_THICKFRAME) || (style & (WS_MAXIMIZE | WS_MINIMIZE));
Alexandre Julliarda3960291999-02-26 11:11:13 +0000474 EnableMenuItem( hmenu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000475 gray = ((style & WS_MAXIMIZE) != 0);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000476 EnableMenuItem( hmenu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000477 gray = !(style & WS_MINIMIZEBOX) || (style & WS_MINIMIZE);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000478 EnableMenuItem( hmenu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000479 gray = !(style & WS_MAXIMIZEBOX) || (style & WS_MAXIMIZE);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000480 EnableMenuItem( hmenu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000481 gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE));
Alexandre Julliarda3960291999-02-26 11:11:13 +0000482 EnableMenuItem( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000483 gray = (clsStyle & CS_NOCLOSE) != 0;
Pascal Lessardd814bb61999-07-31 13:02:02 +0000484
485 /* The menu item must keep its state if it's disabled */
486 if(gray)
487 EnableMenuItem( hmenu, SC_CLOSE, MF_GRAYED);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000488}
489
490
Alexandre Julliard641ee761997-08-04 16:34:36 +0000491/******************************************************************************
492 *
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000493 * UINT MENU_GetStartOfNextColumn(
494 * HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000495 *
496 *****************************************************************************/
497
Alexandre Julliarda3960291999-02-26 11:11:13 +0000498static UINT MENU_GetStartOfNextColumn(
499 HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000500{
501 POPUPMENU *menu = (POPUPMENU *)USER_HEAP_LIN_ADDR(hMenu);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000502 UINT i = menu->FocusedItem + 1;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000503
504 if(!menu)
505 return NO_SELECTED_ITEM;
506
507 if( i == NO_SELECTED_ITEM )
508 return i;
509
510 for( ; i < menu->nItems; ++i ) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000511 if (menu->items[i].fType & MF_MENUBARBREAK)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000512 return i;
513 }
514
515 return NO_SELECTED_ITEM;
516}
517
518
519/******************************************************************************
520 *
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000521 * UINT MENU_GetStartOfPrevColumn(
522 * HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000523 *
524 *****************************************************************************/
525
Alexandre Julliarda3960291999-02-26 11:11:13 +0000526static UINT MENU_GetStartOfPrevColumn(
527 HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000528{
529 POPUPMENU const *menu = (POPUPMENU *)USER_HEAP_LIN_ADDR(hMenu);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000530 UINT i;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000531
532 if( !menu )
533 return NO_SELECTED_ITEM;
534
535 if( menu->FocusedItem == 0 || menu->FocusedItem == NO_SELECTED_ITEM )
536 return NO_SELECTED_ITEM;
537
538 /* Find the start of the column */
539
540 for(i = menu->FocusedItem; i != 0 &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000541 !(menu->items[i].fType & MF_MENUBARBREAK);
Alexandre Julliard641ee761997-08-04 16:34:36 +0000542 --i); /* empty */
543
544 if(i == 0)
545 return NO_SELECTED_ITEM;
546
547 for(--i; i != 0; --i) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000548 if (menu->items[i].fType & MF_MENUBARBREAK)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000549 break;
550 }
551
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000552 TRACE("ret %d.\n", i );
Alexandre Julliard641ee761997-08-04 16:34:36 +0000553
554 return i;
555}
556
557
558
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000559/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000560 * MENU_FindItem
561 *
562 * Find a menu item. Return a pointer on the item, and modifies *hmenu
563 * in case the item was in a sub-menu.
564 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000565static MENUITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000566{
567 POPUPMENU *menu;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000568 UINT i;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000569
Gerard Patel3e629742000-01-17 22:22:16 +0000570 if (((*hmenu)==0xffff) || (!(menu = MENU_GetMenu(*hmenu)))) return NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000571 if (wFlags & MF_BYPOSITION)
572 {
573 if (*nPos >= menu->nItems) return NULL;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000574 return &menu->items[*nPos];
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000575 }
576 else
577 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000578 MENUITEM *item = menu->items;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000579 for (i = 0; i < menu->nItems; i++, item++)
580 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000581 if (item->wID == *nPos)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000582 {
583 *nPos = i;
584 return item;
585 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000586 else if (item->fType & MF_POPUP)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000587 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000588 HMENU hsubmenu = item->hSubMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000589 MENUITEM *subitem = MENU_FindItem( &hsubmenu, nPos, wFlags );
590 if (subitem)
591 {
592 *hmenu = hsubmenu;
593 return subitem;
594 }
595 }
596 }
597 }
598 return NULL;
599}
600
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000601/***********************************************************************
Rein Klazes80c924f1999-12-12 19:40:46 +0000602 * MENU_FindSubMenu
603 *
604 * Find a Sub menu. Return the position of the submenu, and modifies
605 * *hmenu in case it is found in another sub-menu.
606 * If the submenu cannot be found, NO_SELECTED_ITEM is returned.
607 */
608UINT MENU_FindSubMenu( HMENU *hmenu, HMENU hSubTarget )
609{
610 POPUPMENU *menu;
611 UINT i;
612 MENUITEM *item;
613 if (((*hmenu)==0xffff) ||
Gerard Patel3e629742000-01-17 22:22:16 +0000614 (!(menu = MENU_GetMenu(*hmenu))))
Rein Klazes80c924f1999-12-12 19:40:46 +0000615 return NO_SELECTED_ITEM;
616 item = menu->items;
617 for (i = 0; i < menu->nItems; i++, item++) {
618 if(!(item->fType & MF_POPUP)) continue;
619 if (item->hSubMenu == hSubTarget) {
620 return i;
621 }
622 else {
623 HMENU hsubmenu = item->hSubMenu;
624 UINT pos = MENU_FindSubMenu( &hsubmenu, hSubTarget );
625 if (pos != NO_SELECTED_ITEM) {
626 *hmenu = hsubmenu;
627 return pos;
628 }
629 }
630 }
631 return NO_SELECTED_ITEM;
632}
633
634/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000635 * MENU_FreeItemData
636 */
637static void MENU_FreeItemData( MENUITEM* item )
638{
639 /* delete text */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000640 if (IS_STRING_ITEM(item->fType) && item->text)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000641 HeapFree( SystemHeap, 0, item->text );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000642}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000643
644/***********************************************************************
645 * MENU_FindItemByCoords
646 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000647 * Find the item at the specified coordinates (screen coords). Does
648 * not work for child windows and therefore should not be called for
649 * an arbitrary system menu.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000650 */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000651static MENUITEM *MENU_FindItemByCoords( POPUPMENU *menu,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000652 POINT pt, UINT *pos )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000653{
654 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000655 UINT i;
Marcus Meissnerac593bb1999-03-17 15:18:28 +0000656 RECT wrect;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000657
Marcus Meissnerac593bb1999-03-17 15:18:28 +0000658 if (!GetWindowRect(menu->hWnd,&wrect)) return NULL;
659 pt.x -= wrect.left;pt.y -= wrect.top;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000660 item = menu->items;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000661 for (i = 0; i < menu->nItems; i++, item++)
662 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000663 if ((pt.x >= item->rect.left) && (pt.x < item->rect.right) &&
664 (pt.y >= item->rect.top) && (pt.y < item->rect.bottom))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000665 {
666 if (pos) *pos = i;
667 return item;
668 }
669 }
670 return NULL;
671}
672
673
674/***********************************************************************
675 * MENU_FindItemByKey
676 *
677 * Find the menu item selected by a key press.
678 * Return item id, -1 if none, -2 if we should close the menu.
679 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000680static UINT MENU_FindItemByKey( HWND hwndOwner, HMENU hmenu,
681 UINT key, BOOL forceMenuChar )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000682{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000683 TRACE("\tlooking for '%c' in [%04x]\n", (char)key, (UINT16)hmenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000684
Alexandre Julliarda3960291999-02-26 11:11:13 +0000685 if (!IsMenu( hmenu ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000686 {
687 WND* w = WIN_FindWndPtr(hwndOwner);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000688 hmenu = GetSubMenu(w->hSysMenu, 0);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000689 WIN_ReleaseWndPtr(w);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000690 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000691
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000692 if (hmenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000693 {
Gerard Patel3e629742000-01-17 22:22:16 +0000694 POPUPMENU *menu = MENU_GetMenu( hmenu );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000695 MENUITEM *item = menu->items;
696 LONG menuchar;
697
698 if( !forceMenuChar )
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000699 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000700 UINT i;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000701
702 key = toupper(key);
703 for (i = 0; i < menu->nItems; i++, item++)
704 {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000705 if (item->text && (IS_STRING_ITEM(item->fType)))
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000706 {
Norman Stevensa83d0651998-10-12 07:25:35 +0000707 char *p = item->text - 2;
708 do
709 {
710 p = strchr (p + 2, '&');
711 }
712 while (p != NULL && p [1] == '&');
713 if (p && (toupper(p[1]) == key)) return i;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000714 }
715 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000716 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000717 menuchar = SendMessageA( hwndOwner, WM_MENUCHAR,
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000718 MAKEWPARAM( key, menu->wFlags ), hmenu );
719 if (HIWORD(menuchar) == 2) return LOWORD(menuchar);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000720 if (HIWORD(menuchar) == 1) return (UINT)(-2);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000721 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000722 return (UINT)(-1);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000723}
Francois Boisvert8b391741999-02-09 14:09:55 +0000724/***********************************************************************
725 * MENU_LoadMagicItem
726 *
727 * Load the bitmap associated with the magic menu item and its style
728 */
Alexandre Julliarddba420a1994-02-02 06:48:31 +0000729
Juergen Schmied78513941999-04-18 14:40:32 +0000730static HBITMAP MENU_LoadMagicItem(UINT id, BOOL hilite, DWORD dwItemData)
Francois Boisvert8b391741999-02-09 14:09:55 +0000731{
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +0000732 /*
733 * Magic menu item id's section
734 * These magic id's are used by windows to insert "standard" mdi
735 * buttons (minimize,restore,close) on menu. Under windows,
736 * these magic id's make sure the right things appear when those
737 * bitmap buttons are pressed/selected/released.
738 */
Francois Boisvert8b391741999-02-09 14:09:55 +0000739
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +0000740 switch(id & 0xffff)
Juergen Schmied78513941999-04-18 14:40:32 +0000741 { case HBMMENU_SYSTEM:
742 return (dwItemData) ?
743 (HBITMAP)dwItemData :
744 (hilite ? hBmpMinimizeD : hBmpMinimize);
745 case HBMMENU_MBAR_RESTORE:
746 return (hilite ? hBmpMaximizeD: hBmpMaximize);
747 case HBMMENU_MBAR_MINIMIZE:
748 return (hilite ? hBmpMinimizeD : hBmpMinimize);
749 case HBMMENU_MBAR_CLOSE:
750 return (hilite ? hBmpCloseD : hBmpClose);
751 case HBMMENU_CALLBACK:
752 case HBMMENU_MBAR_CLOSE_D:
753 case HBMMENU_MBAR_MINIMIZE_D:
754 case HBMMENU_POPUP_CLOSE:
755 case HBMMENU_POPUP_RESTORE:
756 case HBMMENU_POPUP_MAXIMIZE:
757 case HBMMENU_POPUP_MINIMIZE:
758 default:
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000759 FIXME("Magic 0x%08x not implemented\n", id);
Juergen Schmied78513941999-04-18 14:40:32 +0000760 return 0;
Francois Boisvert8b391741999-02-09 14:09:55 +0000761 }
762
763}
Alexandre Julliardf7207251994-07-23 07:57:48 +0000764
765/***********************************************************************
766 * MENU_CalcItemSize
767 *
768 * Calculate the size of the menu item and store it in lpitem->rect.
769 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000770static void MENU_CalcItemSize( HDC hdc, MENUITEM *lpitem, HWND hwndOwner,
771 INT orgX, INT orgY, BOOL menuBar )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000772{
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000773 char *p;
774
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000775 TRACE("dc=0x%04x owner=0x%04x (%d,%d)\n", hdc, hwndOwner, orgX, orgY);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000776 debug_print_menuitem("MENU_CalcItemSize: menuitem:", lpitem,
777 (menuBar ? " (MenuBar)" : ""));
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000778
Alexandre Julliarda3960291999-02-26 11:11:13 +0000779 SetRect( &lpitem->rect, orgX, orgY, orgX, orgY );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000780
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000781 if (lpitem->fType & MF_OWNERDRAW)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000782 {
Ken Thomases130f0d82000-05-10 21:38:37 +0000783 /*
784 ** Experimentation under Windows reveals that an owner-drawn
785 ** menu is expected to return the size of the content part of
786 ** the menu item, not including the checkmark nor the submenu
787 ** arrow. Windows adds those values itself and returns the
788 ** enlarged rectangle on subsequent WM_DRAWITEM messages.
789 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000790 MEASUREITEMSTRUCT mis;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000791 mis.CtlType = ODT_MENU;
Juergen Schmied7abca951999-04-11 17:02:30 +0000792 mis.CtlID = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000793 mis.itemID = lpitem->wID;
Juergen Schmied7abca951999-04-11 17:02:30 +0000794 mis.itemData = (DWORD)lpitem->dwItemData;
795 mis.itemHeight = 0;
796 mis.itemWidth = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000797 SendMessageA( hwndOwner, WM_MEASUREITEM, 0, (LPARAM)&mis );
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000798 lpitem->rect.right += mis.itemWidth;
Aric Stewart70cc1692000-05-10 21:54:07 +0000799
800 if (menuBar)
801 {
802 lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
803
804
805 /* under at least win95 you seem to be given a standard
806 height for the menu and the height value is ignored */
807
808 if (TWEAK_WineLook == WIN31_LOOK)
809 lpitem->rect.bottom += GetSystemMetrics(SM_CYMENU);
810 else
811 lpitem->rect.bottom += GetSystemMetrics(SM_CYMENU)-1;
812 }
813 else
814 lpitem->rect.bottom += mis.itemHeight;
815
816 TRACE("id=%04x size=%dx%d\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000817 lpitem->wID, mis.itemWidth, mis.itemHeight);
Ken Thomases130f0d82000-05-10 21:38:37 +0000818 /* Fall through to get check/arrow width calculation. */
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000819 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000820
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000821 if (lpitem->fType & MF_SEPARATOR)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000822 {
823 lpitem->rect.bottom += SEPARATOR_HEIGHT;
824 return;
825 }
826
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000827 if (!menuBar)
828 {
829 lpitem->rect.right += 2 * check_bitmap_width;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000830 if (lpitem->fType & MF_POPUP)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000831 lpitem->rect.right += arrow_bitmap_width;
832 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000833
Ken Thomases130f0d82000-05-10 21:38:37 +0000834 if (lpitem->fType & MF_OWNERDRAW)
835 return;
836
Juergen Schmied78513941999-04-18 14:40:32 +0000837 if (IS_BITMAP_ITEM(lpitem->fType))
Alexandre Julliardf7207251994-07-23 07:57:48 +0000838 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000839 BITMAP bm;
Juergen Schmied78513941999-04-18 14:40:32 +0000840 HBITMAP resBmp = 0;
Francois Boisvert8b391741999-02-09 14:09:55 +0000841
Patrik Stridvall1bb94031999-05-08 15:47:44 +0000842 /* Check if there is a magic menu item associated with this item */
Juergen Schmied78513941999-04-18 14:40:32 +0000843 if((LOWORD((int)lpitem->text))<12)
844 {
845 resBmp = MENU_LoadMagicItem((int)lpitem->text, (lpitem->fType & MF_HILITE),
846 lpitem->dwItemData);
Francois Boisvert8b391741999-02-09 14:09:55 +0000847 }
848 else
Alexandre Julliarda3960291999-02-26 11:11:13 +0000849 resBmp = (HBITMAP)lpitem->text;
Francois Boisvert8b391741999-02-09 14:09:55 +0000850
Alexandre Julliarda3960291999-02-26 11:11:13 +0000851 if (GetObjectA(resBmp, sizeof(bm), &bm ))
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000852 {
853 lpitem->rect.right += bm.bmWidth;
854 lpitem->rect.bottom += bm.bmHeight;
Francois Boisvert8b391741999-02-09 14:09:55 +0000855
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000856 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000857 }
858
Juergen Schmied78513941999-04-18 14:40:32 +0000859
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000860 /* If we get here, then it must be a text item */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000861 if (IS_STRING_ITEM( lpitem->fType ))
Juergen Schmied78513941999-04-18 14:40:32 +0000862 { SIZE size;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000863
Juergen Schmied78513941999-04-18 14:40:32 +0000864 GetTextExtentPoint32A(hdc, lpitem->text, strlen(lpitem->text), &size);
865
866 lpitem->rect.right += size.cx;
867 if (TWEAK_WineLook == WIN31_LOOK)
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000868 lpitem->rect.bottom += max( size.cy, GetSystemMetrics(SM_CYMENU) );
Juergen Schmied78513941999-04-18 14:40:32 +0000869 else
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000870 lpitem->rect.bottom += max(size.cy, GetSystemMetrics(SM_CYMENU)-1);
Juergen Schmied78513941999-04-18 14:40:32 +0000871 lpitem->xTab = 0;
872
873 if (menuBar)
874 {
875 lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
876 }
877 else if ((p = strchr( lpitem->text, '\t' )) != NULL)
878 {
879 /* Item contains a tab (only meaningful in popup menus) */
880 GetTextExtentPoint32A(hdc, lpitem->text, (int)(p - lpitem->text) , &size);
881 lpitem->xTab = check_bitmap_width + MENU_TAB_SPACE + size.cx;
882 lpitem->rect.right += MENU_TAB_SPACE;
883 }
884 else
885 {
886 if (strchr( lpitem->text, '\b' ))
887 lpitem->rect.right += MENU_TAB_SPACE;
888 lpitem->xTab = lpitem->rect.right - check_bitmap_width
889 - arrow_bitmap_width;
890 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000891 }
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000892 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 +0000893}
894
895
896/***********************************************************************
897 * MENU_PopupMenuCalcSize
898 *
899 * Calculate the size of a popup menu.
900 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000901static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND hwndOwner )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000902{
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000903 MENUITEM *lpitem;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000904 HDC hdc;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000905 int start, i;
906 int orgX, orgY, maxX, maxTab, maxTabWidth;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000907
Alexandre Julliardf7207251994-07-23 07:57:48 +0000908 lppop->Width = lppop->Height = 0;
909 if (lppop->nItems == 0) return;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000910 hdc = GetDC( 0 );
Juergen Schmied78513941999-04-18 14:40:32 +0000911
912 SelectObject( hdc, hMenuFont);
913
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000914 start = 0;
Marcus Meissnerddca3151999-05-22 11:33:23 +0000915 maxX = (TWEAK_WineLook == WIN31_LOOK) ? GetSystemMetrics(SM_CXBORDER) : 2 ;
Juergen Schmied466a6521999-05-02 11:21:08 +0000916
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000917 while (start < lppop->nItems)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000918 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000919 lpitem = &lppop->items[start];
Alexandre Julliardf7207251994-07-23 07:57:48 +0000920 orgX = maxX;
Marcus Meissnerddca3151999-05-22 11:33:23 +0000921 orgY = (TWEAK_WineLook == WIN31_LOOK) ? GetSystemMetrics(SM_CYBORDER) : 2;
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +0000922
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000923 maxTab = maxTabWidth = 0;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000924
925 /* Parse items until column break or end of menu */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000926 for (i = start; i < lppop->nItems; i++, lpitem++)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000927 {
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000928 if ((i != start) &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000929 (lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000930
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000931 MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, FALSE );
Pascal Lessard47274231999-02-13 12:21:46 +0000932
Juergen Schmied466a6521999-05-02 11:21:08 +0000933 if (lpitem->fType & MF_MENUBARBREAK) orgX++;
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000934 maxX = max( maxX, lpitem->rect.right );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000935 orgY = lpitem->rect.bottom;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000936 if (IS_STRING_ITEM(lpitem->fType) && lpitem->xTab)
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000937 {
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000938 maxTab = max( maxTab, lpitem->xTab );
939 maxTabWidth = max(maxTabWidth,lpitem->rect.right-lpitem->xTab);
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000940 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000941 }
942
943 /* Finish the column (set all items to the largest width found) */
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000944 maxX = max( maxX, maxTab + maxTabWidth );
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000945 for (lpitem = &lppop->items[start]; start < i; start++, lpitem++)
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000946 {
947 lpitem->rect.right = maxX;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000948 if (IS_STRING_ITEM(lpitem->fType) && lpitem->xTab)
Juergen Schmied466a6521999-05-02 11:21:08 +0000949 lpitem->xTab = maxTab;
950
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000951 }
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000952 lppop->Height = max( lppop->Height, orgY );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000953 }
954
955 lppop->Width = maxX;
Juergen Schmied466a6521999-05-02 11:21:08 +0000956
957 /* space for 3d border */
958 if(TWEAK_WineLook > WIN31_LOOK)
959 {
960 lppop->Height += 2;
961 lppop->Width += 2;
962 }
963
Alexandre Julliarda3960291999-02-26 11:11:13 +0000964 ReleaseDC( 0, hdc );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000965}
966
967
968/***********************************************************************
969 * MENU_MenuBarCalcSize
970 *
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000971 * FIXME: Word 6 implements its own MDI and its own 'close window' bitmap
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000972 * height is off by 1 pixel which causes lengthy window relocations when
973 * active document window is maximized/restored.
974 *
Alexandre Julliardf7207251994-07-23 07:57:48 +0000975 * Calculate the size of the menu bar.
976 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000977static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect,
978 LPPOPUPMENU lppop, HWND hwndOwner )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000979{
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000980 MENUITEM *lpitem;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000981 int start, i, orgX, orgY, maxY, helpPos;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000982
983 if ((lprect == NULL) || (lppop == NULL)) return;
984 if (lppop->nItems == 0) return;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000985 TRACE("left=%d top=%d right=%d bottom=%d\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000986 lprect->left, lprect->top, lprect->right, lprect->bottom);
Alexandre Julliardf7207251994-07-23 07:57:48 +0000987 lppop->Width = lprect->right - lprect->left;
988 lppop->Height = 0;
989 maxY = lprect->top;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000990 start = 0;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000991 helpPos = -1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000992 while (start < lppop->nItems)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000993 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000994 lpitem = &lppop->items[start];
Alexandre Julliardf7207251994-07-23 07:57:48 +0000995 orgX = lprect->left;
996 orgY = maxY;
997
998 /* Parse items until line break or end of menu */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000999 for (i = start; i < lppop->nItems; i++, lpitem++)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001000 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001001 if ((helpPos == -1) && (lpitem->fType & MF_HELP)) helpPos = i;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001002 if ((i != start) &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001003 (lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001004
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001005 TRACE("calling MENU_CalcItemSize org=(%d, %d)\n",
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001006 orgX, orgY );
Alexandre Julliard03468f71998-02-15 19:40:49 +00001007 debug_print_menuitem (" item: ", lpitem, "");
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001008 MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, TRUE );
Pascal Lessard47274231999-02-13 12:21:46 +00001009
Alexandre Julliardf7207251994-07-23 07:57:48 +00001010 if (lpitem->rect.right > lprect->right)
1011 {
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001012 if (i != start) break;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001013 else lpitem->rect.right = lprect->right;
1014 }
Francois Gouget6d77d3a2000-03-25 21:44:35 +00001015 maxY = max( maxY, lpitem->rect.bottom );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001016 orgX = lpitem->rect.right;
1017 }
1018
1019 /* Finish the line (set all items to the largest height found) */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001020 while (start < i) lppop->items[start++].rect.bottom = maxY;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001021 }
1022
1023 lprect->bottom = maxY;
1024 lppop->Height = lprect->bottom - lprect->top;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001025
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +00001026 /* Flush right all magic items and items between the MF_HELP and */
1027 /* the last item (if several lines, only move the last line) */
1028 lpitem = &lppop->items[lppop->nItems-1];
1029 orgY = lpitem->rect.top;
1030 orgX = lprect->right;
1031 for (i = lppop->nItems - 1; i >= helpPos; i--, lpitem--)
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001032 {
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +00001033 if ( !IS_BITMAP_ITEM(lpitem->fType) && ((helpPos ==-1) ? TRUE : (helpPos>i) ))
1034 break; /* done */
1035 if (lpitem->rect.top != orgY) break; /* Other line */
1036 if (lpitem->rect.right >= orgX) break; /* Too far right already */
1037 lpitem->rect.left += orgX - lpitem->rect.right;
1038 lpitem->rect.right = orgX;
1039 orgX = lpitem->rect.left;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001040 }
Alexandre Julliardf7207251994-07-23 07:57:48 +00001041}
1042
Alexandre Julliardf7207251994-07-23 07:57:48 +00001043/***********************************************************************
1044 * MENU_DrawMenuItem
1045 *
1046 * Draw a single menu item.
1047 */
Juergen Schmied78513941999-04-18 14:40:32 +00001048static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, MENUITEM *lpitem,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001049 UINT height, BOOL menuBar, UINT odaction )
Alexandre Julliardf7207251994-07-23 07:57:48 +00001050{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001051 RECT rect;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001052
Alexandre Julliard03468f71998-02-15 19:40:49 +00001053 debug_print_menuitem("MENU_DrawMenuItem: ", lpitem, "");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001054
1055 if (lpitem->fType & MF_SYSMENU)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001056 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001057 if( !IsIconic(hwnd) ) {
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001058 if (TWEAK_WineLook > WIN31_LOOK)
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001059 NC_DrawSysButton95( hwnd, hdc,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001060 lpitem->fState &
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001061 (MF_HILITE | MF_MOUSESELECT) );
1062 else
1063 NC_DrawSysButton( hwnd, hdc,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001064 lpitem->fState &
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001065 (MF_HILITE | MF_MOUSESELECT) );
1066 }
1067
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001068 return;
1069 }
1070
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001071 if (lpitem->fType & MF_OWNERDRAW)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001072 {
Ken Thomases130f0d82000-05-10 21:38:37 +00001073 /*
1074 ** Experimentation under Windows reveals that an owner-drawn
1075 ** menu is given the rectangle which includes the space it requested
1076 ** in its response to WM_MEASUREITEM _plus_ width for a checkmark
1077 ** and a popup-menu arrow. This is the value of lpitem->rect.
1078 ** Windows will leave all drawing to the application except for
1079 ** the popup-menu arrow. Windows always draws that itself, after
1080 ** the menu owner has finished drawing.
1081 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001082 DRAWITEMSTRUCT dis;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001083
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001084 dis.CtlType = ODT_MENU;
Juergen Schmied7abca951999-04-11 17:02:30 +00001085 dis.CtlID = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001086 dis.itemID = lpitem->wID;
Juergen Schmied7abca951999-04-11 17:02:30 +00001087 dis.itemData = (DWORD)lpitem->dwItemData;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001088 dis.itemState = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001089 if (lpitem->fState & MF_CHECKED) dis.itemState |= ODS_CHECKED;
1090 if (lpitem->fState & MF_GRAYED) dis.itemState |= ODS_GRAYED;
1091 if (lpitem->fState & MF_HILITE) dis.itemState |= ODS_SELECTED;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001092 dis.itemAction = odaction; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */
Juergen Schmied78513941999-04-18 14:40:32 +00001093 dis.hwndItem = hmenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001094 dis.hDC = hdc;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001095 dis.rcItem = lpitem->rect;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001096 TRACE("Ownerdraw: owner=%04x itemID=%d, itemState=%d, itemAction=%d, "
Juergen Schmied78513941999-04-18 14:40:32 +00001097 "hwndItem=%04x, hdc=%04x, rcItem={%d,%d,%d,%d}\n", hwndOwner,
1098 dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
1099 dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right,
1100 dis.rcItem.bottom);
1101 SendMessageA( hwndOwner, WM_DRAWITEM, 0, (LPARAM)&dis );
Ken Thomases130f0d82000-05-10 21:38:37 +00001102 /* Fall through to draw popup-menu arrow */
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001103 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001104
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001105 TRACE("rect={%d,%d,%d,%d}\n", lpitem->rect.left, lpitem->rect.top,
Juergen Schmied78513941999-04-18 14:40:32 +00001106 lpitem->rect.right,lpitem->rect.bottom);
1107
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001108 if (menuBar && (lpitem->fType & MF_SEPARATOR)) return;
Juergen Schmied78513941999-04-18 14:40:32 +00001109
Alexandre Julliardf7207251994-07-23 07:57:48 +00001110 rect = lpitem->rect;
1111
Ken Thomases130f0d82000-05-10 21:38:37 +00001112 if (!(lpitem->fType & MF_OWNERDRAW))
1113 {
1114 if ((lpitem->fState & MF_HILITE) && !(IS_BITMAP_ITEM(lpitem->fType)))
1115 if ((menuBar) && (TWEAK_WineLook==WIN98_LOOK))
1116 DrawEdge(hdc, &rect, BDR_SUNKENOUTER, BF_RECT);
1117 else
1118 FillRect( hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT) );
1119 else
1120 FillRect( hdc, &rect, GetSysColorBrush(COLOR_MENU) );
1121 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001122
Alexandre Julliarda3960291999-02-26 11:11:13 +00001123 SetBkMode( hdc, TRANSPARENT );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001124
Ken Thomases130f0d82000-05-10 21:38:37 +00001125 if (!(lpitem->fType & MF_OWNERDRAW))
Alexandre Julliardf7207251994-07-23 07:57:48 +00001126 {
Ken Thomases130f0d82000-05-10 21:38:37 +00001127 /* vertical separator */
1128 if (!menuBar && (lpitem->fType & MF_MENUBARBREAK))
1129 {
1130 if (TWEAK_WineLook > WIN31_LOOK)
1131 {
1132 RECT rc = rect;
1133 rc.top = 3;
1134 rc.bottom = height - 3;
1135 DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT);
1136 }
1137 else
1138 {
1139 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1140 MoveTo16( hdc, rect.left, 0 );
1141 LineTo( hdc, rect.left, height );
1142 }
1143 }
Juergen Schmied78513941999-04-18 14:40:32 +00001144
Ken Thomases130f0d82000-05-10 21:38:37 +00001145 /* horizontal separator */
1146 if (lpitem->fType & MF_SEPARATOR)
1147 {
1148 if (TWEAK_WineLook > WIN31_LOOK)
1149 {
1150 RECT rc = rect;
1151 rc.left++;
1152 rc.right--;
1153 rc.top += SEPARATOR_HEIGHT / 2;
1154 DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP);
1155 }
1156 else
1157 {
1158 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1159 MoveTo16( hdc, rect.left, rect.top + SEPARATOR_HEIGHT/2 );
1160 LineTo( hdc, rect.right, rect.top + SEPARATOR_HEIGHT/2 );
1161 }
1162 return;
1163 }
Alexandre Julliardf7207251994-07-23 07:57:48 +00001164 }
1165
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001166 /* Setup colors */
1167
Juergen Schmied78513941999-04-18 14:40:32 +00001168 if ((lpitem->fState & MF_HILITE) && !(IS_BITMAP_ITEM(lpitem->fType)) )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001169 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001170 if (lpitem->fState & MF_GRAYED)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001171 SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001172 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001173 SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
1174 SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001175 }
1176 else
1177 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001178 if (lpitem->fState & MF_GRAYED)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001179 SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001180 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001181 SetTextColor( hdc, GetSysColor( COLOR_MENUTEXT ) );
1182 SetBkColor( hdc, GetSysColor( COLOR_MENU ) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001183 }
1184
Juergen Schmied78513941999-04-18 14:40:32 +00001185 /* helper lines for debugging */
1186/* FrameRect(hdc, &rect, GetStockObject(BLACK_BRUSH));
1187 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1188 MoveTo16( hdc, rect.left, (rect.top + rect.bottom)/2 );
1189 LineTo( hdc, rect.right, (rect.top + rect.bottom)/2 );
1190*/
1191
Alexandre Julliardf7207251994-07-23 07:57:48 +00001192 if (!menuBar)
1193 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001194 INT y = rect.top + rect.bottom;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001195
Ken Thomases130f0d82000-05-10 21:38:37 +00001196 if (!(lpitem->fType & MF_OWNERDRAW))
1197 {
1198 /* Draw the check mark
1199 *
1200 * FIXME:
1201 * Custom checkmark bitmaps are monochrome but not always 1bpp.
1202 */
Alexandre Julliardf7207251994-07-23 07:57:48 +00001203
Ken Thomases130f0d82000-05-10 21:38:37 +00001204 if (lpitem->fState & MF_CHECKED)
1205 {
1206 HBITMAP bm = lpitem->hCheckBit ? lpitem->hCheckBit :
1207 ((lpitem->fType & MFT_RADIOCHECK) ? hStdRadioCheck : hStdCheck);
1208 HDC hdcMem = CreateCompatibleDC( hdc );
Huw D M Davies2d617be1998-12-08 09:14:09 +00001209
Ken Thomases130f0d82000-05-10 21:38:37 +00001210 SelectObject( hdcMem, bm );
1211 BitBlt( hdc, rect.left, (y - check_bitmap_height) / 2,
1212 check_bitmap_width, check_bitmap_height,
1213 hdcMem, 0, 0, SRCCOPY );
1214 DeleteDC( hdcMem );
1215 }
1216 else if (lpitem->hUnCheckBit)
1217 {
1218 HDC hdcMem = CreateCompatibleDC( hdc );
Huw D M Davies2d617be1998-12-08 09:14:09 +00001219
Ken Thomases130f0d82000-05-10 21:38:37 +00001220 SelectObject( hdcMem, lpitem->hUnCheckBit );
1221 BitBlt( hdc, rect.left, (y - check_bitmap_height) / 2,
1222 check_bitmap_width, check_bitmap_height,
1223 hdcMem, 0, 0, SRCCOPY );
1224 DeleteDC( hdcMem );
1225 }
1226 }
Juergen Schmied78513941999-04-18 14:40:32 +00001227
Alexandre Julliardf7207251994-07-23 07:57:48 +00001228 /* Draw the popup-menu arrow */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001229 if (lpitem->fType & MF_POPUP)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001230 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001231 HDC hdcMem = CreateCompatibleDC( hdc );
Ken Thomases130f0d82000-05-10 21:38:37 +00001232 HBITMAP hOrigBitmap;
Huw D M Davies2d617be1998-12-08 09:14:09 +00001233
Ken Thomases130f0d82000-05-10 21:38:37 +00001234 hOrigBitmap = SelectObject( hdcMem, hStdMnArrow );
Juergen Schmied78513941999-04-18 14:40:32 +00001235 BitBlt( hdc, rect.right - arrow_bitmap_width - 1,
Huw D M Davies2d617be1998-12-08 09:14:09 +00001236 (y - arrow_bitmap_height) / 2,
1237 arrow_bitmap_width, arrow_bitmap_height,
1238 hdcMem, 0, 0, SRCCOPY );
Ken Thomases130f0d82000-05-10 21:38:37 +00001239 SelectObject( hdcMem, hOrigBitmap );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001240 DeleteDC( hdcMem );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001241 }
1242
1243 rect.left += check_bitmap_width;
1244 rect.right -= arrow_bitmap_width;
1245 }
1246
Ken Thomases130f0d82000-05-10 21:38:37 +00001247 /* Done for owner-drawn */
1248 if (lpitem->fType & MF_OWNERDRAW)
1249 return;
1250
Juergen Schmied78513941999-04-18 14:40:32 +00001251 /* Draw the item text or bitmap */
1252 if (IS_BITMAP_ITEM(lpitem->fType))
1253 { int top;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001254
Alexandre Julliarda3960291999-02-26 11:11:13 +00001255 HBITMAP resBmp = 0;
Francois Boisvert8b391741999-02-09 14:09:55 +00001256
Alexandre Julliarda3960291999-02-26 11:11:13 +00001257 HDC hdcMem = CreateCompatibleDC( hdc );
Huw D M Davies2d617be1998-12-08 09:14:09 +00001258
Patrik Stridvall1bb94031999-05-08 15:47:44 +00001259 /*
1260 * Check if there is a magic menu item associated with this item
1261 * and load the appropriate bitmap
1262 */
Juergen Schmied78513941999-04-18 14:40:32 +00001263 if((LOWORD((int)lpitem->text)) < 12)
1264 {
1265 resBmp = MENU_LoadMagicItem((int)lpitem->text, (lpitem->fState & MF_HILITE),
1266 lpitem->dwItemData);
Francois Boisvert8b391741999-02-09 14:09:55 +00001267 }
1268 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001269 resBmp = (HBITMAP)lpitem->text;
Juergen Schmied78513941999-04-18 14:40:32 +00001270
1271 if (resBmp)
1272 {
1273 BITMAP bm;
1274 GetObjectA( resBmp, sizeof(bm), &bm );
1275
1276 SelectObject(hdcMem,resBmp );
1277
1278 /* handle fontsize > bitmap_height */
1279 top = ((rect.bottom-rect.top)>bm.bmHeight) ?
1280 rect.top+(rect.bottom-rect.top-bm.bmHeight)/2 : rect.top;
1281
1282 BitBlt( hdc, rect.left, top, rect.right - rect.left,
Huw D M Davies2d617be1998-12-08 09:14:09 +00001283 rect.bottom - rect.top, hdcMem, 0, 0, SRCCOPY );
Juergen Schmied78513941999-04-18 14:40:32 +00001284 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001285 DeleteDC( hdcMem );
Juergen Schmied78513941999-04-18 14:40:32 +00001286
Alexandre Julliardf7207251994-07-23 07:57:48 +00001287 return;
Francois Boisvert8b391741999-02-09 14:09:55 +00001288
Alexandre Julliardf7207251994-07-23 07:57:48 +00001289 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001290 /* No bitmap - process text if present */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001291 else if (IS_STRING_ITEM(lpitem->fType))
Alexandre Julliardf7207251994-07-23 07:57:48 +00001292 {
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001293 register int i;
Juergen Schmied466a6521999-05-02 11:21:08 +00001294 HFONT hfontOld = 0;
1295
Juergen Schmied78513941999-04-18 14:40:32 +00001296 UINT uFormat = (menuBar) ?
1297 DT_CENTER | DT_VCENTER | DT_SINGLELINE :
1298 DT_LEFT | DT_VCENTER | DT_SINGLELINE;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001299
Juergen Schmied466a6521999-05-02 11:21:08 +00001300 if ( lpitem->fState & MFS_DEFAULT )
1301 {
1302 hfontOld = SelectObject( hdc, hMenuFontBold);
1303 }
1304
Alexandre Julliardf7207251994-07-23 07:57:48 +00001305 if (menuBar)
1306 {
1307 rect.left += MENU_BAR_ITEMS_SPACE / 2;
1308 rect.right -= MENU_BAR_ITEMS_SPACE / 2;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001309 i = strlen( lpitem->text );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001310 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001311 else
Alexandre Julliardf7207251994-07-23 07:57:48 +00001312 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001313 for (i = 0; lpitem->text[i]; i++)
Juergen Schmied466a6521999-05-02 11:21:08 +00001314 if ((lpitem->text[i] == '\t') || (lpitem->text[i] == '\b'))
1315 break;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001316 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001317
Juergen Schmied466a6521999-05-02 11:21:08 +00001318 if( !(TWEAK_WineLook == WIN31_LOOK) && (lpitem->fState & MF_GRAYED))
Juergen Schmied78513941999-04-18 14:40:32 +00001319 {
Juergen Schmied466a6521999-05-02 11:21:08 +00001320 if (!(lpitem->fState & MF_HILITE) )
Juergen Schmied78513941999-04-18 14:40:32 +00001321 {
Juergen Schmied466a6521999-05-02 11:21:08 +00001322 ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001323 SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
Juergen Schmied78513941999-04-18 14:40:32 +00001324 DrawTextA( hdc, lpitem->text, i, &rect, uFormat );
Juergen Schmied466a6521999-05-02 11:21:08 +00001325 --rect.left; --rect.top; --rect.right; --rect.bottom;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001326 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001327 SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001328 }
Juergen Schmied466a6521999-05-02 11:21:08 +00001329
1330 DrawTextA( hdc, lpitem->text, i, &rect, uFormat);
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001331
Juergen Schmied466a6521999-05-02 11:21:08 +00001332 /* paint the shortcut text */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001333 if (lpitem->text[i]) /* There's a tab or flush-right char */
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001334 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001335 if (lpitem->text[i] == '\t')
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001336 {
1337 rect.left = lpitem->xTab;
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +00001338 uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001339 }
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +00001340 else
1341 {
1342 uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
1343 }
1344
Juergen Schmied466a6521999-05-02 11:21:08 +00001345 if( !(TWEAK_WineLook == WIN31_LOOK) && (lpitem->fState & MF_GRAYED))
1346 {
1347 if (!(lpitem->fState & MF_HILITE) )
1348 {
1349 ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
1350 SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
1351 DrawTextA( hdc, lpitem->text + i + 1, -1, &rect, uFormat );
1352 --rect.left; --rect.top; --rect.right; --rect.bottom;
1353 }
1354 SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
1355 }
Juergen Schmiedcd0ed1e1999-04-26 14:54:38 +00001356 DrawTextA( hdc, lpitem->text + i + 1, -1, &rect, uFormat );
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001357 }
Juergen Schmied466a6521999-05-02 11:21:08 +00001358
1359 if (hfontOld)
1360 SelectObject (hdc, hfontOld);
Alexandre Julliardf7207251994-07-23 07:57:48 +00001361 }
1362}
1363
1364
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001365/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001366 * MENU_DrawPopupMenu
1367 *
1368 * Paint a popup menu.
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001369 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001370static void MENU_DrawPopupMenu( HWND hwnd, HDC hdc, HMENU hmenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001371{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001372 HBRUSH hPrevBrush = 0;
1373 RECT rect;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001374
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001375 TRACE("wnd=0x%04x dc=0x%04x menu=0x%04x\n", hwnd, hdc, hmenu);
Juergen Schmied78513941999-04-18 14:40:32 +00001376
Alexandre Julliarda3960291999-02-26 11:11:13 +00001377 GetClientRect( hwnd, &rect );
Alexandre Julliard641ee761997-08-04 16:34:36 +00001378
Alex Korobka44a1b591999-04-01 12:03:52 +00001379 if(TWEAK_WineLook == WIN31_LOOK)
1380 {
Marcus Meissnerddca3151999-05-22 11:33:23 +00001381 rect.bottom -= POPUP_YSHADE * GetSystemMetrics(SM_CYBORDER);
1382 rect.right -= POPUP_XSHADE * GetSystemMetrics(SM_CXBORDER);
Alex Korobka44a1b591999-04-01 12:03:52 +00001383 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001384
Juergen Schmied78513941999-04-18 14:40:32 +00001385 if((hPrevBrush = SelectObject( hdc, GetSysColorBrush(COLOR_MENU) ))
1386 && (SelectObject( hdc, hMenuFont)))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001387 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001388 HPEN hPrevPen;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001389
Alexandre Julliarda3960291999-02-26 11:11:13 +00001390 Rectangle( hdc, rect.left, rect.top, rect.right, rect.bottom );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001391
Alexandre Julliarda3960291999-02-26 11:11:13 +00001392 hPrevPen = SelectObject( hdc, GetStockObject( NULL_PEN ) );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001393 if( hPrevPen )
1394 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001395 INT ropPrev, i;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001396 POPUPMENU *menu;
1397
1398 /* draw 3-d shade */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001399 if(TWEAK_WineLook == WIN31_LOOK) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001400 SelectObject( hdc, hShadeBrush );
1401 SetBkMode( hdc, TRANSPARENT );
1402 ropPrev = SetROP2( hdc, R2_MASKPEN );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001403
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001404 i = rect.right; /* why SetBrushOrg() doesn't? */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001405 PatBlt( hdc, i & 0xfffffffe,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001406 rect.top + POPUP_YSHADE*GetSystemMetrics(SM_CYBORDER),
1407 i%2 + POPUP_XSHADE*GetSystemMetrics(SM_CXBORDER),
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001408 rect.bottom - rect.top, 0x00a000c9 );
1409 i = rect.bottom;
Marcus Meissnerddca3151999-05-22 11:33:23 +00001410 PatBlt( hdc, rect.left + POPUP_XSHADE*GetSystemMetrics(SM_CXBORDER),
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001411 i & 0xfffffffe,rect.right - rect.left,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001412 i%2 + POPUP_YSHADE*GetSystemMetrics(SM_CYBORDER), 0x00a000c9 );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001413 SelectObject( hdc, hPrevPen );
1414 SelectObject( hdc, hPrevBrush );
1415 SetROP2( hdc, ropPrev );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001416 }
1417 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001418 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001419
1420 /* draw menu items */
1421
Gerard Patel3e629742000-01-17 22:22:16 +00001422 menu = MENU_GetMenu( hmenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001423 if (menu && menu->nItems)
1424 {
1425 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001426 UINT u;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001427
1428 for (u = menu->nItems, item = menu->items; u > 0; u--, item++)
Juergen Schmied78513941999-04-18 14:40:32 +00001429 MENU_DrawMenuItem( hwnd, hmenu, menu->hwndOwner, hdc, item,
1430 menu->Height, FALSE, ODA_DRAWENTIRE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001431
1432 }
Juergen Schmied78513941999-04-18 14:40:32 +00001433 } else
1434 {
1435 SelectObject( hdc, hPrevBrush );
1436 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001437 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001438}
1439
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001440/***********************************************************************
1441 * MENU_DrawMenuBar
1442 *
1443 * Paint a menu bar. Returns the height of the menu bar.
Juergen Schmied78513941999-04-18 14:40:32 +00001444 * called from [windows/nonclient.c]
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001445 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001446UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd,
1447 BOOL suppress_draw)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001448{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001449 LPPOPUPMENU lppop;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001450 UINT i,retvalue;
Juergen Schmied78513941999-04-18 14:40:32 +00001451 HFONT hfontOld = 0;
1452
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001453 WND *wndPtr = WIN_FindWndPtr( hwnd );
1454
Gerard Patel3e629742000-01-17 22:22:16 +00001455 lppop = MENU_GetMenu ((HMENU)wndPtr->wIDmenu );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001456 if (lppop == NULL || lprect == NULL)
1457 {
Marcus Meissnerddca3151999-05-22 11:33:23 +00001458 retvalue = GetSystemMetrics(SM_CYMENU);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001459 goto END;
1460 }
Juergen Schmied78513941999-04-18 14:40:32 +00001461
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001462 TRACE("(%04x, %p, %p)\n", hDC, lprect, lppop);
Juergen Schmied78513941999-04-18 14:40:32 +00001463
1464 hfontOld = SelectObject( hDC, hMenuFont);
1465
1466 if (lppop->Height == 0)
1467 MENU_MenuBarCalcSize(hDC, lprect, lppop, hwnd);
1468
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001469 lprect->bottom = lprect->top + lppop->Height;
Juergen Schmied78513941999-04-18 14:40:32 +00001470
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001471 if (suppress_draw)
1472 {
1473 retvalue = lppop->Height;
1474 goto END;
1475 }
Juergen Schmied78513941999-04-18 14:40:32 +00001476
Alexandre Julliarda3960291999-02-26 11:11:13 +00001477 FillRect(hDC, lprect, GetSysColorBrush(COLOR_MENU) );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001478
Juergen Schmied78513941999-04-18 14:40:32 +00001479 if (TWEAK_WineLook == WIN31_LOOK)
1480 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001481 SelectObject( hDC, GetSysColorPen(COLOR_WINDOWFRAME) );
1482 MoveTo16( hDC, lprect->left, lprect->bottom );
1483 LineTo( hDC, lprect->right, lprect->bottom );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001484 }
Juergen Schmied78513941999-04-18 14:40:32 +00001485 else
1486 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001487 SelectObject( hDC, GetSysColorPen(COLOR_3DFACE));
1488 MoveTo16( hDC, lprect->left, lprect->bottom );
1489 LineTo( hDC, lprect->right, lprect->bottom );
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001490 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001491
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001492 if (lppop->nItems == 0)
1493 {
Marcus Meissnerddca3151999-05-22 11:33:23 +00001494 retvalue = GetSystemMetrics(SM_CYMENU);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001495 goto END;
1496 }
Juergen Schmied78513941999-04-18 14:40:32 +00001497
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001498 for (i = 0; i < lppop->nItems; i++)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001499 {
Aric Stewart70cc1692000-05-10 21:54:07 +00001500 MENU_DrawMenuItem( hwnd, (HMENU)wndPtr->wIDmenu, hwnd,
Juergen Schmied78513941999-04-18 14:40:32 +00001501 hDC, &lppop->items[i], lppop->Height, TRUE, ODA_DRAWENTIRE );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001502 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001503 retvalue = lppop->Height;
Juergen Schmied78513941999-04-18 14:40:32 +00001504
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001505END:
Juergen Schmied78513941999-04-18 14:40:32 +00001506 if (hfontOld)
1507 SelectObject (hDC, hfontOld);
1508
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001509 WIN_ReleaseWndPtr(wndPtr);
1510 return retvalue;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001511}
1512
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001513/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001514 * MENU_PatchResidentPopup
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001515 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001516BOOL MENU_PatchResidentPopup( HQUEUE16 checkQueue, WND* checkWnd )
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001517{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001518 WND *pTPWnd = MENU_GetTopPopupWnd();
1519
1520 if( pTPWnd )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001521 {
1522 HTASK16 hTask = 0;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001523
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001524 TRACE("patching resident popup: %04x %04x [%04x %04x]\n",
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001525 checkQueue, checkWnd ? checkWnd->hwndSelf : 0, pTPWnd->hmemTaskQ,
1526 pTPWnd->owner ? pTPWnd->owner->hwndSelf : 0);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001527
Alexandre Julliard77b99181997-09-14 17:17:23 +00001528 switch( checkQueue )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001529 {
Alexandre Julliard77b99181997-09-14 17:17:23 +00001530 case 0: /* checkWnd is the new popup owner */
1531 if( checkWnd )
1532 {
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001533 pTPWnd->owner = checkWnd;
1534 if( pTPWnd->hmemTaskQ != checkWnd->hmemTaskQ )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001535 hTask = QUEUE_GetQueueTask( checkWnd->hmemTaskQ );
1536 }
1537 break;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001538
Alexandre Julliard77b99181997-09-14 17:17:23 +00001539 case 0xFFFF: /* checkWnd is destroyed */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001540 if( pTPWnd->owner == checkWnd )
1541 pTPWnd->owner = NULL;
1542 MENU_ReleaseTopPopupWnd();
Alexandre Julliard77b99181997-09-14 17:17:23 +00001543 return TRUE;
1544
1545 default: /* checkQueue is exiting */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001546 if( pTPWnd->hmemTaskQ == checkQueue )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001547 {
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001548 hTask = QUEUE_GetQueueTask( pTPWnd->hmemTaskQ );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001549 hTask = TASK_GetNextTask( hTask );
1550 }
1551 break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001552 }
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001553
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001554 if( hTask )
1555 {
1556 TDB* task = (TDB*)GlobalLock16( hTask );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001557 if( task )
1558 {
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001559 pTPWnd->hInstance = task->hInstance;
1560 pTPWnd->hmemTaskQ = task->hQueue;
1561 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001562 return TRUE;
1563 }
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001564 else WARN("failed to patch resident popup.\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001565 }
1566 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001567 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001568 return FALSE;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001569}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001570
1571/***********************************************************************
1572 * MENU_ShowPopup
1573 *
1574 * Display a popup menu.
1575 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001576static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id,
1577 INT x, INT y, INT xanchor, INT yanchor )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001578{
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001579 POPUPMENU *menu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001580 WND *wndOwner = NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001581
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001582 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 +00001583 hwndOwner, hmenu, id, x, y, xanchor, yanchor);
1584
Gerard Patel3e629742000-01-17 22:22:16 +00001585 if (!(menu = MENU_GetMenu( hmenu ))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001586 if (menu->FocusedItem != NO_SELECTED_ITEM)
1587 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001588 menu->items[menu->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001589 menu->FocusedItem = NO_SELECTED_ITEM;
1590 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001591
Juergen Schmied78513941999-04-18 14:40:32 +00001592 /* store the owner for DrawItem*/
1593 menu->hwndOwner = hwndOwner;
1594
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001595 if( (wndOwner = WIN_FindWndPtr( hwndOwner )) )
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001596 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001597 UINT width, height;
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001598
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001599 MENU_PopupMenuCalcSize( menu, hwndOwner );
1600
1601 /* adjust popup menu pos so that it fits within the desktop */
1602
Marcus Meissnerddca3151999-05-22 11:33:23 +00001603 width = menu->Width + GetSystemMetrics(SM_CXBORDER);
1604 height = menu->Height + GetSystemMetrics(SM_CYBORDER);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001605
Marcus Meissnerddca3151999-05-22 11:33:23 +00001606 if( x + width > GetSystemMetrics(SM_CXSCREEN ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001607 {
1608 if( xanchor )
1609 x -= width - xanchor;
Marcus Meissnerddca3151999-05-22 11:33:23 +00001610 if( x + width > GetSystemMetrics(SM_CXSCREEN))
1611 x = GetSystemMetrics(SM_CXSCREEN) - width;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001612 }
1613 if( x < 0 ) x = 0;
1614
Marcus Meissnerddca3151999-05-22 11:33:23 +00001615 if( y + height > GetSystemMetrics(SM_CYSCREEN ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001616 {
1617 if( yanchor )
1618 y -= height + yanchor;
Marcus Meissnerddca3151999-05-22 11:33:23 +00001619 if( y + height > GetSystemMetrics(SM_CYSCREEN ))
1620 y = GetSystemMetrics(SM_CYSCREEN) - height;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001621 }
1622 if( y < 0 ) y = 0;
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001623
Alex Korobka44a1b591999-04-01 12:03:52 +00001624 if( TWEAK_WineLook == WIN31_LOOK )
1625 {
Marcus Meissnerddca3151999-05-22 11:33:23 +00001626 width += POPUP_XSHADE * GetSystemMetrics(SM_CXBORDER); /* add space for shading */
1627 height += POPUP_YSHADE * GetSystemMetrics(SM_CYBORDER);
Alex Korobka44a1b591999-04-01 12:03:52 +00001628 }
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001629
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001630 /* NOTE: In Windows, top menu popup is not owned. */
1631 if (!pTopPopupWnd) /* create top level popup menu window */
1632 {
1633 assert( uSubPWndLevel == 0 );
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001634
Alexandre Julliarda3960291999-02-26 11:11:13 +00001635 pTopPopupWnd = WIN_FindWndPtr(CreateWindowA( POPUPMENU_CLASS_ATOM, NULL,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001636 WS_POPUP, x, y, width, height,
1637 hwndOwner, 0, wndOwner->hInstance,
1638 (LPVOID)hmenu ));
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001639 if (!pTopPopupWnd)
1640 {
1641 WIN_ReleaseWndPtr(wndOwner);
1642 return FALSE;
1643 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001644 menu->hWnd = pTopPopupWnd->hwndSelf;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001645 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001646 }
1647 else
1648 if( uSubPWndLevel )
1649 {
1650 /* create a new window for the submenu */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001651
Alexandre Julliarda3960291999-02-26 11:11:13 +00001652 menu->hWnd = CreateWindowA( POPUPMENU_CLASS_ATOM, NULL,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001653 WS_POPUP, x, y, width, height,
Juergen Schmied78513941999-04-18 14:40:32 +00001654 hwndOwner, 0, wndOwner->hInstance,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001655 (LPVOID)hmenu );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001656 if( !menu->hWnd )
1657 {
1658 WIN_ReleaseWndPtr(wndOwner);
1659 return FALSE;
1660 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001661 }
1662 else /* top level popup menu window already exists */
1663 {
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001664 WND *pTPWnd = MENU_GetTopPopupWnd();
1665 menu->hWnd = pTPWnd->hwndSelf;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001666
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001667 MENU_PatchResidentPopup( 0, wndOwner );
Juergen Schmied78513941999-04-18 14:40:32 +00001668 SendMessageA( pTPWnd->hwndSelf, MM_SETMENUHANDLE, (WPARAM16)hmenu, 0L);
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001669
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001670 /* adjust its size */
1671
Alexandre Julliarda3960291999-02-26 11:11:13 +00001672 SetWindowPos( menu->hWnd, 0, x, y, width, height,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001673 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001674 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001675 }
1676
1677 uSubPWndLevel++; /* menu level counter */
1678
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001679 /* Display the window */
1680
Alexandre Julliarda3960291999-02-26 11:11:13 +00001681 SetWindowPos( menu->hWnd, HWND_TOP, 0, 0, 0, 0,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001682 SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001683 UpdateWindow( menu->hWnd );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001684 WIN_ReleaseWndPtr(wndOwner);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001685 return TRUE;
1686 }
1687 return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001688}
1689
1690
1691/***********************************************************************
1692 * MENU_SelectItem
1693 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001694static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, UINT wIndex,
Rein Klazes80c924f1999-12-12 19:40:46 +00001695 BOOL sendMenuSelect, HMENU topmenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001696{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001697 LPPOPUPMENU lppop;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001698 HDC hdc;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001699
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001700 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 +00001701
Gerard Patel3e629742000-01-17 22:22:16 +00001702 lppop = MENU_GetMenu( hmenu );
1703 if ((!lppop) || (!lppop->nItems)) return;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001704
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001705 if (lppop->FocusedItem == wIndex) return;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001706 if (lppop->wFlags & MF_POPUP) hdc = GetDC( lppop->hWnd );
1707 else hdc = GetDCEx( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW);
Alexandre Julliardf7207251994-07-23 07:57:48 +00001708
Juergen Schmied78513941999-04-18 14:40:32 +00001709 SelectObject( hdc, hMenuFont);
1710
Alexandre Julliardf7207251994-07-23 07:57:48 +00001711 /* Clear previous highlighted item */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001712 if (lppop->FocusedItem != NO_SELECTED_ITEM)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001713 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001714 lppop->items[lppop->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
Juergen Schmied78513941999-04-18 14:40:32 +00001715 MENU_DrawMenuItem(lppop->hWnd, hmenu, hwndOwner, hdc,&lppop->items[lppop->FocusedItem],
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001716 lppop->Height, !(lppop->wFlags & MF_POPUP),
1717 ODA_SELECT );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001718 }
1719
1720 /* Highlight new item (if any) */
1721 lppop->FocusedItem = wIndex;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001722 if (lppop->FocusedItem != NO_SELECTED_ITEM)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001723 {
Rein Klazes80c924f1999-12-12 19:40:46 +00001724 if(!(lppop->items[wIndex].fType & MF_SEPARATOR)) {
1725 lppop->items[wIndex].fState |= MF_HILITE;
1726 MENU_DrawMenuItem( lppop->hWnd, hmenu, hwndOwner, hdc,
1727 &lppop->items[wIndex], lppop->Height,
1728 !(lppop->wFlags & MF_POPUP), ODA_SELECT );
1729 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001730 if (sendMenuSelect)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001731 {
1732 MENUITEM *ip = &lppop->items[lppop->FocusedItem];
Juergen Schmied78513941999-04-18 14:40:32 +00001733 SendMessageA( hwndOwner, WM_MENUSELECT,
Rein Klazes80c924f1999-12-12 19:40:46 +00001734 MAKELONG(ip->fType & MF_POPUP ? wIndex: ip->wID,
1735 ip->fType | ip->fState | MF_MOUSESELECT |
1736 (lppop->wFlags & MF_SYSMENU)), hmenu);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001737 }
Alexandre Julliardf7207251994-07-23 07:57:48 +00001738 }
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001739 else if (sendMenuSelect) {
Rein Klazes80c924f1999-12-12 19:40:46 +00001740 if(topmenu){
1741 int pos;
1742 if((pos=MENU_FindSubMenu(&topmenu, hmenu))!=NO_SELECTED_ITEM){
1743 POPUPMENU *ptm = (POPUPMENU *) USER_HEAP_LIN_ADDR( topmenu );
1744 MENUITEM *ip = &ptm->items[pos];
1745 SendMessageA( hwndOwner, WM_MENUSELECT, MAKELONG(pos,
1746 ip->fType | ip->fState | MF_MOUSESELECT |
1747 (ptm->wFlags & MF_SYSMENU)), topmenu);
1748 }
1749 }
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001750 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001751 ReleaseDC( lppop->hWnd, hdc );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001752}
1753
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001754
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001755/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001756 * MENU_MoveSelection
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001757 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001758 * Moves currently selected item according to the offset parameter.
1759 * If there is no selection then it should select the last item if
1760 * offset is ITEM_PREV or the first item if offset is ITEM_NEXT.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001761 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001762static void MENU_MoveSelection( HWND hwndOwner, HMENU hmenu, INT offset )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001763{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001764 INT i;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001765 POPUPMENU *menu;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001766
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001767 TRACE("hwnd=0x%04x hmenu=0x%04x off=0x%04x\n", hwndOwner, hmenu, offset);
Juergen Schmied466a6521999-05-02 11:21:08 +00001768
Gerard Patel3e629742000-01-17 22:22:16 +00001769 menu = MENU_GetMenu( hmenu );
1770 if ((!menu) || (!menu->items)) return;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001771
1772 if ( menu->FocusedItem != NO_SELECTED_ITEM )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001773 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001774 if( menu->nItems == 1 ) return; else
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001775 for (i = menu->FocusedItem + offset ; i >= 0 && i < menu->nItems
1776 ; i += offset)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001777 if (!(menu->items[i].fType & MF_SEPARATOR))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001778 {
Rein Klazes80c924f1999-12-12 19:40:46 +00001779 MENU_SelectItem( hwndOwner, hmenu, i, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001780 return;
1781 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001782 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001783
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001784 for ( i = (offset > 0) ? 0 : menu->nItems - 1;
1785 i >= 0 && i < menu->nItems ; i += offset)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001786 if (!(menu->items[i].fType & MF_SEPARATOR))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001787 {
Rein Klazes80c924f1999-12-12 19:40:46 +00001788 MENU_SelectItem( hwndOwner, hmenu, i, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001789 return;
1790 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001791}
1792
1793
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001794/**********************************************************************
1795 * MENU_SetItemData
1796 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001797 * Set an item flags, id and text ptr. Called by InsertMenu() and
1798 * ModifyMenu().
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001799 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001800static BOOL MENU_SetItemData( MENUITEM *item, UINT flags, UINT id,
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001801 LPCSTR str )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001802{
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001803 LPSTR prevText = IS_STRING_ITEM(item->fType) ? item->text : NULL;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001804
Alexandre Julliard03468f71998-02-15 19:40:49 +00001805 debug_print_menuitem("MENU_SetItemData from: ", item, "");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001806
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001807 if (IS_STRING_ITEM(flags))
1808 {
Alexandre Julliard491502b1997-11-01 19:08:16 +00001809 if (!str || !*str)
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001810 {
1811 flags |= MF_SEPARATOR;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001812 item->text = NULL;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001813 }
1814 else
1815 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001816 LPSTR text;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001817 /* Item beginning with a backspace is a help item */
1818 if (*str == '\b')
1819 {
1820 flags |= MF_HELP;
1821 str++;
1822 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001823 if (!(text = HEAP_strdupA( SystemHeap, 0, str ))) return FALSE;
1824 item->text = text;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001825 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001826 }
Juergen Schmied78513941999-04-18 14:40:32 +00001827 else if (IS_BITMAP_ITEM(flags))
1828 item->text = (LPSTR)(HBITMAP)LOWORD(str);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001829 else item->text = NULL;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001830
Alexandre Julliarda845b881998-06-01 10:44:35 +00001831 if (flags & MF_OWNERDRAW)
1832 item->dwItemData = (DWORD)str;
1833 else
1834 item->dwItemData = 0;
1835
Alexandre Julliard02e90081998-01-04 17:49:09 +00001836 if ((item->fType & MF_POPUP) && (flags & MF_POPUP) && (item->hSubMenu != id) )
Alexandre Julliarda3960291999-02-26 11:11:13 +00001837 DestroyMenu( item->hSubMenu ); /* ModifyMenu() spec */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001838
1839 if (flags & MF_POPUP)
1840 {
Gerard Patel3e629742000-01-17 22:22:16 +00001841 POPUPMENU *menu = MENU_GetMenu((UINT16)id);
1842 if (menu) menu->wFlags |= MF_POPUP;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001843 else
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001844 {
1845 item->wID = 0;
1846 item->hSubMenu = 0;
1847 item->fType = 0;
1848 item->fState = 0;
1849 return FALSE;
1850 }
Alexandre Julliard02e90081998-01-04 17:49:09 +00001851 }
1852
1853 item->wID = id;
1854 if (flags & MF_POPUP)
1855 item->hSubMenu = id;
1856
1857 if ((item->fType & MF_POPUP) && !(flags & MF_POPUP) )
1858 flags |= MF_POPUP; /* keep popup */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001859
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001860 item->fType = flags & TYPE_MASK;
1861 item->fState = (flags & STATE_MASK) &
1862 ~(MF_HILITE | MF_MOUSESELECT | MF_BYPOSITION);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001863
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001864
1865 /* Don't call SetRectEmpty here! */
1866
1867
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001868 if (prevText) HeapFree( SystemHeap, 0, prevText );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001869
Alexandre Julliard03468f71998-02-15 19:40:49 +00001870 debug_print_menuitem("MENU_SetItemData to : ", item, "");
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001871 return TRUE;
1872}
1873
1874
1875/**********************************************************************
1876 * MENU_InsertItem
1877 *
1878 * Insert a new item into a menu.
1879 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001880static MENUITEM *MENU_InsertItem( HMENU hMenu, UINT pos, UINT flags )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001881{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001882 MENUITEM *newItems;
1883 POPUPMENU *menu;
1884
Gerard Patel3e629742000-01-17 22:22:16 +00001885 if (!(menu = MENU_GetMenu(hMenu)))
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001886 return NULL;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001887
1888 /* Find where to insert new item */
1889
Gerard Patelc6369b02000-05-14 22:52:52 +00001890 if (flags & MF_BYPOSITION) {
1891 if (pos > menu->nItems)
1892 pos = menu->nItems;
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00001893 } else {
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001894 if (!MENU_FindItem( &hMenu, &pos, flags ))
Gerard Patelc6369b02000-05-14 22:52:52 +00001895 pos = menu->nItems;
1896 else {
1897 if (!(menu = MENU_GetMenu( hMenu )))
1898 return NULL;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001899 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001900 }
1901
1902 /* Create new items array */
1903
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001904 newItems = HeapAlloc( SystemHeap, 0, sizeof(MENUITEM) * (menu->nItems+1) );
1905 if (!newItems)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001906 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001907 WARN("allocation failed\n" );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001908 return NULL;
1909 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001910 if (menu->nItems > 0)
1911 {
1912 /* Copy the old array into the new */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001913 if (pos > 0) memcpy( newItems, menu->items, pos * sizeof(MENUITEM) );
1914 if (pos < menu->nItems) memcpy( &newItems[pos+1], &menu->items[pos],
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001915 (menu->nItems-pos)*sizeof(MENUITEM) );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001916 HeapFree( SystemHeap, 0, menu->items );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001917 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001918 menu->items = newItems;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001919 menu->nItems++;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001920 memset( &newItems[pos], 0, sizeof(*newItems) );
Gerard Patel6df06941999-09-28 13:05:54 +00001921 menu->Height = 0; /* force size recalculate */
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001922 return &newItems[pos];
1923}
1924
1925
1926/**********************************************************************
1927 * MENU_ParseResource
1928 *
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001929 * Parse a standard menu resource and add items to the menu.
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001930 * Return a pointer to the end of the resource.
1931 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001932static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001933{
1934 WORD flags, id = 0;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001935 LPCSTR str;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001936
1937 do
1938 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001939 flags = GET_WORD(res);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001940 res += sizeof(WORD);
1941 if (!(flags & MF_POPUP))
1942 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001943 id = GET_WORD(res);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001944 res += sizeof(WORD);
1945 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001946 if (!IS_STRING_ITEM(flags))
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00001947 ERR("not a string item %04x\n", flags );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001948 str = res;
1949 if (!unicode) res += strlen(str) + 1;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001950 else res += (lstrlenW((LPCWSTR)str) + 1) * sizeof(WCHAR);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001951 if (flags & MF_POPUP)
1952 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001953 HMENU hSubMenu = CreatePopupMenu();
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001954 if (!hSubMenu) return NULL;
1955 if (!(res = MENU_ParseResource( res, hSubMenu, unicode )))
1956 return NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001957 if (!unicode) AppendMenuA( hMenu, flags, (UINT)hSubMenu, str );
1958 else AppendMenuW( hMenu, flags, (UINT)hSubMenu, (LPCWSTR)str );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001959 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001960 else /* Not a popup */
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001961 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001962 if (!unicode) AppendMenuA( hMenu, flags, id, *str ? str : NULL );
1963 else AppendMenuW( hMenu, flags, id,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001964 *(LPCWSTR)str ? (LPCWSTR)str : NULL );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001965 }
1966 } while (!(flags & MF_END));
1967 return res;
1968}
1969
1970
Alexandre Julliard641ee761997-08-04 16:34:36 +00001971/**********************************************************************
1972 * MENUEX_ParseResource
1973 *
1974 * Parse an extended menu resource and add items to the menu.
1975 * Return a pointer to the end of the resource.
1976 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001977static LPCSTR MENUEX_ParseResource( LPCSTR res, HMENU hMenu)
Alexandre Julliard641ee761997-08-04 16:34:36 +00001978{
Alexandre Julliard641ee761997-08-04 16:34:36 +00001979 WORD resinfo;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001980 do {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001981 MENUITEMINFOW mii;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001982
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001983 mii.cbSize = sizeof(mii);
1984 mii.fMask = MIIM_STATE | MIIM_ID | MIIM_TYPE;
1985 mii.fType = GET_DWORD(res);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001986 res += sizeof(DWORD);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001987 mii.fState = GET_DWORD(res);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001988 res += sizeof(DWORD);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001989 mii.wID = GET_DWORD(res);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001990 res += sizeof(DWORD);
1991 resinfo = GET_WORD(res); /* FIXME: for 16-bit apps this is a byte. */
1992 res += sizeof(WORD);
1993 /* Align the text on a word boundary. */
1994 res += (~((int)res - 1)) & 1;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001995 mii.dwTypeData = (LPWSTR) res;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001996 res += (1 + lstrlenW(mii.dwTypeData)) * sizeof(WCHAR);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001997 /* Align the following fields on a dword boundary. */
1998 res += (~((int)res - 1)) & 3;
1999
2000 /* FIXME: This is inefficient and cannot be optimised away by gcc. */
2001 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002002 LPSTR newstr = HEAP_strdupWtoA(GetProcessHeap(),
2003 0, mii.dwTypeData);
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002004 TRACE("Menu item: [%08x,%08x,%04x,%04x,%s]\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002005 mii.fType, mii.fState, mii.wID, resinfo, newstr);
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002006 HeapFree( GetProcessHeap(), 0, newstr );
Alexandre Julliard641ee761997-08-04 16:34:36 +00002007 }
2008
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002009 if (resinfo & 1) { /* Pop-up? */
Marcus Meissnerde43ef41999-02-28 19:56:59 +00002010 /* DWORD helpid = GET_DWORD(res); FIXME: use this. */
Alexandre Julliard641ee761997-08-04 16:34:36 +00002011 res += sizeof(DWORD);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002012 mii.hSubMenu = CreatePopupMenu();
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002013 if (!mii.hSubMenu)
2014 return NULL;
2015 if (!(res = MENUEX_ParseResource(res, mii.hSubMenu))) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002016 DestroyMenu(mii.hSubMenu);
Alexandre Julliard641ee761997-08-04 16:34:36 +00002017 return NULL;
Alexandre Julliard641ee761997-08-04 16:34:36 +00002018 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002019 mii.fMask |= MIIM_SUBMENU;
2020 mii.fType |= MF_POPUP;
Alexandre Julliard641ee761997-08-04 16:34:36 +00002021 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002022 InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii);
Alexandre Julliard641ee761997-08-04 16:34:36 +00002023 } while (!(resinfo & MF_END));
2024 return res;
2025}
2026
2027
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002028/***********************************************************************
2029 * MENU_GetSubPopup
2030 *
2031 * Return the handle of the selected sub-popup menu (if any).
2032 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002033static HMENU MENU_GetSubPopup( HMENU hmenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002034{
2035 POPUPMENU *menu;
2036 MENUITEM *item;
2037
Gerard Patel3e629742000-01-17 22:22:16 +00002038 menu = MENU_GetMenu( hmenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002039
Gerard Patel3e629742000-01-17 22:22:16 +00002040 if ((!menu) || (menu->FocusedItem == NO_SELECTED_ITEM)) return 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002041
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002042 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002043 if ((item->fType & MF_POPUP) && (item->fState & MF_MOUSESELECT))
2044 return item->hSubMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002045 return 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002046}
2047
2048
2049/***********************************************************************
2050 * MENU_HideSubPopups
2051 *
2052 * Hide the sub-popup menus of this menu.
2053 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002054static void MENU_HideSubPopups( HWND hwndOwner, HMENU hmenu,
2055 BOOL sendMenuSelect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002056{
Gerard Patel3e629742000-01-17 22:22:16 +00002057 POPUPMENU *menu = MENU_GetMenu( hmenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002058
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002059 TRACE("owner=0x%04x hmenu=0x%04x 0x%04x\n", hwndOwner, hmenu, sendMenuSelect);
Juergen Schmied466a6521999-05-02 11:21:08 +00002060
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002061 if (menu && uSubPWndLevel)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002062 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002063 HMENU hsubmenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002064 POPUPMENU *submenu;
2065 MENUITEM *item;
2066
2067 if (menu->FocusedItem != NO_SELECTED_ITEM)
2068 {
2069 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002070 if (!(item->fType & MF_POPUP) ||
2071 !(item->fState & MF_MOUSESELECT)) return;
2072 item->fState &= ~MF_MOUSESELECT;
2073 hsubmenu = item->hSubMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002074 } else return;
2075
Gerard Patel3e629742000-01-17 22:22:16 +00002076 submenu = MENU_GetMenu( hsubmenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002077 MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00002078 MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002079
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002080 if (submenu->hWnd == MENU_GetTopPopupWnd()->hwndSelf )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002081 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002082 ShowWindow( submenu->hWnd, SW_HIDE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002083 uSubPWndLevel = 0;
2084 }
2085 else
2086 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002087 DestroyWindow( submenu->hWnd );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002088 submenu->hWnd = 0;
2089 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002090 MENU_ReleaseTopPopupWnd();
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002091 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002092}
2093
2094
2095/***********************************************************************
2096 * MENU_ShowSubPopup
2097 *
2098 * Display the sub-menu of the selected item of this menu.
2099 * Return the handle of the submenu, or hmenu if no submenu to display.
2100 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002101static HMENU MENU_ShowSubPopup( HWND hwndOwner, HMENU hmenu,
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002102 BOOL selectFirst, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002103{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002104 RECT rect;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002105 POPUPMENU *menu;
2106 MENUITEM *item;
2107 WND *wndPtr;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002108 HDC hdc;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002109
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002110 TRACE("owner=0x%04x hmenu=0x%04x 0x%04x\n", hwndOwner, hmenu, selectFirst);
Juergen Schmied466a6521999-05-02 11:21:08 +00002111
Gerard Patel3e629742000-01-17 22:22:16 +00002112 if (!(menu = MENU_GetMenu( hmenu ))) return hmenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002113
2114 if (!(wndPtr = WIN_FindWndPtr( menu->hWnd )) ||
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002115 (menu->FocusedItem == NO_SELECTED_ITEM))
2116 {
2117 WIN_ReleaseWndPtr(wndPtr);
2118 return hmenu;
2119 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002120
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002121 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002122 if (!(item->fType & MF_POPUP) ||
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002123 (item->fState & (MF_GRAYED | MF_DISABLED)))
2124 {
2125 WIN_ReleaseWndPtr(wndPtr);
2126 return hmenu;
2127 }
Alexandre Julliard02e90081998-01-04 17:49:09 +00002128
2129 /* message must be send before using item,
2130 because nearly everything may by changed by the application ! */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002131
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002132 /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
2133 if (!(wFlags & TPM_NONOTIFY))
2134 SendMessageA( hwndOwner, WM_INITMENUPOPUP, item->hSubMenu,
Alexandre Julliard02e90081998-01-04 17:49:09 +00002135 MAKELONG( menu->FocusedItem, IS_SYSTEM_MENU(menu) ));
2136
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002137 item = &menu->items[menu->FocusedItem];
2138 rect = item->rect;
2139
Alexandre Julliard02e90081998-01-04 17:49:09 +00002140 /* correct item if modified as a reaction to WM_INITMENUPOPUP-message */
2141 if (!(item->fState & MF_HILITE))
2142 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002143 if (menu->wFlags & MF_POPUP) hdc = GetDC( menu->hWnd );
2144 else hdc = GetDCEx( menu->hWnd, 0, DCX_CACHE | DCX_WINDOW);
Juergen Schmied78513941999-04-18 14:40:32 +00002145
2146 SelectObject( hdc, hMenuFont);
2147
Alexandre Julliard02e90081998-01-04 17:49:09 +00002148 item->fState |= MF_HILITE;
Juergen Schmied78513941999-04-18 14:40:32 +00002149 MENU_DrawMenuItem( menu->hWnd, hmenu, hwndOwner, hdc, item, menu->Height, !(menu->wFlags & MF_POPUP), ODA_DRAWENTIRE );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002150 ReleaseDC( menu->hWnd, hdc );
Alexandre Julliard02e90081998-01-04 17:49:09 +00002151 }
2152 if (!item->rect.top && !item->rect.left && !item->rect.bottom && !item->rect.right)
2153 item->rect = rect;
2154
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002155 item->fState |= MF_MOUSESELECT;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002156
2157 if (IS_SYSTEM_MENU(menu))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002158 {
Patrik Stridvall4bf33541999-06-12 14:52:15 +00002159 MENU_InitSysMenuPopup(item->hSubMenu, wndPtr->dwStyle, GetClassLongA(wndPtr->hwndSelf, GCL_STYLE));
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002160
2161 NC_GetSysPopupPos( wndPtr, &rect );
2162 rect.top = rect.bottom;
Marcus Meissnerddca3151999-05-22 11:33:23 +00002163 rect.right = GetSystemMetrics(SM_CXSIZE);
2164 rect.bottom = GetSystemMetrics(SM_CYSIZE);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002165 }
2166 else
2167 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002168 if (menu->wFlags & MF_POPUP)
2169 {
Ken Thomases130f0d82000-05-10 21:38:37 +00002170 rect.left = wndPtr->rectWindow.left + item->rect.right - GetSystemMetrics(SM_CXBORDER);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002171 rect.top = wndPtr->rectWindow.top + item->rect.top;
Ken Thomases130f0d82000-05-10 21:38:37 +00002172 rect.right = item->rect.left - item->rect.right + GetSystemMetrics(SM_CXBORDER);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002173 rect.bottom = item->rect.top - item->rect.bottom;
2174 }
2175 else
2176 {
2177 rect.left = wndPtr->rectWindow.left + item->rect.left;
2178 rect.top = wndPtr->rectWindow.top + item->rect.bottom;
2179 rect.right = item->rect.right - item->rect.left;
2180 rect.bottom = item->rect.bottom - item->rect.top;
2181 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002182 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002183
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002184 MENU_ShowPopup( hwndOwner, item->hSubMenu, menu->FocusedItem,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002185 rect.left, rect.top, rect.right, rect.bottom );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002186 if (selectFirst)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002187 MENU_MoveSelection( hwndOwner, item->hSubMenu, ITEM_NEXT );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002188 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002189 return item->hSubMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002190}
2191
Ulrich Czekalla33026a22000-02-26 19:13:44 +00002192
2193
2194/**********************************************************************
2195 * MENU_IsMenuActive
2196 */
2197BOOL MENU_IsMenuActive(void)
2198{
2199 return pTopPopupWnd && (pTopPopupWnd->dwStyle & WS_VISIBLE);
2200}
2201
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002202/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002203 * MENU_PtMenu
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002204 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002205 * Walks menu chain trying to find a menu pt maps to.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002206 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002207static HMENU MENU_PtMenu( HMENU hMenu, POINT16 pt )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002208{
Gerard Patel3e629742000-01-17 22:22:16 +00002209 POPUPMENU *menu = MENU_GetMenu( hMenu );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002210 register UINT ht = menu->FocusedItem;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002211
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002212 /* try subpopup first (if any) */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002213 ht = (ht != NO_SELECTED_ITEM &&
2214 (menu->items[ht].fType & MF_POPUP) &&
2215 (menu->items[ht].fState & MF_MOUSESELECT))
Alexandre Julliarda3960291999-02-26 11:11:13 +00002216 ? (UINT) MENU_PtMenu(menu->items[ht].hSubMenu, pt) : 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002217
2218 if( !ht ) /* check the current window (avoiding WM_HITTEST) */
2219 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002220 ht = (UINT)NC_HandleNCHitTest( menu->hWnd, pt );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002221 if( menu->wFlags & MF_POPUP )
Alexandre Julliarda3960291999-02-26 11:11:13 +00002222 ht = (ht != (UINT)HTNOWHERE &&
2223 ht != (UINT)HTERROR) ? (UINT)hMenu : 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002224 else
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002225 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002226 WND* wndPtr = WIN_FindWndPtr(menu->hWnd);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002227
Alexandre Julliarda3960291999-02-26 11:11:13 +00002228 ht = ( ht == HTSYSMENU ) ? (UINT)(wndPtr->hSysMenu)
2229 : ( ht == HTMENU ) ? (UINT)(wndPtr->wIDmenu) : 0;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002230 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002231 }
2232 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002233 return (HMENU)ht;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002234}
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002235
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002236/***********************************************************************
2237 * MENU_ExecFocusedItem
2238 *
2239 * Execute a menu item (for instance when user pressed Enter).
Karl Lessard13409b31999-09-28 16:24:58 +00002240 * Return the wID of the executed item. Otherwise, -1 indicating
Andreas Mohr2e011a52000-06-01 23:28:25 +00002241 * that no menu item was executed;
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002242 * Have to receive the flags for the TrackPopupMenu options to avoid
2243 * sending unwanted message.
2244 *
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002245 */
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002246static INT MENU_ExecFocusedItem( MTRACKER* pmt, HMENU hMenu, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002247{
2248 MENUITEM *item;
Gerard Patel3e629742000-01-17 22:22:16 +00002249 POPUPMENU *menu = MENU_GetMenu( hMenu );
Juergen Schmied466a6521999-05-02 11:21:08 +00002250
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002251 TRACE("%p hmenu=0x%04x\n", pmt, hMenu);
Juergen Schmied466a6521999-05-02 11:21:08 +00002252
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002253 if (!menu || !menu->nItems ||
Karl Lessard13409b31999-09-28 16:24:58 +00002254 (menu->FocusedItem == NO_SELECTED_ITEM)) return -1;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002255
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002256 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002257
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002258 TRACE("%08x %08x %08x\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002259 hMenu, item->wID, item->hSubMenu);
2260
2261 if (!(item->fType & MF_POPUP))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002262 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002263 if (!(item->fState & (MF_GRAYED | MF_DISABLED)))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002264 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002265 /* If TPM_RETURNCMD is set you return the id, but
2266 do not send a message to the owner */
2267 if(!(wFlags & TPM_RETURNCMD))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002268 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002269 if( menu->wFlags & MF_SYSMENU )
2270 PostMessageA( pmt->hOwnerWnd, WM_SYSCOMMAND, item->wID,
2271 MAKELPARAM((INT16)pmt->pt.x, (INT16)pmt->pt.y) );
2272 else
2273 PostMessageA( pmt->hOwnerWnd, WM_COMMAND, item->wID, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002274 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002275 return item->wID;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002276 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002277 }
2278 else
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002279 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hMenu, TRUE, wFlags);
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002280
Karl Lessard13409b31999-09-28 16:24:58 +00002281 return -1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002282}
2283
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002284/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002285 * MENU_SwitchTracking
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002286 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002287 * Helper function for menu navigation routines.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002288 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002289static void MENU_SwitchTracking( MTRACKER* pmt, HMENU hPtMenu, UINT id )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002290{
Gerard Patel3e629742000-01-17 22:22:16 +00002291 POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
2292 POPUPMENU *topmenu = MENU_GetMenu( pmt->hTopMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002293
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002294 TRACE("%p hmenu=0x%04x 0x%04x\n", pmt, hPtMenu, id);
Juergen Schmied466a6521999-05-02 11:21:08 +00002295
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002296 if( pmt->hTopMenu != hPtMenu &&
2297 !((ptmenu->wFlags | topmenu->wFlags) & MF_POPUP) )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002298 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002299 /* both are top level menus (system and menu-bar) */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002300 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00002301 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM, FALSE, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002302 pmt->hTopMenu = hPtMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002303 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002304 else MENU_HideSubPopups( pmt->hOwnerWnd, hPtMenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00002305 MENU_SelectItem( pmt->hOwnerWnd, hPtMenu, id, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002306}
2307
2308
2309/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002310 * MENU_ButtonDown
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002311 *
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002312 * Return TRUE if we can go on with menu tracking.
2313 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002314static BOOL MENU_ButtonDown( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002315{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002316 TRACE("%p hmenu=0x%04x\n", pmt, hPtMenu);
Juergen Schmied466a6521999-05-02 11:21:08 +00002317
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002318 if (hPtMenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002319 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002320 UINT id = 0;
Gerard Patel3e629742000-01-17 22:22:16 +00002321 POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002322 MENUITEM *item;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002323
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002324 if( IS_SYSTEM_MENU(ptmenu) )
2325 item = ptmenu->items;
2326 else
2327 item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002328
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002329 if( item )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002330 {
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002331 if( ptmenu->FocusedItem != id )
2332 MENU_SwitchTracking( pmt, hPtMenu, id );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002333
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002334 /* If the popup menu is not already "popped" */
2335 if(!(item->fState & MF_MOUSESELECT ))
Pascal Lessard07c447f1999-09-19 12:03:25 +00002336 {
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002337 pmt->hCurrentMenu = MENU_ShowSubPopup( pmt->hOwnerWnd, hPtMenu, FALSE, wFlags );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002338
Pascal Lessard07c447f1999-09-19 12:03:25 +00002339 /* In win31, a newly popped menu always remain opened for the next buttonup */
2340 if(TWEAK_WineLook == WIN31_LOOK)
2341 ptmenu->bTimeToHide = FALSE;
2342 }
2343
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002344 return TRUE;
2345 }
Pascal Lessard445c9101999-09-20 18:27:14 +00002346 /* Else the click was on the menu bar, finish the tracking */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002347 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002348 return FALSE;
2349}
2350
2351/***********************************************************************
2352 * MENU_ButtonUp
2353 *
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002354 * Return the value of MENU_ExecFocusedItem if
2355 * the selected item was not a popup. Else open the popup.
Karl Lessard13409b31999-09-28 16:24:58 +00002356 * A -1 return value indicates that we go on with menu tracking.
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002357 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002358 */
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002359static INT MENU_ButtonUp( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002360{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002361 TRACE("%p hmenu=0x%04x\n", pmt, hPtMenu);
Juergen Schmied466a6521999-05-02 11:21:08 +00002362
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002363 if (hPtMenu)
2364 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002365 UINT id = 0;
Gerard Patel3e629742000-01-17 22:22:16 +00002366 POPUPMENU *ptmenu = MENU_GetMenu( hPtMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002367 MENUITEM *item;
2368
2369 if( IS_SYSTEM_MENU(ptmenu) )
2370 item = ptmenu->items;
2371 else
2372 item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
2373
Alexandre Julliard491502b1997-11-01 19:08:16 +00002374 if( item && (ptmenu->FocusedItem == id ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002375 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002376 if( !(item->fType & MF_POPUP) )
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002377 return MENU_ExecFocusedItem( pmt, hPtMenu, wFlags);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002378
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002379 /* If we are dealing with the top-level menu and that this */
2380 /* is a click on an already "poppped" item */
2381 /* Stop the menu tracking and close the opened submenus */
2382 if((pmt->hTopMenu == hPtMenu) && (ptmenu->bTimeToHide == TRUE))
Karl Lessard13409b31999-09-28 16:24:58 +00002383 return 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002384 }
Pascal Lessard2eb0a301999-09-03 16:38:52 +00002385 ptmenu->bTimeToHide = TRUE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002386 }
Karl Lessard13409b31999-09-28 16:24:58 +00002387 return -1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002388}
2389
2390
2391/***********************************************************************
2392 * MENU_MouseMove
2393 *
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002394 * Return TRUE if we can go on with menu tracking.
2395 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002396static BOOL MENU_MouseMove( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002397{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002398 UINT id = NO_SELECTED_ITEM;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002399 POPUPMENU *ptmenu = NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002400
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002401 if( hPtMenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002402 {
Gerard Patel3e629742000-01-17 22:22:16 +00002403 ptmenu = MENU_GetMenu( hPtMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002404 if( IS_SYSTEM_MENU(ptmenu) )
2405 id = 0;
2406 else
2407 MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
2408 }
2409
2410 if( id == NO_SELECTED_ITEM )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002411 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002412 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002413 NO_SELECTED_ITEM, TRUE, pmt->hTopMenu);
2414
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002415 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002416 else if( ptmenu->FocusedItem != id )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002417 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002418 MENU_SwitchTracking( pmt, hPtMenu, id );
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002419 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hPtMenu, FALSE, wFlags);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002420 }
2421 return TRUE;
2422}
2423
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002424
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002425/***********************************************************************
2426 * MENU_DoNextMenu
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002427 *
2428 * NOTE: WM_NEXTMENU documented in Win32 is a bit different.
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002429 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002430static LRESULT MENU_DoNextMenu( MTRACKER* pmt, UINT vk )
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002431{
Gerard Patel3e629742000-01-17 22:22:16 +00002432 POPUPMENU *menu = MENU_GetMenu( pmt->hTopMenu );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002433
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002434 if( (vk == VK_LEFT && menu->FocusedItem == 0 ) ||
2435 (vk == VK_RIGHT && menu->FocusedItem == menu->nItems - 1))
2436 {
2437 WND* wndPtr;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002438 HMENU hNewMenu;
2439 HWND hNewWnd;
2440 UINT id = 0;
Juergen Schmied78513941999-04-18 14:40:32 +00002441 LRESULT l = SendMessageA( pmt->hOwnerWnd, WM_NEXTMENU, vk,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002442 (IS_SYSTEM_MENU(menu)) ? GetSubMenu16(pmt->hTopMenu,0) : pmt->hTopMenu );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002443
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002444 TRACE("%04x [%04x] -> %04x [%04x]\n",
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002445 (UINT16)pmt->hCurrentMenu, (UINT16)pmt->hOwnerWnd, LOWORD(l), HIWORD(l) );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002446
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002447 if( l == 0 )
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002448 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002449 wndPtr = WIN_FindWndPtr(pmt->hOwnerWnd);
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002450
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002451 hNewWnd = pmt->hOwnerWnd;
2452 if( IS_SYSTEM_MENU(menu) )
2453 {
2454 /* switch to the menu bar */
2455
2456 if( wndPtr->dwStyle & WS_CHILD || !wndPtr->wIDmenu )
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002457 {
2458 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002459 return FALSE;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002460 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002461
2462 hNewMenu = wndPtr->wIDmenu;
2463 if( vk == VK_LEFT )
2464 {
Gerard Patel3e629742000-01-17 22:22:16 +00002465 menu = MENU_GetMenu( hNewMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002466 id = menu->nItems - 1;
2467 }
2468 }
2469 else if( wndPtr->dwStyle & WS_SYSMENU )
2470 {
2471 /* switch to the system menu */
2472 hNewMenu = wndPtr->hSysMenu;
2473 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002474 else
2475 {
2476 WIN_ReleaseWndPtr(wndPtr);
2477 return FALSE;
2478 }
2479 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002480 }
2481 else /* application returned a new menu to switch to */
2482 {
2483 hNewMenu = LOWORD(l); hNewWnd = HIWORD(l);
2484
Alexandre Julliarda3960291999-02-26 11:11:13 +00002485 if( IsMenu(hNewMenu) && IsWindow(hNewWnd) )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002486 {
2487 wndPtr = WIN_FindWndPtr(hNewWnd);
2488
2489 if( wndPtr->dwStyle & WS_SYSMENU &&
2490 GetSubMenu16(wndPtr->hSysMenu, 0) == hNewMenu )
2491 {
2492 /* get the real system menu */
2493 hNewMenu = wndPtr->hSysMenu;
2494 }
2495 else if( wndPtr->dwStyle & WS_CHILD || wndPtr->wIDmenu != hNewMenu )
2496 {
2497 /* FIXME: Not sure what to do here, perhaps,
2498 * try to track hNewMenu as a popup? */
2499
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002500 TRACE(" -- got confused.\n");
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002501 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002502 return FALSE;
2503 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002504 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002505 }
2506 else return FALSE;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002507 }
2508
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002509 if( hNewMenu != pmt->hTopMenu )
2510 {
Rein Klazes80c924f1999-12-12 19:40:46 +00002511 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM,
2512 FALSE, 0 );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002513 if( pmt->hCurrentMenu != pmt->hTopMenu )
2514 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
2515 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002516
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002517 if( hNewWnd != pmt->hOwnerWnd )
2518 {
2519 ReleaseCapture();
2520 pmt->hOwnerWnd = hNewWnd;
2521 EVENT_Capture( pmt->hOwnerWnd, HTMENU );
2522 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002523
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002524 pmt->hTopMenu = pmt->hCurrentMenu = hNewMenu; /* all subpopups are hidden */
Rein Klazes80c924f1999-12-12 19:40:46 +00002525 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, id, TRUE, 0 );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002526
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002527 return TRUE;
2528 }
2529 return FALSE;
2530}
2531
2532/***********************************************************************
2533 * MENU_SuspendPopup
2534 *
2535 * The idea is not to show the popup if the next input message is
2536 * going to hide it anyway.
2537 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002538static BOOL MENU_SuspendPopup( MTRACKER* pmt, UINT16 uMsg )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002539{
Juergen Schmied78513941999-04-18 14:40:32 +00002540 MSG msg;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002541
2542 msg.hwnd = pmt->hOwnerWnd;
2543
Juergen Schmied78513941999-04-18 14:40:32 +00002544 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002545 pmt->trackFlags |= TF_SKIPREMOVE;
2546
2547 switch( uMsg )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002548 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002549 case WM_KEYDOWN:
Juergen Schmied78513941999-04-18 14:40:32 +00002550 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002551 if( msg.message == WM_KEYUP || msg.message == WM_PAINT )
2552 {
Juergen Schmied78513941999-04-18 14:40:32 +00002553 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE);
2554 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002555 if( msg.message == WM_KEYDOWN &&
2556 (msg.wParam == VK_LEFT || msg.wParam == VK_RIGHT))
2557 {
2558 pmt->trackFlags |= TF_SUSPENDPOPUP;
2559 return TRUE;
2560 }
2561 }
2562 break;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002563 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002564
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002565 /* failures go through this */
2566 pmt->trackFlags &= ~TF_SUSPENDPOPUP;
2567 return FALSE;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002568}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002569
2570/***********************************************************************
2571 * MENU_KeyLeft
2572 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002573 * Handle a VK_LEFT key event in a menu.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002574 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002575static void MENU_KeyLeft( MTRACKER* pmt, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002576{
2577 POPUPMENU *menu;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002578 HMENU hmenutmp, hmenuprev;
2579 UINT prevcol;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002580
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002581 hmenuprev = hmenutmp = pmt->hTopMenu;
Gerard Patel3e629742000-01-17 22:22:16 +00002582 menu = MENU_GetMenu( hmenutmp );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002583
Alexandre Julliard641ee761997-08-04 16:34:36 +00002584 /* Try to move 1 column left (if possible) */
2585 if( (prevcol = MENU_GetStartOfPrevColumn( pmt->hCurrentMenu )) !=
2586 NO_SELECTED_ITEM ) {
2587
2588 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002589 prevcol, TRUE, 0 );
Alexandre Julliard641ee761997-08-04 16:34:36 +00002590 return;
2591 }
2592
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002593 /* close topmost popup */
2594 while (hmenutmp != pmt->hCurrentMenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002595 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002596 hmenuprev = hmenutmp;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002597 hmenutmp = MENU_GetSubPopup( hmenuprev );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002598 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002599
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002600 MENU_HideSubPopups( pmt->hOwnerWnd, hmenuprev, TRUE );
2601 pmt->hCurrentMenu = hmenuprev;
2602
2603 if ( (hmenuprev == pmt->hTopMenu) && !(menu->wFlags & MF_POPUP) )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002604 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002605 /* move menu bar selection if no more popups are left */
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002606
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002607 if( !MENU_DoNextMenu( pmt, VK_LEFT) )
2608 MENU_MoveSelection( pmt->hOwnerWnd, pmt->hTopMenu, ITEM_PREV );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002609
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002610 if ( hmenuprev != hmenutmp || pmt->trackFlags & TF_SUSPENDPOPUP )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002611 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002612 /* A sublevel menu was displayed - display the next one
2613 * unless there is another displacement coming up */
2614
2615 if( !MENU_SuspendPopup( pmt, WM_KEYDOWN ) )
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002616 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd,
2617 pmt->hTopMenu, TRUE, wFlags);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002618 }
2619 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002620}
2621
2622
2623/***********************************************************************
2624 * MENU_KeyRight
2625 *
2626 * Handle a VK_RIGHT key event in a menu.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002627 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002628static void MENU_KeyRight( MTRACKER* pmt, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002629{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002630 HMENU hmenutmp;
Gerard Patel3e629742000-01-17 22:22:16 +00002631 POPUPMENU *menu = MENU_GetMenu( pmt->hTopMenu );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002632 UINT nextcol;
Alexandre Julliard641ee761997-08-04 16:34:36 +00002633
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002634 TRACE("MENU_KeyRight called, cur %x (%s), top %x (%s).\n",
Alexandre Julliard641ee761997-08-04 16:34:36 +00002635 pmt->hCurrentMenu,
Gerard Patel3e629742000-01-17 22:22:16 +00002636 (MENU_GetMenu(pmt->hCurrentMenu))->
Alexandre Julliard641ee761997-08-04 16:34:36 +00002637 items[0].text,
2638 pmt->hTopMenu, menu->items[0].text );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002639
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002640 if ( (menu->wFlags & MF_POPUP) || (pmt->hCurrentMenu != pmt->hTopMenu))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002641 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002642 /* If already displaying a popup, try to display sub-popup */
2643
2644 hmenutmp = pmt->hCurrentMenu;
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002645 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hmenutmp, TRUE, wFlags);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002646
2647 /* if subpopup was displayed then we are done */
2648 if (hmenutmp != pmt->hCurrentMenu) return;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002649 }
2650
Alexandre Julliard641ee761997-08-04 16:34:36 +00002651 /* Check to see if there's another column */
2652 if( (nextcol = MENU_GetStartOfNextColumn( pmt->hCurrentMenu )) !=
2653 NO_SELECTED_ITEM ) {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002654 TRACE("Going to %d.\n", nextcol );
Alexandre Julliard641ee761997-08-04 16:34:36 +00002655 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002656 nextcol, TRUE, 0 );
Alexandre Julliard641ee761997-08-04 16:34:36 +00002657 return;
2658 }
2659
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002660 if (!(menu->wFlags & MF_POPUP)) /* menu bar tracking */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002661 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002662 if( pmt->hCurrentMenu != pmt->hTopMenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002663 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002664 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
2665 hmenutmp = pmt->hCurrentMenu = pmt->hTopMenu;
2666 } else hmenutmp = 0;
2667
2668 /* try to move to the next item */
2669 if( !MENU_DoNextMenu( pmt, VK_RIGHT) )
2670 MENU_MoveSelection( pmt->hOwnerWnd, pmt->hTopMenu, ITEM_NEXT );
2671
2672 if( hmenutmp || pmt->trackFlags & TF_SUSPENDPOPUP )
2673 if( !MENU_SuspendPopup(pmt, WM_KEYDOWN) )
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002674 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd,
2675 pmt->hTopMenu, TRUE, wFlags);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002676 }
2677}
2678
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002679/***********************************************************************
2680 * MENU_TrackMenu
2681 *
2682 * Menu tracking code.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002683 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002684static INT MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y,
2685 HWND hwnd, const RECT *lprect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002686{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002687 MSG msg;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002688 POPUPMENU *menu;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002689 BOOL fRemove;
Karl Lessard13409b31999-09-28 16:24:58 +00002690 INT executedMenuId = -1;
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +00002691 MTRACKER mt;
Francis Beaudet7ed1af31999-08-15 16:58:03 +00002692 BOOL enterIdleSent = FALSE;
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +00002693
2694 mt.trackFlags = 0;
2695 mt.hCurrentMenu = hmenu;
2696 mt.hTopMenu = hmenu;
2697 mt.hOwnerWnd = hwnd;
2698 mt.pt.x = x;
2699 mt.pt.y = y;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002700
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002701 TRACE("hmenu=0x%04x flags=0x%08x (%d,%d) hwnd=0x%04x (%d,%d)-(%d,%d)\n",
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00002702 hmenu, wFlags, x, y, hwnd, (lprect) ? lprect->left : 0, (lprect) ? lprect->top : 0,
2703 (lprect) ? lprect->right : 0, (lprect) ? lprect->bottom : 0);
Juergen Schmied78513941999-04-18 14:40:32 +00002704
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002705 fEndMenu = FALSE;
Gerard Patel3e629742000-01-17 22:22:16 +00002706 if (!(menu = MENU_GetMenu( hmenu ))) return FALSE;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002707
Pascal Lessardae6de762000-01-09 02:38:02 +00002708 if (wFlags & TPM_BUTTONDOWN)
2709 {
2710 /* Get the result in order to start the tracking or not */
2711 fRemove = MENU_ButtonDown( &mt, hmenu, wFlags );
2712 fEndMenu = !fRemove;
2713 }
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002714
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002715 EVENT_Capture( mt.hOwnerWnd, HTMENU );
2716
2717 while (!fEndMenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002718 {
Gerard Patel3e629742000-01-17 22:22:16 +00002719 menu = MENU_GetMenu( mt.hCurrentMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002720 msg.hwnd = (wFlags & TPM_ENTERIDLEEX && menu->wFlags & MF_POPUP) ? menu->hWnd : 0;
2721
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002722 /* we have to keep the message in the queue until it's
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002723 * clear that menu loop is not over yet. */
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002724
Ulrich Weigand2faf2cf1999-12-10 03:47:13 +00002725 if (!MSG_InternalGetMessage( QMSG_WIN32A, &msg, msg.hwnd, mt.hOwnerWnd,
Francis Beaudet7ed1af31999-08-15 16:58:03 +00002726 MSGF_MENU, PM_NOREMOVE, !enterIdleSent, &enterIdleSent )) break;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002727
Rob Farnumb2007932000-05-23 23:34:17 +00002728 /* check if EndMenu() tried to cancel us, by posting this message */
2729 if(msg.message == WM_CANCELMODE)
2730 {
2731 /* we are now out of the loop */
2732 fEndMenu = TRUE;
2733
2734 /* remove the message from the queue */
2735 PeekMessageA( &msg, 0, msg.message, msg.message, PM_REMOVE );
2736
2737 /* break out of internal loop, ala ESCAPE */
2738 break;
2739 }
2740
Alexandre Julliarda3960291999-02-26 11:11:13 +00002741 TranslateMessage( &msg );
Stephane Lussierb3a99de1999-02-09 15:35:12 +00002742 mt.pt = msg.pt;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002743
Francis Beaudet7ed1af31999-08-15 16:58:03 +00002744 if ( (msg.hwnd==menu->hWnd) || (msg.message!=WM_TIMER) )
2745 enterIdleSent=FALSE;
2746
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002747 fRemove = FALSE;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002748 if ((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002749 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002750 /* Find a menu for this mouse event */
Stephane Lussierb3a99de1999-02-09 15:35:12 +00002751 POINT16 pt16;
2752 CONV_POINT32TO16( &msg.pt, &pt16 );
2753 hmenu = MENU_PtMenu( mt.hTopMenu, pt16 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002754
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002755 switch(msg.message)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002756 {
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002757 /* no WM_NC... messages in captured state */
2758
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002759 case WM_RBUTTONDBLCLK:
2760 case WM_RBUTTONDOWN:
2761 if (!(wFlags & TPM_RIGHTBUTTON)) break;
2762 /* fall through */
2763 case WM_LBUTTONDBLCLK:
2764 case WM_LBUTTONDOWN:
Karl Lessard4a0a7df1999-11-07 05:17:10 +00002765 /* If the message belongs to the menu, removes it from the queue */
2766 /* Else, end menu tracking */
2767 fRemove = MENU_ButtonDown( &mt, hmenu, wFlags );
2768 fEndMenu = !fRemove;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002769 break;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002770
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002771 case WM_RBUTTONUP:
2772 if (!(wFlags & TPM_RIGHTBUTTON)) break;
2773 /* fall through */
2774 case WM_LBUTTONUP:
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002775 /* Check if a menu was selected by the mouse */
2776 if (hmenu)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002777 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002778 executedMenuId = MENU_ButtonUp( &mt, hmenu, wFlags);
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002779
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002780 /* End the loop if executedMenuId is an item ID */
Karl Lessard13409b31999-09-28 16:24:58 +00002781 /* or if the job was done (executedMenuId = 0). */
2782 fEndMenu = fRemove = (executedMenuId != -1);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002783 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002784 /* No menu was selected by the mouse */
2785 /* if the function was called by TrackPopupMenu, continue
2786 with the menu tracking. If not, stop it */
2787 else
2788 fEndMenu = ((wFlags & TPM_POPUPMENU) ? FALSE : TRUE);
2789
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002790 break;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002791
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002792 case WM_MOUSEMOVE:
Alexandre Julliard8da12c41999-01-17 16:55:11 +00002793 /* In win95 winelook, the selected menu item must be changed every time the
2794 mouse moves. In Win31 winelook, the mouse button has to be held down */
2795
2796 if ( (TWEAK_WineLook > WIN31_LOOK) ||
2797 ( (msg.wParam & MK_LBUTTON) ||
2798 ((wFlags & TPM_RIGHTBUTTON) && (msg.wParam & MK_RBUTTON))) )
2799
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002800 fEndMenu |= !MENU_MouseMove( &mt, hmenu, wFlags );
Alexandre Julliard8da12c41999-01-17 16:55:11 +00002801
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002802 } /* switch(msg.message) - mouse */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002803 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002804 else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002805 {
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002806 fRemove = TRUE; /* Keyboard messages are always removed */
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002807 switch(msg.message)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002808 {
2809 case WM_KEYDOWN:
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002810 switch(msg.wParam)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002811 {
2812 case VK_HOME:
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002813 case VK_END:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002814 MENU_SelectItem( mt.hOwnerWnd, mt.hCurrentMenu,
Rein Klazes80c924f1999-12-12 19:40:46 +00002815 NO_SELECTED_ITEM, FALSE, 0 );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002816 /* fall through */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002817 case VK_UP:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002818 MENU_MoveSelection( mt.hOwnerWnd, mt.hCurrentMenu,
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002819 (msg.wParam == VK_HOME)? ITEM_NEXT : ITEM_PREV );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002820 break;
2821
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002822 case VK_DOWN: /* If on menu bar, pull-down the menu */
2823
Gerard Patel3e629742000-01-17 22:22:16 +00002824 menu = MENU_GetMenu( mt.hCurrentMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002825 if (!(menu->wFlags & MF_POPUP))
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002826 mt.hCurrentMenu = MENU_ShowSubPopup(mt.hOwnerWnd, mt.hTopMenu, TRUE, wFlags);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002827 else /* otherwise try to move selection */
2828 MENU_MoveSelection( mt.hOwnerWnd, mt.hCurrentMenu, ITEM_NEXT );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002829 break;
2830
2831 case VK_LEFT:
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002832 MENU_KeyLeft( &mt, wFlags );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002833 break;
2834
2835 case VK_RIGHT:
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002836 MENU_KeyRight( &mt, wFlags );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002837 break;
2838
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002839 case VK_ESCAPE:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002840 fEndMenu = TRUE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002841 break;
2842
Ulrich Czekalla33026a22000-02-26 19:13:44 +00002843 case VK_F1:
2844 {
2845 HELPINFO hi;
2846 hi.cbSize = sizeof(HELPINFO);
2847 hi.iContextType = HELPINFO_MENUITEM;
2848 if (menu->FocusedItem == NO_SELECTED_ITEM)
2849 hi.iCtrlId = 0;
2850 else
2851 hi.iCtrlId = menu->items[menu->FocusedItem].wID;
2852 hi.hItemHandle = hmenu;
2853 hi.dwContextId = menu->dwContextHelpID;
2854 hi.MousePos = msg.pt;
2855 SendMessageA(hwnd, WM_HELP, 0, (LPARAM)&hi);
2856 break;
2857 }
2858
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002859 default:
2860 break;
2861 }
2862 break; /* WM_KEYDOWN */
2863
2864 case WM_SYSKEYDOWN:
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002865 switch(msg.wParam)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002866 {
2867 case VK_MENU:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002868 fEndMenu = TRUE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002869 break;
2870
2871 }
2872 break; /* WM_SYSKEYDOWN */
2873
2874 case WM_CHAR:
2875 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002876 UINT pos;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002877
Norman Stevensa83d0651998-10-12 07:25:35 +00002878 if (msg.wParam == '\r' || msg.wParam == ' ')
2879 {
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002880 executedMenuId = MENU_ExecFocusedItem(&mt,mt.hCurrentMenu, wFlags);
Karl Lessard13409b31999-09-28 16:24:58 +00002881 fEndMenu = (executedMenuId != -1);
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002882
Norman Stevensa83d0651998-10-12 07:25:35 +00002883 break;
2884 }
2885
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002886 /* Hack to avoid control chars. */
2887 /* We will find a better way real soon... */
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002888 if ((msg.wParam <= 32) || (msg.wParam >= 127)) break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002889
2890 pos = MENU_FindItemByKey( mt.hOwnerWnd, mt.hCurrentMenu,
Stephane Lussierb3a99de1999-02-09 15:35:12 +00002891 LOWORD(msg.wParam), FALSE );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002892 if (pos == (UINT)-2) fEndMenu = TRUE;
2893 else if (pos == (UINT)-1) MessageBeep(0);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002894 else
2895 {
Rein Klazes80c924f1999-12-12 19:40:46 +00002896 MENU_SelectItem( mt.hOwnerWnd, mt.hCurrentMenu, pos,
2897 TRUE, 0 );
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00002898 executedMenuId = MENU_ExecFocusedItem(&mt,mt.hCurrentMenu, wFlags);
Karl Lessard13409b31999-09-28 16:24:58 +00002899 fEndMenu = (executedMenuId != -1);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002900 }
2901 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002902 break;
2903 } /* switch(msg.message) - kbd */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002904 }
2905 else
2906 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002907 DispatchMessageA( &msg );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002908 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002909
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002910 if (!fEndMenu) fRemove = TRUE;
2911
2912 /* finally remove message from the queue */
2913
2914 if (fRemove && !(mt.trackFlags & TF_SKIPREMOVE) )
Alexandre Julliarda3960291999-02-26 11:11:13 +00002915 PeekMessageA( &msg, 0, msg.message, msg.message, PM_REMOVE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002916 else mt.trackFlags &= ~TF_SKIPREMOVE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002917 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002918
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002919 ReleaseCapture();
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00002920
Guy Albertellif12b70a2000-05-11 00:06:11 +00002921 /* If dropdown is still painted and the close box is clicked on
2922 then the menu will be destroyed as part of the DispatchMessage above.
2923 This will then invalidate the menu handle in mt.hTopMenu. We should
2924 check for this first. */
2925 if( IsMenu( mt.hTopMenu ) )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002926 {
Guy Albertellif12b70a2000-05-11 00:06:11 +00002927 menu = MENU_GetMenu( mt.hTopMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002928
Guy Albertellif12b70a2000-05-11 00:06:11 +00002929 if( IsWindow( mt.hOwnerWnd ) )
2930 {
2931 MENU_HideSubPopups( mt.hOwnerWnd, mt.hTopMenu, FALSE );
2932
2933 if (menu && menu->wFlags & MF_POPUP)
2934 {
2935 ShowWindow( menu->hWnd, SW_HIDE );
2936 uSubPWndLevel = 0;
2937 }
2938 MENU_SelectItem( mt.hOwnerWnd, mt.hTopMenu, NO_SELECTED_ITEM, FALSE, 0 );
2939 SendMessageA( mt.hOwnerWnd, WM_MENUSELECT, MAKELONG(0,0xffff), 0 );
2940 }
2941
2942 /* Reset the variable for hiding menu */
2943 if( menu ) menu->bTimeToHide = FALSE;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002944 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002945
Juergen Schmied371c4201999-10-13 12:27:44 +00002946 /* The return value is only used by TrackPopupMenu */
2947 return ((executedMenuId != -1) ? executedMenuId : 0);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002948}
2949
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002950/***********************************************************************
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002951 * MENU_InitTracking
2952 */
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002953static BOOL MENU_InitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT wFlags)
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002954{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002955 TRACE("hwnd=0x%04x hmenu=0x%04x\n", hWnd, hMenu);
Juergen Schmied78513941999-04-18 14:40:32 +00002956
Alexandre Julliarda3960291999-02-26 11:11:13 +00002957 HideCaret(0);
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002958
2959 /* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */
2960 if (!(wFlags & TPM_NONOTIFY))
2961 SendMessageA( hWnd, WM_ENTERMENULOOP, bPopup, 0 );
2962
Juergen Schmied78513941999-04-18 14:40:32 +00002963 SendMessageA( hWnd, WM_SETCURSOR, hWnd, HTCAPTION );
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002964
2965 if (!(wFlags & TPM_NONOTIFY))
2966 SendMessageA( hWnd, WM_INITMENU, hMenu, 0 );
2967
Juergen Schmied78513941999-04-18 14:40:32 +00002968 return TRUE;
2969}
2970/***********************************************************************
2971 * MENU_ExitTracking
2972 */
2973static BOOL MENU_ExitTracking(HWND hWnd)
2974{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002975 TRACE("hwnd=0x%04x\n", hWnd);
Juergen Schmied78513941999-04-18 14:40:32 +00002976
2977 SendMessageA( hWnd, WM_EXITMENULOOP, 0, 0 );
2978 ShowCaret(0);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002979 return TRUE;
2980}
2981
2982/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002983 * MENU_TrackMouseMenuBar
2984 *
2985 * Menu-bar tracking upon a mouse event. Called from NC_HandleSysCommand().
2986 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002987void MENU_TrackMouseMenuBar( WND* wndPtr, INT ht, POINT pt )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002988{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002989 HWND hWnd = wndPtr->hwndSelf;
2990 HMENU hMenu = (ht == HTSYSMENU) ? wndPtr->hSysMenu : wndPtr->wIDmenu;
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002991 UINT wFlags = TPM_ENTERIDLEEX | TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002992
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00002993 TRACE("pwnd=%p ht=0x%04x (%ld,%ld)\n", wndPtr, ht, pt.x, pt.y);
Juergen Schmied78513941999-04-18 14:40:32 +00002994
Alexandre Julliarda3960291999-02-26 11:11:13 +00002995 if (IsMenu(hMenu))
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002996 {
Abey Georgeb59d4bc1999-09-22 15:10:42 +00002997 MENU_InitTracking( hWnd, hMenu, FALSE, wFlags );
2998 MENU_TrackMenu( hMenu, wFlags, pt.x, pt.y, hWnd, NULL );
Juergen Schmied78513941999-04-18 14:40:32 +00002999 MENU_ExitTracking(hWnd);
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003000 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003001}
3002
3003
3004/***********************************************************************
3005 * MENU_TrackKbdMenuBar
3006 *
3007 * Menu-bar tracking upon a keyboard event. Called from NC_HandleSysCommand().
3008 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003009void MENU_TrackKbdMenuBar( WND* wndPtr, UINT wParam, INT vkey)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003010{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003011 UINT uItem = NO_SELECTED_ITEM;
3012 HMENU hTrackMenu;
Abey Georgeb59d4bc1999-09-22 15:10:42 +00003013 UINT wFlags = TPM_ENTERIDLEEX | TPM_LEFTALIGN | TPM_LEFTBUTTON;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003014
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003015 /* find window that has a menu */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003016
Pierre Mageau891d4d21999-10-23 20:05:04 +00003017 while( wndPtr->dwStyle & WS_CHILD)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003018 if( !(wndPtr = wndPtr->parent) ) return;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003019
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003020 /* check if we have to track a system menu */
3021
3022 if( (wndPtr->dwStyle & (WS_CHILD | WS_MINIMIZE)) ||
3023 !wndPtr->wIDmenu || vkey == VK_SPACE )
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003024 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003025 if( !(wndPtr->dwStyle & WS_SYSMENU) ) return;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003026 hTrackMenu = wndPtr->hSysMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003027 uItem = 0;
3028 wParam |= HTSYSMENU; /* prevent item lookup */
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003029 }
3030 else
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003031 hTrackMenu = wndPtr->wIDmenu;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003032
Alexandre Julliarda3960291999-02-26 11:11:13 +00003033 if (IsMenu( hTrackMenu ))
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003034 {
Abey Georgeb59d4bc1999-09-22 15:10:42 +00003035 MENU_InitTracking( wndPtr->hwndSelf, hTrackMenu, FALSE, wFlags );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003036
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003037 if( vkey && vkey != VK_SPACE )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003038 {
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003039 uItem = MENU_FindItemByKey( wndPtr->hwndSelf, hTrackMenu,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003040 vkey, (wParam & HTSYSMENU) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003041 if( uItem >= (UINT)(-2) )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003042 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003043 if( uItem == (UINT)(-1) ) MessageBeep(0);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003044 hTrackMenu = 0;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003045 }
3046 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003047
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003048 if( hTrackMenu )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003049 {
Rein Klazes80c924f1999-12-12 19:40:46 +00003050 MENU_SelectItem( wndPtr->hwndSelf, hTrackMenu, uItem, TRUE, 0 );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003051
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003052 if( uItem == NO_SELECTED_ITEM )
3053 MENU_MoveSelection( wndPtr->hwndSelf, hTrackMenu, ITEM_NEXT );
3054 else if( vkey )
Juergen Schmied78513941999-04-18 14:40:32 +00003055 PostMessageA( wndPtr->hwndSelf, WM_KEYDOWN, VK_DOWN, 0L );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003056
Abey Georgeb59d4bc1999-09-22 15:10:42 +00003057 MENU_TrackMenu( hTrackMenu, wFlags, 0, 0, wndPtr->hwndSelf, NULL );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003058 }
Juergen Schmied78513941999-04-18 14:40:32 +00003059
3060 MENU_ExitTracking (wndPtr->hwndSelf);
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003061 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003062}
3063
3064
3065/**********************************************************************
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003066 * TrackPopupMenu16 (USER.416)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003067 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003068BOOL16 WINAPI TrackPopupMenu16( HMENU16 hMenu, UINT16 wFlags, INT16 x, INT16 y,
3069 INT16 nReserved, HWND16 hWnd, const RECT16 *lpRect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003070{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003071 RECT r;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003072 if (lpRect)
3073 CONV_RECT16TO32( lpRect, &r );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003074 return TrackPopupMenu( hMenu, wFlags, x, y, nReserved, hWnd,
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003075 lpRect ? &r : NULL );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003076}
3077
3078
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003079/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00003080 * TrackPopupMenu (USER32.549)
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003081 *
3082 * Like the win32 API, the function return the command ID only if the
3083 * flag TPM_RETURNCMD is on.
3084 *
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003085 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003086BOOL WINAPI TrackPopupMenu( HMENU hMenu, UINT wFlags, INT x, INT y,
3087 INT nReserved, HWND hWnd, const RECT *lpRect )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003088{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003089 BOOL ret = FALSE;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003090
Abey Georgeb59d4bc1999-09-22 15:10:42 +00003091 MENU_InitTracking(hWnd, hMenu, TRUE, wFlags);
3092
3093 /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
3094 if (!(wFlags & TPM_NONOTIFY))
3095 SendMessageA( hWnd, WM_INITMENUPOPUP, hMenu, 0);
3096
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003097 if (MENU_ShowPopup( hWnd, hMenu, 0, x, y, 0, 0 ))
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00003098 ret = MENU_TrackMenu( hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd, lpRect );
Juergen Schmied78513941999-04-18 14:40:32 +00003099 MENU_ExitTracking(hWnd);
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003100
3101 if( (!(wFlags & TPM_RETURNCMD)) && (ret != FALSE) )
3102 ret = 1;
3103
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003104 return ret;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003105}
3106
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003107/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003108 * TrackPopupMenuEx (USER32.550)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003109 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003110BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y,
3111 HWND hWnd, LPTPMPARAMS lpTpm )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003112{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003113 FIXME("not fully implemented\n" );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003114 return TrackPopupMenu( hMenu, wFlags, x, y, 0, hWnd,
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003115 lpTpm ? &lpTpm->rcExclude : NULL );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00003116}
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003117
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003118/***********************************************************************
3119 * PopupMenuWndProc
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003120 *
3121 * NOTE: Windows has totally different (and undocumented) popup wndproc.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003122 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003123LRESULT WINAPI PopupMenuWndProc( HWND hwnd, UINT message, WPARAM wParam,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003124 LPARAM lParam )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003125{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003126 WND* wndPtr = WIN_FindWndPtr(hwnd);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003127 LRESULT retvalue;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003128
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003129 TRACE("hwnd=0x%04x msg=0x%04x wp=0x%04x lp=0x%08lx\n",
Juergen Schmied78513941999-04-18 14:40:32 +00003130 hwnd, message, wParam, lParam);
3131
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003132 switch(message)
3133 {
3134 case WM_CREATE:
3135 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003136 CREATESTRUCTA *cs = (CREATESTRUCTA*)lParam;
3137 SetWindowLongA( hwnd, 0, (LONG)cs->lpCreateParams );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003138 retvalue = 0;
3139 goto END;
Alexandre Julliardf7207251994-07-23 07:57:48 +00003140 }
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003141
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003142 case WM_MOUSEACTIVATE: /* We don't want to be activated */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003143 retvalue = MA_NOACTIVATE;
3144 goto END;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003145
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003146 case WM_PAINT:
3147 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003148 PAINTSTRUCT ps;
3149 BeginPaint( hwnd, &ps );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003150 MENU_DrawPopupMenu( hwnd, ps.hdc,
Alexandre Julliarda3960291999-02-26 11:11:13 +00003151 (HMENU)GetWindowLongA( hwnd, 0 ) );
3152 EndPaint( hwnd, &ps );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003153 retvalue = 0;
3154 goto END;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003155 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003156 case WM_ERASEBKGND:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003157 retvalue = 1;
3158 goto END;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003159
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00003160 case WM_DESTROY:
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00003161
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003162 /* zero out global pointer in case resident popup window
3163 * was somehow destroyed. */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00003164
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003165 if(MENU_GetTopPopupWnd() )
Alexandre Julliard54c27111998-03-29 19:44:57 +00003166 {
3167 if( hwnd == pTopPopupWnd->hwndSelf )
3168 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003169 ERR("resident popup destroyed!\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003170
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003171 MENU_DestroyTopPopupWnd();
Alexandre Julliard54c27111998-03-29 19:44:57 +00003172 uSubPWndLevel = 0;
3173 }
3174 else
3175 uSubPWndLevel--;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003176 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003177 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003178 break;
3179
3180 case WM_SHOWWINDOW:
3181
3182 if( wParam )
3183 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003184 if( !(*(HMENU*)wndPtr->wExtra) )
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003185 ERR("no menu to display\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003186 }
3187 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00003188 *(HMENU*)wndPtr->wExtra = 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003189 break;
3190
3191 case MM_SETMENUHANDLE:
3192
Alexandre Julliarda3960291999-02-26 11:11:13 +00003193 *(HMENU*)wndPtr->wExtra = (HMENU)wParam;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00003194 break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003195
3196 case MM_GETMENUHANDLE:
3197
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003198 retvalue = *(HMENU*)wndPtr->wExtra;
3199 goto END;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003200
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003201 default:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003202 retvalue = DefWindowProcA( hwnd, message, wParam, lParam );
3203 goto END;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003204 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003205 retvalue = 0;
3206END:
3207 WIN_ReleaseWndPtr(wndPtr);
3208 return retvalue;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003209}
3210
3211
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00003212/***********************************************************************
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003213 * MENU_GetMenuBarHeight
3214 *
3215 * Compute the size of the menu bar height. Used by NC_HandleNCCalcSize().
3216 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003217UINT MENU_GetMenuBarHeight( HWND hwnd, UINT menubarWidth,
3218 INT orgX, INT orgY )
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003219{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003220 HDC hdc;
3221 RECT rectBar;
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003222 WND *wndPtr;
3223 LPPOPUPMENU lppop;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003224 UINT retvalue;
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003225
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003226 TRACE("HWND 0x%x, width %d, at (%d, %d).\n",
Juergen Schmied78513941999-04-18 14:40:32 +00003227 hwnd, menubarWidth, orgX, orgY );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00003228
Juergen Schmied78513941999-04-18 14:40:32 +00003229 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
3230 return 0;
3231
Gerard Patel3e629742000-01-17 22:22:16 +00003232 if (!(lppop = MENU_GetMenu((HMENU16)wndPtr->wIDmenu)))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003233 {
Juergen Schmied78513941999-04-18 14:40:32 +00003234 WIN_ReleaseWndPtr(wndPtr);
3235 return 0;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003236 }
Juergen Schmied78513941999-04-18 14:40:32 +00003237
Alexandre Julliarda3960291999-02-26 11:11:13 +00003238 hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_WINDOW );
Juergen Schmied78513941999-04-18 14:40:32 +00003239 SelectObject( hdc, hMenuFont);
Marcus Meissnerddca3151999-05-22 11:33:23 +00003240 SetRect(&rectBar, orgX, orgY, orgX+menubarWidth, orgY+GetSystemMetrics(SM_CYMENU));
Juergen Schmied78513941999-04-18 14:40:32 +00003241 MENU_MenuBarCalcSize( hdc, &rectBar, lppop, hwnd );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003242 ReleaseDC( hwnd, hdc );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003243 retvalue = lppop->Height;
3244 WIN_ReleaseWndPtr(wndPtr);
3245 return retvalue;
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003246}
3247
3248
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003249/*******************************************************************
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003250 * ChangeMenu16 (USER.153)
Alexandre Julliard401710d1993-09-04 10:09:32 +00003251 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003252BOOL16 WINAPI ChangeMenu16( HMENU16 hMenu, UINT16 pos, SEGPTR data,
3253 UINT16 id, UINT16 flags )
Alexandre Julliard401710d1993-09-04 10:09:32 +00003254{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003255 TRACE("menu=%04x pos=%d data=%08lx id=%04x flags=%04x\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +00003256 hMenu, pos, (DWORD)data, id, flags );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003257 if (flags & MF_APPEND) return AppendMenu16( hMenu, flags & ~MF_APPEND,
3258 id, data );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003259
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003260 /* FIXME: Word passes the item id in 'pos' and 0 or 0xffff as id */
3261 /* for MF_DELETE. We should check the parameters for all others */
3262 /* MF_* actions also (anybody got a doc on ChangeMenu?). */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003263
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003264 if (flags & MF_DELETE) return DeleteMenu16(hMenu, pos, flags & ~MF_DELETE);
3265 if (flags & MF_CHANGE) return ModifyMenu16(hMenu, pos, flags & ~MF_CHANGE,
3266 id, data );
3267 if (flags & MF_REMOVE) return RemoveMenu16(hMenu,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003268 flags & MF_BYPOSITION ? pos : id,
3269 flags & ~MF_REMOVE );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003270 /* Default: MF_INSERT */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003271 return InsertMenu16( hMenu, pos, flags, id, data );
3272}
3273
3274
3275/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003276 * ChangeMenuA (USER32.23)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003277 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003278BOOL WINAPI ChangeMenuA( HMENU hMenu, UINT pos, LPCSTR data,
3279 UINT id, UINT flags )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003280{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003281 TRACE("menu=%08x pos=%d data=%08lx id=%08x flags=%08x\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003282 hMenu, pos, (DWORD)data, id, flags );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003283 if (flags & MF_APPEND) return AppendMenuA( hMenu, flags & ~MF_APPEND,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003284 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003285 if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
3286 if (flags & MF_CHANGE) return ModifyMenuA(hMenu, pos, flags & ~MF_CHANGE,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003287 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003288 if (flags & MF_REMOVE) return RemoveMenu( hMenu,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003289 flags & MF_BYPOSITION ? pos : id,
3290 flags & ~MF_REMOVE );
3291 /* Default: MF_INSERT */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003292 return InsertMenuA( hMenu, pos, flags, id, data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003293}
3294
3295
3296/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003297 * ChangeMenuW (USER32.24)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003298 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003299BOOL WINAPI ChangeMenuW( HMENU hMenu, UINT pos, LPCWSTR data,
3300 UINT id, UINT flags )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003301{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003302 TRACE("menu=%08x pos=%d data=%08lx id=%08x flags=%08x\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003303 hMenu, pos, (DWORD)data, id, flags );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003304 if (flags & MF_APPEND) return AppendMenuW( hMenu, flags & ~MF_APPEND,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003305 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003306 if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
3307 if (flags & MF_CHANGE) return ModifyMenuW(hMenu, pos, flags & ~MF_CHANGE,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003308 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003309 if (flags & MF_REMOVE) return RemoveMenu( hMenu,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003310 flags & MF_BYPOSITION ? pos : id,
3311 flags & ~MF_REMOVE );
3312 /* Default: MF_INSERT */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003313 return InsertMenuW( hMenu, pos, flags, id, data );
Alexandre Julliard401710d1993-09-04 10:09:32 +00003314}
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003315
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003316
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003317/*******************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003318 * CheckMenuItem16 (USER.154)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003319 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003320BOOL16 WINAPI CheckMenuItem16( HMENU16 hMenu, UINT16 id, UINT16 flags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003321{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003322 return (BOOL16)CheckMenuItem( hMenu, id, flags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003323}
3324
3325
3326/*******************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00003327 * CheckMenuItem (USER32.46)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003328 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003329DWORD WINAPI CheckMenuItem( HMENU hMenu, UINT id, UINT flags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003330{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003331 MENUITEM *item;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003332 DWORD ret;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003333
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003334 TRACE("menu=%04x id=%04x flags=%04x\n", hMenu, id, flags );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003335 if (!(item = MENU_FindItem( &hMenu, &id, flags ))) return -1;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003336 ret = item->fState & MF_CHECKED;
3337 if (flags & MF_CHECKED) item->fState |= MF_CHECKED;
3338 else item->fState &= ~MF_CHECKED;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003339 return ret;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003340}
3341
3342
3343/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003344 * EnableMenuItem16 (USER.155)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003345 */
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003346UINT16 WINAPI EnableMenuItem16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003347{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003348 return EnableMenuItem( hMenu, wItemID, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003349}
3350
3351
3352/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003353 * EnableMenuItem (USER32.170)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003354 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003355UINT WINAPI EnableMenuItem( HMENU hMenu, UINT wItemID, UINT wFlags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003356{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003357 UINT oldflags;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003358 MENUITEM *item;
Pascal Lessardd814bb61999-07-31 13:02:02 +00003359 POPUPMENU *menu;
Alexandre Julliardf7207251994-07-23 07:57:48 +00003360
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003361 TRACE("(%04x, %04X, %04X) !\n",
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003362 hMenu, wItemID, wFlags);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003363
Pascal Lessardd814bb61999-07-31 13:02:02 +00003364 /* Get the Popupmenu to access the owner menu */
Gerard Patel3e629742000-01-17 22:22:16 +00003365 if (!(menu = MENU_GetMenu(hMenu)))
Pascal Lessardd814bb61999-07-31 13:02:02 +00003366 return (UINT)-1;
3367
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003368 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags )))
Alexandre Julliarda3960291999-02-26 11:11:13 +00003369 return (UINT)-1;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003370
3371 oldflags = item->fState & (MF_GRAYED | MF_DISABLED);
3372 item->fState ^= (oldflags ^ wFlags) & (MF_GRAYED | MF_DISABLED);
Pascal Lessardd814bb61999-07-31 13:02:02 +00003373
3374 /* In win95 if the close item in the system menu change update the close button */
3375 if (TWEAK_WineLook == WIN95_LOOK)
3376 if((item->wID == SC_CLOSE) && (oldflags != wFlags))
3377 {
3378 if (menu->hSysMenuOwner != 0)
3379 {
3380 POPUPMENU* parentMenu;
3381
3382 /* Get the parent menu to access*/
Gerard Patel3e629742000-01-17 22:22:16 +00003383 if (!(parentMenu = MENU_GetMenu(menu->hSysMenuOwner)))
Pascal Lessardd814bb61999-07-31 13:02:02 +00003384 return (UINT)-1;
3385
3386 /* Refresh the frame to reflect the change*/
3387 SetWindowPos(parentMenu->hWnd, 0, 0, 0, 0, 0,
Stephane Lussiera833f631999-08-21 14:46:06 +00003388 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
Pascal Lessardd814bb61999-07-31 13:02:02 +00003389 }
3390 }
3391
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003392 return oldflags;
Alexandre Julliard1f579291994-05-25 16:25:21 +00003393}
3394
3395
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00003396/*******************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003397 * GetMenuString16 (USER.161)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003398 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003399INT16 WINAPI GetMenuString16( HMENU16 hMenu, UINT16 wItemID,
3400 LPSTR str, INT16 nMaxSiz, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003401{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003402 return GetMenuStringA( hMenu, wItemID, str, nMaxSiz, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003403}
3404
3405
3406/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003407 * GetMenuStringA (USER32.268)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003408 */
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00003409INT WINAPI GetMenuStringA(
3410 HMENU hMenu, /* [in] menuhandle */
3411 UINT wItemID, /* [in] menu item (dep. on wFlags) */
3412 LPSTR str, /* [out] outbuffer. If NULL, func returns entry length*/
3413 INT nMaxSiz, /* [in] length of buffer. if 0, func returns entry len*/
3414 UINT wFlags /* [in] MF_ flags */
3415) {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003416 MENUITEM *item;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00003417
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003418 TRACE("menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00003419 hMenu, wItemID, str, nMaxSiz, wFlags );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003420 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003421 if (!IS_STRING_ITEM(item->fType)) return 0;
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00003422 if (!str || !nMaxSiz) return strlen(item->text);
3423 str[0] = '\0';
Alexandre Julliarda3960291999-02-26 11:11:13 +00003424 lstrcpynA( str, item->text, nMaxSiz );
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003425 TRACE("returning '%s'\n", str );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003426 return strlen(str);
Alexandre Julliard1f579291994-05-25 16:25:21 +00003427}
3428
3429
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003430/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003431 * GetMenuStringW (USER32.269)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003432 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003433INT WINAPI GetMenuStringW( HMENU hMenu, UINT wItemID,
3434 LPWSTR str, INT nMaxSiz, UINT wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003435{
3436 MENUITEM *item;
3437
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003438 TRACE("menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003439 hMenu, wItemID, str, nMaxSiz, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003440 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003441 if (!IS_STRING_ITEM(item->fType)) return 0;
Marcus Meissnercb3c7bf2000-01-08 22:25:57 +00003442 if (!str || !nMaxSiz) return strlen(item->text);
3443 str[0] = '\0';
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003444 lstrcpynAtoW( str, item->text, nMaxSiz );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003445 return lstrlenW(str);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003446}
3447
3448
3449/**********************************************************************
3450 * HiliteMenuItem16 (USER.162)
3451 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003452BOOL16 WINAPI HiliteMenuItem16( HWND16 hWnd, HMENU16 hMenu, UINT16 wItemID,
3453 UINT16 wHilite )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003454{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003455 return HiliteMenuItem( hWnd, hMenu, wItemID, wHilite );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003456}
3457
3458
3459/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003460 * HiliteMenuItem (USER32.318)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003461 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003462BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
3463 UINT wHilite )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003464{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003465 LPPOPUPMENU menu;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003466 TRACE("(%04x, %04x, %04x, %04x);\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +00003467 hWnd, hMenu, wItemID, wHilite);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003468 if (!MENU_FindItem( &hMenu, &wItemID, wHilite )) return FALSE;
Gerard Patel3e629742000-01-17 22:22:16 +00003469 if (!(menu = MENU_GetMenu(hMenu))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003470 if (menu->FocusedItem == wItemID) return TRUE;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003471 MENU_HideSubPopups( hWnd, hMenu, FALSE );
Rein Klazes80c924f1999-12-12 19:40:46 +00003472 MENU_SelectItem( hWnd, hMenu, wItemID, TRUE, 0 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003473 return TRUE;
Alexandre Julliard1f579291994-05-25 16:25:21 +00003474}
3475
3476
3477/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003478 * GetMenuState16 (USER.250)
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00003479 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003480UINT16 WINAPI GetMenuState16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003481{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003482 return GetMenuState( hMenu, wItemID, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003483}
3484
3485
3486/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00003487 * GetMenuState (USER32.267)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003488 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003489UINT WINAPI GetMenuState( HMENU hMenu, UINT wItemID, UINT wFlags )
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00003490{
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003491 MENUITEM *item;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003492 TRACE("(menu=%04x, id=%04x, flags=%04x);\n",
Alexandre Julliardaca05781994-10-17 18:12:41 +00003493 hMenu, wItemID, wFlags);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003494 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return -1;
Alexandre Julliard03468f71998-02-15 19:40:49 +00003495 debug_print_menuitem (" item: ", item, "");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003496 if (item->fType & MF_POPUP)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003497 {
Gerard Patel3e629742000-01-17 22:22:16 +00003498 POPUPMENU *menu = MENU_GetMenu( item->hSubMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003499 if (!menu) return -1;
Alexandre Julliard829fe321998-07-26 14:27:39 +00003500 else return (menu->nItems << 8) | ((item->fState|item->fType) & 0xff);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003501 }
Alexandre Julliard889f7421997-04-15 17:19:52 +00003502 else
Alexandre Julliard491502b1997-11-01 19:08:16 +00003503 {
Alexandre Julliard829fe321998-07-26 14:27:39 +00003504 /* We used to (from way back then) mask the result to 0xff. */
3505 /* I don't know why and it seems wrong as the documented */
3506 /* return flag MF_SEPARATOR is outside that mask. */
3507 return (item->fType | item->fState);
Alexandre Julliard491502b1997-11-01 19:08:16 +00003508 }
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00003509}
3510
3511
3512/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003513 * GetMenuItemCount16 (USER.263)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003514 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003515INT16 WINAPI GetMenuItemCount16( HMENU16 hMenu )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003516{
Gerard Patel3e629742000-01-17 22:22:16 +00003517 LPPOPUPMENU menu = MENU_GetMenu(hMenu);
3518 if (!menu) return -1;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003519 TRACE("(%04x) returning %d\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003520 hMenu, menu->nItems );
3521 return menu->nItems;
Alexandre Julliard1f579291994-05-25 16:25:21 +00003522}
3523
3524
3525/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003526 * GetMenuItemCount (USER32.262)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003527 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003528INT WINAPI GetMenuItemCount( HMENU hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003529{
Gerard Patel3e629742000-01-17 22:22:16 +00003530 LPPOPUPMENU menu = MENU_GetMenu(hMenu);
3531 if (!menu) return -1;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003532 TRACE("(%04x) returning %d\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003533 hMenu, menu->nItems );
3534 return menu->nItems;
3535}
3536
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003537/**********************************************************************
3538 * GetMenuItemID16 (USER.264)
3539 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003540UINT16 WINAPI GetMenuItemID16( HMENU16 hMenu, INT16 nPos )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003541{
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003542 return (UINT16) GetMenuItemID (hMenu, nPos);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003543}
3544
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003545/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003546 * GetMenuItemID (USER32.263)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003547 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003548UINT WINAPI GetMenuItemID( HMENU hMenu, INT nPos )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003549{
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003550 MENUITEM * lpmi;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003551
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003552 if (!(lpmi = MENU_FindItem(&hMenu,&nPos,MF_BYPOSITION))) return 0;
3553 if (lpmi->fType & MF_POPUP) return -1;
3554 return lpmi->wID;
3555
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003556}
3557
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003558/*******************************************************************
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003559 * InsertMenu16 (USER.410)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003560 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003561BOOL16 WINAPI InsertMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags,
3562 UINT16 id, SEGPTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003563{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003564 UINT pos32 = (UINT)pos;
3565 if ((pos == (UINT16)-1) && (flags & MF_BYPOSITION)) pos32 = (UINT)-1;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003566 if (IS_STRING_ITEM(flags) && data)
Alexandre Julliarda3960291999-02-26 11:11:13 +00003567 return InsertMenuA( hMenu, pos32, flags, id,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003568 (LPSTR)PTR_SEG_TO_LIN(data) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003569 return InsertMenuA( hMenu, pos32, flags, id, (LPSTR)data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003570}
3571
3572
3573/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003574 * InsertMenuA (USER32.322)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003575 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003576BOOL WINAPI InsertMenuA( HMENU hMenu, UINT pos, UINT flags,
3577 UINT id, LPCSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003578{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003579 MENUITEM *item;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00003580
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003581 if (IS_STRING_ITEM(flags) && str)
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003582 TRACE("hMenu %04x, pos %d, flags %08x, "
Alexandre Julliardd37eb361997-07-20 16:23:21 +00003583 "id %04x, str '%s'\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003584 hMenu, pos, flags, id, str );
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003585 else TRACE("hMenu %04x, pos %d, flags %08x, "
Alexandre Julliardd37eb361997-07-20 16:23:21 +00003586 "id %04x, str %08lx (not a string)\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003587 hMenu, pos, flags, id, (DWORD)str );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003588
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003589 if (!(item = MENU_InsertItem( hMenu, pos, flags ))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003590
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003591 if (!(MENU_SetItemData( item, flags, id, str )))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003592 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003593 RemoveMenu( hMenu, pos, flags );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00003594 return FALSE;
3595 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003596
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003597 if (flags & MF_POPUP) /* Set the MF_POPUP flag on the popup-menu */
Gerard Patel3e629742000-01-17 22:22:16 +00003598 (MENU_GetMenu((HMENU16)id))->wFlags |= MF_POPUP;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003599
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003600 item->hCheckBit = item->hUnCheckBit = 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003601 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003602}
3603
3604
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003605/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003606 * InsertMenuW (USER32.325)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003607 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003608BOOL WINAPI InsertMenuW( HMENU hMenu, UINT pos, UINT flags,
3609 UINT id, LPCWSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003610{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003611 BOOL ret;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003612
3613 if (IS_STRING_ITEM(flags) && str)
3614 {
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003615 LPSTR newstr = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003616 ret = InsertMenuA( hMenu, pos, flags, id, newstr );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003617 HeapFree( GetProcessHeap(), 0, newstr );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003618 return ret;
3619 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00003620 else return InsertMenuA( hMenu, pos, flags, id, (LPCSTR)str );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003621}
3622
3623
3624/*******************************************************************
3625 * AppendMenu16 (USER.411)
3626 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003627BOOL16 WINAPI AppendMenu16(HMENU16 hMenu, UINT16 flags, UINT16 id, SEGPTR data)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003628{
3629 return InsertMenu16( hMenu, -1, flags | MF_BYPOSITION, id, data );
3630}
3631
3632
3633/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003634 * AppendMenuA (USER32.5)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003635 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003636BOOL WINAPI AppendMenuA( HMENU hMenu, UINT flags,
3637 UINT id, LPCSTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003638{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003639 return InsertMenuA( hMenu, -1, flags | MF_BYPOSITION, id, data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003640}
3641
3642
3643/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003644 * AppendMenuW (USER32.6)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003645 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003646BOOL WINAPI AppendMenuW( HMENU hMenu, UINT flags,
3647 UINT id, LPCWSTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003648{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003649 return InsertMenuW( hMenu, -1, flags | MF_BYPOSITION, id, data );
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003650}
3651
3652
3653/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003654 * RemoveMenu16 (USER.412)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003655 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003656BOOL16 WINAPI RemoveMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003657{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003658 return RemoveMenu( hMenu, nPos, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003659}
3660
3661
3662/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00003663 * RemoveMenu (USER32.441)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003664 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003665BOOL WINAPI RemoveMenu( HMENU hMenu, UINT nPos, UINT wFlags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003666{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003667 LPPOPUPMENU menu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003668 MENUITEM *item;
3669
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003670 TRACE("(menu=%04x pos=%04x flags=%04x)\n",hMenu, nPos, wFlags);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003671 if (!(item = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
Gerard Patel3e629742000-01-17 22:22:16 +00003672 if (!(menu = MENU_GetMenu(hMenu))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003673
3674 /* Remove item */
3675
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003676 MENU_FreeItemData( item );
3677
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003678 if (--menu->nItems == 0)
3679 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003680 HeapFree( SystemHeap, 0, menu->items );
3681 menu->items = NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003682 }
3683 else
3684 {
3685 while(nPos < menu->nItems)
3686 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003687 *item = *(item+1);
3688 item++;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003689 nPos++;
3690 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003691 menu->items = HeapReAlloc( SystemHeap, 0, menu->items,
3692 menu->nItems * sizeof(MENUITEM) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003693 }
3694 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003695}
3696
3697
3698/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003699 * DeleteMenu16 (USER.413)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003700 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003701BOOL16 WINAPI DeleteMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003702{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003703 return DeleteMenu( hMenu, nPos, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003704}
3705
3706
3707/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003708 * DeleteMenu (USER32.129)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003709 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003710BOOL WINAPI DeleteMenu( HMENU hMenu, UINT nPos, UINT wFlags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003711{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003712 MENUITEM *item = MENU_FindItem( &hMenu, &nPos, wFlags );
3713 if (!item) return FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003714 if (item->fType & MF_POPUP) DestroyMenu( item->hSubMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003715 /* nPos is now the position of the item */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003716 RemoveMenu( hMenu, nPos, wFlags | MF_BYPOSITION );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003717 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003718}
3719
3720
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003721/*******************************************************************
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003722 * ModifyMenu16 (USER.414)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003723 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003724BOOL16 WINAPI ModifyMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags,
3725 UINT16 id, SEGPTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003726{
3727 if (IS_STRING_ITEM(flags))
Alexandre Julliarda3960291999-02-26 11:11:13 +00003728 return ModifyMenuA( hMenu, pos, flags, id,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003729 (LPSTR)PTR_SEG_TO_LIN(data) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003730 return ModifyMenuA( hMenu, pos, flags, id, (LPSTR)data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003731}
3732
3733
3734/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003735 * ModifyMenuA (USER32.397)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003736 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003737BOOL WINAPI ModifyMenuA( HMENU hMenu, UINT pos, UINT flags,
3738 UINT id, LPCSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003739{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003740 MENUITEM *item;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003741
3742 if (IS_STRING_ITEM(flags))
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00003743 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003744 TRACE("%04x %d %04x %04x '%s'\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003745 hMenu, pos, flags, id, str ? str : "#NULL#" );
3746 if (!str) return FALSE;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00003747 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003748 else
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003749 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003750 TRACE("%04x %d %04x %04x %08lx\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003751 hMenu, pos, flags, id, (DWORD)str );
3752 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003753
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003754 if (!(item = MENU_FindItem( &hMenu, &pos, flags ))) return FALSE;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003755 return MENU_SetItemData( item, flags, id, str );
3756}
3757
3758
3759/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003760 * ModifyMenuW (USER32.398)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003761 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003762BOOL WINAPI ModifyMenuW( HMENU hMenu, UINT pos, UINT flags,
3763 UINT id, LPCWSTR str )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003764{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003765 BOOL ret;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003766
3767 if (IS_STRING_ITEM(flags) && str)
3768 {
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003769 LPSTR newstr = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003770 ret = ModifyMenuA( hMenu, pos, flags, id, newstr );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003771 HeapFree( GetProcessHeap(), 0, newstr );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003772 return ret;
3773 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00003774 else return ModifyMenuA( hMenu, pos, flags, id, (LPCSTR)str );
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003775}
3776
3777
3778/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003779 * CreatePopupMenu16 (USER.415)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003780 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003781HMENU16 WINAPI CreatePopupMenu16(void)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003782{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003783 return CreatePopupMenu();
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003784}
3785
3786
3787/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003788 * CreatePopupMenu (USER32.82)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003789 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003790HMENU WINAPI CreatePopupMenu(void)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003791{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003792 HMENU hmenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003793 POPUPMENU *menu;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003794
Alexandre Julliarda3960291999-02-26 11:11:13 +00003795 if (!(hmenu = CreateMenu())) return 0;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00003796 menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003797 menu->wFlags |= MF_POPUP;
Pascal Lessard2eb0a301999-09-03 16:38:52 +00003798 menu->bTimeToHide = FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003799 return hmenu;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003800}
3801
3802
3803/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003804 * GetMenuCheckMarkDimensions (USER.417) (USER32.258)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003805 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003806DWORD WINAPI GetMenuCheckMarkDimensions(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003807{
Alexandre Julliardf7207251994-07-23 07:57:48 +00003808 return MAKELONG( check_bitmap_width, check_bitmap_height );
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003809}
3810
3811
3812/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003813 * SetMenuItemBitmaps16 (USER.418)
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003814 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003815BOOL16 WINAPI SetMenuItemBitmaps16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags,
3816 HBITMAP16 hNewUnCheck, HBITMAP16 hNewCheck)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003817{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003818 return SetMenuItemBitmaps( hMenu, nPos, wFlags, hNewUnCheck, hNewCheck );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003819}
3820
3821
3822/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003823 * SetMenuItemBitmaps (USER32.490)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003824 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003825BOOL WINAPI SetMenuItemBitmaps( HMENU hMenu, UINT nPos, UINT wFlags,
3826 HBITMAP hNewUnCheck, HBITMAP hNewCheck)
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003827{
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003828 MENUITEM *item;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003829 TRACE("(%04x, %04x, %04x, %04x, %04x)\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003830 hMenu, nPos, wFlags, hNewCheck, hNewUnCheck);
3831 if (!(item = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003832
3833 if (!hNewCheck && !hNewUnCheck)
3834 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003835 item->fState &= ~MF_USECHECKBITMAPS;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003836 }
3837 else /* Install new bitmaps */
3838 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003839 item->hCheckBit = hNewCheck;
3840 item->hUnCheckBit = hNewUnCheck;
3841 item->fState |= MF_USECHECKBITMAPS;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003842 }
3843 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003844}
3845
3846
3847/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003848 * CreateMenu16 (USER.151)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003849 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003850HMENU16 WINAPI CreateMenu16(void)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003851{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003852 return CreateMenu();
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003853}
3854
3855
3856/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00003857 * CreateMenu (USER32.81)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003858 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003859HMENU WINAPI CreateMenu(void)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003860{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003861 HMENU hMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003862 LPPOPUPMENU menu;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003863 if (!(hMenu = USER_HEAP_ALLOC( sizeof(POPUPMENU) ))) return 0;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00003864 menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
Juergen Schmied78513941999-04-18 14:40:32 +00003865
3866 ZeroMemory(menu, sizeof(POPUPMENU));
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003867 menu->wMagic = MENU_MAGIC;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003868 menu->FocusedItem = NO_SELECTED_ITEM;
Pascal Lessard2eb0a301999-09-03 16:38:52 +00003869 menu->bTimeToHide = FALSE;
Juergen Schmied78513941999-04-18 14:40:32 +00003870
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003871 TRACE("return %04x\n", hMenu );
Pascal Lessardd9ab1f31999-05-29 10:56:43 +00003872
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003873 return hMenu;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003874}
3875
3876
3877/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003878 * DestroyMenu16 (USER.152)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003879 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003880BOOL16 WINAPI DestroyMenu16( HMENU16 hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003881{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003882 return DestroyMenu( hMenu );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003883}
3884
3885
3886/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003887 * DestroyMenu (USER32.134)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003888 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003889BOOL WINAPI DestroyMenu( HMENU hMenu )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003890{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00003891 TRACE("(%04x)\n", hMenu);
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003892
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003893 /* Silently ignore attempts to destroy default system popup */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003894
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003895 if (hMenu && hMenu != MENU_DefSysPopup)
Alexandre Julliardff8331e1995-09-18 11:19:54 +00003896 {
Gerard Patel3e629742000-01-17 22:22:16 +00003897 LPPOPUPMENU lppop = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003898 WND *pTPWnd = MENU_GetTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003899
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003900 if( pTPWnd && (hMenu == *(HMENU*)pTPWnd->wExtra) )
3901 *(UINT*)pTPWnd->wExtra = 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003902
Gerard Patel3e629742000-01-17 22:22:16 +00003903 if (!IS_A_MENU(lppop)) lppop = NULL;
3904 if ( lppop )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003905 {
3906 lppop->wMagic = 0; /* Mark it as destroyed */
3907
3908 if ((lppop->wFlags & MF_POPUP) && lppop->hWnd &&
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003909 (!pTPWnd || (lppop->hWnd != pTPWnd->hwndSelf)))
Alexandre Julliarda3960291999-02-26 11:11:13 +00003910 DestroyWindow( lppop->hWnd );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003911
3912 if (lppop->items) /* recursively destroy submenus */
3913 {
3914 int i;
3915 MENUITEM *item = lppop->items;
3916 for (i = lppop->nItems; i > 0; i--, item++)
3917 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003918 if (item->fType & MF_POPUP) DestroyMenu(item->hSubMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003919 MENU_FreeItemData( item );
3920 }
3921 HeapFree( SystemHeap, 0, lppop->items );
3922 }
3923 USER_HEAP_FREE( hMenu );
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +00003924 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003925 }
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +00003926 else
3927 {
3928 MENU_ReleaseTopPopupWnd();
3929 return FALSE;
3930 }
Alexandre Julliardff8331e1995-09-18 11:19:54 +00003931 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003932 return (hMenu != MENU_DefSysPopup);
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003933}
3934
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003935
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003936/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003937 * GetSystemMenu16 (USER.156)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003938 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003939HMENU16 WINAPI GetSystemMenu16( HWND16 hWnd, BOOL16 bRevert )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003940{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003941 return GetSystemMenu( hWnd, bRevert );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003942}
3943
3944
3945/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003946 * GetSystemMenu (USER32.291)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003947 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003948HMENU WINAPI GetSystemMenu( HWND hWnd, BOOL bRevert )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003949{
Alexandre Julliardb7258be1995-09-01 15:57:28 +00003950 WND *wndPtr = WIN_FindWndPtr( hWnd );
Eric Pouech562309a1999-08-21 12:59:44 +00003951 HMENU retvalue = 0;
Alexandre Julliardb7258be1995-09-01 15:57:28 +00003952
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003953 if (wndPtr)
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003954 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003955 if( wndPtr->hSysMenu )
3956 {
3957 if( bRevert )
3958 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003959 DestroyMenu(wndPtr->hSysMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003960 wndPtr->hSysMenu = 0;
3961 }
3962 else
3963 {
Gerard Patel3e629742000-01-17 22:22:16 +00003964 POPUPMENU *menu = MENU_GetMenu( wndPtr->hSysMenu );
3965 if( menu )
Eric Pouech562309a1999-08-21 12:59:44 +00003966 {
3967 if( menu->nItems > 0 && menu->items[0].hSubMenu == MENU_DefSysPopup )
3968 menu->items[0].hSubMenu = MENU_CopySysPopup();
3969 }
3970 else
3971 {
3972 WARN("Current sys-menu (%04x) of wnd %04x is broken\n",
3973 wndPtr->hSysMenu, hWnd);
3974 wndPtr->hSysMenu = 0;
3975 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003976 }
3977 }
3978
3979 if(!wndPtr->hSysMenu && (wndPtr->dwStyle & WS_SYSMENU) )
Alexandre Julliarda3960291999-02-26 11:11:13 +00003980 wndPtr->hSysMenu = MENU_GetSysMenu( hWnd, (HMENU)(-1) );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003981
3982 if( wndPtr->hSysMenu )
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003983 {
Eric Pouech562309a1999-08-21 12:59:44 +00003984 POPUPMENU *menu;
3985 retvalue = GetSubMenu16(wndPtr->hSysMenu, 0);
Pascal Lessardd814bb61999-07-31 13:02:02 +00003986
3987 /* Store the dummy sysmenu handle to facilitate the refresh */
3988 /* of the close button if the SC_CLOSE item change */
Gerard Patel3e629742000-01-17 22:22:16 +00003989 menu = MENU_GetMenu(retvalue);
3990 if ( menu )
Eric Pouech562309a1999-08-21 12:59:44 +00003991 menu->hSysMenuOwner = wndPtr->hSysMenu;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003992 }
3993 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003994 }
Eric Pouech562309a1999-08-21 12:59:44 +00003995 return retvalue;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003996}
3997
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003998
3999/*******************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004000 * SetSystemMenu16 (USER.280)
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00004001 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004002BOOL16 WINAPI SetSystemMenu16( HWND16 hwnd, HMENU16 hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004003{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004004 return SetSystemMenu( hwnd, hMenu );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004005}
4006
4007
4008/*******************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004009 * SetSystemMenu (USER32.508)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004010 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004011BOOL WINAPI SetSystemMenu( HWND hwnd, HMENU hMenu )
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00004012{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004013 WND *wndPtr = WIN_FindWndPtr(hwnd);
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00004014
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004015 if (wndPtr)
4016 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004017 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004018 wndPtr->hSysMenu = MENU_GetSysMenu( hwnd, hMenu );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004019 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004020 return TRUE;
4021 }
4022 return FALSE;
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00004023}
4024
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004025
4026/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004027 * GetMenu16 (USER.157)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004028 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004029HMENU16 WINAPI GetMenu16( HWND16 hWnd )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004030{
Richard Cohen56753621999-09-19 14:08:13 +00004031 return (HMENU16)GetMenu(hWnd);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004032}
4033
4034
4035/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004036 * GetMenu (USER32.257)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004037 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004038HMENU WINAPI GetMenu( HWND hWnd )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004039{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004040 HMENU retvalue;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004041 WND * wndPtr = WIN_FindWndPtr(hWnd);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004042 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004043 {
4044 retvalue = (HMENU)wndPtr->wIDmenu;
4045 goto END;
4046 }
4047 retvalue = 0;
4048END:
4049 WIN_ReleaseWndPtr(wndPtr);
4050 return retvalue;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004051}
4052
4053
4054/**********************************************************************
4055 * SetMenu16 (USER.158)
4056 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004057BOOL16 WINAPI SetMenu16( HWND16 hWnd, HMENU16 hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004058{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004059 return SetMenu( hWnd, hMenu );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004060}
4061
4062
4063/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004064 * SetMenu (USER32.487)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004065 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004066BOOL WINAPI SetMenu( HWND hWnd, HMENU hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004067{
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004068 WND * wndPtr = WIN_FindWndPtr(hWnd);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004069
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004070 TRACE("(%04x, %04x);\n", hWnd, hMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004071
Richard Cohen56753621999-09-19 14:08:13 +00004072 if (hMenu && !IsMenu(hMenu))
4073 {
4074 WARN("hMenu is not a menu handle\n");
4075 return FALSE;
4076 }
4077
4078
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004079 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD))
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004080 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004081 if (GetCapture() == hWnd) ReleaseCapture();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004082
Alexandre Julliarda3960291999-02-26 11:11:13 +00004083 wndPtr->wIDmenu = (UINT)hMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004084 if (hMenu != 0)
4085 {
4086 LPPOPUPMENU lpmenu;
4087
Gerard Patel3e629742000-01-17 22:22:16 +00004088 if (!(lpmenu = MENU_GetMenu(hMenu)))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004089 {
4090 WIN_ReleaseWndPtr(wndPtr);
4091 return FALSE;
4092 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004093 lpmenu->hWnd = hWnd;
4094 lpmenu->wFlags &= ~MF_POPUP; /* Can't be a popup */
4095 lpmenu->Height = 0; /* Make sure we recalculate the size */
4096 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00004097 if (IsWindowVisible(hWnd))
4098 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
Alexandre Julliard01d63461997-01-20 19:43:45 +00004099 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004100 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004101 return TRUE;
4102 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004103 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00004104 return FALSE;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004105}
4106
4107
Alexandre Julliardd18872d1994-05-11 12:18:19 +00004108
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004109/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004110 * GetSubMenu16 (USER.159)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004111 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004112HMENU16 WINAPI GetSubMenu16( HMENU16 hMenu, INT16 nPos )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004113{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004114 return GetSubMenu( hMenu, nPos );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004115}
4116
4117
4118/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004119 * GetSubMenu (USER32.288)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004120 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004121HMENU WINAPI GetSubMenu( HMENU hMenu, INT nPos )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004122{
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00004123 MENUITEM * lpmi;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004124
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00004125 if (!(lpmi = MENU_FindItem(&hMenu,&nPos,MF_BYPOSITION))) return 0;
4126 if (!(lpmi->fType & MF_POPUP)) return 0;
4127 return lpmi->hSubMenu;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00004128}
4129
4130
4131/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004132 * DrawMenuBar16 (USER.160)
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004133 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004134void WINAPI DrawMenuBar16( HWND16 hWnd )
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004135{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004136 DrawMenuBar( hWnd );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004137}
Alexandre Julliardf7207251994-07-23 07:57:48 +00004138
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004139
4140/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004141 * DrawMenuBar (USER32.161)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004142 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004143BOOL WINAPI DrawMenuBar( HWND hWnd )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004144{
4145 LPPOPUPMENU lppop;
4146 WND *wndPtr = WIN_FindWndPtr(hWnd);
4147 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && wndPtr->wIDmenu)
4148 {
Gerard Patel3e629742000-01-17 22:22:16 +00004149 lppop = MENU_GetMenu((HMENU16)wndPtr->wIDmenu);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004150 if (lppop == NULL)
4151 {
4152 WIN_ReleaseWndPtr(wndPtr);
4153 return FALSE;
4154 }
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004155
4156 lppop->Height = 0; /* Make sure we call MENU_MenuBarCalcSize */
Juergen Schmied78513941999-04-18 14:40:32 +00004157 lppop->hwndOwner = hWnd;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004158 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
Alexandre Julliard01d63461997-01-20 19:43:45 +00004159 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004160 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004161 return TRUE;
4162 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00004163 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004164 return FALSE;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004165}
4166
4167
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004168/***********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00004169 * EndMenu (USER.187) (USER32.175)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004170 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004171void WINAPI EndMenu(void)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004172{
Rob Farnumb2007932000-05-23 23:34:17 +00004173 /* if we are in the menu code, and it is active */
4174 if (fEndMenu == FALSE && MENU_IsMenuActive())
4175 {
4176 /* terminate the menu handling code */
4177 fEndMenu = TRUE;
Alex Korobka4f1ac051999-03-28 09:37:57 +00004178
Rob Farnumb2007932000-05-23 23:34:17 +00004179 /* needs to be posted to wakeup the internal menu handler */
4180 /* which will now terminate the menu, in the event that */
4181 /* the main window was minimized, or lost focus, so we */
4182 /* don't end up with an orphaned menu */
4183 PostMessageA( pTopPopupWnd->hwndSelf, WM_CANCELMODE, 0, 0);
4184 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004185}
4186
4187
4188/***********************************************************************
4189 * LookupMenuHandle (USER.217)
4190 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004191HMENU16 WINAPI LookupMenuHandle16( HMENU16 hmenu, INT16 id )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004192{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004193 HMENU hmenu32 = hmenu;
4194 UINT id32 = id;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004195 if (!MENU_FindItem( &hmenu32, &id32, MF_BYCOMMAND )) return 0;
4196 else return hmenu32;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004197}
4198
4199
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004200/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004201 * LoadMenu16 (USER.150)
Alexandre Julliard594997c1995-04-30 10:05:20 +00004202 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004203HMENU16 WINAPI LoadMenu16( HINSTANCE16 instance, SEGPTR name )
Alexandre Julliard594997c1995-04-30 10:05:20 +00004204{
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004205 HRSRC16 hRsrc;
4206 HGLOBAL16 handle;
4207 HMENU16 hMenu;
Alexandre Julliard594997c1995-04-30 10:05:20 +00004208
4209 if (HIWORD(name))
4210 {
4211 char *str = (char *)PTR_SEG_TO_LIN( name );
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004212 TRACE("(%04x,'%s')\n", instance, str );
Alexandre Julliard594997c1995-04-30 10:05:20 +00004213 if (str[0] == '#') name = (SEGPTR)atoi( str + 1 );
4214 }
4215 else
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004216 TRACE("(%04x,%04x)\n",instance,LOWORD(name));
Alexandre Julliard594997c1995-04-30 10:05:20 +00004217
4218 if (!name) return 0;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00004219
4220 /* check for Win32 module */
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00004221 if (HIWORD(instance))
Alexandre Julliarda3960291999-02-26 11:11:13 +00004222 return LoadMenuA(instance,PTR_SEG_TO_LIN(name));
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00004223 instance = GetExePtr( instance );
Alexandre Julliard594997c1995-04-30 10:05:20 +00004224
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00004225 if (!(hRsrc = FindResource16( instance, name, RT_MENU16 ))) return 0;
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004226 if (!(handle = LoadResource16( instance, hRsrc ))) return 0;
4227 hMenu = LoadMenuIndirect16(LockResource16(handle));
4228 FreeResource16( handle );
Alexandre Julliard594997c1995-04-30 10:05:20 +00004229 return hMenu;
4230}
4231
4232
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004233/*****************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004234 * LoadMenuA (USER32.370)
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004235 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004236HMENU WINAPI LoadMenuA( HINSTANCE instance, LPCSTR name )
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004237{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004238 HRSRC hrsrc = FindResourceA( instance, name, RT_MENUA );
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004239 if (!hrsrc) return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004240 return LoadMenuIndirectA( (LPCVOID)LoadResource( instance, hrsrc ));
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004241}
4242
4243
4244/*****************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004245 * LoadMenuW (USER32.373)
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004246 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004247HMENU WINAPI LoadMenuW( HINSTANCE instance, LPCWSTR name )
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004248{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004249 HRSRC hrsrc = FindResourceW( instance, name, RT_MENUW );
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004250 if (!hrsrc) return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004251 return LoadMenuIndirectW( (LPCVOID)LoadResource( instance, hrsrc ));
Alexandre Julliard18f92e71996-07-17 20:02:21 +00004252}
4253
4254
Alexandre Julliard594997c1995-04-30 10:05:20 +00004255/**********************************************************************
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004256 * LoadMenuIndirect16 (USER.220)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00004257 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004258HMENU16 WINAPI LoadMenuIndirect16( LPCVOID template )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00004259{
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00004260 HMENU16 hMenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004261 WORD version, offset;
4262 LPCSTR p = (LPCSTR)template;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00004263
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004264 TRACE("(%p)\n", template );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004265 version = GET_WORD(p);
4266 p += sizeof(WORD);
4267 if (version)
4268 {
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004269 WARN("version must be 0 for Win16\n" );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004270 return 0;
4271 }
4272 offset = GET_WORD(p);
4273 p += sizeof(WORD) + offset;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004274 if (!(hMenu = CreateMenu())) return 0;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004275 if (!MENU_ParseResource( p, hMenu, FALSE ))
Alexandre Julliard7e56f681996-01-31 19:02:28 +00004276 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004277 DestroyMenu( hMenu );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004278 return 0;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00004279 }
4280 return hMenu;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004281}
4282
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004283
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004284/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004285 * LoadMenuIndirectA (USER32.371)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004286 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004287HMENU WINAPI LoadMenuIndirectA( LPCVOID template )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004288{
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00004289 HMENU16 hMenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004290 WORD version, offset;
4291 LPCSTR p = (LPCSTR)template;
4292
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004293 TRACE("%p\n", template );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004294 version = GET_WORD(p);
4295 p += sizeof(WORD);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004296 switch (version)
4297 {
4298 case 0:
4299 offset = GET_WORD(p);
4300 p += sizeof(WORD) + offset;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004301 if (!(hMenu = CreateMenu())) return 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004302 if (!MENU_ParseResource( p, hMenu, TRUE ))
4303 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004304 DestroyMenu( hMenu );
Alexandre Julliard641ee761997-08-04 16:34:36 +00004305 return 0;
4306 }
4307 return hMenu;
4308 case 1:
4309 offset = GET_WORD(p);
4310 p += sizeof(WORD) + offset;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004311 if (!(hMenu = CreateMenu())) return 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004312 if (!MENUEX_ParseResource( p, hMenu))
4313 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004314 DestroyMenu( hMenu );
Alexandre Julliard641ee761997-08-04 16:34:36 +00004315 return 0;
4316 }
4317 return hMenu;
4318 default:
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004319 ERR("version %d not supported.\n", version);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004320 return 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004321 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004322}
4323
4324
4325/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004326 * LoadMenuIndirectW (USER32.372)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004327 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004328HMENU WINAPI LoadMenuIndirectW( LPCVOID template )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004329{
4330 /* FIXME: is there anything different between A and W? */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004331 return LoadMenuIndirectA( template );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004332}
4333
4334
4335/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004336 * IsMenu16 (USER.358)
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004337 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004338BOOL16 WINAPI IsMenu16( HMENU16 hmenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004339{
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004340 LPPOPUPMENU menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hmenu);
4341 return IS_A_MENU(menu);
4342}
4343
4344
4345/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004346 * IsMenu (USER32.346)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004347 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004348BOOL WINAPI IsMenu(HMENU hmenu)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004349{
4350 LPPOPUPMENU menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hmenu);
4351 return IS_A_MENU(menu);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004352}
4353
Alexandre Julliard641ee761997-08-04 16:34:36 +00004354/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004355 * GetMenuItemInfo_common
Alexandre Julliard641ee761997-08-04 16:34:36 +00004356 */
4357
Juergen Schmied78513941999-04-18 14:40:32 +00004358static BOOL GetMenuItemInfo_common ( HMENU hmenu, UINT item, BOOL bypos,
4359 LPMENUITEMINFOA lpmii, BOOL unicode)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004360{
Juergen Schmied78513941999-04-18 14:40:32 +00004361 MENUITEM *menu = MENU_FindItem (&hmenu, &item, bypos? MF_BYPOSITION : 0);
4362
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004363 debug_print_menuitem("GetMenuItemInfo_common: ", menu, "");
Juergen Schmied78513941999-04-18 14:40:32 +00004364
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004365 if (!menu)
4366 return FALSE;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004367
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004368 if (lpmii->fMask & MIIM_TYPE) {
4369 lpmii->fType = menu->fType;
4370 switch (MENU_ITEM_TYPE(menu->fType)) {
Huw D M Davies2d6eaba2000-03-24 19:48:53 +00004371 case MF_STRING:
4372 if (menu->text) {
4373 int len = lstrlenA(menu->text);
4374 if(lpmii->dwTypeData && lpmii->cch) {
4375 if (unicode)
4376 lstrcpynAtoW((LPWSTR) lpmii->dwTypeData, menu->text,
4377 lpmii->cch);
4378 else
4379 lstrcpynA(lpmii->dwTypeData, menu->text, lpmii->cch);
4380 /* if we've copied a substring we return its length */
4381 if(lpmii->cch <= len)
4382 lpmii->cch--;
4383 } else /* return length of string */
4384 lpmii->cch = len;
4385 }
4386 break;
4387 case MF_OWNERDRAW:
4388 case MF_BITMAP:
4389 lpmii->dwTypeData = menu->text;
4390 /* fall through */
4391 default:
4392 lpmii->cch = 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004393 }
Alexandre Julliard641ee761997-08-04 16:34:36 +00004394 }
Juergen Schmied78513941999-04-18 14:40:32 +00004395
4396 if (lpmii->fMask & MIIM_STRING) {
Huw D M Davies2d6eaba2000-03-24 19:48:53 +00004397 if(lpmii->dwTypeData && lpmii->cch) {
4398 if (unicode)
4399 lstrcpynAtoW((LPWSTR) lpmii->dwTypeData, menu->text,
4400 lpmii->cch);
4401 else
4402 lstrcpynA(lpmii->dwTypeData, menu->text, lpmii->cch);
Juergen Schmied78513941999-04-18 14:40:32 +00004403 }
Huw D M Davies2d6eaba2000-03-24 19:48:53 +00004404 lpmii->cch = lstrlenA(menu->text);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004405 }
Juergen Schmied78513941999-04-18 14:40:32 +00004406
4407 if (lpmii->fMask & MIIM_FTYPE)
4408 lpmii->fType = menu->fType;
4409
4410 if (lpmii->fMask & MIIM_BITMAP)
4411 lpmii->hbmpItem = menu->hbmpItem;
4412
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004413 if (lpmii->fMask & MIIM_STATE)
4414 lpmii->fState = menu->fState;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004415
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004416 if (lpmii->fMask & MIIM_ID)
4417 lpmii->wID = menu->wID;
4418
4419 if (lpmii->fMask & MIIM_SUBMENU)
4420 lpmii->hSubMenu = menu->hSubMenu;
4421
4422 if (lpmii->fMask & MIIM_CHECKMARKS) {
4423 lpmii->hbmpChecked = menu->hCheckBit;
4424 lpmii->hbmpUnchecked = menu->hUnCheckBit;
4425 }
4426 if (lpmii->fMask & MIIM_DATA)
4427 lpmii->dwItemData = menu->dwItemData;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004428
4429 return TRUE;
4430}
4431
4432/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004433 * GetMenuItemInfoA (USER32.264)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004434 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004435BOOL WINAPI GetMenuItemInfoA( HMENU hmenu, UINT item, BOOL bypos,
4436 LPMENUITEMINFOA lpmii)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004437{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004438 return GetMenuItemInfo_common (hmenu, item, bypos, lpmii, FALSE);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004439}
4440
4441/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004442 * GetMenuItemInfoW (USER32.265)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004443 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004444BOOL WINAPI GetMenuItemInfoW( HMENU hmenu, UINT item, BOOL bypos,
4445 LPMENUITEMINFOW lpmii)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004446{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004447 return GetMenuItemInfo_common (hmenu, item, bypos,
4448 (LPMENUITEMINFOA)lpmii, TRUE);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004449}
4450
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004451/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004452 * SetMenuItemInfo_common
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004453 */
4454
Alexandre Julliarda3960291999-02-26 11:11:13 +00004455static BOOL SetMenuItemInfo_common(MENUITEM * menu,
4456 const MENUITEMINFOA *lpmii,
4457 BOOL unicode)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004458{
4459 if (!menu) return FALSE;
4460
Juergen Schmied78513941999-04-18 14:40:32 +00004461 if (lpmii->fMask & MIIM_TYPE ) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004462 /* Get rid of old string. */
Juergen Schmied78513941999-04-18 14:40:32 +00004463 if ( IS_STRING_ITEM(menu->fType) && menu->text) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004464 HeapFree(SystemHeap, 0, menu->text);
Juergen Schmied78513941999-04-18 14:40:32 +00004465 menu->text = NULL;
4466 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004467
Juergen Schmied78513941999-04-18 14:40:32 +00004468 /* make only MENU_ITEM_TYPE bits in menu->fType equal lpmii->fType */
4469 menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
4470 menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
Paul Millar39da2221999-04-11 12:08:42 +00004471
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004472 menu->text = lpmii->dwTypeData;
Juergen Schmied78513941999-04-18 14:40:32 +00004473
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004474 if (IS_STRING_ITEM(menu->fType) && menu->text) {
Juergen Schmied78513941999-04-18 14:40:32 +00004475 if (unicode)
4476 menu->text = HEAP_strdupWtoA(SystemHeap, 0, (LPWSTR) lpmii->dwTypeData);
4477 else
4478 menu->text = HEAP_strdupA(SystemHeap, 0, lpmii->dwTypeData);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004479 }
4480 }
Juergen Schmied78513941999-04-18 14:40:32 +00004481
4482 if (lpmii->fMask & MIIM_FTYPE ) {
4483 /* free the string when the type is changing */
4484 if ( (!IS_STRING_ITEM(lpmii->fType)) && IS_STRING_ITEM(menu->fType) && menu->text) {
4485 HeapFree(SystemHeap, 0, menu->text);
4486 menu->text = NULL;
4487 }
4488 menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
4489 menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
4490 }
4491
4492 if (lpmii->fMask & MIIM_STRING ) {
4493 /* free the string when used */
4494 if ( IS_STRING_ITEM(menu->fType) && menu->text) {
4495 HeapFree(SystemHeap, 0, menu->text);
4496 if (unicode)
4497 menu->text = HEAP_strdupWtoA(SystemHeap, 0, (LPWSTR) lpmii->dwTypeData);
4498 else
4499 menu->text = HEAP_strdupA(SystemHeap, 0, lpmii->dwTypeData);
4500 }
4501 }
4502
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004503 if (lpmii->fMask & MIIM_STATE)
Juergen Schmied466a6521999-05-02 11:21:08 +00004504 {
4505 /* fixme: MFS_DEFAULT do we have to reset the other menu items? */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004506 menu->fState = lpmii->fState;
Juergen Schmied466a6521999-05-02 11:21:08 +00004507 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004508
4509 if (lpmii->fMask & MIIM_ID)
4510 menu->wID = lpmii->wID;
4511
Alexandre Julliarda0d77311998-09-13 16:32:00 +00004512 if (lpmii->fMask & MIIM_SUBMENU) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004513 menu->hSubMenu = lpmii->hSubMenu;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00004514 if (menu->hSubMenu) {
Gerard Patel3e629742000-01-17 22:22:16 +00004515 POPUPMENU *subMenu = MENU_GetMenu((UINT16)menu->hSubMenu);
4516 if (subMenu) {
Alexandre Julliarda0d77311998-09-13 16:32:00 +00004517 subMenu->wFlags |= MF_POPUP;
4518 menu->fType |= MF_POPUP;
4519 }
4520 else
4521 /* FIXME: Return an error ? */
4522 menu->fType &= ~MF_POPUP;
4523 }
4524 else
4525 menu->fType &= ~MF_POPUP;
4526 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004527
4528 if (lpmii->fMask & MIIM_CHECKMARKS)
4529 {
Susan Farleyf1d467a2000-05-12 21:59:31 +00004530 if (lpmii->fType & MFT_RADIOCHECK)
4531 menu->fType |= MFT_RADIOCHECK;
4532
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004533 menu->hCheckBit = lpmii->hbmpChecked;
4534 menu->hUnCheckBit = lpmii->hbmpUnchecked;
4535 }
4536 if (lpmii->fMask & MIIM_DATA)
4537 menu->dwItemData = lpmii->dwItemData;
4538
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004539 debug_print_menuitem("SetMenuItemInfo_common: ", menu, "");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004540 return TRUE;
4541}
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004542
4543/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004544 * SetMenuItemInfoA (USER32.491)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004545 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004546BOOL WINAPI SetMenuItemInfoA(HMENU hmenu, UINT item, BOOL bypos,
4547 const MENUITEMINFOA *lpmii)
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004548{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004549 return SetMenuItemInfo_common(MENU_FindItem(&hmenu, &item, bypos? MF_BYPOSITION : 0),
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004550 lpmii, FALSE);
4551}
4552
4553/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004554 * SetMenuItemInfoW (USER32.492)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004555 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004556BOOL WINAPI SetMenuItemInfoW(HMENU hmenu, UINT item, BOOL bypos,
4557 const MENUITEMINFOW *lpmii)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004558{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004559 return SetMenuItemInfo_common(MENU_FindItem(&hmenu, &item, bypos? MF_BYPOSITION : 0),
4560 (const MENUITEMINFOA*)lpmii, TRUE);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004561}
4562
4563/**********************************************************************
Juergen Schmied466a6521999-05-02 11:21:08 +00004564 * SetMenuDefaultItem (USER32.489)
4565 *
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004566 */
Juergen Schmied466a6521999-05-02 11:21:08 +00004567BOOL WINAPI SetMenuDefaultItem(HMENU hmenu, UINT uItem, UINT bypos)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004568{
Juergen Schmied466a6521999-05-02 11:21:08 +00004569 UINT i;
4570 POPUPMENU *menu;
4571 MENUITEM *item;
4572
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004573 TRACE("(0x%x,%d,%d)\n", hmenu, uItem, bypos);
Alexandre Julliarda845b881998-06-01 10:44:35 +00004574
Gerard Patel3e629742000-01-17 22:22:16 +00004575 if (!(menu = MENU_GetMenu(hmenu))) return FALSE;
Alexandre Julliarda845b881998-06-01 10:44:35 +00004576
Juergen Schmied466a6521999-05-02 11:21:08 +00004577 /* reset all default-item flags */
4578 item = menu->items;
4579 for (i = 0; i < menu->nItems; i++, item++)
4580 {
4581 item->fState &= ~MFS_DEFAULT;
4582 }
4583
4584 /* no default item */
4585 if ( -1 == uItem)
4586 {
4587 return TRUE;
4588 }
Alexandre Julliarda845b881998-06-01 10:44:35 +00004589
Juergen Schmied466a6521999-05-02 11:21:08 +00004590 item = menu->items;
4591 if ( bypos )
4592 {
4593 if ( uItem >= menu->nItems ) return FALSE;
4594 item[uItem].fState |= MFS_DEFAULT;
4595 return TRUE;
4596 }
4597 else
4598 {
4599 for (i = 0; i < menu->nItems; i++, item++)
4600 {
4601 if (item->wID == uItem)
4602 {
4603 item->fState |= MFS_DEFAULT;
4604 return TRUE;
4605 }
4606 }
4607
4608 }
4609 return FALSE;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004610}
4611
Alexandre Julliarda845b881998-06-01 10:44:35 +00004612/**********************************************************************
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00004613 * GetMenuDefaultItem (USER32.260)
Alexandre Julliarda845b881998-06-01 10:44:35 +00004614 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004615UINT WINAPI GetMenuDefaultItem(HMENU hmenu, UINT bypos, UINT flags)
Alexandre Julliarda845b881998-06-01 10:44:35 +00004616{
Juergen Schmied466a6521999-05-02 11:21:08 +00004617 POPUPMENU *menu;
4618 MENUITEM * item;
4619 UINT i = 0;
Alexandre Julliarda845b881998-06-01 10:44:35 +00004620
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004621 TRACE("(0x%x,%d,%d)\n", hmenu, bypos, flags);
Alexandre Julliarda845b881998-06-01 10:44:35 +00004622
Gerard Patel3e629742000-01-17 22:22:16 +00004623 if (!(menu = MENU_GetMenu(hmenu))) return -1;
Juergen Schmied466a6521999-05-02 11:21:08 +00004624
4625 /* find default item */
4626 item = menu->items;
Juergen Schmied49251861999-05-13 18:42:03 +00004627
4628 /* empty menu */
4629 if (! item) return -1;
4630
Juergen Schmied466a6521999-05-02 11:21:08 +00004631 while ( !( item->fState & MFS_DEFAULT ) )
4632 {
4633 i++; item++;
4634 if (i >= menu->nItems ) return -1;
4635 }
4636
4637 /* default: don't return disabled items */
4638 if ( (!(GMDI_USEDISABLED & flags)) && (item->fState & MFS_DISABLED )) return -1;
4639
4640 /* search rekursiv when needed */
4641 if ( (item->fType & MF_POPUP) && (flags & GMDI_GOINTOPOPUPS) )
4642 {
4643 UINT ret;
4644 ret = GetMenuDefaultItem( item->hSubMenu, bypos, flags );
4645 if ( -1 != ret ) return ret;
4646
4647 /* when item not found in submenu, return the popup item */
4648 }
4649 return ( bypos ) ? i : item->wID;
4650
Alexandre Julliarda845b881998-06-01 10:44:35 +00004651}
4652
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004653/*******************************************************************
4654 * InsertMenuItem16 (USER.441)
4655 *
4656 * FIXME: untested
4657 */
4658BOOL16 WINAPI InsertMenuItem16( HMENU16 hmenu, UINT16 pos, BOOL16 byposition,
4659 const MENUITEMINFO16 *mii )
4660{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004661 MENUITEMINFOA miia;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004662
4663 miia.cbSize = sizeof(miia);
4664 miia.fMask = mii->fMask;
Alexandre Julliard77b99181997-09-14 17:17:23 +00004665 miia.dwTypeData = mii->dwTypeData;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004666 miia.fType = mii->fType;
4667 miia.fState = mii->fState;
4668 miia.wID = mii->wID;
4669 miia.hSubMenu = mii->hSubMenu;
4670 miia.hbmpChecked = mii->hbmpChecked;
4671 miia.hbmpUnchecked = mii->hbmpUnchecked;
4672 miia.dwItemData = mii->dwItemData;
4673 miia.cch = mii->cch;
4674 if (IS_STRING_ITEM(miia.fType))
4675 miia.dwTypeData = PTR_SEG_TO_LIN(miia.dwTypeData);
Alexandre Julliarda3960291999-02-26 11:11:13 +00004676 return InsertMenuItemA( hmenu, pos, byposition, &miia );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004677}
4678
4679
4680/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004681 * InsertMenuItemA (USER32.323)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004682 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004683BOOL WINAPI InsertMenuItemA(HMENU hMenu, UINT uItem, BOOL bypos,
4684 const MENUITEMINFOA *lpmii)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004685{
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00004686 MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
Alexandre Julliarda3960291999-02-26 11:11:13 +00004687 return SetMenuItemInfo_common(item, lpmii, FALSE);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004688}
4689
4690
4691/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004692 * InsertMenuItemW (USER32.324)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004693 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004694BOOL WINAPI InsertMenuItemW(HMENU hMenu, UINT uItem, BOOL bypos,
4695 const MENUITEMINFOW *lpmii)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004696{
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00004697 MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
Alexandre Julliarda3960291999-02-26 11:11:13 +00004698 return SetMenuItemInfo_common(item, (const MENUITEMINFOA*)lpmii, TRUE);
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004699}
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004700
4701/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004702 * CheckMenuRadioItem (USER32.47)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004703 */
4704
Alexandre Julliarda3960291999-02-26 11:11:13 +00004705BOOL WINAPI CheckMenuRadioItem(HMENU hMenu,
4706 UINT first, UINT last, UINT check,
4707 UINT bypos)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004708{
4709 MENUITEM *mifirst, *milast, *micheck;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004710 HMENU mfirst = hMenu, mlast = hMenu, mcheck = hMenu;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004711
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004712 TRACE("ox%x: %d-%d, check %d, bypos=%d\n",
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00004713 hMenu, first, last, check, bypos);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004714
4715 mifirst = MENU_FindItem (&mfirst, &first, bypos);
4716 milast = MENU_FindItem (&mlast, &last, bypos);
4717 micheck = MENU_FindItem (&mcheck, &check, bypos);
4718
4719 if (mifirst == NULL || milast == NULL || micheck == NULL ||
4720 mifirst > milast || mfirst != mlast || mfirst != mcheck ||
4721 micheck > milast || micheck < mifirst)
4722 return FALSE;
4723
4724 while (mifirst <= milast)
4725 {
4726 if (mifirst == micheck)
4727 {
4728 mifirst->fType |= MFT_RADIOCHECK;
4729 mifirst->fState |= MFS_CHECKED;
4730 } else {
4731 mifirst->fType &= ~MFT_RADIOCHECK;
4732 mifirst->fState &= ~MFS_CHECKED;
4733 }
4734 mifirst++;
4735 }
4736
4737 return TRUE;
4738}
4739
4740/**********************************************************************
4741 * CheckMenuRadioItem16 (not a Windows API)
4742 */
4743
4744BOOL16 WINAPI CheckMenuRadioItem16(HMENU16 hMenu,
4745 UINT16 first, UINT16 last, UINT16 check,
4746 BOOL16 bypos)
4747{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004748 return CheckMenuRadioItem (hMenu, first, last, check, bypos);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004749}
4750
4751/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00004752 * GetMenuItemRect (USER32.266)
Pascal Lessard47274231999-02-13 12:21:46 +00004753 *
4754 * ATTENTION: Here, the returned values in rect are the screen
4755 * coordinates of the item just like if the menu was
4756 * always on the upper left side of the application.
4757 *
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004758 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004759BOOL WINAPI GetMenuItemRect (HWND hwnd, HMENU hMenu, UINT uItem,
4760 LPRECT rect)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004761{
Pascal Lessard47274231999-02-13 12:21:46 +00004762 POPUPMENU *itemMenu;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004763 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004764 HWND referenceHwnd;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004765
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004766 TRACE("(0x%x,0x%x,%d,%p)\n", hwnd, hMenu, uItem, rect);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004767
4768 item = MENU_FindItem (&hMenu, &uItem, MF_BYPOSITION);
Pascal Lessard47274231999-02-13 12:21:46 +00004769 referenceHwnd = hwnd;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004770
Pascal Lessard47274231999-02-13 12:21:46 +00004771 if(!hwnd)
4772 {
Gerard Patel3e629742000-01-17 22:22:16 +00004773 itemMenu = MENU_GetMenu(hMenu);
Pascal Lessard47274231999-02-13 12:21:46 +00004774 if (itemMenu == NULL)
4775 return FALSE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004776
Marcus Meissnerac593bb1999-03-17 15:18:28 +00004777 if(itemMenu->hWnd == 0)
Pascal Lessard47274231999-02-13 12:21:46 +00004778 return FALSE;
4779 referenceHwnd = itemMenu->hWnd;
4780 }
4781
4782 if ((rect == NULL) || (item == NULL))
4783 return FALSE;
4784
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004785 *rect = item->rect;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004786
Alexandre Julliarda3960291999-02-26 11:11:13 +00004787 MapWindowPoints(referenceHwnd, 0, (LPPOINT)rect, 2);
Pascal Lessard47274231999-02-13 12:21:46 +00004788
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004789 return TRUE;
4790}
4791
4792/**********************************************************************
4793 * GetMenuItemRect16 (USER.665)
4794 */
4795
4796BOOL16 WINAPI GetMenuItemRect16 (HWND16 hwnd, HMENU16 hMenu, UINT16 uItem,
4797 LPRECT16 rect)
4798{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004799 RECT r32;
4800 BOOL res;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004801
4802 if (!rect) return FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004803 res = GetMenuItemRect (hwnd, hMenu, uItem, &r32);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004804 CONV_RECT32TO16 (&r32, rect);
4805 return res;
4806}
Paul Quinn1beaae51998-12-15 15:38:36 +00004807
4808/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004809 * SetMenuInfo
4810 *
4811 * FIXME
4812 * MIM_APPLYTOSUBMENUS
4813 * actually use the items to draw the menu
4814 */
4815BOOL WINAPI SetMenuInfo (HMENU hMenu, LPCMENUINFO lpmi)
4816{
4817 POPUPMENU *menu;
4818
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004819 TRACE("(0x%04x %p)\n", hMenu, lpmi);
Juergen Schmied78513941999-04-18 14:40:32 +00004820
Gerard Patel3e629742000-01-17 22:22:16 +00004821 if (lpmi && (lpmi->cbSize==sizeof(MENUINFO)) && (menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004822 {
4823
4824 if (lpmi->fMask & MIM_BACKGROUND)
4825 menu->hbrBack = lpmi->hbrBack;
4826
4827 if (lpmi->fMask & MIM_HELPID)
4828 menu->dwContextHelpID = lpmi->dwContextHelpID;
4829
4830 if (lpmi->fMask & MIM_MAXHEIGHT)
4831 menu->cyMax = lpmi->cyMax;
4832
4833 if (lpmi->fMask & MIM_MENUDATA)
4834 menu->dwMenuData = lpmi->dwMenuData;
4835
4836 if (lpmi->fMask & MIM_STYLE)
4837 menu->dwStyle = lpmi->dwStyle;
4838
4839 return TRUE;
4840 }
4841 return FALSE;
4842}
4843
4844/**********************************************************************
4845 * GetMenuInfo
4846 *
4847 * NOTES
4848 * win98/NT5.0
4849 *
4850 */
4851BOOL WINAPI GetMenuInfo (HMENU hMenu, LPMENUINFO lpmi)
4852{ POPUPMENU *menu;
4853
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004854 TRACE("(0x%04x %p)\n", hMenu, lpmi);
Juergen Schmied78513941999-04-18 14:40:32 +00004855
Gerard Patel3e629742000-01-17 22:22:16 +00004856 if (lpmi && (menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004857 {
4858
4859 if (lpmi->fMask & MIM_BACKGROUND)
4860 lpmi->hbrBack = menu->hbrBack;
4861
4862 if (lpmi->fMask & MIM_HELPID)
4863 lpmi->dwContextHelpID = menu->dwContextHelpID;
4864
4865 if (lpmi->fMask & MIM_MAXHEIGHT)
4866 lpmi->cyMax = menu->cyMax;
4867
4868 if (lpmi->fMask & MIM_MENUDATA)
4869 lpmi->dwMenuData = menu->dwMenuData;
4870
4871 if (lpmi->fMask & MIM_STYLE)
4872 lpmi->dwStyle = menu->dwStyle;
4873
4874 return TRUE;
4875 }
4876 return FALSE;
4877}
4878
4879/**********************************************************************
Paul Quinn1beaae51998-12-15 15:38:36 +00004880 * SetMenuContextHelpId16 (USER.384)
4881 */
Juergen Schmied78513941999-04-18 14:40:32 +00004882BOOL16 WINAPI SetMenuContextHelpId16( HMENU16 hMenu, DWORD dwContextHelpID)
Paul Quinn1beaae51998-12-15 15:38:36 +00004883{
Juergen Schmied78513941999-04-18 14:40:32 +00004884 return SetMenuContextHelpId( hMenu, dwContextHelpID );
Paul Quinn1beaae51998-12-15 15:38:36 +00004885}
4886
4887
4888/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004889 * SetMenuContextHelpId (USER32.488)
Paul Quinn1beaae51998-12-15 15:38:36 +00004890 */
Juergen Schmied78513941999-04-18 14:40:32 +00004891BOOL WINAPI SetMenuContextHelpId( HMENU hMenu, DWORD dwContextHelpID)
Paul Quinn1beaae51998-12-15 15:38:36 +00004892{
Juergen Schmied78513941999-04-18 14:40:32 +00004893 LPPOPUPMENU menu;
4894
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004895 TRACE("(0x%04x 0x%08lx)\n", hMenu, dwContextHelpID);
Juergen Schmied78513941999-04-18 14:40:32 +00004896
Gerard Patel3e629742000-01-17 22:22:16 +00004897 if ((menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004898 {
4899 menu->dwContextHelpID = dwContextHelpID;
4900 return TRUE;
4901 }
4902 return FALSE;
Paul Quinn1beaae51998-12-15 15:38:36 +00004903}
4904
4905/**********************************************************************
4906 * GetMenuContextHelpId16 (USER.385)
4907 */
4908DWORD WINAPI GetMenuContextHelpId16( HMENU16 hMenu )
4909{
Juergen Schmied78513941999-04-18 14:40:32 +00004910 return GetMenuContextHelpId( hMenu );
Paul Quinn1beaae51998-12-15 15:38:36 +00004911}
4912
4913/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004914 * GetMenuContextHelpId (USER32.488)
Paul Quinn1beaae51998-12-15 15:38:36 +00004915 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004916DWORD WINAPI GetMenuContextHelpId( HMENU hMenu )
Paul Quinn1beaae51998-12-15 15:38:36 +00004917{
Juergen Schmied78513941999-04-18 14:40:32 +00004918 LPPOPUPMENU menu;
4919
Alexandre Julliard9fe7a251999-05-14 08:17:14 +00004920 TRACE("(0x%04x)\n", hMenu);
Juergen Schmied78513941999-04-18 14:40:32 +00004921
Gerard Patel3e629742000-01-17 22:22:16 +00004922 if ((menu = MENU_GetMenu(hMenu)))
Juergen Schmied78513941999-04-18 14:40:32 +00004923 {
4924 return menu->dwContextHelpID;
4925 }
4926 return 0;
Paul Quinn1beaae51998-12-15 15:38:36 +00004927}
Eric Pouech0c62bf01999-09-13 15:11:35 +00004928
4929/**********************************************************************
4930 * MenuItemFromPoint (USER32.387)
4931 */
4932UINT WINAPI MenuItemFromPoint(HWND hWnd, HMENU hMenu, POINT ptScreen)
4933{
4934 FIXME("(0x%04x,0x%04x,(%ld,%ld)):stub\n",
4935 hWnd, hMenu, ptScreen.x, ptScreen.y);
4936 return 0;
4937}