diff options
Diffstat (limited to 'src/macmenu.c')
| -rw-r--r-- | src/macmenu.c | 95 |
1 files changed, 74 insertions, 21 deletions
diff --git a/src/macmenu.c b/src/macmenu.c index d205ee3b877..88012b01f73 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 |
| @@ -163,6 +165,12 @@ extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; | |||
| 163 | 165 | ||
| 164 | extern Lisp_Object Qmenu_bar_update_hook; | 166 | extern Lisp_Object Qmenu_bar_update_hook; |
| 165 | 167 | ||
| 168 | #if TARGET_API_MAC_CARBON | ||
| 169 | #define ENCODE_MENU_STRING(str) ENCODE_UTF_8 (str) | ||
| 170 | #else | ||
| 171 | #define ENCODE_MENU_STRING(str) ENCODE_SYSTEM (str) | ||
| 172 | #endif | ||
| 173 | |||
| 166 | void set_frame_menubar (); | 174 | void set_frame_menubar (); |
| 167 | 175 | ||
| 168 | static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object, | 176 | static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object, |
| @@ -1215,12 +1223,9 @@ single_submenu (item_key, item_name, maps) | |||
| 1215 | save_wv->next = wv; | 1223 | save_wv->next = wv; |
| 1216 | else | 1224 | else |
| 1217 | first_wv->contents = wv; | 1225 | first_wv->contents = wv; |
| 1218 | wv->name = pane_string; | 1226 | wv->lname = pane_name; |
| 1219 | /* Ignore the @ that means "separate pane". | 1227 | /* Set value to 1 so update_submenu_strings can handle '@' */ |
| 1220 | This is a kludge, but this isn't worth more time. */ | 1228 | wv->value = (char *)1; |
| 1221 | if (!NILP (prefix) && wv->name[0] == '@') | ||
| 1222 | wv->name++; | ||
| 1223 | wv->value = 0; | ||
| 1224 | wv->enabled = 1; | 1229 | wv->enabled = 1; |
| 1225 | wv->button_type = BUTTON_TYPE_NONE; | 1230 | wv->button_type = BUTTON_TYPE_NONE; |
| 1226 | wv->help = Qnil; | 1231 | wv->help = Qnil; |
| @@ -1246,13 +1251,13 @@ single_submenu (item_key, item_name, maps) | |||
| 1246 | #ifndef HAVE_MULTILINGUAL_MENU | 1251 | #ifndef HAVE_MULTILINGUAL_MENU |
| 1247 | if (STRING_MULTIBYTE (item_name)) | 1252 | if (STRING_MULTIBYTE (item_name)) |
| 1248 | { | 1253 | { |
| 1249 | item_name = ENCODE_SYSTEM (item_name); | 1254 | item_name = ENCODE_MENU_STRING (item_name); |
| 1250 | AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name; | 1255 | AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name; |
| 1251 | } | 1256 | } |
| 1252 | 1257 | ||
| 1253 | if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) | 1258 | if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) |
| 1254 | { | 1259 | { |
| 1255 | descrip = ENCODE_SYSTEM (descrip); | 1260 | descrip = ENCODE_MENU_STRING (descrip); |
| 1256 | AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip; | 1261 | AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip; |
| 1257 | } | 1262 | } |
| 1258 | #endif /* not HAVE_MULTILINGUAL_MENU */ | 1263 | #endif /* not HAVE_MULTILINGUAL_MENU */ |
| @@ -1263,9 +1268,9 @@ single_submenu (item_key, item_name, maps) | |||
| 1263 | else | 1268 | else |
| 1264 | save_wv->contents = wv; | 1269 | save_wv->contents = wv; |
| 1265 | 1270 | ||
| 1266 | wv->name = (char *) SDATA (item_name); | 1271 | wv->lname = item_name; |
| 1267 | if (!NILP (descrip)) | 1272 | if (!NILP (descrip)) |
| 1268 | wv->key = (char *) SDATA (descrip); | 1273 | wv->lkey = descrip; |
| 1269 | wv->value = 0; | 1274 | wv->value = 0; |
| 1270 | /* The EMACS_INT cast avoids a warning. There's no problem | 1275 | /* The EMACS_INT cast avoids a warning. There's no problem |
| 1271 | as long as pointers have enough bits to hold small integers. */ | 1276 | as long as pointers have enough bits to hold small integers. */ |
| @@ -1304,6 +1309,41 @@ single_submenu (item_key, item_name, maps) | |||
| 1304 | 1309 | ||
| 1305 | return first_wv; | 1310 | return first_wv; |
| 1306 | } | 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 | |||
| 1307 | 1347 | ||
| 1308 | /* Set the contents of the menubar widgets of frame F. | 1348 | /* Set the contents of the menubar widgets of frame F. |
| 1309 | The argument FIRST_TIME is currently ignored; | 1349 | The argument FIRST_TIME is currently ignored; |
| @@ -1382,8 +1422,6 @@ set_frame_menubar (f, first_time, deep_p) | |||
| 1382 | 1422 | ||
| 1383 | items = FRAME_MENU_BAR_ITEMS (f); | 1423 | items = FRAME_MENU_BAR_ITEMS (f); |
| 1384 | 1424 | ||
| 1385 | inhibit_garbage_collection (); | ||
| 1386 | |||
| 1387 | /* Save the frame's previous menu bar contents data. */ | 1425 | /* Save the frame's previous menu bar contents data. */ |
| 1388 | if (previous_menu_items_used) | 1426 | if (previous_menu_items_used) |
| 1389 | bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items, | 1427 | bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items, |
| @@ -1448,6 +1486,7 @@ set_frame_menubar (f, first_time, deep_p) | |||
| 1448 | if (NILP (string)) | 1486 | if (NILP (string)) |
| 1449 | break; | 1487 | break; |
| 1450 | wv->name = (char *) SDATA (string); | 1488 | wv->name = (char *) SDATA (string); |
| 1489 | update_submenu_strings (wv->contents); | ||
| 1451 | wv = wv->next; | 1490 | wv = wv->next; |
| 1452 | } | 1491 | } |
| 1453 | 1492 | ||
| @@ -1705,12 +1744,12 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) | |||
| 1705 | #ifndef HAVE_MULTILINGUAL_MENU | 1744 | #ifndef HAVE_MULTILINGUAL_MENU |
| 1706 | if (STRINGP (item_name) && STRING_MULTIBYTE (item_name)) | 1745 | if (STRINGP (item_name) && STRING_MULTIBYTE (item_name)) |
| 1707 | { | 1746 | { |
| 1708 | item_name = ENCODE_SYSTEM (item_name); | 1747 | item_name = ENCODE_MENU_STRING (item_name); |
| 1709 | AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name; | 1748 | AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name; |
| 1710 | } | 1749 | } |
| 1711 | if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) | 1750 | if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) |
| 1712 | { | 1751 | { |
| 1713 | descrip = ENCODE_SYSTEM (descrip); | 1752 | descrip = ENCODE_MENU_STRING (descrip); |
| 1714 | AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip; | 1753 | AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip; |
| 1715 | } | 1754 | } |
| 1716 | #endif /* not HAVE_MULTILINGUAL_MENU */ | 1755 | #endif /* not HAVE_MULTILINGUAL_MENU */ |
| @@ -1764,7 +1803,7 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) | |||
| 1764 | 1803 | ||
| 1765 | #ifndef HAVE_MULTILINGUAL_MENU | 1804 | #ifndef HAVE_MULTILINGUAL_MENU |
| 1766 | if (STRING_MULTIBYTE (title)) | 1805 | if (STRING_MULTIBYTE (title)) |
| 1767 | title = ENCODE_SYSTEM (title); | 1806 | title = ENCODE_MENU_STRING (title); |
| 1768 | #endif | 1807 | #endif |
| 1769 | wv_title->name = (char *) SDATA (title); | 1808 | wv_title->name = (char *) SDATA (title); |
| 1770 | wv_title->enabled = TRUE; | 1809 | wv_title->enabled = TRUE; |
| @@ -1801,9 +1840,9 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) | |||
| 1801 | /* Get the refcon to find the correct item*/ | 1840 | /* Get the refcon to find the correct item*/ |
| 1802 | if (menu_item_selection) | 1841 | if (menu_item_selection) |
| 1803 | { | 1842 | { |
| 1804 | menu = GetMenuHandle (HiWord (menu_item_choice)); | 1843 | MenuHandle sel_menu = GetMenuHandle (HiWord (menu_item_choice)); |
| 1805 | if (menu) { | 1844 | if (sel_menu) { |
| 1806 | GetMenuItemRefCon (menu, menu_item_selection, &refcon); | 1845 | GetMenuItemRefCon (sel_menu, menu_item_selection, &refcon); |
| 1807 | } | 1846 | } |
| 1808 | } | 1847 | } |
| 1809 | 1848 | ||
| @@ -1813,6 +1852,10 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) | |||
| 1813 | discard_mouse_events (); | 1852 | discard_mouse_events (); |
| 1814 | #endif | 1853 | #endif |
| 1815 | 1854 | ||
| 1855 | /* Must reset this manually because the button release event is not | ||
| 1856 | passed to Emacs event loop. */ | ||
| 1857 | FRAME_MAC_DISPLAY_INFO (f)->grabbed = 0; | ||
| 1858 | |||
| 1816 | /* Free the widget_value objects we used to specify the | 1859 | /* Free the widget_value objects we used to specify the |
| 1817 | contents. */ | 1860 | contents. */ |
| 1818 | free_menubar_widget_value_tree (first_wv); | 1861 | free_menubar_widget_value_tree (first_wv); |
| @@ -1821,11 +1864,11 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) | |||
| 1821 | { | 1864 | { |
| 1822 | int i = MIN_POPUP_SUBMENU_ID; | 1865 | int i = MIN_POPUP_SUBMENU_ID; |
| 1823 | MenuHandle submenu = GetMenuHandle (i); | 1866 | MenuHandle submenu = GetMenuHandle (i); |
| 1824 | while (menu != NULL) | 1867 | while (submenu != NULL) |
| 1825 | { | 1868 | { |
| 1826 | DeleteMenu (i); | 1869 | DeleteMenu (i); |
| 1827 | DisposeMenu (menu); | 1870 | DisposeMenu (submenu); |
| 1828 | menu = GetMenuHandle (++i); | 1871 | submenu = GetMenuHandle (++i); |
| 1829 | } | 1872 | } |
| 1830 | } | 1873 | } |
| 1831 | 1874 | ||
| @@ -2219,8 +2262,18 @@ add_menu_item (MenuHandle menu, widget_value *wv, int submenu, | |||
| 2219 | strncat (item_name, wv->key, 255); | 2262 | strncat (item_name, wv->key, 255); |
| 2220 | } | 2263 | } |
| 2221 | item_name[255] = 0; | 2264 | item_name[255] = 0; |
| 2265 | #if TARGET_API_MAC_CARBON | ||
| 2266 | { | ||
| 2267 | CFStringRef string = | ||
| 2268 | CFStringCreateWithCString (NULL, item_name, kCFStringEncodingUTF8); | ||
| 2269 | |||
| 2270 | SetMenuItemTextWithCFString (menu, pos, string); | ||
| 2271 | CFRelease (string); | ||
| 2272 | } | ||
| 2273 | #else | ||
| 2222 | c2pstr (item_name); | 2274 | c2pstr (item_name); |
| 2223 | SetMenuItemText (menu, pos, item_name); | 2275 | SetMenuItemText (menu, pos, item_name); |
| 2276 | #endif | ||
| 2224 | 2277 | ||
| 2225 | if (wv->enabled && !force_disable) | 2278 | if (wv->enabled && !force_disable) |
| 2226 | #if TARGET_API_MAC_CARBON | 2279 | #if TARGET_API_MAC_CARBON |