XEmacs 21.2.29 "Hestia".
[chise/xemacs-chise.git.1] / src / menubar.c
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   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   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   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   /* put in Vblank_menubar a menubar value which has no visible
359    * items.  This is a bit tricky due to various quirks.  We
360    * could use '(["" nil nil]), but this is apparently equivalent
361    * to '(nil), and a new frame created with this menubar will
362    * get a vertically-squished menubar.  If we use " " as the
363    * button title instead of "", we get an etched button border.
364    * So we use
365    *  '(("No active menubar" ["" nil nil]))
366    * which creates a menu whose title is "No active menubar",
367    * and this works fine.
368    */
369
370   Vblank_menubar = list1 (list2 (build_string ("No active menubar"),
371                                  vector3 (build_string (""), Qnil, Qnil)));
372   staticpro (&Vblank_menubar);
373
374   DEFVAR_BOOL ("popup-menu-titles", &popup_menu_titles /*
375 If true, popup menus will have title bars at the top.
376 */ );
377   popup_menu_titles = 1;
378
379   /* #### Replace current menubar with a specifier. */
380
381   /* All C code must access the menubar via Qcurrent_menubar
382      because it can be buffer-local.  Note that Vcurrent_menubar
383      doesn't need to exist at all, except for the magic function. */
384
385   DEFVAR_LISP_MAGIC ("current-menubar", &Vcurrent_menubar /*
386 The current menubar.  This may be buffer-local.
387
388 When the menubar is changed, the function `set-menubar-dirty-flag' has to
389 be called for the menubar to be updated on the frame.  See `set-menubar'
390 and `set-buffer-menubar'.
391
392 A menubar is a list of menus and menu-items.
393 A menu is a list of menu items, keyword-value pairs, strings, and submenus.
394
395 The first element of a menu must be a string, which is the name of the menu.
396 This is the string that will be displayed in the parent menu, if any.  For
397 toplevel menus, it is ignored.  This string is not displayed in the menu
398 itself.
399
400 Immediately following the name string of the menu, any of three
401 optional keyword-value pairs is permitted.
402
403 If an element of a menu (or menubar) is a string, then that string will be
404 presented as unselectable text.
405
406 If an element of a menu is a string consisting solely of hyphens, then that
407 item will be presented as a solid horizontal line.
408
409 If an element of a menu is a list, it is treated as a submenu.  The name of
410 that submenu (the first element in the list) will be used as the name of the
411 item representing this menu on the parent.
412
413 If an element of a menubar is `nil', then it is used to represent the
414 division between the set of menubar-items which are flushleft and those
415 which are flushright.
416
417 Otherwise, the element must be a vector, which describes a menu item.
418 A menu item can have any of the following forms:
419
420  [ "name" callback <active-p> ]
421  [ "name" callback <active-p> <suffix> ]
422  [ "name" callback :<keyword> <value>  :<keyword> <value> ... ]
423
424 The name is the string to display on the menu; it is filtered through the
425 resource database, so it is possible for resources to override what string
426 is actually displayed.
427
428 If the `callback' of a menu item is a symbol, then it must name a command.
429 It will be invoked with `call-interactively'.  If it is a list, then it is
430 evaluated with `eval'.
431
432 The possible keywords are this:
433
434  :active   <form>    Same as <active-p> in the first two forms: the
435                      expression is evaluated just before the menu is
436                      displayed, and the menu will be selectable only if
437                      the result is non-nil.
438
439  :suffix   <form>    Same as <suffix> in the second form: the expression
440                      is evaluated just before the menu is displayed and
441                      resulting string is appended to the displayed name,
442                      providing a convenient way of adding the name of a
443                      command's ``argument'' to the menu, like
444                      ``Kill Buffer NAME''.
445
446  :keys     "string"  Normally, the keyboard equivalents of commands in
447                      menus are displayed when the `callback' is a symbol.
448                      This can be used to specify keys for more complex menu
449                      items.  It is passed through `substitute-command-keys'
450                      first.
451
452  :style    <style>   Specifies what kind of object this menu item is:
453
454                         nil     A normal menu item.
455                         toggle  A toggle button.
456                         radio   A radio button.
457                         button  A menubar button.
458
459                      The only difference between toggle and radio buttons is
460                      how they are displayed.  But for consistency, a toggle
461                      button should be used when there is one option whose
462                      value can be turned on or off, and radio buttons should
463                      be used when there is a set of mutually exclusive
464                      options.  When using a group of radio buttons, you
465                      should arrange for no more than one to be marked as
466                      selected at a time.
467
468  :selected <form>    Meaningful only when STYLE is `toggle', `radio' or
469                      `button'.  This specifies whether the button will be in
470                      the selected or unselected state.
471
472  :included <form>    This can be used to control the visibility of a menu or
473                      menu item.  The form is evaluated and the menu or menu
474                      item is only displayed if the result is non-nil.
475
476  :config  <symbol>   This is an efficient shorthand for
477                          :included (memq symbol menubar-configuration)
478                      See the variable `menubar-configuration'.
479
480  :filter <function>  A menu filter can only be used in a menu item list.
481                      (i.e.:  not in a menu item itself).  It is used to
482                      sensitize or incrementally create a submenu only when
483                      it is selected by the user and not every time the
484                      menubar is activated.  The filter function is passed
485                      the list of menu items in the submenu and must return a
486                      list of menu items to be used for the menu.  It is
487                      called only when the menu is about to be displayed, so
488                      other menus may already be displayed.  Vile and
489                      terrible things will happen if a menu filter function
490                      changes the current buffer, window, or frame.  It
491                      also should not raise, lower, or iconify any frames.
492                      Basically, the filter function should have no
493                      side-effects.
494
495  :key-sequence keys  Used in FSF Emacs as an hint to an equivalent keybinding.
496                      Ignored by XEnacs for easymenu.el compatibility.
497
498  :label <form>       (unimplemented!) Like :suffix, but replaces label
499                      completely.
500                      (might be added in 21.2).
501
502 For example:
503
504  ("File"
505   :filter file-menu-filter      ; file-menu-filter is a function that takes
506                                 ; one argument (a list of menu items) and
507                                 ; returns a list of menu items
508   [ "Save As..."    write-file  t ]
509   [ "Revert Buffer" revert-buffer (buffer-modified-p) ]
510   [ "Read Only"     toggle-read-only :style toggle
511                       :selected buffer-read-only ]
512   )
513
514 See x-menubar.el for many more examples.
515
516 After the menubar is clicked upon, but before any menus are popped up,
517 the functions on the `activate-menubar-hook' are invoked to make top-level
518 changes to the menus and menubar.  Note, however, that the use of menu
519 filters (using the :filter keyword) is usually a more efficient way to
520 dynamically alter or sensitize menus.
521 */, menubar_variable_changed);
522
523   Vcurrent_menubar = Qnil;
524
525   DEFVAR_LISP ("activate-menubar-hook", &Vactivate_menubar_hook /*
526 Function or functions called before a menubar menu is pulled down.
527 These functions are called with no arguments, and should interrogate and
528 modify the value of `current-menubar' as desired.
529
530 The functions on this hook are invoked after the mouse goes down, but before
531 the menu is mapped, and may be used to activate, deactivate, add, or delete
532 items from the menus.  However, it is probably the case that using a :filter
533 keyword in a submenu would be a more efficient way of updating menus.  See
534 the documentation of `current-menubar'.
535
536 These functions may return the symbol `t' to assert that they have made
537 no changes to the menubar.  If any other value is returned, the menubar is
538 recomputed.  If `t' is returned but the menubar has been changed, then the
539 changes may not show up right away.  Returning `nil' when the menubar has
540 not changed is not so bad; more computation will be done, but redisplay of
541 the menubar will still be performed optimally.
542 */ );
543   Vactivate_menubar_hook = Qnil;
544   defsymbol (&Qactivate_menubar_hook, "activate-menubar-hook");
545
546   DEFVAR_BOOL ("menubar-show-keybindings", &menubar_show_keybindings /*
547 If true, the menubar will display keyboard equivalents.
548 If false, only the command names will be displayed.
549 */ );
550   menubar_show_keybindings = 1;
551
552   DEFVAR_LISP_MAGIC ("menubar-configuration", &Vmenubar_configuration /*
553 A list of symbols, against which the value of the :config tag for each
554 menubar item will be compared.  If a menubar item has a :config tag, then
555 it is omitted from the menubar if that tag is not a member of the
556 `menubar-configuration' list.
557 */ , menubar_variable_changed);
558   Vmenubar_configuration = Qnil;
559
560   DEFVAR_LISP ("menubar-pointer-glyph", &Vmenubar_pointer_glyph /*
561 *The shape of the mouse-pointer when over the menubar.
562 This is a glyph; use `set-glyph-image' to change it.
563 If unspecified in a particular domain, the window-system-provided
564 default pointer is used.
565 */ );
566
567   Fprovide (intern ("menubar"));
568 }
569
570 void
571 specifier_vars_of_menubar (void)
572 {
573   DEFVAR_SPECIFIER ("menubar-visible-p", &Vmenubar_visible_p /*
574 *Whether the menubar is visible.
575 This is a specifier; use `set-specifier' to change it.
576 */ );
577   Vmenubar_visible_p = Fmake_specifier (Qboolean);
578
579   set_specifier_fallback (Vmenubar_visible_p, list1 (Fcons (Qnil, Qt)));
580   set_specifier_caching (Vmenubar_visible_p,
581                          offsetof (struct window, menubar_visible_p),
582                          menubar_visible_p_changed,
583                          offsetof (struct frame, menubar_visible_p),
584                          menubar_visible_p_changed_in_frame);
585 }
586
587 void
588 complex_vars_of_menubar (void)
589 {
590   Vmenubar_pointer_glyph = Fmake_glyph_internal (Qpointer);
591 }