Release 940804
[wine/gsoc-2012-control.git] / controls / menu.c
blob18ca83298fbee1bc8cfc9f5f3e7d046bba257401
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 "syscolor.h"
15 #include "sysmetrics.h"
16 #include "prototypes.h"
17 #include "menu.h"
18 #include "user.h"
19 #include "heap.h"
20 #include "win.h"
22 #define SC_ABOUTWINE SC_SCREENSAVE+1
23 #define SC_SYSMENU SC_SCREENSAVE+2
24 #define SC_ABOUTWINEDLG SC_SCREENSAVE+3
26 /* Dimension of the menu bitmaps */
27 static WORD check_bitmap_width = 0, check_bitmap_height = 0;
28 static WORD arrow_bitmap_width = 0, arrow_bitmap_height = 0;
30 /* Space between 2 menu bar items */
31 #define MENU_BAR_ITEMS_SPACE 16
33 /* Height of a separator item */
34 #define SEPARATOR_HEIGHT 5
36 extern HINSTANCE hSysRes;
37 HMENU hSysMenu = 0;
38 HBITMAP hStdCheck = 0;
39 HBITMAP hStdMnArrow = 0;
40 static BOOL MenuHasFocus = FALSE;
42 LPPOPUPMENU PopupMenuGetStorageHeader(HWND hwnd);
43 LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr);
44 void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop,
45 BOOL suppress_draw);
46 BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
47 void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
48 void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y);
49 void StdDrawPopupMenu(HWND hwnd);
50 void ResetHiliteFlags(LPPOPUPMENU lppop);
51 void SelectPrevItem(LPPOPUPMENU lppop);
52 void SelectNextItem(LPPOPUPMENU lppop);
53 BOOL ExecFocusedMenuItem(HWND hWnd, LPPOPUPMENU lppop);
54 void MenuItemSelect(HWND hWnd, LPPOPUPMENU lppop, WORD wIndex);
55 LPMENUITEM MenuFindItem(LPPOPUPMENU lppop, int x, int y, WORD *lpRet);
56 LPMENUITEM MenuFindItemBySelKey(LPPOPUPMENU lppop, WORD key, WORD *lpRet);
57 BOOL ActivateMenuBarFocus(HWND hWnd);
58 BOOL MenuFocusLoop(HWND hWnd, LPPOPUPMENU lpmenu);
59 LPMENUITEM FindMenuItem(HMENU hMenu, WORD nPos, WORD wFlags);
60 LPMENUITEM GetMenuItemPtr(LPPOPUPMENU menu, WORD nPos);
61 WORD GetSelectionKey(LPSTR str);
62 LPSTR GetShortCutString(LPSTR str);
63 int GetShortCutPos(LPSTR str);
64 BOOL HideAllSubPopupMenu(LPPOPUPMENU menu);
65 void InitStdBitmaps();
66 HMENU CopySysMenu();
67 WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu);
68 void SetMenuLogicalParent(HMENU hMenu, HWND hWnd);
70 BOOL FAR PASCAL AboutWine_Proc(HWND hDlg, WORD msg, WORD wParam, LONG lParam);
73 /***********************************************************************
74 * MENU_CalcItemSize
76 * Calculate the size of the menu item and store it in lpitem->rect.
78 static void MENU_CalcItemSize( HDC hdc, LPMENUITEM lpitem,
79 int orgX, int orgY, BOOL menuBar )
81 DWORD dwSize;
82 SetRect( &lpitem->rect, orgX, orgY, orgX, orgY );
84 if (lpitem->item_flags & MF_SEPARATOR)
86 lpitem->rect.bottom += SEPARATOR_HEIGHT;
87 return;
90 if (!menuBar) lpitem->rect.right += check_bitmap_width+arrow_bitmap_width;
92 if (lpitem->item_flags & MF_BITMAP)
94 BITMAP bm;
95 HBITMAP hbitmap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
96 GetObject(hbitmap, sizeof(BITMAP), (LPSTR)&bm);
97 lpitem->rect.right += bm.bmWidth;
98 lpitem->rect.bottom += bm.bmHeight;
99 return;
102 /* If we get here, then it is a text item */
104 if (menuBar) lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
105 dwSize = GetTextExtent( hdc, lpitem->item_text, strlen(lpitem->item_text));
106 lpitem->rect.right += LOWORD(dwSize);
107 lpitem->rect.bottom += max( HIWORD(dwSize), SYSMETRICS_CYMENU );
111 /***********************************************************************
112 * MENU_PopupMenuCalcSize
114 * Calculate the size of a popup menu.
116 static void MENU_PopupMenuCalcSize( HWND hwnd )
118 LPPOPUPMENU lppop;
119 LPMENUITEM lpitem, lpitemStart, lptmp;
120 WND *wndPtr;
121 HDC hdc;
122 int orgX, orgY, maxX;
124 if (!(lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr))) return;
125 SetRect( &lppop->rect, 0, 0, 0, 0 );
126 lppop->Width = lppop->Height = 0;
127 if (lppop->nItems == 0) return;
128 hdc = GetDC( hwnd );
129 maxX = 0;
130 lpitemStart = lppop->firstItem;
131 while (lpitemStart != NULL)
133 orgX = maxX;
134 orgY = 0;
136 /* Parse items until column break or end of menu */
137 for (lpitem = lpitemStart; lpitem != NULL; lpitem = lpitem->next)
139 if ((lpitem != lpitemStart) &&
140 (lpitem->item_flags & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
141 MENU_CalcItemSize( hdc, lpitem, orgX, orgY, FALSE );
142 maxX = max( maxX, lpitem->rect.right );
143 orgY = lpitem->rect.bottom;
146 /* Finish the column (set all items to the largest width found) */
147 for (lptmp = lpitemStart; lptmp != lpitem; lptmp = lptmp->next)
149 lptmp->rect.right = maxX;
152 /* And go to the next column */
153 lppop->Height = max( lppop->Height, orgY );
154 lpitemStart = lpitem;
157 lppop->Width = maxX;
158 SetRect( &lppop->rect, 0, 0, lppop->Width, lppop->Height );
159 ReleaseDC( hwnd, hdc );
163 /***********************************************************************
164 * MENU_MenuBarCalcSize
166 * Calculate the size of the menu bar.
168 static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect, LPPOPUPMENU lppop )
170 LPMENUITEM lpitem, lpitemStart, lptmp;
171 int orgX, orgY, maxY;
173 if ((lprect == NULL) || (lppop == NULL)) return;
174 if (lppop->nItems == 0) return;
175 #ifdef DEBUG_MENUCALC
176 printf("MenuBarCalcSize left=%d top=%d right=%d bottom=%d !\n",
177 lprect->left, lprect->top, lprect->right, lprect->bottom);
178 #endif
179 lppop->Width = lprect->right - lprect->left;
180 lppop->Height = 0;
181 maxY = lprect->top;
183 lpitemStart = lppop->firstItem;
184 while (lpitemStart != NULL)
186 orgX = lprect->left;
187 orgY = maxY;
189 /* Parse items until line break or end of menu */
190 for (lpitem = lpitemStart; lpitem != NULL; lpitem = lpitem->next)
192 if ((lpitem != lpitemStart) &&
193 (lpitem->item_flags & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
194 MENU_CalcItemSize( hdc, lpitem, orgX, orgY, TRUE );
195 if (lpitem->rect.right > lprect->right)
197 if (lpitem != lpitemStart) break;
198 else lpitem->rect.right = lprect->right;
200 maxY = max( maxY, lpitem->rect.bottom );
201 orgX = lpitem->rect.right;
204 /* Finish the line (set all items to the largest height found) */
205 for (lptmp = lpitemStart; lptmp != lpitem; lptmp = lptmp->next)
207 lptmp->rect.bottom = maxY;
210 /* And go to the next line */
211 lpitemStart = lpitem;
214 lprect->bottom = maxY;
215 lppop->Height = lprect->bottom - lprect->top;
216 CopyRect( &lppop->rect, lprect );
220 /***********************************************************************
221 * MENU_DrawMenuItem
223 * Draw a single menu item.
225 static void MENU_DrawMenuItem( HDC hdc, LPMENUITEM lpitem,
226 LPRECT menuRect, BOOL menuBar )
228 RECT rect;
230 if (menuBar && (lpitem->item_flags & MF_SEPARATOR)) return;
231 rect = lpitem->rect;
233 /* Draw the background */
235 if (lpitem->item_flags & MF_HILITE)
236 FillRect( hdc, &rect, sysColorObjects.hbrushHighlight );
237 else FillRect( hdc, &rect, sysColorObjects.hbrushMenu );
238 SetBkMode( hdc, TRANSPARENT );
240 /* Draw the separator bar (if any) */
242 if (!menuBar && (lpitem->item_flags & MF_MENUBARBREAK))
244 SelectObject( hdc, sysColorObjects.hpenWindowFrame );
245 MoveTo( hdc, rect.left, menuRect->top );
246 LineTo( hdc, rect.left, menuRect->bottom );
248 if (lpitem->item_flags & MF_SEPARATOR)
250 SelectObject( hdc, sysColorObjects.hpenWindowFrame );
251 MoveTo( hdc, rect.left, rect.top + SEPARATOR_HEIGHT/2 );
252 LineTo( hdc, rect.right, rect.top + SEPARATOR_HEIGHT/2 );
255 if (!menuBar)
257 /* Draw the check mark */
259 if (lpitem->item_flags & MF_CHECKED)
261 HDC hMemDC = CreateCompatibleDC( hdc );
262 if (lpitem->hCheckBit == 0) SelectObject(hMemDC, hStdCheck);
263 else SelectObject(hMemDC, lpitem->hCheckBit);
264 BitBlt( hdc, rect.left,
265 (rect.top + rect.bottom - check_bitmap_height) / 2,
266 check_bitmap_width, check_bitmap_height,
267 hMemDC, 0, 0, SRCCOPY );
268 DeleteDC( hMemDC );
270 else /* Not checked */
272 if (lpitem->hUnCheckBit != 0)
274 HDC hMemDC = CreateCompatibleDC( hdc );
275 SelectObject(hMemDC, lpitem->hUnCheckBit);
276 BitBlt( hdc, rect.left,
277 (rect.top + rect.bottom - check_bitmap_height) / 2,
278 check_bitmap_width, check_bitmap_height,
279 hMemDC, 0, 0, SRCCOPY );
280 DeleteDC( hMemDC );
284 /* Draw the popup-menu arrow */
286 if (lpitem->item_flags & MF_POPUP)
288 HDC hMemDC = CreateCompatibleDC( hdc );
289 SelectObject(hMemDC, hStdMnArrow);
290 BitBlt( hdc, rect.right-arrow_bitmap_width,
291 (rect.top + rect.bottom - arrow_bitmap_height) / 2,
292 arrow_bitmap_width, arrow_bitmap_height,
293 hMemDC, 0, 0, SRCCOPY );
294 DeleteDC(hMemDC);
297 rect.left += check_bitmap_width;
298 rect.right -= arrow_bitmap_width;
301 /* Setup colors */
303 if (lpitem->item_flags & MF_HILITE)
305 SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
306 SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) );
308 else
310 if (lpitem->item_flags & MF_GRAYED)
311 SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
312 else
313 SetTextColor( hdc, GetSysColor( COLOR_MENUTEXT ) );
314 SetBkColor( hdc, GetSysColor( COLOR_MENU ) );
317 /* Draw the item text or bitmap */
319 if (lpitem->item_flags & MF_BITMAP)
321 HBITMAP hbitmap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
322 HDC hMemDC = CreateCompatibleDC( hdc );
323 SelectObject( hMemDC, hbitmap );
324 BitBlt( hdc, rect.left, rect.top,
325 rect.right-rect.left, rect.bottom-rect.top,
326 hMemDC, 0, 0, SRCCOPY );
327 DeleteDC( hMemDC );
328 return;
330 else /* No bitmap */
332 int x = GetShortCutPos(lpitem->item_text);
333 if (menuBar)
335 rect.left += MENU_BAR_ITEMS_SPACE / 2;
336 rect.right -= MENU_BAR_ITEMS_SPACE / 2;
338 if (x != -1)
340 DrawText( hdc, lpitem->item_text, x, &rect,
341 DT_LEFT | DT_VCENTER | DT_SINGLELINE );
342 DrawText( hdc, lpitem->item_text + x, -1, &rect,
343 DT_RIGHT | DT_VCENTER | DT_SINGLELINE );
345 else DrawText( hdc, lpitem->item_text, -1, &rect,
346 DT_LEFT | DT_VCENTER | DT_SINGLELINE );
351 /***********************************************************************
352 * PopupMenuWndProc
354 LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
356 CREATESTRUCT *createStruct;
357 WORD wRet;
358 short x, y;
359 WND *wndPtr;
360 LPPOPUPMENU lppop, lppop2;
361 LPMENUITEM lpitem, lpitem2;
362 HMENU hSubMenu;
363 RECT rect;
364 HDC hDC;
365 PAINTSTRUCT ps;
366 switch(message) {
367 case WM_CREATE:
368 #ifdef DEBUG_MENU
369 printf("PopupMenu WM_CREATE lParam=%08X !\n", lParam);
370 #endif
371 createStruct = (CREATESTRUCT *)lParam;
372 lppop = (LPPOPUPMENU)createStruct->lpCreateParams;
373 if (lppop == NULL) break;
374 wndPtr = WIN_FindWndPtr(hwnd);
375 *((LPPOPUPMENU *)&wndPtr->wExtra[1]) = lppop;
376 #ifdef DEBUG_MENU
377 printf("PopupMenu WM_CREATE lppop=%08X !\n", lppop);
378 #endif
379 InitStdBitmaps();
380 #ifdef DEBUG_MENU
381 printf("PopupMenu End of WM_CREATE !\n");
382 #endif
383 ResetHiliteFlags(lppop);
384 return 0;
385 case WM_DESTROY:
386 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
387 #ifdef DEBUG_MENU
388 printf("PopupMenu WM_DESTROY %lX !\n", lppop);
389 #endif
390 return 0;
391 case WM_COMMAND:
392 #ifdef DEBUG_MENU
393 printf("PopupMenuWndProc // WM_COMMAND received !\n");
394 #endif
395 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
396 if (lppop == NULL) break;
397 if (lppop->SysFlag) {
398 MenuHasFocus = FALSE;
399 if (wParam == SC_ABOUTWINE) {
400 printf("SysMenu // Show 'About Wine ...' !\n");
401 /* DialogBox(hSysRes, MAKEINTRESOURCE(SC_ABOUTWINEDLG), */
402 DialogBox(hSysRes, MAKEINTRESOURCE(2),
403 GetParent(hwnd), (FARPROC)AboutWine_Proc);
405 else {
406 #ifdef DEBUG_MENU
407 printf("PopupMenuWndProc // push to Owner WM_SYSCOMMAND !\n");
408 #endif
409 PostMessage(lppop->ownerWnd, WM_SYSCOMMAND, wParam, lParam);
411 break;
413 #ifdef DEBUG_MENU
414 printf("PopupMenuWndProc // push to Owner WM_COMMAND !\n");
415 #endif
416 MenuHasFocus = FALSE;
417 PostMessage(lppop->hWndParent, WM_COMMAND, wParam, lParam);
418 break;
419 case WM_SHOWWINDOW:
420 #ifdef DEBUG_MENU
421 printf("PopupMenuWndProc // WM_SHOWWINDOW received !\n");
422 #endif
423 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
424 if (lppop == NULL) break;
425 if (wParam == 0 && lParam == 0L) {
426 ResetHiliteFlags(lppop);
427 HideAllSubPopupMenu(lppop);
428 #ifdef DEBUG_MENU
429 printf("PopupMenuWndProc hWnd=%04X WM_SHOWWINDOW -> HIDE!\n", hwnd);
430 #endif
431 if (lppop->SysFlag) MenuHasFocus = FALSE;
432 SetFocus(lppop->hWndPrev);
433 if (GetCapture() != 0) ReleaseCapture();
434 break;
436 lppop->FocusedItem = (WORD)-1;
437 break;
438 case WM_LBUTTONDOWN:
439 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
440 if (lppop == NULL) break;
441 SetCapture(hwnd);
442 MenuButtonDown(hwnd, lppop, LOWORD(lParam), HIWORD(lParam));
443 break;
444 case WM_LBUTTONUP:
445 lppop = PopupMenuGetStorageHeader(hwnd);
446 if (lppop == NULL) break;
447 ReleaseCapture();
448 MenuButtonUp(hwnd, lppop, LOWORD(lParam), HIWORD(lParam));
449 break;
450 case WM_MOUSEMOVE:
451 lppop = PopupMenuGetStorageHeader(hwnd);
452 if (lppop == NULL) break;
453 MenuMouseMove(hwnd, lppop, wParam, LOWORD(lParam), HIWORD(lParam));
454 break;
456 case WM_KEYUP:
457 #ifdef DEBUG_MENU
458 printf("PopupMenuWndProc hWnd=%04X WM_KEYUP w=%04X l=%08X !\n",
459 hwnd, wParam, lParam);
460 #endif
461 break;
462 case WM_KEYDOWN:
463 #ifdef DEBUG_MENU
464 printf("PopupMenuWndProc hWnd=%04X WM_KEYDOWN w=%04X l=%08X !\n",
465 hwnd, wParam, lParam);
466 #endif
467 if (lParam < 0L) break;
468 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
469 if (lppop == NULL) break;
470 switch(wParam) {
471 case VK_HOME:
472 if (lppop->FocusedItem == 0) break;
473 MenuItemSelect(hwnd, lppop, 0);
474 break;
475 case VK_UP:
476 if (lppop->BarFlag) break;
477 SelectPrevItem(lppop);
478 break;
479 case VK_DOWN:
480 if (lppop->BarFlag) goto ProceedSPACE;
481 SelectNextItem(lppop);
482 break;
483 case VK_LEFT:
484 if (lppop->SysFlag != 0) {
485 ShowWindow(hwnd, SW_HIDE);
486 hwnd = lppop->hWndParent;
487 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
488 printf("VK_LEFT // try to put focus on MenuBar %08X !\n", lppop);
489 if (lppop == NULL) break;
490 MenuItemSelect(hwnd, lppop, lppop->nItems - 1);
491 break;
493 if (lppop->BarFlag) {
494 if (lppop->FocusedItem < 1) {
495 MenuItemSelect(hwnd, lppop, -1);
496 NC_TrackSysMenu(hwnd);
497 break;
499 if (HideAllSubPopupMenu(lppop)) {
500 MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
501 goto ProceedSPACE;
504 if (lppop->hWndParent != 0) {
505 PostMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam);
506 break;
508 MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
509 break;
510 case VK_RIGHT:
511 if (lppop->SysFlag != 0) {
512 ShowWindow(hwnd, SW_HIDE);
513 hwnd = lppop->hWndParent;
514 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
515 printf("VK_RIGHT // try to put focus on MenuBar %08X !\n", lppop);
516 if (lppop == NULL) break;
517 MenuItemSelect(hwnd, lppop, 0);
518 break;
520 if (lppop->BarFlag) {
521 if (lppop->FocusedItem >= lppop->nItems - 1) {
522 MenuItemSelect(hwnd, lppop, -1);
523 NC_TrackSysMenu(hwnd);
524 break;
526 if (HideAllSubPopupMenu(lppop)) {
527 MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
528 goto ProceedSPACE;
531 if (lppop->hWndParent != 0) {
532 PostMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam);
533 break;
535 MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
536 break;
537 default:
538 break;
540 break;
541 case WM_CHAR:
542 #ifdef DEBUG_MENU
543 printf("PopupMenuWndProc hWnd=%04X WM_CHAR wParam=%04X !\n", hwnd, wParam);
544 #endif
545 if (lParam < 0L) break;
546 hwnd = GetFocus();
547 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
548 if (lppop == NULL) break;
549 switch(wParam) {
550 case VK_RETURN:
551 case VK_SPACE:
552 ProceedSPACE: lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
553 ExecFocusedMenuItem(hwnd, lppop);
554 break;
555 case VK_ESCAPE:
556 if (lppop->BarFlag) {
557 #ifdef DEBUG_MENU
558 printf("VK_ESCAPE // Unselect all MenuBar's Items !\n");
559 #endif
560 if (lppop->FocusedItem != (WORD)-1)
561 MenuItemSelect(hwnd, lppop, -1);
563 if (lppop->SysFlag) {
564 #ifdef DEBUG_MENU
565 printf("VK_ESCAPE // SysMenu !\n");
566 #endif
567 ShowWindow(hwnd, SW_HIDE);
568 break;
570 if (lppop->hWndParent != 0) {
571 #ifdef DEBUG_MENU
572 printf("VK_ESCAPE // Hide only SubPopup !\n");
573 #endif
574 lppop2 = PopupMenuGetWindowAndStorage(lppop->hWndParent, &wndPtr);
575 if (lppop2 == NULL) break;
576 HideAllSubPopupMenu(lppop2);
577 break;
579 else {
580 #ifdef DEBUG_MENU
581 printf("VK_ESCAPE // Hide Root Popup !\n");
582 #endif
583 ShowWindow(hwnd, SW_HIDE);
584 MenuHasFocus = FALSE;
586 break;
587 default:
588 if (wParam >= 'a' && wParam <= 'z') wParam -= 'a' - 'A';
589 lpitem = MenuFindItemBySelKey(lppop, wParam, &wRet);
590 if (lpitem != NULL) {
591 printf("ShortKey Found wRet=%d !\n", wRet);
592 MenuItemSelect(hwnd, lppop, wRet);
593 lppop->FocusedItem = wRet;
594 goto ProceedSPACE;
596 printf("ShortKey Not Found wParam=%04X wRet=%d lpitem=%08X !\n",
597 wParam, wRet, lpitem);
598 if (lppop->hWndParent != (HWND)NULL)
599 SendMessage(lppop->hWndParent, WM_MENUCHAR, wParam,
600 MAKELONG(0, 0));
601 else
602 SendMessage(lppop->ownerWnd, WM_MENUCHAR, wParam,
603 MAKELONG(0, 0));
604 break;
606 break;
607 case WM_PAINT:
608 #ifdef DEBUG_MENU
609 printf("PopupMenuWndProc // WM_PAINT received !\n");
610 #endif
611 StdDrawPopupMenu(hwnd);
612 break;
613 default:
614 return DefWindowProc(hwnd, message, wParam, lParam);
616 return 0;
620 BOOL ExecFocusedMenuItem(HWND hWnd, LPPOPUPMENU lppop)
622 short x, y;
623 LPPOPUPMENU lppop2;
624 LPMENUITEM lpitem;
625 HMENU hSubMenu;
626 RECT rect;
627 lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
628 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
629 hSubMenu = (HMENU)lpitem->item_id;
630 lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
631 if (lppop2 == NULL) return FALSE;
632 lppop2->hWndParent = hWnd;
633 GetClientRect(hWnd, &rect);
634 if (lppop->BarFlag) {
635 GetWindowRect(hWnd, &rect);
636 y = rect.top + lpitem->rect.bottom;
637 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
638 rect.left + lpitem->rect.left,
639 y, 0, lppop->ownerWnd, (LPRECT)NULL);
641 else {
642 x = lppop->rect.right;
643 GetWindowRect(hWnd, &rect);
644 x += rect.left;
645 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
646 x, rect.top + lpitem->rect.top,
647 0, lppop->ownerWnd, (LPRECT)NULL);
649 GlobalUnlock(hSubMenu);
650 return TRUE;
652 if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
653 ((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
654 MenuHasFocus = FALSE;
655 if (lppop->BarFlag) {
656 PostMessage(lppop->ownerWnd, WM_COMMAND, lpitem->item_id, 0L);
658 else {
659 ShowWindow(lppop->hWnd, SW_HIDE);
660 SendMessage(lppop->hWnd, WM_COMMAND, lpitem->item_id, 0L);
663 return TRUE;
668 BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y)
670 HDC hDC;
671 LPMENUITEM lpitem, lpitem2;
672 RECT rect;
673 HMENU hSubMenu;
674 WORD wRet;
675 LPPOPUPMENU lppop2;
676 if (lppop == NULL) return;
677 lpitem = MenuFindItem(lppop, x, y, &wRet);
678 #ifdef DEBUG_MENU
679 printf("MenuButtonDown hWnd=%04X x=%d y=%d // wRet=%d lpitem=%08X !\n",
680 hWnd, x, y, wRet, lpitem);
681 #endif
682 if (lpitem != NULL) {
683 if (lppop->FocusedItem != (WORD)-1 && wRet == lppop->FocusedItem) {
684 lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem);
685 if ((lpitem2->item_flags & MF_POPUP) == MF_POPUP) {
686 hSubMenu = (HMENU)lpitem2->item_id;
687 lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
688 if (lppop2 == NULL) return FALSE;
689 if (IsWindowVisible(lppop2->hWnd)) {
690 ShowWindow(lppop2->hWnd, SW_HIDE);
691 return TRUE;
695 MenuItemSelect(hWnd, lppop, wRet);
696 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
697 hSubMenu = (HMENU)lpitem->item_id;
698 lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
699 if (lppop2 == NULL) return FALSE;
700 lppop2->hWndParent = hWnd;
701 if (lppop->BarFlag) {
702 GetWindowRect(hWnd, &rect);
703 y = rect.top + lpitem->rect.bottom;
704 ReleaseCapture();
705 if (MenuHasFocus) {
706 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
707 rect.left + lpitem->rect.left,
708 y, 0, lppop->ownerWnd, (LPRECT)NULL);
710 else {
711 MenuHasFocus = TRUE;
712 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
713 rect.left + lpitem->rect.left,
714 y, 0, lppop->ownerWnd, (LPRECT)NULL);
715 MenuHasFocus = FALSE;
716 MenuFocusLoop(hWnd, lppop);
717 return TRUE;
720 else {
721 x = lppop->rect.right;
722 GetWindowRect(hWnd, &rect);
723 x += rect.left;
724 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
725 x, rect.top + lpitem->rect.top,
726 0, lppop->ownerWnd, (LPRECT)NULL);
728 GlobalUnlock(hSubMenu);
729 return TRUE;
731 if (lppop->BarFlag && !MenuHasFocus) {
732 MenuFocusLoop(hWnd, lppop);
734 return TRUE;
736 printf("MenuButtonDown // x=%d y=%d // Not Found !\n", x, y);
737 if (GetCapture() != 0) ReleaseCapture();
738 MenuHasFocus = FALSE;
739 ShowWindow(lppop->hWnd, SW_HIDE);
740 return FALSE;
745 void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y)
747 HDC hDC;
748 LPMENUITEM lpitem, lpitem2;
749 RECT rect;
750 HMENU hSubMenu;
751 WORD wRet;
752 LPPOPUPMENU lppop2;
753 if (lppop == NULL) return;
754 lpitem = MenuFindItem(lppop, x, y, &wRet);
755 #ifdef DEBUG_MENU
756 printf("MenuButtonUp // x=%d y=%d // wRet=%d lpitem=%08X !\n",
757 x, y, wRet, lpitem);
758 #endif
759 if (lpitem != NULL) {
760 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
761 return;
763 if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
764 ((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
765 MenuHasFocus = FALSE;
766 if (lppop->BarFlag) {
767 PostMessage(lppop->ownerWnd, WM_COMMAND, lpitem->item_id, 0L);
769 else {
770 ShowWindow(lppop->hWnd, SW_HIDE);
771 SendMessage(lppop->hWnd, WM_COMMAND, lpitem->item_id, 0L);
773 return;
776 if (lppop->FocusedItem != (WORD)-1) {
777 MenuItemSelect(hWnd, lppop, lppop->FocusedItem);
783 void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y)
785 HDC hDC;
786 RECT rect;
787 HMENU hSubMenu;
788 LPMENUITEM lpitem, lpitem2;
789 LPPOPUPMENU lppop2;
790 WORD wRet;
792 if (GetKeyState(VK_LBUTTON) != 0)
794 lpitem = MenuFindItem(lppop, x, y, &wRet);
795 #ifdef DEBUG_MENU
796 printf("MenuMouseMove // x=%d y=%d // wRet=%d lpitem=%08X !\n",
797 x, y, wRet, lpitem);
798 #endif
799 if ((lpitem != NULL) && (lppop->FocusedItem != wRet))
801 lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem);
802 hDC = GetWindowDC(hWnd);
803 if ((lpitem2 != NULL ) &&
804 (lpitem2->item_flags & MF_POPUP) == MF_POPUP)
806 HideAllSubPopupMenu(lppop);
808 MenuItemSelect(hWnd, lppop, wRet);
809 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP)
811 hSubMenu = (HMENU)lpitem->item_id;
812 lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
813 if (lppop2 == NULL)
815 ReleaseDC(hWnd, hDC);
816 return;
818 if (lppop->BarFlag)
820 lppop2->hWndParent = hWnd;
821 GetWindowRect(hWnd, &rect);
822 rect.top += lpitem->rect.bottom;
823 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
824 rect.left + lpitem->rect.left, rect.top,
825 0, lppop->ownerWnd, (LPRECT)NULL);
827 GlobalUnlock(hSubMenu);
829 ReleaseDC(hWnd, hDC);
835 void SelectPrevItem(LPPOPUPMENU lppop)
837 int nIndex;
838 LPMENUITEM lpitem;
839 if (lppop == NULL) return;
840 nIndex = lppop->FocusedItem;
841 if (nIndex < 1) {
842 if (nIndex == -1)
843 nIndex = 0;
844 else
845 nIndex = lppop->nItems - 1;
846 lpitem = GetMenuItemPtr(lppop, nIndex);
848 else {
849 nIndex--;
850 lpitem = GetMenuItemPtr(lppop, nIndex);
852 while (lpitem != NULL && lpitem->item_flags & MF_SEPARATOR) {
853 nIndex--;
854 lpitem = GetMenuItemPtr(lppop, nIndex);
856 MenuItemSelect(lppop->hWnd, lppop, nIndex);
860 void SelectNextItem(LPPOPUPMENU lppop)
862 int nIndex;
863 LPMENUITEM lpitem;
864 if (lppop == NULL) return;
865 nIndex = lppop->FocusedItem;
866 if ((nIndex == -1) || (nIndex >= lppop->nItems - 1)) {
867 nIndex = 0;
868 lpitem = GetMenuItemPtr(lppop, nIndex);
870 else {
871 nIndex++;
872 lpitem = GetMenuItemPtr(lppop, nIndex);
874 while (lpitem != NULL && (lpitem->item_flags & MF_SEPARATOR)) {
875 nIndex++;
876 lpitem = GetMenuItemPtr(lppop, nIndex);
878 MenuItemSelect(lppop->hWnd, lppop, nIndex);
882 void ResetHiliteFlags(LPPOPUPMENU lppop)
884 LPMENUITEM lpitem;
885 int i;
886 #ifdef DEBUG_MENU
887 printf("ResetHiliteFlags lppop=%08X\n", lppop);
888 #endif
889 if (lppop == NULL) return;
890 lpitem = lppop->firstItem;
891 for(i = 0; i < lppop->nItems; i++) {
892 if (lpitem == NULL) return;
893 lpitem->item_flags &= ~MF_HILITE;
894 lpitem = (LPMENUITEM)lpitem->next;
899 void MenuItemSelect(HWND hWnd, LPPOPUPMENU lppop, WORD wIndex)
901 LPMENUITEM lpitem;
902 HDC hdc;
904 if (lppop == NULL) return;
905 if (lppop->BarFlag) hdc = GetDCEx( hWnd, 0, DCX_CACHE | DCX_WINDOW );
906 else hdc = GetDC( hWnd );
908 /* Clear previous highlighted item */
909 if (lppop->FocusedItem != (WORD)-1)
911 if ((lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem)) != NULL)
913 lpitem->item_flags &= ~MF_HILITE;
914 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP)
915 HideAllSubPopupMenu(lppop);
916 MENU_DrawMenuItem( hdc, lpitem, &lppop->rect, lppop->BarFlag );
920 /* Highlight new item (if any) */
921 lppop->FocusedItem = wIndex;
922 if (lppop->FocusedItem != (WORD)-1)
924 if ((lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem)) != NULL)
926 lpitem->item_flags |= MF_HILITE;
927 MENU_DrawMenuItem( hdc, lpitem, &lppop->rect, lppop->BarFlag );
928 SendMessage(hWnd, WM_MENUSELECT, lpitem->item_id,
929 MAKELONG(0, lpitem->item_flags));
932 ReleaseDC( hWnd, hdc );
936 LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr)
938 WND *Ptr;
939 LPPOPUPMENU lppop;
940 *(wndPtr) = Ptr = WIN_FindWndPtr(hwnd);
941 if (Ptr == 0) {
942 printf("PopupMenuGetWindowAndStorage // Bad Window handle !\n");
943 return NULL;
945 lppop = *((LPPOPUPMENU *)&Ptr->wExtra[1]);
946 if (lppop == NULL) {
947 lppop = (LPPOPUPMENU) GlobalLock(Ptr->wIDmenu);
948 if (lppop == NULL) {
949 printf("PopupMenuGetWindowAndStorage // Bad Menu Handle !\n");
950 return NULL;
953 return lppop;
957 LPPOPUPMENU PopupMenuGetStorageHeader(HWND hwnd)
959 WND *Ptr;
960 LPPOPUPMENU lppop;
961 Ptr = WIN_FindWndPtr(hwnd);
962 if (Ptr == 0) {
963 printf("Bad Window handle on PopupMenu !\n");
964 return 0;
966 lppop = *((LPPOPUPMENU *)&Ptr->wExtra[1]);
967 return lppop;
971 void SetMenuLogicalParent(HMENU hMenu, HWND hWnd)
973 LPPOPUPMENU lppop;
974 lppop = (LPPOPUPMENU)GlobalLock(hMenu);
975 lppop->hWndParent = hWnd;
976 GlobalUnlock(hMenu);
980 void StdDrawPopupMenu(HWND hwnd)
982 WND *wndPtr;
983 LPPOPUPMENU lppop;
984 LPMENUITEM lpitem;
985 PAINTSTRUCT ps;
986 RECT rect;
987 HDC hDC;
989 hDC = BeginPaint(hwnd, &ps);
990 GetClientRect(hwnd, &rect);
991 FillRect(hDC, &rect, sysColorObjects.hbrushMenu );
993 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
994 for (lpitem = lppop->firstItem; lpitem != NULL; lpitem = lpitem->next )
996 MENU_DrawMenuItem( hDC, lpitem, &rect, FALSE );
998 EndPaint( hwnd, &ps );
1002 void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop,
1003 BOOL suppress_draw)
1005 LPMENUITEM lpitem;
1006 if (lppop == NULL || lprect == NULL) return;
1007 #ifdef DEBUG_MENU
1008 printf("StdDrawMenuBar(%04X, %08X, %08X); !\n", hDC, lprect, lppop);
1009 #endif
1010 if (lppop->Height == 0) MENU_MenuBarCalcSize(hDC, lprect, lppop);
1011 if (suppress_draw) return;
1013 FillRect(hDC, lprect, sysColorObjects.hbrushMenu );
1014 SelectObject( hDC, sysColorObjects.hpenWindowFrame );
1015 MoveTo( hDC, lprect->left, lprect->bottom );
1016 LineTo( hDC, lprect->right, lprect->bottom );
1018 if (lppop->nItems == 0) return;
1019 for (lpitem = lppop->firstItem; lpitem != NULL; lpitem = lpitem->next )
1021 MENU_DrawMenuItem( hDC, lpitem, lprect, TRUE );
1027 LPMENUITEM MenuFindItem(LPPOPUPMENU lppop, int x, int y, WORD *lpRet)
1029 LPMENUITEM lpitem;
1030 UINT i;
1031 if (lpRet != NULL) *lpRet = 0;
1032 if (lppop == NULL) return NULL;
1033 if (lppop->nItems == 0) return NULL;
1034 lpitem = lppop->firstItem;
1035 for(i = 0; i < lppop->nItems; i++) {
1036 if (lpitem == NULL) return NULL;
1037 #ifdef DEBUG_MENUFINDITEM
1038 printf("FindItem // left=%d top=%d right=%d bottom=%d\n",
1039 lpitem->rect.left, lpitem->rect.top,
1040 lpitem->rect.right, lpitem->rect.bottom);
1041 #endif
1042 if (x > lpitem->rect.left && x < lpitem->rect.right &&
1043 y > lpitem->rect.top && y < lpitem->rect.bottom) {
1044 if (lpRet != NULL) *lpRet = i;
1045 return lpitem;
1047 lpitem = (LPMENUITEM)lpitem->next;
1049 return NULL;
1053 LPMENUITEM MenuFindItemBySelKey(LPPOPUPMENU lppop, WORD key, WORD *lpRet)
1055 LPMENUITEM lpitem;
1056 UINT i;
1057 if (lppop == NULL) return NULL;
1059 if (lppop->nItems == 0) return NULL;
1060 lpitem = lppop->firstItem;
1061 for(i = 0; i < lppop->nItems; i++) {
1062 if (lpitem == NULL) return NULL;
1063 #ifdef DEBUG_MENUFINDITEM
1064 printf("FindItemBySelKey // key=%04X lpitem->sel_key=%04X\n",
1065 key, lpitem->sel_key);
1066 #endif
1067 if (key == lpitem->sel_key) {
1068 if (lpRet != NULL) *lpRet = i;
1069 return lpitem;
1071 lpitem = (LPMENUITEM)lpitem->next;
1073 return NULL;
1081 /***********************************************************************
1082 * MENU_GetMenuBarHeight
1084 * Compute the size of the menu bar height. Used by NC_HandleNCCalcSize().
1086 WORD MENU_GetMenuBarHeight( HWND hwnd, WORD menubarWidth, int orgX, int orgY )
1088 HDC hdc;
1089 RECT rectBar;
1090 WND *wndPtr;
1091 LPPOPUPMENU lppop;
1093 if (!(lppop = PopupMenuGetWindowAndStorage( hwnd, &wndPtr ))) return 0;
1094 if (!wndPtr) return 0;
1095 hdc = GetDC( hwnd );
1096 SetRect( &rectBar, orgX, orgY, orgX+menubarWidth, orgY+SYSMETRICS_CYMENU );
1097 MENU_MenuBarCalcSize( hdc, &rectBar, lppop );
1098 ReleaseDC( hwnd, hdc );
1099 printf( "MENU_GetMenuBarHeight: returning %d\n", lppop->Height );
1100 return lppop->Height;
1104 /***********************************************************************
1105 * FindMenuItem
1107 LPMENUITEM FindMenuItem(HMENU hMenu, WORD nPos, WORD wFlags)
1109 LPPOPUPMENU menu;
1110 LPMENUITEM lpitem;
1111 int i;
1112 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1113 if (menu == NULL) {
1114 GlobalUnlock(hMenu);
1115 return FALSE;
1117 lpitem = menu->firstItem;
1118 if (wFlags & MF_BYPOSITION) {
1119 for (i = 0; i < nPos; i++, lpitem = lpitem->next)
1120 if (lpitem == NULL) return NULL;
1122 else {
1123 for (i = 0; i < menu->nItems && lpitem != NULL; i++) {
1124 if (lpitem->item_id == nPos) return lpitem;
1125 lpitem = lpitem->next;
1127 return NULL;
1129 return lpitem;
1133 LPMENUITEM GetMenuItemPtr(LPPOPUPMENU menu, WORD nPos)
1135 LPMENUITEM lpitem;
1136 int i;
1137 if (menu == NULL) return NULL;
1138 lpitem = menu->firstItem;
1139 for (i = 0; i < menu->nItems; i++) {
1140 if (lpitem == NULL) return NULL;
1141 if (i == nPos) return(lpitem);
1142 lpitem = (LPMENUITEM)lpitem->next;
1144 return NULL;
1148 WORD GetSelectionKey(LPSTR str)
1150 int i;
1151 WORD sel_key;
1152 for (i = 0; i < strlen(str); i++) {
1153 if (str[i] == '&' && str[i + 1] != '&') {
1154 sel_key = str[i + 1];
1155 if (sel_key >= 'a' && sel_key <= 'z') sel_key -= 'a' - 'A';
1156 #ifdef DEBUG_MENU
1157 printf("GetSelectionKey // %04X\n", sel_key);
1158 #endif
1159 return sel_key;
1162 #ifdef DEBUG_MENU
1163 printf("GetSelectionKey NULL \n");
1164 #endif
1165 return 0;
1170 LPSTR GetShortCutString(LPSTR str)
1172 int i;
1173 LPSTR str2;
1174 for (i = 0; i < strlen(str); i++) {
1175 if (str[i] == '\t' && str[i + 1] != '\t') {
1176 str2 = &str[i + 1];
1177 #ifdef DEBUG_MENUSHORTCUT
1178 printf("GetShortCutString // '%s' \n", str2);
1179 #endif
1180 return str2;
1183 #ifdef DEBUG_MENUSHORTCUT
1184 printf("GetShortCutString NULL \n");
1185 #endif
1186 return NULL;
1191 int GetShortCutPos(LPSTR str)
1193 int i;
1194 for (i = 0; i < strlen(str); i++) {
1195 if (str[i] == '\t' && str[i + 1] != '\t') {
1196 #ifdef DEBUG_MENUSHORTCUT
1197 printf("GetShortCutPos = %d \n", i);
1198 #endif
1199 return i;
1202 #ifdef DEBUG_MENUSHORTCUT
1203 printf("GetShortCutString NULL \n");
1204 #endif
1205 return -1;
1210 BOOL HideAllSubPopupMenu(LPPOPUPMENU menu)
1212 LPPOPUPMENU submenu;
1213 LPMENUITEM lpitem;
1214 BOOL someClosed = FALSE;
1215 int i;
1216 if (menu == NULL) return;
1217 lpitem = menu->firstItem;
1218 for (i = 0; i < menu->nItems; i++) {
1219 if (lpitem == NULL) return;
1220 if (lpitem->item_flags & MF_POPUP) {
1221 submenu = (LPPOPUPMENU) GlobalLock((HMENU)lpitem->item_id);
1222 if (submenu != NULL) {
1223 if (IsWindowVisible(submenu->hWnd)) {
1224 ShowWindow(submenu->hWnd, SW_HIDE);
1225 someClosed = TRUE;
1227 GlobalUnlock((HMENU)lpitem->item_id);
1230 lpitem = (LPMENUITEM)lpitem->next;
1232 return someClosed;
1238 /**********************************************************************
1239 * ChangeMenu [USER.153]
1241 BOOL ChangeMenu(HMENU hMenu, WORD nPos, LPSTR lpNewItem,
1242 WORD wItemID, WORD wFlags)
1244 if (wFlags & MF_APPEND)
1245 return AppendMenu(hMenu, wFlags, wItemID, lpNewItem);
1246 if (wFlags & MF_DELETE)
1247 return DeleteMenu(hMenu, wItemID, wFlags);
1248 if (wFlags & MF_INSERT)
1249 return InsertMenu(hMenu, nPos, wFlags, wItemID, lpNewItem);
1250 if (wFlags & MF_CHANGE)
1251 return ModifyMenu(hMenu, nPos, wFlags, wItemID, lpNewItem);
1252 if (wFlags & MF_REMOVE)
1253 return RemoveMenu(hMenu, wItemID, wFlags);
1254 return FALSE;
1258 /**********************************************************************
1259 * CheckMenuItem [USER.154]
1261 BOOL CheckMenuItem(HMENU hMenu, WORD wItemID, WORD wFlags)
1263 LPMENUITEM lpitem;
1264 #ifdef DEBUG_MENU
1265 printf("CheckMenuItem (%04X, %04X, %04X) !\n", hMenu, wItemID, wFlags);
1266 #endif
1267 lpitem = FindMenuItem(hMenu, wItemID, wFlags);
1268 if (lpitem != NULL) {
1269 if ((wFlags & MF_CHECKED) == MF_CHECKED)
1270 lpitem->item_flags |= MF_CHECKED;
1271 else
1272 lpitem->item_flags &= ((WORD)-1 ^ MF_CHECKED);
1273 #ifdef DEBUG_MENU
1274 printf("CheckMenuItem // Found !\n");
1275 #endif
1276 return(TRUE);
1278 return FALSE;
1282 /**********************************************************************
1283 * EnableMenuItem [USER.155]
1285 BOOL EnableMenuItem(HMENU hMenu, WORD wItemID, WORD wFlags)
1287 LPMENUITEM lpitem;
1288 #ifdef DEBUG_MENU
1289 printf("EnableMenuItem (%04X, %04X, %04X) !\n", hMenu, wItemID, wFlags);
1290 #endif
1291 if (!(lpitem = FindMenuItem(hMenu, wItemID, wFlags))) return FALSE;
1293 /* We can't have MF_GRAYED and MF_DISABLED together */
1294 if (wFlags & MF_GRAYED)
1296 lpitem->item_flags = (lpitem->item_flags & ~MF_DISABLED) | MF_GRAYED;
1298 else if (wFlags & MF_DISABLED)
1300 lpitem->item_flags = (lpitem->item_flags & ~MF_GRAYED) | MF_DISABLED;
1302 else /* MF_ENABLED */
1304 lpitem->item_flags &= ~(MF_GRAYED | MF_DISABLED);
1306 return TRUE;
1310 /**********************************************************************
1311 * GetMenuString [USER.161]
1313 int GetMenuString(HMENU hMenu, WORD wItemID,
1314 LPSTR str, short nMaxSiz, WORD wFlags)
1316 LPMENUITEM lpitem;
1317 int maxsiz;
1318 #ifdef DEBUG_MENU
1319 printf("GetMenuString(%04X, %04X, %08X, %d, %04X);\n",
1320 hMenu, wItemID, str, nMaxSiz, wFlags);
1321 #endif
1322 if (str == NULL) return FALSE;
1323 lpitem = FindMenuItem(hMenu, wItemID, wFlags);
1324 if (lpitem != NULL) {
1325 if (lpitem->item_text != NULL) {
1326 maxsiz = min(nMaxSiz - 1, strlen(lpitem->item_text));
1327 strncpy(str, lpitem->item_text, maxsiz + 1);
1329 else
1330 maxsiz = 0;
1331 #ifdef DEBUG_MENU
1332 printf("GetMenuString // Found !\n");
1333 #endif
1334 return maxsiz;
1336 return 0;
1340 /**********************************************************************
1341 * HiliteMenuItem [USER.162]
1343 BOOL HiliteMenuItem(HWND hWnd, HMENU hMenu, WORD wItemID, WORD wHilite)
1345 LPPOPUPMENU menu;
1346 LPMENUITEM lpitem;
1347 #ifdef DEBUG_MENU
1348 printf("HiliteMenuItem(%04X, %04X, %04X, %04X);\n",
1349 hWnd, hMenu, wItemID, wHilite);
1350 #endif
1351 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1352 if (menu == NULL) return FALSE;
1353 lpitem = FindMenuItem(hMenu, wItemID, wHilite);
1354 if (lpitem == NULL) return FALSE;
1355 return FALSE;
1359 /**********************************************************************
1360 * GetMenuState [USER.250]
1362 WORD GetMenuState(HMENU hMenu, WORD wItemID, WORD wFlags)
1364 LPPOPUPMENU menu;
1365 LPMENUITEM lpitem;
1366 #ifdef DEBUG_MENU
1367 printf("GetMenuState(%04X, %04X, %04X);\n", hMenu, wItemID, wFlags);
1368 #endif
1369 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1370 if (menu == NULL) return -1;
1371 lpitem = FindMenuItem(hMenu, wItemID, wFlags);
1372 if (lpitem == NULL) return -1;
1373 return lpitem->item_flags;
1377 /**********************************************************************
1378 * GetMenuItemCount [USER.263]
1380 WORD GetMenuItemCount(HMENU hMenu)
1382 LPPOPUPMENU menu;
1383 #ifdef DEBUG_MENU
1384 printf("GetMenuItemCount(%04X);\n", hMenu);
1385 #endif
1386 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1387 if (menu == NULL) return (WORD)-1;
1388 #ifdef DEBUG_MENU
1389 printf("GetMenuItemCount(%04X) return %d \n", hMenu, menu->nItems);
1390 #endif
1391 return menu->nItems;
1395 /**********************************************************************
1396 * GetMenuItemID [USER.264]
1398 WORD GetMenuItemID(HMENU hMenu, int nPos)
1400 WORD i;
1401 LPPOPUPMENU menu;
1402 LPMENUITEM lpitem;
1403 printf("GetMenuItemID(%04X, %d);\n", hMenu, nPos);
1404 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1405 if (menu == NULL) return -1;
1406 lpitem = menu->firstItem;
1407 for (i = 0; i < menu->nItems; i++) {
1408 if (lpitem == NULL) break;
1409 if (i == nPos) {
1410 #ifdef DEBUG_MENU
1411 printf("GetMenuItemID // Found !\n");
1412 #endif
1413 return lpitem->item_id;
1415 lpitem = (LPMENUITEM)lpitem->next;
1417 return -1;
1421 /**********************************************************************
1422 * InsertMenu [USER.410]
1424 BOOL InsertMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
1426 LPPOPUPMENU menu;
1427 HANDLE hNewItem;
1428 LPMENUITEM lpitem, lpitem2;
1429 #ifdef DEBUG_MENU
1430 if ((wFlags & (MF_BITMAP | MF_SEPARATOR | MF_MENUBREAK | MF_OWNERDRAW)) == 0)
1431 printf("InsertMenu (%04X, %04X, %04X, '%s') !\n",
1432 hMenu, wFlags, wItemID, lpNewItem);
1433 else
1434 printf("InsertMenu (%04X, %04X, %04X, %04X, %08X) !\n",
1435 hMenu, nPos, wFlags, wItemID, lpNewItem);
1436 #endif
1437 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1438 if (menu == NULL) return FALSE;
1439 lpitem = FindMenuItem(hMenu, nPos, wFlags);
1440 if (lpitem == NULL) lpitem = menu->firstItem;
1441 hNewItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM));
1442 if (hNewItem == 0) {
1443 GlobalUnlock(hMenu);
1444 return FALSE;
1446 lpitem2 = (LPMENUITEM)GlobalLock(hNewItem);
1447 if (lpitem2 == NULL) {
1448 GlobalFree(hNewItem);
1449 GlobalUnlock(hMenu);
1450 return FALSE;
1452 lpitem2->hItem = hNewItem;
1453 lpitem2->item_flags = wFlags;
1454 lpitem2->item_id = wItemID;
1455 if (!(wFlags & (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
1456 MF_MENUBREAK | MF_SEPARATOR))) {
1457 lpitem2->hText = GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1);
1458 lpitem2->item_text = GlobalLock(lpitem2->hText);
1459 if (lpitem2->item_text != NULL)
1460 strcpy(lpitem2->item_text, lpNewItem);
1461 else {
1462 printf("InsertMenu // Bad Alloc !\n");
1463 return FALSE;
1465 lpitem2->sel_key = GetSelectionKey(lpitem2->item_text);
1467 else {
1468 lpitem2->item_text = lpNewItem;
1470 if (lpitem == NULL) {
1471 menu->firstItem = lpitem2;
1472 lpitem2->prev = NULL;
1473 lpitem2->next = NULL;
1475 else {
1476 lpitem2->prev = lpitem;
1477 lpitem2->next = lpitem->next;
1478 if (lpitem2->next != NULL) lpitem2->next->prev = lpitem2;
1479 lpitem->next = lpitem2;
1481 menu->nItems++;
1482 GlobalUnlock(hMenu);
1483 return TRUE;
1487 /**********************************************************************
1488 * AppendMenu [USER.411]
1490 BOOL AppendMenu(HMENU hMenu, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
1492 LPPOPUPMENU menu;
1493 HANDLE hNewItem;
1494 LPMENUITEM lpitem, lpitem2;
1495 #ifdef DEBUG_MENU
1496 if ((wFlags & (MF_BITMAP | MF_SEPARATOR | MF_MENUBREAK | MF_OWNERDRAW)) == 0)
1497 printf("AppendMenu (%04X, %04X, %04X, '%s') !\n",
1498 hMenu, wFlags, wItemID, lpNewItem);
1499 else
1500 printf("AppendMenu (%04X, %04X, %04X, %08X) !\n",
1501 hMenu, wFlags, wItemID, lpNewItem);
1502 #endif
1503 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1504 if (menu == NULL) return FALSE;
1505 lpitem = menu->firstItem;
1506 if (lpitem != NULL) {
1507 while (lpitem->next != NULL) {
1508 lpitem = (LPMENUITEM)lpitem->next;
1511 hNewItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM));
1512 if (hNewItem == 0) {
1513 GlobalUnlock(hMenu);
1514 return FALSE;
1516 lpitem2 = (LPMENUITEM)GlobalLock(hNewItem);
1517 lpitem2->hItem = hNewItem;
1518 if (lpitem2 == NULL) {
1519 GlobalFree(hNewItem);
1520 GlobalUnlock(hMenu);
1521 return FALSE;
1523 lpitem2->item_flags = wFlags;
1524 lpitem2->item_id = wItemID;
1525 if (!(wFlags & (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
1526 MF_MENUBREAK | MF_SEPARATOR))) {
1527 lpitem2->hText = GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1);
1528 lpitem2->item_text = GlobalLock(lpitem2->hText);
1529 if (lpitem2->item_text != NULL)
1530 strcpy(lpitem2->item_text, lpNewItem);
1531 else {
1532 printf("AppendMenu // Bad Alloc !\n");
1533 return FALSE;
1535 lpitem2->sel_key = GetSelectionKey(lpitem2->item_text);
1537 else {
1538 lpitem2->item_text = lpNewItem;
1540 if (lpitem == NULL)
1541 menu->firstItem = lpitem2;
1542 else
1543 lpitem->next = lpitem2;
1544 lpitem2->prev = lpitem;
1545 lpitem2->next = NULL;
1546 lpitem2->hCheckBit = (HBITMAP)NULL;
1547 lpitem2->hUnCheckBit = (HBITMAP)NULL;
1548 menu->nItems++;
1549 GlobalUnlock(hMenu);
1550 return TRUE;
1554 /**********************************************************************
1555 * RemoveMenu [USER.412]
1557 BOOL RemoveMenu(HMENU hMenu, WORD nPos, WORD wFlags)
1559 LPPOPUPMENU menu;
1560 LPMENUITEM lpitem;
1561 int i;
1562 #ifdef DEBUG_MENU
1563 printf("RemoveMenu (%04X, %04X, %04X) !\n", hMenu, nPos, wFlags);
1564 #endif
1565 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1566 if (menu == NULL) return FALSE;
1567 lpitem = menu->firstItem;
1568 for (i = 0; i < menu->nItems; i++) {
1569 if (lpitem == NULL) break;
1570 if (i == nPos) {
1571 lpitem->prev->next = lpitem->next;
1572 lpitem->next->prev = lpitem->prev;
1573 if (!(lpitem->item_flags &
1574 (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
1575 MF_MENUBREAK | MF_SEPARATOR))) {
1576 GlobalUnlock(lpitem->hText);
1577 GlobalFree(lpitem->hText);
1579 GlobalFree(lpitem->hItem);
1580 GlobalUnlock(hMenu);
1581 return TRUE;
1583 lpitem = (LPMENUITEM)lpitem->next;
1584 printf("RemoveMenu // during loop items !\n");
1586 printf("RemoveMenu // after loop items !\n");
1587 GlobalUnlock(hMenu);
1588 return FALSE;
1592 /**********************************************************************
1593 * DeleteMenu [USER.413]
1595 BOOL DeleteMenu(HMENU hMenu, WORD nPos, WORD wFlags)
1597 LPPOPUPMENU menu;
1598 LPMENUITEM lpitem;
1599 int i;
1600 #ifdef DEBUG_MENU
1601 printf("DeleteMenu (%04X, %04X, %04X) !\n", hMenu, nPos, wFlags);
1602 #endif
1603 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1604 if (menu == NULL) {
1605 GlobalUnlock(hMenu);
1606 return FALSE;
1608 lpitem = FindMenuItem(hMenu, nPos, wFlags);
1609 if (lpitem != NULL) {
1610 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP)
1611 DestroyMenu((HMENU)lpitem->item_id);
1612 if (!(lpitem->item_flags &
1613 (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
1614 MF_MENUBREAK | MF_SEPARATOR))) {
1615 GlobalUnlock(lpitem->hText);
1616 GlobalFree(lpitem->hText);
1618 if (lpitem->prev) lpitem->prev->next = lpitem->next;
1619 if (lpitem->next) lpitem->next->prev = lpitem->prev;
1620 GlobalFree(lpitem->hItem);
1621 GlobalUnlock(hMenu);
1622 return TRUE;
1624 GlobalUnlock(hMenu);
1625 return FALSE;
1629 /**********************************************************************
1630 * ModifyMenu [USER.414]
1632 BOOL ModifyMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
1634 LPPOPUPMENU menu;
1635 LPMENUITEM lpitem;
1636 int i;
1637 #ifdef DEBUG_MENU
1638 if ((wFlags & (MF_BITMAP | MF_SEPARATOR | MF_MENUBREAK | MF_OWNERDRAW)) == 0)
1639 printf("ModifyMenu (%04X, %04X, %04X, %04X, '%s') !\n",
1640 hMenu, nPos, wFlags, wItemID, lpNewItem);
1641 else
1642 printf("ModifyMenu (%04X, %04X, %04X, %04X, %08X) !\n",
1643 hMenu, nPos, wFlags, wItemID, lpNewItem);
1644 #endif
1645 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1646 if (menu == NULL) return FALSE;
1647 lpitem = menu->firstItem;
1648 for (i = 0; i < menu->nItems; i++) {
1649 if (lpitem == NULL) break;
1650 if (i == nPos) {
1651 lpitem->item_flags = wFlags;
1652 lpitem->item_id = wItemID;
1653 if (!(lpitem->item_flags &
1654 (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
1655 MF_MENUBREAK | MF_SEPARATOR))) {
1656 GlobalUnlock(lpitem->hText);
1657 GlobalFree(lpitem->hText);
1658 lpitem->hText = GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1);
1659 lpitem->item_text = GlobalLock(lpitem->hText);
1660 printf("ModifyMenu %08X %08X '%s') !\n",
1661 lpitem->item_text, lpNewItem, lpNewItem);
1662 if (lpitem->item_text != NULL)
1663 strcpy(lpitem->item_text, lpNewItem);
1664 else
1665 printf("ModifyMenu // Bad Alloc !\n");
1667 else
1668 lpitem->item_text = lpNewItem;
1669 GlobalUnlock(hMenu);
1670 return(TRUE);
1672 lpitem = (LPMENUITEM)lpitem->next;
1674 GlobalUnlock(hMenu);
1675 return FALSE;
1679 /**********************************************************************
1680 * CreatePopupMenu [USER.415]
1682 HMENU CreatePopupMenu()
1684 HANDLE hItem;
1685 HMENU hMenu;
1686 LPPOPUPMENU menu;
1687 #ifdef DEBUG_MENU
1688 printf("CreatePopupMenu !\n");
1689 #endif
1690 hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
1691 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1692 if (menu == NULL) {
1693 GlobalFree(hMenu);
1694 return 0;
1696 menu->nItems = 0;
1697 menu->firstItem = NULL;
1698 menu->ownerWnd = 0;
1699 menu->hWndPrev = 0;
1700 menu->hWnd = 0;
1701 menu->hWndParent = 0;
1702 menu->MouseFlags = 0;
1703 menu->BarFlag = FALSE;
1704 menu->SysFlag = FALSE;
1705 menu->ChildFlag = TRUE;
1706 menu->Width = 100;
1707 menu->Height = 0;
1708 GlobalUnlock(hMenu);
1709 #ifdef DEBUG_MENU
1710 printf("CreatePopupMenu // return %04X\n", hMenu);
1711 #endif
1712 return hMenu;
1716 /**********************************************************************
1717 * TrackPopupMenu [USER.416]
1719 BOOL TrackPopupMenu(HMENU hMenu, WORD wFlags, short x, short y,
1720 short nReserved, HWND hWnd, LPRECT lpRect)
1722 WND *wndPtr;
1723 LPPOPUPMENU lppop;
1724 RECT rect;
1725 #ifdef DEBUG_MENU
1726 printf("TrackPopupMenu (%04X, %04X, %d, %d, %04X, %04X, %08X) !\n",
1727 hMenu, wFlags, x, y, nReserved, hWnd, lpRect);
1728 #endif
1729 lppop = (LPPOPUPMENU) GlobalLock(hMenu);
1730 if (lppop == NULL) {
1731 printf("TrackPopupMenu // Bad menu handle %04X !\n", hMenu);
1732 return FALSE;
1734 wndPtr = WIN_FindWndPtr(hWnd);
1735 if (wndPtr == NULL) {
1736 printf("TrackPopupMenu // Bad window handle %04X !\n", hWnd);
1737 return FALSE;
1739 lppop->ownerWnd = hWnd;
1740 lppop->hWndPrev = GetFocus();
1741 if (lppop->hWnd == (HWND)NULL) {
1742 lppop->hWnd = CreateWindow(POPUPMENU_CLASS_NAME, "",
1743 WS_POPUP | WS_BORDER,
1744 x, y, lppop->Width, lppop->Height, (HWND)NULL, 0,
1745 wndPtr->hInstance, (LPSTR)lppop);
1746 if (lppop->hWnd == 0) {
1747 printf("TrackPopupMenu // Can't create PopupMenu window !\n");
1748 return FALSE;
1751 if (!lppop->BarFlag) {
1752 MENU_PopupMenuCalcSize(lppop->hWnd);
1753 #ifdef DEBUG_MENU
1754 printf("TrackPopupMenu // x=%d y=%d Width=%d Height=%d\n",
1755 x, y, lppop->Width, lppop->Height);
1756 #endif
1757 SetWindowPos(lppop->hWnd, 0, x, y, lppop->Width + 2, lppop->Height + 2,
1758 SWP_NOACTIVATE | SWP_NOZORDER);
1760 ShowWindow(lppop->hWnd, SW_SHOWNOACTIVATE);
1761 SetFocus(lppop->hWnd);
1762 if (!MenuHasFocus) {
1763 #ifdef DEBUG_MENU
1764 printf("TrackPopupMenu // before MenuFocusLoop !\n");
1765 #endif
1766 MenuFocusLoop(hWnd, NULL);
1767 #ifdef DEBUG_MENU
1768 printf("TrackPopupMenu // after MenuFocusLoop !\n");
1769 #endif
1771 GlobalUnlock(hMenu);
1772 return TRUE;
1776 BOOL ActivateMenuBarFocus(HWND hWnd)
1778 WND *wndPtr;
1779 LPPOPUPMENU lpmenu;
1780 BOOL bRet;
1781 MSG msg;
1782 if (MenuHasFocus) return FALSE;
1783 wndPtr = WIN_FindWndPtr(hWnd);
1784 if (wndPtr == NULL) return FALSE;
1785 #ifdef DEBUG_MENU
1786 printf("ActivateMenuBarFocus (%04X) !\n", hWnd);
1787 #endif
1788 while((wndPtr->dwStyle & WS_CHILD) == WS_CHILD) {
1789 hWnd = GetParent(hWnd);
1790 printf("ActivateMenuBarFocus // next Parent=%04X !\n", hWnd);
1791 wndPtr = WIN_FindWndPtr(hWnd);
1792 if (wndPtr == NULL) return FALSE;
1794 if ((wndPtr->dwStyle & WS_CHILD) == 0 && wndPtr->wIDmenu != 0) {
1795 lpmenu = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu);
1796 if (lpmenu == NULL) return FALSE;
1797 lpmenu->hWndPrev = GetFocus();
1798 SetFocus(hWnd);
1799 MenuItemSelect(hWnd, lpmenu, 0);
1800 bRet = MenuFocusLoop(hWnd, lpmenu);
1801 GlobalUnlock(wndPtr->wIDmenu);
1802 return bRet;
1804 return FALSE;
1808 BOOL MenuFocusLoop(HWND hWnd, LPPOPUPMENU lpmenu)
1810 MSG msg;
1811 #ifdef DEBUG_MENU
1812 printf("Enter in Menu Focus Loop !\n");
1813 #endif
1814 MenuHasFocus = TRUE;
1815 while(TRUE) {
1816 if (!MenuHasFocus) break;
1817 if (!GetMessage(&msg, (HWND)NULL, 0, 0)) break;
1818 TranslateMessage(&msg);
1819 if (hWnd == msg.hwnd && lpmenu != NULL) {
1820 if ((msg.message == WM_SYSKEYDOWN && msg.wParam == VK_MENU) ||
1821 (msg.message == WM_CHAR && msg.wParam == VK_ESCAPE)) {
1822 HideAllSubPopupMenu(lpmenu);
1823 break;
1825 ScreenToClient(hWnd, &msg.pt);
1826 msg.pt.y += lpmenu->rect.bottom;
1827 switch(msg.message) {
1828 case WM_LBUTTONDOWN:
1829 case WM_NCLBUTTONDOWN:
1830 SetCapture(hWnd);
1831 MenuButtonDown(hWnd, lpmenu, msg.pt.x, msg.pt.y);
1832 break;
1833 case WM_LBUTTONUP:
1834 case WM_NCLBUTTONUP:
1835 MenuButtonUp(hWnd, lpmenu, msg.pt.x, msg.pt.y);
1836 ReleaseCapture();
1837 break;
1838 case WM_MOUSEMOVE:
1839 case WM_NCMOUSEMOVE:
1840 MenuMouseMove(hWnd, lpmenu, msg.wParam, msg.pt.x, msg.pt.y);
1841 break;
1842 case WM_KEYDOWN:
1843 case WM_KEYUP:
1844 case WM_CHAR:
1845 PopupMenuWndProc(hWnd, msg.message, msg.wParam, msg.lParam);
1846 default:
1847 DispatchMessage(&msg);
1850 else
1851 DispatchMessage(&msg);
1853 EndOfFocus:
1854 MenuHasFocus = FALSE;
1855 if (lpmenu != NULL) MenuItemSelect(hWnd, lpmenu, -1);
1856 #ifdef DEBUG_MENU
1857 printf("End of Menu Focus Loop !\n");
1858 #endif
1859 return TRUE;
1863 /**********************************************************************
1864 * NC_TrackSysMenu [Internal]
1866 void NC_TrackSysMenu(HWND hWnd)
1868 RECT rect;
1869 LPPOPUPMENU lpsys;
1870 WND *wndPtr = WIN_FindWndPtr(hWnd);
1871 #ifdef DEBUG_MENU
1872 printf("NC_TrackSysMenu hWnd=%04X !\n", hWnd);
1873 #endif
1874 if (!wndPtr) return;
1875 lpsys = (LPPOPUPMENU)GlobalLock(wndPtr->hSysMenu);
1876 #ifdef DEBUG_MENU
1877 printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu);
1878 #endif
1879 if (lpsys == NULL) return;
1880 #ifdef DEBUG_MENU
1881 printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu);
1882 #endif
1883 lpsys->BarFlag = FALSE;
1884 lpsys->SysFlag = TRUE;
1885 lpsys->ChildFlag = FALSE;
1886 lpsys->hWndParent = hWnd;
1887 if (!IsWindowVisible(lpsys->hWnd)) {
1888 GetWindowRect(hWnd, &rect);
1889 #ifdef DEBUG_MENU
1890 printf("NC_TrackSysMenu lpsys->hWnd=%04X !\n", lpsys->hWnd);
1891 #endif
1892 if (MenuHasFocus) {
1893 TrackPopupMenu(wndPtr->hSysMenu, TPM_LEFTBUTTON,
1894 rect.left, rect.top + SYSMETRICS_CYSIZE,
1895 0, hWnd, (LPRECT)NULL);
1897 else {
1898 MenuHasFocus = TRUE;
1899 TrackPopupMenu(wndPtr->hSysMenu, TPM_LEFTBUTTON,
1900 rect.left, rect.top + SYSMETRICS_CYSIZE,
1901 0, hWnd, (LPRECT)NULL);
1902 MenuHasFocus = FALSE;
1903 #ifdef DEBUG_MENU
1904 printf("NC_TrackSysMenu // before MenuFocusLoop !\n");
1905 #endif
1906 MenuFocusLoop(hWnd, NULL);
1907 #ifdef DEBUG_MENU
1908 printf("NC_TrackSysMenu // after MenuFocusLoop !\n");
1909 #endif
1912 else {
1913 ShowWindow(lpsys->hWnd, SW_HIDE);
1915 GlobalUnlock(wndPtr->hSysMenu);
1919 /**********************************************************************
1920 * GetMenuCheckMarkDimensions [USER.417]
1922 DWORD GetMenuCheckMarkDimensions()
1924 InitStdBitmaps();
1925 return MAKELONG( check_bitmap_width, check_bitmap_height );
1929 /**********************************************************************
1930 * SetMenuItemBitmaps [USER.418]
1932 BOOL SetMenuItemBitmaps(HMENU hMenu, WORD nPos, WORD wFlags,
1933 HBITMAP hNewCheck, HBITMAP hNewUnCheck)
1935 LPPOPUPMENU menu;
1936 LPMENUITEM lpitem;
1937 int i;
1938 #ifdef DEBUG_MENU
1939 printf("SetMenuItemBitmaps (%04X, %04X, %04X, %04X, %08X) !\n",
1940 hMenu, nPos, wFlags, hNewCheck, hNewUnCheck);
1941 #endif
1942 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1943 if (menu == NULL) return FALSE;
1944 lpitem = menu->firstItem;
1945 for (i = 0; i < menu->nItems; i++) {
1946 if (lpitem == NULL) break;
1947 if (i == nPos) {
1948 lpitem->hCheckBit = hNewCheck;
1949 lpitem->hUnCheckBit = hNewUnCheck;
1950 GlobalUnlock(hMenu);
1951 return TRUE;
1953 lpitem = (LPMENUITEM)lpitem->next;
1955 GlobalUnlock(hMenu);
1956 return FALSE;
1960 /**********************************************************************
1961 * CreateMenu [USER.151]
1963 HMENU CreateMenu()
1965 HANDLE hItem;
1966 HMENU hMenu;
1967 LPPOPUPMENU menu;
1968 #ifdef DEBUG_MENU
1969 printf("CreateMenu !\n");
1970 #endif
1971 hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
1972 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1973 if (menu == NULL) {
1974 GlobalFree(hMenu);
1975 return 0;
1977 menu->nItems = 0;
1978 menu->firstItem = NULL;
1979 menu->hWndPrev = 0;
1980 menu->ownerWnd = 0;
1981 menu->hWnd = 0;
1982 menu->hWndParent = 0;
1983 menu->MouseFlags = 0;
1984 menu->BarFlag = TRUE;
1985 menu->SysFlag = FALSE;
1986 menu->ChildFlag = TRUE;
1987 menu->Width = 100;
1988 menu->Height = 0;
1989 GlobalUnlock(hMenu);
1990 #ifdef DEBUG_MENU
1991 printf("CreateMenu // return %04X\n", hMenu);
1992 #endif
1993 return hMenu;
1997 /**********************************************************************
1998 * DestroyMenu [USER.152]
2000 BOOL DestroyMenu(HMENU hMenu)
2002 LPPOPUPMENU lppop;
2003 LPMENUITEM lpitem, lpitem2;
2004 #ifdef DEBUG_MENU
2005 printf("DestroyMenu (%04X) !\n", hMenu);
2006 #endif
2007 if (hMenu == 0) return FALSE;
2008 lppop = (LPPOPUPMENU) GlobalLock(hMenu);
2009 if (lppop == NULL) return FALSE;
2010 if (lppop->hWnd) DestroyWindow (lppop->hWnd);
2011 lpitem = lppop->firstItem;
2012 while (lpitem != NULL) {
2013 #ifdef DEBUG_MENU
2014 printf("DestroyMenu (%04X) // during loop items !\n", hMenu);
2015 #endif
2016 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
2017 DestroyMenu((HMENU)lpitem->item_id);
2019 lpitem = (LPMENUITEM)lpitem->next;
2021 GlobalUnlock(hMenu);
2022 GlobalFree(hMenu);
2023 #ifdef DEBUG_MENU
2024 printf("DestroyMenu (%04X) // End !\n", hMenu);
2025 #endif
2026 return TRUE;
2030 /**********************************************************************
2031 * LoadMenu [USER.150]
2033 HMENU LoadMenu(HINSTANCE instance, char *menu_name)
2035 HMENU hMenu;
2036 HANDLE hMenu_desc;
2037 MENU_HEADER *menu_desc;
2038 #ifdef DEBUG_MENU
2039 if ((LONG)menu_name & 0xFFFF0000L)
2040 printf("LoadMenu: instance %02x, menu '%s'\n", instance, menu_name);
2041 else
2042 printf("LoadMenu: instance %02x, menu '%04X'\n", instance, menu_name);
2043 #endif
2044 if (instance == (HANDLE)NULL) instance = hSysRes;
2045 if (menu_name == NULL ||
2046 (hMenu_desc = RSC_LoadMenu(instance, menu_name)) == 0 ||
2047 (menu_desc = (MENU_HEADER *) GlobalLock(hMenu_desc)) == NULL) {
2048 return 0;
2050 hMenu = LoadMenuIndirect((LPSTR)menu_desc);
2051 return hMenu;
2055 /**********************************************************************
2056 * GetSystemMenu [USER.156]
2058 HMENU GetSystemMenu(HWND hWnd, BOOL bRevert)
2060 WND *wndPtr;
2061 wndPtr = WIN_FindWndPtr(hWnd);
2062 if (!bRevert) {
2063 return wndPtr->hSysMenu;
2065 else {
2066 DestroyMenu(wndPtr->hSysMenu);
2067 wndPtr->hSysMenu = CopySysMenu();
2069 return wndPtr->hSysMenu;
2072 /**********************************************************************
2073 * SetSystemMenu [USER.280]
2075 BOOL SetSystemMenu(HWND hWnd, HMENU newHmenu)
2077 WND *wndPtr;
2079 if ((wndPtr = WIN_FindWndPtr(hWnd)) != NULL)
2080 wndPtr->hSysMenu = newHmenu;
2084 /**********************************************************************
2085 * GetMenu [USER.157]
2087 HMENU GetMenu(HWND hWnd)
2089 WND * wndPtr = WIN_FindWndPtr(hWnd);
2090 if (wndPtr == NULL) return 0;
2091 return wndPtr->wIDmenu;
2094 /**********************************************************************
2095 * SetMenu [USER.158]
2097 BOOL SetMenu(HWND hWnd, HMENU hMenu)
2099 RECT rect;
2100 LPPOPUPMENU lpmenu;
2101 WORD flags;
2102 WND * wndPtr = WIN_FindWndPtr(hWnd);
2103 if (wndPtr == NULL) {
2104 printf("SetMenu(%04X, %04X) // Bad window handle !\n", hWnd, hMenu);
2105 return FALSE;
2107 #ifdef DEBUG_MENU
2108 printf("SetMenu(%04X, %04X);\n", hWnd, hMenu);
2109 #endif
2110 if (GetCapture() == hWnd) ReleaseCapture();
2111 wndPtr->wIDmenu = hMenu;
2112 if (hMenu != 0)
2114 lpmenu = (LPPOPUPMENU) GlobalLock(hMenu);
2115 if (lpmenu == NULL) {
2116 printf("SetMenu(%04X, %04X) // Bad menu handle !\n", hWnd, hMenu);
2117 return FALSE;
2119 lpmenu->ownerWnd = hWnd;
2120 lpmenu->Height = 0; /* Make sure we recalculate the size */
2121 ResetHiliteFlags(lpmenu);
2122 GlobalUnlock(hMenu);
2124 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
2125 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
2126 return TRUE;
2131 /**********************************************************************
2132 * GetSubMenu [USER.159]
2134 HMENU GetSubMenu(HMENU hMenu, short nPos)
2136 HMENU hSubMenu;
2137 LPPOPUPMENU lppop;
2138 LPMENUITEM lpitem;
2139 int i;
2140 #ifdef DEBUG_MENU
2141 printf("GetSubMenu (%04X, %04X) !\n", hMenu, nPos);
2142 #endif
2143 if (hMenu == 0) return 0;
2144 lppop = (LPPOPUPMENU) GlobalLock(hMenu);
2145 if (lppop == NULL) return 0;
2146 lpitem = lppop->firstItem;
2147 for (i = 0; i < lppop->nItems; i++) {
2148 if (lpitem == NULL) break;
2149 if (i == nPos) {
2150 #ifdef DEBUG_MENU
2151 printf(" found %04x\n", lpitem->item_id);
2152 #endif
2153 if (lpitem->item_flags & MF_POPUP)
2154 return lpitem->item_id;
2155 else
2156 return 0;
2158 lpitem = (LPMENUITEM)lpitem->next;
2160 return 0;
2164 /**********************************************************************
2165 * DrawMenuBar [USER.160]
2167 void DrawMenuBar(HWND hWnd)
2169 WND *wndPtr;
2170 LPPOPUPMENU lppop;
2171 #ifdef DEBUG_MENU
2172 printf("DrawMenuBar (%04X)\n", hWnd);
2173 #endif
2174 wndPtr = WIN_FindWndPtr(hWnd);
2175 if (wndPtr != NULL && (wndPtr->dwStyle & WS_CHILD) == 0 &&
2176 wndPtr->wIDmenu != 0) {
2177 #ifdef DEBUG_MENU
2178 printf("DrawMenuBar wIDmenu=%04X \n", wndPtr->wIDmenu);
2179 #endif
2180 lppop = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu);
2181 if (lppop == NULL) return;
2183 lppop->Height = 0; /* Make sure we call MENU_MenuBarCalcSize */
2184 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
2185 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
2186 GlobalUnlock(wndPtr->wIDmenu);
2191 /**********************************************************************
2192 * LoadMenuIndirect [USER.220]
2194 HMENU LoadMenuIndirect(LPSTR menu_template)
2196 HMENU hMenu;
2197 MENU_HEADER *menu_desc;
2198 LPPOPUPMENU lppop;
2199 #ifdef DEBUG_MENU
2200 printf("LoadMenuIndirect: menu_template '%08X'\n", menu_template);
2201 #endif
2202 hMenu = CreateMenu();
2203 menu_desc = (MENU_HEADER *)menu_template;
2204 ParseMenuResource((WORD *)(menu_desc + 1), 0, hMenu);
2205 lppop = (LPPOPUPMENU) GlobalLock(hMenu);
2206 ResetHiliteFlags(lppop);
2207 GlobalUnlock(hMenu);
2208 return hMenu;
2212 /**********************************************************************
2213 * InitStdBitmaps (Internal)
2215 void InitStdBitmaps()
2217 BITMAP bm;
2218 if (hStdCheck == (HBITMAP)NULL)
2220 hStdCheck = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_CHECK);
2221 GetObject( hStdCheck, sizeof(BITMAP), (LPSTR)&bm );
2222 check_bitmap_width = bm.bmWidth;
2223 check_bitmap_height = bm.bmHeight;
2225 if (hStdMnArrow == (HBITMAP)NULL)
2227 hStdMnArrow = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_MNARROW);
2228 GetObject( hStdMnArrow, sizeof(BITMAP), (LPSTR)&bm );
2229 arrow_bitmap_width = bm.bmWidth;
2230 arrow_bitmap_height = bm.bmHeight;
2235 /**********************************************************************
2236 * CopySysMenu (Internal)
2238 HMENU CopySysMenu()
2240 HMENU hMenu;
2241 LPPOPUPMENU menu;
2242 LPPOPUPMENU sysmenu;
2243 #ifdef DEBUG_MENU
2244 printf("CopySysMenu entry !\n");
2245 #endif
2246 if (hSysMenu == 0) {
2247 /* hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(1)); */
2248 /* hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(SC_SYSMENU));*/
2249 hSysMenu = LoadMenu((HINSTANCE)NULL, "SYSMENU");
2250 if (hSysMenu == 0) {
2251 printf("SysMenu not found in system resources !\n");
2252 return (HMENU)NULL;
2254 #ifdef DEBUG_MENU
2255 else
2256 printf("SysMenu loaded from system resources %04X !\n", hSysMenu);
2257 #endif
2259 hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
2260 menu = (LPPOPUPMENU) GlobalLock(hMenu);
2261 sysmenu = (LPPOPUPMENU) GlobalLock(hSysMenu);
2262 if (menu != NULL && sysmenu != NULL) {
2263 sysmenu->BarFlag = FALSE;
2264 sysmenu->SysFlag = TRUE;
2265 memcpy(menu, sysmenu, sizeof(POPUPMENU));
2267 else {
2268 printf("CopySysMenu // Bad SysMenu pointers !\n");
2269 if (menu != NULL) {
2270 GlobalUnlock(hMenu);
2271 GlobalFree(hMenu);
2273 return (HMENU)NULL;
2275 GlobalUnlock(hMenu);
2276 GlobalUnlock(hSysMenu);
2277 #ifdef DEBUG_MENU
2278 printf("CopySysMenu hMenu=%04X !\n", hMenu);
2279 #endif
2280 return hMenu;
2284 /**********************************************************************
2285 * ParseMenuResource (from Resource or Template)
2287 WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu)
2289 WORD *item;
2290 WORD *next_item;
2291 HMENU hSubMenu;
2292 int i;
2294 level++;
2295 next_item = first_item;
2296 i = 0;
2297 do {
2298 i++;
2299 item = next_item;
2300 if (*item & MF_POPUP) {
2301 MENU_POPUPITEM *popup_item = (MENU_POPUPITEM *) item;
2302 next_item = (WORD *) (popup_item->item_text +
2303 strlen(popup_item->item_text) + 1);
2304 hSubMenu = CreatePopupMenu();
2305 next_item = ParseMenuResource(next_item, level, hSubMenu);
2306 AppendMenu(hMenu, popup_item->item_flags,
2307 hSubMenu, popup_item->item_text);
2309 else {
2310 MENUITEMTEMPLATE *normal_item = (MENUITEMTEMPLATE *) item;
2311 next_item = (WORD *) (normal_item->item_text +
2312 strlen(normal_item->item_text) + 1);
2313 if (strlen(normal_item->item_text) == 0 && normal_item->item_id == 0)
2314 normal_item->item_flags |= MF_SEPARATOR;
2315 AppendMenu(hMenu, normal_item->item_flags,
2316 normal_item->item_id, normal_item->item_text);
2319 while (!(*item & MF_END));
2320 return next_item;
2323 /**********************************************************************
2324 * IsMenu(USER.358)
2326 BOOL IsMenu(HMENU hMenu)
2328 LPPOPUPMENU menu;
2330 menu = (LPPOPUPMENU) GlobalLock(hMenu);
2331 if (menu == NULL)
2332 return FALSE;
2334 GlobalUnlock(hMenu);
2335 return TRUE;