1 /* Platform-independent code for terminal communications.
2 Copyright (C) 1986, 1988, 1993, 1994, 1996, 1999, 2000, 2001, 2002, 2003,
3 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
27 #include "termhooks.h"
28 #include "blockinput.h"
29 #include "dispextern.h"
32 #include "../lwlib/lwlib.h"
46 extern AppendMenuW_Proc unicode_append_menu
;
48 #endif /* HAVE_NTGUI */
52 /* Define HAVE_BOXES if menus can handle radio and toggle buttons. */
53 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
57 extern Lisp_Object QCtoggle
, QCradio
;
59 Lisp_Object menu_items
;
61 /* If non-nil, means that the global vars defined here are already in use.
62 Used to detect cases where we try to re-enter this non-reentrant code. */
63 Lisp_Object menu_items_inuse
;
65 /* Number of slots currently allocated in menu_items. */
66 int menu_items_allocated
;
68 /* This is the index in menu_items of the first empty slot. */
71 /* The number of panes currently recorded in menu_items,
72 excluding those within submenus. */
73 int menu_items_n_panes
;
75 /* Current depth within submenus. */
76 static int menu_items_submenu_depth
;
81 if (!NILP (menu_items_inuse
))
82 error ("Trying to use a menu from within a menu-entry");
84 if (NILP (menu_items
))
86 menu_items_allocated
= 60;
87 menu_items
= Fmake_vector (make_number (menu_items_allocated
), Qnil
);
90 menu_items_inuse
= Qt
;
92 menu_items_n_panes
= 0;
93 menu_items_submenu_depth
= 0;
96 /* Call at the end of generating the data in menu_items. */
104 unuse_menu_items (dummy
)
107 return menu_items_inuse
= Qnil
;
110 /* Call when finished using the data for the current menu
114 discard_menu_items ()
116 /* Free the structure if it is especially large.
117 Otherwise, hold on to it, to save time. */
118 if (menu_items_allocated
> 200)
121 menu_items_allocated
= 0;
123 xassert (NILP (menu_items_inuse
));
126 /* This undoes save_menu_items, and it is called by the specpdl unwind
130 restore_menu_items (saved
)
133 menu_items
= XCAR (saved
);
134 menu_items_inuse
= (! NILP (menu_items
) ? Qt
: Qnil
);
135 menu_items_allocated
= (VECTORP (menu_items
) ? ASIZE (menu_items
) : 0);
136 saved
= XCDR (saved
);
137 menu_items_used
= XINT (XCAR (saved
));
138 saved
= XCDR (saved
);
139 menu_items_n_panes
= XINT (XCAR (saved
));
140 saved
= XCDR (saved
);
141 menu_items_submenu_depth
= XINT (XCAR (saved
));
145 /* Push the whole state of menu_items processing onto the specpdl.
146 It will be restored when the specpdl is unwound. */
151 Lisp_Object saved
= list4 (!NILP (menu_items_inuse
) ? menu_items
: Qnil
,
152 make_number (menu_items_used
),
153 make_number (menu_items_n_panes
),
154 make_number (menu_items_submenu_depth
));
155 record_unwind_protect (restore_menu_items
, saved
);
156 menu_items_inuse
= Qnil
;
161 /* Make the menu_items vector twice as large. */
166 menu_items_allocated
*= 2;
167 menu_items
= larger_vector (menu_items
, menu_items_allocated
, Qnil
);
170 /* Begin a submenu. */
173 push_submenu_start ()
175 if (menu_items_used
+ 1 > menu_items_allocated
)
178 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qnil
;
179 menu_items_submenu_depth
++;
187 if (menu_items_used
+ 1 > menu_items_allocated
)
190 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qlambda
;
191 menu_items_submenu_depth
--;
194 /* Indicate boundary between left and right. */
197 push_left_right_boundary ()
199 if (menu_items_used
+ 1 > menu_items_allocated
)
202 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qquote
;
205 /* Start a new menu pane in menu_items.
206 NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */
209 push_menu_pane (name
, prefix_vec
)
210 Lisp_Object name
, prefix_vec
;
212 if (menu_items_used
+ MENU_ITEMS_PANE_LENGTH
> menu_items_allocated
)
215 if (menu_items_submenu_depth
== 0)
216 menu_items_n_panes
++;
217 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qt
;
218 XVECTOR (menu_items
)->contents
[menu_items_used
++] = name
;
219 XVECTOR (menu_items
)->contents
[menu_items_used
++] = prefix_vec
;
222 /* Push one menu item into the current pane. NAME is the string to
223 display. ENABLE if non-nil means this item can be selected. KEY
224 is the key generated by choosing this item, or nil if this item
225 doesn't really have a definition. DEF is the definition of this
226 item. EQUIV is the textual description of the keyboard equivalent
227 for this item (or nil if none). TYPE is the type of this menu
228 item, one of nil, `toggle' or `radio'. */
231 push_menu_item (name
, enable
, key
, def
, equiv
, type
, selected
, help
)
232 Lisp_Object name
, enable
, key
, def
, equiv
, type
, selected
, help
;
234 if (menu_items_used
+ MENU_ITEMS_ITEM_LENGTH
> menu_items_allocated
)
237 XVECTOR (menu_items
)->contents
[menu_items_used
++] = name
;
238 XVECTOR (menu_items
)->contents
[menu_items_used
++] = enable
;
239 XVECTOR (menu_items
)->contents
[menu_items_used
++] = key
;
240 XVECTOR (menu_items
)->contents
[menu_items_used
++] = equiv
;
241 XVECTOR (menu_items
)->contents
[menu_items_used
++] = def
;
242 XVECTOR (menu_items
)->contents
[menu_items_used
++] = type
;
243 XVECTOR (menu_items
)->contents
[menu_items_used
++] = selected
;
244 XVECTOR (menu_items
)->contents
[menu_items_used
++] = help
;
247 /* Args passed between single_keymap_panes and single_menu_item. */
250 Lisp_Object pending_maps
;
251 int maxdepth
, notreal
;
255 static void single_menu_item
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
,
258 /* This is a recursive subroutine of keymap_panes.
259 It handles one keymap, KEYMAP.
260 The other arguments are passed along
261 or point to local variables of the previous function.
262 If NOTREAL is nonzero, only check for equivalent key bindings, don't
263 evaluate expressions in menu items and don't make any menu.
265 If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
268 single_keymap_panes (keymap
, pane_name
, prefix
, notreal
, maxdepth
)
270 Lisp_Object pane_name
;
278 skp
.pending_maps
= Qnil
;
279 skp
.maxdepth
= maxdepth
;
280 skp
.notreal
= notreal
;
286 push_menu_pane (pane_name
, prefix
);
289 /* Remember index for first item in this pane so we can go back and
290 add a prefix when (if) we see the first button. After that, notbuttons
291 is set to 0, to mark that we have seen a button and all non button
292 items need a prefix. */
293 skp
.notbuttons
= menu_items_used
;
296 GCPRO1 (skp
.pending_maps
);
297 map_keymap_canonical (keymap
, single_menu_item
, Qnil
, &skp
);
300 /* Process now any submenus which want to be panes at this level. */
301 while (CONSP (skp
.pending_maps
))
303 Lisp_Object elt
, eltcdr
, string
;
304 elt
= XCAR (skp
.pending_maps
);
306 string
= XCAR (eltcdr
);
307 /* We no longer discard the @ from the beginning of the string here.
308 Instead, we do this in *menu_show. */
309 single_keymap_panes (Fcar (elt
), string
,
310 XCDR (eltcdr
), notreal
, maxdepth
- 1);
311 skp
.pending_maps
= XCDR (skp
.pending_maps
);
315 /* This is a subroutine of single_keymap_panes that handles one
317 KEY is a key in a keymap and ITEM is its binding.
318 SKP->PENDING_MAPS_PTR is a list of keymaps waiting to be made into
320 If SKP->NOTREAL is nonzero, only check for equivalent key bindings, don't
321 evaluate expressions in menu items and don't make any menu.
322 If we encounter submenus deeper than SKP->MAXDEPTH levels, ignore them. */
325 single_menu_item (key
, item
, dummy
, skp_v
)
326 Lisp_Object key
, item
, dummy
;
329 Lisp_Object map
, item_string
, enabled
;
330 struct gcpro gcpro1
, gcpro2
;
332 struct skp
*skp
= skp_v
;
334 /* Parse the menu item and leave the result in item_properties. */
336 res
= parse_menu_item (item
, skp
->notreal
, 0);
339 return; /* Not a menu item. */
341 map
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_MAP
];
345 /* We don't want to make a menu, just traverse the keymaps to
346 precompute equivalent key bindings. */
348 single_keymap_panes (map
, Qnil
, key
, 1, skp
->maxdepth
- 1);
352 enabled
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_ENABLE
];
353 item_string
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_NAME
];
355 if (!NILP (map
) && SREF (item_string
, 0) == '@')
358 /* An enabled separate pane. Remember this to handle it later. */
359 skp
->pending_maps
= Fcons (Fcons (map
, Fcons (item_string
, key
)),
364 #ifdef HAVE_X_WINDOWS
366 /* Simulate radio buttons and toggle boxes by putting a prefix in
369 Lisp_Object prefix
= Qnil
;
370 Lisp_Object type
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_TYPE
];
374 = XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_SELECTED
];
377 /* The first button. Line up previous items in this menu. */
379 int index
= skp
->notbuttons
; /* Index for first item this menu. */
382 while (index
< menu_items_used
)
385 = XVECTOR (menu_items
)->contents
[index
+ MENU_ITEMS_ITEM_NAME
];
389 submenu
++; /* Skip sub menu. */
391 else if (EQ (tem
, Qlambda
))
394 submenu
--; /* End sub menu. */
396 else if (EQ (tem
, Qt
))
397 index
+= 3; /* Skip new pane marker. */
398 else if (EQ (tem
, Qquote
))
399 index
++; /* Skip a left, right divider. */
402 if (!submenu
&& SREF (tem
, 0) != '\0'
403 && SREF (tem
, 0) != '-')
404 XVECTOR (menu_items
)->contents
[index
+ MENU_ITEMS_ITEM_NAME
]
405 = concat2 (build_string (" "), tem
);
406 index
+= MENU_ITEMS_ITEM_LENGTH
;
412 /* Calculate prefix, if any, for this item. */
413 if (EQ (type
, QCtoggle
))
414 prefix
= build_string (NILP (selected
) ? "[ ] " : "[X] ");
415 else if (EQ (type
, QCradio
))
416 prefix
= build_string (NILP (selected
) ? "( ) " : "(*) ");
418 /* Not a button. If we have earlier buttons, then we need a prefix. */
419 else if (!skp
->notbuttons
&& SREF (item_string
, 0) != '\0'
420 && SREF (item_string
, 0) != '-')
421 prefix
= build_string (" ");
424 item_string
= concat2 (prefix
, item_string
);
426 #endif /* not HAVE_BOXES */
428 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
430 /* Indicate visually that this is a submenu. */
431 item_string
= concat2 (item_string
, build_string (" >"));
434 #endif /* HAVE_X_WINDOWS */
436 push_menu_item (item_string
, enabled
, key
,
437 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_DEF
],
438 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_KEYEQ
],
439 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_TYPE
],
440 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_SELECTED
],
441 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_HELP
]);
443 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
444 /* Display a submenu using the toolkit. */
445 if (! (NILP (map
) || NILP (enabled
)))
447 push_submenu_start ();
448 single_keymap_panes (map
, Qnil
, key
, 0, skp
->maxdepth
- 1);
454 /* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
455 and generate menu panes for them in menu_items.
456 If NOTREAL is nonzero,
457 don't bother really computing whether an item is enabled. */
460 keymap_panes (keymaps
, nmaps
, notreal
)
461 Lisp_Object
*keymaps
;
469 /* Loop over the given keymaps, making a pane for each map.
470 But don't make a pane that is empty--ignore that map instead.
471 P is the number of panes we have made so far. */
472 for (mapno
= 0; mapno
< nmaps
; mapno
++)
473 single_keymap_panes (keymaps
[mapno
],
474 Fkeymap_prompt (keymaps
[mapno
]), Qnil
, notreal
, 10);
476 finish_menu_items ();
480 /* Push the items in a single pane defined by the alist PANE. */
485 Lisp_Object tail
, item
, item1
;
487 for (tail
= pane
; CONSP (tail
); tail
= XCDR (tail
))
491 push_menu_item (ENCODE_MENU_STRING (item
), Qnil
, Qnil
, Qt
,
492 Qnil
, Qnil
, Qnil
, Qnil
);
493 else if (CONSP (item
))
496 CHECK_STRING (item1
);
497 push_menu_item (ENCODE_MENU_STRING (item1
), Qt
, XCDR (item
),
498 Qt
, Qnil
, Qnil
, Qnil
, Qnil
);
501 push_left_right_boundary ();
506 /* Push all the panes and items of a menu described by the
507 alist-of-alists MENU.
508 This handles old-fashioned calls to x-popup-menu. */
517 for (tail
= menu
; CONSP (tail
); tail
= XCDR (tail
))
519 Lisp_Object elt
, pane_name
, pane_data
;
521 pane_name
= Fcar (elt
);
522 CHECK_STRING (pane_name
);
523 push_menu_pane (ENCODE_MENU_STRING (pane_name
), Qnil
);
524 pane_data
= Fcdr (elt
);
525 CHECK_CONS (pane_data
);
526 list_of_items (pane_data
);
529 finish_menu_items ();
532 /* Set up data in menu_items for a menu bar item
533 whose event type is ITEM_KEY (with string ITEM_NAME)
534 and whose contents come from the list of keymaps MAPS. */
536 parse_single_submenu (item_key
, item_name
, maps
)
537 Lisp_Object item_key
, item_name
, maps
;
543 int top_level_items
= 0;
545 length
= Flength (maps
);
548 /* Convert the list MAPS into a vector MAPVEC. */
549 mapvec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
550 for (i
= 0; i
< len
; i
++)
552 mapvec
[i
] = Fcar (maps
);
556 /* Loop over the given keymaps, making a pane for each map.
557 But don't make a pane that is empty--ignore that map instead. */
558 for (i
= 0; i
< len
; i
++)
560 if (!KEYMAPP (mapvec
[i
]))
562 /* Here we have a command at top level in the menu bar
563 as opposed to a submenu. */
565 push_menu_pane (Qnil
, Qnil
);
566 push_menu_item (item_name
, Qt
, item_key
, mapvec
[i
],
567 Qnil
, Qnil
, Qnil
, Qnil
);
572 prompt
= Fkeymap_prompt (mapvec
[i
]);
573 single_keymap_panes (mapvec
[i
],
574 !NILP (prompt
) ? prompt
: item_name
,
579 return top_level_items
;
583 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
585 /* Allocate a widget_value, blocking input. */
588 xmalloc_widget_value ()
593 value
= malloc_widget_value ();
599 /* This recursively calls free_widget_value on the tree of widgets.
600 It must free all data that was malloc'ed for these widget_values.
601 In Emacs, many slots are pointers into the data of Lisp_Strings, and
602 must be left alone. */
605 free_menubar_widget_value_tree (wv
)
610 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
612 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
614 free_menubar_widget_value_tree (wv
->contents
);
615 wv
->contents
= (widget_value
*) 0xDEADBEEF;
619 free_menubar_widget_value_tree (wv
->next
);
620 wv
->next
= (widget_value
*) 0xDEADBEEF;
623 free_widget_value (wv
);
627 /* Create a tree of widget_value objects
628 representing the panes and items
629 in menu_items starting at index START, up to index END. */
632 digest_single_submenu (start
, end
, top_level_items
)
633 int start
, end
, top_level_items
;
635 widget_value
*wv
, *prev_wv
, *save_wv
, *first_wv
;
637 int submenu_depth
= 0;
638 widget_value
**submenu_stack
;
642 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
643 wv
= xmalloc_widget_value ();
647 wv
->button_type
= BUTTON_TYPE_NONE
;
653 /* Loop over all panes and items made by the preceding call
654 to parse_single_submenu and construct a tree of widget_value objects.
655 Ignore the panes and items used by previous calls to
656 digest_single_submenu, even though those are also in menu_items. */
660 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
662 submenu_stack
[submenu_depth
++] = save_wv
;
667 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
670 save_wv
= submenu_stack
[--submenu_depth
];
673 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
)
674 && submenu_depth
!= 0)
675 i
+= MENU_ITEMS_PANE_LENGTH
;
676 /* Ignore a nil in the item list.
677 It's meaningful only for dialog boxes. */
678 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
680 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
682 /* Create a new pane. */
683 Lisp_Object pane_name
, prefix
;
688 pane_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_NAME
];
689 prefix
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
692 if (STRINGP (pane_name
))
694 if (unicode_append_menu
)
695 /* Encode as UTF-8 for now. */
696 pane_name
= ENCODE_UTF_8 (pane_name
);
697 else if (STRING_MULTIBYTE (pane_name
))
698 pane_name
= ENCODE_SYSTEM (pane_name
);
700 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
702 #elif !defined (HAVE_MULTILINGUAL_MENU)
703 if (STRINGP (pane_name
) && STRING_MULTIBYTE (pane_name
))
705 pane_name
= ENCODE_MENU_STRING (pane_name
);
706 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
710 pane_string
= (NILP (pane_name
)
711 ? "" : (char *) SDATA (pane_name
));
712 /* If there is just one top-level pane, put all its items directly
713 under the top-level menu. */
714 if (menu_items_n_panes
== 1)
717 /* If the pane has a meaningful name,
718 make the pane a top-level menu item
719 with its items as a submenu beneath it. */
720 if (strcmp (pane_string
, ""))
722 wv
= xmalloc_widget_value ();
726 first_wv
->contents
= wv
;
727 wv
->lname
= pane_name
;
728 /* Set value to 1 so update_submenu_strings can handle '@' */
729 wv
->value
= (char *)1;
731 wv
->button_type
= BUTTON_TYPE_NONE
;
739 i
+= MENU_ITEMS_PANE_LENGTH
;
743 /* Create a new item within current pane. */
744 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
;
747 /* All items should be contained in panes. */
751 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
752 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
753 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
754 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
755 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
756 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
757 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
760 if (STRINGP (item_name
))
762 if (unicode_append_menu
)
763 item_name
= ENCODE_UTF_8 (item_name
);
764 else if (STRING_MULTIBYTE (item_name
))
765 item_name
= ENCODE_SYSTEM (item_name
);
767 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
770 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
772 descrip
= ENCODE_SYSTEM (descrip
);
773 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
775 #elif !defined (HAVE_MULTILINGUAL_MENU)
776 if (STRING_MULTIBYTE (item_name
))
778 item_name
= ENCODE_MENU_STRING (item_name
);
779 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
782 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
784 descrip
= ENCODE_MENU_STRING (descrip
);
785 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
789 wv
= xmalloc_widget_value ();
793 save_wv
->contents
= wv
;
795 wv
->lname
= item_name
;
799 /* The EMACS_INT cast avoids a warning. There's no problem
800 as long as pointers have enough bits to hold small integers. */
801 wv
->call_data
= (!NILP (def
) ? (void *) (EMACS_INT
) i
: 0);
802 wv
->enabled
= !NILP (enable
);
805 wv
->button_type
= BUTTON_TYPE_NONE
;
806 else if (EQ (type
, QCradio
))
807 wv
->button_type
= BUTTON_TYPE_RADIO
;
808 else if (EQ (type
, QCtoggle
))
809 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
813 wv
->selected
= !NILP (selected
);
814 if (! STRINGP (help
))
821 i
+= MENU_ITEMS_ITEM_LENGTH
;
825 /* If we have just one "menu item"
826 that was originally a button, return it by itself. */
827 if (top_level_items
&& first_wv
->contents
&& first_wv
->contents
->next
== 0)
829 wv
= first_wv
->contents
;
830 free_widget_value (first_wv
);
837 /* Walk through the widget_value tree starting at FIRST_WV and update
838 the char * pointers from the corresponding lisp values.
839 We do this after building the whole tree, since GC may happen while the
840 tree is constructed, and small strings are relocated. So we must wait
841 until no GC can happen before storing pointers into lisp values. */
843 update_submenu_strings (first_wv
)
844 widget_value
*first_wv
;
848 for (wv
= first_wv
; wv
; wv
= wv
->next
)
850 if (STRINGP (wv
->lname
))
852 wv
->name
= (char *) SDATA (wv
->lname
);
854 /* Ignore the @ that means "separate pane".
855 This is a kludge, but this isn't worth more time. */
856 if (wv
->value
== (char *)1)
858 if (wv
->name
[0] == '@')
864 if (STRINGP (wv
->lkey
))
865 wv
->key
= (char *) SDATA (wv
->lkey
);
868 update_submenu_strings (wv
->contents
);
872 /* Find the menu selection and store it in the keyboard buffer.
873 F is the frame the menu is on.
874 MENU_BAR_ITEMS_USED is the length of VECTOR.
875 VECTOR is an array of menu events for the whole menu. */
878 find_and_call_menu_selection (f
, menu_bar_items_used
, vector
, client_data
)
880 EMACS_INT menu_bar_items_used
;
884 Lisp_Object prefix
, entry
;
885 Lisp_Object
*subprefix_stack
;
886 int submenu_depth
= 0;
890 subprefix_stack
= (Lisp_Object
*) alloca (menu_bar_items_used
* sizeof (Lisp_Object
));
894 while (i
< menu_bar_items_used
)
896 if (EQ (XVECTOR (vector
)->contents
[i
], Qnil
))
898 subprefix_stack
[submenu_depth
++] = prefix
;
902 else if (EQ (XVECTOR (vector
)->contents
[i
], Qlambda
))
904 prefix
= subprefix_stack
[--submenu_depth
];
907 else if (EQ (XVECTOR (vector
)->contents
[i
], Qt
))
909 prefix
= XVECTOR (vector
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
910 i
+= MENU_ITEMS_PANE_LENGTH
;
914 entry
= XVECTOR (vector
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
915 /* The EMACS_INT cast avoids a warning. There's no problem
916 as long as pointers have enough bits to hold small integers. */
917 if ((int) (EMACS_INT
) client_data
== i
)
920 struct input_event buf
;
924 XSETFRAME (frame
, f
);
925 buf
.kind
= MENU_BAR_EVENT
;
926 buf
.frame_or_window
= frame
;
928 kbd_buffer_store_event (&buf
);
930 for (j
= 0; j
< submenu_depth
; j
++)
931 if (!NILP (subprefix_stack
[j
]))
933 buf
.kind
= MENU_BAR_EVENT
;
934 buf
.frame_or_window
= frame
;
935 buf
.arg
= subprefix_stack
[j
];
936 kbd_buffer_store_event (&buf
);
941 buf
.kind
= MENU_BAR_EVENT
;
942 buf
.frame_or_window
= frame
;
944 kbd_buffer_store_event (&buf
);
947 buf
.kind
= MENU_BAR_EVENT
;
948 buf
.frame_or_window
= frame
;
950 kbd_buffer_store_event (&buf
);
954 i
+= MENU_ITEMS_ITEM_LENGTH
;
959 #endif /* USE_X_TOOLKIT || USE_GTK || HAVE_NTGUI */
964 staticpro (&menu_items
);
966 menu_items_inuse
= Qnil
;
969 /* arch-tag: 78bbc7cf-8025-4156-aa8a-6c7fd99bf51d
970 (do not change this comment) */