1 /* Implements an elisp-programmable menubar.
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 /* #### There ain't much here because menubars have not been
25 properly abstracted yet. */
35 #include "redisplay.h"
38 int menubar_show_keybindings;
39 Lisp_Object Vmenubar_configuration;
41 Lisp_Object Qcurrent_menubar;
43 Lisp_Object Qactivate_menubar_hook, Vactivate_menubar_hook;
45 Lisp_Object Vmenubar_visible_p;
47 static Lisp_Object Vcurrent_menubar; /* DO NOT ever reference this.
48 Always go through Qcurrent_menubar.
51 Lisp_Object Vblank_menubar;
53 int popup_menu_titles;
55 Lisp_Object Vmenubar_pointer_glyph;
58 menubar_variable_changed (Lisp_Object sym, Lisp_Object *val,
59 Lisp_Object in_object, int flags)
66 update_frame_menubars (struct frame *f)
68 if (f->menubar_changed || f->windows_changed)
69 MAYBE_FRAMEMETH (f, update_frame_menubars, (f));
71 f->menubar_changed = 0;
75 free_frame_menubars (struct frame *f)
77 /* If we had directly allocated any memory for the menubars instead
78 of using all Lisp_Objects this is where we would now free it. */
80 MAYBE_FRAMEMETH (f, free_frame_menubars, (f));
84 menubar_visible_p_changed (Lisp_Object specifier, struct window *w,
91 menubar_visible_p_changed_in_frame (Lisp_Object specifier, struct frame *f,
94 update_frame_menubars (f);
98 current_frame_menubar (CONST struct frame* f)
100 struct window *w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f));
101 return symbol_value_in_buffer (Qcurrent_menubar, w->buffer);
105 menu_parse_submenu_keywords (Lisp_Object desc, Lisp_Object gui_item)
107 struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
109 /* Menu descriptor should be a list */
112 /* First element may be menu name, although can be omitted.
113 Let's think that if stuff begins with anything than a keyword
114 or a list (submenu), this is a menu name, expected to be a string */
115 if (!KEYWORDP (XCAR (desc)) && !CONSP (XCAR (desc)))
117 CHECK_STRING (XCAR (desc));
118 pgui_item->name = XCAR (desc);
124 /* Walk along all key-value pairs */
125 while (!NILP(desc) && KEYWORDP (XCAR (desc)))
127 Lisp_Object key, val;
135 gui_item_add_keyval_pair (gui_item, key, val, ERROR_ME);
138 /* Return the rest - supposed to be a list of items */
142 DEFUN ("menu-find-real-submenu", Fmenu_find_real_submenu, 2, 2, 0, /*
143 Find a submenu descriptor within DESC by following PATH.
144 This function finds a submenu descriptor, either from the description
145 DESC or generated by a filter within DESC. The function regards :config
146 and :included keywords in the DESC, and expands submenus along the
147 PATH using :filter functions. Return value is a descriptor for the
148 submenu, NOT expanded and NOT checked against :config and :included.
149 Also, individual menu items are not looked for, only submenus.
151 See also 'find-menu-item'.
155 Lisp_Object path_entry, submenu_desc, submenu;
157 Lisp_Object gui_item = allocate_gui_item ();
158 struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
162 EXTERNAL_LIST_LOOP (path_entry, path)
164 /* Verify that DESC describes a menu, not single item */
166 RETURN_UNGCPRO (Qnil);
168 /* Parse this menu */
169 desc = menu_parse_submenu_keywords (desc, gui_item);
171 /* Check that this (sub)menu is active */
172 if (!gui_item_active_p (gui_item))
173 RETURN_UNGCPRO (Qnil);
176 if (!NILP (pgui_item->filter))
177 desc = call1 (pgui_item->filter, desc);
179 /* Find the next menu on the path inside this one */
180 EXTERNAL_LIST_LOOP (submenu_desc, desc)
182 submenu = XCAR (submenu_desc);
184 && STRINGP (XCAR (submenu))
185 && !NILP (Fstring_equal (XCAR (submenu), XCAR (path_entry))))
191 /* Submenu not found */
192 RETURN_UNGCPRO (Qnil);
195 /* Prepare for the next iteration */
196 gui_item_init (gui_item);
199 /* We have successfully descended down the end of the path */
204 DEFUN ("popup-menu", Fpopup_menu, 1, 2, 0, /*
205 Pop up the given menu.
206 A menu description is a list of menu items, strings, and submenus.
208 The first element of a menu must be a string, which is the name of the menu.
209 This is the string that will be displayed in the parent menu, if any. For
210 toplevel menus, it is ignored. This string is not displayed in the menu
213 If an element of a menu is a string, then that string will be presented in
214 the menu as unselectable text.
216 If an element of a menu is a string consisting solely of hyphens, then that
217 item will be presented as a solid horizontal line.
219 If an element of a menu is a list, it is treated as a submenu. The name of
220 that submenu (the first element in the list) will be used as the name of the
221 item representing this menu on the parent.
223 Otherwise, the element must be a vector, which describes a menu item.
224 A menu item can have any of the following forms:
226 [ "name" callback <active-p> ]
227 [ "name" callback <active-p> <suffix> ]
228 [ "name" callback :<keyword> <value> :<keyword> <value> ... ]
230 The name is the string to display on the menu; it is filtered through the
231 resource database, so it is possible for resources to override what string
232 is actually displayed.
234 If the `callback' of a menu item is a symbol, then it must name a command.
235 It will be invoked with `call-interactively'. If it is a list, then it is
236 evaluated with `eval'.
238 The possible keywords are this:
240 :active <form> Same as <active-p> in the first two forms: the
241 expression is evaluated just before the menu is
242 displayed, and the menu will be selectable only if
243 the result is non-nil.
245 :suffix <form> Same as <suffix> in the second form: the expression
246 is evaluated just before the menu is displayed and
247 resulting string is appended to the displayed name,
248 providing a convenient way of adding the name of a
249 command's ``argument'' to the menu, like
250 ``Kill Buffer NAME''.
252 :keys "string" Normally, the keyboard equivalents of commands in
253 menus are displayed when the `callback' is a symbol.
254 This can be used to specify keys for more complex menu
255 items. It is passed through `substitute-command-keys'
258 :style <style> Specifies what kind of object this menu item is:
260 nil A normal menu item.
261 toggle A toggle button.
262 radio A radio button.
264 The only difference between toggle and radio buttons is
265 how they are displayed. But for consistency, a toggle
266 button should be used when there is one option whose
267 value can be turned on or off, and radio buttons should
268 be used when there is a set of mutually exclusive
269 options. When using a group of radio buttons, you
270 should arrange for no more than one to be marked as
273 :selected <form> Meaningful only when STYLE is `toggle' or `radio'.
274 This specifies whether the button will be in the
275 selected or unselected state.
279 [ "Save As..." write-file t ]
280 [ "Revert Buffer" revert-buffer (buffer-modified-p) ]
281 [ "Read Only" toggle-read-only :style toggle :selected buffer-read-only ]
283 See menubar.el for many more examples.
287 struct frame *f = decode_frame(Qnil);
288 MAYBE_FRAMEMETH (f, popup_menu, (menu_desc,event));
292 DEFUN ("normalize-menu-item-name", Fnormalize_menu_item_name, 1, 2, 0, /*
293 Convert a menu item name string into normal form, and return the new string.
294 Menu item names should be converted to normal form before being compared.
298 struct buffer *buf = decode_buffer (buffer, 0);
299 struct Lisp_String *n;
303 Bufbyte *string_result;
304 Bufbyte *string_result_ptr;
306 int expecting_underscore = 0;
311 end = string_char_length (n);
312 name_data = string_data (n);
314 string_result = (Bufbyte *) alloca (end * MAX_EMCHAR_LEN);
315 string_result_ptr = string_result;
316 for (i = 0; i < end; i++)
318 elt = charptr_emchar (name_data);
319 elt = DOWNCASE (buf, elt);
320 if (expecting_underscore)
322 expecting_underscore = 0;
326 /* Allow `%%' to mean `%'. */
327 string_result_ptr += set_charptr_emchar (string_result_ptr, '%');
332 string_result_ptr += set_charptr_emchar (string_result_ptr, '%');
333 string_result_ptr += set_charptr_emchar (string_result_ptr, elt);
337 expecting_underscore = 1;
339 string_result_ptr += set_charptr_emchar (string_result_ptr, elt);
340 INC_CHARPTR (name_data);
343 return make_string (string_result, string_result_ptr - string_result);
347 syms_of_menubar (void)
349 defsymbol (&Qcurrent_menubar, "current-menubar");
350 DEFSUBR (Fpopup_menu);
351 DEFSUBR (Fnormalize_menu_item_name);
352 DEFSUBR (Fmenu_find_real_submenu);
356 vars_of_menubar (void)
359 /* put in Vblank_menubar a menubar value which has no visible
360 * items. This is a bit tricky due to various quirks. We
361 * could use '(["" nil nil]), but this is apparently equivalent
362 * to '(nil), and a new frame created with this menubar will
363 * get a vertically-squished menubar. If we use " " as the
364 * button title instead of "", we get an etched button border.
366 * '(("No active menubar" ["" nil nil]))
367 * which creates a menu whose title is "No active menubar",
368 * and this works fine.
371 Lisp_Object menu_item[3];
372 static CONST char *blank_msg = "No active menubar";
374 menu_item[0] = build_string ("");
377 Vblank_menubar = Fcons (Fcons (build_string (blank_msg),
378 Fcons (Fvector (3, &menu_item[0]),
381 Vblank_menubar = Fpurecopy (Vblank_menubar);
382 staticpro (&Vblank_menubar);
385 DEFVAR_BOOL ("popup-menu-titles", &popup_menu_titles /*
386 If true, popup menus will have title bars at the top.
388 popup_menu_titles = 1;
390 /* #### Replace current menubar with a specifier. */
392 /* All C code must access the menubar via Qcurrent_menubar
393 because it can be buffer-local. Note that Vcurrent_menubar
394 doesn't need to exist at all, except for the magic function. */
396 DEFVAR_LISP_MAGIC ("current-menubar", &Vcurrent_menubar /*
397 The current menubar. This may be buffer-local.
399 When the menubar is changed, the function `set-menubar-dirty-flag' has to
400 be called for the menubar to be updated on the frame. See `set-menubar'
401 and `set-buffer-menubar'.
403 A menubar is a list of menus and menu-items.
404 A menu is a list of menu items, keyword-value pairs, strings, and submenus.
406 The first element of a menu must be a string, which is the name of the menu.
407 This is the string that will be displayed in the parent menu, if any. For
408 toplevel menus, it is ignored. This string is not displayed in the menu
411 Immediately following the name string of the menu, any of three
412 optional keyword-value pairs is permitted.
414 If an element of a menu (or menubar) is a string, then that string will be
415 presented as unselectable text.
417 If an element of a menu is a string consisting solely of hyphens, then that
418 item will be presented as a solid horizontal line.
420 If an element of a menu is a list, it is treated as a submenu. The name of
421 that submenu (the first element in the list) will be used as the name of the
422 item representing this menu on the parent.
424 If an element of a menubar is `nil', then it is used to represent the
425 division between the set of menubar-items which are flushleft and those
426 which are flushright.
428 Otherwise, the element must be a vector, which describes a menu item.
429 A menu item can have any of the following forms:
431 [ "name" callback <active-p> ]
432 [ "name" callback <active-p> <suffix> ]
433 [ "name" callback :<keyword> <value> :<keyword> <value> ... ]
435 The name is the string to display on the menu; it is filtered through the
436 resource database, so it is possible for resources to override what string
437 is actually displayed.
439 If the `callback' of a menu item is a symbol, then it must name a command.
440 It will be invoked with `call-interactively'. If it is a list, then it is
441 evaluated with `eval'.
443 The possible keywords are this:
445 :active <form> Same as <active-p> in the first two forms: the
446 expression is evaluated just before the menu is
447 displayed, and the menu will be selectable only if
448 the result is non-nil.
450 :suffix <form> Same as <suffix> in the second form: the expression
451 is evaluated just before the menu is displayed and
452 resulting string is appended to the displayed name,
453 providing a convenient way of adding the name of a
454 command's ``argument'' to the menu, like
455 ``Kill Buffer NAME''.
457 :keys "string" Normally, the keyboard equivalents of commands in
458 menus are displayed when the `callback' is a symbol.
459 This can be used to specify keys for more complex menu
460 items. It is passed through `substitute-command-keys'
463 :style <style> Specifies what kind of object this menu item is:
465 nil A normal menu item.
466 toggle A toggle button.
467 radio A radio button.
468 button A menubar button.
470 The only difference between toggle and radio buttons is
471 how they are displayed. But for consistency, a toggle
472 button should be used when there is one option whose
473 value can be turned on or off, and radio buttons should
474 be used when there is a set of mutually exclusive
475 options. When using a group of radio buttons, you
476 should arrange for no more than one to be marked as
479 :selected <form> Meaningful only when STYLE is `toggle', `radio' or
480 `button'. This specifies whether the button will be in
481 the selected or unselected state.
483 :included <form> This can be used to control the visibility of a menu or
484 menu item. The form is evaluated and the menu or menu
485 item is only displayed if the result is non-nil.
487 :config <symbol> This is an efficient shorthand for
488 :included (memq symbol menubar-configuration)
489 See the variable `menubar-configuration'.
491 :filter <function> A menu filter can only be used in a menu item list.
492 (i.e.: not in a menu item itself). It is used to
493 sensitize or incrementally create a submenu only when
494 it is selected by the user and not every time the
495 menubar is activated. The filter function is passed
496 the list of menu items in the submenu and must return a
497 list of menu items to be used for the menu. It is
498 called only when the menu is about to be displayed, so
499 other menus may already be displayed. Vile and
500 terrible things will happen if a menu filter function
501 changes the current buffer, window, or frame. It
502 also should not raise, lower, or iconify any frames.
503 Basically, the filter function should have no
506 :key-sequence keys Used in FSF Emacs as an hint to an equivalent keybinding.
507 Ignored by XEnacs for easymenu.el compatability.
509 :label <form> (unimplemented!) Like :suffix, but replaces label
511 (might be added in 21.2).
516 :filter file-menu-filter ; file-menu-filter is a function that takes
517 ; one argument (a list of menu items) and
518 ; returns a list of menu items
519 [ "Save As..." write-file t ]
520 [ "Revert Buffer" revert-buffer (buffer-modified-p) ]
521 [ "Read Only" toggle-read-only :style toggle
522 :selected buffer-read-only ]
525 See x-menubar.el for many more examples.
527 After the menubar is clicked upon, but before any menus are popped up,
528 the functions on the `activate-menubar-hook' are invoked to make top-level
529 changes to the menus and menubar. Note, however, that the use of menu
530 filters (using the :filter keyword) is usually a more efficient way to
531 dynamically alter or sensitize menus.
532 */, menubar_variable_changed);
534 Vcurrent_menubar = Qnil;
536 DEFVAR_LISP ("activate-menubar-hook", &Vactivate_menubar_hook /*
537 Function or functions called before a menubar menu is pulled down.
538 These functions are called with no arguments, and should interrogate and
539 modify the value of `current-menubar' as desired.
541 The functions on this hook are invoked after the mouse goes down, but before
542 the menu is mapped, and may be used to activate, deactivate, add, or delete
543 items from the menus. However, it is probably the case that using a :filter
544 keyword in a submenu would be a more efficient way of updating menus. See
545 the documentation of `current-menubar'.
547 These functions may return the symbol `t' to assert that they have made
548 no changes to the menubar. If any other value is returned, the menubar is
549 recomputed. If `t' is returned but the menubar has been changed, then the
550 changes may not show up right away. Returning `nil' when the menubar has
551 not changed is not so bad; more computation will be done, but redisplay of
552 the menubar will still be performed optimally.
554 Vactivate_menubar_hook = Qnil;
555 defsymbol (&Qactivate_menubar_hook, "activate-menubar-hook");
557 DEFVAR_BOOL ("menubar-show-keybindings", &menubar_show_keybindings /*
558 If true, the menubar will display keyboard equivalents.
559 If false, only the command names will be displayed.
561 menubar_show_keybindings = 1;
563 DEFVAR_LISP_MAGIC ("menubar-configuration", &Vmenubar_configuration /*
564 A list of symbols, against which the value of the :config tag for each
565 menubar item will be compared. If a menubar item has a :config tag, then
566 it is omitted from the menubar if that tag is not a member of the
567 `menubar-configuration' list.
568 */ , menubar_variable_changed);
569 Vmenubar_configuration = Qnil;
571 DEFVAR_LISP ("menubar-pointer-glyph", &Vmenubar_pointer_glyph /*
572 *The shape of the mouse-pointer when over the menubar.
573 This is a glyph; use `set-glyph-image' to change it.
574 If unspecified in a particular domain, the window-system-provided
575 default pointer is used.
578 Fprovide (intern ("menubar"));
582 specifier_vars_of_menubar (void)
584 DEFVAR_SPECIFIER ("menubar-visible-p", &Vmenubar_visible_p /*
585 *Whether the menubar is visible.
586 This is a specifier; use `set-specifier' to change it.
588 Vmenubar_visible_p = Fmake_specifier (Qboolean);
590 set_specifier_fallback (Vmenubar_visible_p, list1 (Fcons (Qnil, Qt)));
591 set_specifier_caching (Vmenubar_visible_p,
592 slot_offset (struct window,
594 menubar_visible_p_changed,
595 slot_offset (struct frame,
597 menubar_visible_p_changed_in_frame);
601 complex_vars_of_menubar (void)
603 Vmenubar_pointer_glyph = Fmake_glyph_internal (Qpointer);