Mercurial > hg > xemacs-beta
annotate src/menubar.c @ 4975:c5cb3cb79110
Automatic merge
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Fri, 05 Feb 2010 04:27:45 -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 } |