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;