aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Rumney2004-09-02 23:26:16 +0000
committerJason Rumney2004-09-02 23:26:16 +0000
commit1f06d36755eeae2ae2663f9ee56b7ff747fa20a0 (patch)
tree104cc01dca980fa649d265f34045fd2dbbc0cd4f /src
parente2ea72e9dd38da3faac53ec969d2228624ddf024 (diff)
downloademacs-1f06d36755eeae2ae2663f9ee56b7ff747fa20a0.tar.gz
emacs-1f06d36755eeae2ae2663f9ee56b7ff747fa20a0.zip
(_widget_value): Added lname and lkey.
(digest_single_submenu): Set lname and lkey in widget_value instead of name and key. (update_submenu_strings): New function. (set_frame_menubar): Remove call to inhibit_garbage_collection, call update_submenu_strings. (globals_of_w32menu): Check for Unicode API. (digest_single_submenu, w32_menu_show): Encode menu strings as UTF-8 if Unicode API is available. (utf8to16): New function. (add_menu_item): Use it when calling Unicode API.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog15
-rw-r--r--src/w32menu.c198
2 files changed, 172 insertions, 41 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index c2999317d03..77fd0bb7505 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,18 @@
12004-09-03 Jason Rumney <jasonr@gnu.org>
2
3 * w32menu.c (_widget_value): Added lname and lkey.
4 (digest_single_submenu): Set lname and lkey in widget_value
5 instead of name and key.
6 (update_submenu_strings): New function.
7 (set_frame_menubar): Remove call to inhibit_garbage_collection,
8 call update_submenu_strings.
9
10 * w32menu.c (globals_of_w32menu): Check for Unicode API.
11 (digest_single_submenu, w32_menu_show): Encode menu strings as
12 UTF-8 if Unicode API is available.
13 (utf8to16): New function.
14 (add_menu_item): Use it when calling Unicode API.
15
12004-09-03 Kim F. Storm <storm@cua.dk> 162004-09-03 Kim F. Storm <storm@cua.dk>
2 17
3 * xdisp.c (set_cursor_from_row): Look for non-nil `cursor' property 18 * xdisp.c (set_cursor_from_row): Look for non-nil `cursor' property
diff --git a/src/w32menu.c b/src/w32menu.c
index cc0932d7bf5..f3f3eb785b0 100644
--- a/src/w32menu.c
+++ b/src/w32menu.c
@@ -45,7 +45,6 @@ Boston, MA 02111-1307, USA. */
45 45
46#include "dispextern.h" 46#include "dispextern.h"
47 47
48#undef HAVE_MULTILINGUAL_MENU
49#undef HAVE_DIALOGS /* TODO: Implement native dialogs. */ 48#undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
50 49
51/******************************************************************/ 50/******************************************************************/
@@ -66,10 +65,12 @@ enum button_type
66typedef struct _widget_value 65typedef struct _widget_value
67{ 66{
68 /* name of widget */ 67 /* name of widget */
68 Lisp_Object lname;
69 char* name; 69 char* name;
70 /* value (meaning depend on widget type) */ 70 /* value (meaning depend on widget type) */
71 char* value; 71 char* value;
72 /* keyboard equivalent. no implications for XtTranslations */ 72 /* keyboard equivalent. no implications for XtTranslations */
73 Lisp_Object lkey;
73 char* key; 74 char* key;
74 /* Help string or nil if none. 75 /* Help string or nil if none.
75 GC finds this string through the frame's menu_bar_vector 76 GC finds this string through the frame's menu_bar_vector
@@ -136,17 +137,21 @@ typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) (
136 IN HMENU, 137 IN HMENU,
137 IN UINT, 138 IN UINT,
138 IN BOOL, 139 IN BOOL,
139 IN OUT LPMENUITEMINFOA 140 IN OUT LPMENUITEMINFOA);
140 );
141typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) ( 141typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) (
142 IN HMENU, 142 IN HMENU,
143 IN UINT, 143 IN UINT,
144 IN BOOL, 144 IN BOOL,
145 IN LPCMENUITEMINFOA 145 IN LPCMENUITEMINFOA);
146 ); 146typedef BOOL (WINAPI * AppendMenuW_Proc) (
147 IN HMENU,
148 IN UINT,
149 IN UINT_PTR,
150 IN LPCWSTR);
147 151
148GetMenuItemInfoA_Proc get_menu_item_info=NULL; 152GetMenuItemInfoA_Proc get_menu_item_info = NULL;
149SetMenuItemInfoA_Proc set_menu_item_info=NULL; 153SetMenuItemInfoA_Proc set_menu_item_info = NULL;
154AppendMenuW_Proc unicode_append_menu = NULL;
150 155
151Lisp_Object Vmenu_updating_frame; 156Lisp_Object Vmenu_updating_frame;
152 157
@@ -1235,13 +1240,17 @@ digest_single_submenu (start, end, top_level_items)
1235 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME); 1240 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
1236 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); 1241 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
1237 1242
1238#ifndef HAVE_MULTILINGUAL_MENU 1243 if (STRINGP (pane_name))
1239 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
1240 { 1244 {
1241 pane_name = ENCODE_SYSTEM (pane_name); 1245 if (unicode_append_menu)
1246 /* Encode as UTF-8 for now. */
1247 pane_name = ENCODE_UTF_8 (pane_name);
1248 else if (STRING_MULTIBYTE (pane_name))
1249 pane_name = ENCODE_SYSTEM (pane_name);
1250
1242 ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name); 1251 ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
1243 } 1252 }
1244#endif 1253
1245 pane_string = (NILP (pane_name) 1254 pane_string = (NILP (pane_name)
1246 ? "" : (char *) SDATA (pane_name)); 1255 ? "" : (char *) SDATA (pane_name));
1247 /* If there is just one top-level pane, put all its items directly 1256 /* If there is just one top-level pane, put all its items directly
@@ -1259,12 +1268,9 @@ digest_single_submenu (start, end, top_level_items)
1259 save_wv->next = wv; 1268 save_wv->next = wv;
1260 else 1269 else
1261 first_wv->contents = wv; 1270 first_wv->contents = wv;
1262 wv->name = pane_string; 1271 wv->lname = pane_name;
1263 /* Ignore the @ that means "separate pane". 1272 /* Set value to 1 so update_submenu_strings can handle '@' */
1264 This is a kludge, but this isn't worth more time. */ 1273 wv->value = (char *) 1;
1265 if (!NILP (prefix) && wv->name[0] == '@')
1266 wv->name++;
1267 wv->value = 0;
1268 wv->enabled = 1; 1274 wv->enabled = 1;
1269 wv->button_type = BUTTON_TYPE_NONE; 1275 wv->button_type = BUTTON_TYPE_NONE;
1270 wv->help = Qnil; 1276 wv->help = Qnil;
@@ -1287,10 +1293,13 @@ digest_single_submenu (start, end, top_level_items)
1287 selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED); 1293 selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
1288 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP); 1294 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
1289 1295
1290#ifndef HAVE_MULTILINGUAL_MENU 1296 if (STRINGP (item_name))
1291 if (STRING_MULTIBYTE (item_name))
1292 { 1297 {
1293 item_name = ENCODE_SYSTEM (item_name); 1298 if (unicode_append_menu)
1299 item_name = ENCODE_UTF_8 (item_name);
1300 else if (STRING_MULTIBYTE (item_name))
1301 item_name = ENCODE_SYSTEM (item_name);
1302
1294 ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name); 1303 ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
1295 } 1304 }
1296 1305
@@ -1299,7 +1308,6 @@ digest_single_submenu (start, end, top_level_items)
1299 descrip = ENCODE_SYSTEM (descrip); 1308 descrip = ENCODE_SYSTEM (descrip);
1300 ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip); 1309 ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
1301 } 1310 }
1302#endif /* not HAVE_MULTILINGUAL_MENU */
1303 1311
1304 wv = xmalloc_widget_value (); 1312 wv = xmalloc_widget_value ();
1305 if (prev_wv) 1313 if (prev_wv)
@@ -1307,9 +1315,9 @@ digest_single_submenu (start, end, top_level_items)
1307 else 1315 else
1308 save_wv->contents = wv; 1316 save_wv->contents = wv;
1309 1317
1310 wv->name = (char *) SDATA (item_name); 1318 wv->lname = item_name;
1311 if (!NILP (descrip)) 1319 if (!NILP (descrip))
1312 wv->key = (char *) SDATA (descrip); 1320 wv->lkey = descrip;
1313 wv->value = 0; 1321 wv->value = 0;
1314 /* The EMACS_INT cast avoids a warning. There's no problem 1322 /* The EMACS_INT cast avoids a warning. There's no problem
1315 as long as pointers have enough bits to hold small integers. */ 1323 as long as pointers have enough bits to hold small integers. */
@@ -1348,6 +1356,43 @@ digest_single_submenu (start, end, top_level_items)
1348 1356
1349 return first_wv; 1357 return first_wv;
1350} 1358}
1359
1360
1361/* Walk through the widget_value tree starting at FIRST_WV and update
1362 the char * pointers from the corresponding lisp values.
1363 We do this after building the whole tree, since GC may happen while the
1364 tree is constructed, and small strings are relocated. So we must wait
1365 until no GC can happen before storing pointers into lisp values. */
1366static void
1367update_submenu_strings (first_wv)
1368 widget_value *first_wv;
1369{
1370 widget_value *wv;
1371
1372 for (wv = first_wv; wv; wv = wv->next)
1373 {
1374 if (wv->lname && ! NILP (wv->lname))
1375 {
1376 wv->name = SDATA (wv->lname);
1377
1378 /* Ignore the @ that means "separate pane".
1379 This is a kludge, but this isn't worth more time. */
1380 if (wv->value == (char *)1)
1381 {
1382 if (wv->name[0] == '@')
1383 wv->name++;
1384 wv->value = 0;
1385 }
1386 }
1387
1388 if (wv->lkey && ! NILP (wv->lkey))
1389 wv->key = SDATA (wv->lkey);
1390
1391 if (wv->contents)
1392 update_submenu_strings (wv->contents);
1393 }
1394}
1395
1351 1396
1352/* Set the contents of the menubar widgets of frame F. 1397/* Set the contents of the menubar widgets of frame F.
1353 The argument FIRST_TIME is currently ignored; 1398 The argument FIRST_TIME is currently ignored;
@@ -1516,6 +1561,7 @@ set_frame_menubar (f, first_time, deep_p)
1516 if (NILP (string)) 1561 if (NILP (string))
1517 break; 1562 break;
1518 wv->name = (char *) SDATA (string); 1563 wv->name = (char *) SDATA (string);
1564 update_submenu_strings (wv->contents);
1519 wv = wv->next; 1565 wv = wv->next;
1520 } 1566 }
1521 1567
@@ -1729,13 +1775,17 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
1729 char *pane_string; 1775 char *pane_string;
1730 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME); 1776 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
1731 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); 1777 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
1732#ifndef HAVE_MULTILINGUAL_MENU 1778
1733 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name)) 1779 if (STRINGP (pane_name))
1734 { 1780 {
1735 pane_name = ENCODE_SYSTEM (pane_name); 1781 if (unicode_append_menu)
1782 pane_name = ENCODE_UTF_8 (pane_name);
1783 else if (STRING_MULTIBYTE (pane_name))
1784 pane_name = ENCODE_SYSTEM (pane_name);
1785
1736 ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name); 1786 ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
1737 } 1787 }
1738#endif 1788
1739 pane_string = (NILP (pane_name) 1789 pane_string = (NILP (pane_name)
1740 ? "" : (char *) SDATA (pane_name)); 1790 ? "" : (char *) SDATA (pane_name));
1741 /* If there is just one top-level pane, put all its items directly 1791 /* If there is just one top-level pane, put all its items directly
@@ -1784,18 +1834,21 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
1784 selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED); 1834 selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
1785 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP); 1835 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
1786 1836
1787#ifndef HAVE_MULTILINGUAL_MENU 1837 if (STRINGP (item_name))
1788 if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
1789 { 1838 {
1790 item_name = ENCODE_SYSTEM (item_name); 1839 if (unicode_append_menu)
1840 item_name = ENCODE_UTF_8 (item_name);
1841 else if (STRING_MULTIBYTE (item_name))
1842 item_name = ENCODE_SYSTEM (item_name);
1843
1791 ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name); 1844 ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
1792 } 1845 }
1793 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) 1846
1847 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
1794 { 1848 {
1795 descrip = ENCODE_SYSTEM (descrip); 1849 descrip = ENCODE_SYSTEM (descrip);
1796 ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip); 1850 ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
1797 } 1851 }
1798#endif /* not HAVE_MULTILINGUAL_MENU */
1799 1852
1800 wv = xmalloc_widget_value (); 1853 wv = xmalloc_widget_value ();
1801 if (prev_wv) 1854 if (prev_wv)
@@ -1844,10 +1897,11 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
1844 wv_sep->next = first_wv->contents; 1897 wv_sep->next = first_wv->contents;
1845 wv_sep->help = Qnil; 1898 wv_sep->help = Qnil;
1846 1899
1847#ifndef HAVE_MULTILINGUAL_MENU 1900 if (unicode_append_menu)
1848 if (STRING_MULTIBYTE (title)) 1901 title = ENCODE_UTF_8 (title);
1902 else if (STRING_MULTIBYTE (title))
1849 title = ENCODE_SYSTEM (title); 1903 title = ENCODE_SYSTEM (title);
1850#endif 1904
1851 wv_title->name = (char *) SDATA (title); 1905 wv_title->name = (char *) SDATA (title);
1852 wv_title->enabled = TRUE; 1906 wv_title->enabled = TRUE;
1853 wv_title->title = TRUE; 1907 wv_title->title = TRUE;
@@ -2150,6 +2204,46 @@ add_left_right_boundary (HMENU menu)
2150 return AppendMenu (menu, MF_MENUBARBREAK, 0, NULL); 2204 return AppendMenu (menu, MF_MENUBARBREAK, 0, NULL);
2151} 2205}
2152 2206
2207/* UTF8: 0xxxxxxx, 110xxxxx 10xxxxxx, 1110xxxx, 10xxxxxx, 10xxxxxx */
2208static void
2209utf8to16 (unsigned char * src, int len, WCHAR * dest)
2210{
2211 while (len > 0)
2212 {
2213 int utf16;
2214 if (*src < 0x80)
2215 {
2216 *dest = (WCHAR) *src;
2217 dest++; src++; len--;
2218 }
2219 /* Since we might get >3 byte sequences which we don't handle, ignore the extra parts. */
2220 else if (*src < 0xC0)
2221 {
2222 src++; len--;
2223 }
2224 /* 2 char UTF-8 sequence. */
2225 else if (*src < 0xE0)
2226 {
2227 *dest = (WCHAR) (((*src & 0x1f) << 6)
2228 | (*(src + 1) & 0x3f));
2229 src += 2; len -= 2; dest++;
2230 }
2231 else if (*src < 0xF0)
2232 {
2233 *dest = (WCHAR) (((*src & 0x0f) << 12)
2234 | ((*(src + 1) & 0x3f) << 6)
2235 | (*(src + 2) & 0x3f));
2236 src += 3; len -= 3; dest++;
2237 }
2238 else /* Not encodable. Insert Unicode Substitution char. */
2239 {
2240 *dest = (WCHAR) 0xfffd;
2241 src++; len--; dest++;
2242 }
2243 }
2244 *dest = 0;
2245}
2246
2153static int 2247static int
2154add_menu_item (HMENU menu, widget_value *wv, HMENU item) 2248add_menu_item (HMENU menu, widget_value *wv, HMENU item)
2155{ 2249{
@@ -2206,11 +2300,32 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
2206 fuFlags |= MF_UNCHECKED; 2300 fuFlags |= MF_UNCHECKED;
2207 } 2301 }
2208 2302
2209 return_value = 2303 if (unicode_append_menu && out_string)
2210 AppendMenu (menu, 2304 {
2211 fuFlags, 2305 /* Convert out_string from UTF-8 to UTF-16-LE. */
2212 item != NULL ? (UINT) item : (UINT) wv->call_data, 2306 int utf8_len = strlen (out_string);
2213 out_string ); 2307 WCHAR * utf16_string;
2308 if (fuFlags & MF_OWNERDRAW)
2309 utf16_string = local_alloc ((utf8_len + 1) * sizeof (WCHAR));
2310 else
2311 utf16_string = alloca ((utf8_len + 1) * sizeof (WCHAR));
2312
2313 utf8to16 (out_string, utf8_len, utf16_string);
2314 return_value = unicode_append_menu (menu, fuFlags,
2315 item != NULL ? (UINT) item
2316 : (UINT) wv->call_data,
2317 utf16_string);
2318 if (fuFlags & MF_OWNERDRAW)
2319 local_free (out_string);
2320 }
2321 else
2322 {
2323 return_value =
2324 AppendMenu (menu,
2325 fuFlags,
2326 item != NULL ? (UINT) item : (UINT) wv->call_data,
2327 out_string );
2328 }
2214 2329
2215 /* This must be done after the menu item is created. */ 2330 /* This must be done after the menu item is created. */
2216 if (!wv->title && wv->call_data != 0) 2331 if (!wv->title && wv->call_data != 0)
@@ -2298,7 +2413,7 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags)
2298 struct frame *f = x_window_to_frame (&one_w32_display_info, owner); 2413 struct frame *f = x_window_to_frame (&one_w32_display_info, owner);
2299 Lisp_Object frame, help; 2414 Lisp_Object frame, help;
2300 2415
2301 // No help echo on owner-draw menu items. 2416 /* No help echo on owner-draw menu items. */
2302 if (flags & MF_OWNERDRAW || flags & MF_POPUP) 2417 if (flags & MF_OWNERDRAW || flags & MF_POPUP)
2303 help = Qnil; 2418 help = Qnil;
2304 else 2419 else
@@ -2422,6 +2537,7 @@ void globals_of_w32menu ()
2422 HMODULE user32 = GetModuleHandle ("user32.dll"); 2537 HMODULE user32 = GetModuleHandle ("user32.dll");
2423 get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA"); 2538 get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA");
2424 set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA"); 2539 set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA");
2540 unicode_append_menu = (AppendMenuW_Proc) GetProcAddress (user32, "AppendMenuW");
2425} 2541}
2426 2542
2427/* arch-tag: 0eaed431-bb4e-4aac-a527-95a1b4f1fed0 2543/* arch-tag: 0eaed431-bb4e-4aac-a527-95a1b4f1fed0