diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/macmenu.c | 58 |
1 files changed, 53 insertions, 5 deletions
diff --git a/src/macmenu.c b/src/macmenu.c index 29233ec0d64..be565f89259 100644 --- a/src/macmenu.c +++ b/src/macmenu.c | |||
| @@ -303,6 +303,37 @@ discard_menu_items () | |||
| 303 | } | 303 | } |
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | /* This undoes save_menu_items, and it is called by the specpdl unwind | ||
| 307 | mechanism. */ | ||
| 308 | |||
| 309 | static Lisp_Object | ||
| 310 | restore_menu_items (saved) | ||
| 311 | Lisp_Object saved; | ||
| 312 | { | ||
| 313 | menu_items = XCAR (saved); | ||
| 314 | menu_items_allocated = (VECTORP (menu_items) ? ASIZE (menu_items) : 0); | ||
| 315 | saved = XCDR (saved); | ||
| 316 | menu_items_used = XINT (XCAR (saved)); | ||
| 317 | saved = XCDR (saved); | ||
| 318 | menu_items_n_panes = XINT (XCAR (saved)); | ||
| 319 | saved = XCDR (saved); | ||
| 320 | menu_items_submenu_depth = XINT (XCAR (saved)); | ||
| 321 | } | ||
| 322 | |||
| 323 | /* Push the whole state of menu_items processing onto the specpdl. | ||
| 324 | It will be restored when the specpdl is unwound. */ | ||
| 325 | |||
| 326 | static void | ||
| 327 | save_menu_items () | ||
| 328 | { | ||
| 329 | Lisp_Object saved = list4 (menu_items, | ||
| 330 | make_number (menu_items_used), | ||
| 331 | make_number (menu_items_n_panes), | ||
| 332 | make_number (menu_items_submenu_depth)); | ||
| 333 | record_unwind_protect (restore_menu_items, saved); | ||
| 334 | menu_items = Qnil; | ||
| 335 | } | ||
| 336 | |||
| 306 | /* Make the menu_items vector twice as large. */ | 337 | /* Make the menu_items vector twice as large. */ |
| 307 | 338 | ||
| 308 | static void | 339 | static void |
| @@ -313,6 +344,7 @@ grow_menu_items () | |||
| 313 | old = menu_items; | 344 | old = menu_items; |
| 314 | 345 | ||
| 315 | menu_items_allocated *= 2; | 346 | menu_items_allocated *= 2; |
| 347 | |||
| 316 | menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil); | 348 | menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil); |
| 317 | bcopy (XVECTOR (old)->contents, XVECTOR (menu_items)->contents, | 349 | bcopy (XVECTOR (old)->contents, XVECTOR (menu_items)->contents, |
| 318 | old_size * sizeof (Lisp_Object)); | 350 | old_size * sizeof (Lisp_Object)); |
| @@ -1185,6 +1217,7 @@ digest_single_submenu (start, end, top_level_items) | |||
| 1185 | int i; | 1217 | int i; |
| 1186 | int submenu_depth = 0; | 1218 | int submenu_depth = 0; |
| 1187 | widget_value **submenu_stack; | 1219 | widget_value **submenu_stack; |
| 1220 | int panes_seen = 0; | ||
| 1188 | 1221 | ||
| 1189 | submenu_stack | 1222 | submenu_stack |
| 1190 | = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); | 1223 | = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); |
| @@ -1231,6 +1264,8 @@ digest_single_submenu (start, end, top_level_items) | |||
| 1231 | Lisp_Object pane_name, prefix; | 1264 | Lisp_Object pane_name, prefix; |
| 1232 | char *pane_string; | 1265 | char *pane_string; |
| 1233 | 1266 | ||
| 1267 | panes_seen++; | ||
| 1268 | |||
| 1234 | pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME]; | 1269 | pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME]; |
| 1235 | prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; | 1270 | prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; |
| 1236 | 1271 | ||
| @@ -1278,6 +1313,10 @@ digest_single_submenu (start, end, top_level_items) | |||
| 1278 | Lisp_Object item_name, enable, descrip, def, type, selected; | 1313 | Lisp_Object item_name, enable, descrip, def, type, selected; |
| 1279 | Lisp_Object help; | 1314 | Lisp_Object help; |
| 1280 | 1315 | ||
| 1316 | /* All items should be contained in panes. */ | ||
| 1317 | if (panes_seen == 0) | ||
| 1318 | abort (); | ||
| 1319 | |||
| 1281 | item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME); | 1320 | item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME); |
| 1282 | enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE); | 1321 | enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE); |
| 1283 | descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY); | 1322 | descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY); |
| @@ -1529,6 +1568,8 @@ set_frame_menubar (f, first_time, deep_p) | |||
| 1529 | 1568 | ||
| 1530 | /* Fill in menu_items with the current menu bar contents. | 1569 | /* Fill in menu_items with the current menu bar contents. |
| 1531 | This can evaluate Lisp code. */ | 1570 | This can evaluate Lisp code. */ |
| 1571 | save_menu_items (); | ||
| 1572 | |||
| 1532 | menu_items = f->menu_bar_vector; | 1573 | menu_items = f->menu_bar_vector; |
| 1533 | menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0; | 1574 | menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0; |
| 1534 | submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); | 1575 | submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); |
| @@ -1588,23 +1629,33 @@ set_frame_menubar (f, first_time, deep_p) | |||
| 1588 | } | 1629 | } |
| 1589 | 1630 | ||
| 1590 | set_buffer_internal_1 (prev); | 1631 | set_buffer_internal_1 (prev); |
| 1591 | unbind_to (specpdl_count, Qnil); | ||
| 1592 | 1632 | ||
| 1593 | /* If there has been no change in the Lisp-level contents | 1633 | /* If there has been no change in the Lisp-level contents |
| 1594 | of the menu bar, skip redisplaying it. Just exit. */ | 1634 | of the menu bar, skip redisplaying it. Just exit. */ |
| 1595 | 1635 | ||
| 1636 | /* Compare the new menu items with the ones computed last time. */ | ||
| 1596 | for (i = 0; i < previous_menu_items_used; i++) | 1637 | for (i = 0; i < previous_menu_items_used; i++) |
| 1597 | if (menu_items_used == i | 1638 | if (menu_items_used == i |
| 1598 | || (!EQ (previous_items[i], XVECTOR (menu_items)->contents[i]))) | 1639 | || (!EQ (previous_items[i], XVECTOR (menu_items)->contents[i]))) |
| 1599 | break; | 1640 | break; |
| 1600 | if (i == menu_items_used && i == previous_menu_items_used && i != 0) | 1641 | if (i == menu_items_used && i == previous_menu_items_used && i != 0) |
| 1601 | { | 1642 | { |
| 1643 | /* The menu items have not changed. Don't bother updating | ||
| 1644 | the menus in any form, since it would be a no-op. */ | ||
| 1602 | free_menubar_widget_value_tree (first_wv); | 1645 | free_menubar_widget_value_tree (first_wv); |
| 1603 | discard_menu_items (); | 1646 | discard_menu_items (); |
| 1604 | 1647 | unbind_to (specpdl_count, Qnil); | |
| 1605 | return; | 1648 | return; |
| 1606 | } | 1649 | } |
| 1607 | 1650 | ||
| 1651 | /* The menu items are different, so store them in the frame. */ | ||
| 1652 | f->menu_bar_vector = menu_items; | ||
| 1653 | f->menu_bar_items_used = menu_items_used; | ||
| 1654 | |||
| 1655 | /* This calls restore_menu_items to restore menu_items, etc., | ||
| 1656 | as they were outside. */ | ||
| 1657 | unbind_to (specpdl_count, Qnil); | ||
| 1658 | |||
| 1608 | /* Now GC cannot happen during the lifetime of the widget_value, | 1659 | /* Now GC cannot happen during the lifetime of the widget_value, |
| 1609 | so it's safe to store data from a Lisp_String. */ | 1660 | so it's safe to store data from a Lisp_String. */ |
| 1610 | wv = first_wv->contents; | 1661 | wv = first_wv->contents; |
| @@ -1619,9 +1670,6 @@ set_frame_menubar (f, first_time, deep_p) | |||
| 1619 | wv = wv->next; | 1670 | wv = wv->next; |
| 1620 | } | 1671 | } |
| 1621 | 1672 | ||
| 1622 | f->menu_bar_vector = menu_items; | ||
| 1623 | f->menu_bar_items_used = menu_items_used; | ||
| 1624 | discard_menu_items (); | ||
| 1625 | } | 1673 | } |
| 1626 | else | 1674 | else |
| 1627 | { | 1675 | { |