Mercurial > hg > xemacs-beta
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")); |