aboutsummaryrefslogtreecommitdiffstats
path: root/src/macmenu.c
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu2005-12-21 12:31:02 +0000
committerYAMAMOTO Mitsuharu2005-12-21 12:31:02 +0000
commit4036ffb904fd5a68a739297f7d4a30cdfc2f6f97 (patch)
tree0e9f652a053cc70b1fff985340d11fa6057374c4 /src/macmenu.c
parent3150fbfcca4b29a5408c9be07c14d8edc3debbca (diff)
downloademacs-4036ffb904fd5a68a739297f7d4a30cdfc2f6f97.tar.gz
emacs-4036ffb904fd5a68a739297f7d4a30cdfc2f6f97.zip
(Qmac_apple_event): Add extern.
(set_frame_menubar, mac_menu_show keymp_panes) (single_keymap_panes, list_of_panes, list_of_item) (single_menu_item): Add argument types to prototypes. (mac_dialog_show) [HAVE_DIALOGS]: Likewise. (struct skp): New struct (from xmenu.c). (single_keymap_panes, single_menu_item, list_of_panes) (list_of_item): Sync with xmenu.c. (Fx_popup_menu, Fx_popup_dialog): Likewise. Don't get window from POSITION if it is mac-apple-event event. (menubar_selection_callback): Don't use menu_command_in_progress. (set_frame_menubar): First parse all submenus, then make widget_value trees from them. Don't allocate any widget_value objects until we are done with the parsing. (parse_single_submenu, digest_single_submenu): New functions. (single_submenu): Function deleted, replaced by those two. (install_menu_quit_handler) [HAVE_CANCELMENUTRACKING]: Don't create or dispose of EventHandlerUPP. Install hander to all submenus. (mac_menu_show) [!HAVE_MULTILINGUAL_MENU]: Use ENCODE_MENU_STRING instead of ENCODE_SYSTEM. (free_frame_menubar, fill_submenu, fill_menu): Don't use NULL for integer values. [HAVE_DIALOGS] (mac_dialog_show): Sync with xdialog_show (in xmenu.c). (add_menu_item) [TARGET_API_MAC_CARBON]: Use CFString functions to format menu item string. Don't use NULL for integer value.
Diffstat (limited to 'src/macmenu.c')
-rw-r--r--src/macmenu.c445
1 files changed, 258 insertions, 187 deletions
diff --git a/src/macmenu.c b/src/macmenu.c
index 064cec57486..1b132407df7 100644
--- a/src/macmenu.c
+++ b/src/macmenu.c
@@ -1,4 +1,4 @@
1/* Menu support for GNU Emacs on the for Mac OS. 1/* Menu support for GNU Emacs on Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005 Free Software Foundation, Inc. 3 2005 Free Software Foundation, Inc.
4 4
@@ -24,6 +24,7 @@ Boston, MA 02110-1301, USA. */
24#include <config.h> 24#include <config.h>
25 25
26#include <stdio.h> 26#include <stdio.h>
27
27#include "lisp.h" 28#include "lisp.h"
28#include "termhooks.h" 29#include "termhooks.h"
29#include "keyboard.h" 30#include "keyboard.h"
@@ -154,7 +155,7 @@ Lisp_Object Vmenu_updating_frame;
154 155
155Lisp_Object Qdebug_on_next_call; 156Lisp_Object Qdebug_on_next_call;
156 157
157extern Lisp_Object Qmenu_bar; 158extern Lisp_Object Qmenu_bar, Qmac_apple_event;
158 159
159extern Lisp_Object QCtoggle, QCradio; 160extern Lisp_Object QCtoggle, QCradio;
160 161
@@ -165,27 +166,28 @@ extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
165 166
166extern Lisp_Object Qmenu_bar_update_hook; 167extern Lisp_Object Qmenu_bar_update_hook;
167 168
169void set_frame_menubar P_ ((FRAME_PTR, int, int));
170
168#if TARGET_API_MAC_CARBON 171#if TARGET_API_MAC_CARBON
169#define ENCODE_MENU_STRING(str) ENCODE_UTF_8 (str) 172#define ENCODE_MENU_STRING(str) ENCODE_UTF_8 (str)
170#else 173#else
171#define ENCODE_MENU_STRING(str) ENCODE_SYSTEM (str) 174#define ENCODE_MENU_STRING(str) ENCODE_SYSTEM (str)
172#endif 175#endif
173 176
174void set_frame_menubar ();
175
176static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object, 177static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
177 Lisp_Object, Lisp_Object, Lisp_Object, 178 Lisp_Object, Lisp_Object, Lisp_Object,
178 Lisp_Object, Lisp_Object)); 179 Lisp_Object, Lisp_Object));
179#ifdef HAVE_DIALOGS 180#ifdef HAVE_DIALOGS
180static Lisp_Object mac_dialog_show (); 181static Lisp_Object mac_dialog_show P_ ((FRAME_PTR, int, Lisp_Object,
182 Lisp_Object, char **));
181#endif 183#endif
182static Lisp_Object mac_menu_show (); 184static Lisp_Object mac_menu_show P_ ((struct frame *, int, int, int, int,
183 185 Lisp_Object, char **));
184static void keymap_panes (); 186static void keymap_panes P_ ((Lisp_Object *, int, int));
185static void single_keymap_panes (); 187static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
186static void single_menu_item (); 188 int, int));
187static void list_of_panes (); 189static void list_of_panes P_ ((Lisp_Object));
188static void list_of_items (); 190static void list_of_items P_ ((Lisp_Object));
189 191
190static void fill_submenu (MenuHandle, widget_value *); 192static void fill_submenu (MenuHandle, widget_value *);
191static void fill_menubar (widget_value *); 193static void fill_menubar (widget_value *);
@@ -280,8 +282,7 @@ init_menu_items ()
280 menu_items_submenu_depth = 0; 282 menu_items_submenu_depth = 0;
281} 283}
282 284
283/* Call at the end of generating the data in menu_items. 285/* Call at the end of generating the data in menu_items. */
284 This fills in the number of items in the last pane. */
285 286
286static void 287static void
287finish_menu_items () 288finish_menu_items ()
@@ -415,11 +416,21 @@ keymap_panes (keymaps, nmaps, notreal)
415 P is the number of panes we have made so far. */ 416 P is the number of panes we have made so far. */
416 for (mapno = 0; mapno < nmaps; mapno++) 417 for (mapno = 0; mapno < nmaps; mapno++)
417 single_keymap_panes (keymaps[mapno], 418 single_keymap_panes (keymaps[mapno],
418 Fkeymap_prompt (keymaps[mapno]), Qnil, notreal, 10); 419 Fkeymap_prompt (keymaps[mapno]), Qnil, notreal, 10);
419 420
420 finish_menu_items (); 421 finish_menu_items ();
421} 422}
422 423
424/* Args passed between single_keymap_panes and single_menu_item. */
425struct skp
426 {
427 Lisp_Object pending_maps;
428 int maxdepth, notreal;
429 };
430
431static void single_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
432 void *));
433
423/* This is a recursive subroutine of keymap_panes. 434/* This is a recursive subroutine of keymap_panes.
424 It handles one keymap, KEYMAP. 435 It handles one keymap, KEYMAP.
425 The other arguments are passed along 436 The other arguments are passed along
@@ -437,89 +448,71 @@ single_keymap_panes (keymap, pane_name, prefix, notreal, maxdepth)
437 int notreal; 448 int notreal;
438 int maxdepth; 449 int maxdepth;
439{ 450{
440 Lisp_Object pending_maps = Qnil; 451 struct skp skp;
441 Lisp_Object tail, item; 452 struct gcpro gcpro1;
442 struct gcpro gcpro1, gcpro2; 453
454 skp.pending_maps = Qnil;
455 skp.maxdepth = maxdepth;
456 skp.notreal = notreal;
443 457
444 if (maxdepth <= 0) 458 if (maxdepth <= 0)
445 return; 459 return;
446 460
447 push_menu_pane (pane_name, prefix); 461 push_menu_pane (pane_name, prefix);
448 462
449 for (tail = keymap; CONSP (tail); tail = XCDR (tail)) 463 GCPRO1 (skp.pending_maps);
450 { 464 map_keymap (keymap, single_menu_item, Qnil, &skp, 1);
451 GCPRO2 (keymap, pending_maps); 465 UNGCPRO;
452 /* Look at each key binding, and if it is a menu item add it
453 to this menu. */
454 item = XCAR (tail);
455 if (CONSP (item))
456 single_menu_item (XCAR (item), XCDR (item),
457 &pending_maps, notreal, maxdepth);
458 else if (VECTORP (item))
459 {
460 /* Loop over the char values represented in the vector. */
461 int len = XVECTOR (item)->size;
462 int c;
463 for (c = 0; c < len; c++)
464 {
465 Lisp_Object character;
466 XSETFASTINT (character, c);
467 single_menu_item (character, XVECTOR (item)->contents[c],
468 &pending_maps, notreal, maxdepth);
469 }
470 }
471 UNGCPRO;
472 }
473 466
474 /* Process now any submenus which want to be panes at this level. */ 467 /* Process now any submenus which want to be panes at this level. */
475 while (!NILP (pending_maps)) 468 while (CONSP (skp.pending_maps))
476 { 469 {
477 Lisp_Object elt, eltcdr, string; 470 Lisp_Object elt, eltcdr, string;
478 elt = Fcar (pending_maps); 471 elt = XCAR (skp.pending_maps);
479 eltcdr = XCDR (elt); 472 eltcdr = XCDR (elt);
480 string = XCAR (eltcdr); 473 string = XCAR (eltcdr);
481 /* We no longer discard the @ from the beginning of the string here. 474 /* We no longer discard the @ from the beginning of the string here.
482 Instead, we do this in mac_menu_show. */ 475 Instead, we do this in mac_menu_show. */
483 single_keymap_panes (Fcar (elt), string, 476 single_keymap_panes (Fcar (elt), string,
484 XCDR (eltcdr), notreal, maxdepth - 1); 477 XCDR (eltcdr), notreal, maxdepth - 1);
485 pending_maps = Fcdr (pending_maps); 478 skp.pending_maps = XCDR (skp.pending_maps);
486 } 479 }
487} 480}
488 481
489/* This is a subroutine of single_keymap_panes that handles one 482/* This is a subroutine of single_keymap_panes that handles one
490 keymap entry. 483 keymap entry.
491 KEY is a key in a keymap and ITEM is its binding. 484 KEY is a key in a keymap and ITEM is its binding.
492 PENDING_MAPS_PTR points to a list of keymaps waiting to be made into 485 SKP->PENDING_MAPS_PTR is a list of keymaps waiting to be made into
493 separate panes. 486 separate panes.
494 If NOTREAL is nonzero, only check for equivalent key bindings, don't 487 If SKP->NOTREAL is nonzero, only check for equivalent key bindings, don't
495 evaluate expressions in menu items and don't make any menu. 488 evaluate expressions in menu items and don't make any menu.
496 If we encounter submenus deeper than MAXDEPTH levels, ignore them. */ 489 If we encounter submenus deeper than SKP->MAXDEPTH levels, ignore them. */
497 490
498static void 491static void
499single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth) 492single_menu_item (key, item, dummy, skp_v)
500 Lisp_Object key, item; 493 Lisp_Object key, item, dummy;
501 Lisp_Object *pending_maps_ptr; 494 void *skp_v;
502 int maxdepth, notreal;
503{ 495{
504 Lisp_Object map, item_string, enabled; 496 Lisp_Object map, item_string, enabled;
505 struct gcpro gcpro1, gcpro2; 497 struct gcpro gcpro1, gcpro2;
506 int res; 498 int res;
499 struct skp *skp = skp_v;
507 500
508 /* Parse the menu item and leave the result in item_properties. */ 501 /* Parse the menu item and leave the result in item_properties. */
509 GCPRO2 (key, item); 502 GCPRO2 (key, item);
510 res = parse_menu_item (item, notreal, 0); 503 res = parse_menu_item (item, skp->notreal, 0);
511 UNGCPRO; 504 UNGCPRO;
512 if (!res) 505 if (!res)
513 return; /* Not a menu item. */ 506 return; /* Not a menu item. */
514 507
515 map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP]; 508 map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP];
516 509
517 if (notreal) 510 if (skp->notreal)
518 { 511 {
519 /* We don't want to make a menu, just traverse the keymaps to 512 /* We don't want to make a menu, just traverse the keymaps to
520 precompute equivalent key bindings. */ 513 precompute equivalent key bindings. */
521 if (!NILP (map)) 514 if (!NILP (map))
522 single_keymap_panes (map, Qnil, key, 1, maxdepth - 1); 515 single_keymap_panes (map, Qnil, key, 1, skp->maxdepth - 1);
523 return; 516 return;
524 } 517 }
525 518
@@ -530,8 +523,8 @@ single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth)
530 { 523 {
531 if (!NILP (enabled)) 524 if (!NILP (enabled))
532 /* An enabled separate pane. Remember this to handle it later. */ 525 /* An enabled separate pane. Remember this to handle it later. */
533 *pending_maps_ptr = Fcons (Fcons (map, Fcons (item_string, key)), 526 skp->pending_maps = Fcons (Fcons (map, Fcons (item_string, key)),
534 *pending_maps_ptr); 527 skp->pending_maps);
535 return; 528 return;
536 } 529 }
537 530
@@ -539,14 +532,14 @@ single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth)
539 XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF], 532 XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF],
540 XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ], 533 XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ],
541 XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE], 534 XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE],
542 XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED], 535 XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
543 XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]); 536 XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
544 537
545 /* Display a submenu using the toolkit. */ 538 /* Display a submenu using the toolkit. */
546 if (! (NILP (map) || NILP (enabled))) 539 if (! (NILP (map) || NILP (enabled)))
547 { 540 {
548 push_submenu_start (); 541 push_submenu_start ();
549 single_keymap_panes (map, Qnil, key, 0, maxdepth - 1); 542 single_keymap_panes (map, Qnil, key, 0, skp->maxdepth - 1);
550 push_submenu_end (); 543 push_submenu_end ();
551 } 544 }
552} 545}
@@ -563,13 +556,13 @@ list_of_panes (menu)
563 556
564 init_menu_items (); 557 init_menu_items ();
565 558
566 for (tail = menu; !NILP (tail); tail = Fcdr (tail)) 559 for (tail = menu; CONSP (tail); tail = XCDR (tail))
567 { 560 {
568 Lisp_Object elt, pane_name, pane_data; 561 Lisp_Object elt, pane_name, pane_data;
569 elt = Fcar (tail); 562 elt = XCAR (tail);
570 pane_name = Fcar (elt); 563 pane_name = Fcar (elt);
571 CHECK_STRING (pane_name); 564 CHECK_STRING (pane_name);
572 push_menu_pane (pane_name, Qnil); 565 push_menu_pane (ENCODE_MENU_STRING (pane_name), Qnil);
573 pane_data = Fcdr (elt); 566 pane_data = Fcdr (elt);
574 CHECK_CONS (pane_data); 567 CHECK_CONS (pane_data);
575 list_of_items (pane_data); 568 list_of_items (pane_data);
@@ -586,20 +579,22 @@ list_of_items (pane)
586{ 579{
587 Lisp_Object tail, item, item1; 580 Lisp_Object tail, item, item1;
588 581
589 for (tail = pane; !NILP (tail); tail = Fcdr (tail)) 582 for (tail = pane; CONSP (tail); tail = XCDR (tail))
590 { 583 {
591 item = Fcar (tail); 584 item = XCAR (tail);
592 if (STRINGP (item)) 585 if (STRINGP (item))
593 push_menu_item (item, Qnil, Qnil, Qt, Qnil, Qnil, Qnil, Qnil); 586 push_menu_item (ENCODE_MENU_STRING (item), Qnil, Qnil, Qt,
594 else if (NILP (item)) 587 Qnil, Qnil, Qnil, Qnil);
595 push_left_right_boundary (); 588 else if (CONSP (item))
596 else
597 { 589 {
598 CHECK_CONS (item); 590 item1 = XCAR (item);
599 item1 = Fcar (item);
600 CHECK_STRING (item1); 591 CHECK_STRING (item1);
601 push_menu_item (item1, Qt, Fcdr (item), Qt, Qnil, Qnil, Qnil, Qnil); 592 push_menu_item (ENCODE_MENU_STRING (item1), Qt, XCDR (item),
593 Qt, Qnil, Qnil, Qnil, Qnil);
602 } 594 }
595 else
596 push_left_right_boundary ();
597
603 } 598 }
604} 599}
605 600
@@ -659,15 +654,14 @@ no quit occurs and `x-popup-menu' returns nil. */)
659 Lisp_Object keymap, tem; 654 Lisp_Object keymap, tem;
660 int xpos = 0, ypos = 0; 655 int xpos = 0, ypos = 0;
661 Lisp_Object title; 656 Lisp_Object title;
662 char *error_name; 657 char *error_name = NULL;
663 Lisp_Object selection; 658 Lisp_Object selection;
664 FRAME_PTR f = NULL; 659 FRAME_PTR f = NULL;
665 Lisp_Object x, y, window; 660 Lisp_Object x, y, window;
666 int keymaps = 0; 661 int keymaps = 0;
667 int for_click = 0; 662 int for_click = 0;
668 struct gcpro gcpro1;
669 int specpdl_count = SPECPDL_INDEX (); 663 int specpdl_count = SPECPDL_INDEX ();
670 664 struct gcpro gcpro1;
671 665
672#ifdef HAVE_MENUS 666#ifdef HAVE_MENUS
673 if (! NILP (position)) 667 if (! NILP (position))
@@ -677,7 +671,8 @@ no quit occurs and `x-popup-menu' returns nil. */)
677 /* Decode the first argument: find the window and the coordinates. */ 671 /* Decode the first argument: find the window and the coordinates. */
678 if (EQ (position, Qt) 672 if (EQ (position, Qt)
679 || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar) 673 || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
680 || EQ (XCAR (position), Qtool_bar)))) 674 || EQ (XCAR (position), Qtool_bar)
675 || EQ (XCAR (position), Qmac_apple_event))))
681 { 676 {
682 /* Use the mouse's current position. */ 677 /* Use the mouse's current position. */
683 FRAME_PTR new_f = SELECTED_FRAME (); 678 FRAME_PTR new_f = SELECTED_FRAME ();
@@ -703,8 +698,8 @@ no quit occurs and `x-popup-menu' returns nil. */)
703 if (CONSP (tem)) 698 if (CONSP (tem))
704 { 699 {
705 window = Fcar (Fcdr (position)); 700 window = Fcar (Fcdr (position));
706 x = Fcar (tem); 701 x = XCAR (tem);
707 y = Fcar (Fcdr (tem)); 702 y = Fcar (XCDR (tem));
708 } 703 }
709 else 704 else
710 { 705 {
@@ -788,11 +783,11 @@ no quit occurs and `x-popup-menu' returns nil. */)
788 783
789 /* The first keymap that has a prompt string 784 /* The first keymap that has a prompt string
790 supplies the menu title. */ 785 supplies the menu title. */
791 for (tem = menu, i = 0; CONSP (tem); tem = Fcdr (tem)) 786 for (tem = menu, i = 0; CONSP (tem); tem = XCDR (tem))
792 { 787 {
793 Lisp_Object prompt; 788 Lisp_Object prompt;
794 789
795 maps[i++] = keymap = get_keymap (Fcar (tem), 1, 0); 790 maps[i++] = keymap = get_keymap (XCAR (tem), 1, 0);
796 791
797 prompt = Fkeymap_prompt (keymap); 792 prompt = Fkeymap_prompt (keymap);
798 if (NILP (title) && !NILP (prompt)) 793 if (NILP (title) && !NILP (prompt))
@@ -879,7 +874,8 @@ for instance using the window manager, then this produces a quit and
879 /* Decode the first argument: find the window or frame to use. */ 874 /* Decode the first argument: find the window or frame to use. */
880 if (EQ (position, Qt) 875 if (EQ (position, Qt)
881 || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar) 876 || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
882 || EQ (XCAR (position), Qtool_bar)))) 877 || EQ (XCAR (position), Qtool_bar)
878 || EQ (XCAR (position), Qmac_apple_event))))
883 { 879 {
884#if 0 /* Using the frame the mouse is on may not be right. */ 880#if 0 /* Using the frame the mouse is on may not be right. */
885 /* Use the mouse's current position. */ 881 /* Use the mouse's current position. */
@@ -947,6 +943,7 @@ for instance using the window manager, then this produces a quit and
947 Lisp_Object title; 943 Lisp_Object title;
948 char *error_name; 944 char *error_name;
949 Lisp_Object selection; 945 Lisp_Object selection;
946 int specpdl_count = SPECPDL_INDEX ();
950 947
951 /* Decode the dialog items from what was specified. */ 948 /* Decode the dialog items from what was specified. */
952 title = Fcar (contents); 949 title = Fcar (contents);
@@ -955,11 +952,11 @@ for instance using the window manager, then this produces a quit and
955 list_of_panes (Fcons (contents, Qnil)); 952 list_of_panes (Fcons (contents, Qnil));
956 953
957 /* Display them in a dialog box. */ 954 /* Display them in a dialog box. */
955 record_unwind_protect (cleanup_popup_menu, Qnil);
958 BLOCK_INPUT; 956 BLOCK_INPUT;
959 selection = mac_dialog_show (f, 0, title, header, &error_name); 957 selection = mac_dialog_show (f, 0, title, header, &error_name);
960 UNBLOCK_INPUT; 958 UNBLOCK_INPUT;
961 959 unbind_to (specpdl_count, Qnil);
962 discard_menu_items ();
963 960
964 if (error_name) error (error_name); 961 if (error_name) error (error_name);
965 return selection; 962 return selection;
@@ -971,13 +968,14 @@ for instance using the window manager, then this produces a quit and
971 This is called from keyboard.c when it gets the 968 This is called from keyboard.c when it gets the
972 MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue. 969 MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
973 970
974 To activate the menu bar, we signal to the input thread that it can 971 To activate the menu bar, we use the button-press event location
975 return from the WM_INITMENU message, allowing the normal Windows 972 that was saved in saved_menu_event_location.
976 processing of the menus.
977 973
978 But first we recompute the menu bar contents (the whole tree). 974 But first we recompute the menu bar contents (the whole tree).
979 975
980 This way we can safely execute Lisp code. */ 976 The reason for saving the button event until here, instead of
977 passing it to the toolkit right away, is that we can safely
978 execute Lisp code. */
981 979
982void 980void
983x_activate_menubar (f) 981x_activate_menubar (f)
@@ -1074,14 +1072,12 @@ menubar_selection_callback (FRAME_PTR f, int client_data)
1074 buf.arg = entry; 1072 buf.arg = entry;
1075 kbd_buffer_store_event (&buf); 1073 kbd_buffer_store_event (&buf);
1076 1074
1077 f->output_data.mac->menu_command_in_progress = 0;
1078 f->output_data.mac->menubar_active = 0; 1075 f->output_data.mac->menubar_active = 0;
1079 return; 1076 return;
1080 } 1077 }
1081 i += MENU_ITEMS_ITEM_LENGTH; 1078 i += MENU_ITEMS_ITEM_LENGTH;
1082 } 1079 }
1083 } 1080 }
1084 f->output_data.mac->menu_command_in_progress = 0;
1085 f->output_data.mac->menubar_active = 0; 1081 f->output_data.mac->menubar_active = 0;
1086} 1082}
1087 1083
@@ -1127,22 +1123,18 @@ free_menubar_widget_value_tree (wv)
1127 UNBLOCK_INPUT; 1123 UNBLOCK_INPUT;
1128} 1124}
1129 1125
1130/* Return a tree of widget_value structures for a menu bar item 1126/* Set up data in menu_items for a menu bar item
1131 whose event type is ITEM_KEY (with string ITEM_NAME) 1127 whose event type is ITEM_KEY (with string ITEM_NAME)
1132 and whose contents come from the list of keymaps MAPS. */ 1128 and whose contents come from the list of keymaps MAPS. */
1133 1129
1134static widget_value * 1130static int
1135single_submenu (item_key, item_name, maps) 1131parse_single_submenu (item_key, item_name, maps)
1136 Lisp_Object item_key, item_name, maps; 1132 Lisp_Object item_key, item_name, maps;
1137{ 1133{
1138 widget_value *wv, *prev_wv, *save_wv, *first_wv;
1139 int i;
1140 int submenu_depth = 0;
1141 Lisp_Object length; 1134 Lisp_Object length;
1142 int len; 1135 int len;
1143 Lisp_Object *mapvec; 1136 Lisp_Object *mapvec;
1144 widget_value **submenu_stack; 1137 int i;
1145 int previous_items = menu_items_used;
1146 int top_level_items = 0; 1138 int top_level_items = 0;
1147 1139
1148 length = Flength (maps); 1140 length = Flength (maps);
@@ -1156,28 +1148,44 @@ single_submenu (item_key, item_name, maps)
1156 maps = Fcdr (maps); 1148 maps = Fcdr (maps);
1157 } 1149 }
1158 1150
1159 menu_items_n_panes = 0;
1160
1161 /* Loop over the given keymaps, making a pane for each map. 1151 /* Loop over the given keymaps, making a pane for each map.
1162 But don't make a pane that is empty--ignore that map instead. */ 1152 But don't make a pane that is empty--ignore that map instead. */
1163 for (i = 0; i < len; i++) 1153 for (i = 0; i < len; i++)
1164 { 1154 {
1165 if (SYMBOLP (mapvec[i]) 1155 if (!KEYMAPP (mapvec[i]))
1166 || (CONSP (mapvec[i]) && !KEYMAPP (mapvec[i])))
1167 { 1156 {
1168 /* Here we have a command at top level in the menu bar 1157 /* Here we have a command at top level in the menu bar
1169 as opposed to a submenu. */ 1158 as opposed to a submenu. */
1170 top_level_items = 1; 1159 top_level_items = 1;
1171 push_menu_pane (Qnil, Qnil); 1160 push_menu_pane (Qnil, Qnil);
1172 push_menu_item (item_name, Qt, item_key, mapvec[i], 1161 push_menu_item (item_name, Qt, item_key, mapvec[i],
1173 Qnil, Qnil, Qnil, Qnil); 1162 Qnil, Qnil, Qnil, Qnil);
1174 } 1163 }
1175 else 1164 else
1176 single_keymap_panes (mapvec[i], item_name, item_key, 0, 10); 1165 {
1166 Lisp_Object prompt;
1167 prompt = Fkeymap_prompt (mapvec[i]);
1168 single_keymap_panes (mapvec[i],
1169 !NILP (prompt) ? prompt : item_name,
1170 item_key, 0, 10);
1171 }
1177 } 1172 }
1178 1173
1179 /* Create a tree of widget_value objects 1174 return top_level_items;
1180 representing the panes and their items. */ 1175}
1176
1177/* Create a tree of widget_value objects
1178 representing the panes and items
1179 in menu_items starting at index START, up to index END. */
1180
1181static widget_value *
1182digest_single_submenu (start, end, top_level_items)
1183 int start, end, top_level_items;
1184{
1185 widget_value *wv, *prev_wv, *save_wv, *first_wv;
1186 int i;
1187 int submenu_depth = 0;
1188 widget_value **submenu_stack;
1181 1189
1182 submenu_stack 1190 submenu_stack
1183 = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); 1191 = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
@@ -1191,12 +1199,12 @@ single_submenu (item_key, item_name, maps)
1191 save_wv = 0; 1199 save_wv = 0;
1192 prev_wv = 0; 1200 prev_wv = 0;
1193 1201
1194 /* Loop over all panes and items made during this call 1202 /* Loop over all panes and items made by the preceding call
1195 and construct a tree of widget_value objects. 1203 to parse_single_submenu and construct a tree of widget_value objects.
1196 Ignore the panes and items made by previous calls to 1204 Ignore the panes and items used by previous calls to
1197 single_submenu, even though those are also in menu_items. */ 1205 digest_single_submenu, even though those are also in menu_items. */
1198 i = previous_items; 1206 i = start;
1199 while (i < menu_items_used) 1207 while (i < end)
1200 { 1208 {
1201 if (EQ (XVECTOR (menu_items)->contents[i], Qnil)) 1209 if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
1202 { 1210 {
@@ -1230,7 +1238,7 @@ single_submenu (item_key, item_name, maps)
1230#ifndef HAVE_MULTILINGUAL_MENU 1238#ifndef HAVE_MULTILINGUAL_MENU
1231 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name)) 1239 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
1232 { 1240 {
1233 pane_name = ENCODE_SYSTEM (pane_name); 1241 pane_name = ENCODE_MENU_STRING (pane_name);
1234 AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name; 1242 AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
1235 } 1243 }
1236#endif 1244#endif
@@ -1266,7 +1274,7 @@ single_submenu (item_key, item_name, maps)
1266 { 1274 {
1267 /* Create a new item within current pane. */ 1275 /* Create a new item within current pane. */
1268 Lisp_Object item_name, enable, descrip, def, type, selected; 1276 Lisp_Object item_name, enable, descrip, def, type, selected;
1269 Lisp_Object help; 1277 Lisp_Object help;
1270 1278
1271 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME); 1279 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
1272 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE); 1280 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
@@ -1277,13 +1285,13 @@ single_submenu (item_key, item_name, maps)
1277 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP); 1285 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
1278 1286
1279#ifndef HAVE_MULTILINGUAL_MENU 1287#ifndef HAVE_MULTILINGUAL_MENU
1280 if (STRING_MULTIBYTE (item_name)) 1288 if (STRING_MULTIBYTE (item_name))
1281 { 1289 {
1282 item_name = ENCODE_MENU_STRING (item_name); 1290 item_name = ENCODE_MENU_STRING (item_name);
1283 AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name; 1291 AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
1284 } 1292 }
1285 1293
1286 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) 1294 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
1287 { 1295 {
1288 descrip = ENCODE_MENU_STRING (descrip); 1296 descrip = ENCODE_MENU_STRING (descrip);
1289 AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip; 1297 AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
@@ -1315,7 +1323,7 @@ single_submenu (item_key, item_name, maps)
1315 abort (); 1323 abort ();
1316 1324
1317 wv->selected = !NILP (selected); 1325 wv->selected = !NILP (selected);
1318 if (!STRINGP (help)) 1326 if (! STRINGP (help))
1319 help = Qnil; 1327 help = Qnil;
1320 1328
1321 wv->help = help; 1329 wv->help = help;
@@ -1337,6 +1345,7 @@ single_submenu (item_key, item_name, maps)
1337 1345
1338 return first_wv; 1346 return first_wv;
1339} 1347}
1348
1340/* Walk through the widget_value tree starting at FIRST_WV and update 1349/* Walk through the widget_value tree starting at FIRST_WV and update
1341 the char * pointers from the corresponding lisp values. 1350 the char * pointers from the corresponding lisp values.
1342 We do this after building the whole tree, since GC may happen while the 1351 We do this after building the whole tree, since GC may happen while the
@@ -1418,20 +1427,28 @@ static void
1418install_menu_quit_handler (MenuHandle menu_handle) 1427install_menu_quit_handler (MenuHandle menu_handle)
1419{ 1428{
1420#ifdef HAVE_CANCELMENUTRACKING 1429#ifdef HAVE_CANCELMENUTRACKING
1421 EventHandlerUPP handler = NewEventHandlerUPP(menu_quit_handler);
1422 UInt32 numTypes = 1;
1423 EventTypeSpec typesList[] = { { kEventClassKeyboard, kEventRawKeyDown } }; 1430 EventTypeSpec typesList[] = { { kEventClassKeyboard, kEventRawKeyDown } };
1424 int i = MIN_MENU_ID; 1431 int i = MIN_MENU_ID;
1425 MenuHandle menu = menu_handle ? menu_handle : GetMenuHandle (i); 1432 MenuHandle menu = menu_handle ? menu_handle : GetMenuHandle (i);
1426 1433
1427 while (menu != NULL) 1434 while (menu != NULL)
1428 { 1435 {
1429 InstallMenuEventHandler (menu, handler, GetEventTypeCount (typesList), 1436 InstallMenuEventHandler (menu, menu_quit_handler,
1437 GetEventTypeCount (typesList),
1430 typesList, menu_handle, NULL); 1438 typesList, menu_handle, NULL);
1431 if (menu_handle) break; 1439 if (menu_handle) break;
1432 menu = GetMenuHandle (++i); 1440 menu = GetMenuHandle (++i);
1433 } 1441 }
1434 DisposeEventHandlerUPP (handler); 1442
1443 i = menu_handle ? MIN_POPUP_SUBMENU_ID : MIN_SUBMENU_ID;
1444 menu = GetMenuHandle (i);
1445 while (menu != NULL)
1446 {
1447 InstallMenuEventHandler (menu, menu_quit_handler,
1448 GetEventTypeCount (typesList),
1449 typesList, menu_handle, NULL);
1450 menu = GetMenuHandle (++i);
1451 }
1435#endif /* HAVE_CANCELMENUTRACKING */ 1452#endif /* HAVE_CANCELMENUTRACKING */
1436} 1453}
1437 1454
@@ -1448,7 +1465,9 @@ set_frame_menubar (f, first_time, deep_p)
1448 int menubar_widget = f->output_data.mac->menubar_widget; 1465 int menubar_widget = f->output_data.mac->menubar_widget;
1449 Lisp_Object items; 1466 Lisp_Object items;
1450 widget_value *wv, *first_wv, *prev_wv = 0; 1467 widget_value *wv, *first_wv, *prev_wv = 0;
1451 int i; 1468 int i, last_i = 0;
1469 int *submenu_start, *submenu_end;
1470 int *submenu_top_level_items, *submenu_n_panes;
1452 1471
1453 /* We must not change the menubar when actually in use. */ 1472 /* We must not change the menubar when actually in use. */
1454 if (f->output_data.mac->menubar_active) 1473 if (f->output_data.mac->menubar_active)
@@ -1461,14 +1480,6 @@ set_frame_menubar (f, first_time, deep_p)
1461 else if (pending_menu_activation && !deep_p) 1480 else if (pending_menu_activation && !deep_p)
1462 deep_p = 1; 1481 deep_p = 1;
1463 1482
1464 wv = xmalloc_widget_value ();
1465 wv->name = "menubar";
1466 wv->value = 0;
1467 wv->enabled = 1;
1468 wv->button_type = BUTTON_TYPE_NONE;
1469 wv->help = Qnil;
1470 first_wv = wv;
1471
1472 if (deep_p) 1483 if (deep_p)
1473 { 1484 {
1474 /* Make a widget-value tree representing the entire menu trees. */ 1485 /* Make a widget-value tree representing the entire menu trees. */
@@ -1503,6 +1514,7 @@ set_frame_menubar (f, first_time, deep_p)
1503 1514
1504 /* Run the Lucid hook. */ 1515 /* Run the Lucid hook. */
1505 safe_run_hooks (Qactivate_menubar_hook); 1516 safe_run_hooks (Qactivate_menubar_hook);
1517
1506 /* If it has changed current-menubar from previous value, 1518 /* If it has changed current-menubar from previous value,
1507 really recompute the menubar from the value. */ 1519 really recompute the menubar from the value. */
1508 if (! NILP (Vlucid_menu_bar_dirty_flag)) 1520 if (! NILP (Vlucid_menu_bar_dirty_flag))
@@ -1517,21 +1529,56 @@ set_frame_menubar (f, first_time, deep_p)
1517 bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items, 1529 bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
1518 previous_menu_items_used * sizeof (Lisp_Object)); 1530 previous_menu_items_used * sizeof (Lisp_Object));
1519 1531
1520 /* Fill in the current menu bar contents. */ 1532 /* Fill in menu_items with the current menu bar contents.
1533 This can evaluate Lisp code. */
1521 menu_items = f->menu_bar_vector; 1534 menu_items = f->menu_bar_vector;
1522 menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0; 1535 menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
1536 submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
1537 submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
1538 submenu_n_panes = (int *) alloca (XVECTOR (items)->size * sizeof (int));
1539 submenu_top_level_items
1540 = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
1523 init_menu_items (); 1541 init_menu_items ();
1524 for (i = 0; i < XVECTOR (items)->size; i += 4) 1542 for (i = 0; i < XVECTOR (items)->size; i += 4)
1525 { 1543 {
1526 Lisp_Object key, string, maps; 1544 Lisp_Object key, string, maps;
1527 1545
1546 last_i = i;
1547
1528 key = XVECTOR (items)->contents[i]; 1548 key = XVECTOR (items)->contents[i];
1529 string = XVECTOR (items)->contents[i + 1]; 1549 string = XVECTOR (items)->contents[i + 1];
1530 maps = XVECTOR (items)->contents[i + 2]; 1550 maps = XVECTOR (items)->contents[i + 2];
1531 if (NILP (string)) 1551 if (NILP (string))
1532 break; 1552 break;
1533 1553
1534 wv = single_submenu (key, string, maps); 1554 submenu_start[i] = menu_items_used;
1555
1556 menu_items_n_panes = 0;
1557 submenu_top_level_items[i]
1558 = parse_single_submenu (key, string, maps);
1559 submenu_n_panes[i] = menu_items_n_panes;
1560
1561 submenu_end[i] = menu_items_used;
1562 }
1563
1564 finish_menu_items ();
1565
1566 /* Convert menu_items into widget_value trees
1567 to display the menu. This cannot evaluate Lisp code. */
1568
1569 wv = xmalloc_widget_value ();
1570 wv->name = "menubar";
1571 wv->value = 0;
1572 wv->enabled = 1;
1573 wv->button_type = BUTTON_TYPE_NONE;
1574 wv->help = Qnil;
1575 first_wv = wv;
1576
1577 for (i = 0; i < last_i; i += 4)
1578 {
1579 menu_items_n_panes = submenu_n_panes[i];
1580 wv = digest_single_submenu (submenu_start[i], submenu_end[i],
1581 submenu_top_level_items[i]);
1535 if (prev_wv) 1582 if (prev_wv)
1536 prev_wv->next = wv; 1583 prev_wv->next = wv;
1537 else 1584 else
@@ -1542,8 +1589,6 @@ set_frame_menubar (f, first_time, deep_p)
1542 prev_wv = wv; 1589 prev_wv = wv;
1543 } 1590 }
1544 1591
1545 finish_menu_items ();
1546
1547 set_buffer_internal_1 (prev); 1592 set_buffer_internal_1 (prev);
1548 unbind_to (specpdl_count, Qnil); 1593 unbind_to (specpdl_count, Qnil);
1549 1594
@@ -1552,22 +1597,18 @@ set_frame_menubar (f, first_time, deep_p)
1552 1597
1553 for (i = 0; i < previous_menu_items_used; i++) 1598 for (i = 0; i < previous_menu_items_used; i++)
1554 if (menu_items_used == i 1599 if (menu_items_used == i
1555 || (NILP (Fequal (previous_items[i], 1600 || (!EQ (previous_items[i], XVECTOR (menu_items)->contents[i])))
1556 XVECTOR (menu_items)->contents[i]))))
1557 break; 1601 break;
1558 if (i == menu_items_used && i == previous_menu_items_used && i != 0) 1602 if (i == menu_items_used && i == previous_menu_items_used && i != 0)
1559 { 1603 {
1560 free_menubar_widget_value_tree (first_wv); 1604 free_menubar_widget_value_tree (first_wv);
1561 menu_items = Qnil; 1605 discard_menu_items ();
1562 1606
1563 return; 1607 return;
1564 } 1608 }
1565 1609
1566 /* Now GC cannot happen during the lifetime of the widget_value, 1610 /* Now GC cannot happen during the lifetime of the widget_value,
1567 so it's safe to store data from a Lisp_String, as long as 1611 so it's safe to store data from a Lisp_String. */
1568 local copies are made when the actual menu is created.
1569 Windows takes care of this for normal string items, but
1570 not for owner-drawn items or additional item-info. */
1571 wv = first_wv->contents; 1612 wv = first_wv->contents;
1572 for (i = 0; i < XVECTOR (items)->size; i += 4) 1613 for (i = 0; i < XVECTOR (items)->size; i += 4)
1573 { 1614 {
@@ -1582,13 +1623,21 @@ set_frame_menubar (f, first_time, deep_p)
1582 1623
1583 f->menu_bar_vector = menu_items; 1624 f->menu_bar_vector = menu_items;
1584 f->menu_bar_items_used = menu_items_used; 1625 f->menu_bar_items_used = menu_items_used;
1585 menu_items = Qnil; 1626 discard_menu_items ();
1586 } 1627 }
1587 else 1628 else
1588 { 1629 {
1589 /* Make a widget-value tree containing 1630 /* Make a widget-value tree containing
1590 just the top level menu bar strings. */ 1631 just the top level menu bar strings. */
1591 1632
1633 wv = xmalloc_widget_value ();
1634 wv->name = "menubar";
1635 wv->value = 0;
1636 wv->enabled = 1;
1637 wv->button_type = BUTTON_TYPE_NONE;
1638 wv->help = Qnil;
1639 first_wv = wv;
1640
1592 items = FRAME_MENU_BAR_ITEMS (f); 1641 items = FRAME_MENU_BAR_ITEMS (f);
1593 for (i = 0; i < XVECTOR (items)->size; i += 4) 1642 for (i = 0; i < XVECTOR (items)->size; i += 4)
1594 { 1643 {
@@ -1676,6 +1725,7 @@ initialize_frame_menubar (f)
1676 set_frame_menubar (f, 1, 1); 1725 set_frame_menubar (f, 1, 1);
1677} 1726}
1678 1727
1728
1679/* Get rid of the menu bar of frame F, and free its storage. 1729/* Get rid of the menu bar of frame F, and free its storage.
1680 This is used when deleting a frame, and when turning off the menu bar. */ 1730 This is used when deleting a frame, and when turning off the menu bar. */
1681 1731
@@ -1683,7 +1733,7 @@ void
1683free_frame_menubar (f) 1733free_frame_menubar (f)
1684 FRAME_PTR f; 1734 FRAME_PTR f;
1685{ 1735{
1686 f->output_data.mac->menubar_widget = NULL; 1736 f->output_data.mac->menubar_widget = 0;
1687} 1737}
1688 1738
1689 1739
@@ -1760,6 +1810,7 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error)
1760 Lisp_Object *subprefix_stack 1810 Lisp_Object *subprefix_stack
1761 = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object)); 1811 = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
1762 int submenu_depth = 0; 1812 int submenu_depth = 0;
1813
1763 int first_pane; 1814 int first_pane;
1764 int specpdl_count = SPECPDL_INDEX (); 1815 int specpdl_count = SPECPDL_INDEX ();
1765 1816
@@ -1813,12 +1864,14 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error)
1813 /* Create a new pane. */ 1864 /* Create a new pane. */
1814 Lisp_Object pane_name, prefix; 1865 Lisp_Object pane_name, prefix;
1815 char *pane_string; 1866 char *pane_string;
1867
1816 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME); 1868 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
1817 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); 1869 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
1870
1818#ifndef HAVE_MULTILINGUAL_MENU 1871#ifndef HAVE_MULTILINGUAL_MENU
1819 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name)) 1872 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
1820 { 1873 {
1821 pane_name = ENCODE_SYSTEM (pane_name); 1874 pane_name = ENCODE_MENU_STRING (pane_name);
1822 AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name; 1875 AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
1823 } 1876 }
1824#endif 1877#endif
@@ -1861,14 +1914,13 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error)
1861 { 1914 {
1862 /* Create a new item within current pane. */ 1915 /* Create a new item within current pane. */
1863 Lisp_Object item_name, enable, descrip, def, type, selected, help; 1916 Lisp_Object item_name, enable, descrip, def, type, selected, help;
1864
1865 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME); 1917 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
1866 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE); 1918 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
1867 descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY); 1919 descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
1868 def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION); 1920 def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
1869 type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE); 1921 type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
1870 selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED); 1922 selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
1871 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP); 1923 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
1872 1924
1873#ifndef HAVE_MULTILINGUAL_MENU 1925#ifndef HAVE_MULTILINGUAL_MENU
1874 if (STRINGP (item_name) && STRING_MULTIBYTE (item_name)) 1926 if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
@@ -1876,8 +1928,9 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error)
1876 item_name = ENCODE_MENU_STRING (item_name); 1928 item_name = ENCODE_MENU_STRING (item_name);
1877 AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name; 1929 AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
1878 } 1930 }
1931
1879 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) 1932 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
1880 { 1933 {
1881 descrip = ENCODE_MENU_STRING (descrip); 1934 descrip = ENCODE_MENU_STRING (descrip);
1882 AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip; 1935 AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
1883 } 1936 }
@@ -1907,7 +1960,8 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error)
1907 abort (); 1960 abort ();
1908 1961
1909 wv->selected = !NILP (selected); 1962 wv->selected = !NILP (selected);
1910 if (!STRINGP (help)) 1963
1964 if (! STRINGP (help))
1911 help = Qnil; 1965 help = Qnil;
1912 1966
1913 wv->help = help; 1967 wv->help = help;
@@ -1934,6 +1988,7 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error)
1934 if (STRING_MULTIBYTE (title)) 1988 if (STRING_MULTIBYTE (title))
1935 title = ENCODE_MENU_STRING (title); 1989 title = ENCODE_MENU_STRING (title);
1936#endif 1990#endif
1991
1937 wv_title->name = (char *) SDATA (title); 1992 wv_title->name = (char *) SDATA (title);
1938 wv_title->enabled = FALSE; 1993 wv_title->enabled = FALSE;
1939 wv_title->title = TRUE; 1994 wv_title->title = TRUE;
@@ -1957,7 +2012,6 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error)
1957 pos.v = y; 2012 pos.v = y;
1958 2013
1959 SetPortWindowPort (FRAME_MAC_WINDOW (f)); 2014 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1960
1961 LocalToGlobal (&pos); 2015 LocalToGlobal (&pos);
1962 2016
1963 /* No selection has been chosen yet. */ 2017 /* No selection has been chosen yet. */
@@ -2167,11 +2221,11 @@ static char * button_names [] = {
2167 "button6", "button7", "button8", "button9", "button10" }; 2221 "button6", "button7", "button8", "button9", "button10" };
2168 2222
2169static Lisp_Object 2223static Lisp_Object
2170mac_dialog_show (f, keymaps, title, header, error) 2224mac_dialog_show (f, keymaps, title, header, error_name)
2171 FRAME_PTR f; 2225 FRAME_PTR f;
2172 int keymaps; 2226 int keymaps;
2173 Lisp_Object title, header; 2227 Lisp_Object title, header;
2174 char **error; 2228 char **error_name;
2175{ 2229{
2176 int i, nb_buttons=0; 2230 int i, nb_buttons=0;
2177 char dialog_name[6]; 2231 char dialog_name[6];
@@ -2184,11 +2238,11 @@ mac_dialog_show (f, keymaps, title, header, error)
2184 /* 1 means we've seen the boundary between left-hand elts and right-hand. */ 2238 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
2185 int boundary_seen = 0; 2239 int boundary_seen = 0;
2186 2240
2187 *error = NULL; 2241 *error_name = NULL;
2188 2242
2189 if (menu_items_n_panes > 1) 2243 if (menu_items_n_panes > 1)
2190 { 2244 {
2191 *error = "Multiple panes in dialog box"; 2245 *error_name = "Multiple panes in dialog box";
2192 return Qnil; 2246 return Qnil;
2193 } 2247 }
2194 2248
@@ -2216,18 +2270,16 @@ mac_dialog_show (f, keymaps, title, header, error)
2216 { 2270 {
2217 2271
2218 /* Create a new item within current pane. */ 2272 /* Create a new item within current pane. */
2219 Lisp_Object item_name, enable, descrip, help; 2273 Lisp_Object item_name, enable, descrip;
2220
2221 item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME]; 2274 item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
2222 enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE]; 2275 enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
2223 descrip 2276 descrip
2224 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY]; 2277 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
2225 help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
2226 2278
2227 if (NILP (item_name)) 2279 if (NILP (item_name))
2228 { 2280 {
2229 free_menubar_widget_value_tree (first_wv); 2281 free_menubar_widget_value_tree (first_wv);
2230 *error = "Submenu in dialog items"; 2282 *error_name = "Submenu in dialog items";
2231 return Qnil; 2283 return Qnil;
2232 } 2284 }
2233 if (EQ (item_name, Qquote)) 2285 if (EQ (item_name, Qquote))
@@ -2241,7 +2293,7 @@ mac_dialog_show (f, keymaps, title, header, error)
2241 if (nb_buttons >= 9) 2293 if (nb_buttons >= 9)
2242 { 2294 {
2243 free_menubar_widget_value_tree (first_wv); 2295 free_menubar_widget_value_tree (first_wv);
2244 *error = "Too many dialog items"; 2296 *error_name = "Too many dialog items";
2245 return Qnil; 2297 return Qnil;
2246 } 2298 }
2247 2299
@@ -2304,8 +2356,8 @@ mac_dialog_show (f, keymaps, title, header, error)
2304 /* Free the widget_value objects we used to specify the contents. */ 2356 /* Free the widget_value objects we used to specify the contents. */
2305 free_menubar_widget_value_tree (first_wv); 2357 free_menubar_widget_value_tree (first_wv);
2306 2358
2307 /* Find the selected item, and its pane, to return the proper 2359 /* Find the selected item, and its pane, to return
2308 value. */ 2360 the proper value. */
2309 if (menu_item_selection != 0) 2361 if (menu_item_selection != 0)
2310 { 2362 {
2311 Lisp_Object prefix; 2363 Lisp_Object prefix;
@@ -2322,6 +2374,12 @@ mac_dialog_show (f, keymaps, title, header, error)
2322 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; 2374 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
2323 i += MENU_ITEMS_PANE_LENGTH; 2375 i += MENU_ITEMS_PANE_LENGTH;
2324 } 2376 }
2377 else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
2378 {
2379 /* This is the boundary between left-side elts and
2380 right-side elts. */
2381 ++i;
2382 }
2325 else 2383 else
2326 { 2384 {
2327 entry 2385 entry
@@ -2340,6 +2398,9 @@ mac_dialog_show (f, keymaps, title, header, error)
2340 } 2398 }
2341 } 2399 }
2342 } 2400 }
2401 else
2402 /* Make "Cancel" equivalent to C-g. */
2403 Fsignal (Qquit, Qnil);
2343 2404
2344 return Qnil; 2405 return Qnil;
2345} 2406}
@@ -2365,7 +2426,11 @@ static void
2365add_menu_item (MenuHandle menu, widget_value *wv, int submenu, 2426add_menu_item (MenuHandle menu, widget_value *wv, int submenu,
2366 int force_disable) 2427 int force_disable)
2367{ 2428{
2429#if TARGET_API_MAC_CARBON
2430 CFStringRef item_name;
2431#else
2368 Str255 item_name; 2432 Str255 item_name;
2433#endif
2369 int pos; 2434 int pos;
2370 2435
2371 if (name_is_separator (wv->name)) 2436 if (name_is_separator (wv->name))
@@ -2376,42 +2441,49 @@ add_menu_item (MenuHandle menu, widget_value *wv, int submenu,
2376 2441
2377#if TARGET_API_MAC_CARBON 2442#if TARGET_API_MAC_CARBON
2378 pos = CountMenuItems (menu); 2443 pos = CountMenuItems (menu);
2379#else
2380 pos = CountMItems (menu);
2381#endif
2382 2444
2383 strcpy (item_name, ""); 2445 item_name = cfstring_create_with_utf8_cstring (wv->name);
2384 strncat (item_name, wv->name, 255); 2446
2385 if (wv->key != NULL) 2447 if (wv->key != NULL)
2386 { 2448 {
2387 strncat (item_name, " ", 255); 2449 CFStringRef name, key;
2388 strncat (item_name, wv->key, 255); 2450
2451 name = item_name;
2452 key = cfstring_create_with_utf8_cstring (wv->key);
2453 item_name = CFStringCreateWithFormat (NULL, NULL, CFSTR ("%@ %@"),
2454 name, key);
2455 CFRelease (name);
2456 CFRelease (key);
2389 } 2457 }
2390 item_name[255] = 0;
2391#if TARGET_API_MAC_CARBON
2392 {
2393 CFStringRef string = cfstring_create_with_utf8_cstring (item_name);
2394 2458
2395 SetMenuItemTextWithCFString (menu, pos, string); 2459 SetMenuItemTextWithCFString (menu, pos, item_name);
2396 CFRelease (string); 2460 CFRelease (item_name);
2397 } 2461
2398#else 2462 if (wv->enabled && !force_disable)
2463 EnableMenuItem (menu, pos);
2464 else
2465 DisableMenuItem (menu, pos);
2466#else /* ! TARGET_API_MAC_CARBON */
2467 pos = CountMItems (menu);
2468
2469 item_name[sizeof (item_name) - 1] = '\0';
2470 strncpy (item_name, wv->name, sizeof (item_name) - 1);
2471 if (wv->key != NULL)
2472 {
2473 int len = strlen (item_name);
2474
2475 strncpy (item_name + len, " ", sizeof (item_name) - 1 - len);
2476 len = strlen (item_name);
2477 strncpy (item_name + len, wv->key, sizeof (item_name) - 1 - len);
2478 }
2399 c2pstr (item_name); 2479 c2pstr (item_name);
2400 SetMenuItemText (menu, pos, item_name); 2480 SetMenuItemText (menu, pos, item_name);
2401#endif
2402 2481
2403 if (wv->enabled && !force_disable) 2482 if (wv->enabled && !force_disable)
2404#if TARGET_API_MAC_CARBON
2405 EnableMenuItem (menu, pos);
2406#else
2407 EnableItem (menu, pos); 2483 EnableItem (menu, pos);
2408#endif
2409 else 2484 else
2410#if TARGET_API_MAC_CARBON
2411 DisableMenuItem (menu, pos);
2412#else
2413 DisableItem (menu, pos); 2485 DisableItem (menu, pos);
2414#endif 2486#endif /* ! TARGET_API_MAC_CARBON */
2415 2487
2416 /* Draw radio buttons and tickboxes. */ 2488 /* Draw radio buttons and tickboxes. */
2417 { 2489 {
@@ -2425,7 +2497,7 @@ add_menu_item (MenuHandle menu, widget_value *wv, int submenu,
2425 SetMenuItemRefCon (menu, pos, (UInt32) wv->call_data); 2497 SetMenuItemRefCon (menu, pos, (UInt32) wv->call_data);
2426 } 2498 }
2427 2499
2428 if (submenu != NULL) 2500 if (submenu != 0)
2429 SetMenuItemHierarchicalID (menu, pos, submenu); 2501 SetMenuItemHierarchicalID (menu, pos, submenu);
2430} 2502}
2431 2503
@@ -2444,7 +2516,7 @@ fill_submenu (MenuHandle menu, widget_value *wv)
2444 add_menu_item (menu, wv, cur_submenu, 0); 2516 add_menu_item (menu, wv, cur_submenu, 0);
2445 } 2517 }
2446 else 2518 else
2447 add_menu_item (menu, wv, NULL, 0); 2519 add_menu_item (menu, wv, 0, 0);
2448} 2520}
2449 2521
2450 2522
@@ -2463,7 +2535,7 @@ fill_menu (MenuHandle menu, widget_value *wv)
2463 add_menu_item (menu, wv, cur_submenu, 0); 2535 add_menu_item (menu, wv, cur_submenu, 0);
2464 } 2536 }
2465 else 2537 else
2466 add_menu_item (menu, wv, NULL, 0); 2538 add_menu_item (menu, wv, 0, 0);
2467} 2539}
2468 2540
2469/* Construct native Mac OS menubar based on widget_value tree. */ 2541/* Construct native Mac OS menubar based on widget_value tree. */
@@ -2493,7 +2565,6 @@ fill_menubar (widget_value *wv)
2493} 2565}
2494 2566
2495#endif /* HAVE_MENUS */ 2567#endif /* HAVE_MENUS */
2496
2497 2568
2498void 2569void
2499syms_of_macmenu () 2570syms_of_macmenu ()