comparison src/macmenu.c @ 70148:a2348b30cc21

(restore_menu_items, save_menu_items): New functions from xmenu.c. (set_frame_menubar, digest_single_submenu): Apply 2006-04-18 changes for xmenu.c.
author YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
date Fri, 21 Apr 2006 07:56:47 +0000
parents adc2f96580af
children eb5777232ca5 2ecafc6d5db7
comparison
equal deleted inserted replaced
70147:37f988f09f67 70148:a2348b30cc21
301 menu_items = Qnil; 301 menu_items = Qnil;
302 menu_items_allocated = 0; 302 menu_items_allocated = 0;
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
309 grow_menu_items () 340 grow_menu_items ()
310 { 341 {
311 Lisp_Object old; 342 Lisp_Object old;
312 int old_size = menu_items_allocated; 343 int old_size = menu_items_allocated;
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));
319 } 351 }
320 352
1183 { 1215 {
1184 widget_value *wv, *prev_wv, *save_wv, *first_wv; 1216 widget_value *wv, *prev_wv, *save_wv, *first_wv;
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 *));
1191 wv = xmalloc_widget_value (); 1224 wv = xmalloc_widget_value ();
1192 wv->name = "menu"; 1225 wv->name = "menu";
1228 else if (EQ (XVECTOR (menu_items)->contents[i], Qt)) 1261 else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
1229 { 1262 {
1230 /* Create a new pane. */ 1263 /* Create a new pane. */
1231 Lisp_Object pane_name, prefix; 1264 Lisp_Object pane_name, prefix;
1232 char *pane_string; 1265 char *pane_string;
1266
1267 panes_seen++;
1233 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
1237 #ifndef HAVE_MULTILINGUAL_MENU 1272 #ifndef HAVE_MULTILINGUAL_MENU
1276 { 1311 {
1277 /* Create a new item within current pane. */ 1312 /* Create a new item within current pane. */
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);
1284 def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION); 1323 def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
1285 type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE); 1324 type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
1527 bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items, 1566 bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
1528 previous_menu_items_used * sizeof (Lisp_Object)); 1567 previous_menu_items_used * sizeof (Lisp_Object));
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 *));
1535 submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); 1576 submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
1536 submenu_n_panes = (int *) alloca (XVECTOR (items)->size * sizeof (int)); 1577 submenu_n_panes = (int *) alloca (XVECTOR (items)->size * sizeof (int));
1586 wv->button_type = BUTTON_TYPE_NONE; 1627 wv->button_type = BUTTON_TYPE_NONE;
1587 prev_wv = wv; 1628 prev_wv = wv;
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 }
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);
1607 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;
1611 for (i = 0; i < XVECTOR (items)->size; i += 4) 1662 for (i = 0; i < XVECTOR (items)->size; i += 4)
1617 wv->name = (char *) SDATA (string); 1668 wv->name = (char *) SDATA (string);
1618 update_submenu_strings (wv->contents); 1669 update_submenu_strings (wv->contents);
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 {
1628 /* Make a widget-value tree containing 1676 /* Make a widget-value tree containing
1629 just the top level menu bar strings. */ 1677 just the top level menu bar strings. */