Mercurial > emacs
changeset 46753:5e95e401d481
(set_frame_menubar): First parse all submenus,
then make widget_value trees from them.
Don't allocate any widget_value objects
until we are done with the parsing.
(parse_single_submenu): New function.
(digest_single_submenu): New function.
(single_submenu): Function deleted, replaced by those two.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Wed, 31 Jul 2002 06:15:47 +0000 |
parents | 54b975949d6a |
children | ff5741579fc4 |
files | src/xmenu.c |
diffstat | 1 files changed, 66 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/src/xmenu.c Tue Jul 30 20:24:27 2002 +0000 +++ b/src/xmenu.c Wed Jul 31 06:15:47 2002 +0000 @@ -1345,22 +1345,18 @@ UNBLOCK_INPUT; } -/* Return a tree of widget_value structures for a menu bar item +/* Set up data i menu_items for a menu bar item whose event type is ITEM_KEY (with string ITEM_NAME) and whose contents come from the list of keymaps MAPS. */ -static widget_value * -single_submenu (item_key, item_name, maps) +static int +parse_single_submenu (item_key, item_name, maps) Lisp_Object item_key, item_name, maps; { - widget_value *wv, *prev_wv, *save_wv, *first_wv; - int i; - int submenu_depth = 0; Lisp_Object length; int len; Lisp_Object *mapvec; - widget_value **submenu_stack; - int previous_items = menu_items_used; + int i; int top_level_items = 0; length = Flength (maps); @@ -1374,8 +1370,6 @@ maps = Fcdr (maps); } - menu_items_n_panes = 0; - /* Loop over the given keymaps, making a pane for each map. But don't make a pane that is empty--ignore that map instead. */ for (i = 0; i < len; i++) @@ -1394,8 +1388,21 @@ single_keymap_panes (mapvec[i], item_name, item_key, 0, 10); } - /* Create a tree of widget_value objects - representing the panes and their items. */ + return top_level_items; +} + +/* Create a tree of widget_value objects + representing the panes and items + in menu_items starting at index START, up to index END. */ + +static widget_value * +digest_single_submenu (start, end, top_level_items) + int start, end; +{ + widget_value *wv, *prev_wv, *save_wv, *first_wv; + int i; + int submenu_depth = 0; + widget_value **submenu_stack; submenu_stack = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); @@ -1413,8 +1420,8 @@ and construct a tree of widget_value objects. Ignore the panes and items made by previous calls to single_submenu, even though those are also in menu_items. */ - i = previous_items; - while (i < menu_items_used) + i = start; + while (i < end) { if (EQ (XVECTOR (menu_items)->contents[i], Qnil)) { @@ -1558,8 +1565,6 @@ return first_wv; } - - /* Recompute all the widgets of frame F, when the menu bar has been changed. Value is non-zero if widgets were updated. */ @@ -1618,7 +1623,9 @@ Widget menubar_widget = f->output_data.x->menubar_widget; Lisp_Object items; widget_value *wv, *first_wv, *prev_wv = 0; - int i; + int i, last_i; + int *submenu_start, *submenu_end; + int *submenu_top_level_items; LWLIB_ID id; @@ -1640,14 +1647,6 @@ f->output_data.x->saved_menu_event->type = 0; } - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; - wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; - first_wv = wv; - if (deep_p) { /* Make a widget-value tree representing the entire menu trees. */ @@ -1692,28 +1691,58 @@ items = FRAME_MENU_BAR_ITEMS (f); - inhibit_garbage_collection (); - /* Save the frame's previous menu bar contents data. */ if (previous_menu_items_used) bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items, previous_menu_items_used * sizeof (Lisp_Object)); - /* Fill in the current menu bar contents. */ + /* Fill in menu_items with the current menu bar contents. + This can evaluate Lisp code. */ menu_items = f->menu_bar_vector; menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0; + submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); + submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); + submenu_top_level_items + = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); init_menu_items (); for (i = 0; i < XVECTOR (items)->size; i += 4) { Lisp_Object key, string, maps; + last_i = i; + key = XVECTOR (items)->contents[i]; string = XVECTOR (items)->contents[i + 1]; maps = XVECTOR (items)->contents[i + 2]; if (NILP (string)) break; - wv = single_submenu (key, string, maps); + submenu_start[i] = menu_items_used; + + menu_items_n_panes = 0; + submenu_top_level_items[i] + = parse_single_submenu (key, string, maps); + + submenu_end[i] = menu_items_used; + } + + finish_menu_items (); + + /* Convert menu_items into widget_value trees + to display the menu. This cannot evaluate Lisp code. */ + + wv = xmalloc_widget_value (); + wv->name = "menubar"; + wv->value = 0; + wv->enabled = 1; + wv->button_type = BUTTON_TYPE_NONE; + wv->help = Qnil; + first_wv = wv; + + for (i = 0; i < last_i; i += 4) + { + wv = digest_single_submenu (submenu_start[i], submenu_end[i], + submenu_top_level_items[i]); if (prev_wv) prev_wv->next = wv; else @@ -1724,8 +1753,6 @@ prev_wv = wv; } - finish_menu_items (); - set_buffer_internal_1 (prev); unbind_to (specpdl_count, Qnil); @@ -1766,6 +1793,14 @@ /* Make a widget-value tree containing just the top level menu bar strings. */ + wv = xmalloc_widget_value (); + wv->name = "menubar"; + wv->value = 0; + wv->enabled = 1; + wv->button_type = BUTTON_TYPE_NONE; + wv->help = Qnil; + first_wv = wv; + items = FRAME_MENU_BAR_ITEMS (f); for (i = 0; i < XVECTOR (items)->size; i += 4) {