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, &notbuttons); 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, &notbuttons); 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)