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