diff options
Diffstat (limited to 'src/macmenu.c')
| -rw-r--r-- | src/macmenu.c | 71 |
1 files changed, 52 insertions, 19 deletions
diff --git a/src/macmenu.c b/src/macmenu.c index 67e18481a1b..740bda261d8 100644 --- a/src/macmenu.c +++ b/src/macmenu.c | |||
| @@ -90,10 +90,12 @@ enum button_type | |||
| 90 | typedef struct _widget_value | 90 | typedef struct _widget_value |
| 91 | { | 91 | { |
| 92 | /* name of widget */ | 92 | /* name of widget */ |
| 93 | Lisp_Object lname; | ||
| 93 | char* name; | 94 | char* name; |
| 94 | /* value (meaning depend on widget type) */ | 95 | /* value (meaning depend on widget type) */ |
| 95 | char* value; | 96 | char* value; |
| 96 | /* keyboard equivalent. no implications for XtTranslations */ | 97 | /* keyboard equivalent. no implications for XtTranslations */ |
| 98 | Lisp_Object lkey; | ||
| 97 | char* key; | 99 | char* key; |
| 98 | /* Help string or nil if none. | 100 | /* Help string or nil if none. |
| 99 | GC finds this string through the frame's menu_bar_vector | 101 | GC finds this string through the frame's menu_bar_vector |
| @@ -1221,12 +1223,9 @@ single_submenu (item_key, item_name, maps) | |||
| 1221 | save_wv->next = wv; | 1223 | save_wv->next = wv; |
| 1222 | else | 1224 | else |
| 1223 | first_wv->contents = wv; | 1225 | first_wv->contents = wv; |
| 1224 | wv->name = pane_string; | 1226 | wv->lname = pane_name; |
| 1225 | /* Ignore the @ that means "separate pane". | 1227 | /* Set value to 1 so update_submenu_strings can handle '@' */ |
| 1226 | This is a kludge, but this isn't worth more time. */ | 1228 | wv->value = (char *)1; |
| 1227 | if (!NILP (prefix) && wv->name[0] == '@') | ||
| 1228 | wv->name++; | ||
| 1229 | wv->value = 0; | ||
| 1230 | wv->enabled = 1; | 1229 | wv->enabled = 1; |
| 1231 | wv->button_type = BUTTON_TYPE_NONE; | 1230 | wv->button_type = BUTTON_TYPE_NONE; |
| 1232 | wv->help = Qnil; | 1231 | wv->help = Qnil; |
| @@ -1269,9 +1268,9 @@ single_submenu (item_key, item_name, maps) | |||
| 1269 | else | 1268 | else |
| 1270 | save_wv->contents = wv; | 1269 | save_wv->contents = wv; |
| 1271 | 1270 | ||
| 1272 | wv->name = (char *) SDATA (item_name); | 1271 | wv->lname = item_name; |
| 1273 | if (!NILP (descrip)) | 1272 | if (!NILP (descrip)) |
| 1274 | wv->key = (char *) SDATA (descrip); | 1273 | wv->lkey = descrip; |
| 1275 | wv->value = 0; | 1274 | wv->value = 0; |
| 1276 | /* The EMACS_INT cast avoids a warning. There's no problem | 1275 | /* The EMACS_INT cast avoids a warning. There's no problem |
| 1277 | as long as pointers have enough bits to hold small integers. */ | 1276 | as long as pointers have enough bits to hold small integers. */ |
| @@ -1310,6 +1309,41 @@ single_submenu (item_key, item_name, maps) | |||
| 1310 | 1309 | ||
| 1311 | return first_wv; | 1310 | return first_wv; |
| 1312 | } | 1311 | } |
| 1312 | /* Walk through the widget_value tree starting at FIRST_WV and update | ||
| 1313 | the char * pointers from the corresponding lisp values. | ||
| 1314 | We do this after building the whole tree, since GC may happen while the | ||
| 1315 | tree is constructed, and small strings are relocated. So we must wait | ||
| 1316 | until no GC can happen before storing pointers into lisp values. */ | ||
| 1317 | static void | ||
| 1318 | update_submenu_strings (first_wv) | ||
| 1319 | widget_value *first_wv; | ||
| 1320 | { | ||
| 1321 | widget_value *wv; | ||
| 1322 | |||
| 1323 | for (wv = first_wv; wv; wv = wv->next) | ||
| 1324 | { | ||
| 1325 | if (wv->lname && ! NILP (wv->lname)) | ||
| 1326 | { | ||
| 1327 | wv->name = SDATA (wv->lname); | ||
| 1328 | |||
| 1329 | /* Ignore the @ that means "separate pane". | ||
| 1330 | This is a kludge, but this isn't worth more time. */ | ||
| 1331 | if (wv->value == (char *)1) | ||
| 1332 | { | ||
| 1333 | if (wv->name[0] == '@') | ||
| 1334 | wv->name++; | ||
| 1335 | wv->value = 0; | ||
| 1336 | } | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | if (wv->lkey && ! NILP (wv->lkey)) | ||
| 1340 | wv->key = SDATA (wv->lkey); | ||
| 1341 | |||
| 1342 | if (wv->contents) | ||
| 1343 | update_submenu_strings (wv->contents); | ||
| 1344 | } | ||
| 1345 | } | ||
| 1346 | |||
| 1313 | 1347 | ||
| 1314 | /* Set the contents of the menubar widgets of frame F. | 1348 | /* Set the contents of the menubar widgets of frame F. |
| 1315 | The argument FIRST_TIME is currently ignored; | 1349 | The argument FIRST_TIME is currently ignored; |
| @@ -1388,8 +1422,6 @@ set_frame_menubar (f, first_time, deep_p) | |||
| 1388 | 1422 | ||
| 1389 | items = FRAME_MENU_BAR_ITEMS (f); | 1423 | items = FRAME_MENU_BAR_ITEMS (f); |
| 1390 | 1424 | ||
| 1391 | inhibit_garbage_collection (); | ||
| 1392 | |||
| 1393 | /* Save the frame's previous menu bar contents data. */ | 1425 | /* Save the frame's previous menu bar contents data. */ |
| 1394 | if (previous_menu_items_used) | 1426 | if (previous_menu_items_used) |
| 1395 | bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items, | 1427 | bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items, |
| @@ -1454,6 +1486,7 @@ set_frame_menubar (f, first_time, deep_p) | |||
| 1454 | if (NILP (string)) | 1486 | if (NILP (string)) |
| 1455 | break; | 1487 | break; |
| 1456 | wv->name = (char *) SDATA (string); | 1488 | wv->name = (char *) SDATA (string); |
| 1489 | update_submenu_strings (wv->contents); | ||
| 1457 | wv = wv->next; | 1490 | wv = wv->next; |
| 1458 | } | 1491 | } |
| 1459 | 1492 | ||
| @@ -1807,9 +1840,9 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) | |||
| 1807 | /* Get the refcon to find the correct item*/ | 1840 | /* Get the refcon to find the correct item*/ |
| 1808 | if (menu_item_selection) | 1841 | if (menu_item_selection) |
| 1809 | { | 1842 | { |
| 1810 | menu = GetMenuHandle (HiWord (menu_item_choice)); | 1843 | MenuHandle sel_menu = GetMenuHandle (HiWord (menu_item_choice)); |
| 1811 | if (menu) { | 1844 | if (sel_menu) { |
| 1812 | GetMenuItemRefCon (menu, menu_item_selection, &refcon); | 1845 | GetMenuItemRefCon (sel_menu, menu_item_selection, &refcon); |
| 1813 | } | 1846 | } |
| 1814 | } | 1847 | } |
| 1815 | 1848 | ||
| @@ -1831,11 +1864,11 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) | |||
| 1831 | { | 1864 | { |
| 1832 | int i = MIN_POPUP_SUBMENU_ID; | 1865 | int i = MIN_POPUP_SUBMENU_ID; |
| 1833 | MenuHandle submenu = GetMenuHandle (i); | 1866 | MenuHandle submenu = GetMenuHandle (i); |
| 1834 | while (menu != NULL) | 1867 | while (submenu != NULL) |
| 1835 | { | 1868 | { |
| 1836 | DeleteMenu (i); | 1869 | DeleteMenu (i); |
| 1837 | DisposeMenu (menu); | 1870 | DisposeMenu (submenu); |
| 1838 | menu = GetMenuHandle (++i); | 1871 | submenu = GetMenuHandle (++i); |
| 1839 | } | 1872 | } |
| 1840 | } | 1873 | } |
| 1841 | 1874 | ||
| @@ -2207,7 +2240,7 @@ add_menu_item (MenuHandle menu, widget_value *wv, int submenu, | |||
| 2207 | int force_disable) | 2240 | int force_disable) |
| 2208 | { | 2241 | { |
| 2209 | Str255 item_name; | 2242 | Str255 item_name; |
| 2210 | int pos, i; | 2243 | int pos; |
| 2211 | 2244 | ||
| 2212 | if (name_is_separator (wv->name)) | 2245 | if (name_is_separator (wv->name)) |
| 2213 | AppendMenu (menu, "\p-"); | 2246 | AppendMenu (menu, "\p-"); |
| @@ -2263,9 +2296,9 @@ add_menu_item (MenuHandle menu, widget_value *wv, int submenu, | |||
| 2263 | else | 2296 | else |
| 2264 | SetItemMark (menu, pos, noMark); | 2297 | SetItemMark (menu, pos, noMark); |
| 2265 | } | 2298 | } |
| 2266 | } | ||
| 2267 | 2299 | ||
| 2268 | SetMenuItemRefCon (menu, pos, (UInt32) wv->call_data); | 2300 | SetMenuItemRefCon (menu, pos, (UInt32) wv->call_data); |
| 2301 | } | ||
| 2269 | 2302 | ||
| 2270 | if (submenu != NULL) | 2303 | if (submenu != NULL) |
| 2271 | SetMenuItemHierarchicalID (menu, pos, submenu); | 2304 | SetMenuItemHierarchicalID (menu, pos, submenu); |