diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/xmenu.c | 60 |
1 files changed, 52 insertions, 8 deletions
diff --git a/src/xmenu.c b/src/xmenu.c index 9b93822ecf5..6de1dcb2bd1 100644 --- a/src/xmenu.c +++ b/src/xmenu.c | |||
| @@ -266,14 +266,15 @@ menubar_id_to_frame (id) | |||
| 266 | static void | 266 | static void |
| 267 | init_menu_items () | 267 | init_menu_items () |
| 268 | { | 268 | { |
| 269 | if (!NILP (menu_items_inuse)) | ||
| 270 | error ("Trying to use a menu from within a menu-entry"); | ||
| 271 | |||
| 269 | if (NILP (menu_items)) | 272 | if (NILP (menu_items)) |
| 270 | { | 273 | { |
| 271 | menu_items_allocated = 60; | 274 | menu_items_allocated = 60; |
| 272 | menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil); | 275 | menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil); |
| 273 | } | 276 | } |
| 274 | 277 | ||
| 275 | if (!NILP (menu_items_inuse)) | ||
| 276 | error ("Trying to use a menu from within a menu-entry"); | ||
| 277 | menu_items_inuse = Qt; | 278 | menu_items_inuse = Qt; |
| 278 | menu_items_used = 0; | 279 | menu_items_used = 0; |
| 279 | menu_items_n_panes = 0; | 280 | menu_items_n_panes = 0; |
| @@ -310,6 +311,39 @@ discard_menu_items () | |||
| 310 | xassert (NILP (menu_items_inuse)); | 311 | xassert (NILP (menu_items_inuse)); |
| 311 | } | 312 | } |
| 312 | 313 | ||
| 314 | /* This undoes save_menu_items, and it is called by the specpdl unwind | ||
| 315 | mechanism. */ | ||
| 316 | |||
| 317 | static Lisp_Object | ||
| 318 | restore_menu_items (saved) | ||
| 319 | Lisp_Object saved; | ||
| 320 | { | ||
| 321 | menu_items = XCAR (saved); | ||
| 322 | menu_items_inuse = (! NILP (menu_items) ? Qt : Qnil); | ||
| 323 | menu_items_allocated = (VECTORP (menu_items) ? ASIZE (menu_items) : 0); | ||
| 324 | saved = XCDR (saved); | ||
| 325 | menu_items_used = XINT (XCAR (saved)); | ||
| 326 | saved = XCDR (saved); | ||
| 327 | menu_items_n_panes = XINT (XCAR (saved)); | ||
| 328 | saved = XCDR (saved); | ||
| 329 | menu_items_submenu_depth = XINT (XCAR (saved)); | ||
| 330 | } | ||
| 331 | |||
| 332 | /* Push the whole state of menu_items processing onto the specpdl. | ||
| 333 | It will be restored when the specpdl is unwound. */ | ||
| 334 | |||
| 335 | static void | ||
| 336 | save_menu_items () | ||
| 337 | { | ||
| 338 | Lisp_Object saved = list4 (!NILP (menu_items_inuse) ? menu_items : Qnil, | ||
| 339 | make_number (menu_items_used), | ||
| 340 | make_number (menu_items_n_panes), | ||
| 341 | make_number (menu_items_submenu_depth)); | ||
| 342 | record_unwind_protect (restore_menu_items, saved); | ||
| 343 | menu_items_inuse = Qnil; | ||
| 344 | menu_items = Qnil; | ||
| 345 | } | ||
| 346 | |||
| 313 | /* Make the menu_items vector twice as large. */ | 347 | /* Make the menu_items vector twice as large. */ |
| 314 | 348 | ||
| 315 | static void | 349 | static void |
| @@ -320,6 +354,7 @@ grow_menu_items () | |||
| 320 | old = menu_items; | 354 | old = menu_items; |
| 321 | 355 | ||
| 322 | menu_items_allocated *= 2; | 356 | menu_items_allocated *= 2; |
| 357 | |||
| 323 | menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil); | 358 | menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil); |
| 324 | bcopy (XVECTOR (old)->contents, XVECTOR (menu_items)->contents, | 359 | bcopy (XVECTOR (old)->contents, XVECTOR (menu_items)->contents, |
| 325 | old_size * sizeof (Lisp_Object)); | 360 | old_size * sizeof (Lisp_Object)); |
| @@ -1728,6 +1763,7 @@ digest_single_submenu (start, end, top_level_items) | |||
| 1728 | int i; | 1763 | int i; |
| 1729 | int submenu_depth = 0; | 1764 | int submenu_depth = 0; |
| 1730 | widget_value **submenu_stack; | 1765 | widget_value **submenu_stack; |
| 1766 | int panes_seen = 0; | ||
| 1731 | 1767 | ||
| 1732 | submenu_stack | 1768 | submenu_stack |
| 1733 | = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); | 1769 | = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); |
| @@ -1774,6 +1810,8 @@ digest_single_submenu (start, end, top_level_items) | |||
| 1774 | Lisp_Object pane_name, prefix; | 1810 | Lisp_Object pane_name, prefix; |
| 1775 | char *pane_string; | 1811 | char *pane_string; |
| 1776 | 1812 | ||
| 1813 | panes_seen++; | ||
| 1814 | |||
| 1777 | pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME]; | 1815 | pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME]; |
| 1778 | prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; | 1816 | prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; |
| 1779 | 1817 | ||
| @@ -1821,6 +1859,10 @@ digest_single_submenu (start, end, top_level_items) | |||
| 1821 | Lisp_Object item_name, enable, descrip, def, type, selected; | 1859 | Lisp_Object item_name, enable, descrip, def, type, selected; |
| 1822 | Lisp_Object help; | 1860 | Lisp_Object help; |
| 1823 | 1861 | ||
| 1862 | /* All items should be contained in panes. */ | ||
| 1863 | if (panes_seen == 0) | ||
| 1864 | abort (); | ||
| 1865 | |||
| 1824 | item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME); | 1866 | item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME); |
| 1825 | enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE); | 1867 | enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE); |
| 1826 | descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY); | 1868 | descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY); |
| @@ -2046,7 +2088,6 @@ set_frame_menubar (f, first_time, deep_p) | |||
| 2046 | specbind (Qdebug_on_next_call, Qnil); | 2088 | specbind (Qdebug_on_next_call, Qnil); |
| 2047 | 2089 | ||
| 2048 | record_unwind_save_match_data (); | 2090 | record_unwind_save_match_data (); |
| 2049 | record_unwind_protect (unuse_menu_items, Qnil); | ||
| 2050 | if (NILP (Voverriding_local_map_menu_flag)) | 2091 | if (NILP (Voverriding_local_map_menu_flag)) |
| 2051 | { | 2092 | { |
| 2052 | specbind (Qoverriding_terminal_local_map, Qnil); | 2093 | specbind (Qoverriding_terminal_local_map, Qnil); |
| @@ -2074,6 +2115,8 @@ set_frame_menubar (f, first_time, deep_p) | |||
| 2074 | 2115 | ||
| 2075 | /* Fill in menu_items with the current menu bar contents. | 2116 | /* Fill in menu_items with the current menu bar contents. |
| 2076 | This can evaluate Lisp code. */ | 2117 | This can evaluate Lisp code. */ |
| 2118 | save_menu_items (); | ||
| 2119 | |||
| 2077 | menu_items = f->menu_bar_vector; | 2120 | menu_items = f->menu_bar_vector; |
| 2078 | menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0; | 2121 | menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0; |
| 2079 | submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); | 2122 | submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); |
| @@ -2133,7 +2176,6 @@ set_frame_menubar (f, first_time, deep_p) | |||
| 2133 | } | 2176 | } |
| 2134 | 2177 | ||
| 2135 | set_buffer_internal_1 (prev); | 2178 | set_buffer_internal_1 (prev); |
| 2136 | unbind_to (specpdl_count, Qnil); | ||
| 2137 | 2179 | ||
| 2138 | /* If there has been no change in the Lisp-level contents | 2180 | /* If there has been no change in the Lisp-level contents |
| 2139 | of the menu bar, skip redisplaying it. Just exit. */ | 2181 | of the menu bar, skip redisplaying it. Just exit. */ |
| @@ -2146,10 +2188,15 @@ set_frame_menubar (f, first_time, deep_p) | |||
| 2146 | { | 2188 | { |
| 2147 | free_menubar_widget_value_tree (first_wv); | 2189 | free_menubar_widget_value_tree (first_wv); |
| 2148 | discard_menu_items (); | 2190 | discard_menu_items (); |
| 2149 | 2191 | unbind_to (specpdl_count, Qnil); | |
| 2150 | return; | 2192 | return; |
| 2151 | } | 2193 | } |
| 2152 | 2194 | ||
| 2195 | f->menu_bar_vector = menu_items; | ||
| 2196 | f->menu_bar_items_used = menu_items_used; | ||
| 2197 | |||
| 2198 | unbind_to (specpdl_count, Qnil); | ||
| 2199 | |||
| 2153 | /* Now GC cannot happen during the lifetime of the widget_value, | 2200 | /* Now GC cannot happen during the lifetime of the widget_value, |
| 2154 | so it's safe to store data from a Lisp_String. */ | 2201 | so it's safe to store data from a Lisp_String. */ |
| 2155 | wv = first_wv->contents; | 2202 | wv = first_wv->contents; |
| @@ -2164,9 +2211,6 @@ set_frame_menubar (f, first_time, deep_p) | |||
| 2164 | wv = wv->next; | 2211 | wv = wv->next; |
| 2165 | } | 2212 | } |
| 2166 | 2213 | ||
| 2167 | f->menu_bar_vector = menu_items; | ||
| 2168 | f->menu_bar_items_used = menu_items_used; | ||
| 2169 | discard_menu_items (); | ||
| 2170 | } | 2214 | } |
| 2171 | else | 2215 | else |
| 2172 | { | 2216 | { |