Mercurial > hg > xemacs-beta
diff src/menubar.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 859a2309aef8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/menubar.c Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,428 @@ +/* Implements an elisp-programmable menubar. + Copyright (C) 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1995 Tinker Systems and INS Engineering Corp. + +This file is part of XEmacs. + +XEmacs is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +XEmacs is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with XEmacs; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Synched up with: Not in FSF. */ + +/* #### There ain't much here because menubars have not been + properly abstracted yet. */ + +#include <config.h> +#include "lisp.h" + +#include "device.h" +#include "frame.h" +#include "menubar.h" +#include "redisplay.h" +#include "window.h" + +int menubar_show_keybindings; +Lisp_Object Vmenubar_configuration; + +Lisp_Object Qcurrent_menubar; + +Lisp_Object Qactivate_menubar_hook, Vactivate_menubar_hook; + +Lisp_Object Vmenubar_visible_p; + +static Lisp_Object Vcurrent_menubar; /* DO NOT ever reference this. + Always go through Qcurrent_menubar. + See below. */ +Lisp_Object Vblank_menubar; + +int popup_menu_titles; + +Lisp_Object Vmenubar_pointer_glyph; + +static int +menubar_variable_changed (Lisp_Object sym, Lisp_Object *val, + Lisp_Object in_object, int flags) +{ + MARK_MENUBAR_CHANGED; + return 0; +} + +void +update_frame_menubars (struct frame *f) +{ + if (f->menubar_changed || f->windows_changed) + MAYBE_FRAMEMETH (f, update_frame_menubars, (f)); + + f->menubar_changed = 0; +} + +void +free_frame_menubars (struct frame *f) +{ + /* If we had directly allocated any memory for the menubars instead + of using all Lisp_Objects this is where we would now free it. */ + + MAYBE_FRAMEMETH (f, free_frame_menubars, (f)); +} + +static void +menubar_visible_p_changed (Lisp_Object specifier, struct window *w, + Lisp_Object oldval) +{ + MARK_MENUBAR_CHANGED; +} + +static void +menubar_visible_p_changed_in_frame (Lisp_Object specifier, struct frame *f, + Lisp_Object oldval) +{ + update_frame_menubars (f); +} + +DEFUN ("popup-menu", Fpopup_menu, Spopup_menu, 1, 2, 0 /* +Pop up the given menu. +A menu description is a list of menu items, strings, and submenus. + +The first element of a menu must be a string, which is the name of the menu. +This is the string that will be displayed in the parent menu, if any. For +toplevel menus, it is ignored. This string is not displayed in the menu +itself. + +If an element of a menu is a string, then that string will be presented in +the menu as unselectable text. + +If an element of a menu is a string consisting solely of hyphens, then that +item will be presented as a solid horizontal line. + +If an element of a menu is a list, it is treated as a submenu. The name of +that submenu (the first element in the list) will be used as the name of the +item representing this menu on the parent. + +Otherwise, the element must be a vector, which describes a menu item. +A menu item can have any of the following forms: + + [ \"name\" callback <active-p> ] + [ \"name\" callback <active-p> \"suffix\" ] + [ \"name\" callback :<keyword> <value> :<keyword> <value> ... ] + +The name is the string to display on the menu; it is filtered through the +resource database, so it is possible for resources to override what string +is actually displayed. + +If the `callback' of a menu item is a symbol, then it must name a command. +It will be invoked with `call-interactively'. If it is a list, then it is +evaluated with `eval'. + +The possible keywords are this: + + :active <form> Same as <active-p> in the first two forms: the + expression is evaluated just before the menu is + displayed, and the menu will be selectable only if + the result is non-nil. + + :suffix \"string\" Same as \"suffix\" in the second form: the suffix is + appended to the displayed name, providing a convenient + way of adding the name of a command's ``argument'' to + the menu, like ``Kill Buffer NAME''. + + :keys \"string\" Normally, the keyboard equivalents of commands in + menus are displayed when the `callback' is a symbol. + This can be used to specify keys for more complex menu + items. It is passed through `substitute-command-keys' + first. + + :style <style> Specifies what kind of object this menu item is: + + nil A normal menu item. + toggle A toggle button. + radio A radio button. + + The only difference between toggle and radio buttons is + how they are displayed. But for consistency, a toggle + button should be used when there is one option whose + value can be turned on or off, and radio buttons should + be used when there is a set of mutually exclusive + options. When using a group of radio buttons, you + should arrange for no more than one to be marked as + selected at a time. + + :selected <form> Meaningful only when STYLE is `toggle' or `radio'. + This specifies whether the button will be in the + selected or unselected state. + +For example: + + [ \"Save As...\" write-file t ] + [ \"Revert Buffer\" revert-buffer (buffer-modified-p) ] + [ \"Read Only\" toggle-read-only :style toggle :selected buffer-read-only ] + +See menubar.el for many more examples. +*/ ) + (menu_desc, event) + Lisp_Object menu_desc, event; +{ + struct frame *f = decode_frame(Qnil); + MAYBE_FRAMEMETH (f, popup_menu, (menu_desc,event)); + return Qnil; +} + +void +syms_of_menubar (void) +{ + defsymbol (&Qcurrent_menubar, "current-menubar"); + defsubr (&Spopup_menu); +} + +void +vars_of_menubar (void) +{ + { + /* put in Vblank_menubar a menubar value which has no visible + * items. This is a bit tricky due to various quirks. We + * could use '(["" nil nil]), but this is apparently equivalent + * to '(nil), and a new frame created with this menubar will + * get a vertically-squished menubar. If we use " " as the + * button title instead of "", we get an etched button border. + * So we use + * '(("No active menubar" ["" nil nil])) + * which creates a menu whose title is "No active menubar", + * and this works fine. + */ + + Lisp_Object menu_item[3]; + static CONST char *blank_msg = "No active menubar"; + + menu_item[0] = build_string (""); + menu_item[1] = Qnil; + menu_item[2] = Qnil; + Vblank_menubar = Fcons (Fcons (build_string (blank_msg), + Fcons (Fvector (3, &menu_item[0]), + Qnil)), + Qnil); + Vblank_menubar = Fpurecopy (Vblank_menubar); + staticpro (&Vblank_menubar); + } + + DEFVAR_BOOL ("popup-menu-titles", &popup_menu_titles /* +If true, popup menus will have title bars at the top. +*/ ); + popup_menu_titles = 1; + + /* #### Replace current menubar with a specifier. */ + + /* All C code must access the menubar via Qcurrent_menubar + because it can be buffer-local. Note that Vcurrent_menubar + doesn't need to exist at all, except for the magic function. */ + + DEFVAR_LISP_MAGIC ("current-menubar", &Vcurrent_menubar /* +The current menubar. This may be buffer-local. + +When the menubar is changed, the function `set-menubar-dirty-flag' has to +be called for the menubar to be updated on the frame. See `set-menubar' +and `set-buffer-menubar'. + +A menubar is a list of menus and menu-items. +A menu is a list of menu items, keyword-value pairs, strings, and submenus. + +The first element of a menu must be a string, which is the name of the menu. +This is the string that will be displayed in the parent menu, if any. For +toplevel menus, it is ignored. This string is not displayed in the menu +itself. + +Immediately following the name string of the menu, any of three +optional keyword-value pairs is permitted. + +If an element of a menu (or menubar) is a string, then that string will be +presented as unselectable text. + +If an element of a menu is a string consisting solely of hyphens, then that +item will be presented as a solid horizontal line. + +If an element of a menu is a list, it is treated as a submenu. The name of +that submenu (the first element in the list) will be used as the name of the +item representing this menu on the parent. + +If an element of a menubar is `nil', then it is used to represent the +division between the set of menubar-items which are flushleft and those +which are flushright. + +Otherwise, the element must be a vector, which describes a menu item. +A menu item can have any of the following forms: + + [ \"name\" callback <active-p> ] + [ \"name\" callback <active-p> \"suffix\" ] + [ \"name\" callback :<keyword> <value> :<keyword> <value> ... ] + +The name is the string to display on the menu; it is filtered through the +resource database, so it is possible for resources to override what string +is actually displayed. + +If the `callback' of a menu item is a symbol, then it must name a command. +It will be invoked with `call-interactively'. If it is a list, then it is +evaluated with `eval'. + +The possible keywords are this: + + :active <form> Same as <active-p> in the first two forms: the + expression is evaluated just before the menu is + displayed, and the menu will be selectable only if + the result is non-nil. + + :suffix \"string\" Same as \"suffix\" in the second form: the suffix is + appended to the displayed name, providing a convenient + way of adding the name of a command's ``argument'' to + the menu, like ``Kill Buffer NAME''. + + :keys \"string\" Normally, the keyboard equivalents of commands in + menus are displayed when the `callback' is a symbol. + This can be used to specify keys for more complex menu + items. It is passed through `substitute-command-keys' + first. + + :style <style> Specifies what kind of object this menu item is: + + nil A normal menu item. + toggle A toggle button. + radio A radio button. + button A menubar button. + + The only difference between toggle and radio buttons is + how they are displayed. But for consistency, a toggle + button should be used when there is one option whose + value can be turned on or off, and radio buttons should + be used when there is a set of mutually exclusive + options. When using a group of radio buttons, you + should arrange for no more than one to be marked as + selected at a time. + + :selected <form> Meaningful only when STYLE is `toggle', `radio' or + `button'. This specifies whether the button will be in + the selected or unselected state. + + :included <form> This can be used to control the visibility of a menu or + menu item. The form is evaluated and the menu or menu + item is only displayed if the result is non-nil. + + :config <symbol> This is an efficient shorthand for + :included (memq symbol menubar-configuration) + See the variable `menubar-configuration'. + + :filter <function> A menu filter can only be used in a menu item list. + (i.e.: not in a menu item itself). It is used to + sensitize or incrementally create a submenu only when + it is selected by the user and not every time the + menubar is activated. The filter function is passed + the list of menu items in the submenu and must return a + list of menu items to be used for the menu. It is + called only when the menu is about to be displayed, so + other menus may already be displayed. Vile and + terrible things will happen if a menu filter function + changes the current buffer, window, or frame. It + also should not raise, lower, or iconify any frames. + Basically, the filter function should have no + side-effects. + +For example: + + (\"File\" + :filter file-menu-filter ; file-menu-filter is a function that takes + ; one argument (a list of menu items) and + ; returns a list of menu items + [ \"Save As...\" write-file t ] + [ \"Revert Buffer\" revert-buffer (buffer-modified-p) ] + [ \"Read Only\" toggle-read-only :style toggle + :selected buffer-read-only ] + ) + +See x-menubar.el for many more examples. + +After the menubar is clicked upon, but before any menus are popped up, +the functions on the `activate-menubar-hook' are invoked to make top-level +changes to the menus and menubar. Note, however, that the use of menu +filters (using the :filter keyword) is usually a more efficient way to +dynamically alter or sensitize menus. +*/, menubar_variable_changed); + + Vcurrent_menubar = Qnil; + + DEFVAR_LISP ("activate-menubar-hook", &Vactivate_menubar_hook /* +Function or functions called before a menubar menu is pulled down. +These functions are called with no arguments, and should interrogate and +modify the value of `current-menubar' as desired. + +The functions on this hook are invoked after the mouse goes down, but before +the menu is mapped, and may be used to activate, deactivate, add, or delete +items from the menus. However, it is probably the case that using a :filter +keyword in a submenu would be a more efficient way of updating menus. See +the documentation of `current-menubar'. + +These functions may return the symbol `t' to assert that they have made +no changes to the menubar. If any other value is returned, the menubar is +recomputed. If `t' is returned but the menubar has been changed, then the +changes may not show up right away. Returning `nil' when the menubar has +not changed is not so bad; more computation will be done, but redisplay of +the menubar will still be performed optimally. +*/ ); + Vactivate_menubar_hook = Qnil; + defsymbol (&Qactivate_menubar_hook, "activate-menubar-hook"); + + DEFVAR_BOOL ("menubar-show-keybindings", &menubar_show_keybindings /* +If true, the menubar will display keyboard equivalents. +If false, only the command names will be displayed. +*/ ); + menubar_show_keybindings = 1; + + DEFVAR_LISP_MAGIC ("menubar-configuration", &Vmenubar_configuration /* +A list of symbols, against which the value of the :config tag for each +menubar item will be compared. If a menubar item has a :config tag, then +it is omitted from the menubar if that tag is not a member of the +`menubar-configuration' list. +*/ , menubar_variable_changed); + Vmenubar_configuration = Qnil; + + DEFVAR_LISP ("menubar-pointer-glyph", &Vmenubar_pointer_glyph /* +*The shape of the mouse-pointer when over the menubar. +This is a glyph; use `set-glyph-image' to change it. +If unspecified in a particular domain, the window-system-provided +default pointer is used. +*/ ); + + Fprovide (intern ("menubar")); +} + +void +specifier_vars_of_menubar (void) +{ + DEFVAR_SPECIFIER ("menubar-visible-p", &Vmenubar_visible_p /* +*Whether the menubar is visible. +This is a specifier; use `set-specifier' to change it. +*/ ); + Vmenubar_visible_p = Fmake_specifier (Qboolean); + + set_specifier_fallback (Vmenubar_visible_p, list1 (Fcons (Qnil, Qt))); + set_specifier_caching (Vmenubar_visible_p, + slot_offset (struct window, + menubar_visible_p), + menubar_visible_p_changed, + slot_offset (struct frame, + menubar_visible_p), + menubar_visible_p_changed_in_frame); +} + +void +complex_vars_of_menubar (void) +{ + Vmenubar_pointer_glyph = Fmake_glyph_internal (Qpointer); +}