comparison src/menubar.c @ 428:3ecd8885ac67 r21-2-22

Import from CVS: tag r21-2-22
author cvs
date Mon, 13 Aug 2007 11:28:15 +0200
parents
children 84b14dcb0985
comparison
equal deleted inserted replaced
427:0a0253eac470 428:3ecd8885ac67
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.
4
5 This file is part of XEmacs.
6
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 /* Synched up with: Not in FSF. */
23
24 /* #### There ain't much here because menubars have not been
25 properly abstracted yet. */
26
27 #include <config.h>
28 #include "lisp.h"
29
30 #include "buffer.h"
31 #include "device.h"
32 #include "frame.h"
33 #include "gui.h"
34 #include "menubar.h"
35 #include "redisplay.h"
36 #include "window.h"
37
38 int menubar_show_keybindings;
39 Lisp_Object Vmenubar_configuration;
40
41 Lisp_Object Qcurrent_menubar;
42
43 Lisp_Object Qactivate_menubar_hook, Vactivate_menubar_hook;
44
45 Lisp_Object Vmenubar_visible_p;
46
47 static Lisp_Object Vcurrent_menubar; /* DO NOT ever reference this.
48 Always go through Qcurrent_menubar.
49 See below. */
50
51 Lisp_Object Vblank_menubar;
52
53 int popup_menu_titles;
54
55 Lisp_Object Vmenubar_pointer_glyph;
56
57 static int
58 menubar_variable_changed (Lisp_Object sym, Lisp_Object *val,
59 Lisp_Object in_object, int flags)
60 {
61 MARK_MENUBAR_CHANGED;
62 return 0;
63 }
64
65 void
66 update_frame_menubars (struct frame *f)
67 {
68 if (f->menubar_changed || f->windows_changed)
69 MAYBE_FRAMEMETH (f, update_frame_menubars, (f));
70
71 f->menubar_changed = 0;
72 }
73
74 void
75 free_frame_menubars (struct frame *f)
76 {
77 /* If we had directly allocated any memory for the menubars instead
78 of using all Lisp_Objects this is where we would now free it. */
79
80 MAYBE_FRAMEMETH (f, free_frame_menubars, (f));
81 }
82
83 static void
84 menubar_visible_p_changed (Lisp_Object specifier, struct window *w,
85 Lisp_Object oldval)
86 {
87 MARK_MENUBAR_CHANGED;
88 }
89
90 static void
91 menubar_visible_p_changed_in_frame (Lisp_Object specifier, struct frame *f,
92 Lisp_Object oldval)
93 {
94 update_frame_menubars (f);
95 }
96
97 Lisp_Object
98 current_frame_menubar (CONST struct frame* f)
99 {
100 struct window *w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f));
101 return symbol_value_in_buffer (Qcurrent_menubar, w->buffer);
102 }
103
104 Lisp_Object
105 menu_parse_submenu_keywords (Lisp_Object desc, Lisp_Object gui_item)
106 {
107 struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
108
109 /* Menu descriptor should be a list */
110 CHECK_CONS (desc);
111
112 /* First element may be menu name, although can be omitted.
113 Let's think that if stuff begins with anything than a keyword
114 or a list (submenu), this is a menu name, expected to be a string */
115 if (!KEYWORDP (XCAR (desc)) && !CONSP (XCAR (desc)))
116 {
117 CHECK_STRING (XCAR (desc));
118 pgui_item->name = XCAR (desc);
119 desc = XCDR (desc);
120 if (!NILP (desc))
121 CHECK_CONS (desc);
122 }
123
124 /* Walk along all key-value pairs */
125 while (!NILP(desc) && KEYWORDP (XCAR (desc)))
126 {
127 Lisp_Object key, val;
128 key = XCAR (desc);
129 desc = XCDR (desc);
130 CHECK_CONS (desc);
131 val = XCAR (desc);
132 desc = XCDR (desc);
133 if (!NILP (desc))
134 CHECK_CONS (desc);
135 gui_item_add_keyval_pair (gui_item, key, val, ERROR_ME);
136 }
137
138 /* Return the rest - supposed to be a list of items */
139 return desc;
140 }
141
142 DEFUN ("menu-find-real-submenu", Fmenu_find_real_submenu, 2, 2, 0, /*
143 Find a submenu descriptor within DESC by following PATH.
144 This function finds a submenu descriptor, either from the description
145 DESC or generated by a filter within DESC. The function regards :config
146 and :included keywords in the DESC, and expands submenus along the
147 PATH using :filter functions. Return value is a descriptor for the
148 submenu, NOT expanded and NOT checked against :config and :included.
149 Also, individual menu items are not looked for, only submenus.
150
151 See also 'find-menu-item'.
152 */
153 (desc, path))
154 {
155 Lisp_Object path_entry, submenu_desc, submenu;
156 struct gcpro gcpro1;
157 Lisp_Object gui_item = allocate_gui_item ();
158 struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
159
160 GCPRO1 (gui_item);
161
162 EXTERNAL_LIST_LOOP (path_entry, path)
163 {
164 /* Verify that DESC describes a menu, not single item */
165 if (!CONSP (desc))
166 RETURN_UNGCPRO (Qnil);
167
168 /* Parse this menu */
169 desc = menu_parse_submenu_keywords (desc, gui_item);
170
171 /* Check that this (sub)menu is active */
172 if (!gui_item_active_p (gui_item))
173 RETURN_UNGCPRO (Qnil);
174
175 /* Apply :filter */
176 if (!NILP (pgui_item->filter))
177 desc = call1 (pgui_item->filter, desc);
178
179 /* Find the next menu on the path inside this one */
180 EXTERNAL_LIST_LOOP (submenu_desc, desc)
181 {
182 submenu = XCAR (submenu_desc);
183 if (CONSP (submenu)
184 && STRINGP (XCAR (submenu))
185 && !NILP (Fstring_equal (XCAR (submenu), XCAR (path_entry))))
186 {
187 desc = submenu;
188 goto descend;
189 }
190 }
191 /* Submenu not found */
192 RETURN_UNGCPRO (Qnil);
193
194 descend:
195 /* Prepare for the next iteration */
196 gui_item_init (gui_item);
197 }
198
199 /* We have successfully descended down the end of the path */
200 UNGCPRO;
201 return desc;
202 }
203
204 DEFUN ("popup-menu", Fpopup_menu, 1, 2, 0, /*
205 Pop up the given menu.
206 A menu description is a list of menu items, strings, and submenus.
207
208 The first element of a menu must be a string, which is the name of the menu.
209 This is the string that will be displayed in the parent menu, if any. For
210 toplevel menus, it is ignored. This string is not displayed in the menu
211 itself.
212
213 If an element of a menu is a string, then that string will be presented in
214 the menu as unselectable text.
215
216 If an element of a menu is a string consisting solely of hyphens, then that
217 item will be presented as a solid horizontal line.
218
219 If an element of a menu is a list, it is treated as a submenu. The name of
220 that submenu (the first element in the list) will be used as the name of the
221 item representing this menu on the parent.
222
223 Otherwise, the element must be a vector, which describes a menu item.
224 A menu item can have any of the following forms:
225
226 [ "name" callback <active-p> ]
227 [ "name" callback <active-p> <suffix> ]
228 [ "name" callback :<keyword> <value> :<keyword> <value> ... ]
229
230 The name is the string to display on the menu; it is filtered through the
231 resource database, so it is possible for resources to override what string
232 is actually displayed.
233
234 If the `callback' of a menu item is a symbol, then it must name a command.
235 It will be invoked with `call-interactively'. If it is a list, then it is
236 evaluated with `eval'.
237
238 The possible keywords are this:
239
240 :active <form> Same as <active-p> in the first two forms: the
241 expression is evaluated just before the menu is
242 displayed, and the menu will be selectable only if
243 the result is non-nil.
244
245 :suffix <form> Same as <suffix> in the second form: the expression
246 is evaluated just before the menu is displayed and
247 resulting string is appended to the displayed name,
248 providing a convenient way of adding the name of a
249 command's ``argument'' to the menu, like
250 ``Kill Buffer NAME''.
251
252 :keys "string" Normally, the keyboard equivalents of commands in
253 menus are displayed when the `callback' is a symbol.
254 This can be used to specify keys for more complex menu
255 items. It is passed through `substitute-command-keys'
256 first.
257
258 :style <style> Specifies what kind of object this menu item is:
259
260 nil A normal menu item.
261 toggle A toggle button.
262 radio A radio button.
263
264 The only difference between toggle and radio buttons is
265 how they are displayed. But for consistency, a toggle
266 button should be used when there is one option whose
267 value can be turned on or off, and radio buttons should
268 be used when there is a set of mutually exclusive
269 options. When using a group of radio buttons, you
270 should arrange for no more than one to be marked as
271 selected at a time.
272
273 :selected <form> Meaningful only when STYLE is `toggle' or `radio'.
274 This specifies whether the button will be in the
275 selected or unselected state.
276
277 For example:
278
279 [ "Save As..." write-file t ]
280 [ "Revert Buffer" revert-buffer (buffer-modified-p) ]
281 [ "Read Only" toggle-read-only :style toggle :selected buffer-read-only ]
282
283 See menubar.el for many more examples.
284 */
285 (menu_desc, event))
286 {
287 struct frame *f = decode_frame(Qnil);
288 MAYBE_FRAMEMETH (f, popup_menu, (menu_desc,event));
289 return Qnil;
290 }
291
292 DEFUN ("normalize-menu-item-name", Fnormalize_menu_item_name, 1, 2, 0, /*
293 Convert a menu item name string into normal form, and return the new string.
294 Menu item names should be converted to normal form before being compared.
295 */
296 (name, buffer))
297 {
298 struct buffer *buf = decode_buffer (buffer, 0);
299 struct Lisp_String *n;
300 Charcount end;
301 int i;
302 Bufbyte *name_data;
303 Bufbyte *string_result;
304 Bufbyte *string_result_ptr;
305 Emchar elt;
306 int expecting_underscore = 0;
307
308 CHECK_STRING (name);
309
310 n = XSTRING (name);
311 end = string_char_length (n);
312 name_data = string_data (n);
313
314 string_result = (Bufbyte *) alloca (end * MAX_EMCHAR_LEN);
315 string_result_ptr = string_result;
316 for (i = 0; i < end; i++)
317 {
318 elt = charptr_emchar (name_data);
319 elt = DOWNCASE (buf, elt);
320 if (expecting_underscore)
321 {
322 expecting_underscore = 0;
323 switch (elt)
324 {
325 case '%':
326 /* Allow `%%' to mean `%'. */
327 string_result_ptr += set_charptr_emchar (string_result_ptr, '%');
328 break;
329 case '_':
330 break;
331 default:
332 string_result_ptr += set_charptr_emchar (string_result_ptr, '%');
333 string_result_ptr += set_charptr_emchar (string_result_ptr, elt);
334 }
335 }
336 else if (elt == '%')
337 expecting_underscore = 1;
338 else
339 string_result_ptr += set_charptr_emchar (string_result_ptr, elt);
340 INC_CHARPTR (name_data);
341 }
342
343 return make_string (string_result, string_result_ptr - string_result);
344 }
345
346 void
347 syms_of_menubar (void)
348 {
349 defsymbol (&Qcurrent_menubar, "current-menubar");
350 DEFSUBR (Fpopup_menu);
351 DEFSUBR (Fnormalize_menu_item_name);
352 DEFSUBR (Fmenu_find_real_submenu);
353 }
354
355 void
356 vars_of_menubar (void)
357 {
358 {
359 /* put in Vblank_menubar a menubar value which has no visible
360 * items. This is a bit tricky due to various quirks. We
361 * could use '(["" nil nil]), but this is apparently equivalent
362 * to '(nil), and a new frame created with this menubar will
363 * get a vertically-squished menubar. If we use " " as the
364 * button title instead of "", we get an etched button border.
365 * So we use
366 * '(("No active menubar" ["" nil nil]))
367 * which creates a menu whose title is "No active menubar",
368 * and this works fine.
369 */
370
371 Lisp_Object menu_item[3];
372 static CONST char *blank_msg = "No active menubar";
373
374 menu_item[0] = build_string ("");
375 menu_item[1] = Qnil;
376 menu_item[2] = Qnil;
377 Vblank_menubar = Fcons (Fcons (build_string (blank_msg),
378 Fcons (Fvector (3, &menu_item[0]),
379 Qnil)),
380 Qnil);
381 staticpro (&Vblank_menubar);
382 }
383
384 DEFVAR_BOOL ("popup-menu-titles", &popup_menu_titles /*
385 If true, popup menus will have title bars at the top.
386 */ );
387 popup_menu_titles = 1;
388
389 /* #### Replace current menubar with a specifier. */
390
391 /* All C code must access the menubar via Qcurrent_menubar
392 because it can be buffer-local. Note that Vcurrent_menubar
393 doesn't need to exist at all, except for the magic function. */
394
395 DEFVAR_LISP_MAGIC ("current-menubar", &Vcurrent_menubar /*
396 The current menubar. This may be buffer-local.
397
398 When the menubar is changed, the function `set-menubar-dirty-flag' has to
399 be called for the menubar to be updated on the frame. See `set-menubar'
400 and `set-buffer-menubar'.
401
402 A menubar is a list of menus and menu-items.
403 A menu is a list of menu items, keyword-value pairs, strings, and submenus.
404
405 The first element of a menu must be a string, which is the name of the menu.
406 This is the string that will be displayed in the parent menu, if any. For
407 toplevel menus, it is ignored. This string is not displayed in the menu
408 itself.
409
410 Immediately following the name string of the menu, any of three
411 optional keyword-value pairs is permitted.
412
413 If an element of a menu (or menubar) is a string, then that string will be
414 presented as unselectable text.
415
416 If an element of a menu is a string consisting solely of hyphens, then that
417 item will be presented as a solid horizontal line.
418
419 If an element of a menu is a list, it is treated as a submenu. The name of
420 that submenu (the first element in the list) will be used as the name of the
421 item representing this menu on the parent.
422
423 If an element of a menubar is `nil', then it is used to represent the
424 division between the set of menubar-items which are flushleft and those
425 which are flushright.
426
427 Otherwise, the element must be a vector, which describes a menu item.
428 A menu item can have any of the following forms:
429
430 [ "name" callback <active-p> ]
431 [ "name" callback <active-p> <suffix> ]
432 [ "name" callback :<keyword> <value> :<keyword> <value> ... ]
433
434 The name is the string to display on the menu; it is filtered through the
435 resource database, so it is possible for resources to override what string
436 is actually displayed.
437
438 If the `callback' of a menu item is a symbol, then it must name a command.
439 It will be invoked with `call-interactively'. If it is a list, then it is
440 evaluated with `eval'.
441
442 The possible keywords are this:
443
444 :active <form> Same as <active-p> in the first two forms: the
445 expression is evaluated just before the menu is
446 displayed, and the menu will be selectable only if
447 the result is non-nil.
448
449 :suffix <form> Same as <suffix> in the second form: the expression
450 is evaluated just before the menu is displayed and
451 resulting string is appended to the displayed name,
452 providing a convenient way of adding the name of a
453 command's ``argument'' to the menu, like
454 ``Kill Buffer NAME''.
455
456 :keys "string" Normally, the keyboard equivalents of commands in
457 menus are displayed when the `callback' is a symbol.
458 This can be used to specify keys for more complex menu
459 items. It is passed through `substitute-command-keys'
460 first.
461
462 :style <style> Specifies what kind of object this menu item is:
463
464 nil A normal menu item.
465 toggle A toggle button.
466 radio A radio button.
467 button A menubar button.
468
469 The only difference between toggle and radio buttons is
470 how they are displayed. But for consistency, a toggle
471 button should be used when there is one option whose
472 value can be turned on or off, and radio buttons should
473 be used when there is a set of mutually exclusive
474 options. When using a group of radio buttons, you
475 should arrange for no more than one to be marked as
476 selected at a time.
477
478 :selected <form> Meaningful only when STYLE is `toggle', `radio' or
479 `button'. This specifies whether the button will be in
480 the selected or unselected state.
481
482 :included <form> This can be used to control the visibility of a menu or
483 menu item. The form is evaluated and the menu or menu
484 item is only displayed if the result is non-nil.
485
486 :config <symbol> This is an efficient shorthand for
487 :included (memq symbol menubar-configuration)
488 See the variable `menubar-configuration'.
489
490 :filter <function> A menu filter can only be used in a menu item list.
491 (i.e.: not in a menu item itself). It is used to
492 sensitize or incrementally create a submenu only when
493 it is selected by the user and not every time the
494 menubar is activated. The filter function is passed
495 the list of menu items in the submenu and must return a
496 list of menu items to be used for the menu. It is
497 called only when the menu is about to be displayed, so
498 other menus may already be displayed. Vile and
499 terrible things will happen if a menu filter function
500 changes the current buffer, window, or frame. It
501 also should not raise, lower, or iconify any frames.
502 Basically, the filter function should have no
503 side-effects.
504
505 :key-sequence keys Used in FSF Emacs as an hint to an equivalent keybinding.
506 Ignored by XEnacs for easymenu.el compatability.
507
508 :label <form> (unimplemented!) Like :suffix, but replaces label
509 completely.
510 (might be added in 21.2).
511
512 For example:
513
514 ("File"
515 :filter file-menu-filter ; file-menu-filter is a function that takes
516 ; one argument (a list of menu items) and
517 ; returns a list of menu items
518 [ "Save As..." write-file t ]
519 [ "Revert Buffer" revert-buffer (buffer-modified-p) ]
520 [ "Read Only" toggle-read-only :style toggle
521 :selected buffer-read-only ]
522 )
523
524 See x-menubar.el for many more examples.
525
526 After the menubar is clicked upon, but before any menus are popped up,
527 the functions on the `activate-menubar-hook' are invoked to make top-level
528 changes to the menus and menubar. Note, however, that the use of menu
529 filters (using the :filter keyword) is usually a more efficient way to
530 dynamically alter or sensitize menus.
531 */, menubar_variable_changed);
532
533 Vcurrent_menubar = Qnil;
534
535 DEFVAR_LISP ("activate-menubar-hook", &Vactivate_menubar_hook /*
536 Function or functions called before a menubar menu is pulled down.
537 These functions are called with no arguments, and should interrogate and
538 modify the value of `current-menubar' as desired.
539
540 The functions on this hook are invoked after the mouse goes down, but before
541 the menu is mapped, and may be used to activate, deactivate, add, or delete
542 items from the menus. However, it is probably the case that using a :filter
543 keyword in a submenu would be a more efficient way of updating menus. See
544 the documentation of `current-menubar'.
545
546 These functions may return the symbol `t' to assert that they have made
547 no changes to the menubar. If any other value is returned, the menubar is
548 recomputed. If `t' is returned but the menubar has been changed, then the
549 changes may not show up right away. Returning `nil' when the menubar has
550 not changed is not so bad; more computation will be done, but redisplay of
551 the menubar will still be performed optimally.
552 */ );
553 Vactivate_menubar_hook = Qnil;
554 defsymbol (&Qactivate_menubar_hook, "activate-menubar-hook");
555
556 DEFVAR_BOOL ("menubar-show-keybindings", &menubar_show_keybindings /*
557 If true, the menubar will display keyboard equivalents.
558 If false, only the command names will be displayed.
559 */ );
560 menubar_show_keybindings = 1;
561
562 DEFVAR_LISP_MAGIC ("menubar-configuration", &Vmenubar_configuration /*
563 A list of symbols, against which the value of the :config tag for each
564 menubar item will be compared. If a menubar item has a :config tag, then
565 it is omitted from the menubar if that tag is not a member of the
566 `menubar-configuration' list.
567 */ , menubar_variable_changed);
568 Vmenubar_configuration = Qnil;
569
570 DEFVAR_LISP ("menubar-pointer-glyph", &Vmenubar_pointer_glyph /*
571 *The shape of the mouse-pointer when over the menubar.
572 This is a glyph; use `set-glyph-image' to change it.
573 If unspecified in a particular domain, the window-system-provided
574 default pointer is used.
575 */ );
576
577 Fprovide (intern ("menubar"));
578 }
579
580 void
581 specifier_vars_of_menubar (void)
582 {
583 DEFVAR_SPECIFIER ("menubar-visible-p", &Vmenubar_visible_p /*
584 *Whether the menubar is visible.
585 This is a specifier; use `set-specifier' to change it.
586 */ );
587 Vmenubar_visible_p = Fmake_specifier (Qboolean);
588
589 set_specifier_fallback (Vmenubar_visible_p, list1 (Fcons (Qnil, Qt)));
590 set_specifier_caching (Vmenubar_visible_p,
591 slot_offset (struct window,
592 menubar_visible_p),
593 menubar_visible_p_changed,
594 slot_offset (struct frame,
595 menubar_visible_p),
596 menubar_visible_p_changed_in_frame);
597 }
598
599 void
600 complex_vars_of_menubar (void)
601 {
602 Vmenubar_pointer_glyph = Fmake_glyph_internal (Qpointer);
603 }