Release 940405
[wine/gsoc-2012-control.git] / controls / menu.c
blob9ab0366b600c61a334c4ccd6f2943f22f3b90c7b
1 /*
2 * Menus functions
3 */
4 static char RCSId[] = "$Id$";
5 static char Copyright[] = "Copyright Martin Ayotte, 1993";
7 /*
8 #define DEBUG_MENU
9 */
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include "windows.h"
14 #include "sysmetrics.h"
15 #include "prototypes.h"
16 #include "menu.h"
17 #include "heap.h"
18 #include "win.h"
20 #define SC_ABOUTWINE SC_SCREENSAVE+1
21 #define SC_SYSMENU SC_SCREENSAVE+2
22 #define SC_ABOUTWINEDLG SC_SCREENSAVE+3
24 extern HINSTANCE hSysRes;
25 HMENU hSysMenu = 0;
26 HBITMAP hStdCheck = 0;
27 HBITMAP hStdMnArrow = 0;
28 static BOOL MenuHasFocus = FALSE;
30 LPPOPUPMENU PopupMenuGetStorageHeader(HWND hwnd);
31 LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr);
32 void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop);
33 BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
34 void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
35 void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y);
36 void StdDrawPopupMenu(HWND hwnd);
37 void ResetHiliteFlags(LPPOPUPMENU lppop);
38 BOOL ExecFocusedMenuItem(HWND hWnd, LPPOPUPMENU lppop);
39 void MenuItemSelect(HWND hWnd, LPPOPUPMENU lppop, WORD wIndex);
40 LPMENUITEM MenuFindItem(LPPOPUPMENU lppop, int x, int y, WORD *lpRet);
41 LPMENUITEM MenuFindItemBySelKey(LPPOPUPMENU lppop, WORD key, WORD *lpRet);
42 BOOL ActivateMenuFocus(HWND hWnd);
43 BOOL MenuFocusLoop(HWND hWnd, LPPOPUPMENU lpmenu);
44 void PopupMenuCalcSize(HWND hwnd);
45 void MenuBarCalcSize(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop);
46 LPMENUITEM FindMenuItem(HMENU hMenu, WORD nPos, WORD wFlags);
47 LPMENUITEM GetMenuItemPtr(LPPOPUPMENU menu, WORD nPos);
48 WORD GetSelectionKey(LPSTR str);
49 LPSTR GetShortCutString(LPSTR str);
50 WORD GetShortCutPos(LPSTR str);
51 BOOL HideAllSubPopupMenu(LPPOPUPMENU menu);
52 HMENU CopySysMenu();
53 WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu);
54 void SetMenuLogicalParent(HMENU hMenu, HWND hWnd);
56 BOOL FAR PASCAL AboutWine_Proc(HWND hDlg, WORD msg, WORD wParam, LONG lParam);
58 /***********************************************************************
59 * PopupMenuWndProc
61 LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
63 CREATESTRUCT *createStruct;
64 WORD wRet;
65 short x, y;
66 WND *wndPtr;
67 LPPOPUPMENU lppop, lppop2;
68 LPMENUITEM lpitem, lpitem2;
69 HMENU hSubMenu;
70 RECT rect;
71 HDC hDC;
72 PAINTSTRUCT ps;
73 switch(message) {
74 case WM_CREATE:
75 #ifdef DEBUG_MENU
76 printf("PopupMenu WM_CREATE lParam=%08X !\n", lParam);
77 #endif
78 createStruct = (CREATESTRUCT *)lParam;
79 lppop = (LPPOPUPMENU)createStruct->lpCreateParams;
80 if (lppop == NULL) break;
81 wndPtr = WIN_FindWndPtr(hwnd);
82 *((LPPOPUPMENU *)&wndPtr->wExtra[1]) = lppop;
83 #ifdef DEBUG_MENU
84 printf("PopupMenu WM_CREATE lppop=%08X !\n", lppop);
85 #endif
86 if (hStdCheck == (HBITMAP)NULL)
87 hStdCheck = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_CHECK);
88 if (hStdMnArrow == (HBITMAP)NULL)
89 hStdMnArrow = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_MNARROW);
90 return 0;
91 case WM_DESTROY:
92 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
93 #ifdef DEBUG_MENU
94 printf("PopupMenu WM_DESTROY %lX !\n", lppop);
95 #endif
96 return 0;
97 case WM_COMMAND:
98 #ifdef DEBUG_MENU
99 printf("PopupMenuWndProc // WM_COMMAND received !\n");
100 #endif
101 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
102 if (lppop == NULL) break;
103 /* if (!lppop->BarFlag) ShowWindow(hwnd, SW_HIDE); */
104 if (lppop->SysFlag) {
105 MenuHasFocus = FALSE;
106 if (wParam == SC_ABOUTWINE) {
107 printf("SysMenu // Show 'About Wine ...' !\n");
108 /* DialogBox(hSysRes, MAKEINTRESOURCE(SC_ABOUTWINEDLG), */
109 DialogBox(hSysRes, MAKEINTRESOURCE(2),
110 GetParent(hwnd), (FARPROC)AboutWine_Proc);
112 else
113 #ifdef DEBUG_MENU
114 printf("PopupMenuWndProc // push to Owner WM_SYSCOMMAND !\n");
115 #endif
116 PostMessage(lppop->ownerWnd, WM_SYSCOMMAND, wParam, lParam);
117 /* PostMessage(lppop->hWndParent, WM_SYSCOMMAND, wParam, lParam); */
118 break;
120 #ifdef DEBUG_MENU
121 printf("PopupMenuWndProc // push to Owner WM_COMMAND !\n");
122 #endif
123 MenuHasFocus = FALSE;
124 PostMessage(lppop->hWndParent, WM_COMMAND, wParam, lParam);
125 /* PostMessage(lppop->ownerWnd, WM_COMMAND, wParam, lParam); */
126 break;
127 case WM_SHOWWINDOW:
128 #ifdef DEBUG_MENU
129 printf("PopupMenuWndProc // WM_SHOWWINDOW received !\n");
130 #endif
131 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
132 if (lppop == NULL) break;
133 if (wParam == 0 && lParam == 0L) {
134 HideAllSubPopupMenu(lppop);
135 #ifdef DEBUG_MENU
136 printf("PopupMenuWndProc hWnd=%04X WM_SHOWWINDOW -> HIDE!\n", hwnd);
137 #endif
138 if (lppop->SysFlag) MenuHasFocus = FALSE;
139 SetFocus(lppop->hWndPrev);
140 break;
142 lppop->FocusedItem = (WORD)-1;
143 if (!lppop->BarFlag) {
144 PopupMenuCalcSize(hwnd);
145 ResetHiliteFlags(lppop);
146 #ifdef DEBUG_MENU
147 printf("PopupMenuWndProc hWnd=%04X WM_SHOWWINDOW Width=%d Height=%d !\n",
148 hwnd, lppop->Width, lppop->Height);
149 #endif
150 SetWindowPos(hwnd, 0, 0, 0, lppop->Width + 2, lppop->Height,
151 SWP_NOZORDER | SWP_NOMOVE);
152 #ifdef DEBUG_MENU
153 printf("PopupMenuWndProc // End of WM_SHOWWINDOW !\n");
154 #endif
156 break;
157 case WM_LBUTTONDOWN:
158 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
159 if (lppop == NULL) break;
160 SetCapture(hwnd);
161 MenuButtonDown(hwnd, lppop, LOWORD(lParam), HIWORD(lParam));
162 break;
163 case WM_LBUTTONUP:
164 lppop = PopupMenuGetStorageHeader(hwnd);
165 if (lppop == NULL) break;
166 ReleaseCapture();
167 MenuButtonUp(hwnd, lppop, LOWORD(lParam), HIWORD(lParam));
168 break;
169 case WM_MOUSEMOVE:
170 lppop = PopupMenuGetStorageHeader(hwnd);
171 if (lppop == NULL) break;
172 MenuMouseMove(hwnd, lppop, wParam, LOWORD(lParam), HIWORD(lParam));
173 break;
175 case WM_KEYUP:
176 #ifdef DEBUG_MENU
177 printf("PopupMenuWndProc hWnd=%04X WM_KEYUP w=%04X l=%08X !\n",
178 hwnd, wParam, lParam);
179 #endif
180 break;
181 case WM_KEYDOWN:
182 #ifdef DEBUG_MENU
183 printf("PopupMenuWndProc hWnd=%04X WM_KEYDOWN w=%04X l=%08X !\n",
184 hwnd, wParam, lParam);
185 #endif
186 if (lParam < 0L) break;
187 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
188 if (lppop == NULL) break;
189 switch(wParam) {
190 case VK_HOME:
191 if (lppop->FocusedItem == 0) break;
192 MenuItemSelect(hwnd, lppop, 0);
193 break;
194 case VK_UP:
195 if (lppop->BarFlag) break;
196 if (lppop->FocusedItem < 1) break;
197 MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
198 break;
199 case VK_DOWN:
200 if (lppop->BarFlag) goto ProceedSPACE;
201 if (lppop->FocusedItem == (WORD)-1) {
202 MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
203 break;
205 if (lppop->FocusedItem >= lppop->nItems - 1) break;
206 MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
207 break;
208 case VK_LEFT:
209 if (lppop->SysFlag != 0) {
210 ShowWindow(hwnd, SW_HIDE);
211 hwnd = lppop->hWndParent;
212 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
213 if (lppop == NULL) break;
214 MenuItemSelect(hwnd, lppop, lppop->nItems - 1);
215 break;
217 if (lppop->BarFlag) {
218 if (lppop->FocusedItem < 1) {
219 MenuItemSelect(hwnd, lppop, -1);
220 NC_TrackSysMenu(hwnd);
221 break;
223 if (HideAllSubPopupMenu(lppop)) {
224 MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
225 goto ProceedSPACE;
228 if (lppop->hWndParent != 0) {
229 PostMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam);
230 break;
232 MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
233 break;
234 case VK_RIGHT:
235 if (lppop->SysFlag != 0) {
236 ShowWindow(hwnd, SW_HIDE);
237 hwnd = lppop->hWndParent;
238 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
239 if (lppop == NULL) break;
240 MenuItemSelect(hwnd, lppop, 0);
241 break;
243 if (lppop->BarFlag) {
244 if (lppop->FocusedItem >= lppop->nItems - 1) {
245 MenuItemSelect(hwnd, lppop, -1);
246 NC_TrackSysMenu(hwnd);
247 break;
249 if (HideAllSubPopupMenu(lppop)) {
250 MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
251 goto ProceedSPACE;
254 if (lppop->hWndParent != 0) {
255 PostMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam);
256 break;
258 MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
259 break;
260 case VK_RETURN:
261 case VK_SPACE:
262 ProceedSPACE: lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
263 ExecFocusedMenuItem(hwnd, lppop);
264 break;
265 default:
266 break;
268 break;
269 case WM_CHAR:
270 #ifdef DEBUG_MENU
271 printf("PopupMenuWndProc hWnd=%04X WM_CHAR wParam=%04X !\n", hwnd, wParam);
272 #endif
273 if (lParam < 0L) break;
274 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
275 if (lppop == NULL) break;
276 if (wParam == VK_ESCAPE) {
277 if (lppop->BarFlag) {
278 #ifdef DEBUG_MENU
279 printf("VK_ESCAPE // Unselect all MenuBar's Items !\n");
280 #endif
281 if (lppop->FocusedItem != (WORD)-1)
282 MenuItemSelect(hwnd, lppop, -1);
284 if (lppop->SysFlag) {
285 #ifdef DEBUG_MENU
286 printf("VK_ESCAPE // SysMenu !\n");
287 #endif
288 ShowWindow(hwnd, SW_HIDE);
289 break;
291 if (lppop->hWndParent != 0) {
292 #ifdef DEBUG_MENU
293 printf("VK_ESCAPE // Hide only SubPopup !\n");
294 #endif
295 lppop2 = PopupMenuGetWindowAndStorage(lppop->hWndParent, &wndPtr);
296 if (lppop2 == NULL) break;
297 HideAllSubPopupMenu(lppop2);
298 break;
300 else {
301 #ifdef DEBUG_MENU
302 printf("VK_ESCAPE // Hide Root Popup !\n");
303 #endif
304 ShowWindow(hwnd, SW_HIDE);
305 MenuHasFocus = FALSE;
307 break;
309 if (wParam >= 'a' && wParam <= 'z') wParam -= 'a' - 'A';
310 lpitem = MenuFindItemBySelKey(lppop, wParam, &wRet);
311 if (lpitem != NULL) {
312 printf("Found wRet=%d !\n", wRet);
313 MenuItemSelect(hwnd, lppop, wRet);
314 lppop->FocusedItem = wRet;
315 goto ProceedSPACE;
317 if (lppop->hWndParent != (HWND)NULL)
318 SendMessage(lppop->hWndParent, WM_MENUCHAR, wParam,
319 MAKELONG(0, 0));
320 else
321 SendMessage(lppop->ownerWnd, WM_MENUCHAR, wParam,
322 MAKELONG(0, 0));
323 break;
324 case WM_PAINT:
325 #ifdef DEBUG_MENU
326 printf("PopupMenuWndProc // WM_PAINT received !\n");
327 #endif
328 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
329 if (lppop == NULL) break;
330 if (!lppop->BarFlag) {
331 PopupMenuCalcSize(hwnd);
332 StdDrawPopupMenu(hwnd);
334 break;
335 default:
336 return DefWindowProc(hwnd, message, wParam, lParam);
338 return 0;
342 BOOL ExecFocusedMenuItem(HWND hWnd, LPPOPUPMENU lppop)
344 short x, y;
345 LPPOPUPMENU lppop2;
346 LPMENUITEM lpitem;
347 HMENU hSubMenu;
348 RECT rect;
349 lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
350 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
351 hSubMenu = (HMENU)lpitem->item_id;
352 lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
353 if (lppop2 == NULL) return FALSE;
354 lppop2->hWndParent = hWnd;
355 lppop2->hWndPrev = GetFocus();
356 GetClientRect(hWnd, &rect);
357 if (lppop->BarFlag) {
358 GetWindowRect(hWnd, &rect);
359 y = rect.top + lppop->rect.bottom;
360 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
361 rect.left + lpitem->rect.left,
362 y, 0, lppop->ownerWnd, (LPRECT)NULL);
364 else {
365 x = lppop->rect.right;
366 GetWindowRect(hWnd, &rect);
367 x += rect.left;
368 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
369 x, rect.top + lpitem->rect.top,
370 0, lppop->ownerWnd, (LPRECT)NULL);
372 GlobalUnlock(hSubMenu);
373 return TRUE;
375 if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
376 ((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
377 MenuHasFocus = FALSE;
378 if (lppop->BarFlag) {
379 PostMessage(lppop->ownerWnd, WM_COMMAND, lpitem->item_id, 0L);
381 else {
382 ShowWindow(lppop->hWnd, SW_HIDE);
383 SendMessage(lppop->hWnd, WM_COMMAND, lpitem->item_id, 0L);
386 return TRUE;
391 BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y)
393 HDC hDC;
394 LPMENUITEM lpitem, lpitem2;
395 RECT rect;
396 HMENU hSubMenu;
397 WORD wRet;
398 LPPOPUPMENU lppop2;
399 if (lppop == NULL) return;
400 lpitem = MenuFindItem(lppop, x, y, &wRet);
401 #ifdef DEBUG_MENU
402 printf("MenuButtonDown // x=%d y=%d // wRet=%d lpitem=%08X !\n",
403 x, y, wRet, lpitem);
404 #endif
405 if (lpitem != NULL) {
406 MenuItemSelect(hWnd, lppop, wRet);
407 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
408 hSubMenu = (HMENU)lpitem->item_id;
409 lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
410 if (lppop2 == NULL) return;
411 lppop2->hWndParent = hWnd;
412 lppop2->hWndPrev = GetFocus();
413 if (lppop->BarFlag) {
414 GetWindowRect(hWnd, &rect);
415 y = rect.top + lppop->rect.bottom;
416 ReleaseCapture();
417 if (MenuHasFocus) {
418 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
419 rect.left + lpitem->rect.left,
420 y, 0, lppop->ownerWnd, (LPRECT)NULL);
422 else {
423 MenuHasFocus = TRUE;
424 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
425 rect.left + lpitem->rect.left,
426 y, 0, lppop->ownerWnd, (LPRECT)NULL);
427 MenuHasFocus = FALSE;
428 MenuFocusLoop(hWnd, lppop);
429 return TRUE;
432 else {
433 x = lppop->rect.right;
434 GetWindowRect(hWnd, &rect);
435 x += rect.left;
436 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
437 x, rect.top + lpitem->rect.top,
438 0, lppop->ownerWnd, (LPRECT)NULL);
440 GlobalUnlock(hSubMenu);
442 return TRUE;
444 printf("MenuButtonDown // x=%d y=%d // Not Found !\n", x, y);
445 MenuHasFocus = FALSE;
446 ShowWindow(lppop->hWnd, SW_HIDE);
447 return FALSE;
452 void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y)
454 HDC hDC;
455 LPMENUITEM lpitem, lpitem2;
456 RECT rect;
457 HMENU hSubMenu;
458 WORD wRet;
459 LPPOPUPMENU lppop2;
460 if (lppop == NULL) return;
461 lpitem = MenuFindItem(lppop, x, y, &wRet);
462 #ifdef DEBUG_MENU
463 printf("MenuButtonUp // x=%d y=%d // wRet=%d lpitem=%08X !\n",
464 x, y, wRet, lpitem);
465 #endif
466 if (lpitem != NULL) {
467 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
468 return;
470 if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
471 ((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
472 MenuHasFocus = FALSE;
473 if (lppop->BarFlag) {
474 PostMessage(lppop->ownerWnd, WM_COMMAND, lpitem->item_id, 0L);
476 else {
477 ShowWindow(lppop->hWnd, SW_HIDE);
478 SendMessage(lppop->hWnd, WM_COMMAND, lpitem->item_id, 0L);
480 return;
483 if (lppop->FocusedItem != (WORD)-1) {
484 MenuItemSelect(hWnd, lppop, lppop->FocusedItem);
490 void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y)
492 HDC hDC;
493 RECT rect;
494 HMENU hSubMenu;
495 LPMENUITEM lpitem, lpitem2;
496 LPPOPUPMENU lppop2;
497 WORD wRet;
498 if ((wParam & MK_LBUTTON) != 0) {
499 lpitem = MenuFindItem(lppop, x, y, &wRet);
500 #ifdef DEBUG_MENU
501 printf("MenuMouseMove // x=%d y=%d // wRet=%d lpitem=%08X !\n",
502 x, y, wRet, lpitem);
503 #endif
504 if ((lpitem != NULL) && (lppop->FocusedItem != wRet)) {
505 lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem);
506 hDC = GetWindowDC(hWnd);
507 if ((lpitem2->item_flags & MF_POPUP) == MF_POPUP) {
508 HideAllSubPopupMenu(lppop);
510 MenuItemSelect(hWnd, lppop, wRet);
511 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
512 hSubMenu = (HMENU)lpitem->item_id;
513 lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
514 if (lppop2 == NULL) {
515 ReleaseDC(hWnd, hDC);
516 return;
518 if (lppop->BarFlag) {
519 lppop2->hWndParent = hWnd;
520 lppop2->hWndPrev = GetFocus();
521 GetWindowRect(hWnd, &rect);
522 rect.top += lppop->rect.bottom;
523 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
524 rect.left + lpitem->rect.left, rect.top,
525 0, lppop->ownerWnd, (LPRECT)NULL);
527 GlobalUnlock(hSubMenu);
529 ReleaseDC(hWnd, hDC);
535 void ResetHiliteFlags(LPPOPUPMENU lppop)
537 HDC hDC;
538 LPMENUITEM lpitem;
539 int i;
540 if (lppop == NULL) return;
541 lpitem = lppop->firstItem;
542 for(i = 0; i < lppop->nItems; i++) {
543 if (lpitem == NULL) return;
544 lpitem->item_flags &= MF_HILITE ^ 0xFFFF;
545 lpitem = (LPMENUITEM)lpitem->next;
550 void MenuItemSelect0(HWND hWnd, LPPOPUPMENU lppop,
551 LPMENUITEM lpitem, WORD wIndex)
553 LPMENUITEM lpprev;
554 if (lppop == NULL) return;
555 if (lppop->FocusedItem != (WORD)-1) {
556 lpprev = GetMenuItemPtr(lppop, lppop->FocusedItem);
557 if (lpprev != NULL) {
558 lpprev->item_flags &= MF_HILITE ^ 0xFFFF;
559 if ((lpprev->item_flags & MF_POPUP) == MF_POPUP)
560 HideAllSubPopupMenu(lppop);
561 if (lppop->BarFlag)
562 DrawMenuBar(hWnd);
563 else {
564 InvalidateRect(hWnd, &lpprev->rect, TRUE);
565 UpdateWindow(hWnd);
569 lppop->FocusedItem = wIndex;
570 if (lpitem == NULL || wIndex == (WORD)-1) {
571 ResetHiliteFlags(lppop);
572 if (lppop->BarFlag) DrawMenuBar(hWnd);
574 else {
575 lpitem->item_flags |= MF_HILITE;
576 if (lppop->BarFlag)
577 DrawMenuBar(hWnd);
578 else {
579 InvalidateRect(hWnd, &lpitem->rect, TRUE);
580 UpdateWindow(hWnd);
583 SendMessage(hWnd, WM_MENUSELECT, lpitem->item_id,
584 MAKELONG(0, lpitem->item_flags));
588 void MenuItemSelect(HWND hWnd, LPPOPUPMENU lppop, WORD wIndex)
590 LPMENUITEM lpitem;
591 lpitem = GetMenuItemPtr(lppop, wIndex);
592 MenuItemSelect0(hWnd, lppop, lpitem, wIndex);
596 LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr)
598 WND *Ptr;
599 LPPOPUPMENU lppop;
600 *(wndPtr) = Ptr = WIN_FindWndPtr(hwnd);
601 if (Ptr == 0) {
602 printf("PopupMenuGetWindowAndStorage // Bad Window handle !\n");
603 return NULL;
605 lppop = *((LPPOPUPMENU *)&Ptr->wExtra[1]);
606 if (lppop == NULL) {
607 lppop = (LPPOPUPMENU) GlobalLock(Ptr->wIDmenu);
608 if (lppop == NULL) {
609 printf("PopupMenuGetWindowAndStorage // Bad Menu Handle !\n");
610 return NULL;
613 return lppop;
617 LPPOPUPMENU PopupMenuGetStorageHeader(HWND hwnd)
619 WND *Ptr;
620 LPPOPUPMENU lppop;
621 Ptr = WIN_FindWndPtr(hwnd);
622 if (Ptr == 0) {
623 printf("Bad Window handle on PopupMenu !\n");
624 return 0;
626 lppop = *((LPPOPUPMENU *)&Ptr->wExtra[1]);
627 return lppop;
631 void SetMenuLogicalParent(HMENU hMenu, HWND hWnd)
633 LPPOPUPMENU lppop;
634 lppop = (LPPOPUPMENU)GlobalLock(hMenu);
635 lppop->hWndParent = hWnd;
636 GlobalUnlock(hMenu);
640 void StdDrawPopupMenu(HWND hwnd)
642 WND *wndPtr;
643 LPPOPUPMENU lppop;
644 LPMENUITEM lpitem;
645 PAINTSTRUCT ps;
646 HBRUSH hBrush;
647 HPEN hOldPen;
648 HWND hWndParent;
649 HDC hDC, hMemDC;
650 RECT rect, rect2, rect3;
651 DWORD OldTextColor;
652 int OldBkMode;
653 HFONT hOldFont;
654 HBITMAP hBitMap;
655 BITMAP bm;
656 UINT i, x;
657 hDC = BeginPaint(hwnd, &ps);
658 if (!IsWindowVisible(hwnd)) {
659 EndPaint(hwnd, &ps);
660 return;
662 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
663 if (lppop == NULL) goto EndOfPaint;
664 hBrush = GetStockObject(WHITE_BRUSH);
665 GetClientRect(hwnd, &rect);
666 GetClientRect(hwnd, &rect2);
667 FillRect(hDC, &rect, hBrush);
668 FrameRect(hDC, &rect, GetStockObject(BLACK_BRUSH));
669 if (lppop->nItems == 0) goto EndOfPaint;
670 lpitem = lppop->firstItem;
671 if (lpitem == NULL) goto EndOfPaint;
672 for(i = 0; i < lppop->nItems; i++) {
673 CopyRect(&rect2, &lpitem->rect);
674 if ((lpitem->item_flags & MF_SEPARATOR) == MF_SEPARATOR) {
675 hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN));
676 MoveTo(hDC, rect2.left, rect2.top + 1);
677 LineTo(hDC, rect2.right, rect2.top + 1);
678 SelectObject(hDC, hOldPen);
680 if ((lpitem->item_flags & MF_CHECKED) == MF_CHECKED) {
681 hMemDC = CreateCompatibleDC(hDC);
682 if (lpitem->hCheckBit == 0) {
683 SelectObject(hMemDC, hStdCheck);
684 GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
686 else {
687 SelectObject(hMemDC, lpitem->hCheckBit);
688 GetObject(lpitem->hCheckBit, sizeof(BITMAP), (LPSTR)&bm);
690 BitBlt(hDC, rect2.left, rect2.top + 1,
691 bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
692 DeleteDC(hMemDC);
694 else {
695 if (lpitem->hUnCheckBit != 0) {
696 hMemDC = CreateCompatibleDC(hDC);
697 SelectObject(hMemDC, lpitem->hUnCheckBit);
698 GetObject(lpitem->hUnCheckBit, sizeof(BITMAP), (LPSTR)&bm);
699 BitBlt(hDC, rect2.left, rect2.top + 1,
700 bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
701 DeleteDC(hMemDC);
704 if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
705 hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
706 rect2.left += lppop->CheckWidth;
707 hMemDC = CreateCompatibleDC(hDC);
708 SelectObject(hMemDC, hBitMap);
709 GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
710 BitBlt(hDC, rect2.left, rect2.top,
711 bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
712 DeleteDC(hMemDC);
713 if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
714 InvertRect(hDC, &lpitem->rect);
716 if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
717 ((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
718 ((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
719 hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
720 OldBkMode = SetBkMode(hDC, TRANSPARENT);
721 if ((lpitem->item_flags & MF_DISABLED) == MF_DISABLED)
722 OldTextColor = SetTextColor(hDC, 0x00C0C0C0L);
723 else {
724 if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
725 OldTextColor = SetTextColor(hDC, 0x00FFFFFFL);
726 else
727 OldTextColor = SetTextColor(hDC, 0x00000000L);
729 CopyRect(&rect3, &lpitem->rect);
730 if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
731 FillRect(hDC, &rect3, GetStockObject(BLACK_BRUSH));
732 InflateRect(&rect3, 0, -2);
733 rect3.left += lppop->CheckWidth;
734 if ((x = GetShortCutPos(lpitem->item_text)) != (WORD)-1) {
735 DrawText(hDC, lpitem->item_text, x, &rect3,
736 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
737 DrawText(hDC, &lpitem->item_text[x], -1, &rect3,
738 DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
740 else
741 DrawText(hDC, lpitem->item_text, -1, &rect3,
742 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
743 SetTextColor(hDC, OldTextColor);
744 SetBkMode(hDC, OldBkMode);
745 SelectObject(hDC, hOldFont);
746 CopyRect(&rect2, &lpitem->rect);
748 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
749 CopyRect(&rect3, &lpitem->rect);
750 rect3.left = rect3.right - lppop->PopWidth;
751 hMemDC = CreateCompatibleDC(hDC);
752 SelectObject(hMemDC, hStdMnArrow);
753 GetObject(hStdMnArrow, sizeof(BITMAP), (LPSTR)&bm);
754 BitBlt(hDC, rect3.left, rect3.top + 1,
755 bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
756 DeleteDC(hMemDC);
758 if (lpitem->next == NULL) goto EndOfPaint;
759 lpitem = (LPMENUITEM)lpitem->next;
761 EndOfPaint:
762 EndPaint( hwnd, &ps );
767 void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop)
769 LPMENUITEM lpitem;
770 HBRUSH hBrush;
771 HPEN hOldPen;
772 HDC hMemDC;
773 RECT rect, rect2, rect3;
774 HFONT hOldFont;
775 DWORD OldTextColor;
776 int OldBkMode;
777 HBITMAP hBitMap;
778 BITMAP bm;
779 UINT i, textwidth;
780 if (lppop == NULL || lprect == NULL) return;
781 #ifdef DEBUG_MENU
782 printf("StdDrawMenuBar(%04X, %08X, %08X); !\n", hDC, lprect, lppop);
783 #endif
784 MenuBarCalcSize(hDC, lprect, lppop);
785 hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
786 hBrush = GetStockObject(WHITE_BRUSH);
787 CopyRect(&rect, lprect);
788 FillRect(hDC, &rect, hBrush);
789 FrameRect(hDC, &rect, GetStockObject(BLACK_BRUSH));
790 if (lppop->nItems == 0) goto EndOfPaint;
791 lpitem = lppop->firstItem;
792 if (lpitem == NULL) goto EndOfPaint;
793 for(i = 0; i < lppop->nItems; i++) {
794 CopyRect(&rect2, &lpitem->rect);
795 if ((lpitem->item_flags & MF_CHECKED) == MF_CHECKED) {
796 hMemDC = CreateCompatibleDC(hDC);
797 if (lpitem->hCheckBit == 0) {
798 SelectObject(hMemDC, hStdCheck);
799 GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
801 else {
802 SelectObject(hMemDC, lpitem->hCheckBit);
803 GetObject(lpitem->hCheckBit, sizeof(BITMAP), (LPSTR)&bm);
805 BitBlt(hDC, rect2.left, rect2.top + 1,
806 bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
807 DeleteDC(hMemDC);
809 else {
810 if (lpitem->hUnCheckBit != 0) {
811 hMemDC = CreateCompatibleDC(hDC);
812 SelectObject(hMemDC, lpitem->hUnCheckBit);
813 GetObject(lpitem->hUnCheckBit, sizeof(BITMAP), (LPSTR)&bm);
814 BitBlt(hDC, rect2.left, rect2.top + 1,
815 bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
816 DeleteDC(hMemDC);
819 if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
820 hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
821 hMemDC = CreateCompatibleDC(hDC);
822 SelectObject(hMemDC, hBitMap);
823 GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
824 BitBlt(hDC, rect2.left, rect2.top,
825 bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
826 DeleteDC(hMemDC);
828 if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
829 ((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
830 ((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
831 hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
832 OldBkMode = SetBkMode(hDC, TRANSPARENT);
833 if ((lpitem->item_flags & MF_DISABLED) == MF_DISABLED)
834 OldTextColor = SetTextColor(hDC, 0x00C0C0C0L);
835 else {
836 if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
837 OldTextColor = SetTextColor(hDC, 0x00FFFFFFL);
838 else
839 OldTextColor = SetTextColor(hDC, 0x00000000L);
841 if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
842 FillRect(hDC, &rect2, GetStockObject(BLACK_BRUSH));
843 DrawText(hDC, lpitem->item_text, -1, &rect2,
844 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
845 SetTextColor(hDC, OldTextColor);
846 SetBkMode(hDC, OldBkMode);
847 SelectObject(hDC, hOldFont);
849 if (lpitem->next == NULL) goto EndOfPaint;
850 lpitem = (LPMENUITEM)lpitem->next;
852 EndOfPaint:
853 SelectObject(hDC, hOldFont);
858 LPMENUITEM MenuFindItem(LPPOPUPMENU lppop, int x, int y, WORD *lpRet)
860 LPMENUITEM lpitem;
861 UINT i;
862 if (lpRet != NULL) *lpRet = 0;
863 if (lppop == NULL) return NULL;
864 if (lppop->nItems == 0) return NULL;
865 lpitem = lppop->firstItem;
866 for(i = 0; i < lppop->nItems; i++) {
867 if (lpitem == NULL) return NULL;
868 #ifdef DEBUG_MENUFINDITEM
869 printf("FindItem // left=%d top=%d right=%d bottom=%d\n",
870 lpitem->rect.left, lpitem->rect.top,
871 lpitem->rect.right, lpitem->rect.bottom);
872 #endif
873 if (x > lpitem->rect.left && x < lpitem->rect.right &&
874 y > lpitem->rect.top && y < lpitem->rect.bottom) {
875 if (lpRet != NULL) *lpRet = i;
876 return lpitem;
878 lpitem = (LPMENUITEM)lpitem->next;
880 return NULL;
884 LPMENUITEM MenuFindItemBySelKey(LPPOPUPMENU lppop, WORD key, WORD *lpRet)
886 LPMENUITEM lpitem;
887 UINT i;
888 if (lppop == NULL) return NULL;
889 if (lppop->nItems == 0) return NULL;
890 lpitem = lppop->firstItem;
891 for(i = 0; i < lppop->nItems; i++) {
892 if (lpitem == NULL) return NULL;
893 #ifdef DEBUG_MENUFINDITEM
894 printf("FindItemBySelKey // key=%d lpitem->sel_key=%d\n",
895 key, lpitem->sel_key);
896 #endif
897 if (key == lpitem->sel_key) {
898 if (lpRet != NULL) *lpRet = i;
899 return lpitem;
901 lpitem = (LPMENUITEM)lpitem->next;
903 return NULL;
907 void PopupMenuCalcSize(HWND hwnd)
909 WND *wndPtr;
910 LPPOPUPMENU lppop;
911 LPMENUITEM lpitem;
912 HDC hDC;
913 RECT rect;
914 HBITMAP hBitMap;
915 BITMAP bm;
916 HFONT hOldFont;
917 UINT i, OldWidth, TempWidth;
918 DWORD dwRet;
919 #ifdef DEBUG_MENUCALC
920 printf("PopupMenuCalcSize hWnd=%04X !\n", hWnd);
921 #endif
922 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
923 if (lppop == NULL) return;
924 if (lppop->nItems == 0) return;
925 hDC = GetDC(hwnd);
926 lppop->Width = 20;
927 lppop->CheckWidth = lppop->PopWidth = 0;
928 hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
929 CalcAGAIN:
930 OldWidth = lppop->Width;
931 SetRect(&rect, 1, 1, OldWidth, 0);
932 lpitem = lppop->firstItem;
933 for(i = 0; i < lppop->nItems; i++) {
934 if (lpitem == NULL) break;
935 #ifdef DEBUG_MENUCALC
936 printf("PopupMenuCalcSize item #%d !\n", i);
937 #endif
938 rect.right = rect.left + lppop->Width;
939 if ((lpitem->item_flags & MF_CHECKED) == MF_CHECKED) {
940 if (lpitem->hCheckBit != 0)
941 GetObject(lpitem->hCheckBit, sizeof(BITMAP), (LPSTR)&bm);
942 else
943 GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
944 lppop->CheckWidth = max(lppop->CheckWidth, bm.bmWidth);
946 else {
947 if (lpitem->hUnCheckBit != 0) {
948 GetObject(lpitem->hUnCheckBit, sizeof(BITMAP), (LPSTR)&bm);
949 lppop->CheckWidth = max(lppop->CheckWidth, bm.bmWidth);
952 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
953 GetObject(hStdMnArrow, sizeof(BITMAP), (LPSTR)&bm);
954 lppop->PopWidth = max(lppop->PopWidth, bm.bmWidth);
956 if ((lpitem->item_flags & MF_SEPARATOR) == MF_SEPARATOR) {
957 rect.bottom = rect.top + 3;
959 if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
960 hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
961 GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
962 rect.bottom = rect.top + bm.bmHeight;
963 lppop->Width = max(lppop->Width, bm.bmWidth);
965 if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
966 ((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
967 ((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
968 dwRet = GetTextExtent(hDC, (char *)lpitem->item_text,
969 strlen((char *)lpitem->item_text));
970 rect.bottom = rect.top + HIWORD(dwRet);
971 InflateRect(&rect, 0, 2);
972 TempWidth = LOWORD(dwRet);
973 if (GetShortCutPos(lpitem->item_text) != (WORD)-1)
974 TempWidth += 15;
975 TempWidth += lppop->CheckWidth;
976 TempWidth += lppop->PopWidth;
977 lppop->Width = max(lppop->Width, TempWidth);
979 CopyRect(&lpitem->rect, &rect);
980 rect.top = rect.bottom;
981 lpitem = (LPMENUITEM)lpitem->next;
983 if (OldWidth < lppop->Width) goto CalcAGAIN;
984 lppop->Height = rect.bottom;
985 SetRect(&lppop->rect, 1, 1, lppop->Width, lppop->Height);
986 #ifdef DEBUG_MENUCALC
987 printf("PopupMenuCalcSize w=%d h=%d !\n", lppop->Width, lppop->Height);
988 #endif
989 SelectObject(hDC, hOldFont);
990 ReleaseDC(hwnd, hDC);
995 void MenuBarCalcSize(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop)
997 LPMENUITEM lpitem;
998 RECT rect;
999 HBITMAP hBitMap;
1000 BITMAP bm;
1001 HFONT hOldFont;
1002 UINT i, OldHeight;
1003 DWORD dwRet;
1004 if (lppop == NULL) return;
1005 if (lppop->nItems == 0) return;
1006 #ifdef DEBUG_MENUCALC
1007 printf("MenuBarCalcSize left=%d top=%d right=%d bottom=%d !\n",
1008 lprect->left, lprect->top, lprect->right, lprect->bottom);
1009 #endif
1010 hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
1011 lppop->Height = lprect->bottom - lprect->top;
1012 CalcAGAIN:
1013 OldHeight = lppop->Height;
1014 SetRect(&rect, lprect->left, lprect->top, 0, lprect->top + OldHeight);
1015 lpitem = lppop->firstItem;
1016 for(i = 0; i < lppop->nItems; i++) {
1017 if (lpitem == NULL) break;
1018 rect.bottom = lprect->top + lppop->Height;
1019 if (rect.right > lprect->right)
1020 SetRect(&rect, lprect->left, rect.bottom,
1021 0, rect.bottom + SYSMETRICS_CYMENU);
1022 if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
1023 hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
1024 GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
1025 rect.right = rect.left + bm.bmWidth;
1026 lppop->Height = max(lppop->Height, bm.bmHeight);
1028 if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
1029 ((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
1030 ((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
1031 dwRet = GetTextExtent(hDC, (char *)lpitem->item_text,
1032 strlen((char *)lpitem->item_text));
1033 rect.right = rect.left + LOWORD(dwRet) + 10;
1034 dwRet = max(SYSMETRICS_CYMENU, (HIWORD(dwRet) + 6));
1035 lppop->Height = max(lppop->Height, (WORD)dwRet);
1037 CopyRect(&lpitem->rect, &rect);
1038 rect.left = rect.right;
1039 lpitem = (LPMENUITEM)lpitem->next;
1041 if (OldHeight < lppop->Height) goto CalcAGAIN;
1042 lppop->Width = rect.right;
1043 lprect->bottom = lprect->top + lppop->Height;
1044 CopyRect(&lppop->rect, lprect);
1045 #ifdef DEBUG_MENUCALC
1046 printf("MenuBarCalcSize w=%d h=%d !\n", lppop->Width, lppop->Height);
1047 #endif
1048 SelectObject(hDC, hOldFont);
1053 /***********************************************************************
1054 * FindMenuItem
1056 LPMENUITEM FindMenuItem(HMENU hMenu, WORD nPos, WORD wFlags)
1058 LPPOPUPMENU menu;
1059 LPMENUITEM lpitem;
1060 int i;
1061 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1062 if (menu == NULL) {
1063 GlobalUnlock(hMenu);
1064 return FALSE;
1066 lpitem = menu->firstItem;
1067 if (wFlags & MF_BYPOSITION) {
1068 for (i = 0; i < nPos; i++, lpitem = lpitem->next)
1069 if (lpitem == NULL) return NULL;
1071 else {
1072 for (i = 0; i < menu->nItems && lpitem != NULL; i++) {
1073 if (lpitem->item_id == nPos) return lpitem;
1074 lpitem = lpitem->next;
1076 return NULL;
1078 return lpitem;
1082 LPMENUITEM GetMenuItemPtr(LPPOPUPMENU menu, WORD nPos)
1084 LPMENUITEM lpitem;
1085 int i;
1086 if (menu == NULL) return NULL;
1087 lpitem = menu->firstItem;
1088 for (i = 0; i < menu->nItems; i++) {
1089 if (lpitem == NULL) return NULL;
1090 if (i == nPos) return(lpitem);
1091 lpitem = (LPMENUITEM)lpitem->next;
1093 return NULL;
1097 WORD GetSelectionKey(LPSTR str)
1099 int i;
1100 WORD sel_key;
1101 for (i = 0; i < strlen(str); i++) {
1102 if (str[i] == '&' && str[i + 1] != '&') {
1103 sel_key = str[i + 1];
1104 if (sel_key >= 'a' && sel_key <= 'z') sel_key -= 'a' - 'A';
1105 #ifdef DEBUG_MENU
1106 printf("GetSelectionKey // %04X\n", sel_key);
1107 #endif
1108 return sel_key;
1111 #ifdef DEBUG_MENU
1112 printf("GetSelectionKey NULL \n");
1113 #endif
1114 return 0;
1119 LPSTR GetShortCutString(LPSTR str)
1121 int i;
1122 LPSTR str2;
1123 for (i = 0; i < strlen(str); i++) {
1124 if (str[i] == '\t' && str[i + 1] != '\t') {
1125 str2 = &str[i + 1];
1126 #ifdef DEBUG_MENUSHORTCUT
1127 printf("GetShortCutString // '%s' \n", str2);
1128 #endif
1129 return str2;
1132 #ifdef DEBUG_MENUSHORTCUT
1133 printf("GetShortCutString NULL \n");
1134 #endif
1135 return NULL;
1140 WORD GetShortCutPos(LPSTR str)
1142 int i;
1143 for (i = 0; i < strlen(str); i++) {
1144 if (str[i] == '\t' && str[i + 1] != '\t') {
1145 #ifdef DEBUG_MENUSHORTCUT
1146 printf("GetShortCutPos = %d \n", i);
1147 #endif
1148 return i;
1151 #ifdef DEBUG_MENUSHORTCUT
1152 printf("GetShortCutString NULL \n");
1153 #endif
1154 return -1;
1159 BOOL HideAllSubPopupMenu(LPPOPUPMENU menu)
1161 LPPOPUPMENU submenu;
1162 LPMENUITEM lpitem;
1163 BOOL someClosed = FALSE;
1164 int i;
1165 if (menu == NULL) return;
1166 lpitem = menu->firstItem;
1167 for (i = 0; i < menu->nItems; i++) {
1168 if (lpitem == NULL) return;
1169 if (lpitem->item_flags & MF_POPUP) {
1170 submenu = (LPPOPUPMENU) GlobalLock((HMENU)lpitem->item_id);
1171 if (submenu != NULL) {
1172 if (IsWindowVisible(submenu->hWnd)) {
1173 ShowWindow(submenu->hWnd, SW_HIDE);
1174 someClosed = TRUE;
1176 GlobalUnlock((HMENU)lpitem->item_id);
1179 lpitem = (LPMENUITEM)lpitem->next;
1181 return someClosed;
1187 /**********************************************************************
1188 * ChangeMenu [USER.153]
1190 BOOL ChangeMenu(HMENU hMenu, WORD nPos, LPSTR lpNewItem,
1191 WORD wItemID, WORD wFlags)
1193 if (wFlags & MF_APPEND)
1194 return AppendMenu(hMenu, wFlags, wItemID, lpNewItem);
1195 if (wFlags & MF_DELETE)
1196 return DeleteMenu(hMenu, wItemID, wFlags);
1197 if (wFlags & MF_INSERT)
1198 return InsertMenu(hMenu, nPos, wFlags, wItemID, lpNewItem);
1199 if (wFlags & MF_CHANGE)
1200 return ModifyMenu(hMenu, nPos, wFlags, wItemID, lpNewItem);
1201 if (wFlags & MF_REMOVE)
1202 return RemoveMenu(hMenu, wItemID, wFlags);
1203 return FALSE;
1207 /**********************************************************************
1208 * CheckMenuItem [USER.154]
1210 BOOL CheckMenuItem(HMENU hMenu, WORD wItemID, WORD wFlags)
1212 WND *wndPtr;
1213 LPPOPUPMENU menu;
1214 LPMENUITEM lpitem;
1215 int i;
1216 #ifdef DEBUG_MENU
1217 printf("CheckMenuItem (%04X, %04X, %04X) !\n", hMenu, wItemID, wFlags);
1218 #endif
1219 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1220 if (menu == NULL) return FALSE;
1221 lpitem = menu->firstItem;
1222 for (i = 0; i < menu->nItems; i++) {
1223 if (lpitem == NULL) break;
1224 if (i == wItemID) {
1225 if (wFlags && MF_CHECKED)
1226 lpitem->item_flags |= MF_CHECKED;
1227 else
1228 lpitem->item_flags &= ((WORD)-1 ^ MF_CHECKED);
1229 GlobalUnlock(hMenu);
1230 return(TRUE);
1232 lpitem = (LPMENUITEM)lpitem->next;
1234 GlobalUnlock(hMenu);
1235 return FALSE;
1239 /**********************************************************************
1240 * EnableMenuItem [USER.155]
1242 BOOL EnableMenuItem(HMENU hMenu, WORD wItemID, WORD wFlags)
1244 WND *wndPtr;
1245 LPPOPUPMENU menu;
1246 LPMENUITEM lpitem;
1247 int i;
1248 #ifdef DEBUG_MENU
1249 printf("EnableMenuItem (%04X, %04X, %04X) !\n", hMenu, wItemID, wFlags);
1250 #endif
1251 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1252 if (menu == NULL) return FALSE;
1253 lpitem = menu->firstItem;
1254 for (i = 0; i < menu->nItems; i++) {
1255 if (lpitem == NULL) break;
1256 if (i == wItemID) {
1257 if (wFlags && MF_DISABLED)
1258 lpitem->item_flags |= MF_DISABLED;
1259 else
1260 lpitem->item_flags &= ((WORD)-1 ^ MF_DISABLED);
1261 GlobalUnlock(hMenu);
1262 return(TRUE);
1264 lpitem = (LPMENUITEM)lpitem->next;
1266 GlobalUnlock(hMenu);
1267 return FALSE;
1271 /**********************************************************************
1272 * InsertMenu [USER.410]
1274 BOOL InsertMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
1276 WND *wndPtr;
1277 LPPOPUPMENU menu;
1278 HANDLE hNewItem;
1279 LPMENUITEM lpitem, lpitem2;
1280 int i;
1281 #ifdef DEBUG_MENU
1282 if (wFlags & MF_STRING)
1283 printf("InsertMenu (%04X, %04X, %04X, '%s') !\n",
1284 hMenu, wFlags, wItemID, lpNewItem);
1285 else
1286 printf("InsertMenu (%04X, %04X, %04X, %04X, %08X) !\n",
1287 hMenu, nPos, wFlags, wItemID, lpNewItem);
1288 #endif
1289 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1290 if (menu == NULL) return FALSE;
1291 lpitem = FindMenuItem(hMenu, nPos, wFlags);
1292 hNewItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM));
1293 if (hNewItem == 0) {
1294 GlobalUnlock(hMenu);
1295 return FALSE;
1297 lpitem2 = (LPMENUITEM)GlobalLock(hNewItem);
1298 if (lpitem2 == NULL) {
1299 GlobalFree(hNewItem);
1300 GlobalUnlock(hMenu);
1301 return FALSE;
1303 lpitem2->item_flags = wFlags;
1304 lpitem2->item_id = wItemID;
1305 if (!(wFlags & (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
1306 MF_MENUBREAK | MF_SEPARATOR))) {
1307 lpitem2->item_text = GlobalQuickAlloc(strlen(lpNewItem) + 1);
1308 strcpy(lpitem2->item_text, lpNewItem);
1309 lpitem2->sel_key = GetSelectionKey(lpitem2->item_text);
1311 else {
1312 lpitem2->item_text = lpNewItem;
1315 lpitem2->prev = lpitem;
1316 if (lpitem->next != NULL)
1317 lpitem2->next = lpitem->next;
1318 else
1319 lpitem2->next = NULL;
1320 lpitem->next = lpitem2;
1321 lpitem2->child = NULL;
1322 lpitem2->parent = NULL;
1323 menu->nItems++;
1324 GlobalUnlock(hMenu);
1325 return TRUE;
1329 /**********************************************************************
1330 * AppendMenu [USER.411]
1332 BOOL AppendMenu(HMENU hMenu, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
1334 WND *wndPtr;
1335 LPPOPUPMENU menu;
1336 HANDLE hNewItem;
1337 LPMENUITEM lpitem, lpitem2;
1338 #ifdef DEBUG_MENU
1339 if ((wFlags & (MF_BITMAP | MF_SEPARATOR | MF_MENUBREAK | MF_OWNERDRAW)) == 0)
1340 printf("AppendMenu (%04X, %04X, %04X, '%s') !\n",
1341 hMenu, wFlags, wItemID, lpNewItem);
1342 else
1343 printf("AppendMenu (%04X, %04X, %04X, %08X) !\n",
1344 hMenu, wFlags, wItemID, lpNewItem);
1345 #endif
1346 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1347 if (menu == NULL) return FALSE;
1348 lpitem = menu->firstItem;
1349 if (lpitem != NULL) {
1350 while (lpitem->next != NULL) {
1351 lpitem = (LPMENUITEM)lpitem->next;
1354 hNewItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM));
1355 if (hNewItem == 0) {
1356 GlobalUnlock(hMenu);
1357 return FALSE;
1359 lpitem2 = (LPMENUITEM)GlobalLock(hNewItem);
1360 if (lpitem2 == NULL) {
1361 GlobalFree(hNewItem);
1362 GlobalUnlock(hMenu);
1363 return FALSE;
1365 lpitem2->item_flags = wFlags;
1366 lpitem2->item_id = wItemID;
1367 if (!(wFlags & (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
1368 MF_MENUBREAK | MF_SEPARATOR))) {
1369 lpitem2->item_text = GlobalQuickAlloc(strlen(lpNewItem) + 1);
1370 strcpy(lpitem2->item_text, lpNewItem);
1371 lpitem2->sel_key = GetSelectionKey(lpitem2->item_text);
1373 else {
1374 lpitem2->item_text = lpNewItem;
1377 if (lpitem == NULL)
1378 menu->firstItem = lpitem2;
1379 else
1380 lpitem->next = lpitem2;
1381 lpitem2->prev = lpitem;
1382 lpitem2->next = NULL;
1383 lpitem2->child = NULL;
1384 lpitem2->parent = NULL;
1385 lpitem2->hCheckBit = (HBITMAP)NULL;
1386 lpitem2->hUnCheckBit = (HBITMAP)NULL;
1387 menu->nItems++;
1388 GlobalUnlock(hMenu);
1389 return TRUE;
1393 /**********************************************************************
1394 * RemoveMenu [USER.412]
1396 BOOL RemoveMenu(HMENU hMenu, WORD nPos, WORD wFlags)
1398 WND *wndPtr;
1399 LPPOPUPMENU menu;
1400 LPMENUITEM lpitem;
1401 int i;
1402 #ifdef DEBUG_MENU
1403 printf("RemoveMenu (%04X, %04X, %04X) !\n", hMenu, nPos, wFlags);
1404 #endif
1405 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1406 if (menu == NULL) return FALSE;
1407 lpitem = menu->firstItem;
1408 for (i = 0; i < menu->nItems; i++) {
1409 if (lpitem == NULL) break;
1410 if (i == nPos) {
1411 lpitem->prev->next = lpitem->next;
1412 lpitem->next->prev = lpitem->prev;
1413 if (!(lpitem->item_flags &
1414 (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
1415 MF_MENUBREAK | MF_SEPARATOR))) {
1416 GlobalFree(lpitem->item_text);
1418 GlobalFree(lpitem);
1419 GlobalUnlock(hMenu);
1420 return TRUE;
1422 lpitem = (LPMENUITEM)lpitem->next;
1423 printf("RemoveMenu // during loop items !\n");
1425 printf("RemoveMenu // after loop items !\n");
1426 GlobalUnlock(hMenu);
1427 return FALSE;
1431 /**********************************************************************
1432 * DeleteMenu [USER.413]
1434 BOOL DeleteMenu(HMENU hMenu, WORD nPos, WORD wFlags)
1436 LPPOPUPMENU menu;
1437 LPMENUITEM lpitem;
1438 int i;
1439 #ifdef DEBUG_MENU
1440 printf("DeleteMenu (%04X, %04X, %04X) !\n", hMenu, nPos, wFlags);
1441 #endif
1442 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1443 if (menu == NULL)
1445 GlobalUnlock(hMenu);
1446 return FALSE;
1449 lpitem = FindMenuItem(hMenu, nPos, wFlags);
1450 if (lpitem != NULL)
1452 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP)
1453 DestroyMenu((HMENU)lpitem->item_id);
1455 if (!(lpitem->item_flags &
1456 (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
1457 MF_MENUBREAK | MF_SEPARATOR)))
1459 GlobalFree(lpitem->item_text);
1461 if (lpitem->prev)
1462 lpitem->prev->next = lpitem->next;
1463 if (lpitem->next)
1464 lpitem->next->prev = lpitem->prev;
1465 GlobalFree(lpitem);
1466 GlobalUnlock(hMenu);
1467 return TRUE;
1470 GlobalUnlock(hMenu);
1471 return FALSE;
1475 /**********************************************************************
1476 * ModifyMenu [USER.414]
1478 BOOL ModifyMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
1480 WND *wndPtr;
1481 LPPOPUPMENU menu;
1482 LPMENUITEM lpitem;
1483 int i;
1484 #ifdef DEBUG_MENU
1485 printf("ModifyMenu (%04X, %04X, %04X, %04X, %08X) !\n",
1486 hMenu, nPos, wFlags, wItemID, lpNewItem);
1487 #endif
1488 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1489 if (menu == NULL) return FALSE;
1490 lpitem = menu->firstItem;
1491 for (i = 0; i < menu->nItems; i++) {
1492 if (lpitem == NULL) break;
1493 if (i == nPos) {
1494 lpitem->item_flags = wFlags;
1495 lpitem->item_id = wItemID;
1496 if (!(lpitem->item_flags &
1497 (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
1498 MF_MENUBREAK | MF_SEPARATOR))) {
1499 lpitem->item_text = GlobalReAlloc(lpitem->item_text,
1500 strlen(lpNewItem) + 1,
1501 GLOBAL_FLAGS_MOVEABLE);
1502 strcpy(lpitem->item_text, lpNewItem);
1504 else
1505 lpitem->item_text = lpNewItem;
1506 GlobalUnlock(hMenu);
1507 return(TRUE);
1509 lpitem = (LPMENUITEM)lpitem->next;
1511 GlobalUnlock(hMenu);
1512 return FALSE;
1516 /**********************************************************************
1517 * CreatePopupMenu [USER.415]
1519 HMENU CreatePopupMenu()
1521 HANDLE hItem;
1522 HMENU hMenu;
1523 LPPOPUPMENU menu;
1524 #ifdef DEBUG_MENU
1525 printf("CreatePopupMenu !\n");
1526 #endif
1527 hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
1528 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1529 if (menu == NULL) {
1530 GlobalFree(hMenu);
1531 return 0;
1533 menu->nItems = 0;
1534 menu->firstItem = NULL;
1535 menu->ownerWnd = 0;
1536 menu->hWndPrev = 0;
1537 menu->hWnd = 0;
1538 menu->hWndParent = 0;
1539 menu->MouseFlags = 0;
1540 menu->BarFlag = FALSE;
1541 menu->SysFlag = FALSE;
1542 menu->ChildFlag = TRUE;
1543 menu->Width = 100;
1544 menu->Height = 0;
1545 GlobalUnlock(hMenu);
1546 return hMenu;
1550 /**********************************************************************
1551 * TrackPopupMenu [USER.416]
1553 BOOL TrackPopupMenu(HMENU hMenu, WORD wFlags, short x, short y,
1554 short nReserved, HWND hWnd, LPRECT lpRect)
1556 WND *wndPtr;
1557 LPPOPUPMENU lppop;
1558 RECT rect;
1559 #ifdef DEBUG_MENU
1560 printf("TrackPopupMenu (%04X, %04X, %d, %d, %04X, %04X, %08X) !\n",
1561 hMenu, wFlags, x, y, nReserved, hWnd, lpRect);
1562 #endif
1563 lppop = (LPPOPUPMENU) GlobalLock(hMenu);
1564 if (lppop == NULL) return FALSE;
1565 wndPtr = WIN_FindWndPtr(hWnd);
1566 lppop->ownerWnd = hWnd;
1567 if (lppop->hWnd == (HWND)NULL) {
1568 lppop->hWnd = CreateWindow("POPUPMENU", "", WS_POPUP | WS_VISIBLE,
1569 x, y, lppop->Width, lppop->Height, (HWND)NULL, 0,
1570 wndPtr->hInstance, (LPSTR)lppop);
1572 else {
1573 ShowWindow(lppop->hWnd, SW_SHOW);
1575 if (!lppop->BarFlag) {
1576 PopupMenuCalcSize(lppop->hWnd);
1577 #ifdef DEBUG_MENU
1578 printf("TrackPopupMenu // x=%d y=%d Width=%d Height=%d\n",
1579 x, y, lppop->Width, lppop->Height);
1580 #endif
1581 SetWindowPos(lppop->hWnd, 0, x, y, lppop->Width + 2, lppop->Height,
1582 SWP_NOZORDER);
1584 if (!MenuHasFocus) {
1585 #ifdef DEBUG_MENU
1586 printf("TrackPopupMenu // before MenuFocusLoop !\n");
1587 #endif
1588 MenuFocusLoop(hWnd, NULL);
1589 /* ActivateMenuFocus(hWnd); */
1590 #ifdef DEBUG_MENU
1591 printf("TrackPopupMenu // after MenuFocusLoop !\n");
1592 #endif
1594 GlobalUnlock(hMenu);
1595 return TRUE;
1599 BOOL ActivateMenuFocus(HWND hWnd)
1601 WND *wndPtr;
1602 LPPOPUPMENU lpmenu;
1603 BOOL bRet;
1604 MSG msg;
1605 if (MenuHasFocus) return FALSE;
1606 wndPtr = WIN_FindWndPtr(hWnd);
1607 if (wndPtr == NULL) return FALSE;
1608 #ifdef DEBUG_MENU
1609 printf("ActivateMenuFocus (%04X) !\n", hWnd);
1610 #endif
1611 if ((wndPtr->dwStyle & WS_CHILD) == 0 && wndPtr->wIDmenu != 0) {
1612 lpmenu = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu);
1613 MenuItemSelect(hWnd, lpmenu, 0);
1614 bRet = MenuFocusLoop(hWnd, lpmenu);
1615 if (lpmenu != NULL) GlobalUnlock(wndPtr->wIDmenu);
1616 return bRet;
1618 return FALSE;
1622 BOOL MenuFocusLoop(HWND hWnd, LPPOPUPMENU lpmenu)
1624 WND *wndPtr;
1625 MSG msg;
1626 #ifdef DEBUG_MENU
1627 printf("Enter in Menu Focus Loop !\n");
1628 #endif
1629 MenuHasFocus = TRUE;
1630 while(TRUE) {
1631 if (!MenuHasFocus) break;
1632 if (!GetMessage(&msg, (HWND)NULL, 0, 0)) break;
1633 TranslateMessage(&msg);
1634 if (hWnd == msg.hwnd && lpmenu != NULL) {
1635 if ((msg.message == WM_SYSKEYDOWN && msg.wParam == VK_MENU) ||
1636 (msg.message == WM_CHAR && msg.wParam == VK_ESCAPE)) {
1637 HideAllSubPopupMenu(lpmenu);
1638 break;
1640 switch(msg.message) {
1641 case WM_KEYDOWN:
1642 case WM_KEYUP:
1643 case WM_CHAR:
1644 case WM_LBUTTONDOWN:
1645 case WM_LBUTTONUP:
1646 case WM_MOUSEMOVE:
1647 PopupMenuWndProc(hWnd, msg.message, msg.wParam, msg.lParam);
1648 default:
1649 DispatchMessage(&msg);
1652 else
1653 DispatchMessage(&msg);
1655 EndOfFocus:
1656 MenuHasFocus = FALSE;
1657 if (lpmenu != NULL) MenuItemSelect(hWnd, lpmenu, -1);
1658 #ifdef DEBUG_MENU
1659 printf("End of Menu Focus Loop !\n");
1660 #endif
1661 return TRUE;
1665 /**********************************************************************
1666 * NC_TrackSysMenu [Internal]
1668 void NC_TrackSysMenu(HWND hWnd)
1670 RECT rect;
1671 LPPOPUPMENU lpsys;
1672 WND *wndPtr = WIN_FindWndPtr(hWnd);
1673 #ifdef DEBUG_MENU
1674 printf("NC_TrackSysMenu hWnd=%04X !\n", hWnd);
1675 #endif
1676 if (!wndPtr) return;
1677 lpsys = (LPPOPUPMENU)GlobalLock(wndPtr->hSysMenu);
1678 #ifdef DEBUG_MENU
1679 printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu);
1680 #endif
1681 if (lpsys == NULL) return;
1682 #ifdef DEBUG_MENU
1683 printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu);
1684 #endif
1685 lpsys->BarFlag = FALSE;
1686 lpsys->SysFlag = TRUE;
1687 lpsys->ChildFlag = FALSE;
1688 lpsys->hWndParent = hWnd;
1689 if (!IsWindowVisible(lpsys->hWnd)) {
1690 GetWindowRect(hWnd, &rect);
1691 lpsys->hWndPrev = GetFocus();
1692 #ifdef DEBUG_MENU
1693 printf("NC_TrackSysMenu lpsys->hWnd=%04X !\n", lpsys->hWnd);
1694 #endif
1695 if (MenuHasFocus) {
1696 TrackPopupMenu(wndPtr->hSysMenu, TPM_LEFTBUTTON,
1697 rect.left, rect.top + SYSMETRICS_CYSIZE,
1698 0, hWnd, (LPRECT)NULL);
1700 else {
1701 MenuHasFocus = TRUE;
1702 TrackPopupMenu(wndPtr->hSysMenu, TPM_LEFTBUTTON,
1703 rect.left, rect.top + SYSMETRICS_CYSIZE,
1704 0, hWnd, (LPRECT)NULL);
1705 MenuHasFocus = FALSE;
1706 #ifdef DEBUG_MENU
1707 printf("NC_TrackSysMenu // before MenuFocusLoop !\n");
1708 #endif
1709 MenuFocusLoop(hWnd, NULL);
1710 /* ActivateMenuFocus(hWnd); */
1711 #ifdef DEBUG_MENU
1712 printf("NC_TrackSysMenu // after MenuFocusLoop !\n");
1713 #endif
1716 else {
1717 ShowWindow(lpsys->hWnd, SW_HIDE);
1719 GlobalUnlock(wndPtr->hSysMenu);
1723 /**********************************************************************
1724 * GetMenuCheckMarkDimensions [USER.417]
1726 DWORD GetMenuCheckMarkDimensions()
1728 BITMAP bm;
1729 if (hStdCheck == (HBITMAP)NULL)
1730 hStdCheck = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_CHECK);
1731 GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
1732 return MAKELONG(bm.bmWidth, bm.bmHeight);
1736 /**********************************************************************
1737 * SetMenuItemBitmaps [USER.418]
1739 BOOL SetMenuItemBitmaps(HMENU hMenu, WORD nPos, WORD wFlags,
1740 HBITMAP hNewCheck, HBITMAP hNewUnCheck)
1742 WND *wndPtr;
1743 LPPOPUPMENU menu;
1744 LPMENUITEM lpitem;
1745 int i;
1746 #ifdef DEBUG_MENU
1747 printf("SetMenuItemBitmaps (%04X, %04X, %04X, %04X, %08X) !\n",
1748 hMenu, nPos, wFlags, hNewCheck, hNewUnCheck);
1749 #endif
1750 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1751 if (menu == NULL) return FALSE;
1752 lpitem = menu->firstItem;
1753 for (i = 0; i < menu->nItems; i++) {
1754 if (lpitem == NULL) break;
1755 if (i == nPos) {
1756 lpitem->hCheckBit = hNewCheck;
1757 lpitem->hUnCheckBit = hNewUnCheck;
1758 GlobalUnlock(hMenu);
1759 return TRUE;
1761 lpitem = (LPMENUITEM)lpitem->next;
1763 GlobalUnlock(hMenu);
1764 return FALSE;
1768 /**********************************************************************
1769 * CreateMenu [USER.151]
1771 HMENU CreateMenu()
1773 HANDLE hItem;
1774 HMENU hMenu;
1775 LPPOPUPMENU menu;
1776 #ifdef DEBUG_MENU
1777 printf("CreatePopupMenu !\n");
1778 #endif
1779 hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
1780 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1781 if (menu == NULL) {
1782 GlobalFree(hMenu);
1783 return 0;
1785 menu->nItems = 0;
1786 menu->firstItem = NULL;
1787 menu->hWndPrev = 0;
1788 menu->ownerWnd = 0;
1789 menu->hWnd = 0;
1790 menu->hWndParent = 0;
1791 menu->MouseFlags = 0;
1792 menu->BarFlag = TRUE;
1793 menu->SysFlag = FALSE;
1794 menu->ChildFlag = TRUE;
1795 menu->Width = 100;
1796 menu->Height = 0;
1797 GlobalUnlock(hMenu);
1798 return hMenu;
1802 /**********************************************************************
1803 * DestroyMenu [USER.152]
1805 BOOL DestroyMenu(HMENU hMenu)
1807 LPPOPUPMENU lppop;
1808 LPMENUITEM lpitem, lpitem2;
1809 #ifdef DEBUG_MENU
1810 printf("DestroyMenu (%04X) !\n", hMenu);
1811 #endif
1812 if (hMenu == 0) return FALSE;
1813 lppop = (LPPOPUPMENU) GlobalLock(hMenu);
1814 if (lppop == NULL) return FALSE;
1815 if (lppop->hWnd) DestroyWindow (lppop->hWnd);
1816 lpitem = lppop->firstItem;
1817 while (lpitem != NULL) {
1818 #ifdef DEBUG_MENU
1819 printf("DestroyMenu (%04X) // during loop items !\n", hMenu);
1820 #endif
1821 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
1822 DestroyMenu((HMENU)lpitem->item_id);
1824 lpitem = (LPMENUITEM)lpitem->next;
1826 GlobalUnlock(hMenu);
1827 GlobalFree(hMenu);
1828 #ifdef DEBUG_MENU
1829 printf("DestroyMenu (%04X) // End !\n", hMenu);
1830 #endif
1831 return TRUE;
1835 /**********************************************************************
1836 * LoadMenu [USER.150]
1838 HMENU LoadMenu(HINSTANCE instance, char *menu_name)
1840 HMENU hMenu;
1841 HANDLE hMenu_desc;
1842 MENU_HEADER *menu_desc;
1843 #ifdef DEBUG_MENU
1844 if ((LONG)menu_name & 0xFFFF0000L)
1845 printf("LoadMenu: instance %02x, menu '%s'\n", instance, menu_name);
1846 else
1847 printf("LoadMenu: instance %02x, menu '%04X'\n", instance, menu_name);
1848 #endif
1849 if (instance == (HANDLE)NULL) instance = hSysRes;
1850 if (menu_name == NULL ||
1851 (hMenu_desc = RSC_LoadMenu(instance, menu_name)) == 0 ||
1852 (menu_desc = (MENU_HEADER *) GlobalLock(hMenu_desc)) == NULL) {
1853 return 0;
1855 hMenu = LoadMenuIndirect((LPSTR)menu_desc);
1856 return hMenu;
1860 /**********************************************************************
1861 * GetSystemMenu [USER.156]
1863 HMENU GetSystemMenu(HWND hWnd, BOOL bRevert)
1865 WND *wndPtr;
1866 wndPtr = WIN_FindWndPtr(hWnd);
1867 if (!bRevert) {
1868 return wndPtr->hSysMenu;
1870 else {
1871 DestroyMenu(wndPtr->hSysMenu);
1872 wndPtr->hSysMenu = CopySysMenu();
1874 return wndPtr->hSysMenu;
1878 /**********************************************************************
1879 * GetMenu [USER.157]
1881 HMENU GetMenu(HWND hWnd)
1883 WND * wndPtr = WIN_FindWndPtr(hWnd);
1884 if (wndPtr == NULL) return 0;
1885 return wndPtr->wIDmenu;
1888 /**********************************************************************
1889 * SetMenu [USER.158]
1891 BOOL SetMenu(HWND hWnd, HMENU hMenu)
1893 LPPOPUPMENU lppop;
1894 WND * wndPtr = WIN_FindWndPtr(hWnd);
1895 if (wndPtr == NULL) return FALSE;
1896 #ifdef DEBUG_MENU
1897 printf("SetMenu(%04X, %04X);\n", hWnd, hMenu);
1898 #endif
1899 wndPtr->wIDmenu = hMenu;
1900 if (hMenu == 0) return TRUE;
1901 lppop = (LPPOPUPMENU) GlobalLock(hMenu);
1902 if (lppop == NULL) return FALSE;
1903 lppop->ownerWnd = hWnd;
1904 ResetHiliteFlags(lppop);
1905 GlobalUnlock(hMenu);
1906 return TRUE;
1910 /**********************************************************************
1911 * GetSubMenu [USER.159]
1913 HMENU GetSubMenu(HMENU hMenu, short nPos)
1915 HMENU hSubMenu;
1916 LPPOPUPMENU lppop;
1917 LPMENUITEM lpitem;
1918 int i;
1919 #ifdef DEBUG_MENU
1920 printf("GetSubMenu (%04X, %04X) !\n", hMenu, nPos);
1921 #endif
1922 if (hMenu == 0) return 0;
1923 lppop = (LPPOPUPMENU) GlobalLock(hMenu);
1924 if (lppop == NULL) return 0;
1925 lpitem = lppop->firstItem;
1926 for (i = 0; i < lppop->nItems; i++) {
1927 if (lpitem == NULL) break;
1928 if (i == nPos) {
1929 #ifdef DEBUG_MENU
1930 printf(" found %04x\n", lpitem->item_id);
1931 #endif
1932 if (lpitem->item_flags & MF_POPUP)
1933 return lpitem->item_id;
1934 else
1935 return 0;
1937 lpitem = (LPMENUITEM)lpitem->next;
1939 return 0;
1943 /**********************************************************************
1944 * DrawMenuBar [USER.160]
1946 void DrawMenuBar(HWND hWnd)
1948 WND *wndPtr;
1949 LPPOPUPMENU lppop;
1950 HDC hDC;
1951 #ifdef DEBUG_MENU
1952 printf("DrawMenuBar (%04X)\n", hWnd);
1953 #endif
1954 wndPtr = WIN_FindWndPtr(hWnd);
1955 if (wndPtr != NULL && (wndPtr->dwStyle & WS_CHILD) == 0 &&
1956 wndPtr->wIDmenu != 0) {
1957 #ifdef DEBUG_MENU
1958 printf("DrawMenuBar wIDmenu=%04X \n", wndPtr->wIDmenu);
1959 #endif
1960 lppop = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu);
1961 if (lppop == NULL) return;
1962 if ((lppop->rect.bottom - lppop->rect.top) != 0) {
1963 hDC = GetWindowDC(hWnd);
1964 StdDrawMenuBar(hDC, &lppop->rect, lppop);
1965 ReleaseDC(hWnd, hDC);
1967 else
1968 SendMessage(hWnd, WM_NCPAINT, 1, 0L);
1969 GlobalUnlock(wndPtr->wIDmenu);
1974 /**********************************************************************
1975 * LoadMenuIndirect [USER.220]
1977 HMENU LoadMenuIndirect(LPSTR menu_template)
1979 HMENU hMenu;
1980 MENU_HEADER *menu_desc;
1981 LPPOPUPMENU lppop;
1982 #ifdef DEBUG_MENU
1983 printf("LoadMenuIndirect: menu_template '%08X'\n", menu_template);
1984 #endif
1985 hMenu = CreateMenu();
1986 menu_desc = (MENU_HEADER *)menu_template;
1987 ParseMenuResource((WORD *)(menu_desc + 1), 0, hMenu);
1988 lppop = (LPPOPUPMENU) GlobalLock(hMenu);
1989 ResetHiliteFlags(lppop);
1990 GlobalUnlock(hMenu);
1991 return hMenu;
1995 /**********************************************************************
1996 * CopySysMenu (Internal)
1998 HMENU CopySysMenu()
2000 HMENU hMenu;
2001 LPPOPUPMENU menu;
2002 LPPOPUPMENU sysmenu;
2003 #ifdef DEBUG_MENU
2004 printf("CopySysMenu entry !\n");
2005 #endif
2006 if (hSysMenu == 0) {
2007 hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(1));
2008 /* hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(SC_SYSMENU));*/
2009 /* hSysMenu = LoadMenu((HINSTANCE)NULL, "SYSMENU"); */
2010 if (hSysMenu == 0) {
2011 printf("SysMenu not found in system resources !\n");
2012 return (HMENU)NULL;
2014 #ifdef DEBUG_MENU
2015 else
2016 printf("SysMenu loaded from system resources %04X !\n", hSysMenu);
2017 #endif
2019 hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
2020 menu = (LPPOPUPMENU) GlobalLock(hMenu);
2021 sysmenu = (LPPOPUPMENU) GlobalLock(hSysMenu);
2022 if (menu != NULL && sysmenu != NULL) {
2023 sysmenu->BarFlag = FALSE;
2024 sysmenu->SysFlag = TRUE;
2025 memcpy(menu, sysmenu, sizeof(POPUPMENU));
2027 else {
2028 printf("CopySysMenu // Bad SysMenu pointers !\n");
2029 if (menu != NULL) {
2030 GlobalUnlock(hMenu);
2031 GlobalFree(hMenu);
2033 return (HMENU)NULL;
2035 GlobalUnlock(hMenu);
2036 GlobalUnlock(hSysMenu);
2037 #ifdef DEBUG_MENU
2038 printf("CopySysMenu hMenu=%04X !\n", hMenu);
2039 #endif
2040 return hMenu;
2044 /**********************************************************************
2045 * ParseMenuResource (from Resource or Template)
2047 WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu)
2049 WORD *item;
2050 WORD *next_item;
2051 HMENU hSubMenu;
2052 int i;
2054 level++;
2055 next_item = first_item;
2056 i = 0;
2057 do {
2058 i++;
2059 item = next_item;
2060 if (*item & MF_POPUP) {
2061 MENU_POPUPITEM *popup_item = (MENU_POPUPITEM *) item;
2062 next_item = (WORD *) (popup_item->item_text +
2063 strlen(popup_item->item_text) + 1);
2064 hSubMenu = CreatePopupMenu();
2065 next_item = ParseMenuResource(next_item, level, hSubMenu);
2066 AppendMenu(hMenu, popup_item->item_flags,
2067 hSubMenu, popup_item->item_text);
2069 else {
2070 MENUITEMTEMPLATE *normal_item = (MENUITEMTEMPLATE *) item;
2071 next_item = (WORD *) (normal_item->item_text +
2072 strlen(normal_item->item_text) + 1);
2073 if (strlen(normal_item->item_text) == 0 && normal_item->item_id == 0)
2074 normal_item->item_flags |= MF_SEPARATOR;
2075 AppendMenu(hMenu, normal_item->item_flags,
2076 normal_item->item_id, normal_item->item_text);
2079 while (!(*item & MF_END));
2080 return next_item;