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"
40 /* Definitions copied from lwlib.h */
41 typedef void * XtPointer
;
50 /* This structure is based on the one in ../lwlib/lwlib.h */
51 typedef struct _widget_value
61 enum button_type button_type
;
63 struct _widget_value
* contents
;
65 struct _widget_value
* next
;
68 /* Local memory management */
69 #define local_heap (GetProcessHeap ())
70 #define local_alloc(n) (HeapAlloc (local_heap, HEAP_ZERO_MEMORY, (n)))
71 #define local_free(p) (HeapFree (local_heap, 0, ((LPVOID) (p))))
73 #define malloc_widget_value() ((widget_value *) local_alloc (sizeof (widget_value)))
74 #define free_widget_value(wv) (local_free ((wv)))
76 extern AppendMenuW_Proc unicode_append_menu
;
78 #endif /* HAVE_NTGUI */
81 /* Define HAVE_BOXES if menus can handle radio and toggle buttons. */
82 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
86 extern Lisp_Object QCtoggle
, QCradio
;
88 Lisp_Object menu_items
;
90 /* If non-nil, means that the global vars defined here are already in use.
91 Used to detect cases where we try to re-enter this non-reentrant code. */
92 Lisp_Object menu_items_inuse
;
94 /* Number of slots currently allocated in menu_items. */
95 int menu_items_allocated
;
97 /* This is the index in menu_items of the first empty slot. */
100 /* The number of panes currently recorded in menu_items,
101 excluding those within submenus. */
102 int menu_items_n_panes
;
104 /* Current depth within submenus. */
105 static int menu_items_submenu_depth
;
110 if (!NILP (menu_items_inuse
))
111 error ("Trying to use a menu from within a menu-entry");
113 if (NILP (menu_items
))
115 menu_items_allocated
= 60;
116 menu_items
= Fmake_vector (make_number (menu_items_allocated
), Qnil
);
119 menu_items_inuse
= Qt
;
121 menu_items_n_panes
= 0;
122 menu_items_submenu_depth
= 0;
125 /* Call at the end of generating the data in menu_items. */
133 unuse_menu_items (dummy
)
136 return menu_items_inuse
= Qnil
;
139 /* Call when finished using the data for the current menu
143 discard_menu_items ()
145 /* Free the structure if it is especially large.
146 Otherwise, hold on to it, to save time. */
147 if (menu_items_allocated
> 200)
150 menu_items_allocated
= 0;
152 xassert (NILP (menu_items_inuse
));
155 /* This undoes save_menu_items, and it is called by the specpdl unwind
159 restore_menu_items (saved
)
162 menu_items
= XCAR (saved
);
163 menu_items_inuse
= (! NILP (menu_items
) ? Qt
: Qnil
);
164 menu_items_allocated
= (VECTORP (menu_items
) ? ASIZE (menu_items
) : 0);
165 saved
= XCDR (saved
);
166 menu_items_used
= XINT (XCAR (saved
));
167 saved
= XCDR (saved
);
168 menu_items_n_panes
= XINT (XCAR (saved
));
169 saved
= XCDR (saved
);
170 menu_items_submenu_depth
= XINT (XCAR (saved
));
174 /* Push the whole state of menu_items processing onto the specpdl.
175 It will be restored when the specpdl is unwound. */
180 Lisp_Object saved
= list4 (!NILP (menu_items_inuse
) ? menu_items
: Qnil
,
181 make_number (menu_items_used
),
182 make_number (menu_items_n_panes
),
183 make_number (menu_items_submenu_depth
));
184 record_unwind_protect (restore_menu_items
, saved
);
185 menu_items_inuse
= Qnil
;
190 /* Make the menu_items vector twice as large. */
195 menu_items_allocated
*= 2;
196 menu_items
= larger_vector (menu_items
, menu_items_allocated
, Qnil
);
199 /* Begin a submenu. */
202 push_submenu_start ()
204 if (menu_items_used
+ 1 > menu_items_allocated
)
207 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qnil
;
208 menu_items_submenu_depth
++;
216 if (menu_items_used
+ 1 > menu_items_allocated
)
219 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qlambda
;
220 menu_items_submenu_depth
--;
223 /* Indicate boundary between left and right. */
226 push_left_right_boundary ()
228 if (menu_items_used
+ 1 > menu_items_allocated
)
231 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qquote
;
234 /* Start a new menu pane in menu_items.
235 NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */
238 push_menu_pane (name
, prefix_vec
)
239 Lisp_Object name
, prefix_vec
;
241 if (menu_items_used
+ MENU_ITEMS_PANE_LENGTH
> menu_items_allocated
)
244 if (menu_items_submenu_depth
== 0)
245 menu_items_n_panes
++;
246 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qt
;
247 XVECTOR (menu_items
)->contents
[menu_items_used
++] = name
;
248 XVECTOR (menu_items
)->contents
[menu_items_used
++] = prefix_vec
;
251 /* Push one menu item into the current pane. NAME is the string to
252 display. ENABLE if non-nil means this item can be selected. KEY
253 is the key generated by choosing this item, or nil if this item
254 doesn't really have a definition. DEF is the definition of this
255 item. EQUIV is the textual description of the keyboard equivalent
256 for this item (or nil if none). TYPE is the type of this menu
257 item, one of nil, `toggle' or `radio'. */
260 push_menu_item (name
, enable
, key
, def
, equiv
, type
, selected
, help
)
261 Lisp_Object name
, enable
, key
, def
, equiv
, type
, selected
, help
;
263 if (menu_items_used
+ MENU_ITEMS_ITEM_LENGTH
> menu_items_allocated
)
266 XVECTOR (menu_items
)->contents
[menu_items_used
++] = name
;
267 XVECTOR (menu_items
)->contents
[menu_items_used
++] = enable
;
268 XVECTOR (menu_items
)->contents
[menu_items_used
++] = key
;
269 XVECTOR (menu_items
)->contents
[menu_items_used
++] = equiv
;
270 XVECTOR (menu_items
)->contents
[menu_items_used
++] = def
;
271 XVECTOR (menu_items
)->contents
[menu_items_used
++] = type
;
272 XVECTOR (menu_items
)->contents
[menu_items_used
++] = selected
;
273 XVECTOR (menu_items
)->contents
[menu_items_used
++] = help
;
276 /* Args passed between single_keymap_panes and single_menu_item. */
279 Lisp_Object pending_maps
;
280 int maxdepth
, notreal
;
284 static void single_menu_item
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
,
287 /* This is a recursive subroutine of keymap_panes.
288 It handles one keymap, KEYMAP.
289 The other arguments are passed along
290 or point to local variables of the previous function.
291 If NOTREAL is nonzero, only check for equivalent key bindings, don't
292 evaluate expressions in menu items and don't make any menu.
294 If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
297 single_keymap_panes (keymap
, pane_name
, prefix
, notreal
, maxdepth
)
299 Lisp_Object pane_name
;
307 skp
.pending_maps
= Qnil
;
308 skp
.maxdepth
= maxdepth
;
309 skp
.notreal
= notreal
;
315 push_menu_pane (pane_name
, prefix
);
318 /* Remember index for first item in this pane so we can go back and
319 add a prefix when (if) we see the first button. After that, notbuttons
320 is set to 0, to mark that we have seen a button and all non button
321 items need a prefix. */
322 skp
.notbuttons
= menu_items_used
;
325 GCPRO1 (skp
.pending_maps
);
326 map_keymap_canonical (keymap
, single_menu_item
, Qnil
, &skp
);
329 /* Process now any submenus which want to be panes at this level. */
330 while (CONSP (skp
.pending_maps
))
332 Lisp_Object elt
, eltcdr
, string
;
333 elt
= XCAR (skp
.pending_maps
);
335 string
= XCAR (eltcdr
);
336 /* We no longer discard the @ from the beginning of the string here.
337 Instead, we do this in *menu_show. */
338 single_keymap_panes (Fcar (elt
), string
,
339 XCDR (eltcdr
), notreal
, maxdepth
- 1);
340 skp
.pending_maps
= XCDR (skp
.pending_maps
);
344 /* This is a subroutine of single_keymap_panes that handles one
346 KEY is a key in a keymap and ITEM is its binding.
347 SKP->PENDING_MAPS_PTR is a list of keymaps waiting to be made into
349 If SKP->NOTREAL is nonzero, only check for equivalent key bindings, don't
350 evaluate expressions in menu items and don't make any menu.
351 If we encounter submenus deeper than SKP->MAXDEPTH levels, ignore them. */
354 single_menu_item (key
, item
, dummy
, skp_v
)
355 Lisp_Object key
, item
, dummy
;
358 Lisp_Object map
, item_string
, enabled
;
359 struct gcpro gcpro1
, gcpro2
;
361 struct skp
*skp
= skp_v
;
363 /* Parse the menu item and leave the result in item_properties. */
365 res
= parse_menu_item (item
, skp
->notreal
, 0);
368 return; /* Not a menu item. */
370 map
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_MAP
];
374 /* We don't want to make a menu, just traverse the keymaps to
375 precompute equivalent key bindings. */
377 single_keymap_panes (map
, Qnil
, key
, 1, skp
->maxdepth
- 1);
381 enabled
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_ENABLE
];
382 item_string
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_NAME
];
384 if (!NILP (map
) && SREF (item_string
, 0) == '@')
387 /* An enabled separate pane. Remember this to handle it later. */
388 skp
->pending_maps
= Fcons (Fcons (map
, Fcons (item_string
, key
)),
393 #ifdef HAVE_X_WINDOWS
395 /* Simulate radio buttons and toggle boxes by putting a prefix in
398 Lisp_Object prefix
= Qnil
;
399 Lisp_Object type
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_TYPE
];
403 = XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_SELECTED
];
406 /* The first button. Line up previous items in this menu. */
408 int index
= skp
->notbuttons
; /* Index for first item this menu. */
411 while (index
< menu_items_used
)
414 = XVECTOR (menu_items
)->contents
[index
+ MENU_ITEMS_ITEM_NAME
];
418 submenu
++; /* Skip sub menu. */
420 else if (EQ (tem
, Qlambda
))
423 submenu
--; /* End sub menu. */
425 else if (EQ (tem
, Qt
))
426 index
+= 3; /* Skip new pane marker. */
427 else if (EQ (tem
, Qquote
))
428 index
++; /* Skip a left, right divider. */
431 if (!submenu
&& SREF (tem
, 0) != '\0'
432 && SREF (tem
, 0) != '-')
433 XVECTOR (menu_items
)->contents
[index
+ MENU_ITEMS_ITEM_NAME
]
434 = concat2 (build_string (" "), tem
);
435 index
+= MENU_ITEMS_ITEM_LENGTH
;
441 /* Calculate prefix, if any, for this item. */
442 if (EQ (type
, QCtoggle
))
443 prefix
= build_string (NILP (selected
) ? "[ ] " : "[X] ");
444 else if (EQ (type
, QCradio
))
445 prefix
= build_string (NILP (selected
) ? "( ) " : "(*) ");
447 /* Not a button. If we have earlier buttons, then we need a prefix. */
448 else if (!skp
->notbuttons
&& SREF (item_string
, 0) != '\0'
449 && SREF (item_string
, 0) != '-')
450 prefix
= build_string (" ");
453 item_string
= concat2 (prefix
, item_string
);
455 #endif /* not HAVE_BOXES */
457 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
459 /* Indicate visually that this is a submenu. */
460 item_string
= concat2 (item_string
, build_string (" >"));
463 #endif /* HAVE_X_WINDOWS */
465 push_menu_item (item_string
, enabled
, key
,
466 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_DEF
],
467 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_KEYEQ
],
468 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_TYPE
],
469 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_SELECTED
],
470 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_HELP
]);
472 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
473 /* Display a submenu using the toolkit. */
474 if (! (NILP (map
) || NILP (enabled
)))
476 push_submenu_start ();
477 single_keymap_panes (map
, Qnil
, key
, 0, skp
->maxdepth
- 1);
483 /* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
484 and generate menu panes for them in menu_items.
485 If NOTREAL is nonzero,
486 don't bother really computing whether an item is enabled. */
489 keymap_panes (keymaps
, nmaps
, notreal
)
490 Lisp_Object
*keymaps
;
498 /* Loop over the given keymaps, making a pane for each map.
499 But don't make a pane that is empty--ignore that map instead.
500 P is the number of panes we have made so far. */
501 for (mapno
= 0; mapno
< nmaps
; mapno
++)
502 single_keymap_panes (keymaps
[mapno
],
503 Fkeymap_prompt (keymaps
[mapno
]), Qnil
, notreal
, 10);
505 finish_menu_items ();
509 /* Push the items in a single pane defined by the alist PANE. */
514 Lisp_Object tail
, item
, item1
;
516 for (tail
= pane
; CONSP (tail
); tail
= XCDR (tail
))
520 push_menu_item (ENCODE_MENU_STRING (item
), Qnil
, Qnil
, Qt
,
521 Qnil
, Qnil
, Qnil
, Qnil
);
522 else if (CONSP (item
))
525 CHECK_STRING (item1
);
526 push_menu_item (ENCODE_MENU_STRING (item1
), Qt
, XCDR (item
),
527 Qt
, Qnil
, Qnil
, Qnil
, Qnil
);
530 push_left_right_boundary ();
535 /* Push all the panes and items of a menu described by the
536 alist-of-alists MENU.
537 This handles old-fashioned calls to x-popup-menu. */
546 for (tail
= menu
; CONSP (tail
); tail
= XCDR (tail
))
548 Lisp_Object elt
, pane_name
, pane_data
;
550 pane_name
= Fcar (elt
);
551 CHECK_STRING (pane_name
);
552 push_menu_pane (ENCODE_MENU_STRING (pane_name
), Qnil
);
553 pane_data
= Fcdr (elt
);
554 CHECK_CONS (pane_data
);
555 list_of_items (pane_data
);
558 finish_menu_items ();
561 /* Set up data in menu_items for a menu bar item
562 whose event type is ITEM_KEY (with string ITEM_NAME)
563 and whose contents come from the list of keymaps MAPS. */
565 parse_single_submenu (item_key
, item_name
, maps
)
566 Lisp_Object item_key
, item_name
, maps
;
572 int top_level_items
= 0;
574 length
= Flength (maps
);
577 /* Convert the list MAPS into a vector MAPVEC. */
578 mapvec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
579 for (i
= 0; i
< len
; i
++)
581 mapvec
[i
] = Fcar (maps
);
585 /* Loop over the given keymaps, making a pane for each map.
586 But don't make a pane that is empty--ignore that map instead. */
587 for (i
= 0; i
< len
; i
++)
589 if (!KEYMAPP (mapvec
[i
]))
591 /* Here we have a command at top level in the menu bar
592 as opposed to a submenu. */
594 push_menu_pane (Qnil
, Qnil
);
595 push_menu_item (item_name
, Qt
, item_key
, mapvec
[i
],
596 Qnil
, Qnil
, Qnil
, Qnil
);
601 prompt
= Fkeymap_prompt (mapvec
[i
]);
602 single_keymap_panes (mapvec
[i
],
603 !NILP (prompt
) ? prompt
: item_name
,
608 return top_level_items
;
612 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
614 /* Allocate a widget_value, blocking input. */
617 xmalloc_widget_value ()
622 value
= malloc_widget_value ();
628 /* This recursively calls free_widget_value on the tree of widgets.
629 It must free all data that was malloc'ed for these widget_values.
630 In Emacs, many slots are pointers into the data of Lisp_Strings, and
631 must be left alone. */
634 free_menubar_widget_value_tree (wv
)
639 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
641 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
643 free_menubar_widget_value_tree (wv
->contents
);
644 wv
->contents
= (widget_value
*) 0xDEADBEEF;
648 free_menubar_widget_value_tree (wv
->next
);
649 wv
->next
= (widget_value
*) 0xDEADBEEF;
652 free_widget_value (wv
);
656 /* Create a tree of widget_value objects
657 representing the panes and items
658 in menu_items starting at index START, up to index END. */
661 digest_single_submenu (start
, end
, top_level_items
)
662 int start
, end
, top_level_items
;
664 widget_value
*wv
, *prev_wv
, *save_wv
, *first_wv
;
666 int submenu_depth
= 0;
667 widget_value
**submenu_stack
;
671 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
672 wv
= xmalloc_widget_value ();
676 wv
->button_type
= BUTTON_TYPE_NONE
;
682 /* Loop over all panes and items made by the preceding call
683 to parse_single_submenu and construct a tree of widget_value objects.
684 Ignore the panes and items used by previous calls to
685 digest_single_submenu, even though those are also in menu_items. */
689 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
691 submenu_stack
[submenu_depth
++] = save_wv
;
696 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
699 save_wv
= submenu_stack
[--submenu_depth
];
702 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
)
703 && submenu_depth
!= 0)
704 i
+= MENU_ITEMS_PANE_LENGTH
;
705 /* Ignore a nil in the item list.
706 It's meaningful only for dialog boxes. */
707 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
709 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
711 /* Create a new pane. */
712 Lisp_Object pane_name
, prefix
;
717 pane_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_NAME
];
718 prefix
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
721 if (STRINGP (pane_name
))
723 if (unicode_append_menu
)
724 /* Encode as UTF-8 for now. */
725 pane_name
= ENCODE_UTF_8 (pane_name
);
726 else if (STRING_MULTIBYTE (pane_name
))
727 pane_name
= ENCODE_SYSTEM (pane_name
);
729 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
731 #elif !defined (HAVE_MULTILINGUAL_MENU)
732 if (STRINGP (pane_name
) && STRING_MULTIBYTE (pane_name
))
734 pane_name
= ENCODE_MENU_STRING (pane_name
);
735 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
739 pane_string
= (NILP (pane_name
)
740 ? "" : (char *) SDATA (pane_name
));
741 /* If there is just one top-level pane, put all its items directly
742 under the top-level menu. */
743 if (menu_items_n_panes
== 1)
746 /* If the pane has a meaningful name,
747 make the pane a top-level menu item
748 with its items as a submenu beneath it. */
749 if (strcmp (pane_string
, ""))
751 wv
= xmalloc_widget_value ();
755 first_wv
->contents
= wv
;
756 wv
->lname
= pane_name
;
757 /* Set value to 1 so update_submenu_strings can handle '@' */
758 wv
->value
= (char *)1;
760 wv
->button_type
= BUTTON_TYPE_NONE
;
768 i
+= MENU_ITEMS_PANE_LENGTH
;
772 /* Create a new item within current pane. */
773 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
;
776 /* All items should be contained in panes. */
780 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
781 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
782 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
783 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
784 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
785 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
786 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
789 if (STRINGP (item_name
))
791 if (unicode_append_menu
)
792 item_name
= ENCODE_UTF_8 (item_name
);
793 else if (STRING_MULTIBYTE (item_name
))
794 item_name
= ENCODE_SYSTEM (item_name
);
796 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
799 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
801 descrip
= ENCODE_SYSTEM (descrip
);
802 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
804 #elif !defined (HAVE_MULTILINGUAL_MENU)
805 if (STRING_MULTIBYTE (item_name
))
807 item_name
= ENCODE_MENU_STRING (item_name
);
808 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
811 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
813 descrip
= ENCODE_MENU_STRING (descrip
);
814 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
818 wv
= xmalloc_widget_value ();
822 save_wv
->contents
= wv
;
824 wv
->lname
= item_name
;
828 /* The EMACS_INT cast avoids a warning. There's no problem
829 as long as pointers have enough bits to hold small integers. */
830 wv
->call_data
= (!NILP (def
) ? (void *) (EMACS_INT
) i
: 0);
831 wv
->enabled
= !NILP (enable
);
834 wv
->button_type
= BUTTON_TYPE_NONE
;
835 else if (EQ (type
, QCradio
))
836 wv
->button_type
= BUTTON_TYPE_RADIO
;
837 else if (EQ (type
, QCtoggle
))
838 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
842 wv
->selected
= !NILP (selected
);
843 if (! STRINGP (help
))
850 i
+= MENU_ITEMS_ITEM_LENGTH
;
854 /* If we have just one "menu item"
855 that was originally a button, return it by itself. */
856 if (top_level_items
&& first_wv
->contents
&& first_wv
->contents
->next
== 0)
858 wv
= first_wv
->contents
;
859 free_widget_value (first_wv
);
866 /* Walk through the widget_value tree starting at FIRST_WV and update
867 the char * pointers from the corresponding lisp values.
868 We do this after building the whole tree, since GC may happen while the
869 tree is constructed, and small strings are relocated. So we must wait
870 until no GC can happen before storing pointers into lisp values. */
872 update_submenu_strings (first_wv
)
873 widget_value
*first_wv
;
877 for (wv
= first_wv
; wv
; wv
= wv
->next
)
879 if (STRINGP (wv
->lname
))
881 wv
->name
= (char *) SDATA (wv
->lname
);
883 /* Ignore the @ that means "separate pane".
884 This is a kludge, but this isn't worth more time. */
885 if (wv
->value
== (char *)1)
887 if (wv
->name
[0] == '@')
893 if (STRINGP (wv
->lkey
))
894 wv
->key
= (char *) SDATA (wv
->lkey
);
897 update_submenu_strings (wv
->contents
);
901 /* Find the menu selection and store it in the keyboard buffer.
902 F is the frame the menu is on.
903 MENU_BAR_ITEMS_USED is the length of VECTOR.
904 VECTOR is an array of menu events for the whole menu. */
907 find_and_call_menu_selection (f
, menu_bar_items_used
, vector
, client_data
)
909 EMACS_INT menu_bar_items_used
;
913 Lisp_Object prefix
, entry
;
914 Lisp_Object
*subprefix_stack
;
915 int submenu_depth
= 0;
919 subprefix_stack
= (Lisp_Object
*) alloca (menu_bar_items_used
* sizeof (Lisp_Object
));
923 while (i
< menu_bar_items_used
)
925 if (EQ (XVECTOR (vector
)->contents
[i
], Qnil
))
927 subprefix_stack
[submenu_depth
++] = prefix
;
931 else if (EQ (XVECTOR (vector
)->contents
[i
], Qlambda
))
933 prefix
= subprefix_stack
[--submenu_depth
];
936 else if (EQ (XVECTOR (vector
)->contents
[i
], Qt
))
938 prefix
= XVECTOR (vector
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
939 i
+= MENU_ITEMS_PANE_LENGTH
;
943 entry
= XVECTOR (vector
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
944 /* The EMACS_INT cast avoids a warning. There's no problem
945 as long as pointers have enough bits to hold small integers. */
946 if ((int) (EMACS_INT
) client_data
== i
)
949 struct input_event buf
;
953 XSETFRAME (frame
, f
);
954 buf
.kind
= MENU_BAR_EVENT
;
955 buf
.frame_or_window
= frame
;
957 kbd_buffer_store_event (&buf
);
959 for (j
= 0; j
< submenu_depth
; j
++)
960 if (!NILP (subprefix_stack
[j
]))
962 buf
.kind
= MENU_BAR_EVENT
;
963 buf
.frame_or_window
= frame
;
964 buf
.arg
= subprefix_stack
[j
];
965 kbd_buffer_store_event (&buf
);
970 buf
.kind
= MENU_BAR_EVENT
;
971 buf
.frame_or_window
= frame
;
973 kbd_buffer_store_event (&buf
);
976 buf
.kind
= MENU_BAR_EVENT
;
977 buf
.frame_or_window
= frame
;
979 kbd_buffer_store_event (&buf
);
983 i
+= MENU_ITEMS_ITEM_LENGTH
;
988 #endif /* USE_X_TOOLKIT || USE_GTK || HAVE_NTGUI */
993 staticpro (&menu_items
);
995 menu_items_inuse
= Qnil
;