Mercurial > emacs
comparison src/xmenu.c @ 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 | 40db0673e6f0 |
children | 6a09e4b41337 |
comparison
equal
deleted
inserted
replaced
46752:54b975949d6a | 46753:5e95e401d481 |
---|---|
1343 BLOCK_INPUT; | 1343 BLOCK_INPUT; |
1344 free_widget_value (wv); | 1344 free_widget_value (wv); |
1345 UNBLOCK_INPUT; | 1345 UNBLOCK_INPUT; |
1346 } | 1346 } |
1347 | 1347 |
1348 /* Return a tree of widget_value structures for a menu bar item | 1348 /* Set up data i menu_items for a menu bar item |
1349 whose event type is ITEM_KEY (with string ITEM_NAME) | 1349 whose event type is ITEM_KEY (with string ITEM_NAME) |
1350 and whose contents come from the list of keymaps MAPS. */ | 1350 and whose contents come from the list of keymaps MAPS. */ |
1351 | 1351 |
1352 static widget_value * | 1352 static int |
1353 single_submenu (item_key, item_name, maps) | 1353 parse_single_submenu (item_key, item_name, maps) |
1354 Lisp_Object item_key, item_name, maps; | 1354 Lisp_Object item_key, item_name, maps; |
1355 { | 1355 { |
1356 widget_value *wv, *prev_wv, *save_wv, *first_wv; | |
1357 int i; | |
1358 int submenu_depth = 0; | |
1359 Lisp_Object length; | 1356 Lisp_Object length; |
1360 int len; | 1357 int len; |
1361 Lisp_Object *mapvec; | 1358 Lisp_Object *mapvec; |
1362 widget_value **submenu_stack; | 1359 int i; |
1363 int previous_items = menu_items_used; | |
1364 int top_level_items = 0; | 1360 int top_level_items = 0; |
1365 | 1361 |
1366 length = Flength (maps); | 1362 length = Flength (maps); |
1367 len = XINT (length); | 1363 len = XINT (length); |
1368 | 1364 |
1371 for (i = 0; i < len; i++) | 1367 for (i = 0; i < len; i++) |
1372 { | 1368 { |
1373 mapvec[i] = Fcar (maps); | 1369 mapvec[i] = Fcar (maps); |
1374 maps = Fcdr (maps); | 1370 maps = Fcdr (maps); |
1375 } | 1371 } |
1376 | |
1377 menu_items_n_panes = 0; | |
1378 | 1372 |
1379 /* Loop over the given keymaps, making a pane for each map. | 1373 /* Loop over the given keymaps, making a pane for each map. |
1380 But don't make a pane that is empty--ignore that map instead. */ | 1374 But don't make a pane that is empty--ignore that map instead. */ |
1381 for (i = 0; i < len; i++) | 1375 for (i = 0; i < len; i++) |
1382 { | 1376 { |
1392 } | 1386 } |
1393 else | 1387 else |
1394 single_keymap_panes (mapvec[i], item_name, item_key, 0, 10); | 1388 single_keymap_panes (mapvec[i], item_name, item_key, 0, 10); |
1395 } | 1389 } |
1396 | 1390 |
1397 /* Create a tree of widget_value objects | 1391 return top_level_items; |
1398 representing the panes and their items. */ | 1392 } |
1393 | |
1394 /* Create a tree of widget_value objects | |
1395 representing the panes and items | |
1396 in menu_items starting at index START, up to index END. */ | |
1397 | |
1398 static widget_value * | |
1399 digest_single_submenu (start, end, top_level_items) | |
1400 int start, end; | |
1401 { | |
1402 widget_value *wv, *prev_wv, *save_wv, *first_wv; | |
1403 int i; | |
1404 int submenu_depth = 0; | |
1405 widget_value **submenu_stack; | |
1399 | 1406 |
1400 submenu_stack | 1407 submenu_stack |
1401 = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); | 1408 = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); |
1402 wv = xmalloc_widget_value (); | 1409 wv = xmalloc_widget_value (); |
1403 wv->name = "menu"; | 1410 wv->name = "menu"; |
1411 | 1418 |
1412 /* Loop over all panes and items made during this call | 1419 /* Loop over all panes and items made during this call |
1413 and construct a tree of widget_value objects. | 1420 and construct a tree of widget_value objects. |
1414 Ignore the panes and items made by previous calls to | 1421 Ignore the panes and items made by previous calls to |
1415 single_submenu, even though those are also in menu_items. */ | 1422 single_submenu, even though those are also in menu_items. */ |
1416 i = previous_items; | 1423 i = start; |
1417 while (i < menu_items_used) | 1424 while (i < end) |
1418 { | 1425 { |
1419 if (EQ (XVECTOR (menu_items)->contents[i], Qnil)) | 1426 if (EQ (XVECTOR (menu_items)->contents[i], Qnil)) |
1420 { | 1427 { |
1421 submenu_stack[submenu_depth++] = save_wv; | 1428 submenu_stack[submenu_depth++] = save_wv; |
1422 save_wv = prev_wv; | 1429 save_wv = prev_wv; |
1556 return wv; | 1563 return wv; |
1557 } | 1564 } |
1558 | 1565 |
1559 return first_wv; | 1566 return first_wv; |
1560 } | 1567 } |
1561 | |
1562 | |
1563 | 1568 |
1564 /* Recompute all the widgets of frame F, when the menu bar has been | 1569 /* Recompute all the widgets of frame F, when the menu bar has been |
1565 changed. Value is non-zero if widgets were updated. */ | 1570 changed. Value is non-zero if widgets were updated. */ |
1566 | 1571 |
1567 static int | 1572 static int |
1616 int deep_p; | 1621 int deep_p; |
1617 { | 1622 { |
1618 Widget menubar_widget = f->output_data.x->menubar_widget; | 1623 Widget menubar_widget = f->output_data.x->menubar_widget; |
1619 Lisp_Object items; | 1624 Lisp_Object items; |
1620 widget_value *wv, *first_wv, *prev_wv = 0; | 1625 widget_value *wv, *first_wv, *prev_wv = 0; |
1621 int i; | 1626 int i, last_i; |
1627 int *submenu_start, *submenu_end; | |
1628 int *submenu_top_level_items; | |
1622 | 1629 |
1623 LWLIB_ID id; | 1630 LWLIB_ID id; |
1624 | 1631 |
1625 XSETFRAME (Vmenu_updating_frame, f); | 1632 XSETFRAME (Vmenu_updating_frame, f); |
1626 | 1633 |
1637 { | 1644 { |
1638 deep_p = 1; | 1645 deep_p = 1; |
1639 f->output_data.x->saved_menu_event = (XEvent*)xmalloc (sizeof (XEvent)); | 1646 f->output_data.x->saved_menu_event = (XEvent*)xmalloc (sizeof (XEvent)); |
1640 f->output_data.x->saved_menu_event->type = 0; | 1647 f->output_data.x->saved_menu_event->type = 0; |
1641 } | 1648 } |
1642 | |
1643 wv = xmalloc_widget_value (); | |
1644 wv->name = "menubar"; | |
1645 wv->value = 0; | |
1646 wv->enabled = 1; | |
1647 wv->button_type = BUTTON_TYPE_NONE; | |
1648 wv->help = Qnil; | |
1649 first_wv = wv; | |
1650 | 1649 |
1651 if (deep_p) | 1650 if (deep_p) |
1652 { | 1651 { |
1653 /* Make a widget-value tree representing the entire menu trees. */ | 1652 /* Make a widget-value tree representing the entire menu trees. */ |
1654 | 1653 |
1690 safe_run_hooks (Qmenu_bar_update_hook); | 1689 safe_run_hooks (Qmenu_bar_update_hook); |
1691 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); | 1690 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); |
1692 | 1691 |
1693 items = FRAME_MENU_BAR_ITEMS (f); | 1692 items = FRAME_MENU_BAR_ITEMS (f); |
1694 | 1693 |
1695 inhibit_garbage_collection (); | |
1696 | |
1697 /* Save the frame's previous menu bar contents data. */ | 1694 /* Save the frame's previous menu bar contents data. */ |
1698 if (previous_menu_items_used) | 1695 if (previous_menu_items_used) |
1699 bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items, | 1696 bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items, |
1700 previous_menu_items_used * sizeof (Lisp_Object)); | 1697 previous_menu_items_used * sizeof (Lisp_Object)); |
1701 | 1698 |
1702 /* Fill in the current menu bar contents. */ | 1699 /* Fill in menu_items with the current menu bar contents. |
1700 This can evaluate Lisp code. */ | |
1703 menu_items = f->menu_bar_vector; | 1701 menu_items = f->menu_bar_vector; |
1704 menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0; | 1702 menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0; |
1703 submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); | |
1704 submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); | |
1705 submenu_top_level_items | |
1706 = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); | |
1705 init_menu_items (); | 1707 init_menu_items (); |
1706 for (i = 0; i < XVECTOR (items)->size; i += 4) | 1708 for (i = 0; i < XVECTOR (items)->size; i += 4) |
1707 { | 1709 { |
1708 Lisp_Object key, string, maps; | 1710 Lisp_Object key, string, maps; |
1711 | |
1712 last_i = i; | |
1709 | 1713 |
1710 key = XVECTOR (items)->contents[i]; | 1714 key = XVECTOR (items)->contents[i]; |
1711 string = XVECTOR (items)->contents[i + 1]; | 1715 string = XVECTOR (items)->contents[i + 1]; |
1712 maps = XVECTOR (items)->contents[i + 2]; | 1716 maps = XVECTOR (items)->contents[i + 2]; |
1713 if (NILP (string)) | 1717 if (NILP (string)) |
1714 break; | 1718 break; |
1715 | 1719 |
1716 wv = single_submenu (key, string, maps); | 1720 submenu_start[i] = menu_items_used; |
1721 | |
1722 menu_items_n_panes = 0; | |
1723 submenu_top_level_items[i] | |
1724 = parse_single_submenu (key, string, maps); | |
1725 | |
1726 submenu_end[i] = menu_items_used; | |
1727 } | |
1728 | |
1729 finish_menu_items (); | |
1730 | |
1731 /* Convert menu_items into widget_value trees | |
1732 to display the menu. This cannot evaluate Lisp code. */ | |
1733 | |
1734 wv = xmalloc_widget_value (); | |
1735 wv->name = "menubar"; | |
1736 wv->value = 0; | |
1737 wv->enabled = 1; | |
1738 wv->button_type = BUTTON_TYPE_NONE; | |
1739 wv->help = Qnil; | |
1740 first_wv = wv; | |
1741 | |
1742 for (i = 0; i < last_i; i += 4) | |
1743 { | |
1744 wv = digest_single_submenu (submenu_start[i], submenu_end[i], | |
1745 submenu_top_level_items[i]); | |
1717 if (prev_wv) | 1746 if (prev_wv) |
1718 prev_wv->next = wv; | 1747 prev_wv->next = wv; |
1719 else | 1748 else |
1720 first_wv->contents = wv; | 1749 first_wv->contents = wv; |
1721 /* Don't set wv->name here; GC during the loop might relocate it. */ | 1750 /* Don't set wv->name here; GC during the loop might relocate it. */ |
1722 wv->enabled = 1; | 1751 wv->enabled = 1; |
1723 wv->button_type = BUTTON_TYPE_NONE; | 1752 wv->button_type = BUTTON_TYPE_NONE; |
1724 prev_wv = wv; | 1753 prev_wv = wv; |
1725 } | 1754 } |
1726 | 1755 |
1727 finish_menu_items (); | |
1728 | |
1729 set_buffer_internal_1 (prev); | 1756 set_buffer_internal_1 (prev); |
1730 unbind_to (specpdl_count, Qnil); | 1757 unbind_to (specpdl_count, Qnil); |
1731 | 1758 |
1732 /* If there has been no change in the Lisp-level contents | 1759 /* If there has been no change in the Lisp-level contents |
1733 of the menu bar, skip redisplaying it. Just exit. */ | 1760 of the menu bar, skip redisplaying it. Just exit. */ |
1763 } | 1790 } |
1764 else | 1791 else |
1765 { | 1792 { |
1766 /* Make a widget-value tree containing | 1793 /* Make a widget-value tree containing |
1767 just the top level menu bar strings. */ | 1794 just the top level menu bar strings. */ |
1795 | |
1796 wv = xmalloc_widget_value (); | |
1797 wv->name = "menubar"; | |
1798 wv->value = 0; | |
1799 wv->enabled = 1; | |
1800 wv->button_type = BUTTON_TYPE_NONE; | |
1801 wv->help = Qnil; | |
1802 first_wv = wv; | |
1768 | 1803 |
1769 items = FRAME_MENU_BAR_ITEMS (f); | 1804 items = FRAME_MENU_BAR_ITEMS (f); |
1770 for (i = 0; i < XVECTOR (items)->size; i += 4) | 1805 for (i = 0; i < XVECTOR (items)->size; i += 4) |
1771 { | 1806 { |
1772 Lisp_Object string; | 1807 Lisp_Object string; |