# HG changeset patch # User Richard M. Stallman # Date 1145394076 0 # Node ID 93e99c27012e43222c8e7a51db0f03c115ff10b3 # Parent e15a29aaffbd3ad06d8a6d2f1fbb30cc42930ba3 (restore_menu_items, save_menu_items): New fns. (set_frame_menubar): Use save_menu_items. Save updated vector in the frame before unwinding it. Don't use unuse_menu_items. Don't use discard_menu_items. (digest_single_submenu): Abort if an item is not in a pane. (init_menu_items): Put the error check at the top. diff -r e15a29aaffbd -r 93e99c27012e src/xmenu.c --- a/src/xmenu.c Tue Apr 18 21:00:44 2006 +0000 +++ b/src/xmenu.c Tue Apr 18 21:01:16 2006 +0000 @@ -266,14 +266,15 @@ static void init_menu_items () { + if (!NILP (menu_items_inuse)) + error ("Trying to use a menu from within a menu-entry"); + if (NILP (menu_items)) { menu_items_allocated = 60; menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil); } - if (!NILP (menu_items_inuse)) - error ("Trying to use a menu from within a menu-entry"); menu_items_inuse = Qt; menu_items_used = 0; menu_items_n_panes = 0; @@ -310,6 +311,39 @@ xassert (NILP (menu_items_inuse)); } +/* This undoes save_menu_items, and it is called by the specpdl unwind + mechanism. */ + +static Lisp_Object +restore_menu_items (saved) + Lisp_Object saved; +{ + menu_items = XCAR (saved); + menu_items_inuse = (! NILP (menu_items) ? Qt : Qnil); + menu_items_allocated = (VECTORP (menu_items) ? ASIZE (menu_items) : 0); + saved = XCDR (saved); + menu_items_used = XINT (XCAR (saved)); + saved = XCDR (saved); + menu_items_n_panes = XINT (XCAR (saved)); + saved = XCDR (saved); + menu_items_submenu_depth = XINT (XCAR (saved)); +} + +/* Push the whole state of menu_items processing onto the specpdl. + It will be restored when the specpdl is unwound. */ + +static void +save_menu_items () +{ + Lisp_Object saved = list4 (!NILP (menu_items_inuse) ? menu_items : Qnil, + make_number (menu_items_used), + make_number (menu_items_n_panes), + make_number (menu_items_submenu_depth)); + record_unwind_protect (restore_menu_items, saved); + menu_items_inuse = Qnil; + menu_items = Qnil; +} + /* Make the menu_items vector twice as large. */ static void @@ -320,6 +354,7 @@ old = menu_items; menu_items_allocated *= 2; + menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil); bcopy (XVECTOR (old)->contents, XVECTOR (menu_items)->contents, old_size * sizeof (Lisp_Object)); @@ -1728,6 +1763,7 @@ int i; int submenu_depth = 0; widget_value **submenu_stack; + int panes_seen = 0; submenu_stack = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); @@ -1774,6 +1810,8 @@ Lisp_Object pane_name, prefix; char *pane_string; + panes_seen++; + pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME]; prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; @@ -1821,6 +1859,10 @@ Lisp_Object item_name, enable, descrip, def, type, selected; Lisp_Object help; + /* All items should be contained in panes. */ + if (panes_seen == 0) + abort (); + item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME); enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE); descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY); @@ -2046,7 +2088,6 @@ specbind (Qdebug_on_next_call, Qnil); record_unwind_save_match_data (); - record_unwind_protect (unuse_menu_items, Qnil); if (NILP (Voverriding_local_map_menu_flag)) { specbind (Qoverriding_terminal_local_map, Qnil); @@ -2074,6 +2115,8 @@ /* Fill in menu_items with the current menu bar contents. This can evaluate Lisp code. */ + save_menu_items (); + 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 *)); @@ -2133,7 +2176,6 @@ } set_buffer_internal_1 (prev); - unbind_to (specpdl_count, Qnil); /* If there has been no change in the Lisp-level contents of the menu bar, skip redisplaying it. Just exit. */ @@ -2146,10 +2188,15 @@ { free_menubar_widget_value_tree (first_wv); discard_menu_items (); - + unbind_to (specpdl_count, Qnil); return; } + f->menu_bar_vector = menu_items; + f->menu_bar_items_used = menu_items_used; + + unbind_to (specpdl_count, Qnil); + /* Now GC cannot happen during the lifetime of the widget_value, so it's safe to store data from a Lisp_String. */ wv = first_wv->contents; @@ -2164,9 +2211,6 @@ wv = wv->next; } - f->menu_bar_vector = menu_items; - f->menu_bar_items_used = menu_items_used; - discard_menu_items (); } else {