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);
97 int count = specpdl_depth ();
98 int partition_seen = 0;
99 widget_value *wv = xmalloc_widget_value ();
100 Lisp_Object wv_closure = make_opaque_ptr (wv);
102 record_unwind_protect (widget_value_unwind, wv_closure);
106 char *string_chars = (char *) XSTRING_DATA (desc);
107 wv->type = (separator_string_p (string_chars) ? SEPARATOR_TYPE :
110 /* #### - should internationalize with X resources instead.
112 string_chars = GETTEXT (string_chars);
114 if (wv->type == SEPARATOR_TYPE)
116 wv->value = menu_separator_style (string_chars);
120 wv->name = xstrdup (string_chars);
122 /* dverna Dec. 98: command_builder_operate_menu_accelerator will
123 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
126 wv->accel = LISP_TO_VOID (Qnil);
129 else if (VECTORP (desc))
131 Lisp_Object gui_item = gui_parse_item_keywords (desc);
132 if (!button_item_to_widget_value (gui_item, wv, 1,
133 (menu_type == MENUBAR_TYPE
136 /* :included form was nil */
141 else if (CONSP (desc))
143 Lisp_Object incremental_data = desc;
144 widget_value *prev = 0;
146 if (STRINGP (XCAR (desc)))
148 Lisp_Object key, val;
149 Lisp_Object include_p = Qnil, hook_fn = Qnil, config_tag = Qnil;
150 Lisp_Object active_p = Qt;
152 int included_spec = 0;
154 wv->type = CASCADE_TYPE;
156 wv->name = (char *) XSTRING_DATA (LISP_GETTEXT (XCAR (desc)));
157 wv->name = xstrdup (wv->name);
159 accel = gui_name_accelerator (LISP_GETTEXT (XCAR (desc)));
160 wv->accel = LISP_TO_VOID (accel);
164 while (key = Fcar (desc), KEYWORDP (key))
166 Lisp_Object cascade = desc;
169 signal_simple_error ("Keyword in menu lacks a value",
173 if (EQ (key, Q_included))
174 include_p = val, included_spec = 1;
175 else if (EQ (key, Q_config))
177 else if (EQ (key, Q_filter))
179 else if (EQ (key, Q_active))
180 active_p = val, active_spec = 1;
181 else if (EQ (key, Q_accelerator))
185 wv->accel = LISP_TO_VOID (val);
187 signal_simple_error ("bad keyboard accelerator", val);
189 else if (EQ (key, Q_label))
191 /* implement in 21.2 */
194 signal_simple_error ("Unknown menu cascade keyword", cascade);
197 if ((!NILP (config_tag)
198 && NILP (Fmemq (config_tag, Vmenubar_configuration)))
199 || (included_spec && NILP (Feval (include_p))))
206 active_p = Feval (active_p);
208 if (!NILP (hook_fn) && !NILP (active_p))
210 #if defined LWLIB_MENUBARS_LUCID || defined LWLIB_MENUBARS_MOTIF
211 if (filter_p || depth == 0)
214 desc = call1_trapping_errors ("Error in menubar filter",
218 #if defined LWLIB_MENUBARS_LUCID || defined LWLIB_MENUBARS_MOTIF
222 widget_value *incr_wv = xmalloc_widget_value ();
223 wv->contents = incr_wv;
224 incr_wv->type = INCREMENTAL_TYPE;
225 incr_wv->enabled = 1;
226 incr_wv->name = wv->name;
227 incr_wv->name = xstrdup (wv->name);
228 /* This is automatically GC protected through
229 the call to lw_map_widget_values(); no need
231 incr_wv->call_data = LISP_TO_VOID (incremental_data);
234 #endif /* LWLIB_MENUBARS_LUCID || LWLIB_MENUBARS_MOTIF */
236 if (menu_type == POPUP_TYPE && popup_menu_titles && depth == 0)
238 /* Simply prepend three more widget values to the contents of
239 the menu: a label, and two separators (to get a double
241 widget_value *title_wv = xmalloc_widget_value ();
242 widget_value *sep_wv = xmalloc_widget_value ();
243 title_wv->type = TEXT_TYPE;
244 title_wv->name = xstrdup (wv->name);
245 title_wv->enabled = 1;
246 title_wv->next = sep_wv;
247 sep_wv->type = SEPARATOR_TYPE;
248 sep_wv->value = menu_separator_style ("==");
251 wv->contents = title_wv;
254 wv->enabled = ! NILP (active_p);
255 if (deep_p && !wv->enabled && !NILP (desc))
258 /* Add a fake entry so the menus show up */
259 wv->contents = dummy = xmalloc_widget_value ();
260 dummy->name = xstrdup ("(inactive)");
261 dummy->accel = LISP_TO_VOID (Qnil);
265 dummy->type = BUTTON_TYPE;
266 dummy->call_data = NULL;
273 else if (menubar_root_p)
275 wv->name = xstrdup ("menubar");
276 wv->type = CASCADE_TYPE; /* Well, nothing else seems to fit and
277 this is ignored anyway... */
281 signal_simple_error ("Menu name (first element) must be a string",
285 if (deep_p || menubar_root_p)
288 for (; !NILP (desc); desc = Fcdr (desc))
290 Lisp_Object child = Fcar (desc);
291 if (menubar_root_p && NILP (child)) /* the partition */
295 "More than one partition (nil) in menubar description");
297 next = xmalloc_widget_value ();
298 next->type = PUSHRIGHT_TYPE;
302 next = menu_item_descriptor_to_widget_value_1
303 (child, menu_type, deep_p, filter_p, depth + 1);
314 if (deep_p && !wv->contents)
317 else if (NILP (desc))
318 error ("nil may not appear in menu descriptions");
320 signal_simple_error ("Unrecognized menu descriptor", desc);
326 /* 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
329 set_opaque_ptr (wv_closure, 0);
332 unbind_to (count, Qnil);
336 static widget_value *
337 menu_item_descriptor_to_widget_value (Lisp_Object desc,
338 int menu_type, /* if this is a menubar,
341 int filter_p) /* if :filter forms
345 int count = specpdl_depth ();
346 record_unwind_protect (restore_gc_inhibit,
347 make_int (gc_currently_forbidden));
348 gc_currently_forbidden = 1;
350 wv = menu_item_descriptor_to_widget_value_1 (desc, menu_type, deep_p,
352 unbind_to (count, Qnil);
357 #if defined LWLIB_MENUBARS_LUCID || defined LWLIB_MENUBARS_MOTIF
358 int in_menu_callback;
361 restore_in_menu_callback (Lisp_Object val)
363 in_menu_callback = XINT (val);
366 #endif /* LWLIB_MENUBARS_LUCID || LWLIB_MENUBARS_MOTIF */
369 /* #### Sort of a hack needed to process Vactivate_menubar_hook
370 correctly wrt buffer-local values. A correct solution would
371 involve adding a callback mechanism to run_hook(). This function
372 is currently unused. */
374 my_run_hook (Lisp_Object hooksym, int allow_global_p)
376 /* This function can GC */
378 Lisp_Object value = Fsymbol_value (hooksym);
381 if (!NILP (value) && (!CONSP (value) || EQ (XCAR (value), Qlambda)))
382 return !EQ (call0 (value), Qt);
384 EXTERNAL_LIST_LOOP (tail, value)
386 if (allow_global_p && EQ (XCAR (tail), Qt))
387 changes |= my_run_hook (Fdefault_value (hooksym), 0);
388 if (!EQ (call0 (XCAR (tail)), Qt))
396 /* The order in which callbacks are run is funny to say the least.
397 It's sometimes tricky to avoid running a callback twice, and to
398 avoid returning prematurely. So, this function returns true
399 if the menu's callbacks are no longer gc protected. So long
400 as we unprotect them before allowing other callbacks to run,
401 everything should be ok.
403 The pre_activate_callback() *IS* intentionally called multiple times.
404 If client_data == NULL, then it's being called before the menu is posted.
405 If client_data != NULL, then client_data is a (widget_value *) and
406 client_data->data is a Lisp_Object pointing to a lisp submenu description
407 that must be converted into widget_values. *client_data is destructively
410 #### Stig thinks that there may be a GC problem here due to the
411 fact that pre_activate_callback() is called multiple times, but I
417 pre_activate_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
419 /* This function can GC */
420 struct device *d = get_device_from_display (XtDisplay (widget));
421 struct frame *f = x_any_window_to_frame (d, XtWindow (widget));
425 /* set in lwlib to the time stamp associated with the most recent menu
427 extern Time x_focus_timestamp_really_sucks_fix_me_better;
430 f = x_any_window_to_frame (d, XtWindow (XtParent (widget)));
434 /* make sure f is the selected frame */
435 XSETFRAME (frame, f);
436 Fselect_frame (frame);
440 /* this is an incremental menu construction callback */
441 widget_value *hack_wv = (widget_value *) client_data;
442 Lisp_Object submenu_desc;
445 assert (hack_wv->type == INCREMENTAL_TYPE);
446 VOID_TO_LISP (submenu_desc, hack_wv->call_data);
449 * #### Fix the menu code so this isn't necessary.
451 * Protect against reentering the menu code otherwise we will
452 * crash later when the code gets confused at the state
455 count = specpdl_depth ();
456 record_unwind_protect (restore_in_menu_callback,
457 make_int (in_menu_callback));
458 in_menu_callback = 1;
459 wv = menu_item_descriptor_to_widget_value (submenu_desc, SUBMENU_TYPE,
461 unbind_to (count, Qnil);
465 wv = xmalloc_widget_value ();
466 wv->type = CASCADE_TYPE;
468 wv->accel = LISP_TO_VOID (Qnil);
469 wv->contents = xmalloc_widget_value ();
470 wv->contents->type = TEXT_TYPE;
471 wv->contents->name = xstrdup ("No menu");
472 wv->contents->next = NULL;
473 wv->contents->accel = LISP_TO_VOID (Qnil);
475 assert (wv && wv->type == CASCADE_TYPE && wv->contents);
476 replace_widget_value_tree (hack_wv, wv->contents);
477 free_popup_widget_value_tree (wv);
479 else if (!POPUP_DATAP (FRAME_MENUBAR_DATA (f)))
483 #if 0 /* Unused, see comment below. */
486 /* #### - this menubar update mechanism is expensively anti-social and
487 the activate-menubar-hook is now mostly obsolete. */
488 any_changes = my_run_hook (Qactivate_menubar_hook, 1);
490 /* #### - It is necessary to *ALWAYS* call set_frame_menubar() now that
491 incremental menus are implemented. If a subtree of a menu has been
492 updated incrementally (a destructive operation), then that subtree
493 must somehow be wiped.
495 It is difficult to undo the destructive operation in lwlib because
496 a pointer back to lisp data needs to be hidden away somewhere. So
497 that an INCREMENTAL_TYPE widget_value can be recreated... Hmmmmm. */
499 !XFRAME_MENUBAR_DATA (f)->menubar_contents_up_to_date)
500 set_frame_menubar (f, 1, 0);
502 run_hook (Qactivate_menubar_hook);
503 set_frame_menubar (f, 1, 0);
505 DEVICE_X_MOUSE_TIMESTAMP (XDEVICE (FRAME_DEVICE (f))) =
506 DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (XDEVICE (FRAME_DEVICE (f))) =
507 x_focus_timestamp_really_sucks_fix_me_better;
511 static widget_value *
512 compute_menubar_data (struct frame *f, Lisp_Object menubar, int deep_p)
519 int count = specpdl_depth ();
521 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
522 Fset_buffer (XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer);
523 data = menu_item_descriptor_to_widget_value (menubar, MENUBAR_TYPE,
525 unbind_to (count, Qnil);
532 set_frame_menubar (struct frame *f, int deep_p, int first_time_p)
538 /* As with the toolbar, the minibuffer does not have its own menubar. */
539 struct window *w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f));
544 /***** first compute the contents of the menubar *****/
548 /* evaluate `current-menubar' in the buffer of the selected window
549 of the frame in question. */
550 menubar = symbol_value_in_buffer (Qcurrent_menubar, w->buffer);
554 /* That's a little tricky the first time since the frame isn't
555 fully initialized yet. */
556 menubar = Fsymbol_value (Qcurrent_menubar);
561 menubar = Vblank_menubar;
565 menubar_visible = !NILP (w->menubar_visible_p);
567 data = compute_menubar_data (f, menubar, deep_p);
568 if (!data || (!data->next && !data->contents))
571 if (NILP (FRAME_MENUBAR_DATA (f)))
573 struct popup_data *mdata =
574 alloc_lcrecord_type (struct popup_data, &lrecord_popup_data);
576 mdata->id = new_lwlib_id ();
577 mdata->last_menubar_buffer = Qnil;
578 mdata->menubar_contents_up_to_date = 0;
579 XSETPOPUP_DATA (FRAME_MENUBAR_DATA (f), mdata);
582 /***** now store into the menubar widget, creating it if necessary *****/
584 id = XFRAME_MENUBAR_DATA (f)->id;
585 if (!FRAME_X_MENUBAR_WIDGET (f))
587 Widget parent = FRAME_X_CONTAINER_WIDGET (f);
589 assert (first_time_p);
591 /* It's the first time we've mapped the menubar so compute its
592 contents completely once. This makes sure that the menubar
593 components are created with the right type. */
596 free_popup_widget_value_tree (data);
597 data = compute_menubar_data (f, menubar, 1);
601 FRAME_X_MENUBAR_WIDGET (f) =
602 lw_create_widget ("menubar", "menubar", id, data, parent,
603 0, pre_activate_callback,
604 popup_selection_callback, 0);
609 lw_modify_all_widgets (id, data, deep_p ? True : False);
611 free_popup_widget_value_tree (data);
613 XFRAME_MENUBAR_DATA (f)->menubar_contents_up_to_date = deep_p;
614 XFRAME_MENUBAR_DATA (f)->last_menubar_buffer =
615 XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f))->buffer;
616 return menubar_visible;
620 /* Called from x_create_widgets() to create the initial menubar of a frame
621 before it is mapped, so that the window is mapped with the menubar already
622 there instead of us tacking it on later and thrashing the window after it
625 x_initialize_frame_menubar (struct frame *f)
627 return set_frame_menubar (f, 1, 1);
631 static LWLIB_ID last_popup_menu_selection_callback_id;
634 popup_menu_selection_callback (Widget widget, LWLIB_ID id,
635 XtPointer client_data)
637 last_popup_menu_selection_callback_id = id;
638 popup_selection_callback (widget, id, client_data);
639 /* lw_destroy_all_widgets() will be called from popup_down_callback() */
643 popup_menu_down_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
645 if (popup_handled_p (id))
647 assert (popup_up_p != 0);
648 ungcpro_popup_callbacks (id);
650 /* if this isn't called immediately after the selection callback, then
651 there wasn't a menu selection. */
652 if (id != last_popup_menu_selection_callback_id)
653 popup_selection_callback (widget, id, (XtPointer) -1);
654 lw_destroy_all_widgets (id);
659 make_dummy_xbutton_event (XEvent *dummy,
661 struct Lisp_Event *eev)
662 /* NULL for eev means query pointer */
664 XButtonPressedEvent *btn = (XButtonPressedEvent *) dummy;
666 btn->type = ButtonPress;
669 btn->display = XtDisplay (daddy);
670 btn->window = XtWindow (daddy);
673 Position shellx, shelly, framex, framey;
675 btn->time = eev->timestamp;
676 btn->button = eev->event.button.button;
677 btn->root = RootWindowOfScreen (XtScreen (daddy));
678 btn->subwindow = (Window) NULL;
679 btn->x = eev->event.button.x;
680 btn->y = eev->event.button.y;
682 #ifndef HAVE_WMCOMMAND
684 Widget shell = XtParent (daddy);
686 XtSetArg (al [0], XtNx, &shellx);
687 XtSetArg (al [1], XtNy, &shelly);
688 XtGetValues (shell, al, 2);
691 XtSetArg (al [0], XtNx, &framex);
692 XtSetArg (al [1], XtNy, &framey);
693 XtGetValues (daddy, al, 2);
694 btn->x_root = shellx + framex + btn->x;
695 btn->y_root = shelly + framey + btn->y;
696 btn->state = ButtonPressMask; /* all buttons pressed */
700 /* CurrentTime is just ZERO, so it's worthless for
701 determining relative click times. */
702 struct device *d = get_device_from_display (XtDisplay (daddy));
703 btn->time = DEVICE_X_MOUSE_TIMESTAMP (d); /* event-Xt maintains this */
705 XQueryPointer (btn->display, btn->window, &btn->root,
706 &btn->subwindow, &btn->x_root, &btn->y_root,
707 &btn->x, &btn->y, &btn->state);
714 x_update_frame_menubar_internal (struct frame *f)
716 /* We assume the menubar contents has changed if the global flag is set,
717 or if the current buffer has changed, or if the menubar has never
720 int menubar_contents_changed =
722 || NILP (FRAME_MENUBAR_DATA (f))
723 || (!EQ (XFRAME_MENUBAR_DATA (f)->last_menubar_buffer,
724 XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f))->buffer)));
726 Boolean menubar_was_visible = XtIsManaged (FRAME_X_MENUBAR_WIDGET (f));
727 Boolean menubar_will_be_visible = menubar_was_visible;
728 Boolean menubar_visibility_changed;
730 if (menubar_contents_changed)
731 menubar_will_be_visible = set_frame_menubar (f, 0, 0);
733 menubar_visibility_changed = menubar_was_visible != menubar_will_be_visible;
735 if (!menubar_visibility_changed)
738 /* Set menubar visibility */
739 (menubar_will_be_visible ? XtManageChild : XtUnmanageChild)
740 (FRAME_X_MENUBAR_WIDGET (f));
742 MARK_FRAME_SIZE_SLIPPED (f);
746 x_update_frame_menubars (struct frame *f)
748 assert (FRAME_X_P (f));
750 x_update_frame_menubar_internal (f);
752 /* #### This isn't going to work right now that this function works on
753 a per-frame, not per-device basis. Guess what? I don't care. */
757 x_free_frame_menubars (struct frame *f)
759 Widget menubar_widget;
761 assert (FRAME_X_P (f));
763 menubar_widget = FRAME_X_MENUBAR_WIDGET (f);
766 LWLIB_ID id = XFRAME_MENUBAR_DATA (f)->id;
767 lw_destroy_all_widgets (id);
768 XFRAME_MENUBAR_DATA (f)->id = 0;
773 x_popup_menu (Lisp_Object menu_desc, Lisp_Object event)
776 struct frame *f = selected_frame ();
780 struct Lisp_Event *eev = NULL;
784 XSETFRAME (frame, f);
785 CHECK_X_FRAME (frame);
786 parent = FRAME_X_SHELL_WIDGET (f);
790 CHECK_LIVE_EVENT (event);
792 if (eev->event_type != button_press_event
793 && eev->event_type != button_release_event)
794 wrong_type_argument (Qmouse_event_p, event);
796 else if (!NILP (Vthis_command_keys))
798 /* if an event wasn't passed, use the last event of the event sequence
799 currently being executed, if that event is a mouse event */
800 eev = XEVENT (Vthis_command_keys); /* last event first */
801 if (eev->event_type != button_press_event
802 && eev->event_type != button_release_event)
805 make_dummy_xbutton_event (&xev, parent, eev);
807 if (SYMBOLP (menu_desc))
808 menu_desc = Fsymbol_value (menu_desc);
809 CHECK_CONS (menu_desc);
810 CHECK_STRING (XCAR (menu_desc));
811 data = menu_item_descriptor_to_widget_value (menu_desc, POPUP_TYPE, 1, 1);
813 if (! data) error ("no menu");
815 menu_id = new_lwlib_id ();
816 menu = lw_create_widget ("popup", "popup" /* data->name */, menu_id, data,
818 popup_menu_selection_callback,
819 popup_menu_down_callback);
820 free_popup_widget_value_tree (data);
822 gcpro_popup_callbacks (menu_id);
824 /* Setting zmacs-region-stays is necessary here because executing a command
825 from a menu is really a two-command process: the first command (bound to
826 the button-click) simply pops up the menu, and returns. This causes a
827 sequence of magic-events (destined for the popup-menu widget) to begin.
828 Eventually, a menu item is selected, and a menu-event blip is pushed onto
829 the end of the input stream, which is then executed by the event loop.
831 So there are two command-events, with a bunch of magic-events between
832 them. We don't want the *first* command event to alter the state of the
833 region, so that the region can be available as an argument for the second
837 zmacs_region_stays = 1;
840 lw_popup_menu (menu, &xev);
841 /* this speeds up display of pop-up menus */
842 XFlush (XtDisplay (parent));
847 syms_of_menubar_x (void)
852 console_type_create_menubar_x (void)
854 CONSOLE_HAS_METHOD (x, update_frame_menubars);
855 CONSOLE_HAS_METHOD (x, free_frame_menubars);
856 CONSOLE_HAS_METHOD (x, popup_menu);
860 reinit_vars_of_menubar_x (void)
862 last_popup_menu_selection_callback_id = (LWLIB_ID) -1;
866 vars_of_menubar_x (void)
868 reinit_vars_of_menubar_x ();
870 #if defined (LWLIB_MENUBARS_LUCID)
871 Fprovide (intern ("lucid-menubars"));
872 #elif defined (LWLIB_MENUBARS_MOTIF)
873 Fprovide (intern ("motif-menubars"));
874 #elif defined (LWLIB_MENUBARS_ATHENA)
875 Fprovide (intern ("athena-menubars"));