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, 2009 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/>. */
28 #include "termhooks.h"
29 #include "blockinput.h"
30 #include "dispextern.h"
33 #include "../lwlib/lwlib.h"
51 extern AppendMenuW_Proc unicode_append_menu
;
53 #endif /* HAVE_NTGUI */
57 /* Define HAVE_BOXES if menus can handle radio and toggle buttons. */
58 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
62 extern Lisp_Object QCtoggle
, QCradio
;
64 Lisp_Object menu_items
;
66 /* If non-nil, means that the global vars defined here are already in use.
67 Used to detect cases where we try to re-enter this non-reentrant code. */
68 Lisp_Object menu_items_inuse
;
70 /* Number of slots currently allocated in menu_items. */
71 int menu_items_allocated
;
73 /* This is the index in menu_items of the first empty slot. */
76 /* The number of panes currently recorded in menu_items,
77 excluding those within submenus. */
78 int menu_items_n_panes
;
80 /* Current depth within submenus. */
81 static int menu_items_submenu_depth
;
86 if (!NILP (menu_items_inuse
))
87 error ("Trying to use a menu from within a menu-entry");
89 if (NILP (menu_items
))
91 menu_items_allocated
= 60;
92 menu_items
= Fmake_vector (make_number (menu_items_allocated
), Qnil
);
95 menu_items_inuse
= Qt
;
97 menu_items_n_panes
= 0;
98 menu_items_submenu_depth
= 0;
101 /* Call at the end of generating the data in menu_items. */
109 unuse_menu_items (dummy
)
112 return menu_items_inuse
= Qnil
;
115 /* Call when finished using the data for the current menu
119 discard_menu_items ()
121 /* Free the structure if it is especially large.
122 Otherwise, hold on to it, to save time. */
123 if (menu_items_allocated
> 200)
126 menu_items_allocated
= 0;
128 xassert (NILP (menu_items_inuse
));
131 /* This undoes save_menu_items, and it is called by the specpdl unwind
135 restore_menu_items (saved
)
138 menu_items
= XCAR (saved
);
139 menu_items_inuse
= (! NILP (menu_items
) ? Qt
: Qnil
);
140 menu_items_allocated
= (VECTORP (menu_items
) ? ASIZE (menu_items
) : 0);
141 saved
= XCDR (saved
);
142 menu_items_used
= XINT (XCAR (saved
));
143 saved
= XCDR (saved
);
144 menu_items_n_panes
= XINT (XCAR (saved
));
145 saved
= XCDR (saved
);
146 menu_items_submenu_depth
= XINT (XCAR (saved
));
150 /* Push the whole state of menu_items processing onto the specpdl.
151 It will be restored when the specpdl is unwound. */
156 Lisp_Object saved
= list4 (!NILP (menu_items_inuse
) ? menu_items
: Qnil
,
157 make_number (menu_items_used
),
158 make_number (menu_items_n_panes
),
159 make_number (menu_items_submenu_depth
));
160 record_unwind_protect (restore_menu_items
, saved
);
161 menu_items_inuse
= Qnil
;
166 /* Make the menu_items vector twice as large. */
171 menu_items_allocated
*= 2;
172 menu_items
= larger_vector (menu_items
, menu_items_allocated
, Qnil
);
175 /* Begin a submenu. */
178 push_submenu_start ()
180 if (menu_items_used
+ 1 > menu_items_allocated
)
183 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qnil
;
184 menu_items_submenu_depth
++;
192 if (menu_items_used
+ 1 > menu_items_allocated
)
195 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qlambda
;
196 menu_items_submenu_depth
--;
199 /* Indicate boundary between left and right. */
202 push_left_right_boundary ()
204 if (menu_items_used
+ 1 > menu_items_allocated
)
207 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qquote
;
210 /* Start a new menu pane in menu_items.
211 NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */
214 push_menu_pane (name
, prefix_vec
)
215 Lisp_Object name
, prefix_vec
;
217 if (menu_items_used
+ MENU_ITEMS_PANE_LENGTH
> menu_items_allocated
)
220 if (menu_items_submenu_depth
== 0)
221 menu_items_n_panes
++;
222 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qt
;
223 XVECTOR (menu_items
)->contents
[menu_items_used
++] = name
;
224 XVECTOR (menu_items
)->contents
[menu_items_used
++] = prefix_vec
;
227 /* Push one menu item into the current pane. NAME is the string to
228 display. ENABLE if non-nil means this item can be selected. KEY
229 is the key generated by choosing this item, or nil if this item
230 doesn't really have a definition. DEF is the definition of this
231 item. EQUIV is the textual description of the keyboard equivalent
232 for this item (or nil if none). TYPE is the type of this menu
233 item, one of nil, `toggle' or `radio'. */
236 push_menu_item (name
, enable
, key
, def
, equiv
, type
, selected
, help
)
237 Lisp_Object name
, enable
, key
, def
, equiv
, type
, selected
, help
;
239 if (menu_items_used
+ MENU_ITEMS_ITEM_LENGTH
> menu_items_allocated
)
242 XVECTOR (menu_items
)->contents
[menu_items_used
++] = name
;
243 XVECTOR (menu_items
)->contents
[menu_items_used
++] = enable
;
244 XVECTOR (menu_items
)->contents
[menu_items_used
++] = key
;
245 XVECTOR (menu_items
)->contents
[menu_items_used
++] = equiv
;
246 XVECTOR (menu_items
)->contents
[menu_items_used
++] = def
;
247 XVECTOR (menu_items
)->contents
[menu_items_used
++] = type
;
248 XVECTOR (menu_items
)->contents
[menu_items_used
++] = selected
;
249 XVECTOR (menu_items
)->contents
[menu_items_used
++] = help
;
252 /* Args passed between single_keymap_panes and single_menu_item. */
255 Lisp_Object pending_maps
;
256 int maxdepth
, notreal
;
260 static void single_menu_item
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
,
263 /* This is a recursive subroutine of keymap_panes.
264 It handles one keymap, KEYMAP.
265 The other arguments are passed along
266 or point to local variables of the previous function.
267 If NOTREAL is nonzero, only check for equivalent key bindings, don't
268 evaluate expressions in menu items and don't make any menu.
270 If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
273 single_keymap_panes (keymap
, pane_name
, prefix
, notreal
, maxdepth
)
275 Lisp_Object pane_name
;
283 skp
.pending_maps
= Qnil
;
284 skp
.maxdepth
= maxdepth
;
285 skp
.notreal
= notreal
;
291 push_menu_pane (pane_name
, prefix
);
294 /* Remember index for first item in this pane so we can go back and
295 add a prefix when (if) we see the first button. After that, notbuttons
296 is set to 0, to mark that we have seen a button and all non button
297 items need a prefix. */
298 skp
.notbuttons
= menu_items_used
;
301 GCPRO1 (skp
.pending_maps
);
302 map_keymap_canonical (keymap
, single_menu_item
, Qnil
, &skp
);
305 /* Process now any submenus which want to be panes at this level. */
306 while (CONSP (skp
.pending_maps
))
308 Lisp_Object elt
, eltcdr
, string
;
309 elt
= XCAR (skp
.pending_maps
);
311 string
= XCAR (eltcdr
);
312 /* We no longer discard the @ from the beginning of the string here.
313 Instead, we do this in *menu_show. */
314 single_keymap_panes (Fcar (elt
), string
,
315 XCDR (eltcdr
), notreal
, maxdepth
- 1);
316 skp
.pending_maps
= XCDR (skp
.pending_maps
);
320 /* This is a subroutine of single_keymap_panes that handles one
322 KEY is a key in a keymap and ITEM is its binding.
323 SKP->PENDING_MAPS_PTR is a list of keymaps waiting to be made into
325 If SKP->NOTREAL is nonzero, only check for equivalent key bindings, don't
326 evaluate expressions in menu items and don't make any menu.
327 If we encounter submenus deeper than SKP->MAXDEPTH levels, ignore them. */
330 single_menu_item (key
, item
, dummy
, skp_v
)
331 Lisp_Object key
, item
, dummy
;
334 Lisp_Object map
, item_string
, enabled
;
335 struct gcpro gcpro1
, gcpro2
;
337 struct skp
*skp
= skp_v
;
339 /* Parse the menu item and leave the result in item_properties. */
341 res
= parse_menu_item (item
, skp
->notreal
, 0);
344 return; /* Not a menu item. */
346 map
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_MAP
];
350 /* We don't want to make a menu, just traverse the keymaps to
351 precompute equivalent key bindings. */
353 single_keymap_panes (map
, Qnil
, key
, 1, skp
->maxdepth
- 1);
357 enabled
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_ENABLE
];
358 item_string
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_NAME
];
360 if (!NILP (map
) && SREF (item_string
, 0) == '@')
363 /* An enabled separate pane. Remember this to handle it later. */
364 skp
->pending_maps
= Fcons (Fcons (map
, Fcons (item_string
, key
)),
369 #if defined(HAVE_X_WINDOWS) || defined(MSDOS)
371 /* Simulate radio buttons and toggle boxes by putting a prefix in
374 Lisp_Object prefix
= Qnil
;
375 Lisp_Object type
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_TYPE
];
379 = XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_SELECTED
];
382 /* The first button. Line up previous items in this menu. */
384 int index
= skp
->notbuttons
; /* Index for first item this menu. */
387 while (index
< menu_items_used
)
390 = XVECTOR (menu_items
)->contents
[index
+ MENU_ITEMS_ITEM_NAME
];
394 submenu
++; /* Skip sub menu. */
396 else if (EQ (tem
, Qlambda
))
399 submenu
--; /* End sub menu. */
401 else if (EQ (tem
, Qt
))
402 index
+= 3; /* Skip new pane marker. */
403 else if (EQ (tem
, Qquote
))
404 index
++; /* Skip a left, right divider. */
407 if (!submenu
&& SREF (tem
, 0) != '\0'
408 && SREF (tem
, 0) != '-')
409 XVECTOR (menu_items
)->contents
[index
+ MENU_ITEMS_ITEM_NAME
]
410 = concat2 (build_string (" "), tem
);
411 index
+= MENU_ITEMS_ITEM_LENGTH
;
417 /* Calculate prefix, if any, for this item. */
418 if (EQ (type
, QCtoggle
))
419 prefix
= build_string (NILP (selected
) ? "[ ] " : "[X] ");
420 else if (EQ (type
, QCradio
))
421 prefix
= build_string (NILP (selected
) ? "( ) " : "(*) ");
423 /* Not a button. If we have earlier buttons, then we need a prefix. */
424 else if (!skp
->notbuttons
&& SREF (item_string
, 0) != '\0'
425 && SREF (item_string
, 0) != '-')
426 prefix
= build_string (" ");
429 item_string
= concat2 (prefix
, item_string
);
431 #endif /* not HAVE_BOXES */
433 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
435 /* Indicate visually that this is a submenu. */
436 item_string
= concat2 (item_string
, build_string (" >"));
439 #endif /* HAVE_X_WINDOWS || MSDOS */
441 push_menu_item (item_string
, enabled
, key
,
442 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_DEF
],
443 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_KEYEQ
],
444 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_TYPE
],
445 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_SELECTED
],
446 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_HELP
]);
448 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI)
449 /* Display a submenu using the toolkit. */
450 if (! (NILP (map
) || NILP (enabled
)))
452 push_submenu_start ();
453 single_keymap_panes (map
, Qnil
, key
, 0, skp
->maxdepth
- 1);
459 /* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
460 and generate menu panes for them in menu_items.
461 If NOTREAL is nonzero,
462 don't bother really computing whether an item is enabled. */
465 keymap_panes (keymaps
, nmaps
, notreal
)
466 Lisp_Object
*keymaps
;
474 /* Loop over the given keymaps, making a pane for each map.
475 But don't make a pane that is empty--ignore that map instead.
476 P is the number of panes we have made so far. */
477 for (mapno
= 0; mapno
< nmaps
; mapno
++)
478 single_keymap_panes (keymaps
[mapno
],
479 Fkeymap_prompt (keymaps
[mapno
]), Qnil
, notreal
, 10);
481 finish_menu_items ();
485 /* Push the items in a single pane defined by the alist PANE. */
490 Lisp_Object tail
, item
, item1
;
492 for (tail
= pane
; CONSP (tail
); tail
= XCDR (tail
))
496 push_menu_item (ENCODE_MENU_STRING (item
), Qnil
, Qnil
, Qt
,
497 Qnil
, Qnil
, Qnil
, Qnil
);
498 else if (CONSP (item
))
501 CHECK_STRING (item1
);
502 push_menu_item (ENCODE_MENU_STRING (item1
), Qt
, XCDR (item
),
503 Qt
, Qnil
, Qnil
, Qnil
, Qnil
);
506 push_left_right_boundary ();
511 /* Push all the panes and items of a menu described by the
512 alist-of-alists MENU.
513 This handles old-fashioned calls to x-popup-menu. */
522 for (tail
= menu
; CONSP (tail
); tail
= XCDR (tail
))
524 Lisp_Object elt
, pane_name
, pane_data
;
526 pane_name
= Fcar (elt
);
527 CHECK_STRING (pane_name
);
528 push_menu_pane (ENCODE_MENU_STRING (pane_name
), Qnil
);
529 pane_data
= Fcdr (elt
);
530 CHECK_CONS (pane_data
);
531 list_of_items (pane_data
);
534 finish_menu_items ();
537 /* Set up data in menu_items for a menu bar item
538 whose event type is ITEM_KEY (with string ITEM_NAME)
539 and whose contents come from the list of keymaps MAPS. */
541 parse_single_submenu (item_key
, item_name
, maps
)
542 Lisp_Object item_key
, item_name
, maps
;
548 int top_level_items
= 0;
550 length
= Flength (maps
);
553 /* Convert the list MAPS into a vector MAPVEC. */
554 mapvec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
555 for (i
= 0; i
< len
; i
++)
557 mapvec
[i
] = Fcar (maps
);
561 /* Loop over the given keymaps, making a pane for each map.
562 But don't make a pane that is empty--ignore that map instead. */
563 for (i
= 0; i
< len
; i
++)
565 if (!KEYMAPP (mapvec
[i
]))
567 /* Here we have a command at top level in the menu bar
568 as opposed to a submenu. */
570 push_menu_pane (Qnil
, Qnil
);
571 push_menu_item (item_name
, Qt
, item_key
, mapvec
[i
],
572 Qnil
, Qnil
, Qnil
, Qnil
);
577 prompt
= Fkeymap_prompt (mapvec
[i
]);
578 single_keymap_panes (mapvec
[i
],
579 !NILP (prompt
) ? prompt
: item_name
,
584 return top_level_items
;
588 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI)
590 /* Allocate a widget_value, blocking input. */
593 xmalloc_widget_value ()
598 value
= malloc_widget_value ();
604 /* This recursively calls free_widget_value on the tree of widgets.
605 It must free all data that was malloc'ed for these widget_values.
606 In Emacs, many slots are pointers into the data of Lisp_Strings, and
607 must be left alone. */
610 free_menubar_widget_value_tree (wv
)
615 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
617 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
619 free_menubar_widget_value_tree (wv
->contents
);
620 wv
->contents
= (widget_value
*) 0xDEADBEEF;
624 free_menubar_widget_value_tree (wv
->next
);
625 wv
->next
= (widget_value
*) 0xDEADBEEF;
628 free_widget_value (wv
);
632 /* Create a tree of widget_value objects
633 representing the panes and items
634 in menu_items starting at index START, up to index END. */
637 digest_single_submenu (start
, end
, top_level_items
)
638 int start
, end
, top_level_items
;
640 widget_value
*wv
, *prev_wv
, *save_wv
, *first_wv
;
642 int submenu_depth
= 0;
643 widget_value
**submenu_stack
;
647 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
648 wv
= xmalloc_widget_value ();
652 wv
->button_type
= BUTTON_TYPE_NONE
;
658 /* Loop over all panes and items made by the preceding call
659 to parse_single_submenu and construct a tree of widget_value objects.
660 Ignore the panes and items used by previous calls to
661 digest_single_submenu, even though those are also in menu_items. */
665 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
667 submenu_stack
[submenu_depth
++] = save_wv
;
672 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
675 save_wv
= submenu_stack
[--submenu_depth
];
678 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
)
679 && submenu_depth
!= 0)
680 i
+= MENU_ITEMS_PANE_LENGTH
;
681 /* Ignore a nil in the item list.
682 It's meaningful only for dialog boxes. */
683 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
685 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
687 /* Create a new pane. */
688 Lisp_Object pane_name
, prefix
;
693 pane_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_NAME
];
694 prefix
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
697 if (STRINGP (pane_name
))
699 if (unicode_append_menu
)
700 /* Encode as UTF-8 for now. */
701 pane_name
= ENCODE_UTF_8 (pane_name
);
702 else if (STRING_MULTIBYTE (pane_name
))
703 pane_name
= ENCODE_SYSTEM (pane_name
);
705 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
707 #elif !defined (HAVE_MULTILINGUAL_MENU)
708 if (STRINGP (pane_name
) && STRING_MULTIBYTE (pane_name
))
710 pane_name
= ENCODE_MENU_STRING (pane_name
);
711 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
715 pane_string
= (NILP (pane_name
)
716 ? "" : (char *) SDATA (pane_name
));
717 /* If there is just one top-level pane, put all its items directly
718 under the top-level menu. */
719 if (menu_items_n_panes
== 1)
722 /* If the pane has a meaningful name,
723 make the pane a top-level menu item
724 with its items as a submenu beneath it. */
725 if (strcmp (pane_string
, ""))
727 wv
= xmalloc_widget_value ();
731 first_wv
->contents
= wv
;
732 wv
->lname
= pane_name
;
733 /* Set value to 1 so update_submenu_strings can handle '@' */
734 wv
->value
= (char *)1;
736 wv
->button_type
= BUTTON_TYPE_NONE
;
744 i
+= MENU_ITEMS_PANE_LENGTH
;
748 /* Create a new item within current pane. */
749 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
;
752 /* All items should be contained in panes. */
756 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
757 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
758 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
759 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
760 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
761 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
762 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
765 if (STRINGP (item_name
))
767 if (unicode_append_menu
)
768 item_name
= ENCODE_UTF_8 (item_name
);
769 else if (STRING_MULTIBYTE (item_name
))
770 item_name
= ENCODE_SYSTEM (item_name
);
772 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
775 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
777 descrip
= ENCODE_SYSTEM (descrip
);
778 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
780 #elif !defined (HAVE_MULTILINGUAL_MENU)
781 if (STRING_MULTIBYTE (item_name
))
783 item_name
= ENCODE_MENU_STRING (item_name
);
784 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
787 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
789 descrip
= ENCODE_MENU_STRING (descrip
);
790 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
794 wv
= xmalloc_widget_value ();
798 save_wv
->contents
= wv
;
800 wv
->lname
= item_name
;
804 /* The EMACS_INT cast avoids a warning. There's no problem
805 as long as pointers have enough bits to hold small integers. */
806 wv
->call_data
= (!NILP (def
) ? (void *) (EMACS_INT
) i
: 0);
807 wv
->enabled
= !NILP (enable
);
810 wv
->button_type
= BUTTON_TYPE_NONE
;
811 else if (EQ (type
, QCradio
))
812 wv
->button_type
= BUTTON_TYPE_RADIO
;
813 else if (EQ (type
, QCtoggle
))
814 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
818 wv
->selected
= !NILP (selected
);
819 if (! STRINGP (help
))
826 i
+= MENU_ITEMS_ITEM_LENGTH
;
830 /* If we have just one "menu item"
831 that was originally a button, return it by itself. */
832 if (top_level_items
&& first_wv
->contents
&& first_wv
->contents
->next
== 0)
834 wv
= first_wv
->contents
;
835 free_widget_value (first_wv
);
842 /* Walk through the widget_value tree starting at FIRST_WV and update
843 the char * pointers from the corresponding lisp values.
844 We do this after building the whole tree, since GC may happen while the
845 tree is constructed, and small strings are relocated. So we must wait
846 until no GC can happen before storing pointers into lisp values. */
848 update_submenu_strings (first_wv
)
849 widget_value
*first_wv
;
853 for (wv
= first_wv
; wv
; wv
= wv
->next
)
855 if (STRINGP (wv
->lname
))
857 wv
->name
= (char *) SDATA (wv
->lname
);
859 /* Ignore the @ that means "separate pane".
860 This is a kludge, but this isn't worth more time. */
861 if (wv
->value
== (char *)1)
863 if (wv
->name
[0] == '@')
869 if (STRINGP (wv
->lkey
))
870 wv
->key
= (char *) SDATA (wv
->lkey
);
873 update_submenu_strings (wv
->contents
);
877 /* Find the menu selection and store it in the keyboard buffer.
878 F is the frame the menu is on.
879 MENU_BAR_ITEMS_USED is the length of VECTOR.
880 VECTOR is an array of menu events for the whole menu. */
883 find_and_call_menu_selection (f
, menu_bar_items_used
, vector
, client_data
)
885 int menu_bar_items_used
;
889 Lisp_Object prefix
, entry
;
890 Lisp_Object
*subprefix_stack
;
891 int submenu_depth
= 0;
895 subprefix_stack
= (Lisp_Object
*) alloca (menu_bar_items_used
* sizeof (Lisp_Object
));
899 while (i
< menu_bar_items_used
)
901 if (EQ (XVECTOR (vector
)->contents
[i
], Qnil
))
903 subprefix_stack
[submenu_depth
++] = prefix
;
907 else if (EQ (XVECTOR (vector
)->contents
[i
], Qlambda
))
909 prefix
= subprefix_stack
[--submenu_depth
];
912 else if (EQ (XVECTOR (vector
)->contents
[i
], Qt
))
914 prefix
= XVECTOR (vector
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
915 i
+= MENU_ITEMS_PANE_LENGTH
;
919 entry
= XVECTOR (vector
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
920 /* The EMACS_INT cast avoids a warning. There's no problem
921 as long as pointers have enough bits to hold small integers. */
922 if ((int) (EMACS_INT
) client_data
== i
)
925 struct input_event buf
;
929 XSETFRAME (frame
, f
);
930 buf
.kind
= MENU_BAR_EVENT
;
931 buf
.frame_or_window
= frame
;
933 kbd_buffer_store_event (&buf
);
935 for (j
= 0; j
< submenu_depth
; j
++)
936 if (!NILP (subprefix_stack
[j
]))
938 buf
.kind
= MENU_BAR_EVENT
;
939 buf
.frame_or_window
= frame
;
940 buf
.arg
= subprefix_stack
[j
];
941 kbd_buffer_store_event (&buf
);
946 buf
.kind
= MENU_BAR_EVENT
;
947 buf
.frame_or_window
= frame
;
949 kbd_buffer_store_event (&buf
);
952 buf
.kind
= MENU_BAR_EVENT
;
953 buf
.frame_or_window
= frame
;
955 kbd_buffer_store_event (&buf
);
959 i
+= MENU_ITEMS_ITEM_LENGTH
;
964 #endif /* USE_X_TOOLKIT || USE_GTK || HAVE_NS || HAVE_NTGUI */
967 /* As above, but return the menu selection instead of storing in kb buffer.
968 If keymaps==1, return full prefixes to selection. */
970 find_and_return_menu_selection (FRAME_PTR f
, int keymaps
, void *client_data
)
972 Lisp_Object prefix
, entry
;
974 Lisp_Object
*subprefix_stack
;
975 int submenu_depth
= 0;
977 prefix
= entry
= Qnil
;
980 (Lisp_Object
*)alloca(menu_items_used
* sizeof (Lisp_Object
));
982 while (i
< menu_items_used
)
984 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
986 subprefix_stack
[submenu_depth
++] = prefix
;
990 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
992 prefix
= subprefix_stack
[--submenu_depth
];
995 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
998 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
999 i
+= MENU_ITEMS_PANE_LENGTH
;
1001 /* Ignore a nil in the item list.
1002 It's meaningful only for dialog boxes. */
1003 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1008 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
1009 if ((EMACS_INT
)client_data
== (EMACS_INT
)(&XVECTOR (menu_items
)->contents
[i
]))
1015 entry
= Fcons (entry
, Qnil
);
1017 entry
= Fcons (prefix
, entry
);
1018 for (j
= submenu_depth
- 1; j
>= 0; j
--)
1019 if (!NILP (subprefix_stack
[j
]))
1020 entry
= Fcons (subprefix_stack
[j
], entry
);
1024 i
+= MENU_ITEMS_ITEM_LENGTH
;
1029 #endif /* HAVE_NS */
1034 staticpro (&menu_items
);
1036 menu_items_inuse
= Qnil
;
1039 /* arch-tag: 78bbc7cf-8025-4156-aa8a-6c7fd99bf51d
1040 (do not change this comment) */