comparison src/menubar-x.c @ 412:697ef44129c6 r21-2-14

Import from CVS: tag r21-2-14
author cvs
date Mon, 13 Aug 2007 11:20:41 +0200
parents b8cc9ab3f761
children 41dbb7a9d5f2
comparison
equal deleted inserted replaced
411:12e008d41344 412:697ef44129c6
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */ 20 Boston, MA 02111-1307, USA. */
21 21
22 /* Synched up with: Not in FSF. */ 22 /* Synched up with: Not in FSF. */
23 23
24 /* Authorship: 24 /* created 16-dec-91 by jwz */
25
26 Created 16-dec-91 by Jamie Zawinski.
27 Menu filters and many other keywords added by Stig for 19.12.
28 Original device-abstraction work and GC cleanup work by Ben Wing for 19.13.
29 Menu accelerators c. 1997? by ??. Moved here from event-stream.c.
30 Other work post-1996 by ??.
31 */
32 25
33 #include <config.h> 26 #include <config.h>
34 #include "lisp.h" 27 #include "lisp.h"
35 28
36 #include "console-x.h" 29 #include "console-x.h"
37 #include "EmacsFrame.h" 30 #include "EmacsFrame.h"
38 #include "gui-x.h" 31 #include "gui-x.h"
39 #include "../lwlib/lwlib.h"
40 32
41 #include "buffer.h" 33 #include "buffer.h"
42 #include "commands.h" /* zmacs_regions */ 34 #include "commands.h" /* zmacs_regions */
35 #include "gui.h"
43 #include "events.h" 36 #include "events.h"
44 #include "frame.h" 37 #include "frame.h"
45 #include "gui.h"
46 #include "keymap.h"
47 #include "menubar.h"
48 #include "opaque.h" 38 #include "opaque.h"
49 #include "window.h" 39 #include "window.h"
50 40
51 static int set_frame_menubar (struct frame *f, 41 static int set_frame_menubar (struct frame *f,
52 int deep_p, 42 int deep_p,
102 /* This function cannot GC. 92 /* This function cannot GC.
103 It is only called from menu_item_descriptor_to_widget_value, which 93 It is only called from menu_item_descriptor_to_widget_value, which
104 prohibits GC. */ 94 prohibits GC. */
105 /* !!#### This function has not been Mule-ized */ 95 /* !!#### This function has not been Mule-ized */
106 int menubar_root_p = (menu_type == MENUBAR_TYPE && depth == 0); 96 int menubar_root_p = (menu_type == MENUBAR_TYPE && depth == 0);
97 widget_value *wv;
98 Lisp_Object wv_closure;
107 int count = specpdl_depth (); 99 int count = specpdl_depth ();
108 int partition_seen = 0; 100 int partition_seen = 0;
109 widget_value *wv = xmalloc_widget_value (); 101
110 Lisp_Object wv_closure = make_opaque_ptr (wv); 102 wv = xmalloc_widget_value ();
111 103
104 wv_closure = make_opaque_ptr (wv);
112 record_unwind_protect (widget_value_unwind, wv_closure); 105 record_unwind_protect (widget_value_unwind, wv_closure);
113 106
114 if (STRINGP (desc)) 107 if (STRINGP (desc))
115 { 108 {
116 char *string_chars = (char *) XSTRING_DATA (desc); 109 char *string_chars = (char *) XSTRING_DATA (desc);
125 { 118 {
126 wv->value = menu_separator_style (string_chars); 119 wv->value = menu_separator_style (string_chars);
127 } 120 }
128 else 121 else
129 { 122 {
130 wv->name = xstrdup (string_chars); 123 wv->name = string_chars;
131 wv->enabled = 1; 124 wv->enabled = 1;
132 /* dverna Dec. 98: command_builder_operate_menu_accelerator will 125 /* dverna Dec. 98: command_builder_operate_menu_accelerator will
133 manipulate the accel as a Lisp_Object if the widget has a name. 126 manipulate the accel as a Lisp_Object if the widget has a name.
134 Since simple labels have a name, but no accel, we *must* set it 127 Since simple labels have a name, but no accel, we *must* set it
135 to nil */ 128 to nil */
136 wv->accel = LISP_TO_VOID (Qnil); 129 wv->accel = LISP_TO_VOID (Qnil);
137 } 130 }
138 } 131 }
139 else if (VECTORP (desc)) 132 else if (VECTORP (desc))
140 { 133 {
141 Lisp_Object gui_item = gui_parse_item_keywords (desc); 134 if (!button_item_to_widget_value (desc, wv, 1,
142 if (!button_item_to_widget_value (Qmenubar,
143 gui_item, wv, 1,
144 (menu_type == MENUBAR_TYPE 135 (menu_type == MENUBAR_TYPE
145 && depth <= 1), 1)) 136 && depth <= 1)))
146 { 137 {
147 /* :included form was nil */ 138 /* :included form was nil */
148 wv = NULL; 139 wv = NULL;
149 goto menu_item_done; 140 goto menu_item_done;
150 } 141 }
163 int included_spec = 0; 154 int included_spec = 0;
164 int active_spec = 0; 155 int active_spec = 0;
165 wv->type = CASCADE_TYPE; 156 wv->type = CASCADE_TYPE;
166 wv->enabled = 1; 157 wv->enabled = 1;
167 wv->name = (char *) XSTRING_DATA (LISP_GETTEXT (XCAR (desc))); 158 wv->name = (char *) XSTRING_DATA (LISP_GETTEXT (XCAR (desc)));
168 wv->name = strdup_and_add_accel (wv->name); 159
169 160 accel = menu_name_to_accelerator (wv->name);
170 accel = gui_name_accelerator (LISP_GETTEXT (XCAR (desc)));
171 wv->accel = LISP_TO_VOID (accel); 161 wv->accel = LISP_TO_VOID (accel);
172 162
173 desc = Fcdr (desc); 163 desc = Fcdr (desc);
174 164
175 while (key = Fcar (desc), KEYWORDP (key)) 165 while (key = Fcar (desc), KEYWORDP (key))
233 widget_value *incr_wv = xmalloc_widget_value (); 223 widget_value *incr_wv = xmalloc_widget_value ();
234 wv->contents = incr_wv; 224 wv->contents = incr_wv;
235 incr_wv->type = INCREMENTAL_TYPE; 225 incr_wv->type = INCREMENTAL_TYPE;
236 incr_wv->enabled = 1; 226 incr_wv->enabled = 1;
237 incr_wv->name = wv->name; 227 incr_wv->name = wv->name;
238 incr_wv->name = xstrdup (wv->name);
239 /* This is automatically GC protected through 228 /* This is automatically GC protected through
240 the call to lw_map_widget_values(); no need 229 the call to lw_map_widget_values(); no need
241 to worry. */ 230 to worry. */
242 incr_wv->call_data = LISP_TO_VOID (incremental_data); 231 incr_wv->call_data = LISP_TO_VOID (incremental_data);
243 goto menu_item_done; 232 goto menu_item_done;
250 the menu: a label, and two separators (to get a double 239 the menu: a label, and two separators (to get a double
251 line). */ 240 line). */
252 widget_value *title_wv = xmalloc_widget_value (); 241 widget_value *title_wv = xmalloc_widget_value ();
253 widget_value *sep_wv = xmalloc_widget_value (); 242 widget_value *sep_wv = xmalloc_widget_value ();
254 title_wv->type = TEXT_TYPE; 243 title_wv->type = TEXT_TYPE;
255 title_wv->name = xstrdup (wv->name); 244 title_wv->name = wv->name;
256 title_wv->enabled = 1; 245 title_wv->enabled = 1;
257 title_wv->next = sep_wv; 246 title_wv->next = sep_wv;
258 sep_wv->type = SEPARATOR_TYPE; 247 sep_wv->type = SEPARATOR_TYPE;
259 sep_wv->value = menu_separator_style ("=="); 248 sep_wv->value = menu_separator_style ("==");
260 sep_wv->next = 0; 249 sep_wv->next = 0;
266 if (deep_p && !wv->enabled && !NILP (desc)) 255 if (deep_p && !wv->enabled && !NILP (desc))
267 { 256 {
268 widget_value *dummy; 257 widget_value *dummy;
269 /* Add a fake entry so the menus show up */ 258 /* Add a fake entry so the menus show up */
270 wv->contents = dummy = xmalloc_widget_value (); 259 wv->contents = dummy = xmalloc_widget_value ();
271 dummy->name = xstrdup ("(inactive)"); 260 dummy->name = "(inactive)";
272 dummy->accel = LISP_TO_VOID (Qnil); 261 dummy->accel = LISP_TO_VOID (Qnil);
273 dummy->enabled = 0; 262 dummy->enabled = 0;
274 dummy->selected = 0; 263 dummy->selected = 0;
275 dummy->value = NULL; 264 dummy->value = NULL;
276 dummy->type = BUTTON_TYPE; 265 dummy->type = BUTTON_TYPE;
277 dummy->call_data = NULL; 266 dummy->call_data = NULL;
278 dummy->next = NULL; 267 dummy->next = NULL;
279 268
280 goto menu_item_done; 269 goto menu_item_done;
281 } 270 }
282 271
283 } 272 }
284 else if (menubar_root_p) 273 else if (menubar_root_p)
285 { 274 {
286 wv->name = xstrdup ("menubar"); 275 wv->name = (char *) "menubar";
287 wv->type = CASCADE_TYPE; /* Well, nothing else seems to fit and 276 wv->type = CASCADE_TYPE; /* Well, nothing else seems to fit and
288 this is ignored anyway... */ 277 this is ignored anyway... */
289 } 278 }
290 else 279 else
291 { 280 {
301 Lisp_Object child = Fcar (desc); 290 Lisp_Object child = Fcar (desc);
302 if (menubar_root_p && NILP (child)) /* the partition */ 291 if (menubar_root_p && NILP (child)) /* the partition */
303 { 292 {
304 if (partition_seen) 293 if (partition_seen)
305 error ( 294 error (
306 "More than one partition (nil) in menubar description"); 295 "More than one partition (nil) in menubar description");
307 partition_seen = 1; 296 partition_seen = 1;
308 next = xmalloc_widget_value (); 297 next = xmalloc_widget_value ();
309 next->type = PUSHRIGHT_TYPE; 298 next->type = PUSHRIGHT_TYPE;
310 } 299 }
311 else 300 else
328 else if (NILP (desc)) 317 else if (NILP (desc))
329 error ("nil may not appear in menu descriptions"); 318 error ("nil may not appear in menu descriptions");
330 else 319 else
331 signal_simple_error ("Unrecognized menu descriptor", desc); 320 signal_simple_error ("Unrecognized menu descriptor", desc);
332 321
333 menu_item_done: 322 menu_item_done:
334 323
335 if (wv) 324 if (wv)
336 { 325 {
337 /* Completed normally. Clear out the object that widget_value_unwind() 326 /* Completed normally. Clear out the object that widget_value_unwind()
338 will be called with to tell it not to free the wv (as we are 327 will be called with to tell it not to free the wv (as we are
345 } 334 }
346 335
347 static widget_value * 336 static widget_value *
348 menu_item_descriptor_to_widget_value (Lisp_Object desc, 337 menu_item_descriptor_to_widget_value (Lisp_Object desc,
349 int menu_type, /* if this is a menubar, 338 int menu_type, /* if this is a menubar,
350 popup or sub menu */ 339 popup or sub menu */
351 int deep_p, /* */ 340 int deep_p, /* */
352 int filter_p) /* if :filter forms 341 int filter_p) /* if :filter forms
353 should run now */ 342 should run now */
354 { 343 {
355 widget_value *wv; 344 widget_value *wv;
369 int in_menu_callback; 358 int in_menu_callback;
370 359
371 static Lisp_Object 360 static Lisp_Object
372 restore_in_menu_callback (Lisp_Object val) 361 restore_in_menu_callback (Lisp_Object val)
373 { 362 {
374 in_menu_callback = XINT (val); 363 in_menu_callback = XINT(val);
375 return Qnil; 364 return Qnil;
376 } 365 }
377 #endif /* LWLIB_MENUBARS_LUCID || LWLIB_MENUBARS_MOTIF */ 366 #endif /* LWLIB_MENUBARS_LUCID || LWLIB_MENUBARS_MOTIF */
378 367
379 #if 0 368 #if 0
380 /* #### Sort of a hack needed to process Vactivate_menubar_hook 369 /* #### Sort of a hack needed to process Vactivate_menubar_hook
477 wv->type = CASCADE_TYPE; 466 wv->type = CASCADE_TYPE;
478 wv->next = NULL; 467 wv->next = NULL;
479 wv->accel = LISP_TO_VOID (Qnil); 468 wv->accel = LISP_TO_VOID (Qnil);
480 wv->contents = xmalloc_widget_value (); 469 wv->contents = xmalloc_widget_value ();
481 wv->contents->type = TEXT_TYPE; 470 wv->contents->type = TEXT_TYPE;
482 wv->contents->name = xstrdup ("No menu"); 471 wv->contents->name = (char *) "No menu";
483 wv->contents->next = NULL; 472 wv->contents->next = NULL;
484 wv->contents->accel = LISP_TO_VOID (Qnil); 473 wv->contents->accel = LISP_TO_VOID (Qnil);
485 } 474 }
486 assert (wv && wv->type == CASCADE_TYPE && wv->contents); 475 assert (wv && wv->type == CASCADE_TYPE && wv->contents);
487 replace_widget_value_tree (hack_wv, wv->contents); 476 replace_widget_value_tree (hack_wv, wv->contents);
520 } 509 }
521 510
522 static widget_value * 511 static widget_value *
523 compute_menubar_data (struct frame *f, Lisp_Object menubar, int deep_p) 512 compute_menubar_data (struct frame *f, Lisp_Object menubar, int deep_p)
524 { 513 {
514 widget_value *data;
515
525 if (NILP (menubar)) 516 if (NILP (menubar))
526 return 0; 517 data = 0;
527 else 518 else
528 { 519 {
529 widget_value *data; 520 Lisp_Object old_buffer;
530 int count = specpdl_depth (); 521 int count = specpdl_depth ();
531 522
532 record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); 523 old_buffer = Fcurrent_buffer ();
533 Fset_buffer (XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer); 524 record_unwind_protect (Fset_buffer, old_buffer);
525 Fset_buffer ( XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer);
534 data = menu_item_descriptor_to_widget_value (menubar, MENUBAR_TYPE, 526 data = menu_item_descriptor_to_widget_value (menubar, MENUBAR_TYPE,
535 deep_p, 0); 527 deep_p, 0);
528 Fset_buffer (old_buffer);
536 unbind_to (count, Qnil); 529 unbind_to (count, Qnil);
537 530 }
538 return data; 531 return data;
539 }
540 } 532 }
541 533
542 static int 534 static int
543 set_frame_menubar (struct frame *f, int deep_p, int first_time_p) 535 set_frame_menubar (struct frame *f, int deep_p, int first_time_p)
544 { 536 {
545 widget_value *data; 537 widget_value *data;
546 Lisp_Object menubar; 538 Lisp_Object menubar;
547 int menubar_visible; 539 int menubar_visible;
548 long id; 540 long id;
549 /* As with the toolbar, the minibuffer does not have its own menubar. */ 541 /* As for the toolbar, the minibuffer does not have its own menubar. */
550 struct window *w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)); 542 struct window *w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f));
551 543
552 if (! FRAME_X_P (f)) 544 if (! FRAME_X_P (f))
553 return 0; 545 return 0;
554 546
665 lw_destroy_all_widgets (id); 657 lw_destroy_all_widgets (id);
666 } 658 }
667 659
668 660
669 static void 661 static void
670 make_dummy_xbutton_event (XEvent *dummy, Widget daddy, Lisp_Event *eev) 662 make_dummy_xbutton_event (XEvent *dummy,
663 Widget daddy,
664 struct Lisp_Event *eev)
671 /* NULL for eev means query pointer */ 665 /* NULL for eev means query pointer */
672 { 666 {
673 XButtonPressedEvent *btn = (XButtonPressedEvent *) dummy; 667 XButtonPressedEvent *btn = (XButtonPressedEvent *) dummy;
674 668
675 btn->type = ButtonPress; 669 btn->type = ButtonPress;
678 btn->display = XtDisplay (daddy); 672 btn->display = XtDisplay (daddy);
679 btn->window = XtWindow (daddy); 673 btn->window = XtWindow (daddy);
680 if (eev) 674 if (eev)
681 { 675 {
682 Position shellx, shelly, framex, framey; 676 Position shellx, shelly, framex, framey;
677 Widget shell = XtParent (daddy);
683 Arg al [2]; 678 Arg al [2];
684 btn->time = eev->timestamp; 679 btn->time = eev->timestamp;
685 btn->button = eev->event.button.button; 680 btn->button = eev->event.button.button;
686 btn->root = RootWindowOfScreen (XtScreen (daddy)); 681 btn->root = RootWindowOfScreen (XtScreen (daddy));
687 btn->subwindow = (Window) NULL; 682 btn->subwindow = (Window) NULL;
688 btn->x = eev->event.button.x; 683 btn->x = eev->event.button.x;
689 btn->y = eev->event.button.y; 684 btn->y = eev->event.button.y;
690 shellx = shelly = 0; 685 XtSetArg (al [0], XtNx, &shellx);
691 #ifndef HAVE_WMCOMMAND 686 XtSetArg (al [1], XtNy, &shelly);
692 { 687 XtGetValues (shell, al, 2);
693 Widget shell = XtParent (daddy);
694
695 XtSetArg (al [0], XtNx, &shellx);
696 XtSetArg (al [1], XtNy, &shelly);
697 XtGetValues (shell, al, 2);
698 }
699 #endif
700 XtSetArg (al [0], XtNx, &framex); 688 XtSetArg (al [0], XtNx, &framex);
701 XtSetArg (al [1], XtNy, &framey); 689 XtSetArg (al [1], XtNy, &framey);
702 XtGetValues (daddy, al, 2); 690 XtGetValues (daddy, al, 2);
703 btn->x_root = shellx + framex + btn->x; 691 btn->x_root = shellx + framex + btn->x;
704 btn->y_root = shelly + framey + btn->y; 692 btn->y_root = shelly + framey + btn->y;
784 int menu_id; 772 int menu_id;
785 struct frame *f = selected_frame (); 773 struct frame *f = selected_frame ();
786 widget_value *data; 774 widget_value *data;
787 Widget parent; 775 Widget parent;
788 Widget menu; 776 Widget menu;
789 Lisp_Event *eev = NULL; 777 struct Lisp_Event *eev = NULL;
790 XEvent xev; 778 XEvent xev;
791 Lisp_Object frame; 779 Lisp_Object frame;
792 780
793 XSETFRAME (frame, f); 781 XSETFRAME (frame, f);
794 CHECK_X_FRAME (frame); 782 CHECK_X_FRAME (frame);
839 827
840 So there are two command-events, with a bunch of magic-events between 828 So there are two command-events, with a bunch of magic-events between
841 them. We don't want the *first* command event to alter the state of the 829 them. We don't want the *first* command event to alter the state of the
842 region, so that the region can be available as an argument for the second 830 region, so that the region can be available as an argument for the second
843 command. 831 command.
844 */ 832 */
845 if (zmacs_regions) 833 if (zmacs_regions)
846 zmacs_region_stays = 1; 834 zmacs_region_stays = 1;
847 835
848 popup_up_p++; 836 popup_up_p++;
849 lw_popup_menu (menu, &xev); 837 lw_popup_menu (menu, &xev);
850 /* this speeds up display of pop-up menus */ 838 /* this speeds up display of pop-up menus */
851 XFlush (XtDisplay (parent)); 839 XFlush (XtDisplay (parent));
852 } 840 }
853 841
854 842
855
856 #if defined(LWLIB_MENUBARS_LUCID)
857 static void
858 menu_move_up (void)
859 {
860 widget_value *current = lw_get_entries (False);
861 widget_value *entries = lw_get_entries (True);
862 widget_value *prev = NULL;
863
864 while (entries != current)
865 {
866 if (entries->name /*&& entries->enabled*/) prev = entries;
867 entries = entries->next;
868 assert (entries);
869 }
870
871 if (!prev)
872 /* move to last item */
873 {
874 while (entries->next)
875 {
876 if (entries->name /*&& entries->enabled*/) prev = entries;
877 entries = entries->next;
878 }
879 if (prev)
880 {
881 if (entries->name /*&& entries->enabled*/)
882 prev = entries;
883 }
884 else
885 {
886 /* no selectable items in this menu, pop up to previous level */
887 lw_pop_menu ();
888 return;
889 }
890 }
891 lw_set_item (prev);
892 }
893
894 static void
895 menu_move_down (void)
896 {
897 widget_value *current = lw_get_entries (False);
898 widget_value *new = current;
899
900 while (new->next)
901 {
902 new = new->next;
903 if (new->name /*&& new->enabled*/) break;
904 }
905
906 if (new==current||!(new->name/*||new->enabled*/))
907 {
908 new = lw_get_entries (True);
909 while (new!=current)
910 {
911 if (new->name /*&& new->enabled*/) break;
912 new = new->next;
913 }
914 if (new==current&&!(new->name /*|| new->enabled*/))
915 {
916 lw_pop_menu ();
917 return;
918 }
919 }
920
921 lw_set_item (new);
922 }
923
924 static void
925 menu_move_left (void)
926 {
927 int level = lw_menu_level ();
928 int l = level;
929 widget_value *current;
930
931 while (level-- >= 3)
932 lw_pop_menu ();
933
934 menu_move_up ();
935 current = lw_get_entries (False);
936 if (l > 2 && current->contents)
937 lw_push_menu (current->contents);
938 }
939
940 static void
941 menu_move_right (void)
942 {
943 int level = lw_menu_level ();
944 int l = level;
945 widget_value *current;
946
947 while (level-- >= 3)
948 lw_pop_menu ();
949
950 menu_move_down ();
951 current = lw_get_entries (False);
952 if (l > 2 && current->contents)
953 lw_push_menu (current->contents);
954 }
955
956 static void
957 menu_select_item (widget_value *val)
958 {
959 if (val == NULL)
960 val = lw_get_entries (False);
961
962 /* is match a submenu? */
963
964 if (val->contents)
965 {
966 /* enter the submenu */
967
968 lw_set_item (val);
969 lw_push_menu (val->contents);
970 }
971 else
972 {
973 /* Execute the menu entry by calling the menu's `select'
974 callback function
975 */
976 lw_kill_menus (val);
977 }
978 }
979
980 Lisp_Object
981 command_builder_operate_menu_accelerator (struct command_builder *builder)
982 {
983 /* this function can GC */
984
985 struct console *con = XCONSOLE (Vselected_console);
986 Lisp_Object evee = builder->most_current_event;
987 Lisp_Object binding;
988 widget_value *entries;
989
990 extern int lw_menu_accelerate; /* lwlib.c */
991
992 #if 0
993 {
994 int i;
995 Lisp_Object t;
996 char buf[50];
997
998 t = builder->current_events;
999 i = 0;
1000 while (!NILP (t))
1001 {
1002 i++;
1003 sprintf (buf,"OPERATE (%d): ",i);
1004 write_c_string (buf, Qexternal_debugging_output);
1005 print_internal (t, Qexternal_debugging_output, 1);
1006 write_c_string ("\n", Qexternal_debugging_output);
1007 t = XEVENT_NEXT (t);
1008 }
1009 }
1010 #endif /* 0 */
1011
1012 /* menu accelerator keys don't go into keyboard macros */
1013 if (!NILP (con->defining_kbd_macro) && NILP (Vexecuting_macro))
1014 con->kbd_macro_ptr = con->kbd_macro_end;
1015
1016 /* don't echo menu accelerator keys */
1017 /*reset_key_echo (builder, 1);*/
1018
1019 if (!lw_menu_accelerate)
1020 {
1021 /* `convert' mouse display to keyboard display
1022 by entering the open submenu
1023 */
1024 entries = lw_get_entries (False);
1025 if (entries->contents)
1026 {
1027 lw_push_menu (entries->contents);
1028 lw_display_menu (CurrentTime);
1029 }
1030 }
1031
1032 /* compare event to the current menu accelerators */
1033
1034 entries=lw_get_entries (True);
1035
1036 while (entries)
1037 {
1038 Lisp_Object accel;
1039 VOID_TO_LISP (accel, entries->accel);
1040 if (entries->name && !NILP (accel))
1041 {
1042 if (event_matches_key_specifier_p (XEVENT (evee), accel))
1043 {
1044 /* a match! */
1045
1046 menu_select_item (entries);
1047
1048 if (lw_menu_active) lw_display_menu (CurrentTime);
1049
1050 reset_this_command_keys (Vselected_console, 1);
1051 /*reset_command_builder_event_chain (builder);*/
1052 return Vmenu_accelerator_map;
1053 }
1054 }
1055 entries = entries->next;
1056 }
1057
1058 /* try to look up event in menu-accelerator-map */
1059
1060 binding = event_binding_in (evee, Vmenu_accelerator_map, 1);
1061
1062 if (NILP (binding))
1063 {
1064 /* beep at user for undefined key */
1065 return Qnil;
1066 }
1067 else
1068 {
1069 if (EQ (binding, Qmenu_quit))
1070 {
1071 /* turn off menus and set quit flag */
1072 lw_kill_menus (NULL);
1073 Vquit_flag = Qt;
1074 }
1075 else if (EQ (binding, Qmenu_up))
1076 {
1077 int level = lw_menu_level ();
1078 if (level > 2)
1079 menu_move_up ();
1080 }
1081 else if (EQ (binding, Qmenu_down))
1082 {
1083 int level = lw_menu_level ();
1084 if (level > 2)
1085 menu_move_down ();
1086 else
1087 menu_select_item (NULL);
1088 }
1089 else if (EQ (binding, Qmenu_left))
1090 {
1091 int level = lw_menu_level ();
1092 if (level > 3)
1093 {
1094 lw_pop_menu ();
1095 lw_display_menu (CurrentTime);
1096 }
1097 else
1098 menu_move_left ();
1099 }
1100 else if (EQ (binding, Qmenu_right))
1101 {
1102 int level = lw_menu_level ();
1103 if (level > 2 &&
1104 lw_get_entries (False)->contents)
1105 {
1106 widget_value *current = lw_get_entries (False);
1107 if (current->contents)
1108 menu_select_item (NULL);
1109 }
1110 else
1111 menu_move_right ();
1112 }
1113 else if (EQ (binding, Qmenu_select))
1114 menu_select_item (NULL);
1115 else if (EQ (binding, Qmenu_escape))
1116 {
1117 int level = lw_menu_level ();
1118
1119 if (level > 2)
1120 {
1121 lw_pop_menu ();
1122 lw_display_menu (CurrentTime);
1123 }
1124 else
1125 {
1126 /* turn off menus quietly */
1127 lw_kill_menus (NULL);
1128 }
1129 }
1130 else if (KEYMAPP (binding))
1131 {
1132 /* prefix key */
1133 reset_this_command_keys (Vselected_console, 1);
1134 /*reset_command_builder_event_chain (builder);*/
1135 return binding;
1136 }
1137 else
1138 {
1139 /* turn off menus and execute binding */
1140 lw_kill_menus (NULL);
1141 reset_this_command_keys (Vselected_console, 1);
1142 /*reset_command_builder_event_chain (builder);*/
1143 return binding;
1144 }
1145 }
1146
1147 if (lw_menu_active) lw_display_menu (CurrentTime);
1148
1149 reset_this_command_keys (Vselected_console, 1);
1150 /*reset_command_builder_event_chain (builder);*/
1151
1152 return Vmenu_accelerator_map;
1153 }
1154
1155 static Lisp_Object
1156 menu_accelerator_junk_on_error (Lisp_Object errordata, Lisp_Object ignored)
1157 {
1158 Vmenu_accelerator_prefix = Qnil;
1159 Vmenu_accelerator_modifiers = Qnil;
1160 Vmenu_accelerator_enabled = Qnil;
1161 if (!NILP (errordata))
1162 {
1163 Lisp_Object args[2];
1164
1165 args[0] = build_string ("Error in menu accelerators (setting to nil)");
1166 /* #### This should call
1167 (with-output-to-string (display-error errordata))
1168 but that stuff is all in Lisp currently. */
1169 args[1] = errordata;
1170 warn_when_safe_lispobj
1171 (Qerror, Qwarning,
1172 emacs_doprnt_string_lisp ((const Bufbyte *) "%s: %s",
1173 Qnil, -1, 2, args));
1174 }
1175
1176 return Qnil;
1177 }
1178
1179 static Lisp_Object
1180 menu_accelerator_safe_compare (Lisp_Object event0)
1181 {
1182 if (CONSP (Vmenu_accelerator_prefix))
1183 {
1184 Lisp_Object t;
1185 t=Vmenu_accelerator_prefix;
1186 while (!NILP (t)
1187 && !NILP (event0)
1188 && event_matches_key_specifier_p (XEVENT (event0), Fcar (t)))
1189 {
1190 t = Fcdr (t);
1191 event0 = XEVENT_NEXT (event0);
1192 }
1193 if (!NILP (t))
1194 return Qnil;
1195 }
1196 else if (NILP (event0))
1197 return Qnil;
1198 else if (event_matches_key_specifier_p (XEVENT (event0), Vmenu_accelerator_prefix))
1199 event0 = XEVENT_NEXT (event0);
1200 else
1201 return Qnil;
1202 return event0;
1203 }
1204
1205 static Lisp_Object
1206 menu_accelerator_safe_mod_compare (Lisp_Object cons)
1207 {
1208 return (event_matches_key_specifier_p (XEVENT (XCAR (cons)), XCDR (cons))
1209 ? Qt
1210 : Qnil);
1211 }
1212
1213 Lisp_Object
1214 command_builder_find_menu_accelerator (struct command_builder *builder)
1215 {
1216 /* this function can GC */
1217 Lisp_Object event0 = builder->current_events;
1218 struct console *con = XCONSOLE (Vselected_console);
1219 struct frame *f = XFRAME (CONSOLE_SELECTED_FRAME (con));
1220 Widget menubar_widget;
1221
1222 /* compare entries in event0 against the menu prefix */
1223
1224 if ((!CONSOLE_X_P (XCONSOLE (builder->console))) || NILP (event0) ||
1225 XEVENT (event0)->event_type != key_press_event)
1226 return Qnil;
1227
1228 if (!NILP (Vmenu_accelerator_prefix))
1229 {
1230 event0 = condition_case_1 (Qerror,
1231 menu_accelerator_safe_compare,
1232 event0,
1233 menu_accelerator_junk_on_error,
1234 Qnil);
1235 }
1236
1237 if (NILP (event0))
1238 return Qnil;
1239
1240 menubar_widget = FRAME_X_MENUBAR_WIDGET (f);
1241 if (menubar_widget
1242 && CONSP (Vmenu_accelerator_modifiers))
1243 {
1244 Lisp_Object fake;
1245 Lisp_Object last = Qnil;
1246 struct gcpro gcpro1;
1247 Lisp_Object matchp;
1248
1249 widget_value *val;
1250 LWLIB_ID id = XPOPUP_DATA (f->menubar_data)->id;
1251
1252 val = lw_get_all_values (id);
1253 if (val)
1254 {
1255 val = val->contents;
1256
1257 fake = Fcopy_sequence (Vmenu_accelerator_modifiers);
1258 last = fake;
1259
1260 while (!NILP (Fcdr (last)))
1261 last = Fcdr (last);
1262
1263 Fsetcdr (last, Fcons (Qnil, Qnil));
1264 last = Fcdr (last);
1265 }
1266
1267 fake = Fcons (Qnil, fake);
1268
1269 GCPRO1 (fake);
1270
1271 while (val)
1272 {
1273 Lisp_Object accel;
1274 VOID_TO_LISP (accel, val->accel);
1275 if (val->name && !NILP (accel))
1276 {
1277 Fsetcar (last, accel);
1278 Fsetcar (fake, event0);
1279 matchp = condition_case_1 (Qerror,
1280 menu_accelerator_safe_mod_compare,
1281 fake,
1282 menu_accelerator_junk_on_error,
1283 Qnil);
1284 if (!NILP (matchp))
1285 {
1286 /* we found one! */
1287
1288 lw_set_menu (menubar_widget, val);
1289 /* yah - yet another hack.
1290 pretend emacs timestamp is the same as an X timestamp,
1291 which for the moment it is. (read events.h)
1292 */
1293 lw_map_menu (XEVENT (event0)->timestamp);
1294
1295 if (val->contents)
1296 lw_push_menu (val->contents);
1297
1298 lw_display_menu (CurrentTime);
1299
1300 /* menu accelerator keys don't go into keyboard macros */
1301 if (!NILP (con->defining_kbd_macro)
1302 && NILP (Vexecuting_macro))
1303 con->kbd_macro_ptr = con->kbd_macro_end;
1304
1305 /* don't echo menu accelerator keys */
1306 /*reset_key_echo (builder, 1);*/
1307 reset_this_command_keys (Vselected_console, 1);
1308 UNGCPRO;
1309
1310 return Vmenu_accelerator_map;
1311 }
1312 }
1313
1314 val = val->next;
1315 }
1316
1317 UNGCPRO;
1318 }
1319 return Qnil;
1320 }
1321
1322 int
1323 x_kludge_lw_menu_active (void)
1324 {
1325 return lw_menu_active;
1326 }
1327
1328 DEFUN ("accelerate-menu", Faccelerate_menu, 0, 0, "_", /*
1329 Make the menubar active. Menu items can be selected using menu accelerators
1330 or by actions defined in menu-accelerator-map.
1331 */
1332 ())
1333 {
1334 struct console *con = XCONSOLE (Vselected_console);
1335 struct frame *f = XFRAME (CONSOLE_SELECTED_FRAME (con));
1336 LWLIB_ID id;
1337 widget_value *val;
1338
1339 if (NILP (f->menubar_data))
1340 error ("Frame has no menubar.");
1341
1342 id = XPOPUP_DATA (f->menubar_data)->id;
1343 val = lw_get_all_values (id);
1344 val = val->contents;
1345 lw_set_menu (FRAME_X_MENUBAR_WIDGET (f), val);
1346 lw_map_menu (CurrentTime);
1347
1348 lw_display_menu (CurrentTime);
1349
1350 /* menu accelerator keys don't go into keyboard macros */
1351 if (!NILP (con->defining_kbd_macro) && NILP (Vexecuting_macro))
1352 con->kbd_macro_ptr = con->kbd_macro_end;
1353
1354 return Qnil;
1355 }
1356 #endif /* LWLIB_MENUBARS_LUCID */
1357
1358
1359 void 843 void
1360 syms_of_menubar_x (void) 844 syms_of_menubar_x (void)
1361 { 845 {
1362 #if defined(LWLIB_MENUBARS_LUCID)
1363 DEFSUBR (Faccelerate_menu);
1364 #endif
1365 } 846 }
1366 847
1367 void 848 void
1368 console_type_create_menubar_x (void) 849 console_type_create_menubar_x (void)
1369 { 850 {
1371 CONSOLE_HAS_METHOD (x, free_frame_menubars); 852 CONSOLE_HAS_METHOD (x, free_frame_menubars);
1372 CONSOLE_HAS_METHOD (x, popup_menu); 853 CONSOLE_HAS_METHOD (x, popup_menu);
1373 } 854 }
1374 855
1375 void 856 void
1376 reinit_vars_of_menubar_x (void) 857 vars_of_menubar_x (void)
1377 { 858 {
1378 last_popup_menu_selection_callback_id = (LWLIB_ID) -1; 859 last_popup_menu_selection_callback_id = (LWLIB_ID) -1;
1379 }
1380
1381 void
1382 vars_of_menubar_x (void)
1383 {
1384 reinit_vars_of_menubar_x ();
1385 860
1386 #if defined (LWLIB_MENUBARS_LUCID) 861 #if defined (LWLIB_MENUBARS_LUCID)
1387 Fprovide (intern ("lucid-menubars")); 862 Fprovide (intern ("lucid-menubars"));
1388 #elif defined (LWLIB_MENUBARS_MOTIF) 863 #elif defined (LWLIB_MENUBARS_MOTIF)
1389 Fprovide (intern ("motif-menubars")); 864 Fprovide (intern ("motif-menubars"));