comparison src/menubar-x.c @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents 8de8e3f6228a
children 576fb035e263
comparison
equal deleted inserted replaced
441:72a7cfa4a488 442:abe6d1db359e
1 /* Implements an elisp-programmable menubar -- X interface. 1 /* Implements an elisp-programmable menubar -- X interface.
2 Copyright (C) 1993, 1994 Free Software Foundation, Inc. 2 Copyright (C) 1993, 1994 Free Software Foundation, Inc.
3 Copyright (C) 1995 Tinker Systems and INS Engineering Corp. 3 Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
4 Copyright (C) 2000 Ben Wing.
4 5
5 This file is part of XEmacs. 6 This file is part of XEmacs.
6 7
7 XEmacs is free software; you can redistribute it and/or modify it 8 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the 9 under the terms of the GNU General Public License as published by the
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */ 21 Boston, MA 02111-1307, USA. */
21 22
22 /* Synched up with: Not in FSF. */ 23 /* Synched up with: Not in FSF. */
23 24
24 /* created 16-dec-91 by jwz */ 25 /* This file Mule-ized by Ben Wing, 7-8-00. */
26
27 /* Authorship:
28
29 Created 16-dec-91 by Jamie Zawinski.
30 Menu filters and many other keywords added by Stig for 19.12.
31 Original device-abstraction work and GC cleanup work by Ben Wing for 19.13.
32 Menu accelerators c. 1997? by ??. Moved here from event-stream.c.
33 Other work post-1996 by ??.
34 */
25 35
26 #include <config.h> 36 #include <config.h>
27 #include "lisp.h" 37 #include "lisp.h"
28 38
29 #include "console-x.h" 39 #include "console-x.h"
30 #include "EmacsFrame.h" 40 #include "EmacsFrame.h"
31 #include "gui-x.h" 41 #include "gui-x.h"
42 #include "../lwlib/lwlib.h"
32 43
33 #include "buffer.h" 44 #include "buffer.h"
34 #include "commands.h" /* zmacs_regions */ 45 #include "commands.h" /* zmacs_regions */
35 #include "gui.h"
36 #include "events.h" 46 #include "events.h"
37 #include "frame.h" 47 #include "frame.h"
48 #include "gui.h"
49 #include "keymap.h"
50 #include "menubar.h"
38 #include "opaque.h" 51 #include "opaque.h"
39 #include "window.h" 52 #include "window.h"
40 53
41 static int set_frame_menubar (struct frame *f, 54 static int set_frame_menubar (struct frame *f,
42 int deep_p, 55 int deep_p,
90 int depth) 103 int depth)
91 { 104 {
92 /* This function cannot GC. 105 /* This function cannot GC.
93 It is only called from menu_item_descriptor_to_widget_value, which 106 It is only called from menu_item_descriptor_to_widget_value, which
94 prohibits GC. */ 107 prohibits GC. */
95 /* !!#### This function has not been Mule-ized */
96 int menubar_root_p = (menu_type == MENUBAR_TYPE && depth == 0); 108 int menubar_root_p = (menu_type == MENUBAR_TYPE && depth == 0);
97 int count = specpdl_depth (); 109 int count = specpdl_depth ();
98 int partition_seen = 0; 110 int partition_seen = 0;
99 widget_value *wv = xmalloc_widget_value (); 111 widget_value *wv = xmalloc_widget_value ();
100 Lisp_Object wv_closure = make_opaque_ptr (wv); 112 Lisp_Object wv_closure = make_opaque_ptr (wv);
101 113
102 record_unwind_protect (widget_value_unwind, wv_closure); 114 record_unwind_protect (widget_value_unwind, wv_closure);
103 115
104 if (STRINGP (desc)) 116 if (STRINGP (desc))
105 { 117 {
106 char *string_chars = (char *) XSTRING_DATA (desc); 118 Bufbyte *string_chars = XSTRING_DATA (desc);
107 wv->type = (separator_string_p (string_chars) ? SEPARATOR_TYPE : 119 wv->type = (separator_string_p (string_chars) ? SEPARATOR_TYPE :
108 TEXT_TYPE); 120 TEXT_TYPE);
109 #if 1
110 /* #### - should internationalize with X resources instead.
111 Not so! --ben */
112 string_chars = GETTEXT (string_chars);
113 #endif
114 if (wv->type == SEPARATOR_TYPE) 121 if (wv->type == SEPARATOR_TYPE)
115 { 122 {
116 wv->value = menu_separator_style (string_chars); 123 wv->value = menu_separator_style_and_to_external (string_chars);
117 } 124 }
118 else 125 else
119 { 126 {
120 wv->name = xstrdup (string_chars); 127 LISP_STRING_TO_EXTERNAL_MALLOC (desc, wv->name, Qlwlib_encoding);
121 wv->enabled = 1; 128 wv->enabled = 1;
122 /* dverna Dec. 98: command_builder_operate_menu_accelerator will 129 /* dverna Dec. 98: command_builder_operate_menu_accelerator will
123 manipulate the accel as a Lisp_Object if the widget has a name. 130 manipulate the accel as a Lisp_Object if the widget has a name.
124 Since simple labels have a name, but no accel, we *must* set it 131 Since simple labels have a name, but no accel, we *must* set it
125 to nil */ 132 to nil */
127 } 134 }
128 } 135 }
129 else if (VECTORP (desc)) 136 else if (VECTORP (desc))
130 { 137 {
131 Lisp_Object gui_item = gui_parse_item_keywords (desc); 138 Lisp_Object gui_item = gui_parse_item_keywords (desc);
132 if (!button_item_to_widget_value (gui_item, wv, 1, 139 if (!button_item_to_widget_value (Qmenubar,
140 gui_item, wv, 1,
133 (menu_type == MENUBAR_TYPE 141 (menu_type == MENUBAR_TYPE
134 && depth <= 1))) 142 && depth <= 1), 1, 1))
135 { 143 {
136 /* :included form was nil */ 144 /* :included form was nil */
137 wv = NULL; 145 wv = NULL;
138 goto menu_item_done; 146 goto menu_item_done;
139 } 147 }
151 Lisp_Object accel; 159 Lisp_Object accel;
152 int included_spec = 0; 160 int included_spec = 0;
153 int active_spec = 0; 161 int active_spec = 0;
154 wv->type = CASCADE_TYPE; 162 wv->type = CASCADE_TYPE;
155 wv->enabled = 1; 163 wv->enabled = 1;
156 wv->name = (char *) XSTRING_DATA (LISP_GETTEXT (XCAR (desc))); 164 wv->name = add_accel_and_to_external (XCAR (desc));
157 wv->name = xstrdup (wv->name); 165
158 166 accel = gui_name_accelerator (XCAR (desc));
159 accel = gui_name_accelerator (LISP_GETTEXT (XCAR (desc)));
160 wv->accel = LISP_TO_VOID (accel); 167 wv->accel = LISP_TO_VOID (accel);
161 168
162 desc = Fcdr (desc); 169 desc = Fcdr (desc);
163 170
164 while (key = Fcar (desc), KEYWORDP (key)) 171 while (key = Fcar (desc), KEYWORDP (key))
165 { 172 {
166 Lisp_Object cascade = desc; 173 Lisp_Object cascade = desc;
167 desc = Fcdr (desc); 174 desc = Fcdr (desc);
168 if (NILP (desc)) 175 if (NILP (desc))
169 signal_simple_error ("Keyword in menu lacks a value", 176 syntax_error ("Keyword in menu lacks a value", cascade);
170 cascade);
171 val = Fcar (desc); 177 val = Fcar (desc);
172 desc = Fcdr (desc); 178 desc = Fcdr (desc);
173 if (EQ (key, Q_included)) 179 if (EQ (key, Q_included))
174 include_p = val, included_spec = 1; 180 include_p = val, included_spec = 1;
175 else if (EQ (key, Q_config)) 181 else if (EQ (key, Q_config))
182 { 188 {
183 if ( SYMBOLP (val) 189 if ( SYMBOLP (val)
184 || CHARP (val)) 190 || CHARP (val))
185 wv->accel = LISP_TO_VOID (val); 191 wv->accel = LISP_TO_VOID (val);
186 else 192 else
187 signal_simple_error ("bad keyboard accelerator", val); 193 syntax_error ("bad keyboard accelerator", val);
188 } 194 }
189 else if (EQ (key, Q_label)) 195 else if (EQ (key, Q_label))
190 { 196 {
191 /* implement in 21.2 */ 197 /* implement in 21.2 */
192 } 198 }
193 else 199 else
194 signal_simple_error ("Unknown menu cascade keyword", cascade); 200 syntax_error ("Unknown menu cascade keyword", cascade);
195 } 201 }
196 202
197 if ((!NILP (config_tag) 203 if ((!NILP (config_tag)
198 && NILP (Fmemq (config_tag, Vmenubar_configuration))) 204 && NILP (Fmemq (config_tag, Vmenubar_configuration)))
199 || (included_spec && NILP (Feval (include_p)))) 205 || (included_spec && NILP (Feval (include_p))))
243 title_wv->type = TEXT_TYPE; 249 title_wv->type = TEXT_TYPE;
244 title_wv->name = xstrdup (wv->name); 250 title_wv->name = xstrdup (wv->name);
245 title_wv->enabled = 1; 251 title_wv->enabled = 1;
246 title_wv->next = sep_wv; 252 title_wv->next = sep_wv;
247 sep_wv->type = SEPARATOR_TYPE; 253 sep_wv->type = SEPARATOR_TYPE;
248 sep_wv->value = menu_separator_style ("=="); 254 sep_wv->value = menu_separator_style_and_to_external ("==");
249 sep_wv->next = 0; 255 sep_wv->next = 0;
250 256
251 wv->contents = title_wv; 257 wv->contents = title_wv;
252 prev = sep_wv; 258 prev = sep_wv;
253 } 259 }
265 dummy->type = BUTTON_TYPE; 271 dummy->type = BUTTON_TYPE;
266 dummy->call_data = NULL; 272 dummy->call_data = NULL;
267 dummy->next = NULL; 273 dummy->next = NULL;
268 274
269 goto menu_item_done; 275 goto menu_item_done;
270 } 276 }
271 277
272 } 278 }
273 else if (menubar_root_p) 279 else if (menubar_root_p)
274 { 280 {
275 wv->name = xstrdup ("menubar"); 281 wv->name = xstrdup ("menubar");
276 wv->type = CASCADE_TYPE; /* Well, nothing else seems to fit and 282 wv->type = CASCADE_TYPE; /* Well, nothing else seems to fit and
277 this is ignored anyway... */ 283 this is ignored anyway... */
278 } 284 }
279 else 285 else
280 { 286 {
281 signal_simple_error ("Menu name (first element) must be a string", 287 syntax_error ("Menu name (first element) must be a string", desc);
282 desc);
283 } 288 }
284 289
285 if (deep_p || menubar_root_p) 290 if (deep_p || menubar_root_p)
286 { 291 {
287 widget_value *next; 292 widget_value *next;
289 { 294 {
290 Lisp_Object child = Fcar (desc); 295 Lisp_Object child = Fcar (desc);
291 if (menubar_root_p && NILP (child)) /* the partition */ 296 if (menubar_root_p && NILP (child)) /* the partition */
292 { 297 {
293 if (partition_seen) 298 if (partition_seen)
294 error ( 299 syntax_error
295 "More than one partition (nil) in menubar description"); 300 ("More than one partition (nil) in menubar description",
301 desc);
296 partition_seen = 1; 302 partition_seen = 1;
297 next = xmalloc_widget_value (); 303 next = xmalloc_widget_value ();
298 next->type = PUSHRIGHT_TYPE; 304 next->type = PUSHRIGHT_TYPE;
299 } 305 }
300 else 306 else
313 } 319 }
314 if (deep_p && !wv->contents) 320 if (deep_p && !wv->contents)
315 wv = NULL; 321 wv = NULL;
316 } 322 }
317 else if (NILP (desc)) 323 else if (NILP (desc))
318 error ("nil may not appear in menu descriptions"); 324 syntax_error ("nil may not appear in menu descriptions", desc);
319 else 325 else
320 signal_simple_error ("Unrecognized menu descriptor", desc); 326 syntax_error ("Unrecognized menu descriptor", desc);
321 327
322 menu_item_done: 328 menu_item_done:
323 329
324 if (wv) 330 if (wv)
325 { 331 {
326 /* Completed normally. Clear out the object that widget_value_unwind() 332 /* Completed normally. Clear out the object that widget_value_unwind()
327 will be called with to tell it not to free the wv (as we are 333 will be called with to tell it not to free the wv (as we are
334 } 340 }
335 341
336 static widget_value * 342 static widget_value *
337 menu_item_descriptor_to_widget_value (Lisp_Object desc, 343 menu_item_descriptor_to_widget_value (Lisp_Object desc,
338 int menu_type, /* if this is a menubar, 344 int menu_type, /* if this is a menubar,
339 popup or sub menu */ 345 popup or sub menu */
340 int deep_p, /* */ 346 int deep_p, /* */
341 int filter_p) /* if :filter forms 347 int filter_p) /* if :filter forms
342 should run now */ 348 should run now */
343 { 349 {
344 widget_value *wv; 350 widget_value *wv;
358 int in_menu_callback; 364 int in_menu_callback;
359 365
360 static Lisp_Object 366 static Lisp_Object
361 restore_in_menu_callback (Lisp_Object val) 367 restore_in_menu_callback (Lisp_Object val)
362 { 368 {
363 in_menu_callback = XINT (val); 369 in_menu_callback = XINT (val);
364 return Qnil; 370 return Qnil;
365 } 371 }
366 #endif /* LWLIB_MENUBARS_LUCID || LWLIB_MENUBARS_MOTIF */ 372 #endif /* LWLIB_MENUBARS_LUCID || LWLIB_MENUBARS_MOTIF */
367 373
368 #if 0 374 #if 0
369 /* #### Sort of a hack needed to process Vactivate_menubar_hook 375 /* #### Sort of a hack needed to process Vactivate_menubar_hook
828 834
829 So there are two command-events, with a bunch of magic-events between 835 So there are two command-events, with a bunch of magic-events between
830 them. We don't want the *first* command event to alter the state of the 836 them. We don't want the *first* command event to alter the state of the
831 region, so that the region can be available as an argument for the second 837 region, so that the region can be available as an argument for the second
832 command. 838 command.
833 */ 839 */
834 if (zmacs_regions) 840 if (zmacs_regions)
835 zmacs_region_stays = 1; 841 zmacs_region_stays = 1;
836 842
837 popup_up_p++; 843 popup_up_p++;
838 lw_popup_menu (menu, &xev); 844 lw_popup_menu (menu, &xev);
839 /* this speeds up display of pop-up menus */ 845 /* this speeds up display of pop-up menus */
840 XFlush (XtDisplay (parent)); 846 XFlush (XtDisplay (parent));
841 } 847 }
842 848
843 849
850
851 #if defined(LWLIB_MENUBARS_LUCID)
852 static void
853 menu_move_up (void)
854 {
855 widget_value *current = lw_get_entries (False);
856 widget_value *entries = lw_get_entries (True);
857 widget_value *prev = NULL;
858
859 while (entries != current)
860 {
861 if (entries->name /*&& entries->enabled*/) prev = entries;
862 entries = entries->next;
863 assert (entries);
864 }
865
866 if (!prev)
867 /* move to last item */
868 {
869 while (entries->next)
870 {
871 if (entries->name /*&& entries->enabled*/) prev = entries;
872 entries = entries->next;
873 }
874 if (prev)
875 {
876 if (entries->name /*&& entries->enabled*/)
877 prev = entries;
878 }
879 else
880 {
881 /* no selectable items in this menu, pop up to previous level */
882 lw_pop_menu ();
883 return;
884 }
885 }
886 lw_set_item (prev);
887 }
888
889 static void
890 menu_move_down (void)
891 {
892 widget_value *current = lw_get_entries (False);
893 widget_value *new = current;
894
895 while (new->next)
896 {
897 new = new->next;
898 if (new->name /*&& new->enabled*/) break;
899 }
900
901 if (new==current||!(new->name/*||new->enabled*/))
902 {
903 new = lw_get_entries (True);
904 while (new!=current)
905 {
906 if (new->name /*&& new->enabled*/) break;
907 new = new->next;
908 }
909 if (new==current&&!(new->name /*|| new->enabled*/))
910 {
911 lw_pop_menu ();
912 return;
913 }
914 }
915
916 lw_set_item (new);
917 }
918
919 static void
920 menu_move_left (void)
921 {
922 int level = lw_menu_level ();
923 int l = level;
924 widget_value *current;
925
926 while (level-- >= 3)
927 lw_pop_menu ();
928
929 menu_move_up ();
930 current = lw_get_entries (False);
931 if (l > 2 && current->contents)
932 lw_push_menu (current->contents);
933 }
934
935 static void
936 menu_move_right (void)
937 {
938 int level = lw_menu_level ();
939 int l = level;
940 widget_value *current;
941
942 while (level-- >= 3)
943 lw_pop_menu ();
944
945 menu_move_down ();
946 current = lw_get_entries (False);
947 if (l > 2 && current->contents)
948 lw_push_menu (current->contents);
949 }
950
951 static void
952 menu_select_item (widget_value *val)
953 {
954 if (val == NULL)
955 val = lw_get_entries (False);
956
957 /* is match a submenu? */
958
959 if (val->contents)
960 {
961 /* enter the submenu */
962
963 lw_set_item (val);
964 lw_push_menu (val->contents);
965 }
966 else
967 {
968 /* Execute the menu entry by calling the menu's `select'
969 callback function
970 */
971 lw_kill_menus (val);
972 }
973 }
974
975 Lisp_Object
976 command_builder_operate_menu_accelerator (struct command_builder *builder)
977 {
978 /* this function can GC */
979
980 struct console *con = XCONSOLE (Vselected_console);
981 Lisp_Object evee = builder->most_current_event;
982 Lisp_Object binding;
983 widget_value *entries;
984
985 extern int lw_menu_accelerate; /* lwlib.c */
986
987 #if 0
988 {
989 int i;
990 Lisp_Object t;
991 char buf[50];
992
993 t = builder->current_events;
994 i = 0;
995 while (!NILP (t))
996 {
997 i++;
998 sprintf (buf,"OPERATE (%d): ",i);
999 write_c_string (buf, Qexternal_debugging_output);
1000 print_internal (t, Qexternal_debugging_output, 1);
1001 write_c_string ("\n", Qexternal_debugging_output);
1002 t = XEVENT_NEXT (t);
1003 }
1004 }
1005 #endif /* 0 */
1006
1007 /* menu accelerator keys don't go into keyboard macros */
1008 if (!NILP (con->defining_kbd_macro) && NILP (Vexecuting_macro))
1009 con->kbd_macro_ptr = con->kbd_macro_end;
1010
1011 /* don't echo menu accelerator keys */
1012 /*reset_key_echo (builder, 1);*/
1013
1014 if (!lw_menu_accelerate)
1015 {
1016 /* `convert' mouse display to keyboard display
1017 by entering the open submenu
1018 */
1019 entries = lw_get_entries (False);
1020 if (entries->contents)
1021 {
1022 lw_push_menu (entries->contents);
1023 lw_display_menu (CurrentTime);
1024 }
1025 }
1026
1027 /* compare event to the current menu accelerators */
1028
1029 entries=lw_get_entries (True);
1030
1031 while (entries)
1032 {
1033 Lisp_Object accel;
1034 VOID_TO_LISP (accel, entries->accel);
1035 if (entries->name && !NILP (accel))
1036 {
1037 if (event_matches_key_specifier_p (XEVENT (evee), accel))
1038 {
1039 /* a match! */
1040
1041 menu_select_item (entries);
1042
1043 if (lw_menu_active) lw_display_menu (CurrentTime);
1044
1045 reset_this_command_keys (Vselected_console, 1);
1046 /*reset_command_builder_event_chain (builder);*/
1047 return Vmenu_accelerator_map;
1048 }
1049 }
1050 entries = entries->next;
1051 }
1052
1053 /* try to look up event in menu-accelerator-map */
1054
1055 binding = event_binding_in (evee, Vmenu_accelerator_map, 1);
1056
1057 if (NILP (binding))
1058 {
1059 /* beep at user for undefined key */
1060 return Qnil;
1061 }
1062 else
1063 {
1064 if (EQ (binding, Qmenu_quit))
1065 {
1066 /* turn off menus and set quit flag */
1067 lw_kill_menus (NULL);
1068 Vquit_flag = Qt;
1069 }
1070 else if (EQ (binding, Qmenu_up))
1071 {
1072 int level = lw_menu_level ();
1073 if (level > 2)
1074 menu_move_up ();
1075 }
1076 else if (EQ (binding, Qmenu_down))
1077 {
1078 int level = lw_menu_level ();
1079 if (level > 2)
1080 menu_move_down ();
1081 else
1082 menu_select_item (NULL);
1083 }
1084 else if (EQ (binding, Qmenu_left))
1085 {
1086 int level = lw_menu_level ();
1087 if (level > 3)
1088 {
1089 lw_pop_menu ();
1090 lw_display_menu (CurrentTime);
1091 }
1092 else
1093 menu_move_left ();
1094 }
1095 else if (EQ (binding, Qmenu_right))
1096 {
1097 int level = lw_menu_level ();
1098 if (level > 2 &&
1099 lw_get_entries (False)->contents)
1100 {
1101 widget_value *current = lw_get_entries (False);
1102 if (current->contents)
1103 menu_select_item (NULL);
1104 }
1105 else
1106 menu_move_right ();
1107 }
1108 else if (EQ (binding, Qmenu_select))
1109 menu_select_item (NULL);
1110 else if (EQ (binding, Qmenu_escape))
1111 {
1112 int level = lw_menu_level ();
1113
1114 if (level > 2)
1115 {
1116 lw_pop_menu ();
1117 lw_display_menu (CurrentTime);
1118 }
1119 else
1120 {
1121 /* turn off menus quietly */
1122 lw_kill_menus (NULL);
1123 }
1124 }
1125 else if (KEYMAPP (binding))
1126 {
1127 /* prefix key */
1128 reset_this_command_keys (Vselected_console, 1);
1129 /*reset_command_builder_event_chain (builder);*/
1130 return binding;
1131 }
1132 else
1133 {
1134 /* turn off menus and execute binding */
1135 lw_kill_menus (NULL);
1136 reset_this_command_keys (Vselected_console, 1);
1137 /*reset_command_builder_event_chain (builder);*/
1138 return binding;
1139 }
1140 }
1141
1142 if (lw_menu_active) lw_display_menu (CurrentTime);
1143
1144 reset_this_command_keys (Vselected_console, 1);
1145 /*reset_command_builder_event_chain (builder);*/
1146
1147 return Vmenu_accelerator_map;
1148 }
1149
1150 static Lisp_Object
1151 menu_accelerator_junk_on_error (Lisp_Object errordata, Lisp_Object ignored)
1152 {
1153 Vmenu_accelerator_prefix = Qnil;
1154 Vmenu_accelerator_modifiers = Qnil;
1155 Vmenu_accelerator_enabled = Qnil;
1156 if (!NILP (errordata))
1157 {
1158 Lisp_Object args[2];
1159
1160 args[0] = build_string ("Error in menu accelerators (setting to nil)");
1161 /* #### This should call
1162 (with-output-to-string (display-error errordata))
1163 but that stuff is all in Lisp currently. */
1164 args[1] = errordata;
1165 warn_when_safe_lispobj
1166 (Qerror, Qwarning,
1167 emacs_doprnt_string_lisp ((const Bufbyte *) "%s: %s",
1168 Qnil, -1, 2, args));
1169 }
1170
1171 return Qnil;
1172 }
1173
1174 static Lisp_Object
1175 menu_accelerator_safe_compare (Lisp_Object event0)
1176 {
1177 if (CONSP (Vmenu_accelerator_prefix))
1178 {
1179 Lisp_Object t;
1180 t=Vmenu_accelerator_prefix;
1181 while (!NILP (t)
1182 && !NILP (event0)
1183 && event_matches_key_specifier_p (XEVENT (event0), Fcar (t)))
1184 {
1185 t = Fcdr (t);
1186 event0 = XEVENT_NEXT (event0);
1187 }
1188 if (!NILP (t))
1189 return Qnil;
1190 }
1191 else if (NILP (event0))
1192 return Qnil;
1193 else if (event_matches_key_specifier_p (XEVENT (event0), Vmenu_accelerator_prefix))
1194 event0 = XEVENT_NEXT (event0);
1195 else
1196 return Qnil;
1197 return event0;
1198 }
1199
1200 static Lisp_Object
1201 menu_accelerator_safe_mod_compare (Lisp_Object cons)
1202 {
1203 return (event_matches_key_specifier_p (XEVENT (XCAR (cons)), XCDR (cons))
1204 ? Qt
1205 : Qnil);
1206 }
1207
1208 Lisp_Object
1209 command_builder_find_menu_accelerator (struct command_builder *builder)
1210 {
1211 /* this function can GC */
1212 Lisp_Object event0 = builder->current_events;
1213 struct console *con = XCONSOLE (Vselected_console);
1214 struct frame *f = XFRAME (CONSOLE_SELECTED_FRAME (con));
1215 Widget menubar_widget;
1216
1217 /* compare entries in event0 against the menu prefix */
1218
1219 if ((!CONSOLE_X_P (XCONSOLE (builder->console))) || NILP (event0) ||
1220 XEVENT (event0)->event_type != key_press_event)
1221 return Qnil;
1222
1223 if (!NILP (Vmenu_accelerator_prefix))
1224 {
1225 event0 = condition_case_1 (Qerror,
1226 menu_accelerator_safe_compare,
1227 event0,
1228 menu_accelerator_junk_on_error,
1229 Qnil);
1230 }
1231
1232 if (NILP (event0))
1233 return Qnil;
1234
1235 menubar_widget = FRAME_X_MENUBAR_WIDGET (f);
1236 if (menubar_widget
1237 && CONSP (Vmenu_accelerator_modifiers))
1238 {
1239 Lisp_Object fake;
1240 Lisp_Object last = Qnil;
1241 struct gcpro gcpro1;
1242 Lisp_Object matchp;
1243
1244 widget_value *val;
1245 LWLIB_ID id = XPOPUP_DATA (f->menubar_data)->id;
1246
1247 val = lw_get_all_values (id);
1248 if (val)
1249 {
1250 val = val->contents;
1251
1252 fake = Fcopy_sequence (Vmenu_accelerator_modifiers);
1253 last = fake;
1254
1255 while (!NILP (Fcdr (last)))
1256 last = Fcdr (last);
1257
1258 Fsetcdr (last, Fcons (Qnil, Qnil));
1259 last = Fcdr (last);
1260 }
1261
1262 fake = Fcons (Qnil, fake);
1263
1264 GCPRO1 (fake);
1265
1266 while (val)
1267 {
1268 Lisp_Object accel;
1269 VOID_TO_LISP (accel, val->accel);
1270 if (val->name && !NILP (accel))
1271 {
1272 Fsetcar (last, accel);
1273 Fsetcar (fake, event0);
1274 matchp = condition_case_1 (Qerror,
1275 menu_accelerator_safe_mod_compare,
1276 fake,
1277 menu_accelerator_junk_on_error,
1278 Qnil);
1279 if (!NILP (matchp))
1280 {
1281 /* we found one! */
1282
1283 lw_set_menu (menubar_widget, val);
1284 /* yah - yet another hack.
1285 pretend emacs timestamp is the same as an X timestamp,
1286 which for the moment it is. (read events.h)
1287 */
1288 lw_map_menu (XEVENT (event0)->timestamp);
1289
1290 if (val->contents)
1291 lw_push_menu (val->contents);
1292
1293 lw_display_menu (CurrentTime);
1294
1295 /* menu accelerator keys don't go into keyboard macros */
1296 if (!NILP (con->defining_kbd_macro)
1297 && NILP (Vexecuting_macro))
1298 con->kbd_macro_ptr = con->kbd_macro_end;
1299
1300 /* don't echo menu accelerator keys */
1301 /*reset_key_echo (builder, 1);*/
1302 reset_this_command_keys (Vselected_console, 1);
1303 UNGCPRO;
1304
1305 return Vmenu_accelerator_map;
1306 }
1307 }
1308
1309 val = val->next;
1310 }
1311
1312 UNGCPRO;
1313 }
1314 return Qnil;
1315 }
1316
1317 int
1318 x_kludge_lw_menu_active (void)
1319 {
1320 return lw_menu_active;
1321 }
1322
1323 DEFUN ("accelerate-menu", Faccelerate_menu, 0, 0, "_", /*
1324 Make the menubar active. Menu items can be selected using menu accelerators
1325 or by actions defined in menu-accelerator-map.
1326 */
1327 ())
1328 {
1329 struct console *con = XCONSOLE (Vselected_console);
1330 struct frame *f = XFRAME (CONSOLE_SELECTED_FRAME (con));
1331 LWLIB_ID id;
1332 widget_value *val;
1333
1334 if (NILP (f->menubar_data))
1335 error ("Frame has no menubar.");
1336
1337 id = XPOPUP_DATA (f->menubar_data)->id;
1338 val = lw_get_all_values (id);
1339 val = val->contents;
1340 lw_set_menu (FRAME_X_MENUBAR_WIDGET (f), val);
1341 lw_map_menu (CurrentTime);
1342
1343 lw_display_menu (CurrentTime);
1344
1345 /* menu accelerator keys don't go into keyboard macros */
1346 if (!NILP (con->defining_kbd_macro) && NILP (Vexecuting_macro))
1347 con->kbd_macro_ptr = con->kbd_macro_end;
1348
1349 return Qnil;
1350 }
1351 #endif /* LWLIB_MENUBARS_LUCID */
1352
1353
844 void 1354 void
845 syms_of_menubar_x (void) 1355 syms_of_menubar_x (void)
846 { 1356 {
1357 #if defined(LWLIB_MENUBARS_LUCID)
1358 DEFSUBR (Faccelerate_menu);
1359 #endif
847 } 1360 }
848 1361
849 void 1362 void
850 console_type_create_menubar_x (void) 1363 console_type_create_menubar_x (void)
851 { 1364 {