Mercurial > emacs
comparison src/w32menu.c @ 27932:a590f8d0dbd2
[HAVE_BOXES]: Remove #undef.
(single_keymap_panes): Remove code for simulating checkmarks.
(single_menu_item): Remove notbuttons_ptr argument. Callers changed.
Remove code for drawing simulated checkmarks.
(w32_menu_show): make unibyte help string correctly.
(add_menu_item): draw standard Windows checkmarks. Draw radio buttons
as radio buttons if possible.
author | Jason Rumney <jasonr@gnu.org> |
---|---|
date | Wed, 01 Mar 2000 20:49:16 +0000 |
parents | 75f296b1a872 |
children | 2c8492145fc8 |
comparison
equal
deleted
inserted
replaced
27931:2111ac6eed6d | 27932:a590f8d0dbd2 |
---|---|
41 #endif | 41 #endif |
42 | 42 |
43 #include "dispextern.h" | 43 #include "dispextern.h" |
44 | 44 |
45 #undef HAVE_MULTILINGUAL_MENU | 45 #undef HAVE_MULTILINGUAL_MENU |
46 #undef HAVE_BOXES /* NTEMACS_TODO: Fix native checkmarks and radios. */ | 46 #undef HAVE_DIALOGS /* NTEMACS_TODO: Implement native dialogs. */ |
47 #undef HAVE_DIALOGS /* NTEMACS_TODO: Fix native dialogs. */ | |
48 | 47 |
49 /******************************************************************/ | 48 /******************************************************************/ |
50 /* Definitions copied from lwlib.h */ | 49 /* Definitions copied from lwlib.h */ |
51 | 50 |
52 typedef void * XtPointer; | 51 typedef void * XtPointer; |
431 int maxdepth; | 430 int maxdepth; |
432 { | 431 { |
433 Lisp_Object pending_maps = Qnil; | 432 Lisp_Object pending_maps = Qnil; |
434 Lisp_Object tail, item; | 433 Lisp_Object tail, item; |
435 struct gcpro gcpro1, gcpro2; | 434 struct gcpro gcpro1, gcpro2; |
436 int notbuttons = 0; | |
437 | 435 |
438 if (maxdepth <= 0) | 436 if (maxdepth <= 0) |
439 return; | 437 return; |
440 | 438 |
441 push_menu_pane (pane_name, prefix); | 439 push_menu_pane (pane_name, prefix); |
442 | |
443 #ifndef HAVE_BOXES | |
444 /* Remember index for first item in this pane so we can go back and | |
445 add a prefix when (if) we see the first button. After that, notbuttons | |
446 is set to 0, to mark that we have seen a button and all non button | |
447 items need a prefix. */ | |
448 notbuttons = menu_items_used; | |
449 #endif | |
450 | 440 |
451 for (tail = keymap; CONSP (tail); tail = XCDR (tail)) | 441 for (tail = keymap; CONSP (tail); tail = XCDR (tail)) |
452 { | 442 { |
453 GCPRO2 (keymap, pending_maps); | 443 GCPRO2 (keymap, pending_maps); |
454 /* Look at each key binding, and if it is a menu item add it | 444 /* Look at each key binding, and if it is a menu item add it |
455 to this menu. */ | 445 to this menu. */ |
456 item = XCAR (tail); | 446 item = XCAR (tail); |
457 if (CONSP (item)) | 447 if (CONSP (item)) |
458 single_menu_item (XCAR (item), XCDR (item), | 448 single_menu_item (XCAR (item), XCDR (item), |
459 &pending_maps, notreal, maxdepth, ¬buttons); | 449 &pending_maps, notreal, maxdepth); |
460 else if (VECTORP (item)) | 450 else if (VECTORP (item)) |
461 { | 451 { |
462 /* Loop over the char values represented in the vector. */ | 452 /* Loop over the char values represented in the vector. */ |
463 int len = XVECTOR (item)->size; | 453 int len = XVECTOR (item)->size; |
464 int c; | 454 int c; |
465 for (c = 0; c < len; c++) | 455 for (c = 0; c < len; c++) |
466 { | 456 { |
467 Lisp_Object character; | 457 Lisp_Object character; |
468 XSETFASTINT (character, c); | 458 XSETFASTINT (character, c); |
469 single_menu_item (character, XVECTOR (item)->contents[c], | 459 single_menu_item (character, XVECTOR (item)->contents[c], |
470 &pending_maps, notreal, maxdepth, ¬buttons); | 460 &pending_maps, notreal, maxdepth); |
471 } | 461 } |
472 } | 462 } |
473 UNGCPRO; | 463 UNGCPRO; |
474 } | 464 } |
475 | 465 |
493 KEY is a key in a keymap and ITEM is its binding. | 483 KEY is a key in a keymap and ITEM is its binding. |
494 PENDING_MAPS_PTR points to a list of keymaps waiting to be made into | 484 PENDING_MAPS_PTR points to a list of keymaps waiting to be made into |
495 separate panes. | 485 separate panes. |
496 If NOTREAL is nonzero, only check for equivalent key bindings, don't | 486 If NOTREAL is nonzero, only check for equivalent key bindings, don't |
497 evaluate expressions in menu items and don't make any menu. | 487 evaluate expressions in menu items and don't make any menu. |
498 If we encounter submenus deeper than MAXDEPTH levels, ignore them. | 488 If we encounter submenus deeper than MAXDEPTH levels, ignore them. */ |
499 NOTBUTTONS_PTR is only used when simulating toggle boxes and radio | |
500 buttons. It points to variable notbuttons in single_keymap_panes, | |
501 which keeps track of if we have seen a button in this menu or not. */ | |
502 | 489 |
503 static void | 490 static void |
504 single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth, | 491 single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth) |
505 notbuttons_ptr) | |
506 Lisp_Object key, item; | 492 Lisp_Object key, item; |
507 Lisp_Object *pending_maps_ptr; | 493 Lisp_Object *pending_maps_ptr; |
508 int maxdepth, notreal; | 494 int maxdepth, notreal; |
509 int *notbuttons_ptr; | |
510 { | 495 { |
511 Lisp_Object map, item_string, enabled; | 496 Lisp_Object map, item_string, enabled; |
512 struct gcpro gcpro1, gcpro2; | 497 struct gcpro gcpro1, gcpro2; |
513 int res; | 498 int res; |
514 | 499 |
540 *pending_maps_ptr = Fcons (Fcons (map, Fcons (item_string, key)), | 525 *pending_maps_ptr = Fcons (Fcons (map, Fcons (item_string, key)), |
541 *pending_maps_ptr); | 526 *pending_maps_ptr); |
542 return; | 527 return; |
543 } | 528 } |
544 | 529 |
545 #ifndef HAVE_BOXES | |
546 /* Simulate radio buttons and toggle boxes by putting a prefix in | |
547 front of them. */ | |
548 { | |
549 Lisp_Object prefix = Qnil; | |
550 Lisp_Object type = XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE]; | |
551 if (!NILP (type)) | |
552 { | |
553 Lisp_Object selected | |
554 = XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED]; | |
555 | |
556 if (*notbuttons_ptr) | |
557 /* The first button. Line up previous items in this menu. */ | |
558 { | |
559 int index = *notbuttons_ptr; /* Index for first item this menu. */ | |
560 int submenu = 0; | |
561 Lisp_Object tem; | |
562 while (index < menu_items_used) | |
563 { | |
564 tem | |
565 = XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME]; | |
566 if (NILP (tem)) | |
567 { | |
568 index++; | |
569 submenu++; /* Skip sub menu. */ | |
570 } | |
571 else if (EQ (tem, Qlambda)) | |
572 { | |
573 index++; | |
574 submenu--; /* End sub menu. */ | |
575 } | |
576 else if (EQ (tem, Qt)) | |
577 index += 3; /* Skip new pane marker. */ | |
578 else if (EQ (tem, Qquote)) | |
579 index++; /* Skip a left, right divider. */ | |
580 else | |
581 { | |
582 if (!submenu && XSTRING (tem)->data[0] != '\0' | |
583 && XSTRING (tem)->data[0] != '-') | |
584 XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME] | |
585 = concat2 (build_string (" "), tem); | |
586 index += MENU_ITEMS_ITEM_LENGTH; | |
587 } | |
588 } | |
589 *notbuttons_ptr = 0; | |
590 } | |
591 | |
592 /* Calculate prefix, if any, for this item. */ | |
593 if (EQ (type, QCtoggle)) | |
594 prefix = build_string (NILP (selected) ? "[ ] " : "[X] "); | |
595 else if (EQ (type, QCradio)) | |
596 prefix = build_string (NILP (selected) ? "( ) " : "(*) "); | |
597 } | |
598 /* Not a button. If we have earlier buttons, then we need a prefix. */ | |
599 else if (!*notbuttons_ptr && XSTRING (item_string)->data[0] != '\0' | |
600 && XSTRING (item_string)->data[0] != '-') | |
601 prefix = build_string (" "); | |
602 | |
603 if (!NILP (prefix)) | |
604 item_string = concat2 (prefix, item_string); | |
605 } | |
606 #endif /* HAVE_BOXES */ | |
607 | |
608 #if 0 | |
609 if (!NILP(map)) | |
610 /* Indicate visually that this is a submenu. */ | |
611 item_string = concat2 (item_string, build_string (" >")); | |
612 #endif | |
613 | |
614 push_menu_item (item_string, enabled, key, | 530 push_menu_item (item_string, enabled, key, |
615 XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF], | 531 XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF], |
616 XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ], | 532 XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ], |
617 XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE], | 533 XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE], |
618 XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED], | 534 XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED], |
619 XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]); | 535 XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]); |
620 | 536 |
621 #if 1 | |
622 /* Display a submenu using the toolkit. */ | 537 /* Display a submenu using the toolkit. */ |
623 if (! (NILP (map) || NILP (enabled))) | 538 if (! (NILP (map) || NILP (enabled))) |
624 { | 539 { |
625 push_submenu_start (); | 540 push_submenu_start (); |
626 single_keymap_panes (map, Qnil, key, 0, maxdepth - 1); | 541 single_keymap_panes (map, Qnil, key, 0, maxdepth - 1); |
627 push_submenu_end (); | 542 push_submenu_end (); |
628 } | 543 } |
629 #endif | |
630 } | 544 } |
631 | 545 |
632 /* Push all the panes and items of a menu described by the | 546 /* Push all the panes and items of a menu described by the |
633 alist-of-alists MENU. | 547 alist-of-alists MENU. |
634 This handles old-fashioned calls to x-popup-menu. */ | 548 This handles old-fashioned calls to x-popup-menu. */ |
1767 if (STRINGP (item_name) && STRING_MULTIBYTE (item_name)) | 1681 if (STRINGP (item_name) && STRING_MULTIBYTE (item_name)) |
1768 item_name = string_make_unibyte (item_name); | 1682 item_name = string_make_unibyte (item_name); |
1769 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) | 1683 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) |
1770 descrip = string_make_unibyte (descrip); | 1684 descrip = string_make_unibyte (descrip); |
1771 if (STRINGP (help) && STRING_MULTIBYTE (help)) | 1685 if (STRINGP (help) && STRING_MULTIBYTE (help)) |
1772 help_string = string_make_unibyte (help); | 1686 help = string_make_unibyte (help); |
1773 #endif | 1687 #endif |
1774 | 1688 |
1775 help_string = STRINGP (help) ? XSTRING (help)->data : NULL; | 1689 help_string = STRINGP (help) ? XSTRING (help)->data : NULL; |
1776 | 1690 |
1777 wv = xmalloc_widget_value (); | 1691 wv = xmalloc_widget_value (); |
2124 static int | 2038 static int |
2125 add_menu_item (HMENU menu, widget_value *wv, HMENU item) | 2039 add_menu_item (HMENU menu, widget_value *wv, HMENU item) |
2126 { | 2040 { |
2127 UINT fuFlags; | 2041 UINT fuFlags; |
2128 char *out_string; | 2042 char *out_string; |
2043 int return_value; | |
2129 | 2044 |
2130 if (name_is_separator (wv->name)) | 2045 if (name_is_separator (wv->name)) |
2131 fuFlags = MF_SEPARATOR; | 2046 fuFlags = MF_SEPARATOR; |
2132 else | 2047 else |
2133 { | 2048 { |
2153 strcpy (out_string, wv->name); | 2068 strcpy (out_string, wv->name); |
2154 #endif | 2069 #endif |
2155 fuFlags = MF_OWNERDRAW | MF_DISABLED; | 2070 fuFlags = MF_OWNERDRAW | MF_DISABLED; |
2156 } | 2071 } |
2157 | 2072 |
2158 #ifdef HAVE_BOXES | |
2159 /* Draw radio buttons and tickboxes. */ | 2073 /* Draw radio buttons and tickboxes. */ |
2160 { | 2074 { |
2161 switch (wv->button_type) | 2075 if (wv->selected && (wv->button_type == BUTTON_TYPE_TOGGLE || |
2162 { | 2076 wv->button_type == BUTTON_TYPE_RADIO)) |
2163 case BUTTON_TYPE_TOGGLE: | 2077 fuFlags |= MF_CHECKED; |
2164 CheckMenuItem (menu, (UINT)item, | 2078 else |
2165 wv->selected ? MF_CHECKED : MF_UNCHECKED); | 2079 fuFlags |= MF_UNCHECKED; |
2166 break; | |
2167 | |
2168 case BUTTON_TYPE_RADIO: | |
2169 /* CheckMenuRadioItem does not exist on NT 3.51 and | |
2170 earlier. Fallback on CheckMenuItem. */ | |
2171 { | |
2172 HMODULE user32 = GetModuleHandle ("user32.dll"); | |
2173 FARPROC set_menu_item_info | |
2174 = GetProcAddress (user32, "SetMenuItemInfo"); | |
2175 if (set_menu_item_info) | |
2176 { | |
2177 MENUITEMINFO info; | |
2178 bzero (&info, sizeof (info)); | |
2179 info.cbSize = sizeof (info); | |
2180 info.fMask = MIIM_TYPE | MIIM_STATE; | |
2181 info.fType = MFT_RADIOCHECK; | |
2182 info.fState = wv->selected ? MFS_CHECKED : MFS_UNCHECKED; | |
2183 | |
2184 set_menu_item_info (menu, item, FALSE, &info); | |
2185 } | |
2186 else | |
2187 CheckMenuItem (menu, (UINT)item, wv->selected ? | |
2188 MF_CHECKED : MF_UNCHECKED); | |
2189 } | |
2190 break; | |
2191 | |
2192 default: | |
2193 CheckMenuItem (menu, (UINT)item, MF_UNCHECKED); | |
2194 break; | |
2195 } | |
2196 } | 2080 } |
2197 #endif | 2081 } |
2198 } | |
2199 | |
2200 if (item != NULL) | 2082 if (item != NULL) |
2201 fuFlags = MF_POPUP; | 2083 fuFlags = MF_POPUP; |
2202 | 2084 |
2203 return AppendMenu (menu, | 2085 return_value = |
2204 fuFlags, | 2086 AppendMenu (menu, |
2205 item != NULL ? (UINT) item : (UINT) wv->call_data, | 2087 fuFlags, |
2206 (fuFlags == MF_SEPARATOR) ? NULL: out_string ); | 2088 item != NULL ? (UINT) item : (UINT) wv->call_data, |
2089 (fuFlags == MF_SEPARATOR) ? NULL: out_string ); | |
2090 | |
2091 /* This must be done after the menu item is created. */ | |
2092 if (wv->button_type == BUTTON_TYPE_RADIO) | |
2093 { | |
2094 /* CheckMenuRadioItem allows us to differentiate TOGGLE and | |
2095 RADIO items, but is not available on NT 3.51 and earlier. */ | |
2096 HMODULE user32 = GetModuleHandle ("user32.dll"); | |
2097 FARPROC set_menu_item_info = GetProcAddress (user32, "SetMenuItemInfo"); | |
2098 | |
2099 if (set_menu_item_info) | |
2100 { | |
2101 MENUITEMINFO info; | |
2102 bzero (&info, sizeof (info)); | |
2103 info.cbSize = sizeof (info); | |
2104 info.fMask = MIIM_TYPE | MIIM_STATE; | |
2105 info.fType = MFT_RADIOCHECK; | |
2106 info.fState = wv->selected ? MFS_CHECKED : MFS_UNCHECKED; | |
2107 set_menu_item_info (menu, item, FALSE, &info); | |
2108 } | |
2109 } | |
2110 | |
2111 return return_value; | |
2207 } | 2112 } |
2208 | 2113 |
2209 /* Construct native Windows menu(bar) based on widget_value tree. */ | 2114 /* Construct native Windows menu(bar) based on widget_value tree. */ |
2210 static int | 2115 static int |
2211 fill_in_menu (HMENU menu, widget_value *wv) | 2116 fill_in_menu (HMENU menu, widget_value *wv) |