blob: 0722249383fa427c57eb62daa3b574b325cad386 [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
Marcus Meissnerd5e7c791998-12-09 11:06:00 +000020#include "win.h"
Francois Boisvert85dd9fc1999-02-17 12:50:11 +000021#include "wine/winbase16.h"
Michael Veksler3fbb8dc1999-02-21 18:23:26 +000022#include "wine/winuser16.h"
Alexandre Julliarddba420a1994-02-02 06:48:31 +000023#include "sysmetrics.h"
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000024#include "task.h"
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000025#include "heap.h"
Francois Boisvert197a8e11999-02-13 09:10:17 +000026#include "menu.h"
Alexandre Julliardc6c09441997-01-12 18:32:19 +000027#include "nonclient.h"
Alexandre Julliard1f579291994-05-25 16:25:21 +000028#include "user.h"
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +000029#include "message.h"
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +000030#include "resource.h"
Alexandre Julliardd37eb361997-07-20 16:23:21 +000031#include "tweak.h"
Marcus Meissnerd5e7c791998-12-09 11:06:00 +000032
Alexandre Julliardaca05781994-10-17 18:12:41 +000033#include "debug.h"
34
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000035DEFAULT_DEBUG_CHANNEL(menu)
36
Alexandre Julliardd37eb361997-07-20 16:23:21 +000037
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000038/* internal popup menu window messages */
39
40#define MM_SETMENUHANDLE (WM_USER + 0)
41#define MM_GETMENUHANDLE (WM_USER + 1)
42
Alexandre Julliard2d93d001996-05-21 15:01:41 +000043/* Menu item structure */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000044typedef struct {
45 /* ----------- MENUITEMINFO Stuff ----------- */
Juergen Schmied78513941999-04-18 14:40:32 +000046 UINT fType; /* Item type. */
Alexandre Julliarda3960291999-02-26 11:11:13 +000047 UINT fState; /* Item state. */
48 UINT wID; /* Item id. */
49 HMENU hSubMenu; /* Pop-up menu. */
Juergen Schmied78513941999-04-18 14:40:32 +000050 HBITMAP hCheckBit; /* Bitmap when checked. */
Alexandre Julliarda3960291999-02-26 11:11:13 +000051 HBITMAP hUnCheckBit; /* Bitmap when unchecked. */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000052 LPSTR text; /* Item text or bitmap handle. */
53 DWORD dwItemData; /* Application defined. */
Juergen Schmied78513941999-04-18 14:40:32 +000054 DWORD dwTypeData; /* depends on fMask */
55 HBITMAP hbmpItem; /* bitmap in win98 style menus */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000056 /* ----------- Wine stuff ----------- */
Juergen Schmied78513941999-04-18 14:40:32 +000057 RECT rect; /* Item area (relative to menu window) */
58 UINT xTab; /* X position of text after Tab */
Alexandre Julliard2d93d001996-05-21 15:01:41 +000059} MENUITEM;
60
61/* Popup menu structure */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000062typedef struct {
Alexandre Julliard2d93d001996-05-21 15:01:41 +000063 WORD wFlags; /* Menu flags (MF_POPUP, MF_SYSMENU) */
64 WORD wMagic; /* Magic number */
Alexandre Julliardbf9130a1996-10-13 17:45:47 +000065 HQUEUE16 hTaskQ; /* Task queue for this menu */
Alexandre Julliard2d93d001996-05-21 15:01:41 +000066 WORD Width; /* Width of the whole menu */
67 WORD Height; /* Height of the whole menu */
68 WORD nItems; /* Number of items in the menu */
Juergen Schmied78513941999-04-18 14:40:32 +000069 HWND hWnd; /* Window containing the menu */
70 MENUITEM *items; /* Array of menu items */
71 UINT FocusedItem; /* Currently focused item */
Alexandre Julliarda845b881998-06-01 10:44:35 +000072 WORD defitem; /* default item position. Unused (except for set/get)*/
Juergen Schmied78513941999-04-18 14:40:32 +000073 HWND hwndOwner; /* window receiving the messages for ownerdraw */
74 /* ------------ MENUINFO members ------ */
75 DWORD dwStyle; /* Extended mennu style */
76 UINT cyMax; /* max hight of the whole menu, 0 is screen hight */
77 HBRUSH hbrBack; /* brush for menu background */
78 DWORD dwContextHelpID;
79 DWORD dwMenuData; /* application defined value */
Alexandre Julliard2d93d001996-05-21 15:01:41 +000080} POPUPMENU, *LPPOPUPMENU;
81
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000082/* internal flags for menu tracking */
83
84#define TF_ENDMENU 0x0001
85#define TF_SUSPENDPOPUP 0x0002
86#define TF_SKIPREMOVE 0x0004
87
88typedef struct
89{
Alexandre Julliarda3960291999-02-26 11:11:13 +000090 UINT trackFlags;
91 HMENU hCurrentMenu; /* current submenu (can be equal to hTopMenu)*/
92 HMENU hTopMenu; /* initial menu */
93 HWND hOwnerWnd; /* where notifications are sent */
94 POINT pt;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000095} MTRACKER;
96
Alexandre Julliard2d93d001996-05-21 15:01:41 +000097#define MENU_MAGIC 0x554d /* 'MU' */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000098#define IS_A_MENU(pmenu) ((pmenu) && (pmenu)->wMagic == MENU_MAGIC)
Alexandre Julliard2d93d001996-05-21 15:01:41 +000099
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000100#define ITEM_PREV -1
101#define ITEM_NEXT 1
102
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000103 /* Internal MENU_TrackMenu() flags */
104#define TPM_INTERNAL 0xF0000000
105#define TPM_ENTERIDLEEX 0x80000000 /* set owner window for WM_ENTERIDLE */
106#define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */
Francois Boisvert85dd9fc1999-02-17 12:50:11 +0000107#define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */
Alexandre Julliardf7207251994-07-23 07:57:48 +0000108
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000109 /* popup menu shade thickness */
110#define POPUP_XSHADE 4
111#define POPUP_YSHADE 4
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000112
Alexandre Julliardf7207251994-07-23 07:57:48 +0000113 /* Space between 2 menu bar items */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000114#define MENU_BAR_ITEMS_SPACE 12
Alexandre Julliardf7207251994-07-23 07:57:48 +0000115
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000116 /* Minimum width of a tab character */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000117#define MENU_TAB_SPACE 8
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000118
Alexandre Julliardf7207251994-07-23 07:57:48 +0000119 /* Height of a separator item */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000120#define SEPARATOR_HEIGHT 5
Alexandre Julliardf7207251994-07-23 07:57:48 +0000121
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000122 /* (other menu->FocusedItem values give the position of the focused item) */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000123#define NO_SELECTED_ITEM 0xffff
Alexandre Julliardcdd09231994-01-12 11:12:51 +0000124
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000125#define MENU_ITEM_TYPE(flags) \
126 ((flags) & (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR))
127
128#define IS_STRING_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_STRING)
Juergen Schmied78513941999-04-18 14:40:32 +0000129#define IS_BITMAP_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_BITMAP)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000130
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000131#define IS_SYSTEM_MENU(menu) \
132 (!((menu)->wFlags & MF_POPUP) && (menu)->wFlags & MF_SYSMENU)
Juergen Schmied78513941999-04-18 14:40:32 +0000133
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000134#define IS_SYSTEM_POPUP(menu) \
135 ((menu)->wFlags & MF_POPUP && (menu)->wFlags & MF_SYSMENU)
136
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000137#define TYPE_MASK (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
138 MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
139 MFT_RIGHTORDER | MFT_RIGHTJUSTIFY | \
140 MF_POPUP | MF_SYSMENU | MF_HELP)
141#define STATE_MASK (~TYPE_MASK)
142
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000143 /* Dimension of the menu bitmaps */
144static WORD check_bitmap_width = 0, check_bitmap_height = 0;
145static WORD arrow_bitmap_width = 0, arrow_bitmap_height = 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000146
Alexandre Julliarda3960291999-02-26 11:11:13 +0000147static HBITMAP hStdRadioCheck = 0;
148static HBITMAP hStdCheck = 0;
149static HBITMAP hStdMnArrow = 0;
Francois Boisvert8b391741999-02-09 14:09:55 +0000150
151// Minimze/restore/close buttons to be inserted in menubar
Alexandre Julliarda3960291999-02-26 11:11:13 +0000152static HBITMAP hBmpMinimize = 0;
153static HBITMAP hBmpMinimizeD = 0;
154static HBITMAP hBmpMaximize = 0;
155static HBITMAP hBmpMaximizeD = 0;
156static HBITMAP hBmpClose = 0;
157static HBITMAP hBmpCloseD = 0;
Francois Boisvert308c6af1999-02-18 10:37:17 +0000158
Francois Boisvert8b391741999-02-09 14:09:55 +0000159
Juergen Schmied78513941999-04-18 14:40:32 +0000160static HBRUSH hShadeBrush = 0;
161static HFONT hMenuFont = 0;
162
Alexandre Julliarda3960291999-02-26 11:11:13 +0000163static HMENU MENU_DefSysPopup = 0; /* Default system menu popup */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000164
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000165/* Use global popup window because there's no way 2 menus can
166 * be tracked at the same time. */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000167
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000168static WND* pTopPopupWnd = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000169static UINT uSubPWndLevel = 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000170
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000171 /* Flag set by EndMenu() to force an exit from menu tracking */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000172static BOOL fEndMenu = FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000173
174
175/***********************************************************************
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000176 * debug_print_menuitem
177 *
178 * Print a menuitem in readable form.
179 */
180
Alexandre Julliard03468f71998-02-15 19:40:49 +0000181#define debug_print_menuitem(pre, mp, post) \
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000182 if(!TRACE_ON(menu)) ; else do_debug_print_menuitem(pre, mp, post)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000183
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000184#define MENUOUT(text) \
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000185 dsprintf(menu, "%s%s", (count++ ? "," : ""), (text))
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000186
187#define MENUFLAG(bit,text) \
188 do { \
189 if (flags & (bit)) { flags &= ~(bit); MENUOUT ((text)); } \
190 } while (0)
191
Alexandre Julliard03468f71998-02-15 19:40:49 +0000192static void do_debug_print_menuitem(const char *prefix, MENUITEM * mp,
193 const char *postfix)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000194{
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000195 dbg_decl_str(menu, 256);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000196
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000197 if (mp) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000198 UINT flags = mp->fType;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000199 int typ = MENU_ITEM_TYPE(flags);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000200 dsprintf(menu, "{ ID=0x%x", mp->wID);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000201 if (flags & MF_POPUP)
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000202 dsprintf(menu, ", Sub=0x%x", mp->hSubMenu);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000203 if (flags) {
204 int count = 0;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000205 dsprintf(menu, ", Typ=");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000206 if (typ == MFT_STRING)
207 /* Nothing */ ;
208 else if (typ == MFT_SEPARATOR)
209 MENUOUT("sep");
210 else if (typ == MFT_OWNERDRAW)
211 MENUOUT("own");
212 else if (typ == MFT_BITMAP)
213 MENUOUT("bit");
214 else
215 MENUOUT("???");
216 flags -= typ;
217
218 MENUFLAG(MF_POPUP, "pop");
219 MENUFLAG(MFT_MENUBARBREAK, "barbrk");
220 MENUFLAG(MFT_MENUBREAK, "brk");
221 MENUFLAG(MFT_RADIOCHECK, "radio");
222 MENUFLAG(MFT_RIGHTORDER, "rorder");
223 MENUFLAG(MF_SYSMENU, "sys");
224 MENUFLAG(MFT_RIGHTJUSTIFY, "right");
225
226 if (flags)
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000227 dsprintf(menu, "+0x%x", flags);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000228 }
229 flags = mp->fState;
230 if (flags) {
231 int count = 0;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000232 dsprintf(menu, ", State=");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000233 MENUFLAG(MFS_GRAYED, "grey");
234 MENUFLAG(MFS_DISABLED, "dis");
235 MENUFLAG(MFS_CHECKED, "check");
236 MENUFLAG(MFS_HILITE, "hi");
237 MENUFLAG(MF_USECHECKBITMAPS, "usebit");
238 MENUFLAG(MF_MOUSESELECT, "mouse");
239 if (flags)
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000240 dsprintf(menu, "+0x%x", flags);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000241 }
242 if (mp->hCheckBit)
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000243 dsprintf(menu, ", Chk=0x%x", mp->hCheckBit);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000244 if (mp->hUnCheckBit)
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000245 dsprintf(menu, ", Unc=0x%x", mp->hUnCheckBit);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000246
247 if (typ == MFT_STRING) {
248 if (mp->text)
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000249 dsprintf(menu, ", Text=\"%s\"", mp->text);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000250 else
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000251 dsprintf(menu, ", Text=Null");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000252 } else if (mp->text == NULL)
253 /* Nothing */ ;
254 else
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000255 dsprintf(menu, ", Text=%p", mp->text);
Juergen Schmied7abca951999-04-11 17:02:30 +0000256 if (mp->dwItemData)
257 dsprintf(menu, ", ItemData=0x%08lx", mp->dwItemData);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000258 dsprintf(menu, " }");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000259 } else {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000260 dsprintf(menu, "NULL");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000261 }
Alexandre Julliard03468f71998-02-15 19:40:49 +0000262
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000263 TRACE(menu, "%s %s %s\n", prefix, dbg_str(menu), postfix);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000264}
265
266#undef MENUOUT
267#undef MENUFLAG
268
269/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000270 * MENU_CopySysPopup
271 *
272 * Return the default system menu.
273 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000274static HMENU MENU_CopySysPopup(void)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000275{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000276 HMENU hMenu = LoadMenuIndirectA(SYSRES_GetResPtr(SYSRES_MENU_SYSMENU));
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000277
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000278 if( hMenu ) {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000279 POPUPMENU* menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(hMenu);
280 menu->wFlags |= MF_SYSMENU | MF_POPUP;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000281 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000282 else {
283 hMenu = 0;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000284 ERR(menu, "Unable to load default system menu\n" );
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000285 }
286
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000287 TRACE(menu, "returning %x.\n", hMenu );
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000288
289 return hMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000290}
291
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000292/***********************************************************************
293 * MENU_GetTopPopupWnd()
294 *
295 * Return the locked pointer pTopPopupWnd.
296 */
297WND *MENU_GetTopPopupWnd()
298{
299 return WIN_LockWndPtr(pTopPopupWnd);
300}
301/***********************************************************************
302 * MENU_ReleaseTopPopupWnd()
303 *
304 * Realease the locked pointer pTopPopupWnd.
305 */
306void MENU_ReleaseTopPopupWnd()
307{
308 WIN_ReleaseWndPtr(pTopPopupWnd);
309}
310/***********************************************************************
311 * MENU_DestroyTopPopupWnd()
312 *
313 * Destroy the locked pointer pTopPopupWnd.
314 */
315void MENU_DestroyTopPopupWnd()
316{
317 WND *tmpWnd = pTopPopupWnd;
318 pTopPopupWnd = NULL;
319 WIN_ReleaseWndPtr(tmpWnd);
320}
321
322
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000323
324/**********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000325 * MENU_GetSysMenu
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000326 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000327 * Create a copy of the system menu. System menu in Windows is
328 * a special menu-bar with the single entry - system menu popup.
329 * This popup is presented to the outside world as a "system menu".
330 * However, the real system menu handle is sometimes seen in the
331 * WM_MENUSELECT paramemters (and Word 6 likes it this way).
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000332 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000333HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu )
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000334{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000335 HMENU hMenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000336
Alexandre Julliarda3960291999-02-26 11:11:13 +0000337 if ((hMenu = CreateMenu()))
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000338 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000339 POPUPMENU *menu = (POPUPMENU*) USER_HEAP_LIN_ADDR(hMenu);
340 menu->wFlags = MF_SYSMENU;
341 menu->hWnd = hWnd;
342
Alexandre Julliarda3960291999-02-26 11:11:13 +0000343 if (hPopupMenu == (HMENU)(-1))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000344 hPopupMenu = MENU_CopySysPopup();
345 else if( !hPopupMenu ) hPopupMenu = MENU_DefSysPopup;
346
347 if (hPopupMenu)
348 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000349 InsertMenuA( hMenu, -1, MF_SYSMENU | MF_POPUP | MF_BYPOSITION, hPopupMenu, NULL );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000350
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000351 menu->items[0].fType = MF_SYSMENU | MF_POPUP;
352 menu->items[0].fState = 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000353 menu = (POPUPMENU*) USER_HEAP_LIN_ADDR(hPopupMenu);
354 menu->wFlags |= MF_SYSMENU;
355
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000356 TRACE(menu,"GetSysMenu hMenu=%04x (%04x)\n", hMenu, hPopupMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000357 return hMenu;
358 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000359 DestroyMenu( hMenu );
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000360 }
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000361 ERR(menu, "failed to load system menu!\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000362 return 0;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000363}
364
365
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000366/***********************************************************************
367 * MENU_Init
368 *
369 * Menus initialisation.
370 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000371BOOL MENU_Init()
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000372{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000373 HBITMAP hBitmap;
Juergen Schmied78513941999-04-18 14:40:32 +0000374 NONCLIENTMETRICSA ncm;
375
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000376 static unsigned char shade_bits[16] = { 0x55, 0, 0xAA, 0,
377 0x55, 0, 0xAA, 0,
378 0x55, 0, 0xAA, 0,
379 0x55, 0, 0xAA, 0 };
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000380
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000381 /* Load menu bitmaps */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000382 hStdCheck = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_CHECK));
383 hStdRadioCheck = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_RADIOCHECK));
384 hStdMnArrow = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_MNARROW));
Francois Boisvert8b391741999-02-09 14:09:55 +0000385 /* Load system buttons bitmaps */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000386 hBmpMinimize = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_REDUCE));
387 hBmpMinimizeD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_REDUCED));
388 hBmpMaximize = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_RESTORE));
389 hBmpMaximizeD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_RESTORED));
390 hBmpClose = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_CLOSE));
391 hBmpCloseD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_CLOSED));
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000392
393 if (hStdCheck)
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000394 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000395 BITMAP bm;
396 GetObjectA( hStdCheck, sizeof(bm), &bm );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000397 check_bitmap_width = bm.bmWidth;
398 check_bitmap_height = bm.bmHeight;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000399 } else
400 return FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000401
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000402 /* Assume that radio checks have the same size as regular check. */
403 if (!hStdRadioCheck)
404 return FALSE;
405
406 if (hStdMnArrow)
Juergen Schmied78513941999-04-18 14:40:32 +0000407 {
408 BITMAP bm;
409 GetObjectA( hStdMnArrow, sizeof(bm), &bm );
410 arrow_bitmap_width = bm.bmWidth;
411 arrow_bitmap_height = bm.bmHeight;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000412 } else
Juergen Schmied78513941999-04-18 14:40:32 +0000413 return FALSE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000414
Juergen Schmied78513941999-04-18 14:40:32 +0000415 if (! (hBitmap = CreateBitmap( 8, 8, 1, 1, shade_bits)))
416 return FALSE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000417
Juergen Schmied78513941999-04-18 14:40:32 +0000418 if(!(hShadeBrush = CreatePatternBrush( hBitmap )))
419 return FALSE;
420
421 DeleteObject( hBitmap );
422 if (!(MENU_DefSysPopup = MENU_CopySysPopup()))
423 return FALSE;
424
425 ncm.cbSize = sizeof (NONCLIENTMETRICSA);
426 if (!(SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &ncm, 0)))
427 return FALSE;
428
429 if (!(hMenuFont = CreateFontIndirectA( &ncm.lfMenuFont )))
430 return FALSE;
431
432 return TRUE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000433}
434
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000435/***********************************************************************
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000436 * MENU_InitSysMenuPopup
437 *
438 * Grey the appropriate items in System menu.
439 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000440static void MENU_InitSysMenuPopup( HMENU hmenu, DWORD style, DWORD clsStyle )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000441{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000442 BOOL gray;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000443
444 gray = !(style & WS_THICKFRAME) || (style & (WS_MAXIMIZE | WS_MINIMIZE));
Alexandre Julliarda3960291999-02-26 11:11:13 +0000445 EnableMenuItem( hmenu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000446 gray = ((style & WS_MAXIMIZE) != 0);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000447 EnableMenuItem( hmenu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000448 gray = !(style & WS_MINIMIZEBOX) || (style & WS_MINIMIZE);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000449 EnableMenuItem( hmenu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000450 gray = !(style & WS_MAXIMIZEBOX) || (style & WS_MAXIMIZE);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000451 EnableMenuItem( hmenu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000452 gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE));
Alexandre Julliarda3960291999-02-26 11:11:13 +0000453 EnableMenuItem( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000454 gray = (clsStyle & CS_NOCLOSE) != 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000455 EnableMenuItem( hmenu, SC_CLOSE, (gray ? MF_GRAYED : MF_ENABLED) );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000456}
457
458
Alexandre Julliard641ee761997-08-04 16:34:36 +0000459/******************************************************************************
460 *
461 * UINT32 MENU_GetStartOfNextColumn(
462 * HMENU32 hMenu )
463 *
464 *****************************************************************************/
465
Alexandre Julliarda3960291999-02-26 11:11:13 +0000466static UINT MENU_GetStartOfNextColumn(
467 HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000468{
469 POPUPMENU *menu = (POPUPMENU *)USER_HEAP_LIN_ADDR(hMenu);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000470 UINT i = menu->FocusedItem + 1;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000471
472 if(!menu)
473 return NO_SELECTED_ITEM;
474
475 if( i == NO_SELECTED_ITEM )
476 return i;
477
478 for( ; i < menu->nItems; ++i ) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000479 if (menu->items[i].fType & MF_MENUBARBREAK)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000480 return i;
481 }
482
483 return NO_SELECTED_ITEM;
484}
485
486
487/******************************************************************************
488 *
489 * UINT32 MENU_GetStartOfPrevColumn(
490 * HMENU32 hMenu )
491 *
492 *****************************************************************************/
493
Alexandre Julliarda3960291999-02-26 11:11:13 +0000494static UINT MENU_GetStartOfPrevColumn(
495 HMENU hMenu )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000496{
497 POPUPMENU const *menu = (POPUPMENU *)USER_HEAP_LIN_ADDR(hMenu);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000498 UINT i;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000499
500 if( !menu )
501 return NO_SELECTED_ITEM;
502
503 if( menu->FocusedItem == 0 || menu->FocusedItem == NO_SELECTED_ITEM )
504 return NO_SELECTED_ITEM;
505
506 /* Find the start of the column */
507
508 for(i = menu->FocusedItem; i != 0 &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000509 !(menu->items[i].fType & MF_MENUBARBREAK);
Alexandre Julliard641ee761997-08-04 16:34:36 +0000510 --i); /* empty */
511
512 if(i == 0)
513 return NO_SELECTED_ITEM;
514
515 for(--i; i != 0; --i) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000516 if (menu->items[i].fType & MF_MENUBARBREAK)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000517 break;
518 }
519
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000520 TRACE(menu, "ret %d.\n", i );
Alexandre Julliard641ee761997-08-04 16:34:36 +0000521
522 return i;
523}
524
525
526
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000527/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000528 * MENU_FindItem
529 *
530 * Find a menu item. Return a pointer on the item, and modifies *hmenu
531 * in case the item was in a sub-menu.
532 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000533static MENUITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000534{
535 POPUPMENU *menu;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000536 UINT i;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000537
Juergen Schmied78513941999-04-18 14:40:32 +0000538 if (((*hmenu)==0xffff) || (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(*hmenu)))) return NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000539 if (wFlags & MF_BYPOSITION)
540 {
541 if (*nPos >= menu->nItems) return NULL;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000542 return &menu->items[*nPos];
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000543 }
544 else
545 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000546 MENUITEM *item = menu->items;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000547 for (i = 0; i < menu->nItems; i++, item++)
548 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000549 if (item->wID == *nPos)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000550 {
551 *nPos = i;
552 return item;
553 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000554 else if (item->fType & MF_POPUP)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000555 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000556 HMENU hsubmenu = item->hSubMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000557 MENUITEM *subitem = MENU_FindItem( &hsubmenu, nPos, wFlags );
558 if (subitem)
559 {
560 *hmenu = hsubmenu;
561 return subitem;
562 }
563 }
564 }
565 }
566 return NULL;
567}
568
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000569/***********************************************************************
570 * MENU_FreeItemData
571 */
572static void MENU_FreeItemData( MENUITEM* item )
573{
574 /* delete text */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000575 if (IS_STRING_ITEM(item->fType) && item->text)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000576 HeapFree( SystemHeap, 0, item->text );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000577}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000578
579/***********************************************************************
580 * MENU_FindItemByCoords
581 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000582 * Find the item at the specified coordinates (screen coords). Does
583 * not work for child windows and therefore should not be called for
584 * an arbitrary system menu.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000585 */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000586static MENUITEM *MENU_FindItemByCoords( POPUPMENU *menu,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000587 POINT pt, UINT *pos )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000588{
589 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000590 UINT i;
Marcus Meissnerac593bb1999-03-17 15:18:28 +0000591 RECT wrect;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000592
Marcus Meissnerac593bb1999-03-17 15:18:28 +0000593 if (!GetWindowRect(menu->hWnd,&wrect)) return NULL;
594 pt.x -= wrect.left;pt.y -= wrect.top;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000595 item = menu->items;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000596 for (i = 0; i < menu->nItems; i++, item++)
597 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000598 if ((pt.x >= item->rect.left) && (pt.x < item->rect.right) &&
599 (pt.y >= item->rect.top) && (pt.y < item->rect.bottom))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000600 {
601 if (pos) *pos = i;
602 return item;
603 }
604 }
605 return NULL;
606}
607
608
609/***********************************************************************
610 * MENU_FindItemByKey
611 *
612 * Find the menu item selected by a key press.
613 * Return item id, -1 if none, -2 if we should close the menu.
614 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000615static UINT MENU_FindItemByKey( HWND hwndOwner, HMENU hmenu,
616 UINT key, BOOL forceMenuChar )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000617{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000618 TRACE(menu,"\tlooking for '%c' in [%04x]\n", (char)key, (UINT16)hmenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000619
Alexandre Julliarda3960291999-02-26 11:11:13 +0000620 if (!IsMenu( hmenu ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000621 {
622 WND* w = WIN_FindWndPtr(hwndOwner);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000623 hmenu = GetSubMenu(w->hSysMenu, 0);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000624 WIN_ReleaseWndPtr(w);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000625 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000626
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000627 if (hmenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000628 {
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000629 POPUPMENU *menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
630 MENUITEM *item = menu->items;
631 LONG menuchar;
632
633 if( !forceMenuChar )
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000634 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000635 UINT i;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000636
637 key = toupper(key);
638 for (i = 0; i < menu->nItems; i++, item++)
639 {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000640 if (item->text && (IS_STRING_ITEM(item->fType)))
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000641 {
Norman Stevensa83d0651998-10-12 07:25:35 +0000642 char *p = item->text - 2;
643 do
644 {
645 p = strchr (p + 2, '&');
646 }
647 while (p != NULL && p [1] == '&');
648 if (p && (toupper(p[1]) == key)) return i;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000649 }
650 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000651 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000652 menuchar = SendMessageA( hwndOwner, WM_MENUCHAR,
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000653 MAKEWPARAM( key, menu->wFlags ), hmenu );
654 if (HIWORD(menuchar) == 2) return LOWORD(menuchar);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000655 if (HIWORD(menuchar) == 1) return (UINT)(-2);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000656 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000657 return (UINT)(-1);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000658}
Francois Boisvert8b391741999-02-09 14:09:55 +0000659/***********************************************************************
660 * MENU_LoadMagicItem
661 *
662 * Load the bitmap associated with the magic menu item and its style
663 */
Alexandre Julliarddba420a1994-02-02 06:48:31 +0000664
Juergen Schmied78513941999-04-18 14:40:32 +0000665static HBITMAP MENU_LoadMagicItem(UINT id, BOOL hilite, DWORD dwItemData)
Francois Boisvert8b391741999-02-09 14:09:55 +0000666{
667 // Magic menu item id's section
668 // These magic id's are used by windows to insert "standard" mdi
669 // buttons (minimize,restore,close) on menu. Under windows,
670 // these magic id's make sure the right things appear when those
671 // bitmap buttons are pressed/selected/released.
672
673 switch(id)
Juergen Schmied78513941999-04-18 14:40:32 +0000674 { case HBMMENU_SYSTEM:
675 return (dwItemData) ?
676 (HBITMAP)dwItemData :
677 (hilite ? hBmpMinimizeD : hBmpMinimize);
678 case HBMMENU_MBAR_RESTORE:
679 return (hilite ? hBmpMaximizeD: hBmpMaximize);
680 case HBMMENU_MBAR_MINIMIZE:
681 return (hilite ? hBmpMinimizeD : hBmpMinimize);
682 case HBMMENU_MBAR_CLOSE:
683 return (hilite ? hBmpCloseD : hBmpClose);
684 case HBMMENU_CALLBACK:
685 case HBMMENU_MBAR_CLOSE_D:
686 case HBMMENU_MBAR_MINIMIZE_D:
687 case HBMMENU_POPUP_CLOSE:
688 case HBMMENU_POPUP_RESTORE:
689 case HBMMENU_POPUP_MAXIMIZE:
690 case HBMMENU_POPUP_MINIMIZE:
691 default:
692 FIXME(menu,"Magic 0x%08x not implemented\n", id);
693 return 0;
Francois Boisvert8b391741999-02-09 14:09:55 +0000694 }
695
696}
Alexandre Julliardf7207251994-07-23 07:57:48 +0000697
698/***********************************************************************
699 * MENU_CalcItemSize
700 *
701 * Calculate the size of the menu item and store it in lpitem->rect.
702 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000703static void MENU_CalcItemSize( HDC hdc, MENUITEM *lpitem, HWND hwndOwner,
704 INT orgX, INT orgY, BOOL menuBar )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000705{
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000706 char *p;
707
Juergen Schmied78513941999-04-18 14:40:32 +0000708 TRACE(menu, "dc=0x%04x owner=0x%04x (%d,%d)\n", hdc, hwndOwner, orgX, orgY);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000709 debug_print_menuitem("MENU_CalcItemSize: menuitem:", lpitem,
710 (menuBar ? " (MenuBar)" : ""));
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000711
Alexandre Julliarda3960291999-02-26 11:11:13 +0000712 SetRect( &lpitem->rect, orgX, orgY, orgX, orgY );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000713
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000714 if (lpitem->fType & MF_OWNERDRAW)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000715 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000716 MEASUREITEMSTRUCT mis;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000717 mis.CtlType = ODT_MENU;
Juergen Schmied7abca951999-04-11 17:02:30 +0000718 mis.CtlID = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000719 mis.itemID = lpitem->wID;
Juergen Schmied7abca951999-04-11 17:02:30 +0000720 mis.itemData = (DWORD)lpitem->dwItemData;
721 mis.itemHeight = 0;
722 mis.itemWidth = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000723 SendMessageA( hwndOwner, WM_MEASUREITEM, 0, (LPARAM)&mis );
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000724 lpitem->rect.bottom += mis.itemHeight;
725 lpitem->rect.right += mis.itemWidth;
Juergen Schmied78513941999-04-18 14:40:32 +0000726 TRACE(menu, "id=%04x size=%dx%d\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000727 lpitem->wID, mis.itemWidth, mis.itemHeight);
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000728 return;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000729 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000730
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000731 if (lpitem->fType & MF_SEPARATOR)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000732 {
733 lpitem->rect.bottom += SEPARATOR_HEIGHT;
734 return;
735 }
736
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000737 if (!menuBar)
738 {
739 lpitem->rect.right += 2 * check_bitmap_width;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000740 if (lpitem->fType & MF_POPUP)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000741 lpitem->rect.right += arrow_bitmap_width;
742 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000743
Juergen Schmied78513941999-04-18 14:40:32 +0000744 if (IS_BITMAP_ITEM(lpitem->fType))
Alexandre Julliardf7207251994-07-23 07:57:48 +0000745 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000746 BITMAP bm;
Juergen Schmied78513941999-04-18 14:40:32 +0000747 HBITMAP resBmp = 0;
Francois Boisvert8b391741999-02-09 14:09:55 +0000748
Juergen Schmied78513941999-04-18 14:40:32 +0000749 // Check if there is a magic menu item associated with this item
750 if((LOWORD((int)lpitem->text))<12)
751 {
752 resBmp = MENU_LoadMagicItem((int)lpitem->text, (lpitem->fType & MF_HILITE),
753 lpitem->dwItemData);
Francois Boisvert8b391741999-02-09 14:09:55 +0000754 }
755 else
Alexandre Julliarda3960291999-02-26 11:11:13 +0000756 resBmp = (HBITMAP)lpitem->text;
Francois Boisvert8b391741999-02-09 14:09:55 +0000757
Alexandre Julliarda3960291999-02-26 11:11:13 +0000758 if (GetObjectA(resBmp, sizeof(bm), &bm ))
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000759 {
760 lpitem->rect.right += bm.bmWidth;
761 lpitem->rect.bottom += bm.bmHeight;
Francois Boisvert8b391741999-02-09 14:09:55 +0000762
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000763 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000764 }
765
Juergen Schmied78513941999-04-18 14:40:32 +0000766
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000767 /* If we get here, then it must be a text item */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000768 if (IS_STRING_ITEM( lpitem->fType ))
Juergen Schmied78513941999-04-18 14:40:32 +0000769 { SIZE size;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000770
Juergen Schmied78513941999-04-18 14:40:32 +0000771 GetTextExtentPoint32A(hdc, lpitem->text, strlen(lpitem->text), &size);
772
773 lpitem->rect.right += size.cx;
774 if (TWEAK_WineLook == WIN31_LOOK)
775 lpitem->rect.bottom += MAX( size.cy, SYSMETRICS_CYMENU );
776 else
777 lpitem->rect.bottom += MAX (size.cy, sysMetrics[SM_CYMENU]- 1);
778 lpitem->xTab = 0;
779
780 if (menuBar)
781 {
782 lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
783 }
784 else if ((p = strchr( lpitem->text, '\t' )) != NULL)
785 {
786 /* Item contains a tab (only meaningful in popup menus) */
787 GetTextExtentPoint32A(hdc, lpitem->text, (int)(p - lpitem->text) , &size);
788 lpitem->xTab = check_bitmap_width + MENU_TAB_SPACE + size.cx;
789 lpitem->rect.right += MENU_TAB_SPACE;
790 }
791 else
792 {
793 if (strchr( lpitem->text, '\b' ))
794 lpitem->rect.right += MENU_TAB_SPACE;
795 lpitem->xTab = lpitem->rect.right - check_bitmap_width
796 - arrow_bitmap_width;
797 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000798 }
Juergen Schmied78513941999-04-18 14:40:32 +0000799 TRACE(menu,"(%d,%d)-(%d,%d)\n", lpitem->rect.left, lpitem->rect.top, lpitem->rect.right, lpitem->rect.bottom);
Alexandre Julliardf7207251994-07-23 07:57:48 +0000800}
801
802
803/***********************************************************************
804 * MENU_PopupMenuCalcSize
805 *
806 * Calculate the size of a popup menu.
807 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000808static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND hwndOwner )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000809{
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000810 MENUITEM *lpitem;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000811 HDC hdc;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000812 int start, i;
813 int orgX, orgY, maxX, maxTab, maxTabWidth;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000814
Alexandre Julliardf7207251994-07-23 07:57:48 +0000815 lppop->Width = lppop->Height = 0;
816 if (lppop->nItems == 0) return;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000817 hdc = GetDC( 0 );
Juergen Schmied78513941999-04-18 14:40:32 +0000818
819 SelectObject( hdc, hMenuFont);
820
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000821 start = 0;
822 maxX = SYSMETRICS_CXBORDER;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000823 while (start < lppop->nItems)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000824 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000825 lpitem = &lppop->items[start];
Alexandre Julliardf7207251994-07-23 07:57:48 +0000826 orgX = maxX;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000827 orgY = SYSMETRICS_CYBORDER;
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +0000828
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000829 maxTab = maxTabWidth = 0;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000830
831 /* Parse items until column break or end of menu */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000832 for (i = start; i < lppop->nItems; i++, lpitem++)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000833 {
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000834 if ((i != start) &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000835 (lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000836
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000837 if (TWEAK_WineLook > WIN31_LOOK)
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000838 ++orgY;
839
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000840 MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, FALSE );
Pascal Lessard47274231999-02-13 12:21:46 +0000841
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000842 if (lpitem->fType & MF_MENUBARBREAK) orgX++;
Alexandre Julliard902da691995-11-05 14:39:02 +0000843 maxX = MAX( maxX, lpitem->rect.right );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000844 orgY = lpitem->rect.bottom;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000845 if (IS_STRING_ITEM(lpitem->fType) && lpitem->xTab)
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000846 {
Alexandre Julliard902da691995-11-05 14:39:02 +0000847 maxTab = MAX( maxTab, lpitem->xTab );
848 maxTabWidth = MAX(maxTabWidth,lpitem->rect.right-lpitem->xTab);
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000849 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000850 }
851
852 /* Finish the column (set all items to the largest width found) */
Alexandre Julliard902da691995-11-05 14:39:02 +0000853 maxX = MAX( maxX, maxTab + maxTabWidth );
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000854 for (lpitem = &lppop->items[start]; start < i; start++, lpitem++)
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000855 {
856 lpitem->rect.right = maxX;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000857 if (IS_STRING_ITEM(lpitem->fType) && lpitem->xTab)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000858 lpitem->xTab = maxTab;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000859 }
Alexandre Julliard902da691995-11-05 14:39:02 +0000860 lppop->Height = MAX( lppop->Height, orgY );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000861 }
862
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000863 if(TWEAK_WineLook > WIN31_LOOK)
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +0000864 lppop->Height++;
865
Alexandre Julliardf7207251994-07-23 07:57:48 +0000866 lppop->Width = maxX;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000867 ReleaseDC( 0, hdc );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000868}
869
870
871/***********************************************************************
872 * MENU_MenuBarCalcSize
873 *
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000874 * FIXME: Word 6 implements its own MDI and its own 'close window' bitmap
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000875 * height is off by 1 pixel which causes lengthy window relocations when
876 * active document window is maximized/restored.
877 *
Alexandre Julliardf7207251994-07-23 07:57:48 +0000878 * Calculate the size of the menu bar.
879 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000880static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect,
881 LPPOPUPMENU lppop, HWND hwndOwner )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000882{
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000883 MENUITEM *lpitem;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000884 int start, i, orgX, orgY, maxY, helpPos;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000885
886 if ((lprect == NULL) || (lppop == NULL)) return;
887 if (lppop->nItems == 0) return;
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000888 TRACE(menu,"left=%d top=%d right=%d bottom=%d\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000889 lprect->left, lprect->top, lprect->right, lprect->bottom);
Alexandre Julliardf7207251994-07-23 07:57:48 +0000890 lppop->Width = lprect->right - lprect->left;
891 lppop->Height = 0;
892 maxY = lprect->top;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000893 start = 0;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000894 helpPos = -1;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000895 while (start < lppop->nItems)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000896 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000897 lpitem = &lppop->items[start];
Alexandre Julliardf7207251994-07-23 07:57:48 +0000898 orgX = lprect->left;
899 orgY = maxY;
900
901 /* Parse items until line break or end of menu */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000902 for (i = start; i < lppop->nItems; i++, lpitem++)
Alexandre Julliardf7207251994-07-23 07:57:48 +0000903 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000904 if ((helpPos == -1) && (lpitem->fType & MF_HELP)) helpPos = i;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000905 if ((i != start) &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000906 (lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000907
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000908 TRACE(menu, "calling MENU_CalcItemSize org=(%d, %d)\n",
909 orgX, orgY );
Alexandre Julliard03468f71998-02-15 19:40:49 +0000910 debug_print_menuitem (" item: ", lpitem, "");
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000911 MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, TRUE );
Pascal Lessard47274231999-02-13 12:21:46 +0000912
Alexandre Julliardf7207251994-07-23 07:57:48 +0000913 if (lpitem->rect.right > lprect->right)
914 {
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000915 if (i != start) break;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000916 else lpitem->rect.right = lprect->right;
917 }
Alexandre Julliard902da691995-11-05 14:39:02 +0000918 maxY = MAX( maxY, lpitem->rect.bottom );
Alexandre Julliardf7207251994-07-23 07:57:48 +0000919 orgX = lpitem->rect.right;
920 }
921
922 /* Finish the line (set all items to the largest height found) */
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000923 while (start < i) lppop->items[start++].rect.bottom = maxY;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000924 }
925
926 lprect->bottom = maxY;
927 lppop->Height = lprect->bottom - lprect->top;
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000928
929 /* Flush right all items between the MF_HELP and the last item */
930 /* (if several lines, only move the last line) */
931 if (helpPos != -1)
932 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000933 lpitem = &lppop->items[lppop->nItems-1];
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000934 orgY = lpitem->rect.top;
935 orgX = lprect->right;
936 for (i = lppop->nItems - 1; i >= helpPos; i--, lpitem--)
937 {
938 if (lpitem->rect.top != orgY) break; /* Other line */
939 if (lpitem->rect.right >= orgX) break; /* Too far right already */
940 lpitem->rect.left += orgX - lpitem->rect.right;
941 lpitem->rect.right = orgX;
942 orgX = lpitem->rect.left;
943 }
944 }
Alexandre Julliardf7207251994-07-23 07:57:48 +0000945}
946
Alexandre Julliardf7207251994-07-23 07:57:48 +0000947/***********************************************************************
948 * MENU_DrawMenuItem
949 *
950 * Draw a single menu item.
951 */
Juergen Schmied78513941999-04-18 14:40:32 +0000952static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, MENUITEM *lpitem,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000953 UINT height, BOOL menuBar, UINT odaction )
Alexandre Julliardf7207251994-07-23 07:57:48 +0000954{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000955 RECT rect;
Alexandre Julliardf7207251994-07-23 07:57:48 +0000956
Alexandre Julliard03468f71998-02-15 19:40:49 +0000957 debug_print_menuitem("MENU_DrawMenuItem: ", lpitem, "");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000958
959 if (lpitem->fType & MF_SYSMENU)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000960 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000961 if( !IsIconic(hwnd) ) {
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000962 if (TWEAK_WineLook > WIN31_LOOK)
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000963 NC_DrawSysButton95( hwnd, hdc,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000964 lpitem->fState &
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000965 (MF_HILITE | MF_MOUSESELECT) );
966 else
967 NC_DrawSysButton( hwnd, hdc,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000968 lpitem->fState &
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000969 (MF_HILITE | MF_MOUSESELECT) );
970 }
971
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000972 return;
973 }
974
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000975 if (lpitem->fType & MF_OWNERDRAW)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000976 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000977 DRAWITEMSTRUCT dis;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000978
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000979 dis.CtlType = ODT_MENU;
Juergen Schmied7abca951999-04-11 17:02:30 +0000980 dis.CtlID = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000981 dis.itemID = lpitem->wID;
Juergen Schmied7abca951999-04-11 17:02:30 +0000982 dis.itemData = (DWORD)lpitem->dwItemData;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000983 dis.itemState = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000984 if (lpitem->fState & MF_CHECKED) dis.itemState |= ODS_CHECKED;
985 if (lpitem->fState & MF_GRAYED) dis.itemState |= ODS_GRAYED;
986 if (lpitem->fState & MF_HILITE) dis.itemState |= ODS_SELECTED;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000987 dis.itemAction = odaction; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */
Juergen Schmied78513941999-04-18 14:40:32 +0000988 dis.hwndItem = hmenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000989 dis.hDC = hdc;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000990 dis.rcItem = lpitem->rect;
Juergen Schmied78513941999-04-18 14:40:32 +0000991 TRACE(menu, "Ownerdraw: owner=%04x itemID=%d, itemState=%d, itemAction=%d, "
992 "hwndItem=%04x, hdc=%04x, rcItem={%d,%d,%d,%d}\n", hwndOwner,
993 dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
994 dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right,
995 dis.rcItem.bottom);
996 SendMessageA( hwndOwner, WM_DRAWITEM, 0, (LPARAM)&dis );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000997 return;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000998 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000999
Juergen Schmied78513941999-04-18 14:40:32 +00001000 TRACE(menu, "rect={%d,%d,%d,%d}\n", lpitem->rect.left, lpitem->rect.top,
1001 lpitem->rect.right,lpitem->rect.bottom);
1002
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001003 if (menuBar && (lpitem->fType & MF_SEPARATOR)) return;
Juergen Schmied78513941999-04-18 14:40:32 +00001004
Alexandre Julliardf7207251994-07-23 07:57:48 +00001005 rect = lpitem->rect;
1006
Juergen Schmied78513941999-04-18 14:40:32 +00001007 if ((lpitem->fState & MF_HILITE) && !(IS_BITMAP_ITEM(lpitem->fType)))
1008 if ((menuBar) && (TWEAK_WineLook==WIN98_LOOK))
1009 DrawEdge(hdc, &rect, BDR_SUNKENOUTER, BF_RECT);
1010 else
1011 FillRect( hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT) );
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001012 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001013 FillRect( hdc, &rect, GetSysColorBrush(COLOR_MENU) );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001014
Alexandre Julliarda3960291999-02-26 11:11:13 +00001015 SetBkMode( hdc, TRANSPARENT );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001016
Juergen Schmied78513941999-04-18 14:40:32 +00001017 /* vertical separator */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001018 if (!menuBar && (lpitem->fType & MF_MENUBARBREAK))
Alexandre Julliardf7207251994-07-23 07:57:48 +00001019 {
Juergen Schmied78513941999-04-18 14:40:32 +00001020 if (TWEAK_WineLook > WIN31_LOOK)
1021 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001022 RECT rc = rect;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001023 rc.top = 3;
1024 rc.bottom = height - 3;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001025 DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001026 }
Juergen Schmied78513941999-04-18 14:40:32 +00001027 else
1028 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001029 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1030 MoveTo16( hdc, rect.left, 0 );
1031 LineTo( hdc, rect.left, height );
Alexandre Julliard641ee761997-08-04 16:34:36 +00001032 }
Alexandre Julliardf7207251994-07-23 07:57:48 +00001033 }
Juergen Schmied78513941999-04-18 14:40:32 +00001034
1035 /* horizontal separator */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001036 if (lpitem->fType & MF_SEPARATOR)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001037 {
Juergen Schmied78513941999-04-18 14:40:32 +00001038 if (TWEAK_WineLook > WIN31_LOOK)
1039 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001040 RECT rc = rect;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001041 rc.left++;
1042 rc.right--;
1043 rc.top += SEPARATOR_HEIGHT / 2;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001044 DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001045 }
Juergen Schmied78513941999-04-18 14:40:32 +00001046 else
1047 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001048 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1049 MoveTo16( hdc, rect.left, rect.top + SEPARATOR_HEIGHT/2 );
1050 LineTo( hdc, rect.right, rect.top + SEPARATOR_HEIGHT/2 );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001051 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001052 return;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001053 }
1054
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001055 /* Setup colors */
1056
Juergen Schmied78513941999-04-18 14:40:32 +00001057 if ((lpitem->fState & MF_HILITE) && !(IS_BITMAP_ITEM(lpitem->fType)) )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001058 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001059 if (lpitem->fState & MF_GRAYED)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001060 SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001061 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001062 SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
1063 SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001064 }
1065 else
1066 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001067 if (lpitem->fState & MF_GRAYED)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001068 SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001069 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001070 SetTextColor( hdc, GetSysColor( COLOR_MENUTEXT ) );
1071 SetBkColor( hdc, GetSysColor( COLOR_MENU ) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001072 }
1073
Juergen Schmied78513941999-04-18 14:40:32 +00001074 /* helper lines for debugging */
1075/* FrameRect(hdc, &rect, GetStockObject(BLACK_BRUSH));
1076 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1077 MoveTo16( hdc, rect.left, (rect.top + rect.bottom)/2 );
1078 LineTo( hdc, rect.right, (rect.top + rect.bottom)/2 );
1079*/
1080
Alexandre Julliardf7207251994-07-23 07:57:48 +00001081 if (!menuBar)
1082 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001083 INT y = rect.top + rect.bottom;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001084
1085 /* Draw the check mark
1086 *
Huw D M Davies2d617be1998-12-08 09:14:09 +00001087 * FIXME:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001088 * Custom checkmark bitmaps are monochrome but not always 1bpp.
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001089 */
Alexandre Julliardf7207251994-07-23 07:57:48 +00001090
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001091 if (lpitem->fState & MF_CHECKED)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001092 {
Juergen Schmied78513941999-04-18 14:40:32 +00001093 HBITMAP bm = lpitem->hCheckBit ? lpitem->hCheckBit :
1094 ((lpitem->fType & MFT_RADIOCHECK) ? hStdRadioCheck : hStdCheck);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001095 HDC hdcMem = CreateCompatibleDC( hdc );
Huw D M Davies2d617be1998-12-08 09:14:09 +00001096
Alexandre Julliarda3960291999-02-26 11:11:13 +00001097 SelectObject( hdcMem, bm );
Juergen Schmied78513941999-04-18 14:40:32 +00001098 BitBlt( hdc, rect.left, (y - check_bitmap_height) / 2,
Huw D M Davies2d617be1998-12-08 09:14:09 +00001099 check_bitmap_width, check_bitmap_height,
1100 hdcMem, 0, 0, SRCCOPY );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001101 DeleteDC( hdcMem );
Juergen Schmied78513941999-04-18 14:40:32 +00001102 }
1103 else if (lpitem->hUnCheckBit)
1104 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001105 HDC hdcMem = CreateCompatibleDC( hdc );
Huw D M Davies2d617be1998-12-08 09:14:09 +00001106
Alexandre Julliarda3960291999-02-26 11:11:13 +00001107 SelectObject( hdcMem, lpitem->hUnCheckBit );
Juergen Schmied78513941999-04-18 14:40:32 +00001108 BitBlt( hdc, rect.left, (y - check_bitmap_height) / 2,
Huw D M Davies2d617be1998-12-08 09:14:09 +00001109 check_bitmap_width, check_bitmap_height,
1110 hdcMem, 0, 0, SRCCOPY );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001111 DeleteDC( hdcMem );
Huw D M Davies2d617be1998-12-08 09:14:09 +00001112 }
Juergen Schmied78513941999-04-18 14:40:32 +00001113
Alexandre Julliardf7207251994-07-23 07:57:48 +00001114 /* Draw the popup-menu arrow */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001115 if (lpitem->fType & MF_POPUP)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001116 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001117 HDC hdcMem = CreateCompatibleDC( hdc );
Huw D M Davies2d617be1998-12-08 09:14:09 +00001118
Alexandre Julliarda3960291999-02-26 11:11:13 +00001119 SelectObject( hdcMem, hStdMnArrow );
Juergen Schmied78513941999-04-18 14:40:32 +00001120 BitBlt( hdc, rect.right - arrow_bitmap_width - 1,
Huw D M Davies2d617be1998-12-08 09:14:09 +00001121 (y - arrow_bitmap_height) / 2,
1122 arrow_bitmap_width, arrow_bitmap_height,
1123 hdcMem, 0, 0, SRCCOPY );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001124 DeleteDC( hdcMem );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001125 }
1126
1127 rect.left += check_bitmap_width;
1128 rect.right -= arrow_bitmap_width;
1129 }
1130
Juergen Schmied78513941999-04-18 14:40:32 +00001131 /* Draw the item text or bitmap */
1132 if (IS_BITMAP_ITEM(lpitem->fType))
1133 { int top;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001134
Alexandre Julliarda3960291999-02-26 11:11:13 +00001135 HBITMAP resBmp = 0;
Francois Boisvert8b391741999-02-09 14:09:55 +00001136
Alexandre Julliarda3960291999-02-26 11:11:13 +00001137 HDC hdcMem = CreateCompatibleDC( hdc );
Huw D M Davies2d617be1998-12-08 09:14:09 +00001138
Juergen Schmied78513941999-04-18 14:40:32 +00001139 // Check if there is a magic menu item associated with this item
1140 // and load the appropriate bitmap
1141 if((LOWORD((int)lpitem->text)) < 12)
1142 {
1143 resBmp = MENU_LoadMagicItem((int)lpitem->text, (lpitem->fState & MF_HILITE),
1144 lpitem->dwItemData);
Francois Boisvert8b391741999-02-09 14:09:55 +00001145 }
1146 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001147 resBmp = (HBITMAP)lpitem->text;
Juergen Schmied78513941999-04-18 14:40:32 +00001148
1149 if (resBmp)
1150 {
1151 BITMAP bm;
1152 GetObjectA( resBmp, sizeof(bm), &bm );
1153
1154 SelectObject(hdcMem,resBmp );
1155
1156 /* handle fontsize > bitmap_height */
1157 top = ((rect.bottom-rect.top)>bm.bmHeight) ?
1158 rect.top+(rect.bottom-rect.top-bm.bmHeight)/2 : rect.top;
1159
1160 BitBlt( hdc, rect.left, top, rect.right - rect.left,
Huw D M Davies2d617be1998-12-08 09:14:09 +00001161 rect.bottom - rect.top, hdcMem, 0, 0, SRCCOPY );
Juergen Schmied78513941999-04-18 14:40:32 +00001162 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001163 DeleteDC( hdcMem );
Juergen Schmied78513941999-04-18 14:40:32 +00001164
Alexandre Julliardf7207251994-07-23 07:57:48 +00001165 return;
Francois Boisvert8b391741999-02-09 14:09:55 +00001166
Alexandre Julliardf7207251994-07-23 07:57:48 +00001167 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001168 /* No bitmap - process text if present */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001169 else if (IS_STRING_ITEM(lpitem->fType))
Alexandre Julliardf7207251994-07-23 07:57:48 +00001170 {
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001171 register int i;
Juergen Schmied78513941999-04-18 14:40:32 +00001172 UINT uFormat = (menuBar) ?
1173 DT_CENTER | DT_VCENTER | DT_SINGLELINE :
1174 DT_LEFT | DT_VCENTER | DT_SINGLELINE;
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001175
Alexandre Julliardf7207251994-07-23 07:57:48 +00001176 if (menuBar)
1177 {
1178 rect.left += MENU_BAR_ITEMS_SPACE / 2;
1179 rect.right -= MENU_BAR_ITEMS_SPACE / 2;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001180 i = strlen( lpitem->text );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001181 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001182 else
Alexandre Julliardf7207251994-07-23 07:57:48 +00001183 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001184 for (i = 0; lpitem->text[i]; i++)
1185 if ((lpitem->text[i] == '\t') || (lpitem->text[i] == '\b'))
1186 break;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001187 }
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001188
Juergen Schmied78513941999-04-18 14:40:32 +00001189 if((TWEAK_WineLook == WIN31_LOOK) || !(lpitem->fState & MF_GRAYED))
1190 {
1191 DrawTextA( hdc, lpitem->text, i, &rect, uFormat );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001192 }
Juergen Schmied78513941999-04-18 14:40:32 +00001193 else
1194 { if (!(lpitem->fState & MF_HILITE))
1195 {
Alexandre Julliard641ee761997-08-04 16:34:36 +00001196 ++rect.left;
1197 ++rect.top;
1198 ++rect.right;
1199 ++rect.bottom;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001200 SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
Juergen Schmied78513941999-04-18 14:40:32 +00001201 DrawTextA( hdc, lpitem->text, i, &rect, uFormat );
Alexandre Julliard641ee761997-08-04 16:34:36 +00001202 --rect.left;
1203 --rect.top;
1204 --rect.right;
1205 --rect.bottom;
1206 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001207 SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
Juergen Schmied78513941999-04-18 14:40:32 +00001208 DrawTextA( hdc, lpitem->text, i, &rect, uFormat);
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001209 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001210
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001211 if (lpitem->text[i]) /* There's a tab or flush-right char */
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001212 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001213 if (lpitem->text[i] == '\t')
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001214 {
1215 rect.left = lpitem->xTab;
Juergen Schmied78513941999-04-18 14:40:32 +00001216 DrawTextA( hdc, lpitem->text + i + 1, -1, &rect, uFormat );
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001217 }
Juergen Schmied78513941999-04-18 14:40:32 +00001218 else DrawTextA( hdc, lpitem->text + i + 1, -1, &rect, uFormat );
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001219 }
Alexandre Julliardf7207251994-07-23 07:57:48 +00001220 }
1221}
1222
1223
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001224/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001225 * MENU_DrawPopupMenu
1226 *
1227 * Paint a popup menu.
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001228 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001229static void MENU_DrawPopupMenu( HWND hwnd, HDC hdc, HMENU hmenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001230{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001231 HBRUSH hPrevBrush = 0;
1232 RECT rect;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001233
Juergen Schmied78513941999-04-18 14:40:32 +00001234 TRACE(menu,"wnd=0x%04x dc=0x%04x menu=0x%04x\n", hwnd, hdc, hmenu);
1235
Alexandre Julliarda3960291999-02-26 11:11:13 +00001236 GetClientRect( hwnd, &rect );
Alexandre Julliard641ee761997-08-04 16:34:36 +00001237
Alex Korobka44a1b591999-04-01 12:03:52 +00001238 if(TWEAK_WineLook == WIN31_LOOK)
1239 {
Alexandre Julliard641ee761997-08-04 16:34:36 +00001240 rect.bottom -= POPUP_YSHADE * SYSMETRICS_CYBORDER;
1241 rect.right -= POPUP_XSHADE * SYSMETRICS_CXBORDER;
Alex Korobka44a1b591999-04-01 12:03:52 +00001242 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001243
Juergen Schmied78513941999-04-18 14:40:32 +00001244 if((hPrevBrush = SelectObject( hdc, GetSysColorBrush(COLOR_MENU) ))
1245 && (SelectObject( hdc, hMenuFont)))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001246 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001247 HPEN hPrevPen;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001248
Alexandre Julliarda3960291999-02-26 11:11:13 +00001249 Rectangle( hdc, rect.left, rect.top, rect.right, rect.bottom );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001250
Alexandre Julliarda3960291999-02-26 11:11:13 +00001251 hPrevPen = SelectObject( hdc, GetStockObject( NULL_PEN ) );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001252 if( hPrevPen )
1253 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001254 INT ropPrev, i;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001255 POPUPMENU *menu;
1256
1257 /* draw 3-d shade */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001258 if(TWEAK_WineLook == WIN31_LOOK) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001259 SelectObject( hdc, hShadeBrush );
1260 SetBkMode( hdc, TRANSPARENT );
1261 ropPrev = SetROP2( hdc, R2_MASKPEN );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001262
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001263 i = rect.right; /* why SetBrushOrg() doesn't? */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001264 PatBlt( hdc, i & 0xfffffffe,
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001265 rect.top + POPUP_YSHADE*SYSMETRICS_CYBORDER,
1266 i%2 + POPUP_XSHADE*SYSMETRICS_CXBORDER,
1267 rect.bottom - rect.top, 0x00a000c9 );
1268 i = rect.bottom;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001269 PatBlt( hdc, rect.left + POPUP_XSHADE*SYSMETRICS_CXBORDER,
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001270 i & 0xfffffffe,rect.right - rect.left,
1271 i%2 + POPUP_YSHADE*SYSMETRICS_CYBORDER, 0x00a000c9 );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001272 SelectObject( hdc, hPrevPen );
1273 SelectObject( hdc, hPrevBrush );
1274 SetROP2( hdc, ropPrev );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001275 }
1276 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001277 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001278
1279 /* draw menu items */
1280
1281 menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
1282 if (menu && menu->nItems)
1283 {
1284 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001285 UINT u;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001286
1287 for (u = menu->nItems, item = menu->items; u > 0; u--, item++)
Juergen Schmied78513941999-04-18 14:40:32 +00001288 MENU_DrawMenuItem( hwnd, hmenu, menu->hwndOwner, hdc, item,
1289 menu->Height, FALSE, ODA_DRAWENTIRE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001290
1291 }
Juergen Schmied78513941999-04-18 14:40:32 +00001292 } else
1293 {
1294 SelectObject( hdc, hPrevBrush );
1295 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001296 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001297}
1298
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001299/***********************************************************************
1300 * MENU_DrawMenuBar
1301 *
1302 * Paint a menu bar. Returns the height of the menu bar.
Juergen Schmied78513941999-04-18 14:40:32 +00001303 * called from [windows/nonclient.c]
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001304 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001305UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd,
1306 BOOL suppress_draw)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001307{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001308 LPPOPUPMENU lppop;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001309 UINT i,retvalue;
Juergen Schmied78513941999-04-18 14:40:32 +00001310 HFONT hfontOld = 0;
1311
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001312 WND *wndPtr = WIN_FindWndPtr( hwnd );
1313
Juergen Schmied78513941999-04-18 14:40:32 +00001314 lppop = (LPPOPUPMENU) USER_HEAP_LIN_ADDR( (HMENU)wndPtr->wIDmenu );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001315 if (lppop == NULL || lprect == NULL)
1316 {
1317 retvalue = SYSMETRICS_CYMENU;
1318 goto END;
1319 }
Juergen Schmied78513941999-04-18 14:40:32 +00001320
1321 TRACE(menu,"(%04x, %p, %p)\n", hDC, lprect, lppop);
1322
1323 hfontOld = SelectObject( hDC, hMenuFont);
1324
1325 if (lppop->Height == 0)
1326 MENU_MenuBarCalcSize(hDC, lprect, lppop, hwnd);
1327
Alexandre Julliard940d58c1994-09-16 09:24:37 +00001328 lprect->bottom = lprect->top + lppop->Height;
Juergen Schmied78513941999-04-18 14:40:32 +00001329
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001330 if (suppress_draw)
1331 {
1332 retvalue = lppop->Height;
1333 goto END;
1334 }
Juergen Schmied78513941999-04-18 14:40:32 +00001335
Alexandre Julliarda3960291999-02-26 11:11:13 +00001336 FillRect(hDC, lprect, GetSysColorBrush(COLOR_MENU) );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001337
Juergen Schmied78513941999-04-18 14:40:32 +00001338 if (TWEAK_WineLook == WIN31_LOOK)
1339 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001340 SelectObject( hDC, GetSysColorPen(COLOR_WINDOWFRAME) );
1341 MoveTo16( hDC, lprect->left, lprect->bottom );
1342 LineTo( hDC, lprect->right, lprect->bottom );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001343 }
Juergen Schmied78513941999-04-18 14:40:32 +00001344 else
1345 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001346 SelectObject( hDC, GetSysColorPen(COLOR_3DFACE));
1347 MoveTo16( hDC, lprect->left, lprect->bottom );
1348 LineTo( hDC, lprect->right, lprect->bottom );
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001349 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001350
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001351 if (lppop->nItems == 0)
1352 {
1353 retvalue = SYSMETRICS_CYMENU;
1354 goto END;
1355 }
Juergen Schmied78513941999-04-18 14:40:32 +00001356
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001357 for (i = 0; i < lppop->nItems; i++)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001358 {
Juergen Schmied78513941999-04-18 14:40:32 +00001359 MENU_DrawMenuItem( hwnd, (HMENU)wndPtr->wIDmenu, GetWindow(hwnd,GW_OWNER),
1360 hDC, &lppop->items[i], lppop->Height, TRUE, ODA_DRAWENTIRE );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001361 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001362 retvalue = lppop->Height;
Juergen Schmied78513941999-04-18 14:40:32 +00001363
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001364END:
Juergen Schmied78513941999-04-18 14:40:32 +00001365 if (hfontOld)
1366 SelectObject (hDC, hfontOld);
1367
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001368 WIN_ReleaseWndPtr(wndPtr);
1369 return retvalue;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001370}
1371
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001372/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001373 * MENU_PatchResidentPopup
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001374 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001375BOOL MENU_PatchResidentPopup( HQUEUE16 checkQueue, WND* checkWnd )
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001376{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001377 WND *pTPWnd = MENU_GetTopPopupWnd();
1378
1379 if( pTPWnd )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001380 {
1381 HTASK16 hTask = 0;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001382
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001383 TRACE(menu,"patching resident popup: %04x %04x [%04x %04x]\n",
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001384 checkQueue, checkWnd ? checkWnd->hwndSelf : 0, pTPWnd->hmemTaskQ,
1385 pTPWnd->owner ? pTPWnd->owner->hwndSelf : 0);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001386
Alexandre Julliard77b99181997-09-14 17:17:23 +00001387 switch( checkQueue )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001388 {
Alexandre Julliard77b99181997-09-14 17:17:23 +00001389 case 0: /* checkWnd is the new popup owner */
1390 if( checkWnd )
1391 {
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001392 pTPWnd->owner = checkWnd;
1393 if( pTPWnd->hmemTaskQ != checkWnd->hmemTaskQ )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001394 hTask = QUEUE_GetQueueTask( checkWnd->hmemTaskQ );
1395 }
1396 break;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001397
Alexandre Julliard77b99181997-09-14 17:17:23 +00001398 case 0xFFFF: /* checkWnd is destroyed */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001399 if( pTPWnd->owner == checkWnd )
1400 pTPWnd->owner = NULL;
1401 MENU_ReleaseTopPopupWnd();
Alexandre Julliard77b99181997-09-14 17:17:23 +00001402 return TRUE;
1403
1404 default: /* checkQueue is exiting */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001405 if( pTPWnd->hmemTaskQ == checkQueue )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001406 {
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001407 hTask = QUEUE_GetQueueTask( pTPWnd->hmemTaskQ );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001408 hTask = TASK_GetNextTask( hTask );
1409 }
1410 break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001411 }
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001412
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001413 if( hTask )
1414 {
1415 TDB* task = (TDB*)GlobalLock16( hTask );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001416 if( task )
1417 {
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001418 pTPWnd->hInstance = task->hInstance;
1419 pTPWnd->hmemTaskQ = task->hQueue;
1420 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001421 return TRUE;
1422 }
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001423 else WARN(menu,"failed to patch resident popup.\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001424 }
1425 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001426 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001427 return FALSE;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001428}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001429
1430/***********************************************************************
1431 * MENU_ShowPopup
1432 *
1433 * Display a popup menu.
1434 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001435static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id,
1436 INT x, INT y, INT xanchor, INT yanchor )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001437{
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001438 POPUPMENU *menu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001439 WND *wndOwner = NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001440
Juergen Schmied78513941999-04-18 14:40:32 +00001441 TRACE(menu,"owner=0x%04x hmenu=0x%04x id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n",
1442 hwndOwner, hmenu, id, x, y, xanchor, yanchor);
1443
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00001444 if (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu ))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001445 if (menu->FocusedItem != NO_SELECTED_ITEM)
1446 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001447 menu->items[menu->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001448 menu->FocusedItem = NO_SELECTED_ITEM;
1449 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001450
Juergen Schmied78513941999-04-18 14:40:32 +00001451 /* store the owner for DrawItem*/
1452 menu->hwndOwner = hwndOwner;
1453
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001454 if( (wndOwner = WIN_FindWndPtr( hwndOwner )) )
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001455 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001456 UINT width, height;
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001457
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001458 MENU_PopupMenuCalcSize( menu, hwndOwner );
1459
1460 /* adjust popup menu pos so that it fits within the desktop */
1461
1462 width = menu->Width + SYSMETRICS_CXBORDER;
1463 height = menu->Height + SYSMETRICS_CYBORDER;
1464
1465 if( x + width > SYSMETRICS_CXSCREEN )
1466 {
1467 if( xanchor )
1468 x -= width - xanchor;
1469 if( x + width > SYSMETRICS_CXSCREEN)
1470 x = SYSMETRICS_CXSCREEN - width;
1471 }
1472 if( x < 0 ) x = 0;
1473
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001474 if( y + height > SYSMETRICS_CYSCREEN )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001475 {
1476 if( yanchor )
1477 y -= height + yanchor;
1478 if( y + height > SYSMETRICS_CYSCREEN )
1479 y = SYSMETRICS_CYSCREEN - height;
1480 }
1481 if( y < 0 ) y = 0;
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001482
Alex Korobka44a1b591999-04-01 12:03:52 +00001483 if( TWEAK_WineLook == WIN31_LOOK )
1484 {
1485 width += POPUP_XSHADE * SYSMETRICS_CXBORDER; /* add space for shading */
1486 height += POPUP_YSHADE * SYSMETRICS_CYBORDER;
1487 }
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001488
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001489 /* NOTE: In Windows, top menu popup is not owned. */
1490 if (!pTopPopupWnd) /* create top level popup menu window */
1491 {
1492 assert( uSubPWndLevel == 0 );
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001493
Alexandre Julliarda3960291999-02-26 11:11:13 +00001494 pTopPopupWnd = WIN_FindWndPtr(CreateWindowA( POPUPMENU_CLASS_ATOM, NULL,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001495 WS_POPUP, x, y, width, height,
1496 hwndOwner, 0, wndOwner->hInstance,
1497 (LPVOID)hmenu ));
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001498 if (!pTopPopupWnd)
1499 {
1500 WIN_ReleaseWndPtr(wndOwner);
1501 return FALSE;
1502 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001503 menu->hWnd = pTopPopupWnd->hwndSelf;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001504 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001505 }
1506 else
1507 if( uSubPWndLevel )
1508 {
1509 /* create a new window for the submenu */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001510
Alexandre Julliarda3960291999-02-26 11:11:13 +00001511 menu->hWnd = CreateWindowA( POPUPMENU_CLASS_ATOM, NULL,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001512 WS_POPUP, x, y, width, height,
Juergen Schmied78513941999-04-18 14:40:32 +00001513 hwndOwner, 0, wndOwner->hInstance,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001514 (LPVOID)hmenu );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001515 if( !menu->hWnd )
1516 {
1517 WIN_ReleaseWndPtr(wndOwner);
1518 return FALSE;
1519 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001520 }
1521 else /* top level popup menu window already exists */
1522 {
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001523 WND *pTPWnd = MENU_GetTopPopupWnd();
1524 menu->hWnd = pTPWnd->hwndSelf;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001525
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001526 MENU_PatchResidentPopup( 0, wndOwner );
Juergen Schmied78513941999-04-18 14:40:32 +00001527 SendMessageA( pTPWnd->hwndSelf, MM_SETMENUHANDLE, (WPARAM16)hmenu, 0L);
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001528
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001529 /* adjust its size */
1530
Alexandre Julliarda3960291999-02-26 11:11:13 +00001531 SetWindowPos( menu->hWnd, 0, x, y, width, height,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001532 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001533 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001534 }
1535
1536 uSubPWndLevel++; /* menu level counter */
1537
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001538 /* Display the window */
1539
Alexandre Julliarda3960291999-02-26 11:11:13 +00001540 SetWindowPos( menu->hWnd, HWND_TOP, 0, 0, 0, 0,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001541 SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001542 UpdateWindow( menu->hWnd );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001543 WIN_ReleaseWndPtr(wndOwner);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001544 return TRUE;
1545 }
1546 return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001547}
1548
1549
1550/***********************************************************************
1551 * MENU_SelectItem
1552 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001553static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, UINT wIndex,
1554 BOOL sendMenuSelect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001555{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001556 LPPOPUPMENU lppop;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001557 HDC hdc;
Alexandre Julliardf7207251994-07-23 07:57:48 +00001558
Juergen Schmied78513941999-04-18 14:40:32 +00001559 TRACE(menu, "owner=0x%04x menu=0x%04x index=0x%04x select=0x%04x\n", hwndOwner, hmenu, wIndex, sendMenuSelect);
1560
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00001561 lppop = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001562 if (!lppop->nItems) return;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001563
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001564 if ((wIndex != NO_SELECTED_ITEM) &&
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001565 (lppop->items[wIndex].fType & MF_SEPARATOR))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001566 wIndex = NO_SELECTED_ITEM;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001567
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001568 if (lppop->FocusedItem == wIndex) return;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001569 if (lppop->wFlags & MF_POPUP) hdc = GetDC( lppop->hWnd );
1570 else hdc = GetDCEx( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW);
Alexandre Julliardf7207251994-07-23 07:57:48 +00001571
Juergen Schmied78513941999-04-18 14:40:32 +00001572 SelectObject( hdc, hMenuFont);
1573
Alexandre Julliardf7207251994-07-23 07:57:48 +00001574 /* Clear previous highlighted item */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001575 if (lppop->FocusedItem != NO_SELECTED_ITEM)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001576 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001577 lppop->items[lppop->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
Juergen Schmied78513941999-04-18 14:40:32 +00001578 MENU_DrawMenuItem(lppop->hWnd, hmenu, hwndOwner, hdc,&lppop->items[lppop->FocusedItem],
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001579 lppop->Height, !(lppop->wFlags & MF_POPUP),
1580 ODA_SELECT );
Alexandre Julliardf7207251994-07-23 07:57:48 +00001581 }
1582
1583 /* Highlight new item (if any) */
1584 lppop->FocusedItem = wIndex;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001585 if (lppop->FocusedItem != NO_SELECTED_ITEM)
Alexandre Julliardf7207251994-07-23 07:57:48 +00001586 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001587 lppop->items[lppop->FocusedItem].fState |= MF_HILITE;
Juergen Schmied78513941999-04-18 14:40:32 +00001588 MENU_DrawMenuItem( lppop->hWnd, hmenu, hwndOwner, hdc, &lppop->items[lppop->FocusedItem],
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001589 lppop->Height, !(lppop->wFlags & MF_POPUP),
1590 ODA_SELECT );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001591 if (sendMenuSelect)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001592 {
1593 MENUITEM *ip = &lppop->items[lppop->FocusedItem];
Juergen Schmied78513941999-04-18 14:40:32 +00001594 SendMessageA( hwndOwner, WM_MENUSELECT,
1595 MAKELONG(ip->wID,ip->fType | (ip->fState | MF_MOUSESELECT)), hmenu);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001596 }
Alexandre Julliardf7207251994-07-23 07:57:48 +00001597 }
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001598 else if (sendMenuSelect) {
Juergen Schmied78513941999-04-18 14:40:32 +00001599 SendMessageA( hwndOwner, WM_MENUSELECT,
1600 MAKELONG( hmenu, lppop->wFlags | MF_MOUSESELECT), hmenu );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001601 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001602 ReleaseDC( lppop->hWnd, hdc );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001603}
1604
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001605
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001606/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001607 * MENU_MoveSelection
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001608 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001609 * Moves currently selected item according to the offset parameter.
1610 * If there is no selection then it should select the last item if
1611 * offset is ITEM_PREV or the first item if offset is ITEM_NEXT.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001612 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001613static void MENU_MoveSelection( HWND hwndOwner, HMENU hmenu, INT offset )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001614{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001615 INT i;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001616 POPUPMENU *menu;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001617
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00001618 menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001619 if (!menu->items) return;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001620
1621 if ( menu->FocusedItem != NO_SELECTED_ITEM )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001622 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001623 if( menu->nItems == 1 ) return; else
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001624 for (i = menu->FocusedItem + offset ; i >= 0 && i < menu->nItems
1625 ; i += offset)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001626 if (!(menu->items[i].fType & MF_SEPARATOR))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001627 {
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001628 MENU_SelectItem( hwndOwner, hmenu, i, TRUE );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001629 return;
1630 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001631 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001632
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001633 for ( i = (offset > 0) ? 0 : menu->nItems - 1;
1634 i >= 0 && i < menu->nItems ; i += offset)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001635 if (!(menu->items[i].fType & MF_SEPARATOR))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001636 {
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001637 MENU_SelectItem( hwndOwner, hmenu, i, TRUE );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001638 return;
1639 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001640}
1641
1642
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001643/**********************************************************************
1644 * MENU_SetItemData
1645 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001646 * Set an item flags, id and text ptr. Called by InsertMenu() and
1647 * ModifyMenu().
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001648 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001649static BOOL MENU_SetItemData( MENUITEM *item, UINT flags, UINT id,
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001650 LPCSTR str )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001651{
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001652 LPSTR prevText = IS_STRING_ITEM(item->fType) ? item->text : NULL;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001653
Alexandre Julliard03468f71998-02-15 19:40:49 +00001654 debug_print_menuitem("MENU_SetItemData from: ", item, "");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001655
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001656 if (IS_STRING_ITEM(flags))
1657 {
Alexandre Julliard491502b1997-11-01 19:08:16 +00001658 if (!str || !*str)
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001659 {
1660 flags |= MF_SEPARATOR;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001661 item->text = NULL;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001662 }
1663 else
1664 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001665 LPSTR text;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001666 /* Item beginning with a backspace is a help item */
1667 if (*str == '\b')
1668 {
1669 flags |= MF_HELP;
1670 str++;
1671 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001672 if (!(text = HEAP_strdupA( SystemHeap, 0, str ))) return FALSE;
1673 item->text = text;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001674 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001675 }
Juergen Schmied78513941999-04-18 14:40:32 +00001676 else if (IS_BITMAP_ITEM(flags))
1677 item->text = (LPSTR)(HBITMAP)LOWORD(str);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001678 else item->text = NULL;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001679
Alexandre Julliarda845b881998-06-01 10:44:35 +00001680 if (flags & MF_OWNERDRAW)
1681 item->dwItemData = (DWORD)str;
1682 else
1683 item->dwItemData = 0;
1684
Alexandre Julliard02e90081998-01-04 17:49:09 +00001685 if ((item->fType & MF_POPUP) && (flags & MF_POPUP) && (item->hSubMenu != id) )
Alexandre Julliarda3960291999-02-26 11:11:13 +00001686 DestroyMenu( item->hSubMenu ); /* ModifyMenu() spec */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001687
1688 if (flags & MF_POPUP)
1689 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001690 POPUPMENU *menu = (POPUPMENU *)USER_HEAP_LIN_ADDR((UINT16)id);
1691 if (IS_A_MENU(menu)) menu->wFlags |= MF_POPUP;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001692 else
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001693 {
1694 item->wID = 0;
1695 item->hSubMenu = 0;
1696 item->fType = 0;
1697 item->fState = 0;
1698 return FALSE;
1699 }
Alexandre Julliard02e90081998-01-04 17:49:09 +00001700 }
1701
1702 item->wID = id;
1703 if (flags & MF_POPUP)
1704 item->hSubMenu = id;
1705
1706 if ((item->fType & MF_POPUP) && !(flags & MF_POPUP) )
1707 flags |= MF_POPUP; /* keep popup */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001708
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001709 item->fType = flags & TYPE_MASK;
1710 item->fState = (flags & STATE_MASK) &
1711 ~(MF_HILITE | MF_MOUSESELECT | MF_BYPOSITION);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001712
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001713
1714 /* Don't call SetRectEmpty here! */
1715
1716
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001717 if (prevText) HeapFree( SystemHeap, 0, prevText );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001718
Alexandre Julliard03468f71998-02-15 19:40:49 +00001719 debug_print_menuitem("MENU_SetItemData to : ", item, "");
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001720 return TRUE;
1721}
1722
1723
1724/**********************************************************************
1725 * MENU_InsertItem
1726 *
1727 * Insert a new item into a menu.
1728 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001729static MENUITEM *MENU_InsertItem( HMENU hMenu, UINT pos, UINT flags )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001730{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001731 MENUITEM *newItems;
1732 POPUPMENU *menu;
1733
1734 if (!(menu = (POPUPMENU *)USER_HEAP_LIN_ADDR(hMenu)))
1735 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001736 WARN(menu, "%04x not a menu handle\n",
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001737 hMenu );
1738 return NULL;
1739 }
1740
1741 /* Find where to insert new item */
1742
1743 if ((flags & MF_BYPOSITION) &&
Alexandre Julliarda3960291999-02-26 11:11:13 +00001744 ((pos == (UINT)-1) || (pos == menu->nItems)))
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001745 {
1746 /* Special case: append to menu */
1747 /* Some programs specify the menu length to do that */
1748 pos = menu->nItems;
1749 }
1750 else
1751 {
1752 if (!MENU_FindItem( &hMenu, &pos, flags ))
1753 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001754 WARN(menu, "item %x not found\n",
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001755 pos );
1756 return NULL;
1757 }
1758 if (!(menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu)))
1759 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001760 WARN(menu,"%04x not a menu handle\n",
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001761 hMenu);
1762 return NULL;
1763 }
1764 }
1765
1766 /* Create new items array */
1767
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001768 newItems = HeapAlloc( SystemHeap, 0, sizeof(MENUITEM) * (menu->nItems+1) );
1769 if (!newItems)
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001770 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001771 WARN(menu, "allocation failed\n" );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001772 return NULL;
1773 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001774 if (menu->nItems > 0)
1775 {
1776 /* Copy the old array into the new */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001777 if (pos > 0) memcpy( newItems, menu->items, pos * sizeof(MENUITEM) );
1778 if (pos < menu->nItems) memcpy( &newItems[pos+1], &menu->items[pos],
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001779 (menu->nItems-pos)*sizeof(MENUITEM) );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001780 HeapFree( SystemHeap, 0, menu->items );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001781 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001782 menu->items = newItems;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001783 menu->nItems++;
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001784 memset( &newItems[pos], 0, sizeof(*newItems) );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001785 return &newItems[pos];
1786}
1787
1788
1789/**********************************************************************
1790 * MENU_ParseResource
1791 *
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001792 * Parse a standard menu resource and add items to the menu.
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001793 * Return a pointer to the end of the resource.
1794 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001795static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001796{
1797 WORD flags, id = 0;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001798 LPCSTR str;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001799
1800 do
1801 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001802 flags = GET_WORD(res);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001803 res += sizeof(WORD);
1804 if (!(flags & MF_POPUP))
1805 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001806 id = GET_WORD(res);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001807 res += sizeof(WORD);
1808 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001809 if (!IS_STRING_ITEM(flags))
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001810 ERR(menu, "not a string item %04x\n", flags );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001811 str = res;
1812 if (!unicode) res += strlen(str) + 1;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001813 else res += (lstrlenW((LPCWSTR)str) + 1) * sizeof(WCHAR);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001814 if (flags & MF_POPUP)
1815 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001816 HMENU hSubMenu = CreatePopupMenu();
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001817 if (!hSubMenu) return NULL;
1818 if (!(res = MENU_ParseResource( res, hSubMenu, unicode )))
1819 return NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001820 if (!unicode) AppendMenuA( hMenu, flags, (UINT)hSubMenu, str );
1821 else AppendMenuW( hMenu, flags, (UINT)hSubMenu, (LPCWSTR)str );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001822 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001823 else /* Not a popup */
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001824 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001825 if (!unicode) AppendMenuA( hMenu, flags, id, *str ? str : NULL );
1826 else AppendMenuW( hMenu, flags, id,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001827 *(LPCWSTR)str ? (LPCWSTR)str : NULL );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001828 }
1829 } while (!(flags & MF_END));
1830 return res;
1831}
1832
1833
Alexandre Julliard641ee761997-08-04 16:34:36 +00001834/**********************************************************************
1835 * MENUEX_ParseResource
1836 *
1837 * Parse an extended menu resource and add items to the menu.
1838 * Return a pointer to the end of the resource.
1839 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001840static LPCSTR MENUEX_ParseResource( LPCSTR res, HMENU hMenu)
Alexandre Julliard641ee761997-08-04 16:34:36 +00001841{
Alexandre Julliard641ee761997-08-04 16:34:36 +00001842 WORD resinfo;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001843 do {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001844 MENUITEMINFOW mii;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001845
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001846 mii.cbSize = sizeof(mii);
1847 mii.fMask = MIIM_STATE | MIIM_ID | MIIM_TYPE;
1848 mii.fType = GET_DWORD(res);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001849 res += sizeof(DWORD);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001850 mii.fState = GET_DWORD(res);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001851 res += sizeof(DWORD);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001852 mii.wID = GET_DWORD(res);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001853 res += sizeof(DWORD);
1854 resinfo = GET_WORD(res); /* FIXME: for 16-bit apps this is a byte. */
1855 res += sizeof(WORD);
1856 /* Align the text on a word boundary. */
1857 res += (~((int)res - 1)) & 1;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001858 mii.dwTypeData = (LPWSTR) res;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001859 res += (1 + lstrlenW(mii.dwTypeData)) * sizeof(WCHAR);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001860 /* Align the following fields on a dword boundary. */
1861 res += (~((int)res - 1)) & 3;
1862
1863 /* FIXME: This is inefficient and cannot be optimised away by gcc. */
1864 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001865 LPSTR newstr = HEAP_strdupWtoA(GetProcessHeap(),
1866 0, mii.dwTypeData);
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001867 TRACE(menu, "Menu item: [%08x,%08x,%04x,%04x,%s]\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001868 mii.fType, mii.fState, mii.wID, resinfo, newstr);
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001869 HeapFree( GetProcessHeap(), 0, newstr );
Alexandre Julliard641ee761997-08-04 16:34:36 +00001870 }
1871
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001872 if (resinfo & 1) { /* Pop-up? */
Marcus Meissnerde43ef41999-02-28 19:56:59 +00001873 /* DWORD helpid = GET_DWORD(res); FIXME: use this. */
Alexandre Julliard641ee761997-08-04 16:34:36 +00001874 res += sizeof(DWORD);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001875 mii.hSubMenu = CreatePopupMenu();
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001876 if (!mii.hSubMenu)
1877 return NULL;
1878 if (!(res = MENUEX_ParseResource(res, mii.hSubMenu))) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001879 DestroyMenu(mii.hSubMenu);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001880 return NULL;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001881 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001882 mii.fMask |= MIIM_SUBMENU;
1883 mii.fType |= MF_POPUP;
Alexandre Julliard641ee761997-08-04 16:34:36 +00001884 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001885 InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii);
Alexandre Julliard641ee761997-08-04 16:34:36 +00001886 } while (!(resinfo & MF_END));
1887 return res;
1888}
1889
1890
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001891/***********************************************************************
1892 * MENU_GetSubPopup
1893 *
1894 * Return the handle of the selected sub-popup menu (if any).
1895 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001896static HMENU MENU_GetSubPopup( HMENU hmenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001897{
1898 POPUPMENU *menu;
1899 MENUITEM *item;
1900
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00001901 menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001902
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001903 if (menu->FocusedItem == NO_SELECTED_ITEM) return 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001904
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001905 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001906 if ((item->fType & MF_POPUP) && (item->fState & MF_MOUSESELECT))
1907 return item->hSubMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001908 return 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001909}
1910
1911
1912/***********************************************************************
1913 * MENU_HideSubPopups
1914 *
1915 * Hide the sub-popup menus of this menu.
1916 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001917static void MENU_HideSubPopups( HWND hwndOwner, HMENU hmenu,
1918 BOOL sendMenuSelect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001919{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001920 POPUPMENU *menu = (POPUPMENU*) USER_HEAP_LIN_ADDR( hmenu );;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001921
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001922 if (menu && uSubPWndLevel)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001923 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001924 HMENU hsubmenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001925 POPUPMENU *submenu;
1926 MENUITEM *item;
1927
1928 if (menu->FocusedItem != NO_SELECTED_ITEM)
1929 {
1930 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001931 if (!(item->fType & MF_POPUP) ||
1932 !(item->fState & MF_MOUSESELECT)) return;
1933 item->fState &= ~MF_MOUSESELECT;
1934 hsubmenu = item->hSubMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001935 } else return;
1936
1937 submenu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hsubmenu );
1938 MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE );
1939 MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect );
1940
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001941 if (submenu->hWnd == MENU_GetTopPopupWnd()->hwndSelf )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001942 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001943 ShowWindow( submenu->hWnd, SW_HIDE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001944 uSubPWndLevel = 0;
1945 }
1946 else
1947 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001948 DestroyWindow( submenu->hWnd );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001949 submenu->hWnd = 0;
1950 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001951 MENU_ReleaseTopPopupWnd();
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001952 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001953}
1954
1955
1956/***********************************************************************
1957 * MENU_ShowSubPopup
1958 *
1959 * Display the sub-menu of the selected item of this menu.
1960 * Return the handle of the submenu, or hmenu if no submenu to display.
1961 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001962static HMENU MENU_ShowSubPopup( HWND hwndOwner, HMENU hmenu,
1963 BOOL selectFirst )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001964{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001965 RECT rect;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001966 POPUPMENU *menu;
1967 MENUITEM *item;
1968 WND *wndPtr;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001969 HDC hdc;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001970
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00001971 if (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu ))) return hmenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001972
1973 if (!(wndPtr = WIN_FindWndPtr( menu->hWnd )) ||
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001974 (menu->FocusedItem == NO_SELECTED_ITEM))
1975 {
1976 WIN_ReleaseWndPtr(wndPtr);
1977 return hmenu;
1978 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001979
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001980 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001981 if (!(item->fType & MF_POPUP) ||
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001982 (item->fState & (MF_GRAYED | MF_DISABLED)))
1983 {
1984 WIN_ReleaseWndPtr(wndPtr);
1985 return hmenu;
1986 }
Alexandre Julliard02e90081998-01-04 17:49:09 +00001987
1988 /* message must be send before using item,
1989 because nearly everything may by changed by the application ! */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001990
Juergen Schmied78513941999-04-18 14:40:32 +00001991 SendMessageA( hwndOwner, WM_INITMENUPOPUP, item->hSubMenu,
Alexandre Julliard02e90081998-01-04 17:49:09 +00001992 MAKELONG( menu->FocusedItem, IS_SYSTEM_MENU(menu) ));
1993
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001994 item = &menu->items[menu->FocusedItem];
1995 rect = item->rect;
1996
Alexandre Julliard02e90081998-01-04 17:49:09 +00001997 /* correct item if modified as a reaction to WM_INITMENUPOPUP-message */
1998 if (!(item->fState & MF_HILITE))
1999 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002000 if (menu->wFlags & MF_POPUP) hdc = GetDC( menu->hWnd );
2001 else hdc = GetDCEx( menu->hWnd, 0, DCX_CACHE | DCX_WINDOW);
Juergen Schmied78513941999-04-18 14:40:32 +00002002
2003 SelectObject( hdc, hMenuFont);
2004
Alexandre Julliard02e90081998-01-04 17:49:09 +00002005 item->fState |= MF_HILITE;
Juergen Schmied78513941999-04-18 14:40:32 +00002006 MENU_DrawMenuItem( menu->hWnd, hmenu, hwndOwner, hdc, item, menu->Height, !(menu->wFlags & MF_POPUP), ODA_DRAWENTIRE );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002007 ReleaseDC( menu->hWnd, hdc );
Alexandre Julliard02e90081998-01-04 17:49:09 +00002008 }
2009 if (!item->rect.top && !item->rect.left && !item->rect.bottom && !item->rect.right)
2010 item->rect = rect;
2011
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002012 item->fState |= MF_MOUSESELECT;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002013
2014 if (IS_SYSTEM_MENU(menu))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002015 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002016 MENU_InitSysMenuPopup(item->hSubMenu, wndPtr->dwStyle, wndPtr->class->style);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002017
2018 NC_GetSysPopupPos( wndPtr, &rect );
2019 rect.top = rect.bottom;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002020 rect.right = SYSMETRICS_CXSIZE;
2021 rect.bottom = SYSMETRICS_CYSIZE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002022 }
2023 else
2024 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002025 if (menu->wFlags & MF_POPUP)
2026 {
2027 rect.left = wndPtr->rectWindow.left + item->rect.right-arrow_bitmap_width;
2028 rect.top = wndPtr->rectWindow.top + item->rect.top;
2029 rect.right = item->rect.left - item->rect.right + 2*arrow_bitmap_width;
2030 rect.bottom = item->rect.top - item->rect.bottom;
2031 }
2032 else
2033 {
2034 rect.left = wndPtr->rectWindow.left + item->rect.left;
2035 rect.top = wndPtr->rectWindow.top + item->rect.bottom;
2036 rect.right = item->rect.right - item->rect.left;
2037 rect.bottom = item->rect.bottom - item->rect.top;
2038 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002039 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002040
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002041 MENU_ShowPopup( hwndOwner, item->hSubMenu, menu->FocusedItem,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002042 rect.left, rect.top, rect.right, rect.bottom );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002043 if (selectFirst)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002044 MENU_MoveSelection( hwndOwner, item->hSubMenu, ITEM_NEXT );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002045 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002046 return item->hSubMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002047}
2048
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002049/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002050 * MENU_PtMenu
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002051 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002052 * Walks menu chain trying to find a menu pt maps to.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002053 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002054static HMENU MENU_PtMenu( HMENU hMenu, POINT16 pt )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002055{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002056 POPUPMENU *menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hMenu );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002057 register UINT ht = menu->FocusedItem;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002058
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002059 /* try subpopup first (if any) */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002060 ht = (ht != NO_SELECTED_ITEM &&
2061 (menu->items[ht].fType & MF_POPUP) &&
2062 (menu->items[ht].fState & MF_MOUSESELECT))
Alexandre Julliarda3960291999-02-26 11:11:13 +00002063 ? (UINT) MENU_PtMenu(menu->items[ht].hSubMenu, pt) : 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002064
2065 if( !ht ) /* check the current window (avoiding WM_HITTEST) */
2066 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002067 ht = (UINT)NC_HandleNCHitTest( menu->hWnd, pt );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002068 if( menu->wFlags & MF_POPUP )
Alexandre Julliarda3960291999-02-26 11:11:13 +00002069 ht = (ht != (UINT)HTNOWHERE &&
2070 ht != (UINT)HTERROR) ? (UINT)hMenu : 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002071 else
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002072 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002073 WND* wndPtr = WIN_FindWndPtr(menu->hWnd);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002074
Alexandre Julliarda3960291999-02-26 11:11:13 +00002075 ht = ( ht == HTSYSMENU ) ? (UINT)(wndPtr->hSysMenu)
2076 : ( ht == HTMENU ) ? (UINT)(wndPtr->wIDmenu) : 0;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002077 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002078 }
2079 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002080 return (HMENU)ht;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002081}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002082/***********************************************************************
2083 * MENU_ExecFocusedItem
2084 *
2085 * Execute a menu item (for instance when user pressed Enter).
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002086 * Return the wID of the executed item. Otherwise, zero indicating
2087 * that no menu item wase executed;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002088 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002089static INT MENU_ExecFocusedItem( MTRACKER* pmt, HMENU hMenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002090{
2091 MENUITEM *item;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002092 POPUPMENU *menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hMenu );
2093 if (!menu || !menu->nItems ||
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002094 (menu->FocusedItem == NO_SELECTED_ITEM)) return 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002095
Alexandre Julliard2d93d001996-05-21 15:01:41 +00002096 item = &menu->items[menu->FocusedItem];
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002097
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002098 TRACE(menu, "%08x %08x %08x\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002099 hMenu, item->wID, item->hSubMenu);
2100
2101 if (!(item->fType & MF_POPUP))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002102 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002103 if (!(item->fState & (MF_GRAYED | MF_DISABLED)))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002104 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002105 if( menu->wFlags & MF_SYSMENU )
2106 {
Juergen Schmied78513941999-04-18 14:40:32 +00002107 PostMessageA( pmt->hOwnerWnd, WM_SYSCOMMAND, item->wID,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002108 MAKELPARAM((INT16)pmt->pt.x, (INT16)pmt->pt.y) );
2109 }
2110 else
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002111 {
Juergen Schmied78513941999-04-18 14:40:32 +00002112 PostMessageA( pmt->hOwnerWnd, WM_COMMAND, item->wID, 0 );
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002113 }
2114 return item->wID;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002115 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002116 else return 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002117 }
2118 else
2119 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002120 pmt->hCurrentMenu = MENU_ShowSubPopup( pmt->hOwnerWnd, hMenu, TRUE );
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002121 return 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002122 }
2123}
2124
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002125/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002126 * MENU_SwitchTracking
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002127 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002128 * Helper function for menu navigation routines.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002129 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002130static void MENU_SwitchTracking( MTRACKER* pmt, HMENU hPtMenu, UINT id )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002131{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002132 POPUPMENU *ptmenu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hPtMenu );
2133 POPUPMENU *topmenu = (POPUPMENU *) USER_HEAP_LIN_ADDR( pmt->hTopMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002134
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002135 if( pmt->hTopMenu != hPtMenu &&
2136 !((ptmenu->wFlags | topmenu->wFlags) & MF_POPUP) )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002137 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002138 /* both are top level menus (system and menu-bar) */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002139
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002140 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
2141 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM, FALSE );
2142 pmt->hTopMenu = hPtMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002143 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002144 else MENU_HideSubPopups( pmt->hOwnerWnd, hPtMenu, FALSE );
2145 MENU_SelectItem( pmt->hOwnerWnd, hPtMenu, id, TRUE );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002146}
2147
2148
2149/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002150 * MENU_ButtonDown
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002151 *
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002152 * Return TRUE if we can go on with menu tracking.
2153 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002154static BOOL MENU_ButtonDown( MTRACKER* pmt, HMENU hPtMenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002155{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002156 if (hPtMenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002157 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002158 UINT id = 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002159 POPUPMENU *ptmenu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hPtMenu );
2160 MENUITEM *item;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002161
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002162 if( IS_SYSTEM_MENU(ptmenu) )
2163 item = ptmenu->items;
2164 else
2165 item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002166
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002167 if( item )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002168 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002169 if( ptmenu->FocusedItem == id )
2170 {
2171 /* nothing to do with already selected non-popup */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002172 if( !(item->fType & MF_POPUP) ) return TRUE;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002173
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002174 if( item->fState & MF_MOUSESELECT )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002175 {
2176 if( ptmenu->wFlags & MF_POPUP )
2177 {
2178 /* hide selected subpopup */
2179
2180 MENU_HideSubPopups( pmt->hOwnerWnd, hPtMenu, TRUE );
2181 pmt->hCurrentMenu = hPtMenu;
2182 return TRUE;
2183 }
2184 return FALSE; /* shouldn't get here */
2185 }
2186 }
2187 else MENU_SwitchTracking( pmt, hPtMenu, id );
2188
2189 /* try to display a subpopup */
2190
2191 pmt->hCurrentMenu = MENU_ShowSubPopup( pmt->hOwnerWnd, hPtMenu, FALSE );
2192 return TRUE;
2193 }
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002194 else WARN(menu, "\tunable to find clicked item!\n");
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002195 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002196 return FALSE;
2197}
2198
2199/***********************************************************************
2200 * MENU_ButtonUp
2201 *
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002202 * Return the the value of MENU_ExecFocusedItem if
2203 * the selected item was not a popup
2204 * 1 if the item was a popup
2205 * 0 otherwise.
2206 * A zero return value indicates that we can't go on with menu tracking.
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002207 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002208static INT MENU_ButtonUp( MTRACKER* pmt, HMENU hPtMenu )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002209{
2210 if (hPtMenu)
2211 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002212 UINT id = 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002213 POPUPMENU *ptmenu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hPtMenu );
2214 MENUITEM *item;
2215
2216 if( IS_SYSTEM_MENU(ptmenu) )
2217 item = ptmenu->items;
2218 else
2219 item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
2220
Alexandre Julliard491502b1997-11-01 19:08:16 +00002221 if( item && (ptmenu->FocusedItem == id ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002222 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002223 if( !(item->fType & MF_POPUP) )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002224 return MENU_ExecFocusedItem( pmt, hPtMenu );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002225 hPtMenu = item->hSubMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002226 if( hPtMenu == pmt->hCurrentMenu )
2227 {
2228 /* Select first item of sub-popup */
2229
2230 MENU_SelectItem( pmt->hOwnerWnd, hPtMenu, NO_SELECTED_ITEM, FALSE );
2231 MENU_MoveSelection( pmt->hOwnerWnd, hPtMenu, ITEM_NEXT );
2232 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002233 return 1;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002234 }
2235 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002236 return 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002237}
2238
2239
2240/***********************************************************************
2241 * MENU_MouseMove
2242 *
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002243 * Return TRUE if we can go on with menu tracking.
2244 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002245static BOOL MENU_MouseMove( MTRACKER* pmt, HMENU hPtMenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002246{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002247 UINT id = NO_SELECTED_ITEM;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002248 POPUPMENU *ptmenu = NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002249
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002250 if( hPtMenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002251 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002252 ptmenu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hPtMenu );
2253 if( IS_SYSTEM_MENU(ptmenu) )
2254 id = 0;
2255 else
2256 MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
2257 }
2258
2259 if( id == NO_SELECTED_ITEM )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002260 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002261 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
2262 NO_SELECTED_ITEM, TRUE );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002263 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002264 else if( ptmenu->FocusedItem != id )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002265 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002266 MENU_SwitchTracking( pmt, hPtMenu, id );
2267 pmt->hCurrentMenu = MENU_ShowSubPopup( pmt->hOwnerWnd, hPtMenu, FALSE );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002268 }
2269 return TRUE;
2270}
2271
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002272
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002273/***********************************************************************
2274 * MENU_DoNextMenu
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002275 *
2276 * NOTE: WM_NEXTMENU documented in Win32 is a bit different.
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002277 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002278static LRESULT MENU_DoNextMenu( MTRACKER* pmt, UINT vk )
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002279{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002280 POPUPMENU *menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( pmt->hTopMenu );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002281
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002282 if( (vk == VK_LEFT && menu->FocusedItem == 0 ) ||
2283 (vk == VK_RIGHT && menu->FocusedItem == menu->nItems - 1))
2284 {
2285 WND* wndPtr;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002286 HMENU hNewMenu;
2287 HWND hNewWnd;
2288 UINT id = 0;
Juergen Schmied78513941999-04-18 14:40:32 +00002289 LRESULT l = SendMessageA( pmt->hOwnerWnd, WM_NEXTMENU, vk,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002290 (IS_SYSTEM_MENU(menu)) ? GetSubMenu16(pmt->hTopMenu,0) : pmt->hTopMenu );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002291
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002292 TRACE(menu,"%04x [%04x] -> %04x [%04x]\n",
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002293 (UINT16)pmt->hCurrentMenu, (UINT16)pmt->hOwnerWnd, LOWORD(l), HIWORD(l) );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002294
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002295 if( l == 0 )
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002296 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002297 wndPtr = WIN_FindWndPtr(pmt->hOwnerWnd);
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002298
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002299 hNewWnd = pmt->hOwnerWnd;
2300 if( IS_SYSTEM_MENU(menu) )
2301 {
2302 /* switch to the menu bar */
2303
2304 if( wndPtr->dwStyle & WS_CHILD || !wndPtr->wIDmenu )
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002305 {
2306 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002307 return FALSE;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002308 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002309
2310 hNewMenu = wndPtr->wIDmenu;
2311 if( vk == VK_LEFT )
2312 {
2313 menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hNewMenu );
2314 id = menu->nItems - 1;
2315 }
2316 }
2317 else if( wndPtr->dwStyle & WS_SYSMENU )
2318 {
2319 /* switch to the system menu */
2320 hNewMenu = wndPtr->hSysMenu;
2321 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002322 else
2323 {
2324 WIN_ReleaseWndPtr(wndPtr);
2325 return FALSE;
2326 }
2327 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002328 }
2329 else /* application returned a new menu to switch to */
2330 {
2331 hNewMenu = LOWORD(l); hNewWnd = HIWORD(l);
2332
Alexandre Julliarda3960291999-02-26 11:11:13 +00002333 if( IsMenu(hNewMenu) && IsWindow(hNewWnd) )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002334 {
2335 wndPtr = WIN_FindWndPtr(hNewWnd);
2336
2337 if( wndPtr->dwStyle & WS_SYSMENU &&
2338 GetSubMenu16(wndPtr->hSysMenu, 0) == hNewMenu )
2339 {
2340 /* get the real system menu */
2341 hNewMenu = wndPtr->hSysMenu;
2342 }
2343 else if( wndPtr->dwStyle & WS_CHILD || wndPtr->wIDmenu != hNewMenu )
2344 {
2345 /* FIXME: Not sure what to do here, perhaps,
2346 * try to track hNewMenu as a popup? */
2347
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002348 TRACE(menu," -- got confused.\n");
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002349 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002350 return FALSE;
2351 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002352 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002353 }
2354 else return FALSE;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002355 }
2356
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002357 if( hNewMenu != pmt->hTopMenu )
2358 {
2359 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM, FALSE );
2360 if( pmt->hCurrentMenu != pmt->hTopMenu )
2361 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
2362 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002363
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002364 if( hNewWnd != pmt->hOwnerWnd )
2365 {
2366 ReleaseCapture();
2367 pmt->hOwnerWnd = hNewWnd;
2368 EVENT_Capture( pmt->hOwnerWnd, HTMENU );
2369 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002370
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002371 pmt->hTopMenu = pmt->hCurrentMenu = hNewMenu; /* all subpopups are hidden */
2372 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, id, TRUE );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002373
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002374 return TRUE;
2375 }
2376 return FALSE;
2377}
2378
2379/***********************************************************************
2380 * MENU_SuspendPopup
2381 *
2382 * The idea is not to show the popup if the next input message is
2383 * going to hide it anyway.
2384 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002385static BOOL MENU_SuspendPopup( MTRACKER* pmt, UINT16 uMsg )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002386{
Juergen Schmied78513941999-04-18 14:40:32 +00002387 MSG msg;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002388
2389 msg.hwnd = pmt->hOwnerWnd;
2390
Juergen Schmied78513941999-04-18 14:40:32 +00002391 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002392 pmt->trackFlags |= TF_SKIPREMOVE;
2393
2394 switch( uMsg )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002395 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002396 case WM_KEYDOWN:
Juergen Schmied78513941999-04-18 14:40:32 +00002397 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002398 if( msg.message == WM_KEYUP || msg.message == WM_PAINT )
2399 {
Juergen Schmied78513941999-04-18 14:40:32 +00002400 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE);
2401 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002402 if( msg.message == WM_KEYDOWN &&
2403 (msg.wParam == VK_LEFT || msg.wParam == VK_RIGHT))
2404 {
2405 pmt->trackFlags |= TF_SUSPENDPOPUP;
2406 return TRUE;
2407 }
2408 }
2409 break;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002410 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002411
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002412 /* failures go through this */
2413 pmt->trackFlags &= ~TF_SUSPENDPOPUP;
2414 return FALSE;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002415}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002416
2417/***********************************************************************
2418 * MENU_KeyLeft
2419 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002420 * Handle a VK_LEFT key event in a menu.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002421 */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002422static void MENU_KeyLeft( MTRACKER* pmt )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002423{
2424 POPUPMENU *menu;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002425 HMENU hmenutmp, hmenuprev;
2426 UINT prevcol;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002427
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002428 hmenuprev = hmenutmp = pmt->hTopMenu;
2429 menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenutmp );
2430
Alexandre Julliard641ee761997-08-04 16:34:36 +00002431 /* Try to move 1 column left (if possible) */
2432 if( (prevcol = MENU_GetStartOfPrevColumn( pmt->hCurrentMenu )) !=
2433 NO_SELECTED_ITEM ) {
2434
2435 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
2436 prevcol, TRUE );
2437 return;
2438 }
2439
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002440 /* close topmost popup */
2441 while (hmenutmp != pmt->hCurrentMenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002442 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002443 hmenuprev = hmenutmp;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002444 hmenutmp = MENU_GetSubPopup( hmenuprev );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002445 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002446
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002447 MENU_HideSubPopups( pmt->hOwnerWnd, hmenuprev, TRUE );
2448 pmt->hCurrentMenu = hmenuprev;
2449
2450 if ( (hmenuprev == pmt->hTopMenu) && !(menu->wFlags & MF_POPUP) )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002451 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002452 /* move menu bar selection if no more popups are left */
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002453
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002454 if( !MENU_DoNextMenu( pmt, VK_LEFT) )
2455 MENU_MoveSelection( pmt->hOwnerWnd, pmt->hTopMenu, ITEM_PREV );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002456
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002457 if ( hmenuprev != hmenutmp || pmt->trackFlags & TF_SUSPENDPOPUP )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002458 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002459 /* A sublevel menu was displayed - display the next one
2460 * unless there is another displacement coming up */
2461
2462 if( !MENU_SuspendPopup( pmt, WM_KEYDOWN ) )
2463 pmt->hCurrentMenu = MENU_ShowSubPopup( pmt->hOwnerWnd,
2464 pmt->hTopMenu, TRUE );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002465 }
2466 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002467}
2468
2469
2470/***********************************************************************
2471 * MENU_KeyRight
2472 *
2473 * Handle a VK_RIGHT key event in a menu.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002474 */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002475static void MENU_KeyRight( MTRACKER* pmt )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002476{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002477 HMENU hmenutmp;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002478 POPUPMENU *menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( pmt->hTopMenu );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002479 UINT nextcol;
Alexandre Julliard641ee761997-08-04 16:34:36 +00002480
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002481 TRACE(menu, "MENU_KeyRight called, cur %x (%s), top %x (%s).\n",
Alexandre Julliard641ee761997-08-04 16:34:36 +00002482 pmt->hCurrentMenu,
2483 ((POPUPMENU *)USER_HEAP_LIN_ADDR(pmt->hCurrentMenu))->
2484 items[0].text,
2485 pmt->hTopMenu, menu->items[0].text );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002486
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002487 if ( (menu->wFlags & MF_POPUP) || (pmt->hCurrentMenu != pmt->hTopMenu))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002488 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002489 /* If already displaying a popup, try to display sub-popup */
2490
2491 hmenutmp = pmt->hCurrentMenu;
2492 pmt->hCurrentMenu = MENU_ShowSubPopup( pmt->hOwnerWnd, hmenutmp, TRUE );
2493
2494 /* if subpopup was displayed then we are done */
2495 if (hmenutmp != pmt->hCurrentMenu) return;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002496 }
2497
Alexandre Julliard641ee761997-08-04 16:34:36 +00002498 /* Check to see if there's another column */
2499 if( (nextcol = MENU_GetStartOfNextColumn( pmt->hCurrentMenu )) !=
2500 NO_SELECTED_ITEM ) {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002501 TRACE(menu, "Going to %d.\n", nextcol );
Alexandre Julliard641ee761997-08-04 16:34:36 +00002502 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
2503 nextcol, TRUE );
2504 return;
2505 }
2506
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002507 if (!(menu->wFlags & MF_POPUP)) /* menu bar tracking */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002508 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002509 if( pmt->hCurrentMenu != pmt->hTopMenu )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002510 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002511 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
2512 hmenutmp = pmt->hCurrentMenu = pmt->hTopMenu;
2513 } else hmenutmp = 0;
2514
2515 /* try to move to the next item */
2516 if( !MENU_DoNextMenu( pmt, VK_RIGHT) )
2517 MENU_MoveSelection( pmt->hOwnerWnd, pmt->hTopMenu, ITEM_NEXT );
2518
2519 if( hmenutmp || pmt->trackFlags & TF_SUSPENDPOPUP )
2520 if( !MENU_SuspendPopup(pmt, WM_KEYDOWN) )
2521 pmt->hCurrentMenu = MENU_ShowSubPopup( pmt->hOwnerWnd,
2522 pmt->hTopMenu, TRUE );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002523 }
2524}
2525
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002526/***********************************************************************
2527 * MENU_TrackMenu
2528 *
2529 * Menu tracking code.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002530 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002531static INT MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y,
2532 HWND hwnd, const RECT *lprect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002533{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002534 MSG msg;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002535 POPUPMENU *menu;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002536 BOOL fRemove;
2537 INT executedMenuId = 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002538 MTRACKER mt = { 0, hmenu, hmenu, hwnd, {x, y} }; /* control struct */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002539
Juergen Schmied78513941999-04-18 14:40:32 +00002540 TRACE(menu,"hmenu=0x%04x flags=0x%08x (%d,%d) hwnd=0x%04x (%d,%d)-(%d,%d)\n",
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00002541 hmenu, wFlags, x, y, hwnd, (lprect) ? lprect->left : 0, (lprect) ? lprect->top : 0,
2542 (lprect) ? lprect->right : 0, (lprect) ? lprect->bottom : 0);
Juergen Schmied78513941999-04-18 14:40:32 +00002543
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002544 fEndMenu = FALSE;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002545 if (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu ))) return FALSE;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002546
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002547 if (wFlags & TPM_BUTTONDOWN) MENU_ButtonDown( &mt, hmenu );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002548
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002549 EVENT_Capture( mt.hOwnerWnd, HTMENU );
2550
2551 while (!fEndMenu)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002552 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002553 menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( mt.hCurrentMenu );
2554 msg.hwnd = (wFlags & TPM_ENTERIDLEEX && menu->wFlags & MF_POPUP) ? menu->hWnd : 0;
2555
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002556 /* we have to keep the message in the queue until it's
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002557 * clear that menu loop is not over yet. */
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002558
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002559 if (!MSG_InternalGetMessage( &msg, msg.hwnd, mt.hOwnerWnd,
2560 MSGF_MENU, PM_NOREMOVE, TRUE )) break;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002561
Alexandre Julliarda3960291999-02-26 11:11:13 +00002562 TranslateMessage( &msg );
Stephane Lussierb3a99de1999-02-09 15:35:12 +00002563 mt.pt = msg.pt;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002564
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002565 fRemove = FALSE;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002566 if ((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002567 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002568 /* Find a menu for this mouse event */
Stephane Lussierb3a99de1999-02-09 15:35:12 +00002569 POINT16 pt16;
2570 CONV_POINT32TO16( &msg.pt, &pt16 );
2571 hmenu = MENU_PtMenu( mt.hTopMenu, pt16 );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002572
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002573 switch(msg.message)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002574 {
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002575 /* no WM_NC... messages in captured state */
2576
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002577 case WM_RBUTTONDBLCLK:
2578 case WM_RBUTTONDOWN:
2579 if (!(wFlags & TPM_RIGHTBUTTON)) break;
2580 /* fall through */
2581 case WM_LBUTTONDBLCLK:
2582 case WM_LBUTTONDOWN:
2583 fEndMenu |= !MENU_ButtonDown( &mt, hmenu );
2584 break;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002585
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002586 case WM_RBUTTONUP:
2587 if (!(wFlags & TPM_RIGHTBUTTON)) break;
2588 /* fall through */
2589 case WM_LBUTTONUP:
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002590 /* Check if a menu was selected by the mouse */
2591 if (hmenu)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002592 {
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002593 executedMenuId = MENU_ButtonUp( &mt, hmenu );
2594
2595 /* the executedMenuId higher than one means that it contains
2596 the id of the selected item so we have to put the fEndMenu to TRUE.
2597 Otherwise, it contains a continue
2598 flag returned by MENU_ButtonUp indicating if we can continue with
2599 menu tracking or not*/
2600 fEndMenu = ((executedMenuId > 1) ? TRUE : FALSE);
2601
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002602 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002603 /* No menu was selected by the mouse */
2604 /* if the function was called by TrackPopupMenu, continue
2605 with the menu tracking. If not, stop it */
2606 else
2607 fEndMenu = ((wFlags & TPM_POPUPMENU) ? FALSE : TRUE);
2608
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002609 break;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002610
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002611 case WM_MOUSEMOVE:
Alexandre Julliard8da12c41999-01-17 16:55:11 +00002612 /* In win95 winelook, the selected menu item must be changed every time the
2613 mouse moves. In Win31 winelook, the mouse button has to be held down */
2614
2615 if ( (TWEAK_WineLook > WIN31_LOOK) ||
2616 ( (msg.wParam & MK_LBUTTON) ||
2617 ((wFlags & TPM_RIGHTBUTTON) && (msg.wParam & MK_RBUTTON))) )
2618
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002619 fEndMenu |= !MENU_MouseMove( &mt, hmenu );
Alexandre Julliard8da12c41999-01-17 16:55:11 +00002620
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002621 } /* switch(msg.message) - mouse */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002622 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002623 else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002624 {
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002625 fRemove = TRUE; /* Keyboard messages are always removed */
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002626 switch(msg.message)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002627 {
2628 case WM_KEYDOWN:
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002629 switch(msg.wParam)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002630 {
2631 case VK_HOME:
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002632 case VK_END:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002633 MENU_SelectItem( mt.hOwnerWnd, mt.hCurrentMenu,
2634 NO_SELECTED_ITEM, FALSE );
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002635 /* fall through */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002636 case VK_UP:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002637 MENU_MoveSelection( mt.hOwnerWnd, mt.hCurrentMenu,
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002638 (msg.wParam == VK_HOME)? ITEM_NEXT : ITEM_PREV );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002639 break;
2640
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002641 case VK_DOWN: /* If on menu bar, pull-down the menu */
2642
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002643 menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( mt.hCurrentMenu );
2644 if (!(menu->wFlags & MF_POPUP))
2645 mt.hCurrentMenu = MENU_ShowSubPopup( mt.hOwnerWnd, mt.hTopMenu, TRUE );
2646 else /* otherwise try to move selection */
2647 MENU_MoveSelection( mt.hOwnerWnd, mt.hCurrentMenu, ITEM_NEXT );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002648 break;
2649
2650 case VK_LEFT:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002651 MENU_KeyLeft( &mt );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002652 break;
2653
2654 case VK_RIGHT:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002655 MENU_KeyRight( &mt );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002656 break;
2657
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002658 case VK_ESCAPE:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002659 fEndMenu = TRUE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002660 break;
2661
2662 default:
2663 break;
2664 }
2665 break; /* WM_KEYDOWN */
2666
2667 case WM_SYSKEYDOWN:
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002668 switch(msg.wParam)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002669 {
2670 case VK_MENU:
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002671 fEndMenu = TRUE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002672 break;
2673
2674 }
2675 break; /* WM_SYSKEYDOWN */
2676
2677 case WM_CHAR:
2678 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002679 UINT pos;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002680
Norman Stevensa83d0651998-10-12 07:25:35 +00002681 if (msg.wParam == '\r' || msg.wParam == ' ')
2682 {
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002683 executedMenuId = MENU_ExecFocusedItem(&mt,mt.hCurrentMenu);
2684 fEndMenu = ((executedMenuId != 0) ? TRUE:FALSE);
2685
Norman Stevensa83d0651998-10-12 07:25:35 +00002686 break;
2687 }
2688
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002689 /* Hack to avoid control chars. */
2690 /* We will find a better way real soon... */
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002691 if ((msg.wParam <= 32) || (msg.wParam >= 127)) break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002692
2693 pos = MENU_FindItemByKey( mt.hOwnerWnd, mt.hCurrentMenu,
Stephane Lussierb3a99de1999-02-09 15:35:12 +00002694 LOWORD(msg.wParam), FALSE );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002695 if (pos == (UINT)-2) fEndMenu = TRUE;
2696 else if (pos == (UINT)-1) MessageBeep(0);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002697 else
2698 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002699 MENU_SelectItem( mt.hOwnerWnd, mt.hCurrentMenu, pos, TRUE );
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002700 executedMenuId = MENU_ExecFocusedItem(&mt,mt.hCurrentMenu);
2701 fEndMenu = ((executedMenuId != 0) ? TRUE:FALSE);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002702 }
2703 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002704 break;
2705 } /* switch(msg.message) - kbd */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002706 }
2707 else
2708 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002709 DispatchMessageA( &msg );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002710 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002711
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002712 if (!fEndMenu) fRemove = TRUE;
2713
2714 /* finally remove message from the queue */
2715
2716 if (fRemove && !(mt.trackFlags & TF_SKIPREMOVE) )
Alexandre Julliarda3960291999-02-26 11:11:13 +00002717 PeekMessageA( &msg, 0, msg.message, msg.message, PM_REMOVE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002718 else mt.trackFlags &= ~TF_SKIPREMOVE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002719 }
Alexandre Julliard1e37a181996-08-18 16:21:52 +00002720
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002721 ReleaseCapture();
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00002722
Alexandre Julliarda3960291999-02-26 11:11:13 +00002723 if( IsWindow( mt.hOwnerWnd ) )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002724 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002725 MENU_HideSubPopups( mt.hOwnerWnd, mt.hTopMenu, FALSE );
2726
2727 menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( mt.hTopMenu );
2728 if (menu && menu->wFlags & MF_POPUP)
2729 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002730 ShowWindow( menu->hWnd, SW_HIDE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002731 uSubPWndLevel = 0;
2732 }
2733 MENU_SelectItem( mt.hOwnerWnd, mt.hTopMenu, NO_SELECTED_ITEM, FALSE );
Juergen Schmied78513941999-04-18 14:40:32 +00002734 SendMessageA( mt.hOwnerWnd, WM_MENUSELECT, MAKELONG(0,0), 0xffff );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002735 }
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002736
2737 /* returning the id of the selected menu.
2738 The return value is only used by TrackPopupMenu */
2739 return executedMenuId;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002740}
2741
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002742/***********************************************************************
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002743 * MENU_InitTracking
2744 */
Juergen Schmied78513941999-04-18 14:40:32 +00002745static BOOL MENU_InitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup)
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002746{
Juergen Schmied78513941999-04-18 14:40:32 +00002747
2748 TRACE(menu, "hwnd=0x%04x hmenu=0x%04x\n", hWnd, hMenu);
2749
Alexandre Julliarda3960291999-02-26 11:11:13 +00002750 HideCaret(0);
Juergen Schmied78513941999-04-18 14:40:32 +00002751 SendMessageA( hWnd, WM_ENTERMENULOOP, bPopup, 0 );
2752 SendMessageA( hWnd, WM_SETCURSOR, hWnd, HTCAPTION );
2753 SendMessageA( hWnd, WM_INITMENU, hMenu, 0 );
2754 return TRUE;
2755}
2756/***********************************************************************
2757 * MENU_ExitTracking
2758 */
2759static BOOL MENU_ExitTracking(HWND hWnd)
2760{
2761 TRACE(menu, "hwnd=0x%04x\n", hWnd);
2762
2763 SendMessageA( hWnd, WM_EXITMENULOOP, 0, 0 );
2764 ShowCaret(0);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002765 return TRUE;
2766}
2767
2768/***********************************************************************
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002769 * MENU_TrackMouseMenuBar
2770 *
2771 * Menu-bar tracking upon a mouse event. Called from NC_HandleSysCommand().
2772 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002773void MENU_TrackMouseMenuBar( WND* wndPtr, INT ht, POINT pt )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002774{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002775 HWND hWnd = wndPtr->hwndSelf;
2776 HMENU hMenu = (ht == HTSYSMENU) ? wndPtr->hSysMenu : wndPtr->wIDmenu;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002777
Juergen Schmied78513941999-04-18 14:40:32 +00002778 TRACE(menu,"pwnd=%p ht=0x%04x (%ld,%ld)\n", wndPtr, ht, pt.x, pt.y);
2779
Alexandre Julliarda3960291999-02-26 11:11:13 +00002780 if (IsMenu(hMenu))
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002781 {
Juergen Schmied78513941999-04-18 14:40:32 +00002782 MENU_InitTracking( hWnd, hMenu, FALSE );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002783 MENU_TrackMenu( hMenu, TPM_ENTERIDLEEX | TPM_BUTTONDOWN |
2784 TPM_LEFTALIGN | TPM_LEFTBUTTON, pt.x, pt.y, hWnd, NULL );
Juergen Schmied78513941999-04-18 14:40:32 +00002785 MENU_ExitTracking(hWnd);
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002786 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002787}
2788
2789
2790/***********************************************************************
2791 * MENU_TrackKbdMenuBar
2792 *
2793 * Menu-bar tracking upon a keyboard event. Called from NC_HandleSysCommand().
2794 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002795void MENU_TrackKbdMenuBar( WND* wndPtr, UINT wParam, INT vkey)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002796{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002797 UINT uItem = NO_SELECTED_ITEM;
2798 HMENU hTrackMenu;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002799
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002800 /* find window that has a menu */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002801
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002802 while( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwStyle & WS_SYSMENU) )
2803 if( !(wndPtr = wndPtr->parent) ) return;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002804
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002805 /* check if we have to track a system menu */
2806
2807 if( (wndPtr->dwStyle & (WS_CHILD | WS_MINIMIZE)) ||
2808 !wndPtr->wIDmenu || vkey == VK_SPACE )
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002809 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002810 if( !(wndPtr->dwStyle & WS_SYSMENU) ) return;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002811 hTrackMenu = wndPtr->hSysMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002812 uItem = 0;
2813 wParam |= HTSYSMENU; /* prevent item lookup */
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002814 }
2815 else
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002816 hTrackMenu = wndPtr->wIDmenu;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002817
Alexandre Julliarda3960291999-02-26 11:11:13 +00002818 if (IsMenu( hTrackMenu ))
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002819 {
Juergen Schmied78513941999-04-18 14:40:32 +00002820 MENU_InitTracking( wndPtr->hwndSelf, hTrackMenu, FALSE );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002821
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002822 if( vkey && vkey != VK_SPACE )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002823 {
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00002824 uItem = MENU_FindItemByKey( wndPtr->hwndSelf, hTrackMenu,
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002825 vkey, (wParam & HTSYSMENU) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002826 if( uItem >= (UINT)(-2) )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002827 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002828 if( uItem == (UINT)(-1) ) MessageBeep(0);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002829 hTrackMenu = 0;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002830 }
2831 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002832
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002833 if( hTrackMenu )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002834 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002835 MENU_SelectItem( wndPtr->hwndSelf, hTrackMenu, uItem, TRUE );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002836
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002837 if( uItem == NO_SELECTED_ITEM )
2838 MENU_MoveSelection( wndPtr->hwndSelf, hTrackMenu, ITEM_NEXT );
2839 else if( vkey )
Juergen Schmied78513941999-04-18 14:40:32 +00002840 PostMessageA( wndPtr->hwndSelf, WM_KEYDOWN, VK_DOWN, 0L );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002841
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002842 MENU_TrackMenu( hTrackMenu, TPM_ENTERIDLEEX | TPM_LEFTALIGN | TPM_LEFTBUTTON,
2843 0, 0, wndPtr->hwndSelf, NULL );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002844 }
Juergen Schmied78513941999-04-18 14:40:32 +00002845
2846 MENU_ExitTracking (wndPtr->hwndSelf);
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002847 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002848}
2849
2850
2851/**********************************************************************
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002852 * TrackPopupMenu16 (USER.416)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002853 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002854BOOL16 WINAPI TrackPopupMenu16( HMENU16 hMenu, UINT16 wFlags, INT16 x, INT16 y,
2855 INT16 nReserved, HWND16 hWnd, const RECT16 *lpRect )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002856{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002857 RECT r;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002858 if (lpRect)
2859 CONV_RECT16TO32( lpRect, &r );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002860 return TrackPopupMenu( hMenu, wFlags, x, y, nReserved, hWnd,
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002861 lpRect ? &r : NULL );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002862}
2863
2864
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002865/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00002866 * TrackPopupMenu (USER32.549)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002867 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002868BOOL WINAPI TrackPopupMenu( HMENU hMenu, UINT wFlags, INT x, INT y,
2869 INT nReserved, HWND hWnd, const RECT *lpRect )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002870{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002871 BOOL ret = FALSE;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002872
Juergen Schmied78513941999-04-18 14:40:32 +00002873 MENU_InitTracking(hWnd, hMenu, TRUE);
2874 SendMessageA( hWnd, WM_INITMENUPOPUP, hMenu, 0);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002875 if (MENU_ShowPopup( hWnd, hMenu, 0, x, y, 0, 0 ))
Francois Boisvert85dd9fc1999-02-17 12:50:11 +00002876 ret = MENU_TrackMenu( hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd, lpRect );
Juergen Schmied78513941999-04-18 14:40:32 +00002877 MENU_ExitTracking(hWnd);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002878 return ret;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002879}
2880
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002881/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00002882 * TrackPopupMenuEx (USER32.550)
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002883 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002884BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y,
2885 HWND hWnd, LPTPMPARAMS lpTpm )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002886{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002887 FIXME(menu, "not fully implemented\n" );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002888 return TrackPopupMenu( hMenu, wFlags, x, y, 0, hWnd,
Alexandre Julliardc6c09441997-01-12 18:32:19 +00002889 lpTpm ? &lpTpm->rcExclude : NULL );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00002890}
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002891
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002892/***********************************************************************
2893 * PopupMenuWndProc
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002894 *
2895 * NOTE: Windows has totally different (and undocumented) popup wndproc.
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002896 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002897LRESULT WINAPI PopupMenuWndProc( HWND hwnd, UINT message, WPARAM wParam,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002898 LPARAM lParam )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002899{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002900 WND* wndPtr = WIN_FindWndPtr(hwnd);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002901 LRESULT retvalue;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002902
Juergen Schmied78513941999-04-18 14:40:32 +00002903 TRACE(menu,"hwnd=0x%04x msg=0x%04x wp=0x%04x lp=0x%08lx\n",
2904 hwnd, message, wParam, lParam);
2905
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002906 switch(message)
2907 {
2908 case WM_CREATE:
2909 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002910 CREATESTRUCTA *cs = (CREATESTRUCTA*)lParam;
2911 SetWindowLongA( hwnd, 0, (LONG)cs->lpCreateParams );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002912 retvalue = 0;
2913 goto END;
Alexandre Julliardf7207251994-07-23 07:57:48 +00002914 }
Alexandre Julliardcdd09231994-01-12 11:12:51 +00002915
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002916 case WM_MOUSEACTIVATE: /* We don't want to be activated */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002917 retvalue = MA_NOACTIVATE;
2918 goto END;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00002919
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002920 case WM_PAINT:
2921 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002922 PAINTSTRUCT ps;
2923 BeginPaint( hwnd, &ps );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002924 MENU_DrawPopupMenu( hwnd, ps.hdc,
Alexandre Julliarda3960291999-02-26 11:11:13 +00002925 (HMENU)GetWindowLongA( hwnd, 0 ) );
2926 EndPaint( hwnd, &ps );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002927 retvalue = 0;
2928 goto END;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002929 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002930 case WM_ERASEBKGND:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002931 retvalue = 1;
2932 goto END;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00002933
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00002934 case WM_DESTROY:
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00002935
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002936 /* zero out global pointer in case resident popup window
2937 * was somehow destroyed. */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00002938
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002939 if(MENU_GetTopPopupWnd() )
Alexandre Julliard54c27111998-03-29 19:44:57 +00002940 {
2941 if( hwnd == pTopPopupWnd->hwndSelf )
2942 {
2943 ERR(menu, "resident popup destroyed!\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002944
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002945 MENU_DestroyTopPopupWnd();
Alexandre Julliard54c27111998-03-29 19:44:57 +00002946 uSubPWndLevel = 0;
2947 }
2948 else
2949 uSubPWndLevel--;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002950 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002951 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002952 break;
2953
2954 case WM_SHOWWINDOW:
2955
2956 if( wParam )
2957 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002958 if( !(*(HMENU*)wndPtr->wExtra) )
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002959 ERR(menu,"no menu to display\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002960 }
2961 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00002962 *(HMENU*)wndPtr->wExtra = 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002963 break;
2964
2965 case MM_SETMENUHANDLE:
2966
Alexandre Julliarda3960291999-02-26 11:11:13 +00002967 *(HMENU*)wndPtr->wExtra = (HMENU)wParam;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00002968 break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002969
2970 case MM_GETMENUHANDLE:
2971
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002972 retvalue = *(HMENU*)wndPtr->wExtra;
2973 goto END;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002974
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002975 default:
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002976 retvalue = DefWindowProcA( hwnd, message, wParam, lParam );
2977 goto END;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00002978 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002979 retvalue = 0;
2980END:
2981 WIN_ReleaseWndPtr(wndPtr);
2982 return retvalue;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00002983}
2984
2985
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00002986/***********************************************************************
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00002987 * MENU_GetMenuBarHeight
2988 *
2989 * Compute the size of the menu bar height. Used by NC_HandleNCCalcSize().
2990 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002991UINT MENU_GetMenuBarHeight( HWND hwnd, UINT menubarWidth,
2992 INT orgX, INT orgY )
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00002993{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002994 HDC hdc;
2995 RECT rectBar;
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00002996 WND *wndPtr;
2997 LPPOPUPMENU lppop;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00002998 UINT retvalue;
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00002999
Juergen Schmied78513941999-04-18 14:40:32 +00003000 TRACE(menu, "HWND 0x%x, width %d, at (%d, %d).\n",
3001 hwnd, menubarWidth, orgX, orgY );
Alexandre Julliardd37eb361997-07-20 16:23:21 +00003002
Juergen Schmied78513941999-04-18 14:40:32 +00003003 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
3004 return 0;
3005
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00003006 if (!(lppop = (LPPOPUPMENU)USER_HEAP_LIN_ADDR((HMENU16)wndPtr->wIDmenu)))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003007 {
Juergen Schmied78513941999-04-18 14:40:32 +00003008 WIN_ReleaseWndPtr(wndPtr);
3009 return 0;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003010 }
Juergen Schmied78513941999-04-18 14:40:32 +00003011
Alexandre Julliarda3960291999-02-26 11:11:13 +00003012 hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_WINDOW );
Juergen Schmied78513941999-04-18 14:40:32 +00003013 SelectObject( hdc, hMenuFont);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003014 SetRect(&rectBar, orgX, orgY, orgX+menubarWidth, orgY+SYSMETRICS_CYMENU);
Juergen Schmied78513941999-04-18 14:40:32 +00003015 MENU_MenuBarCalcSize( hdc, &rectBar, lppop, hwnd );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003016 ReleaseDC( hwnd, hdc );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003017 retvalue = lppop->Height;
3018 WIN_ReleaseWndPtr(wndPtr);
3019 return retvalue;
Alexandre Julliard2d159fb1994-07-15 16:04:31 +00003020}
3021
3022
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003023/*******************************************************************
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003024 * ChangeMenu16 (USER.153)
Alexandre Julliard401710d1993-09-04 10:09:32 +00003025 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003026BOOL16 WINAPI ChangeMenu16( HMENU16 hMenu, UINT16 pos, SEGPTR data,
3027 UINT16 id, UINT16 flags )
Alexandre Julliard401710d1993-09-04 10:09:32 +00003028{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003029 TRACE(menu,"menu=%04x pos=%d data=%08lx id=%04x flags=%04x\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +00003030 hMenu, pos, (DWORD)data, id, flags );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003031 if (flags & MF_APPEND) return AppendMenu16( hMenu, flags & ~MF_APPEND,
3032 id, data );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003033
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003034 /* FIXME: Word passes the item id in 'pos' and 0 or 0xffff as id */
3035 /* for MF_DELETE. We should check the parameters for all others */
3036 /* MF_* actions also (anybody got a doc on ChangeMenu?). */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003037
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003038 if (flags & MF_DELETE) return DeleteMenu16(hMenu, pos, flags & ~MF_DELETE);
3039 if (flags & MF_CHANGE) return ModifyMenu16(hMenu, pos, flags & ~MF_CHANGE,
3040 id, data );
3041 if (flags & MF_REMOVE) return RemoveMenu16(hMenu,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003042 flags & MF_BYPOSITION ? pos : id,
3043 flags & ~MF_REMOVE );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003044 /* Default: MF_INSERT */
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003045 return InsertMenu16( hMenu, pos, flags, id, data );
3046}
3047
3048
3049/*******************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003050 * ChangeMenu32A (USER32.23)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003051 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003052BOOL WINAPI ChangeMenuA( HMENU hMenu, UINT pos, LPCSTR data,
3053 UINT id, UINT flags )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003054{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003055 TRACE(menu,"menu=%08x pos=%d data=%08lx id=%08x flags=%08x\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003056 hMenu, pos, (DWORD)data, id, flags );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003057 if (flags & MF_APPEND) return AppendMenuA( hMenu, flags & ~MF_APPEND,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003058 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003059 if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
3060 if (flags & MF_CHANGE) return ModifyMenuA(hMenu, pos, flags & ~MF_CHANGE,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003061 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003062 if (flags & MF_REMOVE) return RemoveMenu( hMenu,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003063 flags & MF_BYPOSITION ? pos : id,
3064 flags & ~MF_REMOVE );
3065 /* Default: MF_INSERT */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003066 return InsertMenuA( hMenu, pos, flags, id, data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003067}
3068
3069
3070/*******************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003071 * ChangeMenu32W (USER32.24)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003072 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003073BOOL WINAPI ChangeMenuW( HMENU hMenu, UINT pos, LPCWSTR data,
3074 UINT id, UINT flags )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003075{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003076 TRACE(menu,"menu=%08x pos=%d data=%08lx id=%08x flags=%08x\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003077 hMenu, pos, (DWORD)data, id, flags );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003078 if (flags & MF_APPEND) return AppendMenuW( hMenu, flags & ~MF_APPEND,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003079 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003080 if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
3081 if (flags & MF_CHANGE) return ModifyMenuW(hMenu, pos, flags & ~MF_CHANGE,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003082 id, data );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003083 if (flags & MF_REMOVE) return RemoveMenu( hMenu,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003084 flags & MF_BYPOSITION ? pos : id,
3085 flags & ~MF_REMOVE );
3086 /* Default: MF_INSERT */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003087 return InsertMenuW( hMenu, pos, flags, id, data );
Alexandre Julliard401710d1993-09-04 10:09:32 +00003088}
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003089
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003090
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003091/*******************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003092 * CheckMenuItem16 (USER.154)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003093 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003094BOOL16 WINAPI CheckMenuItem16( HMENU16 hMenu, UINT16 id, UINT16 flags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003095{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003096 return (BOOL16)CheckMenuItem( hMenu, id, flags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003097}
3098
3099
3100/*******************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00003101 * CheckMenuItem (USER32.46)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003102 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003103DWORD WINAPI CheckMenuItem( HMENU hMenu, UINT id, UINT flags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003104{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003105 MENUITEM *item;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003106 DWORD ret;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003107
Juergen Schmied78513941999-04-18 14:40:32 +00003108 TRACE(menu,"menu=%04x id=%04x flags=%04x\n", hMenu, id, flags );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003109 if (!(item = MENU_FindItem( &hMenu, &id, flags ))) return -1;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003110 ret = item->fState & MF_CHECKED;
3111 if (flags & MF_CHECKED) item->fState |= MF_CHECKED;
3112 else item->fState &= ~MF_CHECKED;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003113 return ret;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003114}
3115
3116
3117/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003118 * EnableMenuItem16 (USER.155)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003119 */
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003120UINT16 WINAPI EnableMenuItem16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003121{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003122 return EnableMenuItem( hMenu, wItemID, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003123}
3124
3125
3126/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003127 * EnableMenuItem32 (USER32.170)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003128 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003129UINT WINAPI EnableMenuItem( HMENU hMenu, UINT wItemID, UINT wFlags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003130{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003131 UINT oldflags;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003132 MENUITEM *item;
Alexandre Julliardf7207251994-07-23 07:57:48 +00003133
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003134 TRACE(menu,"(%04x, %04X, %04X) !\n",
3135 hMenu, wItemID, wFlags);
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00003136
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003137 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags )))
Alexandre Julliarda3960291999-02-26 11:11:13 +00003138 return (UINT)-1;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003139
3140 oldflags = item->fState & (MF_GRAYED | MF_DISABLED);
3141 item->fState ^= (oldflags ^ wFlags) & (MF_GRAYED | MF_DISABLED);
3142 return oldflags;
Alexandre Julliard1f579291994-05-25 16:25:21 +00003143}
3144
3145
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00003146/*******************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003147 * GetMenuString16 (USER.161)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003148 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003149INT16 WINAPI GetMenuString16( HMENU16 hMenu, UINT16 wItemID,
3150 LPSTR str, INT16 nMaxSiz, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003151{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003152 return GetMenuStringA( hMenu, wItemID, str, nMaxSiz, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003153}
3154
3155
3156/*******************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003157 * GetMenuString32A (USER32.268)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003158 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003159INT WINAPI GetMenuStringA( HMENU hMenu, UINT wItemID,
3160 LPSTR str, INT nMaxSiz, UINT wFlags )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003161{
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003162 MENUITEM *item;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00003163
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003164 TRACE(menu, "menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00003165 hMenu, wItemID, str, nMaxSiz, wFlags );
3166 if (!str || !nMaxSiz) return 0;
3167 str[0] = '\0';
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003168 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003169 if (!IS_STRING_ITEM(item->fType)) return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003170 lstrcpynA( str, item->text, nMaxSiz );
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003171 TRACE(menu, "returning '%s'\n", str );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003172 return strlen(str);
Alexandre Julliard1f579291994-05-25 16:25:21 +00003173}
3174
3175
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003176/*******************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003177 * GetMenuString32W (USER32.269)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003178 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003179INT WINAPI GetMenuStringW( HMENU hMenu, UINT wItemID,
3180 LPWSTR str, INT nMaxSiz, UINT wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003181{
3182 MENUITEM *item;
3183
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003184 TRACE(menu, "menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003185 hMenu, wItemID, str, nMaxSiz, wFlags );
3186 if (!str || !nMaxSiz) return 0;
3187 str[0] = '\0';
3188 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003189 if (!IS_STRING_ITEM(item->fType)) return 0;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003190 lstrcpynAtoW( str, item->text, nMaxSiz );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003191 return lstrlenW(str);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003192}
3193
3194
3195/**********************************************************************
3196 * HiliteMenuItem16 (USER.162)
3197 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003198BOOL16 WINAPI HiliteMenuItem16( HWND16 hWnd, HMENU16 hMenu, UINT16 wItemID,
3199 UINT16 wHilite )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003200{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003201 return HiliteMenuItem( hWnd, hMenu, wItemID, wHilite );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003202}
3203
3204
3205/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003206 * HiliteMenuItem32 (USER32.318)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003207 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003208BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
3209 UINT wHilite )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003210{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003211 LPPOPUPMENU menu;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003212 TRACE(menu,"(%04x, %04x, %04x, %04x);\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +00003213 hWnd, hMenu, wItemID, wHilite);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003214 if (!MENU_FindItem( &hMenu, &wItemID, wHilite )) return FALSE;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00003215 if (!(menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003216 if (menu->FocusedItem == wItemID) return TRUE;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003217 MENU_HideSubPopups( hWnd, hMenu, FALSE );
3218 MENU_SelectItem( hWnd, hMenu, wItemID, TRUE );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003219 return TRUE;
Alexandre Julliard1f579291994-05-25 16:25:21 +00003220}
3221
3222
3223/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003224 * GetMenuState16 (USER.250)
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00003225 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003226UINT16 WINAPI GetMenuState16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003227{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003228 return GetMenuState( hMenu, wItemID, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003229}
3230
3231
3232/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00003233 * GetMenuState (USER32.267)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003234 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003235UINT WINAPI GetMenuState( HMENU hMenu, UINT wItemID, UINT wFlags )
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00003236{
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003237 MENUITEM *item;
Juergen Schmied78513941999-04-18 14:40:32 +00003238 TRACE(menu,"(menu=%04x, id=%04x, flags=%04x);\n",
Alexandre Julliardaca05781994-10-17 18:12:41 +00003239 hMenu, wItemID, wFlags);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003240 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return -1;
Alexandre Julliard03468f71998-02-15 19:40:49 +00003241 debug_print_menuitem (" item: ", item, "");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003242 if (item->fType & MF_POPUP)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003243 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003244 POPUPMENU *menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( item->hSubMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003245 if (!menu) return -1;
Alexandre Julliard829fe321998-07-26 14:27:39 +00003246 else return (menu->nItems << 8) | ((item->fState|item->fType) & 0xff);
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003247 }
Alexandre Julliard889f7421997-04-15 17:19:52 +00003248 else
Alexandre Julliard491502b1997-11-01 19:08:16 +00003249 {
Alexandre Julliard829fe321998-07-26 14:27:39 +00003250 /* We used to (from way back then) mask the result to 0xff. */
3251 /* I don't know why and it seems wrong as the documented */
3252 /* return flag MF_SEPARATOR is outside that mask. */
3253 return (item->fType | item->fState);
Alexandre Julliard491502b1997-11-01 19:08:16 +00003254 }
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00003255}
3256
3257
3258/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003259 * GetMenuItemCount16 (USER.263)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003260 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003261INT16 WINAPI GetMenuItemCount16( HMENU16 hMenu )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003262{
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003263 LPPOPUPMENU menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003264 if (!IS_A_MENU(menu)) return -1;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003265 TRACE(menu,"(%04x) returning %d\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003266 hMenu, menu->nItems );
3267 return menu->nItems;
Alexandre Julliard1f579291994-05-25 16:25:21 +00003268}
3269
3270
3271/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003272 * GetMenuItemCount32 (USER32.262)
Alexandre Julliard1f579291994-05-25 16:25:21 +00003273 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003274INT WINAPI GetMenuItemCount( HMENU hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003275{
3276 LPPOPUPMENU menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003277 if (!IS_A_MENU(menu)) return -1;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003278 TRACE(menu,"(%04x) returning %d\n",
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003279 hMenu, menu->nItems );
3280 return menu->nItems;
3281}
3282
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003283/**********************************************************************
3284 * GetMenuItemID16 (USER.264)
3285 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003286UINT16 WINAPI GetMenuItemID16( HMENU16 hMenu, INT16 nPos )
Alexandre Julliard1f579291994-05-25 16:25:21 +00003287{
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003288 return (UINT16) GetMenuItemID (hMenu, nPos);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003289}
3290
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003291/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003292 * GetMenuItemID32 (USER32.263)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003293 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003294UINT WINAPI GetMenuItemID( HMENU hMenu, INT nPos )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003295{
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003296 MENUITEM * lpmi;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003297
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003298 if (!(lpmi = MENU_FindItem(&hMenu,&nPos,MF_BYPOSITION))) return 0;
3299 if (lpmi->fType & MF_POPUP) return -1;
3300 return lpmi->wID;
3301
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003302}
3303
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003304/*******************************************************************
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003305 * InsertMenu16 (USER.410)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003306 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003307BOOL16 WINAPI InsertMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags,
3308 UINT16 id, SEGPTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003309{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003310 UINT pos32 = (UINT)pos;
3311 if ((pos == (UINT16)-1) && (flags & MF_BYPOSITION)) pos32 = (UINT)-1;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003312 if (IS_STRING_ITEM(flags) && data)
Alexandre Julliarda3960291999-02-26 11:11:13 +00003313 return InsertMenuA( hMenu, pos32, flags, id,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003314 (LPSTR)PTR_SEG_TO_LIN(data) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003315 return InsertMenuA( hMenu, pos32, flags, id, (LPSTR)data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003316}
3317
3318
3319/*******************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003320 * InsertMenu32A (USER32.322)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003321 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003322BOOL WINAPI InsertMenuA( HMENU hMenu, UINT pos, UINT flags,
3323 UINT id, LPCSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003324{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003325 MENUITEM *item;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00003326
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003327 if (IS_STRING_ITEM(flags) && str)
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003328 TRACE(menu, "hMenu %04x, pos %d, flags %08x, "
Alexandre Julliardd37eb361997-07-20 16:23:21 +00003329 "id %04x, str '%s'\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003330 hMenu, pos, flags, id, str );
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003331 else TRACE(menu, "hMenu %04x, pos %d, flags %08x, "
Alexandre Julliardd37eb361997-07-20 16:23:21 +00003332 "id %04x, str %08lx (not a string)\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003333 hMenu, pos, flags, id, (DWORD)str );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003334
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003335 if (!(item = MENU_InsertItem( hMenu, pos, flags ))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003336
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003337 if (!(MENU_SetItemData( item, flags, id, str )))
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003338 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003339 RemoveMenu( hMenu, pos, flags );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00003340 return FALSE;
3341 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003342
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003343 if (flags & MF_POPUP) /* Set the MF_POPUP flag on the popup-menu */
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00003344 ((POPUPMENU *)USER_HEAP_LIN_ADDR((HMENU16)id))->wFlags |= MF_POPUP;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003345
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003346 item->hCheckBit = item->hUnCheckBit = 0;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003347 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003348}
3349
3350
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003351/*******************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003352 * InsertMenu32W (USER32.325)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003353 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003354BOOL WINAPI InsertMenuW( HMENU hMenu, UINT pos, UINT flags,
3355 UINT id, LPCWSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003356{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003357 BOOL ret;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003358
3359 if (IS_STRING_ITEM(flags) && str)
3360 {
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003361 LPSTR newstr = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003362 ret = InsertMenuA( hMenu, pos, flags, id, newstr );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003363 HeapFree( GetProcessHeap(), 0, newstr );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003364 return ret;
3365 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00003366 else return InsertMenuA( hMenu, pos, flags, id, (LPCSTR)str );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003367}
3368
3369
3370/*******************************************************************
3371 * AppendMenu16 (USER.411)
3372 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003373BOOL16 WINAPI AppendMenu16(HMENU16 hMenu, UINT16 flags, UINT16 id, SEGPTR data)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003374{
3375 return InsertMenu16( hMenu, -1, flags | MF_BYPOSITION, id, data );
3376}
3377
3378
3379/*******************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003380 * AppendMenu32A (USER32.5)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003381 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003382BOOL WINAPI AppendMenuA( HMENU hMenu, UINT flags,
3383 UINT id, LPCSTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003384{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003385 return InsertMenuA( hMenu, -1, flags | MF_BYPOSITION, id, data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003386}
3387
3388
3389/*******************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003390 * AppendMenu32W (USER32.6)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003391 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003392BOOL WINAPI AppendMenuW( HMENU hMenu, UINT flags,
3393 UINT id, LPCWSTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003394{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003395 return InsertMenuW( hMenu, -1, flags | MF_BYPOSITION, id, data );
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003396}
3397
3398
3399/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003400 * RemoveMenu16 (USER.412)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003401 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003402BOOL16 WINAPI RemoveMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003403{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003404 return RemoveMenu( hMenu, nPos, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003405}
3406
3407
3408/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00003409 * RemoveMenu (USER32.441)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003410 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003411BOOL WINAPI RemoveMenu( HMENU hMenu, UINT nPos, UINT wFlags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003412{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003413 LPPOPUPMENU menu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003414 MENUITEM *item;
3415
Juergen Schmied78513941999-04-18 14:40:32 +00003416 TRACE(menu,"(menu=%04x pos=%04x flags=%04x)\n",hMenu, nPos, wFlags);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003417 if (!(item = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00003418 if (!(menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003419
3420 /* Remove item */
3421
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003422 MENU_FreeItemData( item );
3423
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003424 if (--menu->nItems == 0)
3425 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003426 HeapFree( SystemHeap, 0, menu->items );
3427 menu->items = NULL;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003428 }
3429 else
3430 {
3431 while(nPos < menu->nItems)
3432 {
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003433 *item = *(item+1);
3434 item++;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003435 nPos++;
3436 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003437 menu->items = HeapReAlloc( SystemHeap, 0, menu->items,
3438 menu->nItems * sizeof(MENUITEM) );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003439 }
3440 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003441}
3442
3443
3444/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003445 * DeleteMenu16 (USER.413)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003446 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003447BOOL16 WINAPI DeleteMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003448{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003449 return DeleteMenu( hMenu, nPos, wFlags );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003450}
3451
3452
3453/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003454 * DeleteMenu32 (USER32.129)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003455 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003456BOOL WINAPI DeleteMenu( HMENU hMenu, UINT nPos, UINT wFlags )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003457{
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003458 MENUITEM *item = MENU_FindItem( &hMenu, &nPos, wFlags );
3459 if (!item) return FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003460 if (item->fType & MF_POPUP) DestroyMenu( item->hSubMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003461 /* nPos is now the position of the item */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003462 RemoveMenu( hMenu, nPos, wFlags | MF_BYPOSITION );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003463 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003464}
3465
3466
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003467/*******************************************************************
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003468 * ModifyMenu16 (USER.414)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003469 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003470BOOL16 WINAPI ModifyMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags,
3471 UINT16 id, SEGPTR data )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003472{
3473 if (IS_STRING_ITEM(flags))
Alexandre Julliarda3960291999-02-26 11:11:13 +00003474 return ModifyMenuA( hMenu, pos, flags, id,
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003475 (LPSTR)PTR_SEG_TO_LIN(data) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003476 return ModifyMenuA( hMenu, pos, flags, id, (LPSTR)data );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003477}
3478
3479
3480/*******************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003481 * ModifyMenu32A (USER32.397)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003482 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003483BOOL WINAPI ModifyMenuA( HMENU hMenu, UINT pos, UINT flags,
3484 UINT id, LPCSTR str )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003485{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003486 MENUITEM *item;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003487
3488 if (IS_STRING_ITEM(flags))
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00003489 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003490 TRACE(menu, "%04x %d %04x %04x '%s'\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003491 hMenu, pos, flags, id, str ? str : "#NULL#" );
3492 if (!str) return FALSE;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00003493 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003494 else
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003495 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003496 TRACE(menu, "%04x %d %04x %04x %08lx\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003497 hMenu, pos, flags, id, (DWORD)str );
3498 }
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003499
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003500 if (!(item = MENU_FindItem( &hMenu, &pos, flags ))) return FALSE;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003501 return MENU_SetItemData( item, flags, id, str );
3502}
3503
3504
3505/*******************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003506 * ModifyMenu32W (USER32.398)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003507 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003508BOOL WINAPI ModifyMenuW( HMENU hMenu, UINT pos, UINT flags,
3509 UINT id, LPCWSTR str )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003510{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003511 BOOL ret;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003512
3513 if (IS_STRING_ITEM(flags) && str)
3514 {
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003515 LPSTR newstr = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
Alexandre Julliarda3960291999-02-26 11:11:13 +00003516 ret = ModifyMenuA( hMenu, pos, flags, id, newstr );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003517 HeapFree( GetProcessHeap(), 0, newstr );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003518 return ret;
3519 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00003520 else return ModifyMenuA( hMenu, pos, flags, id, (LPCSTR)str );
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003521}
3522
3523
3524/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003525 * CreatePopupMenu16 (USER.415)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003526 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003527HMENU16 WINAPI CreatePopupMenu16(void)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003528{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003529 return CreatePopupMenu();
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003530}
3531
3532
3533/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003534 * CreatePopupMenu32 (USER32.82)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003535 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003536HMENU WINAPI CreatePopupMenu(void)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003537{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003538 HMENU hmenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003539 POPUPMENU *menu;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003540
Alexandre Julliarda3960291999-02-26 11:11:13 +00003541 if (!(hmenu = CreateMenu())) return 0;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00003542 menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003543 menu->wFlags |= MF_POPUP;
3544 return hmenu;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003545}
3546
3547
3548/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003549 * GetMenuCheckMarkDimensions (USER.417) (USER32.258)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003550 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003551DWORD WINAPI GetMenuCheckMarkDimensions(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003552{
Alexandre Julliardf7207251994-07-23 07:57:48 +00003553 return MAKELONG( check_bitmap_width, check_bitmap_height );
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003554}
3555
3556
3557/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003558 * SetMenuItemBitmaps16 (USER.418)
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003559 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003560BOOL16 WINAPI SetMenuItemBitmaps16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags,
3561 HBITMAP16 hNewUnCheck, HBITMAP16 hNewCheck)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003562{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003563 return SetMenuItemBitmaps( hMenu, nPos, wFlags, hNewUnCheck, hNewCheck );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003564}
3565
3566
3567/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003568 * SetMenuItemBitmaps32 (USER32.490)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003569 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003570BOOL WINAPI SetMenuItemBitmaps( HMENU hMenu, UINT nPos, UINT wFlags,
3571 HBITMAP hNewUnCheck, HBITMAP hNewCheck)
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003572{
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003573 MENUITEM *item;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003574 TRACE(menu,"(%04x, %04x, %04x, %04x, %04x)\n",
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003575 hMenu, nPos, wFlags, hNewCheck, hNewUnCheck);
3576 if (!(item = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003577
3578 if (!hNewCheck && !hNewUnCheck)
3579 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003580 item->fState &= ~MF_USECHECKBITMAPS;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003581 }
3582 else /* Install new bitmaps */
3583 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003584 item->hCheckBit = hNewCheck;
3585 item->hUnCheckBit = hNewUnCheck;
3586 item->fState |= MF_USECHECKBITMAPS;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003587 }
3588 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003589}
3590
3591
3592/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003593 * CreateMenu16 (USER.151)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003594 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003595HMENU16 WINAPI CreateMenu16(void)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003596{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003597 return CreateMenu();
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003598}
3599
3600
3601/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00003602 * CreateMenu (USER32.81)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003603 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003604HMENU WINAPI CreateMenu(void)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003605{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003606 HMENU hMenu;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003607 LPPOPUPMENU menu;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003608 if (!(hMenu = USER_HEAP_ALLOC( sizeof(POPUPMENU) ))) return 0;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00003609 menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
Juergen Schmied78513941999-04-18 14:40:32 +00003610
3611 ZeroMemory(menu, sizeof(POPUPMENU));
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003612 menu->wMagic = MENU_MAGIC;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003613 menu->FocusedItem = NO_SELECTED_ITEM;
Juergen Schmied78513941999-04-18 14:40:32 +00003614
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003615 TRACE(menu, "return %04x\n", hMenu );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003616 return hMenu;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003617}
3618
3619
3620/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003621 * DestroyMenu16 (USER.152)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003622 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003623BOOL16 WINAPI DestroyMenu16( HMENU16 hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003624{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003625 return DestroyMenu( hMenu );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003626}
3627
3628
3629/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003630 * DestroyMenu32 (USER32.134)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003631 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003632BOOL WINAPI DestroyMenu( HMENU hMenu )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003633{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003634 TRACE(menu,"(%04x)\n", hMenu);
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003635
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003636 /* Silently ignore attempts to destroy default system popup */
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003637
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003638 if (hMenu && hMenu != MENU_DefSysPopup)
Alexandre Julliardff8331e1995-09-18 11:19:54 +00003639 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003640 LPPOPUPMENU lppop = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003641 WND *pTPWnd = MENU_GetTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003642
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003643 if( pTPWnd && (hMenu == *(HMENU*)pTPWnd->wExtra) )
3644 *(UINT*)pTPWnd->wExtra = 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003645
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003646 if (IS_A_MENU( lppop ))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003647 {
3648 lppop->wMagic = 0; /* Mark it as destroyed */
3649
3650 if ((lppop->wFlags & MF_POPUP) && lppop->hWnd &&
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003651 (!pTPWnd || (lppop->hWnd != pTPWnd->hwndSelf)))
Alexandre Julliarda3960291999-02-26 11:11:13 +00003652 DestroyWindow( lppop->hWnd );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003653
3654 if (lppop->items) /* recursively destroy submenus */
3655 {
3656 int i;
3657 MENUITEM *item = lppop->items;
3658 for (i = lppop->nItems; i > 0; i--, item++)
3659 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003660 if (item->fType & MF_POPUP) DestroyMenu(item->hSubMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003661 MENU_FreeItemData( item );
3662 }
3663 HeapFree( SystemHeap, 0, lppop->items );
3664 }
3665 USER_HEAP_FREE( hMenu );
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +00003666 MENU_ReleaseTopPopupWnd();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003667 }
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +00003668 else
3669 {
3670 MENU_ReleaseTopPopupWnd();
3671 return FALSE;
3672 }
Alexandre Julliardff8331e1995-09-18 11:19:54 +00003673 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003674 return (hMenu != MENU_DefSysPopup);
Alexandre Julliard5f721f81994-01-04 20:14:34 +00003675}
3676
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003677
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003678/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003679 * GetSystemMenu16 (USER.156)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003680 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003681HMENU16 WINAPI GetSystemMenu16( HWND16 hWnd, BOOL16 bRevert )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003682{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003683 return GetSystemMenu( hWnd, bRevert );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003684}
3685
3686
3687/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003688 * GetSystemMenu32 (USER32.291)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003689 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003690HMENU WINAPI GetSystemMenu( HWND hWnd, BOOL bRevert )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003691{
Alexandre Julliardb7258be1995-09-01 15:57:28 +00003692 WND *wndPtr = WIN_FindWndPtr( hWnd );
Alexandre Julliardb7258be1995-09-01 15:57:28 +00003693
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003694 if (wndPtr)
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003695 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003696 if( wndPtr->hSysMenu )
3697 {
3698 if( bRevert )
3699 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003700 DestroyMenu(wndPtr->hSysMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003701 wndPtr->hSysMenu = 0;
3702 }
3703 else
3704 {
3705 POPUPMENU *menu = (POPUPMENU*)
3706 USER_HEAP_LIN_ADDR(wndPtr->hSysMenu);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003707 if( menu->items[0].hSubMenu == MENU_DefSysPopup )
3708 menu->items[0].hSubMenu = MENU_CopySysPopup();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003709 }
3710 }
3711
3712 if(!wndPtr->hSysMenu && (wndPtr->dwStyle & WS_SYSMENU) )
Alexandre Julliarda3960291999-02-26 11:11:13 +00003713 wndPtr->hSysMenu = MENU_GetSysMenu( hWnd, (HMENU)(-1) );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003714
3715 if( wndPtr->hSysMenu )
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003716 {
3717 HMENU retvalue = GetSubMenu16(wndPtr->hSysMenu, 0);
3718 WIN_ReleaseWndPtr(wndPtr);
3719 return retvalue;
3720 }
3721 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00003722 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003723 return 0;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003724}
3725
Alexandre Julliard7e56f681996-01-31 19:02:28 +00003726
3727/*******************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003728 * SetSystemMenu16 (USER.280)
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00003729 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003730BOOL16 WINAPI SetSystemMenu16( HWND16 hwnd, HMENU16 hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003731{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003732 return SetSystemMenu( hwnd, hMenu );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003733}
3734
3735
3736/*******************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003737 * SetSystemMenu32 (USER32.508)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003738 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003739BOOL WINAPI SetSystemMenu( HWND hwnd, HMENU hMenu )
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00003740{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003741 WND *wndPtr = WIN_FindWndPtr(hwnd);
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00003742
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003743 if (wndPtr)
3744 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003745 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003746 wndPtr->hSysMenu = MENU_GetSysMenu( hwnd, hMenu );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003747 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003748 return TRUE;
3749 }
3750 return FALSE;
Alexandre Julliard1d62f6b1994-05-04 19:15:00 +00003751}
3752
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003753
3754/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003755 * GetMenu16 (USER.157)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003756 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003757HMENU16 WINAPI GetMenu16( HWND16 hWnd )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003758{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003759 HMENU16 retvalue;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003760 WND * wndPtr = WIN_FindWndPtr(hWnd);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003761 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003762 {
3763 retvalue = (HMENU16)wndPtr->wIDmenu;
3764 goto END;
3765}
3766 retvalue = 0;
3767END:
3768 WIN_ReleaseWndPtr(wndPtr);
3769 return retvalue;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003770}
3771
3772
3773/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003774 * GetMenu32 (USER32.257)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003775 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003776HMENU WINAPI GetMenu( HWND hWnd )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003777{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003778 HMENU retvalue;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003779 WND * wndPtr = WIN_FindWndPtr(hWnd);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003780 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD))
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003781 {
3782 retvalue = (HMENU)wndPtr->wIDmenu;
3783 goto END;
3784 }
3785 retvalue = 0;
3786END:
3787 WIN_ReleaseWndPtr(wndPtr);
3788 return retvalue;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003789}
3790
3791
3792/**********************************************************************
3793 * SetMenu16 (USER.158)
3794 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003795BOOL16 WINAPI SetMenu16( HWND16 hWnd, HMENU16 hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003796{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003797 return SetMenu( hWnd, hMenu );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003798}
3799
3800
3801/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003802 * SetMenu32 (USER32.487)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003803 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003804BOOL WINAPI SetMenu( HWND hWnd, HMENU hMenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003805{
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003806 WND * wndPtr = WIN_FindWndPtr(hWnd);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003807
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003808 TRACE(menu,"(%04x, %04x);\n", hWnd, hMenu);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003809
3810 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD))
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003811 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003812 if (GetCapture() == hWnd) ReleaseCapture();
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003813
Alexandre Julliarda3960291999-02-26 11:11:13 +00003814 wndPtr->wIDmenu = (UINT)hMenu;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003815 if (hMenu != 0)
3816 {
3817 LPPOPUPMENU lpmenu;
3818
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003819 if (!(lpmenu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu)))
3820 {
3821 WIN_ReleaseWndPtr(wndPtr);
3822 return FALSE;
3823 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003824 lpmenu->hWnd = hWnd;
3825 lpmenu->wFlags &= ~MF_POPUP; /* Can't be a popup */
3826 lpmenu->Height = 0; /* Make sure we recalculate the size */
3827 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00003828 if (IsWindowVisible(hWnd))
3829 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
Alexandre Julliard01d63461997-01-20 19:43:45 +00003830 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003831 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003832 return TRUE;
3833 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003834 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003835 return FALSE;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003836}
3837
3838
Alexandre Julliardd18872d1994-05-11 12:18:19 +00003839
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003840/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003841 * GetSubMenu16 (USER.159)
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003842 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003843HMENU16 WINAPI GetSubMenu16( HMENU16 hMenu, INT16 nPos )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003844{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003845 return GetSubMenu( hMenu, nPos );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003846}
3847
3848
3849/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003850 * GetSubMenu32 (USER32.288)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003851 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003852HMENU WINAPI GetSubMenu( HMENU hMenu, INT nPos )
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003853{
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003854 MENUITEM * lpmi;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003855
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00003856 if (!(lpmi = MENU_FindItem(&hMenu,&nPos,MF_BYPOSITION))) return 0;
3857 if (!(lpmi->fType & MF_POPUP)) return 0;
3858 return lpmi->hSubMenu;
Alexandre Julliarddba420a1994-02-02 06:48:31 +00003859}
3860
3861
3862/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003863 * DrawMenuBar16 (USER.160)
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003864 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003865void WINAPI DrawMenuBar16( HWND16 hWnd )
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003866{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003867 DrawMenuBar( hWnd );
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003868}
Alexandre Julliardf7207251994-07-23 07:57:48 +00003869
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003870
3871/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00003872 * DrawMenuBar (USER32.161)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003873 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003874BOOL WINAPI DrawMenuBar( HWND hWnd )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003875{
3876 LPPOPUPMENU lppop;
3877 WND *wndPtr = WIN_FindWndPtr(hWnd);
3878 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && wndPtr->wIDmenu)
3879 {
3880 lppop = (LPPOPUPMENU) USER_HEAP_LIN_ADDR((HMENU16)wndPtr->wIDmenu);
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003881 if (lppop == NULL)
3882 {
3883 WIN_ReleaseWndPtr(wndPtr);
3884 return FALSE;
3885 }
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003886
3887 lppop->Height = 0; /* Make sure we call MENU_MenuBarCalcSize */
Juergen Schmied78513941999-04-18 14:40:32 +00003888 lppop->hwndOwner = hWnd;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003889 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
Alexandre Julliard01d63461997-01-20 19:43:45 +00003890 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003891 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003892 return TRUE;
3893 }
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00003894 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003895 return FALSE;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003896}
3897
3898
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003899/***********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003900 * EndMenu (USER.187) (USER32.175)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003901 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003902void WINAPI EndMenu(void)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003903{
Alex Korobka4f1ac051999-03-28 09:37:57 +00003904 /*
3905 * FIXME: NOT ENOUGH! This has to cancel menu tracking right away.
3906 */
3907
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003908 fEndMenu = TRUE;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003909}
3910
3911
3912/***********************************************************************
3913 * LookupMenuHandle (USER.217)
3914 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003915HMENU16 WINAPI LookupMenuHandle16( HMENU16 hmenu, INT16 id )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003916{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003917 HMENU hmenu32 = hmenu;
3918 UINT id32 = id;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003919 if (!MENU_FindItem( &hmenu32, &id32, MF_BYCOMMAND )) return 0;
3920 else return hmenu32;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00003921}
3922
3923
Alexandre Julliardcdd09231994-01-12 11:12:51 +00003924/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00003925 * LoadMenu16 (USER.150)
Alexandre Julliard594997c1995-04-30 10:05:20 +00003926 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003927HMENU16 WINAPI LoadMenu16( HINSTANCE16 instance, SEGPTR name )
Alexandre Julliard594997c1995-04-30 10:05:20 +00003928{
Alexandre Julliard18f92e71996-07-17 20:02:21 +00003929 HRSRC16 hRsrc;
3930 HGLOBAL16 handle;
3931 HMENU16 hMenu;
Alexandre Julliard594997c1995-04-30 10:05:20 +00003932
3933 if (HIWORD(name))
3934 {
3935 char *str = (char *)PTR_SEG_TO_LIN( name );
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003936 TRACE(menu, "(%04x,'%s')\n", instance, str );
Alexandre Julliard594997c1995-04-30 10:05:20 +00003937 if (str[0] == '#') name = (SEGPTR)atoi( str + 1 );
3938 }
3939 else
Dimitrie O. Paun05c0c8e1999-03-28 15:07:41 +00003940 TRACE(menu,"(%04x,%04x)\n",instance,LOWORD(name));
Alexandre Julliard594997c1995-04-30 10:05:20 +00003941
3942 if (!name) return 0;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003943
3944 /* check for Win32 module */
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00003945 if (HIWORD(instance))
Alexandre Julliarda3960291999-02-26 11:11:13 +00003946 return LoadMenuA(instance,PTR_SEG_TO_LIN(name));
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00003947 instance = GetExePtr( instance );
Alexandre Julliard594997c1995-04-30 10:05:20 +00003948
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003949 if (!(hRsrc = FindResource16( instance, name, RT_MENU16 ))) return 0;
Alexandre Julliard18f92e71996-07-17 20:02:21 +00003950 if (!(handle = LoadResource16( instance, hRsrc ))) return 0;
3951 hMenu = LoadMenuIndirect16(LockResource16(handle));
3952 FreeResource16( handle );
Alexandre Julliard594997c1995-04-30 10:05:20 +00003953 return hMenu;
3954}
3955
3956
Alexandre Julliard18f92e71996-07-17 20:02:21 +00003957/*****************************************************************
3958 * LoadMenu32A (USER32.370)
3959 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003960HMENU WINAPI LoadMenuA( HINSTANCE instance, LPCSTR name )
Alexandre Julliard18f92e71996-07-17 20:02:21 +00003961{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003962 HRSRC hrsrc = FindResourceA( instance, name, RT_MENUA );
Alexandre Julliard18f92e71996-07-17 20:02:21 +00003963 if (!hrsrc) return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003964 return LoadMenuIndirectA( (LPCVOID)LoadResource( instance, hrsrc ));
Alexandre Julliard18f92e71996-07-17 20:02:21 +00003965}
3966
3967
3968/*****************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00003969 * LoadMenu32W (USER32.373)
Alexandre Julliard18f92e71996-07-17 20:02:21 +00003970 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003971HMENU WINAPI LoadMenuW( HINSTANCE instance, LPCWSTR name )
Alexandre Julliard18f92e71996-07-17 20:02:21 +00003972{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003973 HRSRC hrsrc = FindResourceW( instance, name, RT_MENUW );
Alexandre Julliard18f92e71996-07-17 20:02:21 +00003974 if (!hrsrc) return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003975 return LoadMenuIndirectW( (LPCVOID)LoadResource( instance, hrsrc ));
Alexandre Julliard18f92e71996-07-17 20:02:21 +00003976}
3977
3978
Alexandre Julliard594997c1995-04-30 10:05:20 +00003979/**********************************************************************
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003980 * LoadMenuIndirect16 (USER.220)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003981 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003982HMENU16 WINAPI LoadMenuIndirect16( LPCVOID template )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003983{
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00003984 HMENU16 hMenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003985 WORD version, offset;
3986 LPCSTR p = (LPCSTR)template;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003987
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003988 TRACE(menu,"(%p)\n", template );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003989 version = GET_WORD(p);
3990 p += sizeof(WORD);
3991 if (version)
3992 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00003993 WARN(menu, "version must be 0 for Win16\n" );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003994 return 0;
3995 }
3996 offset = GET_WORD(p);
3997 p += sizeof(WORD) + offset;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003998 if (!(hMenu = CreateMenu())) return 0;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00003999 if (!MENU_ParseResource( p, hMenu, FALSE ))
Alexandre Julliard7e56f681996-01-31 19:02:28 +00004000 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004001 DestroyMenu( hMenu );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004002 return 0;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00004003 }
4004 return hMenu;
Alexandre Julliardcdd09231994-01-12 11:12:51 +00004005}
4006
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00004007
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004008/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00004009 * LoadMenuIndirect32A (USER32.371)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004010 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004011HMENU WINAPI LoadMenuIndirectA( LPCVOID template )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004012{
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00004013 HMENU16 hMenu;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004014 WORD version, offset;
4015 LPCSTR p = (LPCSTR)template;
4016
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00004017 TRACE(menu,"%p\n", template );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004018 version = GET_WORD(p);
4019 p += sizeof(WORD);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004020 switch (version)
4021 {
4022 case 0:
4023 offset = GET_WORD(p);
4024 p += sizeof(WORD) + offset;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004025 if (!(hMenu = CreateMenu())) return 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004026 if (!MENU_ParseResource( p, hMenu, TRUE ))
4027 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004028 DestroyMenu( hMenu );
Alexandre Julliard641ee761997-08-04 16:34:36 +00004029 return 0;
4030 }
4031 return hMenu;
4032 case 1:
4033 offset = GET_WORD(p);
4034 p += sizeof(WORD) + offset;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004035 if (!(hMenu = CreateMenu())) return 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004036 if (!MENUEX_ParseResource( p, hMenu))
4037 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00004038 DestroyMenu( hMenu );
Alexandre Julliard641ee761997-08-04 16:34:36 +00004039 return 0;
4040 }
4041 return hMenu;
4042 default:
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00004043 ERR(menu, "version %d not supported.\n", version);
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004044 return 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004045 }
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004046}
4047
4048
4049/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00004050 * LoadMenuIndirect32W (USER32.372)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004051 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004052HMENU WINAPI LoadMenuIndirectW( LPCVOID template )
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004053{
4054 /* FIXME: is there anything different between A and W? */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004055 return LoadMenuIndirectA( template );
Alexandre Julliard2d93d001996-05-21 15:01:41 +00004056}
4057
4058
4059/**********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004060 * IsMenu16 (USER.358)
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004061 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004062BOOL16 WINAPI IsMenu16( HMENU16 hmenu )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004063{
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004064 LPPOPUPMENU menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hmenu);
4065 return IS_A_MENU(menu);
4066}
4067
4068
4069/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00004070 * IsMenu32 (USER32.346)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004071 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004072BOOL WINAPI IsMenu(HMENU hmenu)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004073{
4074 LPPOPUPMENU menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hmenu);
4075 return IS_A_MENU(menu);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004076}
4077
Alexandre Julliard641ee761997-08-04 16:34:36 +00004078/**********************************************************************
4079 * GetMenuItemInfo32_common
4080 */
4081
Juergen Schmied78513941999-04-18 14:40:32 +00004082static BOOL GetMenuItemInfo_common ( HMENU hmenu, UINT item, BOOL bypos,
4083 LPMENUITEMINFOA lpmii, BOOL unicode)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004084{
Juergen Schmied78513941999-04-18 14:40:32 +00004085 MENUITEM *menu = MENU_FindItem (&hmenu, &item, bypos? MF_BYPOSITION : 0);
4086
Alexandre Julliard03468f71998-02-15 19:40:49 +00004087 debug_print_menuitem("GetMenuItemInfo32_common: ", menu, "");
Juergen Schmied78513941999-04-18 14:40:32 +00004088
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004089 if (!menu)
4090 return FALSE;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004091
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004092 if (lpmii->fMask & MIIM_TYPE) {
4093 lpmii->fType = menu->fType;
4094 switch (MENU_ITEM_TYPE(menu->fType)) {
Juergen Schmied78513941999-04-18 14:40:32 +00004095 case MF_STRING:
4096 if (menu->text && lpmii->dwTypeData && lpmii->cch) {
4097 if (unicode) {
4098 lstrcpynAtoW((LPWSTR) lpmii->dwTypeData, menu->text, lpmii->cch);
4099 lpmii->cch = lstrlenW((LPWSTR)menu->text);
4100 } else {
4101 lstrcpynA(lpmii->dwTypeData, menu->text, lpmii->cch);
4102 lpmii->cch = lstrlenA(menu->text);
4103 }
4104 }
4105 break;
4106 case MF_OWNERDRAW:
4107 case MF_BITMAP:
4108 lpmii->dwTypeData = menu->text;
4109 /* fall through */
4110 default:
4111 lpmii->cch = 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004112 }
Alexandre Julliard641ee761997-08-04 16:34:36 +00004113 }
Juergen Schmied78513941999-04-18 14:40:32 +00004114
4115 if (lpmii->fMask & MIIM_STRING) {
4116 if (unicode) {
4117 lstrcpynAtoW((LPWSTR) lpmii->dwTypeData, menu->text, lpmii->cch);
4118 lpmii->cch = lstrlenW((LPWSTR)menu->text);
4119 } else {
4120 lstrcpynA(lpmii->dwTypeData, menu->text, lpmii->cch);
4121 lpmii->cch = lstrlenA(menu->text);
4122 }
Alexandre Julliard641ee761997-08-04 16:34:36 +00004123 }
Juergen Schmied78513941999-04-18 14:40:32 +00004124
4125 if (lpmii->fMask & MIIM_FTYPE)
4126 lpmii->fType = menu->fType;
4127
4128 if (lpmii->fMask & MIIM_BITMAP)
4129 lpmii->hbmpItem = menu->hbmpItem;
4130
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004131 if (lpmii->fMask & MIIM_STATE)
4132 lpmii->fState = menu->fState;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004133
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004134 if (lpmii->fMask & MIIM_ID)
4135 lpmii->wID = menu->wID;
4136
4137 if (lpmii->fMask & MIIM_SUBMENU)
4138 lpmii->hSubMenu = menu->hSubMenu;
4139
4140 if (lpmii->fMask & MIIM_CHECKMARKS) {
4141 lpmii->hbmpChecked = menu->hCheckBit;
4142 lpmii->hbmpUnchecked = menu->hUnCheckBit;
4143 }
4144 if (lpmii->fMask & MIIM_DATA)
4145 lpmii->dwItemData = menu->dwItemData;
Alexandre Julliard641ee761997-08-04 16:34:36 +00004146
4147 return TRUE;
4148}
4149
4150/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004151 * GetMenuItemInfoA (USER32.264)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004152 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004153BOOL WINAPI GetMenuItemInfoA( HMENU hmenu, UINT item, BOOL bypos,
4154 LPMENUITEMINFOA lpmii)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004155{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004156 return GetMenuItemInfo_common (hmenu, item, bypos, lpmii, FALSE);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004157}
4158
4159/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004160 * GetMenuItemInfoW (USER32.265)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004161 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004162BOOL WINAPI GetMenuItemInfoW( HMENU hmenu, UINT item, BOOL bypos,
4163 LPMENUITEMINFOW lpmii)
Alexandre Julliard641ee761997-08-04 16:34:36 +00004164{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004165 return GetMenuItemInfo_common (hmenu, item, bypos,
4166 (LPMENUITEMINFOA)lpmii, TRUE);
Alexandre Julliard641ee761997-08-04 16:34:36 +00004167}
4168
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004169/**********************************************************************
4170 * SetMenuItemInfo32_common
4171 */
4172
Alexandre Julliarda3960291999-02-26 11:11:13 +00004173static BOOL SetMenuItemInfo_common(MENUITEM * menu,
4174 const MENUITEMINFOA *lpmii,
4175 BOOL unicode)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004176{
4177 if (!menu) return FALSE;
4178
Juergen Schmied78513941999-04-18 14:40:32 +00004179 if (lpmii->fMask & MIIM_TYPE ) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004180 /* Get rid of old string. */
Juergen Schmied78513941999-04-18 14:40:32 +00004181 if ( IS_STRING_ITEM(menu->fType) && menu->text) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004182 HeapFree(SystemHeap, 0, menu->text);
Juergen Schmied78513941999-04-18 14:40:32 +00004183 menu->text = NULL;
4184 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004185
Juergen Schmied78513941999-04-18 14:40:32 +00004186 /* make only MENU_ITEM_TYPE bits in menu->fType equal lpmii->fType */
4187 menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
4188 menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
Paul Millar39da2221999-04-11 12:08:42 +00004189
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004190 menu->text = lpmii->dwTypeData;
Juergen Schmied78513941999-04-18 14:40:32 +00004191
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004192 if (IS_STRING_ITEM(menu->fType) && menu->text) {
Juergen Schmied78513941999-04-18 14:40:32 +00004193 if (unicode)
4194 menu->text = HEAP_strdupWtoA(SystemHeap, 0, (LPWSTR) lpmii->dwTypeData);
4195 else
4196 menu->text = HEAP_strdupA(SystemHeap, 0, lpmii->dwTypeData);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004197 }
4198 }
Juergen Schmied78513941999-04-18 14:40:32 +00004199
4200 if (lpmii->fMask & MIIM_FTYPE ) {
4201 /* free the string when the type is changing */
4202 if ( (!IS_STRING_ITEM(lpmii->fType)) && IS_STRING_ITEM(menu->fType) && menu->text) {
4203 HeapFree(SystemHeap, 0, menu->text);
4204 menu->text = NULL;
4205 }
4206 menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
4207 menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
4208 }
4209
4210 if (lpmii->fMask & MIIM_STRING ) {
4211 /* free the string when used */
4212 if ( IS_STRING_ITEM(menu->fType) && menu->text) {
4213 HeapFree(SystemHeap, 0, menu->text);
4214 if (unicode)
4215 menu->text = HEAP_strdupWtoA(SystemHeap, 0, (LPWSTR) lpmii->dwTypeData);
4216 else
4217 menu->text = HEAP_strdupA(SystemHeap, 0, lpmii->dwTypeData);
4218 }
4219 }
4220
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004221 if (lpmii->fMask & MIIM_STATE)
4222 menu->fState = lpmii->fState;
4223
4224 if (lpmii->fMask & MIIM_ID)
4225 menu->wID = lpmii->wID;
4226
Alexandre Julliarda0d77311998-09-13 16:32:00 +00004227 if (lpmii->fMask & MIIM_SUBMENU) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004228 menu->hSubMenu = lpmii->hSubMenu;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00004229 if (menu->hSubMenu) {
4230 POPUPMENU *subMenu = (POPUPMENU *)USER_HEAP_LIN_ADDR((UINT16)menu->hSubMenu);
4231 if (IS_A_MENU(subMenu)) {
4232 subMenu->wFlags |= MF_POPUP;
4233 menu->fType |= MF_POPUP;
4234 }
4235 else
4236 /* FIXME: Return an error ? */
4237 menu->fType &= ~MF_POPUP;
4238 }
4239 else
4240 menu->fType &= ~MF_POPUP;
4241 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004242
4243 if (lpmii->fMask & MIIM_CHECKMARKS)
4244 {
4245 menu->hCheckBit = lpmii->hbmpChecked;
4246 menu->hUnCheckBit = lpmii->hbmpUnchecked;
4247 }
4248 if (lpmii->fMask & MIIM_DATA)
4249 menu->dwItemData = lpmii->dwItemData;
4250
Alexandre Julliard03468f71998-02-15 19:40:49 +00004251 debug_print_menuitem("SetMenuItemInfo32_common: ", menu, "");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004252 return TRUE;
4253}
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004254
4255/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00004256 * SetMenuItemInfo32A (USER32.491)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00004257 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004258BOOL WINAPI SetMenuItemInfoA(HMENU hmenu, UINT item, BOOL bypos,
4259 const MENUITEMINFOA *lpmii)
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004260{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004261 return SetMenuItemInfo_common(MENU_FindItem(&hmenu, &item, bypos? MF_BYPOSITION : 0),
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004262 lpmii, FALSE);
4263}
4264
4265/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00004266 * SetMenuItemInfo32W (USER32.492)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004267 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004268BOOL WINAPI SetMenuItemInfoW(HMENU hmenu, UINT item, BOOL bypos,
4269 const MENUITEMINFOW *lpmii)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004270{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004271 return SetMenuItemInfo_common(MENU_FindItem(&hmenu, &item, bypos? MF_BYPOSITION : 0),
4272 (const MENUITEMINFOA*)lpmii, TRUE);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004273}
4274
4275/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00004276 * SetMenuDefaultItem32 (USER32.489)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004277 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004278BOOL WINAPI SetMenuDefaultItem(HMENU hmenu, UINT item, UINT bypos)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004279{
Alexandre Julliarda845b881998-06-01 10:44:35 +00004280 MENUITEM *menuitem = MENU_FindItem(&hmenu, &item, bypos);
4281 POPUPMENU *menu;
4282
4283 if (!menuitem) return FALSE;
4284 if (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(hmenu))) return FALSE;
4285
4286 menu->defitem = item; /* position */
4287
4288 debug_print_menuitem("SetMenuDefaultItem32: ", menuitem, "");
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00004289 FIXME(menu, "(0x%x,%d,%d), empty stub!\n",
4290 hmenu, item, bypos);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004291 return TRUE;
4292}
4293
Alexandre Julliarda845b881998-06-01 10:44:35 +00004294/**********************************************************************
Juergen Schmiedc77fd5b1999-04-21 14:27:37 +00004295 * GetMenuDefaultItem (USER32.260)
Alexandre Julliarda845b881998-06-01 10:44:35 +00004296 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004297UINT WINAPI GetMenuDefaultItem(HMENU hmenu, UINT bypos, UINT flags)
Alexandre Julliarda845b881998-06-01 10:44:35 +00004298{
4299 POPUPMENU *menu;
4300
Eric Kohl329072d1998-10-24 10:46:10 +00004301 if (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(hmenu)))
4302 return -1;
Alexandre Julliarda845b881998-06-01 10:44:35 +00004303
4304 FIXME(menu, "(0x%x,%d,%d), stub!\n", hmenu, bypos, flags);
4305 if (bypos & MF_BYPOSITION)
4306 return menu->defitem;
Eric Kohl329072d1998-10-24 10:46:10 +00004307 else {
4308 FIXME (menu, "default item 0x%x\n", menu->defitem);
4309 if ((menu->defitem > 0) && (menu->defitem < menu->nItems))
4310 return menu->items[menu->defitem].wID;
4311 }
4312 return -1;
Alexandre Julliarda845b881998-06-01 10:44:35 +00004313}
4314
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004315/*******************************************************************
4316 * InsertMenuItem16 (USER.441)
4317 *
4318 * FIXME: untested
4319 */
4320BOOL16 WINAPI InsertMenuItem16( HMENU16 hmenu, UINT16 pos, BOOL16 byposition,
4321 const MENUITEMINFO16 *mii )
4322{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004323 MENUITEMINFOA miia;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004324
4325 miia.cbSize = sizeof(miia);
4326 miia.fMask = mii->fMask;
Alexandre Julliard77b99181997-09-14 17:17:23 +00004327 miia.dwTypeData = mii->dwTypeData;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004328 miia.fType = mii->fType;
4329 miia.fState = mii->fState;
4330 miia.wID = mii->wID;
4331 miia.hSubMenu = mii->hSubMenu;
4332 miia.hbmpChecked = mii->hbmpChecked;
4333 miia.hbmpUnchecked = mii->hbmpUnchecked;
4334 miia.dwItemData = mii->dwItemData;
4335 miia.cch = mii->cch;
4336 if (IS_STRING_ITEM(miia.fType))
4337 miia.dwTypeData = PTR_SEG_TO_LIN(miia.dwTypeData);
Alexandre Julliarda3960291999-02-26 11:11:13 +00004338 return InsertMenuItemA( hmenu, pos, byposition, &miia );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004339}
4340
4341
4342/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00004343 * InsertMenuItem32A (USER32.323)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004344 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004345BOOL WINAPI InsertMenuItemA(HMENU hMenu, UINT uItem, BOOL bypos,
4346 const MENUITEMINFOA *lpmii)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004347{
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00004348 MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
Alexandre Julliarda3960291999-02-26 11:11:13 +00004349 return SetMenuItemInfo_common(item, lpmii, FALSE);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004350}
4351
4352
4353/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00004354 * InsertMenuItem32W (USER32.324)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004355 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004356BOOL WINAPI InsertMenuItemW(HMENU hMenu, UINT uItem, BOOL bypos,
4357 const MENUITEMINFOW *lpmii)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00004358{
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00004359 MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
Alexandre Julliarda3960291999-02-26 11:11:13 +00004360 return SetMenuItemInfo_common(item, (const MENUITEMINFOA*)lpmii, TRUE);
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00004361}
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004362
4363/**********************************************************************
4364 * CheckMenuRadioItem32 (USER32.47)
4365 */
4366
Alexandre Julliarda3960291999-02-26 11:11:13 +00004367BOOL WINAPI CheckMenuRadioItem(HMENU hMenu,
4368 UINT first, UINT last, UINT check,
4369 UINT bypos)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004370{
4371 MENUITEM *mifirst, *milast, *micheck;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004372 HMENU mfirst = hMenu, mlast = hMenu, mcheck = hMenu;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004373
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00004374 TRACE(menu, "ox%x: %d-%d, check %d, bypos=%d\n",
4375 hMenu, first, last, check, bypos);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004376
4377 mifirst = MENU_FindItem (&mfirst, &first, bypos);
4378 milast = MENU_FindItem (&mlast, &last, bypos);
4379 micheck = MENU_FindItem (&mcheck, &check, bypos);
4380
4381 if (mifirst == NULL || milast == NULL || micheck == NULL ||
4382 mifirst > milast || mfirst != mlast || mfirst != mcheck ||
4383 micheck > milast || micheck < mifirst)
4384 return FALSE;
4385
4386 while (mifirst <= milast)
4387 {
4388 if (mifirst == micheck)
4389 {
4390 mifirst->fType |= MFT_RADIOCHECK;
4391 mifirst->fState |= MFS_CHECKED;
4392 } else {
4393 mifirst->fType &= ~MFT_RADIOCHECK;
4394 mifirst->fState &= ~MFS_CHECKED;
4395 }
4396 mifirst++;
4397 }
4398
4399 return TRUE;
4400}
4401
4402/**********************************************************************
4403 * CheckMenuRadioItem16 (not a Windows API)
4404 */
4405
4406BOOL16 WINAPI CheckMenuRadioItem16(HMENU16 hMenu,
4407 UINT16 first, UINT16 last, UINT16 check,
4408 BOOL16 bypos)
4409{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004410 return CheckMenuRadioItem (hMenu, first, last, check, bypos);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004411}
4412
4413/**********************************************************************
4414 * GetMenuItemRect32 (USER32.266)
Pascal Lessard47274231999-02-13 12:21:46 +00004415 *
4416 * ATTENTION: Here, the returned values in rect are the screen
4417 * coordinates of the item just like if the menu was
4418 * always on the upper left side of the application.
4419 *
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004420 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004421BOOL WINAPI GetMenuItemRect (HWND hwnd, HMENU hMenu, UINT uItem,
4422 LPRECT rect)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004423{
Pascal Lessard47274231999-02-13 12:21:46 +00004424 POPUPMENU *itemMenu;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004425 MENUITEM *item;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004426 HWND referenceHwnd;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004427
Pascal Lessard47274231999-02-13 12:21:46 +00004428 TRACE(menu, "(0x%x,0x%x,%d,%p)\n", hwnd, hMenu, uItem, rect);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004429
4430 item = MENU_FindItem (&hMenu, &uItem, MF_BYPOSITION);
Pascal Lessard47274231999-02-13 12:21:46 +00004431 referenceHwnd = hwnd;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004432
Pascal Lessard47274231999-02-13 12:21:46 +00004433 if(!hwnd)
4434 {
4435 itemMenu = (POPUPMENU *) USER_HEAP_LIN_ADDR(hMenu);
4436 if (itemMenu == NULL)
4437 return FALSE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004438
Marcus Meissnerac593bb1999-03-17 15:18:28 +00004439 if(itemMenu->hWnd == 0)
Pascal Lessard47274231999-02-13 12:21:46 +00004440 return FALSE;
4441 referenceHwnd = itemMenu->hWnd;
4442 }
4443
4444 if ((rect == NULL) || (item == NULL))
4445 return FALSE;
4446
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004447 *rect = item->rect;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004448
Alexandre Julliarda3960291999-02-26 11:11:13 +00004449 MapWindowPoints(referenceHwnd, 0, (LPPOINT)rect, 2);
Pascal Lessard47274231999-02-13 12:21:46 +00004450
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004451 return TRUE;
4452}
4453
4454/**********************************************************************
4455 * GetMenuItemRect16 (USER.665)
4456 */
4457
4458BOOL16 WINAPI GetMenuItemRect16 (HWND16 hwnd, HMENU16 hMenu, UINT16 uItem,
4459 LPRECT16 rect)
4460{
Alexandre Julliarda3960291999-02-26 11:11:13 +00004461 RECT r32;
4462 BOOL res;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004463
4464 if (!rect) return FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00004465 res = GetMenuItemRect (hwnd, hMenu, uItem, &r32);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00004466 CONV_RECT32TO16 (&r32, rect);
4467 return res;
4468}
Paul Quinn1beaae51998-12-15 15:38:36 +00004469
4470/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004471 * SetMenuInfo
4472 *
4473 * FIXME
4474 * MIM_APPLYTOSUBMENUS
4475 * actually use the items to draw the menu
4476 */
4477BOOL WINAPI SetMenuInfo (HMENU hMenu, LPCMENUINFO lpmi)
4478{
4479 POPUPMENU *menu;
4480
4481 TRACE(menu,"(0x%04x %p)\n", hMenu, lpmi);
4482
4483 if (lpmi && (lpmi->cbSize==sizeof(MENUINFO)) && (menu=(POPUPMENU*)USER_HEAP_LIN_ADDR(hMenu)))
4484 {
4485
4486 if (lpmi->fMask & MIM_BACKGROUND)
4487 menu->hbrBack = lpmi->hbrBack;
4488
4489 if (lpmi->fMask & MIM_HELPID)
4490 menu->dwContextHelpID = lpmi->dwContextHelpID;
4491
4492 if (lpmi->fMask & MIM_MAXHEIGHT)
4493 menu->cyMax = lpmi->cyMax;
4494
4495 if (lpmi->fMask & MIM_MENUDATA)
4496 menu->dwMenuData = lpmi->dwMenuData;
4497
4498 if (lpmi->fMask & MIM_STYLE)
4499 menu->dwStyle = lpmi->dwStyle;
4500
4501 return TRUE;
4502 }
4503 return FALSE;
4504}
4505
4506/**********************************************************************
4507 * GetMenuInfo
4508 *
4509 * NOTES
4510 * win98/NT5.0
4511 *
4512 */
4513BOOL WINAPI GetMenuInfo (HMENU hMenu, LPMENUINFO lpmi)
4514{ POPUPMENU *menu;
4515
4516 TRACE(menu,"(0x%04x %p)\n", hMenu, lpmi);
4517
4518 if (lpmi && (menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(hMenu)))
4519 {
4520
4521 if (lpmi->fMask & MIM_BACKGROUND)
4522 lpmi->hbrBack = menu->hbrBack;
4523
4524 if (lpmi->fMask & MIM_HELPID)
4525 lpmi->dwContextHelpID = menu->dwContextHelpID;
4526
4527 if (lpmi->fMask & MIM_MAXHEIGHT)
4528 lpmi->cyMax = menu->cyMax;
4529
4530 if (lpmi->fMask & MIM_MENUDATA)
4531 lpmi->dwMenuData = menu->dwMenuData;
4532
4533 if (lpmi->fMask & MIM_STYLE)
4534 lpmi->dwStyle = menu->dwStyle;
4535
4536 return TRUE;
4537 }
4538 return FALSE;
4539}
4540
4541/**********************************************************************
Paul Quinn1beaae51998-12-15 15:38:36 +00004542 * SetMenuContextHelpId16 (USER.384)
4543 */
Juergen Schmied78513941999-04-18 14:40:32 +00004544BOOL16 WINAPI SetMenuContextHelpId16( HMENU16 hMenu, DWORD dwContextHelpID)
Paul Quinn1beaae51998-12-15 15:38:36 +00004545{
Juergen Schmied78513941999-04-18 14:40:32 +00004546 return SetMenuContextHelpId( hMenu, dwContextHelpID );
Paul Quinn1beaae51998-12-15 15:38:36 +00004547}
4548
4549
4550/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004551 * SetMenuContextHelpId (USER32.488)
Paul Quinn1beaae51998-12-15 15:38:36 +00004552 */
Juergen Schmied78513941999-04-18 14:40:32 +00004553BOOL WINAPI SetMenuContextHelpId( HMENU hMenu, DWORD dwContextHelpID)
Paul Quinn1beaae51998-12-15 15:38:36 +00004554{
Juergen Schmied78513941999-04-18 14:40:32 +00004555 LPPOPUPMENU menu;
4556
4557 TRACE(menu,"(0x%04x 0x%08lx)\n", hMenu, dwContextHelpID);
4558
4559 if ((menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(hMenu)))
4560 {
4561 menu->dwContextHelpID = dwContextHelpID;
4562 return TRUE;
4563 }
4564 return FALSE;
Paul Quinn1beaae51998-12-15 15:38:36 +00004565}
4566
4567/**********************************************************************
4568 * GetMenuContextHelpId16 (USER.385)
4569 */
4570DWORD WINAPI GetMenuContextHelpId16( HMENU16 hMenu )
4571{
Juergen Schmied78513941999-04-18 14:40:32 +00004572 return GetMenuContextHelpId( hMenu );
Paul Quinn1beaae51998-12-15 15:38:36 +00004573}
4574
4575/**********************************************************************
Juergen Schmied78513941999-04-18 14:40:32 +00004576 * GetMenuContextHelpId (USER32.488)
Paul Quinn1beaae51998-12-15 15:38:36 +00004577 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004578DWORD WINAPI GetMenuContextHelpId( HMENU hMenu )
Paul Quinn1beaae51998-12-15 15:38:36 +00004579{
Juergen Schmied78513941999-04-18 14:40:32 +00004580 LPPOPUPMENU menu;
4581
4582 TRACE(menu,"(0x%04x)\n", hMenu);
4583
4584 if ((menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(hMenu)))
4585 {
4586 return menu->dwContextHelpID;
4587 }
4588 return 0;
Paul Quinn1beaae51998-12-15 15:38:36 +00004589}