Mercurial > hg > xemacs-beta
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 { |