Mercurial > hg > xemacs-beta
annotate src/menubar.c @ 5868:da732079c58d
Correct some code with badly-placed parentheses, thank you Mats Lidell.
lisp/ChangeLog addition:
2015-03-16 Aidan Kehoe <kehoea@parhasard.net>
* tty-init.el (make-frame-after-init-entry-point):
Some parentheses were placed badly here with the last change,
thank you Mats for pointing it out; in passing, change to a
version of the code that doesn't create a string for garbage, not
that it matters.
| author | Aidan Kehoe <kehoea@parhasard.net> |
|---|---|
| date | Mon, 16 Mar 2015 00:40:31 +0000 |
| parents | 68f8d295be49 |
| children |
| rev | line source |
|---|---|
| 428 | 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. | |
| 3025 | 4 Copyright (C) 2001, 2002, 2003, 2005 Ben Wing. |
| 428 | 5 |
| 6 This file is part of XEmacs. | |
| 7 | |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4952
diff
changeset
|
8 XEmacs is free software: you can redistribute it and/or modify it |
| 428 | 9 under the terms of the GNU General Public License as published by the |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4952
diff
changeset
|
10 Free Software Foundation, either version 3 of the License, or (at your |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4952
diff
changeset
|
11 option) any later version. |
| 428 | 12 |
| 13 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
| 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 16 for more details. | |
| 17 | |
| 18 You should have received a copy of the GNU General Public License | |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4952
diff
changeset
|
19 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
| 428 | 20 |
| 21 /* Synched up with: Not in FSF. */ | |
| 22 | |
| 442 | 23 /* Authorship: |
| 24 | |
| 25 Created by Ben Wing as part of device-abstraction work for 19.12. | |
| 26 Menu filters and many other keywords added by Stig for 19.12. | |
| 27 Menu accelerators c. 1997? by ??. Moved here from event-stream.c. | |
| 28 Much other work post-1996 by ??. | |
| 29 */ | |
| 428 | 30 |
| 31 #include <config.h> | |
| 32 #include "lisp.h" | |
| 33 | |
| 34 #include "buffer.h" | |
| 872 | 35 #include "device-impl.h" |
| 36 #include "frame-impl.h" | |
| 428 | 37 #include "gui.h" |
| 442 | 38 #include "keymap.h" |
| 428 | 39 #include "menubar.h" |
| 40 #include "redisplay.h" | |
| 800 | 41 #include "specifier.h" |
| 872 | 42 #include "window-impl.h" |
| 428 | 43 |
| 44 int menubar_show_keybindings; | |
| 45 Lisp_Object Vmenubar_configuration; | |
| 46 | |
| 47 Lisp_Object Qcurrent_menubar; | |
| 48 | |
| 49 Lisp_Object Qactivate_menubar_hook, Vactivate_menubar_hook; | |
| 50 | |
| 51 Lisp_Object Vmenubar_visible_p; | |
| 52 | |
| 53 static Lisp_Object Vcurrent_menubar; /* DO NOT ever reference this. | |
| 54 Always go through Qcurrent_menubar. | |
| 55 See below. */ | |
| 56 | |
| 57 Lisp_Object Vblank_menubar; | |
| 58 | |
| 59 int popup_menu_titles; | |
| 1279 | 60 int in_menu_callback; |
| 428 | 61 |
| 62 Lisp_Object Vmenubar_pointer_glyph; | |
| 63 | |
| 442 | 64 /* prefix key(s) that must match in order to activate menu. |
| 65 This is ugly. fix me. | |
| 66 */ | |
| 67 Lisp_Object Vmenu_accelerator_prefix; | |
| 68 | |
| 69 /* list of modifier keys to match accelerator for top level menus */ | |
| 70 Lisp_Object Vmenu_accelerator_modifiers; | |
| 71 | |
| 72 /* whether menu accelerators are enabled */ | |
| 73 Lisp_Object Vmenu_accelerator_enabled; | |
| 74 | |
| 75 /* keymap for auxiliary menu accelerator functions */ | |
| 76 Lisp_Object Vmenu_accelerator_map; | |
| 77 | |
| 78 Lisp_Object Qmenu_force; | |
| 79 Lisp_Object Qmenu_fallback; | |
| 80 Lisp_Object Qmenu_quit; | |
| 81 Lisp_Object Qmenu_up; | |
| 82 Lisp_Object Qmenu_down; | |
| 83 Lisp_Object Qmenu_left; | |
| 84 Lisp_Object Qmenu_right; | |
| 85 Lisp_Object Qmenu_select; | |
| 86 Lisp_Object Qmenu_escape; | |
| 87 | |
| 428 | 88 static int |
| 2286 | 89 menubar_variable_changed (Lisp_Object UNUSED (sym), Lisp_Object *UNUSED (val), |
| 90 Lisp_Object UNUSED (in_object), int UNUSED (flags)) | |
| 428 | 91 { |
| 92 MARK_MENUBAR_CHANGED; | |
| 93 return 0; | |
| 94 } | |
| 95 | |
| 96 void | |
| 97 update_frame_menubars (struct frame *f) | |
| 98 { | |
| 99 if (f->menubar_changed || f->windows_changed) | |
| 100 MAYBE_FRAMEMETH (f, update_frame_menubars, (f)); | |
| 101 | |
| 102 f->menubar_changed = 0; | |
| 103 } | |
| 104 | |
| 105 void | |
| 106 free_frame_menubars (struct frame *f) | |
| 107 { | |
| 108 /* If we had directly allocated any memory for the menubars instead | |
| 109 of using all Lisp_Objects this is where we would now free it. */ | |
| 110 | |
| 111 MAYBE_FRAMEMETH (f, free_frame_menubars, (f)); | |
| 112 } | |
| 113 | |
| 114 static void | |
| 2286 | 115 menubar_visible_p_changed (Lisp_Object UNUSED (specifier), |
| 116 struct window *UNUSED (w), | |
| 117 Lisp_Object UNUSED (oldval)) | |
| 428 | 118 { |
| 119 MARK_MENUBAR_CHANGED; | |
| 120 } | |
| 121 | |
| 122 static void | |
| 2286 | 123 menubar_visible_p_changed_in_frame (Lisp_Object UNUSED (specifier), |
| 124 struct frame *f, | |
| 125 Lisp_Object UNUSED (oldval)) | |
| 428 | 126 { |
| 127 update_frame_menubars (f); | |
| 128 } | |
| 129 | |
| 130 Lisp_Object | |
| 442 | 131 current_frame_menubar (const struct frame* f) |
| 428 | 132 { |
| 133 struct window *w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)); | |
| 134 return symbol_value_in_buffer (Qcurrent_menubar, w->buffer); | |
| 135 } | |
| 136 | |
| 137 Lisp_Object | |
| 138 menu_parse_submenu_keywords (Lisp_Object desc, Lisp_Object gui_item) | |
| 139 { | |
| 442 | 140 Lisp_Gui_Item *pgui_item = XGUI_ITEM (gui_item); |
| 428 | 141 |
| 142 /* Menu descriptor should be a list */ | |
| 143 CHECK_CONS (desc); | |
| 144 | |
| 145 /* First element may be menu name, although can be omitted. | |
| 146 Let's think that if stuff begins with anything than a keyword | |
| 147 or a list (submenu), this is a menu name, expected to be a string */ | |
| 148 if (!KEYWORDP (XCAR (desc)) && !CONSP (XCAR (desc))) | |
| 149 { | |
| 150 CHECK_STRING (XCAR (desc)); | |
| 151 pgui_item->name = XCAR (desc); | |
| 152 desc = XCDR (desc); | |
| 153 if (!NILP (desc)) | |
| 154 CHECK_CONS (desc); | |
| 155 } | |
| 156 | |
| 157 /* Walk along all key-value pairs */ | |
| 158 while (!NILP(desc) && KEYWORDP (XCAR (desc))) | |
| 159 { | |
| 160 Lisp_Object key, val; | |
| 161 key = XCAR (desc); | |
| 162 desc = XCDR (desc); | |
| 163 CHECK_CONS (desc); | |
| 164 val = XCAR (desc); | |
| 165 desc = XCDR (desc); | |
| 166 if (!NILP (desc)) | |
| 167 CHECK_CONS (desc); | |
| 168 gui_item_add_keyval_pair (gui_item, key, val, ERROR_ME); | |
| 169 } | |
| 170 | |
| 171 /* Return the rest - supposed to be a list of items */ | |
| 172 return desc; | |
| 173 } | |
| 174 | |
| 175 DEFUN ("menu-find-real-submenu", Fmenu_find_real_submenu, 2, 2, 0, /* | |
| 176 Find a submenu descriptor within DESC by following PATH. | |
| 177 This function finds a submenu descriptor, either from the description | |
| 178 DESC or generated by a filter within DESC. The function regards :config | |
| 179 and :included keywords in the DESC, and expands submenus along the | |
| 180 PATH using :filter functions. Return value is a descriptor for the | |
| 181 submenu, NOT expanded and NOT checked against :config and :included. | |
| 182 Also, individual menu items are not looked for, only submenus. | |
| 183 | |
| 184 See also 'find-menu-item'. | |
| 185 */ | |
| 186 (desc, path)) | |
| 187 { | |
| 442 | 188 struct gcpro gcpro1, gcpro2; |
| 428 | 189 Lisp_Object gui_item = allocate_gui_item (); |
| 440 | 190 Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item); |
| 428 | 191 |
| 442 | 192 GCPRO2 (gui_item, desc); |
| 428 | 193 |
| 2367 | 194 { |
| 195 EXTERNAL_LIST_LOOP_2 (elt, path) | |
| 196 { | |
| 197 /* Verify that DESC describes a menu, not single item */ | |
| 198 if (!CONSP (desc)) | |
| 199 RETURN_UNGCPRO (Qnil); | |
| 200 | |
| 201 /* Parse this menu */ | |
| 202 desc = menu_parse_submenu_keywords (desc, gui_item); | |
| 203 | |
| 204 /* Check that this (sub)menu is active */ | |
| 205 if (!gui_item_active_p (gui_item)) | |
| 206 RETURN_UNGCPRO (Qnil); | |
| 428 | 207 |
| 2367 | 208 /* Apply :filter */ |
| 209 if (!NILP (pgui_item->filter)) | |
| 210 desc = call1 (pgui_item->filter, desc); | |
| 428 | 211 |
| 2367 | 212 /* Find the next menu on the path inside this one */ |
| 213 { | |
| 214 EXTERNAL_LIST_LOOP_2 (submenu, desc) | |
| 215 { | |
| 216 if (CONSP (submenu) | |
| 217 && STRINGP (XCAR (submenu)) | |
| 218 && !NILP (Fstring_equal (XCAR (submenu), elt))) | |
| 219 { | |
| 220 desc = submenu; | |
| 221 goto descend; | |
| 222 } | |
| 223 } | |
| 224 } | |
| 225 /* Submenu not found */ | |
| 428 | 226 RETURN_UNGCPRO (Qnil); |
| 227 | |
| 2367 | 228 descend: |
| 229 /* Prepare for the next iteration */ | |
| 230 gui_item_init (gui_item); | |
| 231 } | |
| 232 } | |
| 428 | 233 |
| 234 /* We have successfully descended down the end of the path */ | |
| 235 UNGCPRO; | |
| 236 return desc; | |
| 237 } | |
| 238 | |
| 239 DEFUN ("popup-menu", Fpopup_menu, 1, 2, 0, /* | |
| 444 | 240 Pop up the menu described by MENU-DESCRIPTION. |
| 428 | 241 A menu description is a list of menu items, strings, and submenus. |
| 242 | |
| 243 The first element of a menu must be a string, which is the name of the menu. | |
| 244 This is the string that will be displayed in the parent menu, if any. For | |
| 245 toplevel menus, it is ignored. This string is not displayed in the menu | |
| 246 itself. | |
| 247 | |
| 248 If an element of a menu is a string, then that string will be presented in | |
| 249 the menu as unselectable text. | |
| 250 | |
| 251 If an element of a menu is a string consisting solely of hyphens, then that | |
| 252 item will be presented as a solid horizontal line. | |
| 253 | |
| 254 If an element of a menu is a list, it is treated as a submenu. The name of | |
| 255 that submenu (the first element in the list) will be used as the name of the | |
| 256 item representing this menu on the parent. | |
| 257 | |
| 258 Otherwise, the element must be a vector, which describes a menu item. | |
| 259 A menu item can have any of the following forms: | |
| 260 | |
| 261 [ "name" callback <active-p> ] | |
| 262 [ "name" callback <active-p> <suffix> ] | |
| 263 [ "name" callback :<keyword> <value> :<keyword> <value> ... ] | |
| 264 | |
| 265 The name is the string to display on the menu; it is filtered through the | |
| 266 resource database, so it is possible for resources to override what string | |
| 267 is actually displayed. | |
| 268 | |
| 269 If the `callback' of a menu item is a symbol, then it must name a command. | |
| 270 It will be invoked with `call-interactively'. If it is a list, then it is | |
| 271 evaluated with `eval'. | |
| 272 | |
| 273 The possible keywords are this: | |
| 274 | |
| 275 :active <form> Same as <active-p> in the first two forms: the | |
| 276 expression is evaluated just before the menu is | |
| 277 displayed, and the menu will be selectable only if | |
| 278 the result is non-nil. | |
| 279 | |
| 280 :suffix <form> Same as <suffix> in the second form: the expression | |
| 281 is evaluated just before the menu is displayed and | |
| 282 resulting string is appended to the displayed name, | |
| 283 providing a convenient way of adding the name of a | |
| 284 command's ``argument'' to the menu, like | |
| 285 ``Kill Buffer NAME''. | |
| 286 | |
| 287 :keys "string" Normally, the keyboard equivalents of commands in | |
| 288 menus are displayed when the `callback' is a symbol. | |
| 289 This can be used to specify keys for more complex menu | |
| 290 items. It is passed through `substitute-command-keys' | |
| 291 first. | |
| 292 | |
| 293 :style <style> Specifies what kind of object this menu item is: | |
| 294 | |
| 295 nil A normal menu item. | |
| 296 toggle A toggle button. | |
| 297 radio A radio button. | |
| 298 | |
| 299 The only difference between toggle and radio buttons is | |
| 300 how they are displayed. But for consistency, a toggle | |
| 301 button should be used when there is one option whose | |
| 302 value can be turned on or off, and radio buttons should | |
| 303 be used when there is a set of mutually exclusive | |
| 304 options. When using a group of radio buttons, you | |
| 305 should arrange for no more than one to be marked as | |
| 306 selected at a time. | |
| 307 | |
| 308 :selected <form> Meaningful only when STYLE is `toggle' or `radio'. | |
| 309 This specifies whether the button will be in the | |
| 310 selected or unselected state. | |
| 311 | |
| 312 For example: | |
| 313 | |
| 314 [ "Save As..." write-file t ] | |
| 315 [ "Revert Buffer" revert-buffer (buffer-modified-p) ] | |
| 316 [ "Read Only" toggle-read-only :style toggle :selected buffer-read-only ] | |
| 317 | |
| 318 See menubar.el for many more examples. | |
| 319 */ | |
| 444 | 320 (menu_description, event)) |
| 428 | 321 { |
| 444 | 322 struct frame *f = decode_frame (Qnil); |
| 323 MAYBE_FRAMEMETH (f, popup_menu, (menu_description, event)); | |
| 428 | 324 return Qnil; |
| 325 } | |
| 326 | |
| 2545 | 327 DEFUN ("compare-menu-text", Fcompare_menu_text, 2, 2, 0, /* |
| 328 Compare the text of two menu items, ignoring accelerator specs and case. | |
| 329 Also treat %% as a single %. Return < 0 if STRING1 is less than STRING2, | |
| 330 0 if equal, > 0 if STRING1 is greater than STRING2. | |
| 331 */ | |
| 332 (string1, string2)) | |
| 333 { | |
| 334 Ibyte *p; | |
| 335 Ibyte *q; | |
| 336 | |
| 337 CHECK_STRING (string1); | |
| 338 CHECK_STRING (string2); | |
| 339 | |
| 340 p = XSTRING_DATA (string1); | |
| 341 q = XSTRING_DATA (string2); | |
| 342 | |
| 343 for (;;) | |
| 344 { | |
| 345 Ichar val; | |
| 346 if (*p == '%' && *(p + 1) == '%') | |
| 347 p++; | |
| 348 else if (*p == '%' && *(p + 1) == '_') | |
| 349 p += 2; | |
| 350 if (*q == '%' && *(q + 1) == '%') | |
| 351 q++; | |
| 352 else if (*q == '%' && *(q + 1) == '_') | |
| 353 q += 2; | |
| 354 if (!*p || !*q) | |
|
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5402
diff
changeset
|
355 return make_fixnum (*p - *q); |
| 2545 | 356 val = DOWNCASE (0, itext_ichar (p)) - DOWNCASE (0, itext_ichar (q)); |
| 357 if (val) | |
|
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5402
diff
changeset
|
358 return make_fixnum (val); |
| 2545 | 359 INC_IBYTEPTR (p); |
| 360 INC_IBYTEPTR (q); | |
| 361 } | |
| 362 } | |
| 363 | |
| 364 DEFUN ("normalize-menu-text", Fnormalize_menu_text, 1, 1, 0, /* | |
| 428 | 365 Convert a menu item name string into normal form, and return the new string. |
| 366 Menu item names should be converted to normal form before being compared. | |
| 442 | 367 This removes %_'s (accelerator indications) and converts %% to %. |
| 2545 | 368 The returned string may be the same string as the original. |
| 428 | 369 */ |
| 2545 | 370 (name)) |
| 428 | 371 { |
| 372 Charcount end; | |
| 373 int i; | |
| 867 | 374 Ibyte *name_data; |
| 375 Ibyte *string_result; | |
| 376 Ibyte *string_result_ptr; | |
| 377 Ichar elt; | |
| 428 | 378 int expecting_underscore = 0; |
| 379 | |
| 380 CHECK_STRING (name); | |
| 381 | |
| 826 | 382 end = string_char_length (name); |
| 793 | 383 name_data = XSTRING_DATA (name); |
| 428 | 384 |
| 2367 | 385 string_result = alloca_ibytes (end * MAX_ICHAR_LEN); |
| 428 | 386 string_result_ptr = string_result; |
| 387 for (i = 0; i < end; i++) | |
| 388 { | |
| 867 | 389 elt = itext_ichar (name_data); |
| 428 | 390 if (expecting_underscore) |
| 391 { | |
| 392 expecting_underscore = 0; | |
| 393 switch (elt) | |
| 394 { | |
| 395 case '%': | |
| 396 /* Allow `%%' to mean `%'. */ | |
| 867 | 397 string_result_ptr += set_itext_ichar (string_result_ptr, '%'); |
| 428 | 398 break; |
| 399 case '_': | |
| 400 break; | |
| 401 default: | |
| 867 | 402 string_result_ptr += set_itext_ichar (string_result_ptr, '%'); |
| 403 string_result_ptr += set_itext_ichar (string_result_ptr, elt); | |
| 428 | 404 } |
| 405 } | |
| 406 else if (elt == '%') | |
| 407 expecting_underscore = 1; | |
| 408 else | |
| 867 | 409 string_result_ptr += set_itext_ichar (string_result_ptr, elt); |
| 410 INC_IBYTEPTR (name_data); | |
| 428 | 411 } |
| 412 | |
| 442 | 413 if (string_result_ptr - string_result == XSTRING_LENGTH (name) |
| 414 && !memcmp (string_result, XSTRING_DATA (name), XSTRING_LENGTH (name))) | |
| 415 return name; | |
| 416 | |
| 428 | 417 return make_string (string_result, string_result_ptr - string_result); |
| 418 } | |
| 419 | |
| 420 void | |
| 421 syms_of_menubar (void) | |
| 422 { | |
| 563 | 423 DEFSYMBOL (Qcurrent_menubar); |
| 442 | 424 |
| 563 | 425 DEFSYMBOL (Qmenu_force); |
| 426 DEFSYMBOL (Qmenu_fallback); | |
| 442 | 427 |
| 563 | 428 DEFSYMBOL (Qmenu_quit); |
| 429 DEFSYMBOL (Qmenu_up); | |
| 430 DEFSYMBOL (Qmenu_down); | |
| 431 DEFSYMBOL (Qmenu_left); | |
| 432 DEFSYMBOL (Qmenu_right); | |
| 433 DEFSYMBOL (Qmenu_select); | |
| 434 DEFSYMBOL (Qmenu_escape); | |
| 442 | 435 |
| 428 | 436 DEFSUBR (Fpopup_menu); |
| 2545 | 437 DEFSUBR (Fcompare_menu_text); |
| 438 DEFSUBR (Fnormalize_menu_text); | |
| 428 | 439 DEFSUBR (Fmenu_find_real_submenu); |
| 440 } | |
| 441 | |
| 442 void | |
| 443 vars_of_menubar (void) | |
| 444 { | |
| 440 | 445 /* put in Vblank_menubar a menubar value which has no visible |
| 446 * items. This is a bit tricky due to various quirks. We | |
| 447 * could use '(["" nil nil]), but this is apparently equivalent | |
| 448 * to '(nil), and a new frame created with this menubar will | |
| 449 * get a vertically-squished menubar. If we use " " as the | |
| 450 * button title instead of "", we get an etched button border. | |
| 451 * So we use | |
| 452 * '(("No active menubar" ["" nil nil])) | |
| 453 * which creates a menu whose title is "No active menubar", | |
| 454 * and this works fine. | |
| 455 */ | |
| 428 | 456 |
|
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
3025
diff
changeset
|
457 Vblank_menubar = list1 (list2 (build_defer_string ("No active menubar"), |
|
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
3025
diff
changeset
|
458 vector3 (build_ascstring (""), Qnil, Qnil))); |
| 440 | 459 staticpro (&Vblank_menubar); |
| 428 | 460 |
| 461 DEFVAR_BOOL ("popup-menu-titles", &popup_menu_titles /* | |
| 462 If true, popup menus will have title bars at the top. | |
| 463 */ ); | |
| 464 popup_menu_titles = 1; | |
| 465 | |
| 466 /* #### Replace current menubar with a specifier. */ | |
| 467 | |
| 468 /* All C code must access the menubar via Qcurrent_menubar | |
| 469 because it can be buffer-local. Note that Vcurrent_menubar | |
| 470 doesn't need to exist at all, except for the magic function. */ | |
| 471 | |
| 472 DEFVAR_LISP_MAGIC ("current-menubar", &Vcurrent_menubar /* | |
| 473 The current menubar. This may be buffer-local. | |
| 474 | |
| 475 When the menubar is changed, the function `set-menubar-dirty-flag' has to | |
| 476 be called for the menubar to be updated on the frame. See `set-menubar' | |
| 477 and `set-buffer-menubar'. | |
| 478 | |
| 479 A menubar is a list of menus and menu-items. | |
| 480 A menu is a list of menu items, keyword-value pairs, strings, and submenus. | |
| 481 | |
| 482 The first element of a menu must be a string, which is the name of the menu. | |
| 483 This is the string that will be displayed in the parent menu, if any. For | |
| 484 toplevel menus, it is ignored. This string is not displayed in the menu | |
| 485 itself. | |
| 486 | |
| 442 | 487 Menu accelerators can be indicated in the string by putting the |
| 488 sequence "%_" before the character corresponding to the key that will | |
| 489 invoke the menu or menu item. Uppercase and lowercase accelerators | |
| 490 are equivalent. The sequence "%%" is also special, and is translated | |
| 491 into a single %. | |
| 492 | |
| 493 If no menu accelerator is present in the string, XEmacs will act as if | |
| 494 the first character has been tagged as an accelerator. | |
| 495 | |
| 496 Immediately following the name string of the menu, various optional | |
| 497 keyword-value pairs are permitted: currently, :filter, :active, :included, | |
|
5715
68f8d295be49
Support :visible in menu specifications.
Jerry James <james@xemacs.org>
parents:
5581
diff
changeset
|
498 :visible, and :config. (See below.) |
| 428 | 499 |
| 500 If an element of a menu (or menubar) is a string, then that string will be | |
| 501 presented as unselectable text. | |
| 502 | |
| 503 If an element of a menu is a string consisting solely of hyphens, then that | |
| 504 item will be presented as a solid horizontal line. | |
| 505 | |
| 442 | 506 If an element of a menu is a string beginning with "--:", it will be |
| 507 presented as a line whose appearance is controlled by the rest of the | |
| 508 text in the string. The allowed line specs are system-dependent, and | |
| 509 currently work only under X Windows (with Lucid and Motif menubars); | |
| 510 otherwise, a solid horizontal line is presented, as if the string were | |
| 511 all hyphens. | |
| 512 | |
| 513 The possibilities are: | |
| 514 | |
| 515 "--:singleLine" | |
| 516 "--:doubleLine" | |
| 517 "--:singleDashedLine" | |
| 518 "--:doubleDashedLine" | |
| 519 "--:noLine" | |
| 520 "--:shadowEtchedIn" | |
| 521 "--:shadowEtchedOut" | |
| 522 "--:shadowEtchedInDash" | |
| 523 "--:shadowEtchedOutDash" | |
| 524 "--:shadowDoubleEtchedIn" (Lucid menubars only) | |
| 525 "--:shadowDoubleEtchedOut" (Lucid menubars only) | |
| 526 "--:shadowDoubleEtchedInDash" (Lucid menubars only) | |
| 527 "--:shadowDoubleEtchedOutDash" (Lucid menubars only) | |
| 528 | |
| 428 | 529 If an element of a menu is a list, it is treated as a submenu. The name of |
| 530 that submenu (the first element in the list) will be used as the name of the | |
| 531 item representing this menu on the parent. | |
| 532 | |
| 533 If an element of a menubar is `nil', then it is used to represent the | |
| 534 division between the set of menubar-items which are flushleft and those | |
| 535 which are flushright. | |
| 536 | |
| 537 Otherwise, the element must be a vector, which describes a menu item. | |
| 442 | 538 A menu item is of the following form: |
| 539 | |
| 540 [ "name" callback :<keyword> <value> :<keyword> <value> ... ] | |
| 541 | |
| 542 The following forms are also accepted for compatibility, but deprecated: | |
| 428 | 543 |
| 544 [ "name" callback <active-p> ] | |
| 545 [ "name" callback <active-p> <suffix> ] | |
| 546 | |
| 547 The name is the string to display on the menu; it is filtered through the | |
| 548 resource database, so it is possible for resources to override what string | |
| 442 | 549 is actually displayed. Menu accelerator indicators (the sequence `%_') are |
| 550 also processed; see above. If the name is not a string, it will be | |
| 551 evaluated with `eval', and the result should be a string. | |
| 428 | 552 |
| 553 If the `callback' of a menu item is a symbol, then it must name a command. | |
| 554 It will be invoked with `call-interactively'. If it is a list, then it is | |
| 555 evaluated with `eval'. | |
| 556 | |
| 442 | 557 In the deprecated forms, <active-p> is equivalent to using the :active |
| 558 keyword, and <suffix> is equivalent to using the :suffix keyword. | |
| 428 | 559 |
| 442 | 560 The possible keywords are: |
| 561 | |
| 562 :active <form> The expression is evaluated just before the menu is | |
| 428 | 563 displayed, and the menu will be selectable only if |
| 564 the result is non-nil. | |
| 565 | |
| 442 | 566 :suffix <form> The expression is evaluated just before the menu is |
| 567 displayed and the resulting string is appended to | |
| 568 the displayed name, providing a convenient way of | |
| 569 adding the name of a command's ``argument'' to the | |
| 570 menu, like ``Kill Buffer NAME''. | |
| 428 | 571 |
| 572 :keys "string" Normally, the keyboard equivalents of commands in | |
| 573 menus are displayed when the `callback' is a symbol. | |
| 574 This can be used to specify keys for more complex menu | |
| 575 items. It is passed through `substitute-command-keys' | |
| 576 first. | |
| 577 | |
| 578 :style <style> Specifies what kind of object this menu item is: | |
| 579 | |
| 580 nil A normal menu item. | |
| 581 toggle A toggle button. | |
| 582 radio A radio button. | |
| 583 button A menubar button. | |
| 584 | |
| 585 The only difference between toggle and radio buttons is | |
| 586 how they are displayed. But for consistency, a toggle | |
| 587 button should be used when there is one option whose | |
| 588 value can be turned on or off, and radio buttons should | |
| 589 be used when there is a set of mutually exclusive | |
| 590 options. When using a group of radio buttons, you | |
| 591 should arrange for no more than one to be marked as | |
| 592 selected at a time. | |
| 593 | |
| 594 :selected <form> Meaningful only when STYLE is `toggle', `radio' or | |
| 595 `button'. This specifies whether the button will be in | |
| 596 the selected or unselected state. | |
| 597 | |
| 598 :included <form> This can be used to control the visibility of a menu or | |
| 599 menu item. The form is evaluated and the menu or menu | |
|
5715
68f8d295be49
Support :visible in menu specifications.
Jerry James <james@xemacs.org>
parents:
5581
diff
changeset
|
600 item is only displayed if the result is non-nil. The |
|
68f8d295be49
Support :visible in menu specifications.
Jerry James <james@xemacs.org>
parents:
5581
diff
changeset
|
601 keyword :visible is an alias for :included. |
| 428 | 602 |
| 603 :config <symbol> This is an efficient shorthand for | |
| 604 :included (memq symbol menubar-configuration) | |
| 605 See the variable `menubar-configuration'. | |
| 606 | |
| 442 | 607 :filter <function> A menu filter can only be used at the beginning of a |
| 608 submenu description (i.e. not in a menu item itself). | |
| 609 (Remember that most of the keywords can take evaluated | |
| 610 expressions as well as constants.) The filter is used to | |
| 611 incrementally create a submenu only when it is selected | |
| 612 by the user and not every time the menubar is activated. | |
| 613 The filter function is passed the list of menu items in | |
| 614 the submenu and must return the modified list to be | |
| 615 actually used. The filter MUST NOT destructively modify | |
| 616 the list of menu items passed to it. It is called only | |
| 617 when the menu is about to be displayed, so other menus | |
| 618 may already be displayed. Vile and terrible things will | |
| 619 happen if a menu filter function changes the current | |
| 620 buffer, window, or frame. It also should not raise, | |
| 621 lower, or iconify any frames. Basically, the filter | |
| 622 function should have no side-effects. | |
| 428 | 623 |
| 624 :key-sequence keys Used in FSF Emacs as an hint to an equivalent keybinding. | |
| 442 | 625 Ignored by XEmacs for easymenu.el compatibility. |
| 626 (XEmacs computes this information automatically.) | |
| 428 | 627 |
| 628 For example: | |
| 629 | |
| 442 | 630 ("%_File" |
| 428 | 631 :filter file-menu-filter ; file-menu-filter is a function that takes |
| 632 ; one argument (a list of menu items) and | |
| 633 ; returns a list of menu items | |
| 442 | 634 [ "Save %_As..." write-file t ] |
| 635 [ "%_Revert Buffer" revert-buffer (buffer-modified-p) ] | |
| 636 [ "R%_ead Only" toggle-read-only :style toggle | |
| 428 | 637 :selected buffer-read-only ] |
| 638 ) | |
| 639 | |
| 442 | 640 See menubar-items.el for many more examples. |
| 428 | 641 |
| 642 After the menubar is clicked upon, but before any menus are popped up, | |
| 643 the functions on the `activate-menubar-hook' are invoked to make top-level | |
| 644 changes to the menus and menubar. Note, however, that the use of menu | |
| 645 filters (using the :filter keyword) is usually a more efficient way to | |
| 442 | 646 dynamically alter or sensitize menus. */, menubar_variable_changed); |
| 428 | 647 |
| 648 Vcurrent_menubar = Qnil; | |
| 649 | |
| 650 DEFVAR_LISP ("activate-menubar-hook", &Vactivate_menubar_hook /* | |
| 651 Function or functions called before a menubar menu is pulled down. | |
| 652 These functions are called with no arguments, and should interrogate and | |
| 653 modify the value of `current-menubar' as desired. | |
| 654 | |
| 655 The functions on this hook are invoked after the mouse goes down, but before | |
| 656 the menu is mapped, and may be used to activate, deactivate, add, or delete | |
| 657 items from the menus. However, it is probably the case that using a :filter | |
| 658 keyword in a submenu would be a more efficient way of updating menus. See | |
| 659 the documentation of `current-menubar'. | |
| 660 | |
| 661 These functions may return the symbol `t' to assert that they have made | |
| 662 no changes to the menubar. If any other value is returned, the menubar is | |
| 663 recomputed. If `t' is returned but the menubar has been changed, then the | |
| 664 changes may not show up right away. Returning `nil' when the menubar has | |
| 665 not changed is not so bad; more computation will be done, but redisplay of | |
| 666 the menubar will still be performed optimally. | |
| 667 */ ); | |
| 668 Vactivate_menubar_hook = Qnil; | |
| 563 | 669 DEFSYMBOL (Qactivate_menubar_hook); |
| 428 | 670 |
| 671 DEFVAR_BOOL ("menubar-show-keybindings", &menubar_show_keybindings /* | |
| 672 If true, the menubar will display keyboard equivalents. | |
| 673 If false, only the command names will be displayed. | |
| 674 */ ); | |
| 675 menubar_show_keybindings = 1; | |
| 676 | |
| 677 DEFVAR_LISP_MAGIC ("menubar-configuration", &Vmenubar_configuration /* | |
| 678 A list of symbols, against which the value of the :config tag for each | |
| 679 menubar item will be compared. If a menubar item has a :config tag, then | |
| 680 it is omitted from the menubar if that tag is not a member of the | |
| 681 `menubar-configuration' list. | |
| 682 */ , menubar_variable_changed); | |
| 683 Vmenubar_configuration = Qnil; | |
| 684 | |
| 685 DEFVAR_LISP ("menubar-pointer-glyph", &Vmenubar_pointer_glyph /* | |
| 686 *The shape of the mouse-pointer when over the menubar. | |
| 687 This is a glyph; use `set-glyph-image' to change it. | |
| 688 If unspecified in a particular domain, the window-system-provided | |
| 689 default pointer is used. | |
| 690 */ ); | |
| 691 | |
| 442 | 692 DEFVAR_LISP ("menu-accelerator-prefix", &Vmenu_accelerator_prefix /* |
| 693 Prefix key(s) that must be typed before menu accelerators will be activated. | |
| 694 Set this to a value acceptable by define-key. | |
| 695 | |
| 696 NOTE: This currently only has any effect under X Windows. | |
| 697 */ ); | |
| 698 Vmenu_accelerator_prefix = Qnil; | |
| 699 | |
| 700 DEFVAR_LISP ("menu-accelerator-modifiers", &Vmenu_accelerator_modifiers /* | |
| 701 Modifier keys which must be pressed to get to the top level menu accelerators. | |
| 702 This is a list of modifier key symbols. All modifier keys must be held down | |
| 703 while a valid menu accelerator key is pressed in order for the top level | |
| 704 menu to become active. | |
| 705 | |
| 706 NOTE: This currently only has any effect under X Windows. | |
| 707 | |
| 708 See also menu-accelerator-enabled and menu-accelerator-prefix. | |
| 709 */ ); | |
| 710 Vmenu_accelerator_modifiers = list1 (Qmeta); | |
| 711 | |
| 712 DEFVAR_LISP ("menu-accelerator-enabled", &Vmenu_accelerator_enabled /* | |
| 713 Whether menu accelerator keys can cause the menubar to become active. | |
| 3025 | 714 If `menu-force' or `menu-fallback', then menu accelerator keys can |
| 442 | 715 be used to activate the top level menu. Once the menubar becomes active, the |
| 716 accelerator keys can be used regardless of the value of this variable. | |
| 717 | |
| 718 menu-force is used to indicate that the menu accelerator key takes | |
| 719 precedence over bindings in the current keymap(s). menu-fallback means | |
| 720 that bindings in the current keymap take precedence over menu accelerator keys. | |
| 721 Thus a top level menu with an accelerator of "T" would be activated on a | |
| 722 keypress of Meta-t if menu-accelerator-enabled is menu-force. | |
| 723 However, if menu-accelerator-enabled is menu-fallback, then | |
| 724 Meta-t will not activate the menubar and will instead run the function | |
| 725 transpose-words, to which it is normally bound. | |
| 726 | |
| 727 See also menu-accelerator-modifiers and menu-accelerator-prefix. | |
| 728 */ ); | |
| 729 Vmenu_accelerator_enabled = Qnil; | |
| 730 | |
| 731 DEFVAR_LISP ("menu-accelerator-map", &Vmenu_accelerator_map /* | |
| 732 Keymap for use when the menubar is active. | |
| 733 The actions menu-quit, menu-up, menu-down, menu-left, menu-right, | |
| 734 menu-select and menu-escape can be mapped to keys in this map. | |
| 735 NOTE: This currently only has any effect under X Windows. | |
| 736 | |
| 737 menu-quit Immediately deactivate the menubar and any open submenus without | |
| 738 selecting an item. | |
| 739 menu-up Move the menu cursor up one row in the current menu. If the | |
| 740 move extends past the top of the menu, wrap around to the bottom. | |
| 741 menu-down Move the menu cursor down one row in the current menu. If the | |
| 742 move extends past the bottom of the menu, wrap around to the top. | |
| 743 If executed while the cursor is in the top level menu, move down | |
| 744 into the selected menu. | |
| 745 menu-left Move the cursor from a submenu into the parent menu. If executed | |
| 746 while the cursor is in the top level menu, move the cursor to the | |
| 747 left. If the move extends past the left edge of the menu, wrap | |
| 748 around to the right edge. | |
| 749 menu-right Move the cursor into a submenu. If the cursor is located in the | |
| 750 top level menu or is not currently on a submenu heading, then move | |
| 751 the cursor to the next top level menu entry. If the move extends | |
| 752 past the right edge of the menu, wrap around to the left edge. | |
| 753 menu-select Activate the item under the cursor. If the cursor is located on | |
| 754 a submenu heading, then move the cursor into the submenu. | |
| 755 menu-escape Pop up to the next level of menus. Moves from a submenu into its | |
| 756 parent menu. From the top level menu, this deactivates the | |
| 757 menubar. | |
| 758 | |
| 759 This keymap can also contain normal key-command bindings, in which case the | |
| 760 menubar is deactivated and the corresponding command is executed. | |
| 761 | |
| 762 The action bindings used by the menu accelerator code are designed to mimic | |
| 763 the actions of menu traversal keys in a commonly used PC operating system. | |
| 764 */ ); | |
| 765 | |
| 428 | 766 Fprovide (intern ("menubar")); |
| 464 | 767 Fprovide (intern ("menu-accelerator-support")); |
| 428 | 768 } |
| 769 | |
| 770 void | |
| 771 specifier_vars_of_menubar (void) | |
| 772 { | |
| 773 DEFVAR_SPECIFIER ("menubar-visible-p", &Vmenubar_visible_p /* | |
| 774 *Whether the menubar is visible. | |
| 775 This is a specifier; use `set-specifier' to change it. | |
| 776 */ ); | |
| 777 Vmenubar_visible_p = Fmake_specifier (Qboolean); | |
| 778 | |
| 779 set_specifier_fallback (Vmenubar_visible_p, list1 (Fcons (Qnil, Qt))); | |
| 780 set_specifier_caching (Vmenubar_visible_p, | |
| 438 | 781 offsetof (struct window, menubar_visible_p), |
| 428 | 782 menubar_visible_p_changed, |
| 438 | 783 offsetof (struct frame, menubar_visible_p), |
| 444 | 784 menubar_visible_p_changed_in_frame, 0); |
| 428 | 785 } |
| 786 | |
| 787 void | |
| 788 complex_vars_of_menubar (void) | |
| 789 { | |
| 790 Vmenubar_pointer_glyph = Fmake_glyph_internal (Qpointer); | |
| 442 | 791 |
| 792 Vmenu_accelerator_map = Fmake_keymap (Qnil); | |
| 428 | 793 } |
