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 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 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);
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)
358 /* put in Vblank_menubar a menubar value which has no visible
359 * items. This is a bit tricky due to various quirks. We
360 * could use '(["" nil nil]), but this is apparently equivalent
361 * to '(nil), and a new frame created with this menubar will
362 * get a vertically-squished menubar. If we use " " as the
363 * button title instead of "", we get an etched button border.
365 * '(("No active menubar" ["" nil nil]))
366 * which creates a menu whose title is "No active menubar",
367 * and this works fine.
370 Vblank_menubar = list1 (list2 (build_string ("No active menubar"),
371 vector3 (build_string (""), Qnil, Qnil)));
372 staticpro (&Vblank_menubar);
374 DEFVAR_BOOL ("popup-menu-titles", &popup_menu_titles /*
375 If true, popup menus will have title bars at the top.
377 popup_menu_titles = 1;
379 /* #### Replace current menubar with a specifier. */
381 /* All C code must access the menubar via Qcurrent_menubar
382 because it can be buffer-local. Note that Vcurrent_menubar
383 doesn't need to exist at all, except for the magic function. */
385 DEFVAR_LISP_MAGIC ("current-menubar", &Vcurrent_menubar /*
386 The current menubar. This may be buffer-local.
388 When the menubar is changed, the function `set-menubar-dirty-flag' has to
389 be called for the menubar to be updated on the frame. See `set-menubar'
390 and `set-buffer-menubar'.
392 A menubar is a list of menus and menu-items.
393 A menu is a list of menu items, keyword-value pairs, strings, and submenus.
395 The first element of a menu must be a string, which is the name of the menu.
396 This is the string that will be displayed in the parent menu, if any. For
397 toplevel menus, it is ignored. This string is not displayed in the menu
400 Immediately following the name string of the menu, any of three
401 optional keyword-value pairs is permitted.
403 If an element of a menu (or menubar) is a string, then that string will be
404 presented as unselectable text.
406 If an element of a menu is a string consisting solely of hyphens, then that
407 item will be presented as a solid horizontal line.
409 If an element of a menu is a list, it is treated as a submenu. The name of
410 that submenu (the first element in the list) will be used as the name of the
411 item representing this menu on the parent.
413 If an element of a menubar is `nil', then it is used to represent the
414 division between the set of menubar-items which are flushleft and those
415 which are flushright.
417 Otherwise, the element must be a vector, which describes a menu item.
418 A menu item can have any of the following forms:
420 [ "name" callback <active-p> ]
421 [ "name" callback <active-p> <suffix> ]
422 [ "name" callback :<keyword> <value> :<keyword> <value> ... ]
424 The name is the string to display on the menu; it is filtered through the
425 resource database, so it is possible for resources to override what string
426 is actually displayed.
428 If the `callback' of a menu item is a symbol, then it must name a command.
429 It will be invoked with `call-interactively'. If it is a list, then it is
430 evaluated with `eval'.
432 The possible keywords are this:
434 :active <form> Same as <active-p> in the first two forms: the
435 expression is evaluated just before the menu is
436 displayed, and the menu will be selectable only if
437 the result is non-nil.
439 :suffix <form> Same as <suffix> in the second form: the expression
440 is evaluated just before the menu is displayed and
441 resulting string is appended to the displayed name,
442 providing a convenient way of adding the name of a
443 command's ``argument'' to the menu, like
444 ``Kill Buffer NAME''.
446 :keys "string" Normally, the keyboard equivalents of commands in
447 menus are displayed when the `callback' is a symbol.
448 This can be used to specify keys for more complex menu
449 items. It is passed through `substitute-command-keys'
452 :style <style> Specifies what kind of object this menu item is:
454 nil A normal menu item.
455 toggle A toggle button.
456 radio A radio button.
457 button A menubar button.
459 The only difference between toggle and radio buttons is
460 how they are displayed. But for consistency, a toggle
461 button should be used when there is one option whose
462 value can be turned on or off, and radio buttons should
463 be used when there is a set of mutually exclusive
464 options. When using a group of radio buttons, you
465 should arrange for no more than one to be marked as
468 :selected <form> Meaningful only when STYLE is `toggle', `radio' or
469 `button'. This specifies whether the button will be in
470 the selected or unselected state.
472 :included <form> This can be used to control the visibility of a menu or
473 menu item. The form is evaluated and the menu or menu
474 item is only displayed if the result is non-nil.
476 :config <symbol> This is an efficient shorthand for
477 :included (memq symbol menubar-configuration)
478 See the variable `menubar-configuration'.
480 :filter <function> A menu filter can only be used in a menu item list.
481 (i.e.: not in a menu item itself). It is used to
482 sensitize or incrementally create a submenu only when
483 it is selected by the user and not every time the
484 menubar is activated. The filter function is passed
485 the list of menu items in the submenu and must return a
486 list of menu items to be used for the menu. It is
487 called only when the menu is about to be displayed, so
488 other menus may already be displayed. Vile and
489 terrible things will happen if a menu filter function
490 changes the current buffer, window, or frame. It
491 also should not raise, lower, or iconify any frames.
492 Basically, the filter function should have no
495 :key-sequence keys Used in FSF Emacs as an hint to an equivalent keybinding.
496 Ignored by XEnacs for easymenu.el compatibility.
498 :label <form> (unimplemented!) Like :suffix, but replaces label
500 (might be added in 21.2).
505 :filter file-menu-filter ; file-menu-filter is a function that takes
506 ; one argument (a list of menu items) and
507 ; returns a list of menu items
508 [ "Save As..." write-file t ]
509 [ "Revert Buffer" revert-buffer (buffer-modified-p) ]
510 [ "Read Only" toggle-read-only :style toggle
511 :selected buffer-read-only ]
514 See x-menubar.el for many more examples.
516 After the menubar is clicked upon, but before any menus are popped up,
517 the functions on the `activate-menubar-hook' are invoked to make top-level
518 changes to the menus and menubar. Note, however, that the use of menu
519 filters (using the :filter keyword) is usually a more efficient way to
520 dynamically alter or sensitize menus.
521 */, menubar_variable_changed);
523 Vcurrent_menubar = Qnil;
525 DEFVAR_LISP ("activate-menubar-hook", &Vactivate_menubar_hook /*
526 Function or functions called before a menubar menu is pulled down.
527 These functions are called with no arguments, and should interrogate and
528 modify the value of `current-menubar' as desired.
530 The functions on this hook are invoked after the mouse goes down, but before
531 the menu is mapped, and may be used to activate, deactivate, add, or delete
532 items from the menus. However, it is probably the case that using a :filter
533 keyword in a submenu would be a more efficient way of updating menus. See
534 the documentation of `current-menubar'.
536 These functions may return the symbol `t' to assert that they have made
537 no changes to the menubar. If any other value is returned, the menubar is
538 recomputed. If `t' is returned but the menubar has been changed, then the
539 changes may not show up right away. Returning `nil' when the menubar has
540 not changed is not so bad; more computation will be done, but redisplay of
541 the menubar will still be performed optimally.
543 Vactivate_menubar_hook = Qnil;
544 defsymbol (&Qactivate_menubar_hook, "activate-menubar-hook");
546 DEFVAR_BOOL ("menubar-show-keybindings", &menubar_show_keybindings /*
547 If true, the menubar will display keyboard equivalents.
548 If false, only the command names will be displayed.
550 menubar_show_keybindings = 1;
552 DEFVAR_LISP_MAGIC ("menubar-configuration", &Vmenubar_configuration /*
553 A list of symbols, against which the value of the :config tag for each
554 menubar item will be compared. If a menubar item has a :config tag, then
555 it is omitted from the menubar if that tag is not a member of the
556 `menubar-configuration' list.
557 */ , menubar_variable_changed);
558 Vmenubar_configuration = Qnil;
560 DEFVAR_LISP ("menubar-pointer-glyph", &Vmenubar_pointer_glyph /*
561 *The shape of the mouse-pointer when over the menubar.
562 This is a glyph; use `set-glyph-image' to change it.
563 If unspecified in a particular domain, the window-system-provided
564 default pointer is used.
567 Fprovide (intern ("menubar"));
571 specifier_vars_of_menubar (void)
573 DEFVAR_SPECIFIER ("menubar-visible-p", &Vmenubar_visible_p /*
574 *Whether the menubar is visible.
575 This is a specifier; use `set-specifier' to change it.
577 Vmenubar_visible_p = Fmake_specifier (Qboolean);
579 set_specifier_fallback (Vmenubar_visible_p, list1 (Fcons (Qnil, Qt)));
580 set_specifier_caching (Vmenubar_visible_p,
581 offsetof (struct window, menubar_visible_p),
582 menubar_visible_p_changed,
583 offsetof (struct frame, menubar_visible_p),
584 menubar_visible_p_changed_in_frame);
588 complex_vars_of_menubar (void)
590 Vmenubar_pointer_glyph = Fmake_glyph_internal (Qpointer);