1 /* Implements an elisp-programmable menubar -- X interface.
2 Copyright (C) 1993, 1994 Free Software Foundation, Inc.
3 Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
5 This file is part of XEmacs.
7 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 Free Software Foundation; either version 2, or (at your option) any
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* Synched up with: Not in FSF. */
24 /* created 16-dec-91 by jwz */
29 #include "console-x.h"
30 #include "EmacsFrame.h"
34 #include "commands.h" /* zmacs_regions */
41 static int set_frame_menubar (struct frame *f,
45 #define FRAME_MENUBAR_DATA(frame) ((frame)->menubar_data)
46 #define XFRAME_MENUBAR_DATA(frame) XPOPUP_DATA ((frame)->menubar_data)
48 #define MENUBAR_TYPE 0
49 #define SUBMENU_TYPE 1
53 /* Converting Lisp menu tree descriptions to lwlib's `widget_value' form.
55 menu_item_descriptor_to_widget_value() converts a lisp description of a
56 menubar into a tree of widget_value structures. It allocates widget_values
57 with malloc_widget_value() and allocates other storage only for the `key'
58 slot. All other slots are filled with pointers to Lisp_String data. We
59 allocate a widget_value description of the menu or menubar, and hand it to
60 lwlib, which then makes a copy of it, which it manages internally. We then
61 immediately free our widget_value tree; it will not be referenced again.
63 Incremental menu construction callbacks operate just a bit differently.
64 They allocate widget_values and call replace_widget_value_tree() to tell
65 lwlib to destructively modify the incremental stub (subtree) of its
66 separate widget_value tree.
68 This function is highly recursive (it follows the menu trees) and may call
69 eval. The reason we keep pointers to lisp string data instead of copying
70 it and freeing it later is to avoid the speed penalty that would entail
71 (since this needs to be fast, in the simple cases at least). (The reason
72 we malloc/free the keys slot is because there's not a lisp string around
73 for us to use in that case.)
75 Since we keep pointers to lisp strings, and we call eval, we could lose if
76 GC relocates (or frees) those strings. It's not easy to gc protect the
77 strings because of the recursive nature of this function, and the fact that
78 it returns a data structure that gets freed later. So... we do the
79 sleaziest thing possible and inhibit GC for the duration. This is probably
82 We do not have to worry about the pointers to Lisp_String data after
83 this function successfully finishes. lwlib copies all such data with
87 menu_item_descriptor_to_widget_value_1 (Lisp_Object desc,
88 int menu_type, int deep_p,
92 /* This function cannot GC.
93 It is only called from menu_item_descriptor_to_widget_value, which
95 /* !!#### This function has not been Mule-ized */
96 int menubar_root_p = (menu_type == MENUBAR_TYPE && depth == 0);
98 Lisp_Object wv_closure;
99 int count = specpdl_depth ();
100 int partition_seen = 0;
102 wv = xmalloc_widget_value ();
104 wv_closure = make_opaque_ptr (wv);
105 record_unwind_protect (widget_value_unwind, wv_closure);
109 char *string_chars = (char *) XSTRING_DATA (desc);
110 wv->type = (separator_string_p (string_chars) ? SEPARATOR_TYPE :
113 /* #### - should internationalize with X resources instead.
115 string_chars = GETTEXT (string_chars);
117 if (wv->type == SEPARATOR_TYPE)
119 wv->value = menu_separator_style (string_chars);
123 wv->name = xstrdup (string_chars);
125 /* dverna Dec. 98: command_builder_operate_menu_accelerator will
126 manipulate the accel as a Lisp_Object if the widget has a name.
127 Since simple labels have a name, but no accel, we *must* set it
129 wv->accel = LISP_TO_VOID (Qnil);
132 else if (VECTORP (desc))
134 Lisp_Object gui_item = gui_parse_item_keywords (desc);
135 if (!button_item_to_widget_value (gui_item, wv, 1,
136 (menu_type == MENUBAR_TYPE
139 /* :included form was nil */
144 else if (CONSP (desc))
146 Lisp_Object incremental_data = desc;
147 widget_value *prev = 0;
149 if (STRINGP (XCAR (desc)))
151 Lisp_Object key, val;
152 Lisp_Object include_p = Qnil, hook_fn = Qnil, config_tag = Qnil;
153 Lisp_Object active_p = Qt;
155 int included_spec = 0;
157 wv->type = CASCADE_TYPE;
159 wv->name = (char *) XSTRING_DATA (LISP_GETTEXT (XCAR (desc)));
160 wv->name = xstrdup (wv->name);
162 accel = gui_name_accelerator (LISP_GETTEXT (XCAR (desc)));
163 wv->accel = LISP_TO_VOID (accel);
167 while (key = Fcar (desc), KEYWORDP (key))
169 Lisp_Object cascade = desc;
172 signal_simple_error ("Keyword in menu lacks a value",
176 if (EQ (key, Q_included))
177 include_p = val, included_spec = 1;
178 else if (EQ (key, Q_config))
180 else if (EQ (key, Q_filter))
182 else if (EQ (key, Q_active))
183 active_p = val, active_spec = 1;
184 else if (EQ (key, Q_accelerator))
188 wv->accel = LISP_TO_VOID (val);
190 signal_simple_error ("bad keyboard accelerator", val);
192 else if (EQ (key, Q_label))
194 /* implement in 21.2 */
197 signal_simple_error ("Unknown menu cascade keyword", cascade);
200 if ((!NILP (config_tag)
201 && NILP (Fmemq (config_tag, Vmenubar_configuration)))
202 || (included_spec && NILP (Feval (include_p))))
209 active_p = Feval (active_p);
211 if (!NILP (hook_fn) && !NILP (active_p))
213 #if defined LWLIB_MENUBARS_LUCID || defined LWLIB_MENUBARS_MOTIF
214 if (filter_p || depth == 0)
217 desc = call1_trapping_errors ("Error in menubar filter",
221 #if defined LWLIB_MENUBARS_LUCID || defined LWLIB_MENUBARS_MOTIF
225 widget_value *incr_wv = xmalloc_widget_value ();
226 wv->contents = incr_wv;
227 incr_wv->type = INCREMENTAL_TYPE;
228 incr_wv->enabled = 1;
229 incr_wv->name = wv->name;
230 incr_wv->name = xstrdup (wv->name);
231 /* This is automatically GC protected through
232 the call to lw_map_widget_values(); no need
234 incr_wv->call_data = LISP_TO_VOID (incremental_data);
237 #endif /* LWLIB_MENUBARS_LUCID || LWLIB_MENUBARS_MOTIF */
239 if (menu_type == POPUP_TYPE && popup_menu_titles && depth == 0)
241 /* Simply prepend three more widget values to the contents of
242 the menu: a label, and two separators (to get a double
244 widget_value *title_wv = xmalloc_widget_value ();
245 widget_value *sep_wv = xmalloc_widget_value ();
246 title_wv->type = TEXT_TYPE;
247 title_wv->name = xstrdup (wv->name);
248 title_wv->enabled = 1;
249 title_wv->next = sep_wv;
250 sep_wv->type = SEPARATOR_TYPE;
251 sep_wv->value = menu_separator_style ("==");
254 wv->contents = title_wv;
257 wv->enabled = ! NILP (active_p);
258 if (deep_p && !wv->enabled && !NILP (desc))
261 /* Add a fake entry so the menus show up */
262 wv->contents = dummy = xmalloc_widget_value ();
263 dummy->name = xstrdup ("(inactive)");
264 dummy->accel = LISP_TO_VOID (Qnil);
268 dummy->type = BUTTON_TYPE;
269 dummy->call_data = NULL;
276 else if (menubar_root_p)
278 wv->name = xstrdup ("menubar");
279 wv->type = CASCADE_TYPE; /* Well, nothing else seems to fit and
280 this is ignored anyway... */
284 signal_simple_error ("Menu name (first element) must be a string",
288 if (deep_p || menubar_root_p)
291 for (; !NILP (desc); desc = Fcdr (desc))
293 Lisp_Object child = Fcar (desc);
294 if (menubar_root_p && NILP (child)) /* the partition */
298 "More than one partition (nil) in menubar description");
300 next = xmalloc_widget_value ();
301 next->type = PUSHRIGHT_TYPE;
305 next = menu_item_descriptor_to_widget_value_1
306 (child, menu_type, deep_p, filter_p, depth + 1);
317 if (deep_p && !wv->contents)
320 else if (NILP (desc))
321 error ("nil may not appear in menu descriptions");
323 signal_simple_error ("Unrecognized menu descriptor", desc);
329 /* Completed normally. Clear out the object that widget_value_unwind()
330 will be called with to tell it not to free the wv (as we are
332 set_opaque_ptr (wv_closure, 0);
335 unbind_to (count, Qnil);
339 static widget_value *
340 menu_item_descriptor_to_widget_value (Lisp_Object desc,
341 int menu_type, /* if this is a menubar,
344 int filter_p) /* if :filter forms
348 int count = specpdl_depth ();
349 record_unwind_protect (restore_gc_inhibit,
350 make_int (gc_currently_forbidden));
351 gc_currently_forbidden = 1;
353 wv = menu_item_descriptor_to_widget_value_1 (desc, menu_type, deep_p,
355 unbind_to (count, Qnil);
360 #if defined LWLIB_MENUBARS_LUCID || defined LWLIB_MENUBARS_MOTIF
361 int in_menu_callback;
364 restore_in_menu_callback (Lisp_Object val)
366 in_menu_callback = XINT(val);
369 #endif /* LWLIB_MENUBARS_LUCID || LWLIB_MENUBARS_MOTIF */
372 /* #### Sort of a hack needed to process Vactivate_menubar_hook
373 correctly wrt buffer-local values. A correct solution would
374 involve adding a callback mechanism to run_hook(). This function
375 is currently unused. */
377 my_run_hook (Lisp_Object hooksym, int allow_global_p)
379 /* This function can GC */
381 Lisp_Object value = Fsymbol_value (hooksym);
384 if (!NILP (value) && (!CONSP (value) || EQ (XCAR (value), Qlambda)))
385 return !EQ (call0 (value), Qt);
387 EXTERNAL_LIST_LOOP (tail, value)
389 if (allow_global_p && EQ (XCAR (tail), Qt))
390 changes |= my_run_hook (Fdefault_value (hooksym), 0);
391 if (!EQ (call0 (XCAR (tail)), Qt))
399 /* The order in which callbacks are run is funny to say the least.
400 It's sometimes tricky to avoid running a callback twice, and to
401 avoid returning prematurely. So, this function returns true
402 if the menu's callbacks are no longer gc protected. So long
403 as we unprotect them before allowing other callbacks to run,
404 everything should be ok.
406 The pre_activate_callback() *IS* intentionally called multiple times.
407 If client_data == NULL, then it's being called before the menu is posted.
408 If client_data != NULL, then client_data is a (widget_value *) and
409 client_data->data is a Lisp_Object pointing to a lisp submenu description
410 that must be converted into widget_values. *client_data is destructively
413 #### Stig thinks that there may be a GC problem here due to the
414 fact that pre_activate_callback() is called multiple times, but I
420 pre_activate_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
422 /* This function can GC */
423 struct device *d = get_device_from_display (XtDisplay (widget));
424 struct frame *f = x_any_window_to_frame (d, XtWindow (widget));
428 /* set in lwlib to the time stamp associated with the most recent menu
430 extern Time x_focus_timestamp_really_sucks_fix_me_better;
433 f = x_any_window_to_frame (d, XtWindow (XtParent (widget)));
437 /* make sure f is the selected frame */
438 XSETFRAME (frame, f);
439 Fselect_frame (frame);
443 /* this is an incremental menu construction callback */
444 widget_value *hack_wv = (widget_value *) client_data;
445 Lisp_Object submenu_desc;
448 assert (hack_wv->type == INCREMENTAL_TYPE);
449 VOID_TO_LISP (submenu_desc, hack_wv->call_data);
452 * #### Fix the menu code so this isn't necessary.
454 * Protect against reentering the menu code otherwise we will
455 * crash later when the code gets confused at the state
458 count = specpdl_depth ();
459 record_unwind_protect (restore_in_menu_callback,
460 make_int (in_menu_callback));
461 in_menu_callback = 1;
462 wv = menu_item_descriptor_to_widget_value (submenu_desc, SUBMENU_TYPE,
464 unbind_to (count, Qnil);
468 wv = xmalloc_widget_value ();
469 wv->type = CASCADE_TYPE;
471 wv->accel = LISP_TO_VOID (Qnil);
472 wv->contents = xmalloc_widget_value ();
473 wv->contents->type = TEXT_TYPE;
474 wv->contents->name = xstrdup ("No menu");
475 wv->contents->next = NULL;
476 wv->contents->accel = LISP_TO_VOID (Qnil);
478 assert (wv && wv->type == CASCADE_TYPE && wv->contents);
479 replace_widget_value_tree (hack_wv, wv->contents);
480 free_popup_widget_value_tree (wv);
482 else if (!POPUP_DATAP (FRAME_MENUBAR_DATA (f)))
486 #if 0 /* Unused, see comment below. */
489 /* #### - this menubar update mechanism is expensively anti-social and
490 the activate-menubar-hook is now mostly obsolete. */
491 any_changes = my_run_hook (Qactivate_menubar_hook, 1);
493 /* #### - It is necessary to *ALWAYS* call set_frame_menubar() now that
494 incremental menus are implemented. If a subtree of a menu has been
495 updated incrementally (a destructive operation), then that subtree
496 must somehow be wiped.
498 It is difficult to undo the destructive operation in lwlib because
499 a pointer back to lisp data needs to be hidden away somewhere. So
500 that an INCREMENTAL_TYPE widget_value can be recreated... Hmmmmm. */
502 !XFRAME_MENUBAR_DATA (f)->menubar_contents_up_to_date)
503 set_frame_menubar (f, 1, 0);
505 run_hook (Qactivate_menubar_hook);
506 set_frame_menubar (f, 1, 0);
508 DEVICE_X_MOUSE_TIMESTAMP (XDEVICE (FRAME_DEVICE (f))) =
509 DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (XDEVICE (FRAME_DEVICE (f))) =
510 x_focus_timestamp_really_sucks_fix_me_better;
514 static widget_value *
515 compute_menubar_data (struct frame *f, Lisp_Object menubar, int deep_p)
523 Lisp_Object old_buffer;
524 int count = specpdl_depth ();
526 old_buffer = Fcurrent_buffer ();
527 record_unwind_protect (Fset_buffer, old_buffer);
528 Fset_buffer ( XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer);
529 data = menu_item_descriptor_to_widget_value (menubar, MENUBAR_TYPE,
531 Fset_buffer (old_buffer);
532 unbind_to (count, Qnil);
538 set_frame_menubar (struct frame *f, int deep_p, int first_time_p)
544 /* As for the toolbar, the minibuffer does not have its own menubar. */
545 struct window *w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f));
550 /***** first compute the contents of the menubar *****/
554 /* evaluate `current-menubar' in the buffer of the selected window
555 of the frame in question. */
556 menubar = symbol_value_in_buffer (Qcurrent_menubar, w->buffer);
560 /* That's a little tricky the first time since the frame isn't
561 fully initialized yet. */
562 menubar = Fsymbol_value (Qcurrent_menubar);
567 menubar = Vblank_menubar;
571 menubar_visible = !NILP (w->menubar_visible_p);
573 data = compute_menubar_data (f, menubar, deep_p);
574 if (!data || (!data->next && !data->contents))
577 if (NILP (FRAME_MENUBAR_DATA (f)))
579 struct popup_data *mdata =
580 alloc_lcrecord_type (struct popup_data, &lrecord_popup_data);
582 mdata->id = new_lwlib_id ();
583 mdata->last_menubar_buffer = Qnil;
584 mdata->menubar_contents_up_to_date = 0;
585 XSETPOPUP_DATA (FRAME_MENUBAR_DATA (f), mdata);
588 /***** now store into the menubar widget, creating it if necessary *****/
590 id = XFRAME_MENUBAR_DATA (f)->id;
591 if (!FRAME_X_MENUBAR_WIDGET (f))
593 Widget parent = FRAME_X_CONTAINER_WIDGET (f);
595 assert (first_time_p);
597 /* It's the first time we've mapped the menubar so compute its
598 contents completely once. This makes sure that the menubar
599 components are created with the right type. */
602 free_popup_widget_value_tree (data);
603 data = compute_menubar_data (f, menubar, 1);
607 FRAME_X_MENUBAR_WIDGET (f) =
608 lw_create_widget ("menubar", "menubar", id, data, parent,
609 0, pre_activate_callback,
610 popup_selection_callback, 0);
615 lw_modify_all_widgets (id, data, deep_p ? True : False);
617 free_popup_widget_value_tree (data);
619 XFRAME_MENUBAR_DATA (f)->menubar_contents_up_to_date = deep_p;
620 XFRAME_MENUBAR_DATA (f)->last_menubar_buffer =
621 XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f))->buffer;
622 return menubar_visible;
626 /* Called from x_create_widgets() to create the initial menubar of a frame
627 before it is mapped, so that the window is mapped with the menubar already
628 there instead of us tacking it on later and thrashing the window after it
631 x_initialize_frame_menubar (struct frame *f)
633 return set_frame_menubar (f, 1, 1);
637 static LWLIB_ID last_popup_menu_selection_callback_id;
640 popup_menu_selection_callback (Widget widget, LWLIB_ID id,
641 XtPointer client_data)
643 last_popup_menu_selection_callback_id = id;
644 popup_selection_callback (widget, id, client_data);
645 /* lw_destroy_all_widgets() will be called from popup_down_callback() */
649 popup_menu_down_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
651 if (popup_handled_p (id))
653 assert (popup_up_p != 0);
654 ungcpro_popup_callbacks (id);
656 /* if this isn't called immediately after the selection callback, then
657 there wasn't a menu selection. */
658 if (id != last_popup_menu_selection_callback_id)
659 popup_selection_callback (widget, id, (XtPointer) -1);
660 lw_destroy_all_widgets (id);
665 make_dummy_xbutton_event (XEvent *dummy,
667 struct Lisp_Event *eev)
668 /* NULL for eev means query pointer */
670 XButtonPressedEvent *btn = (XButtonPressedEvent *) dummy;
672 btn->type = ButtonPress;
675 btn->display = XtDisplay (daddy);
676 btn->window = XtWindow (daddy);
679 Position shellx, shelly, framex, framey;
681 btn->time = eev->timestamp;
682 btn->button = eev->event.button.button;
683 btn->root = RootWindowOfScreen (XtScreen (daddy));
684 btn->subwindow = (Window) NULL;
685 btn->x = eev->event.button.x;
686 btn->y = eev->event.button.y;
688 #ifndef HAVE_WMCOMMAND
690 Widget shell = XtParent (daddy);
692 XtSetArg (al [0], XtNx, &shellx);
693 XtSetArg (al [1], XtNy, &shelly);
694 XtGetValues (shell, al, 2);
697 XtSetArg (al [0], XtNx, &framex);
698 XtSetArg (al [1], XtNy, &framey);
699 XtGetValues (daddy, al, 2);
700 btn->x_root = shellx + framex + btn->x;
701 btn->y_root = shelly + framey + btn->y;
702 btn->state = ButtonPressMask; /* all buttons pressed */
706 /* CurrentTime is just ZERO, so it's worthless for
707 determining relative click times. */
708 struct device *d = get_device_from_display (XtDisplay (daddy));
709 btn->time = DEVICE_X_MOUSE_TIMESTAMP (d); /* event-Xt maintains this */
711 XQueryPointer (btn->display, btn->window, &btn->root,
712 &btn->subwindow, &btn->x_root, &btn->y_root,
713 &btn->x, &btn->y, &btn->state);
720 x_update_frame_menubar_internal (struct frame *f)
722 /* We assume the menubar contents has changed if the global flag is set,
723 or if the current buffer has changed, or if the menubar has never
726 int menubar_contents_changed =
728 || NILP (FRAME_MENUBAR_DATA (f))
729 || (!EQ (XFRAME_MENUBAR_DATA (f)->last_menubar_buffer,
730 XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f))->buffer)));
732 Boolean menubar_was_visible = XtIsManaged (FRAME_X_MENUBAR_WIDGET (f));
733 Boolean menubar_will_be_visible = menubar_was_visible;
734 Boolean menubar_visibility_changed;
736 if (menubar_contents_changed)
737 menubar_will_be_visible = set_frame_menubar (f, 0, 0);
739 menubar_visibility_changed = menubar_was_visible != menubar_will_be_visible;
741 if (!menubar_visibility_changed)
744 /* Set menubar visibility */
745 (menubar_will_be_visible ? XtManageChild : XtUnmanageChild)
746 (FRAME_X_MENUBAR_WIDGET (f));
748 MARK_FRAME_SIZE_SLIPPED (f);
752 x_update_frame_menubars (struct frame *f)
754 assert (FRAME_X_P (f));
756 x_update_frame_menubar_internal (f);
758 /* #### This isn't going to work right now that this function works on
759 a per-frame, not per-device basis. Guess what? I don't care. */
763 x_free_frame_menubars (struct frame *f)
765 Widget menubar_widget;
767 assert (FRAME_X_P (f));
769 menubar_widget = FRAME_X_MENUBAR_WIDGET (f);
772 LWLIB_ID id = XFRAME_MENUBAR_DATA (f)->id;
773 lw_destroy_all_widgets (id);
774 XFRAME_MENUBAR_DATA (f)->id = 0;
779 x_popup_menu (Lisp_Object menu_desc, Lisp_Object event)
782 struct frame *f = selected_frame ();
786 struct Lisp_Event *eev = NULL;
790 XSETFRAME (frame, f);
791 CHECK_X_FRAME (frame);
792 parent = FRAME_X_SHELL_WIDGET (f);
796 CHECK_LIVE_EVENT (event);
798 if (eev->event_type != button_press_event
799 && eev->event_type != button_release_event)
800 wrong_type_argument (Qmouse_event_p, event);
802 else if (!NILP (Vthis_command_keys))
804 /* if an event wasn't passed, use the last event of the event sequence
805 currently being executed, if that event is a mouse event */
806 eev = XEVENT (Vthis_command_keys); /* last event first */
807 if (eev->event_type != button_press_event
808 && eev->event_type != button_release_event)
811 make_dummy_xbutton_event (&xev, parent, eev);
813 if (SYMBOLP (menu_desc))
814 menu_desc = Fsymbol_value (menu_desc);
815 CHECK_CONS (menu_desc);
816 CHECK_STRING (XCAR (menu_desc));
817 data = menu_item_descriptor_to_widget_value (menu_desc, POPUP_TYPE, 1, 1);
819 if (! data) error ("no menu");
821 menu_id = new_lwlib_id ();
822 menu = lw_create_widget ("popup", "popup" /* data->name */, menu_id, data,
824 popup_menu_selection_callback,
825 popup_menu_down_callback);
826 free_popup_widget_value_tree (data);
828 gcpro_popup_callbacks (menu_id);
830 /* Setting zmacs-region-stays is necessary here because executing a command
831 from a menu is really a two-command process: the first command (bound to
832 the button-click) simply pops up the menu, and returns. This causes a
833 sequence of magic-events (destined for the popup-menu widget) to begin.
834 Eventually, a menu item is selected, and a menu-event blip is pushed onto
835 the end of the input stream, which is then executed by the event loop.
837 So there are two command-events, with a bunch of magic-events between
838 them. We don't want the *first* command event to alter the state of the
839 region, so that the region can be available as an argument for the second
843 zmacs_region_stays = 1;
846 lw_popup_menu (menu, &xev);
847 /* this speeds up display of pop-up menus */
848 XFlush (XtDisplay (parent));
853 syms_of_menubar_x (void)
858 console_type_create_menubar_x (void)
860 CONSOLE_HAS_METHOD (x, update_frame_menubars);
861 CONSOLE_HAS_METHOD (x, free_frame_menubars);
862 CONSOLE_HAS_METHOD (x, popup_menu);
866 reinit_vars_of_menubar_x (void)
868 last_popup_menu_selection_callback_id = (LWLIB_ID) -1;
872 vars_of_menubar_x (void)
874 reinit_vars_of_menubar_x ();
876 #if defined (LWLIB_MENUBARS_LUCID)
877 Fprovide (intern ("lucid-menubars"));
878 #elif defined (LWLIB_MENUBARS_MOTIF)
879 Fprovide (intern ("motif-menubars"));
880 #elif defined (LWLIB_MENUBARS_ATHENA)
881 Fprovide (intern ("athena-menubars"));