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 */
51 /* Define HAVE_BOXES if menus can handle radio and toggle buttons. */
52 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
56 extern Lisp_Object QCtoggle
, QCradio
;
58 Lisp_Object menu_items
;
60 /* If non-nil, means that the global vars defined here are already in use.
61 Used to detect cases where we try to re-enter this non-reentrant code. */
62 Lisp_Object menu_items_inuse
;
64 /* Number of slots currently allocated in menu_items. */
65 int menu_items_allocated
;
67 /* This is the index in menu_items of the first empty slot. */
70 /* The number of panes currently recorded in menu_items,
71 excluding those within submenus. */
72 int menu_items_n_panes
;
74 /* Current depth within submenus. */
75 static int menu_items_submenu_depth
;
80 if (!NILP (menu_items_inuse
))
81 error ("Trying to use a menu from within a menu-entry");
83 if (NILP (menu_items
))
85 menu_items_allocated
= 60;
86 menu_items
= Fmake_vector (make_number (menu_items_allocated
), Qnil
);
89 menu_items_inuse
= Qt
;
91 menu_items_n_panes
= 0;
92 menu_items_submenu_depth
= 0;
95 /* Call at the end of generating the data in menu_items. */
103 unuse_menu_items (dummy
)
106 return menu_items_inuse
= Qnil
;
109 /* Call when finished using the data for the current menu
113 discard_menu_items ()
115 /* Free the structure if it is especially large.
116 Otherwise, hold on to it, to save time. */
117 if (menu_items_allocated
> 200)
120 menu_items_allocated
= 0;
122 xassert (NILP (menu_items_inuse
));
125 /* This undoes save_menu_items, and it is called by the specpdl unwind
129 restore_menu_items (saved
)
132 menu_items
= XCAR (saved
);
133 menu_items_inuse
= (! NILP (menu_items
) ? Qt
: Qnil
);
134 menu_items_allocated
= (VECTORP (menu_items
) ? ASIZE (menu_items
) : 0);
135 saved
= XCDR (saved
);
136 menu_items_used
= XINT (XCAR (saved
));
137 saved
= XCDR (saved
);
138 menu_items_n_panes
= XINT (XCAR (saved
));
139 saved
= XCDR (saved
);
140 menu_items_submenu_depth
= XINT (XCAR (saved
));
144 /* Push the whole state of menu_items processing onto the specpdl.
145 It will be restored when the specpdl is unwound. */
150 Lisp_Object saved
= list4 (!NILP (menu_items_inuse
) ? menu_items
: Qnil
,
151 make_number (menu_items_used
),
152 make_number (menu_items_n_panes
),
153 make_number (menu_items_submenu_depth
));
154 record_unwind_protect (restore_menu_items
, saved
);
155 menu_items_inuse
= Qnil
;
160 /* Make the menu_items vector twice as large. */
165 menu_items_allocated
*= 2;
166 menu_items
= larger_vector (menu_items
, menu_items_allocated
, Qnil
);
169 /* Begin a submenu. */
172 push_submenu_start ()
174 if (menu_items_used
+ 1 > menu_items_allocated
)
177 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qnil
;
178 menu_items_submenu_depth
++;
186 if (menu_items_used
+ 1 > menu_items_allocated
)
189 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qlambda
;
190 menu_items_submenu_depth
--;
193 /* Indicate boundary between left and right. */
196 push_left_right_boundary ()
198 if (menu_items_used
+ 1 > menu_items_allocated
)
201 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qquote
;
204 /* Start a new menu pane in menu_items.
205 NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */
208 push_menu_pane (name
, prefix_vec
)
209 Lisp_Object name
, prefix_vec
;
211 if (menu_items_used
+ MENU_ITEMS_PANE_LENGTH
> menu_items_allocated
)
214 if (menu_items_submenu_depth
== 0)
215 menu_items_n_panes
++;
216 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qt
;
217 XVECTOR (menu_items
)->contents
[menu_items_used
++] = name
;
218 XVECTOR (menu_items
)->contents
[menu_items_used
++] = prefix_vec
;
221 /* Push one menu item into the current pane. NAME is the string to
222 display. ENABLE if non-nil means this item can be selected. KEY
223 is the key generated by choosing this item, or nil if this item
224 doesn't really have a definition. DEF is the definition of this
225 item. EQUIV is the textual description of the keyboard equivalent
226 for this item (or nil if none). TYPE is the type of this menu
227 item, one of nil, `toggle' or `radio'. */
230 push_menu_item (name
, enable
, key
, def
, equiv
, type
, selected
, help
)
231 Lisp_Object name
, enable
, key
, def
, equiv
, type
, selected
, help
;
233 if (menu_items_used
+ MENU_ITEMS_ITEM_LENGTH
> menu_items_allocated
)
236 XVECTOR (menu_items
)->contents
[menu_items_used
++] = name
;
237 XVECTOR (menu_items
)->contents
[menu_items_used
++] = enable
;
238 XVECTOR (menu_items
)->contents
[menu_items_used
++] = key
;
239 XVECTOR (menu_items
)->contents
[menu_items_used
++] = equiv
;
240 XVECTOR (menu_items
)->contents
[menu_items_used
++] = def
;
241 XVECTOR (menu_items
)->contents
[menu_items_used
++] = type
;
242 XVECTOR (menu_items
)->contents
[menu_items_used
++] = selected
;
243 XVECTOR (menu_items
)->contents
[menu_items_used
++] = help
;
246 /* Args passed between single_keymap_panes and single_menu_item. */
249 Lisp_Object pending_maps
;
250 int maxdepth
, notreal
;
254 static void single_menu_item
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
,
257 /* This is a recursive subroutine of keymap_panes.
258 It handles one keymap, KEYMAP.
259 The other arguments are passed along
260 or point to local variables of the previous function.
261 If NOTREAL is nonzero, only check for equivalent key bindings, don't
262 evaluate expressions in menu items and don't make any menu.
264 If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
267 single_keymap_panes (keymap
, pane_name
, prefix
, notreal
, maxdepth
)
269 Lisp_Object pane_name
;
277 skp
.pending_maps
= Qnil
;
278 skp
.maxdepth
= maxdepth
;
279 skp
.notreal
= notreal
;
285 push_menu_pane (pane_name
, prefix
);
288 /* Remember index for first item in this pane so we can go back and
289 add a prefix when (if) we see the first button. After that, notbuttons
290 is set to 0, to mark that we have seen a button and all non button
291 items need a prefix. */
292 skp
.notbuttons
= menu_items_used
;
295 GCPRO1 (skp
.pending_maps
);
296 map_keymap_canonical (keymap
, single_menu_item
, Qnil
, &skp
);
299 /* Process now any submenus which want to be panes at this level. */
300 while (CONSP (skp
.pending_maps
))
302 Lisp_Object elt
, eltcdr
, string
;
303 elt
= XCAR (skp
.pending_maps
);
305 string
= XCAR (eltcdr
);
306 /* We no longer discard the @ from the beginning of the string here.
307 Instead, we do this in *menu_show. */
308 single_keymap_panes (Fcar (elt
), string
,
309 XCDR (eltcdr
), notreal
, maxdepth
- 1);
310 skp
.pending_maps
= XCDR (skp
.pending_maps
);
314 /* This is a subroutine of single_keymap_panes that handles one
316 KEY is a key in a keymap and ITEM is its binding.
317 SKP->PENDING_MAPS_PTR is a list of keymaps waiting to be made into
319 If SKP->NOTREAL is nonzero, only check for equivalent key bindings, don't
320 evaluate expressions in menu items and don't make any menu.
321 If we encounter submenus deeper than SKP->MAXDEPTH levels, ignore them. */
324 single_menu_item (key
, item
, dummy
, skp_v
)
325 Lisp_Object key
, item
, dummy
;
328 Lisp_Object map
, item_string
, enabled
;
329 struct gcpro gcpro1
, gcpro2
;
331 struct skp
*skp
= skp_v
;
333 /* Parse the menu item and leave the result in item_properties. */
335 res
= parse_menu_item (item
, skp
->notreal
, 0);
338 return; /* Not a menu item. */
340 map
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_MAP
];
344 /* We don't want to make a menu, just traverse the keymaps to
345 precompute equivalent key bindings. */
347 single_keymap_panes (map
, Qnil
, key
, 1, skp
->maxdepth
- 1);
351 enabled
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_ENABLE
];
352 item_string
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_NAME
];
354 if (!NILP (map
) && SREF (item_string
, 0) == '@')
357 /* An enabled separate pane. Remember this to handle it later. */
358 skp
->pending_maps
= Fcons (Fcons (map
, Fcons (item_string
, key
)),
363 #ifdef HAVE_X_WINDOWS
365 /* Simulate radio buttons and toggle boxes by putting a prefix in
368 Lisp_Object prefix
= Qnil
;
369 Lisp_Object type
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_TYPE
];
373 = XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_SELECTED
];
376 /* The first button. Line up previous items in this menu. */
378 int index
= skp
->notbuttons
; /* Index for first item this menu. */
381 while (index
< menu_items_used
)
384 = XVECTOR (menu_items
)->contents
[index
+ MENU_ITEMS_ITEM_NAME
];
388 submenu
++; /* Skip sub menu. */
390 else if (EQ (tem
, Qlambda
))
393 submenu
--; /* End sub menu. */
395 else if (EQ (tem
, Qt
))
396 index
+= 3; /* Skip new pane marker. */
397 else if (EQ (tem
, Qquote
))
398 index
++; /* Skip a left, right divider. */
401 if (!submenu
&& SREF (tem
, 0) != '\0'
402 && SREF (tem
, 0) != '-')
403 XVECTOR (menu_items
)->contents
[index
+ MENU_ITEMS_ITEM_NAME
]
404 = concat2 (build_string (" "), tem
);
405 index
+= MENU_ITEMS_ITEM_LENGTH
;
411 /* Calculate prefix, if any, for this item. */
412 if (EQ (type
, QCtoggle
))
413 prefix
= build_string (NILP (selected
) ? "[ ] " : "[X] ");
414 else if (EQ (type
, QCradio
))
415 prefix
= build_string (NILP (selected
) ? "( ) " : "(*) ");
417 /* Not a button. If we have earlier buttons, then we need a prefix. */
418 else if (!skp
->notbuttons
&& SREF (item_string
, 0) != '\0'
419 && SREF (item_string
, 0) != '-')
420 prefix
= build_string (" ");
423 item_string
= concat2 (prefix
, item_string
);
425 #endif /* not HAVE_BOXES */
427 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
429 /* Indicate visually that this is a submenu. */
430 item_string
= concat2 (item_string
, build_string (" >"));
433 #endif /* HAVE_X_WINDOWS */
435 push_menu_item (item_string
, enabled
, key
,
436 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_DEF
],
437 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_KEYEQ
],
438 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_TYPE
],
439 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_SELECTED
],
440 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_HELP
]);
442 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
443 /* Display a submenu using the toolkit. */
444 if (! (NILP (map
) || NILP (enabled
)))
446 push_submenu_start ();
447 single_keymap_panes (map
, Qnil
, key
, 0, skp
->maxdepth
- 1);
453 /* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
454 and generate menu panes for them in menu_items.
455 If NOTREAL is nonzero,
456 don't bother really computing whether an item is enabled. */
459 keymap_panes (keymaps
, nmaps
, notreal
)
460 Lisp_Object
*keymaps
;
468 /* Loop over the given keymaps, making a pane for each map.
469 But don't make a pane that is empty--ignore that map instead.
470 P is the number of panes we have made so far. */
471 for (mapno
= 0; mapno
< nmaps
; mapno
++)
472 single_keymap_panes (keymaps
[mapno
],
473 Fkeymap_prompt (keymaps
[mapno
]), Qnil
, notreal
, 10);
475 finish_menu_items ();
479 /* Push the items in a single pane defined by the alist PANE. */
484 Lisp_Object tail
, item
, item1
;
486 for (tail
= pane
; CONSP (tail
); tail
= XCDR (tail
))
490 push_menu_item (ENCODE_MENU_STRING (item
), Qnil
, Qnil
, Qt
,
491 Qnil
, Qnil
, Qnil
, Qnil
);
492 else if (CONSP (item
))
495 CHECK_STRING (item1
);
496 push_menu_item (ENCODE_MENU_STRING (item1
), Qt
, XCDR (item
),
497 Qt
, Qnil
, Qnil
, Qnil
, Qnil
);
500 push_left_right_boundary ();
505 /* Push all the panes and items of a menu described by the
506 alist-of-alists MENU.
507 This handles old-fashioned calls to x-popup-menu. */
516 for (tail
= menu
; CONSP (tail
); tail
= XCDR (tail
))
518 Lisp_Object elt
, pane_name
, pane_data
;
520 pane_name
= Fcar (elt
);
521 CHECK_STRING (pane_name
);
522 push_menu_pane (ENCODE_MENU_STRING (pane_name
), Qnil
);
523 pane_data
= Fcdr (elt
);
524 CHECK_CONS (pane_data
);
525 list_of_items (pane_data
);
528 finish_menu_items ();
531 /* Set up data in menu_items for a menu bar item
532 whose event type is ITEM_KEY (with string ITEM_NAME)
533 and whose contents come from the list of keymaps MAPS. */
535 parse_single_submenu (item_key
, item_name
, maps
)
536 Lisp_Object item_key
, item_name
, maps
;
542 int top_level_items
= 0;
544 length
= Flength (maps
);
547 /* Convert the list MAPS into a vector MAPVEC. */
548 mapvec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
549 for (i
= 0; i
< len
; i
++)
551 mapvec
[i
] = Fcar (maps
);
555 /* Loop over the given keymaps, making a pane for each map.
556 But don't make a pane that is empty--ignore that map instead. */
557 for (i
= 0; i
< len
; i
++)
559 if (!KEYMAPP (mapvec
[i
]))
561 /* Here we have a command at top level in the menu bar
562 as opposed to a submenu. */
564 push_menu_pane (Qnil
, Qnil
);
565 push_menu_item (item_name
, Qt
, item_key
, mapvec
[i
],
566 Qnil
, Qnil
, Qnil
, Qnil
);
571 prompt
= Fkeymap_prompt (mapvec
[i
]);
572 single_keymap_panes (mapvec
[i
],
573 !NILP (prompt
) ? prompt
: item_name
,
578 return top_level_items
;
582 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
584 /* Allocate a widget_value, blocking input. */
587 xmalloc_widget_value ()
592 value
= malloc_widget_value ();
598 /* This recursively calls free_widget_value on the tree of widgets.
599 It must free all data that was malloc'ed for these widget_values.
600 In Emacs, many slots are pointers into the data of Lisp_Strings, and
601 must be left alone. */
604 free_menubar_widget_value_tree (wv
)
609 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
611 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
613 free_menubar_widget_value_tree (wv
->contents
);
614 wv
->contents
= (widget_value
*) 0xDEADBEEF;
618 free_menubar_widget_value_tree (wv
->next
);
619 wv
->next
= (widget_value
*) 0xDEADBEEF;
622 free_widget_value (wv
);
626 /* Create a tree of widget_value objects
627 representing the panes and items
628 in menu_items starting at index START, up to index END. */
631 digest_single_submenu (start
, end
, top_level_items
)
632 int start
, end
, top_level_items
;
634 widget_value
*wv
, *prev_wv
, *save_wv
, *first_wv
;
636 int submenu_depth
= 0;
637 widget_value
**submenu_stack
;
641 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
642 wv
= xmalloc_widget_value ();
646 wv
->button_type
= BUTTON_TYPE_NONE
;
652 /* Loop over all panes and items made by the preceding call
653 to parse_single_submenu and construct a tree of widget_value objects.
654 Ignore the panes and items used by previous calls to
655 digest_single_submenu, even though those are also in menu_items. */
659 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
661 submenu_stack
[submenu_depth
++] = save_wv
;
666 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
669 save_wv
= submenu_stack
[--submenu_depth
];
672 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
)
673 && submenu_depth
!= 0)
674 i
+= MENU_ITEMS_PANE_LENGTH
;
675 /* Ignore a nil in the item list.
676 It's meaningful only for dialog boxes. */
677 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
679 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
681 /* Create a new pane. */
682 Lisp_Object pane_name
, prefix
;
687 pane_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_NAME
];
688 prefix
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
691 if (STRINGP (pane_name
))
693 if (unicode_append_menu
)
694 /* Encode as UTF-8 for now. */
695 pane_name
= ENCODE_UTF_8 (pane_name
);
696 else if (STRING_MULTIBYTE (pane_name
))
697 pane_name
= ENCODE_SYSTEM (pane_name
);
699 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
701 #elif !defined (HAVE_MULTILINGUAL_MENU)
702 if (STRINGP (pane_name
) && STRING_MULTIBYTE (pane_name
))
704 pane_name
= ENCODE_MENU_STRING (pane_name
);
705 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
709 pane_string
= (NILP (pane_name
)
710 ? "" : (char *) SDATA (pane_name
));
711 /* If there is just one top-level pane, put all its items directly
712 under the top-level menu. */
713 if (menu_items_n_panes
== 1)
716 /* If the pane has a meaningful name,
717 make the pane a top-level menu item
718 with its items as a submenu beneath it. */
719 if (strcmp (pane_string
, ""))
721 wv
= xmalloc_widget_value ();
725 first_wv
->contents
= wv
;
726 wv
->lname
= pane_name
;
727 /* Set value to 1 so update_submenu_strings can handle '@' */
728 wv
->value
= (char *)1;
730 wv
->button_type
= BUTTON_TYPE_NONE
;
738 i
+= MENU_ITEMS_PANE_LENGTH
;
742 /* Create a new item within current pane. */
743 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
;
746 /* All items should be contained in panes. */
750 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
751 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
752 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
753 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
754 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
755 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
756 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
759 if (STRINGP (item_name
))
761 if (unicode_append_menu
)
762 item_name
= ENCODE_UTF_8 (item_name
);
763 else if (STRING_MULTIBYTE (item_name
))
764 item_name
= ENCODE_SYSTEM (item_name
);
766 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
769 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
771 descrip
= ENCODE_SYSTEM (descrip
);
772 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
774 #elif !defined (HAVE_MULTILINGUAL_MENU)
775 if (STRING_MULTIBYTE (item_name
))
777 item_name
= ENCODE_MENU_STRING (item_name
);
778 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
781 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
783 descrip
= ENCODE_MENU_STRING (descrip
);
784 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
788 wv
= xmalloc_widget_value ();
792 save_wv
->contents
= wv
;
794 wv
->lname
= item_name
;
798 /* The EMACS_INT cast avoids a warning. There's no problem
799 as long as pointers have enough bits to hold small integers. */
800 wv
->call_data
= (!NILP (def
) ? (void *) (EMACS_INT
) i
: 0);
801 wv
->enabled
= !NILP (enable
);
804 wv
->button_type
= BUTTON_TYPE_NONE
;
805 else if (EQ (type
, QCradio
))
806 wv
->button_type
= BUTTON_TYPE_RADIO
;
807 else if (EQ (type
, QCtoggle
))
808 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
812 wv
->selected
= !NILP (selected
);
813 if (! STRINGP (help
))
820 i
+= MENU_ITEMS_ITEM_LENGTH
;
824 /* If we have just one "menu item"
825 that was originally a button, return it by itself. */
826 if (top_level_items
&& first_wv
->contents
&& first_wv
->contents
->next
== 0)
828 wv
= first_wv
->contents
;
829 free_widget_value (first_wv
);
836 /* Walk through the widget_value tree starting at FIRST_WV and update
837 the char * pointers from the corresponding lisp values.
838 We do this after building the whole tree, since GC may happen while the
839 tree is constructed, and small strings are relocated. So we must wait
840 until no GC can happen before storing pointers into lisp values. */
842 update_submenu_strings (first_wv
)
843 widget_value
*first_wv
;
847 for (wv
= first_wv
; wv
; wv
= wv
->next
)
849 if (STRINGP (wv
->lname
))
851 wv
->name
= (char *) SDATA (wv
->lname
);
853 /* Ignore the @ that means "separate pane".
854 This is a kludge, but this isn't worth more time. */
855 if (wv
->value
== (char *)1)
857 if (wv
->name
[0] == '@')
863 if (STRINGP (wv
->lkey
))
864 wv
->key
= (char *) SDATA (wv
->lkey
);
867 update_submenu_strings (wv
->contents
);
871 /* Find the menu selection and store it in the keyboard buffer.
872 F is the frame the menu is on.
873 MENU_BAR_ITEMS_USED is the length of VECTOR.
874 VECTOR is an array of menu events for the whole menu. */
877 find_and_call_menu_selection (f
, menu_bar_items_used
, vector
, client_data
)
879 EMACS_INT menu_bar_items_used
;
883 Lisp_Object prefix
, entry
;
884 Lisp_Object
*subprefix_stack
;
885 int submenu_depth
= 0;
889 subprefix_stack
= (Lisp_Object
*) alloca (menu_bar_items_used
* sizeof (Lisp_Object
));
893 while (i
< menu_bar_items_used
)
895 if (EQ (XVECTOR (vector
)->contents
[i
], Qnil
))
897 subprefix_stack
[submenu_depth
++] = prefix
;
901 else if (EQ (XVECTOR (vector
)->contents
[i
], Qlambda
))
903 prefix
= subprefix_stack
[--submenu_depth
];
906 else if (EQ (XVECTOR (vector
)->contents
[i
], Qt
))
908 prefix
= XVECTOR (vector
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
909 i
+= MENU_ITEMS_PANE_LENGTH
;
913 entry
= XVECTOR (vector
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
914 /* The EMACS_INT cast avoids a warning. There's no problem
915 as long as pointers have enough bits to hold small integers. */
916 if ((int) (EMACS_INT
) client_data
== i
)
919 struct input_event buf
;
923 XSETFRAME (frame
, f
);
924 buf
.kind
= MENU_BAR_EVENT
;
925 buf
.frame_or_window
= frame
;
927 kbd_buffer_store_event (&buf
);
929 for (j
= 0; j
< submenu_depth
; j
++)
930 if (!NILP (subprefix_stack
[j
]))
932 buf
.kind
= MENU_BAR_EVENT
;
933 buf
.frame_or_window
= frame
;
934 buf
.arg
= subprefix_stack
[j
];
935 kbd_buffer_store_event (&buf
);
940 buf
.kind
= MENU_BAR_EVENT
;
941 buf
.frame_or_window
= frame
;
943 kbd_buffer_store_event (&buf
);
946 buf
.kind
= MENU_BAR_EVENT
;
947 buf
.frame_or_window
= frame
;
949 kbd_buffer_store_event (&buf
);
953 i
+= MENU_ITEMS_ITEM_LENGTH
;
958 #endif /* USE_X_TOOLKIT || USE_GTK || HAVE_NTGUI */
963 staticpro (&menu_items
);
965 menu_items_inuse
= Qnil
;
968 /* arch-tag: 78bbc7cf-8025-4156-aa8a-6c7fd99bf51d
969 (do not change this comment) */