45 |
|
|
46 |
#include "dispextern.h" |
#include "dispextern.h" |
47 |
|
|
|
#undef HAVE_MULTILINGUAL_MENU |
|
48 |
#undef HAVE_DIALOGS /* TODO: Implement native dialogs. */ |
#undef HAVE_DIALOGS /* TODO: Implement native dialogs. */ |
49 |
|
|
50 |
/******************************************************************/ |
/******************************************************************/ |
65 |
typedef struct _widget_value |
typedef struct _widget_value |
66 |
{ |
{ |
67 |
/* name of widget */ |
/* name of widget */ |
68 |
|
Lisp_Object lname; |
69 |
char* name; |
char* name; |
70 |
/* value (meaning depend on widget type) */ |
/* value (meaning depend on widget type) */ |
71 |
char* value; |
char* value; |
72 |
/* keyboard equivalent. no implications for XtTranslations */ |
/* keyboard equivalent. no implications for XtTranslations */ |
73 |
|
Lisp_Object lkey; |
74 |
char* key; |
char* key; |
75 |
/* Help string or nil if none. |
/* Help string or nil if none. |
76 |
GC finds this string through the frame's menu_bar_vector |
GC finds this string through the frame's menu_bar_vector |
137 |
IN HMENU, |
IN HMENU, |
138 |
IN UINT, |
IN UINT, |
139 |
IN BOOL, |
IN BOOL, |
140 |
IN OUT LPMENUITEMINFOA |
IN OUT LPMENUITEMINFOA); |
|
); |
|
141 |
typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) ( |
typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) ( |
142 |
IN HMENU, |
IN HMENU, |
143 |
IN UINT, |
IN UINT, |
144 |
IN BOOL, |
IN BOOL, |
145 |
IN LPCMENUITEMINFOA |
IN LPCMENUITEMINFOA); |
146 |
); |
typedef BOOL (WINAPI * AppendMenuW_Proc) ( |
147 |
|
IN HMENU, |
148 |
|
IN UINT, |
149 |
|
IN UINT_PTR, |
150 |
|
IN LPCWSTR); |
151 |
|
|
152 |
GetMenuItemInfoA_Proc get_menu_item_info=NULL; |
GetMenuItemInfoA_Proc get_menu_item_info = NULL; |
153 |
SetMenuItemInfoA_Proc set_menu_item_info=NULL; |
SetMenuItemInfoA_Proc set_menu_item_info = NULL; |
154 |
|
AppendMenuW_Proc unicode_append_menu = NULL; |
155 |
|
|
156 |
Lisp_Object Vmenu_updating_frame; |
Lisp_Object Vmenu_updating_frame; |
157 |
|
|
1240 |
pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME); |
pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME); |
1241 |
prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); |
prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); |
1242 |
|
|
1243 |
#ifndef HAVE_MULTILINGUAL_MENU |
if (STRINGP (pane_name)) |
|
if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name)) |
|
1244 |
{ |
{ |
1245 |
pane_name = ENCODE_SYSTEM (pane_name); |
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 |
|
|
1251 |
ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name); |
ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name); |
1252 |
} |
} |
1253 |
#endif |
|
1254 |
pane_string = (NILP (pane_name) |
pane_string = (NILP (pane_name) |
1255 |
? "" : (char *) SDATA (pane_name)); |
? "" : (char *) SDATA (pane_name)); |
1256 |
/* If there is just one top-level pane, put all its items directly |
/* If there is just one top-level pane, put all its items directly |
1268 |
save_wv->next = wv; |
save_wv->next = wv; |
1269 |
else |
else |
1270 |
first_wv->contents = wv; |
first_wv->contents = wv; |
1271 |
wv->name = pane_string; |
wv->lname = pane_name; |
1272 |
/* Ignore the @ that means "separate pane". |
/* Set value to 1 so update_submenu_strings can handle '@' */ |
1273 |
This is a kludge, but this isn't worth more time. */ |
wv->value = (char *) 1; |
|
if (!NILP (prefix) && wv->name[0] == '@') |
|
|
wv->name++; |
|
|
wv->value = 0; |
|
1274 |
wv->enabled = 1; |
wv->enabled = 1; |
1275 |
wv->button_type = BUTTON_TYPE_NONE; |
wv->button_type = BUTTON_TYPE_NONE; |
1276 |
wv->help = Qnil; |
wv->help = Qnil; |
1293 |
selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED); |
selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED); |
1294 |
help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP); |
help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP); |
1295 |
|
|
1296 |
#ifndef HAVE_MULTILINGUAL_MENU |
if (STRINGP (item_name)) |
|
if (STRING_MULTIBYTE (item_name)) |
|
1297 |
{ |
{ |
1298 |
item_name = ENCODE_SYSTEM (item_name); |
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 |
|
|
1303 |
ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name); |
ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name); |
1304 |
} |
} |
1305 |
|
|
1308 |
descrip = ENCODE_SYSTEM (descrip); |
descrip = ENCODE_SYSTEM (descrip); |
1309 |
ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip); |
ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip); |
1310 |
} |
} |
|
#endif /* not HAVE_MULTILINGUAL_MENU */ |
|
1311 |
|
|
1312 |
wv = xmalloc_widget_value (); |
wv = xmalloc_widget_value (); |
1313 |
if (prev_wv) |
if (prev_wv) |
1315 |
else |
else |
1316 |
save_wv->contents = wv; |
save_wv->contents = wv; |
1317 |
|
|
1318 |
wv->name = (char *) SDATA (item_name); |
wv->lname = item_name; |
1319 |
if (!NILP (descrip)) |
if (!NILP (descrip)) |
1320 |
wv->key = (char *) SDATA (descrip); |
wv->lkey = descrip; |
1321 |
wv->value = 0; |
wv->value = 0; |
1322 |
/* The EMACS_INT cast avoids a warning. There's no problem |
/* The EMACS_INT cast avoids a warning. There's no problem |
1323 |
as long as pointers have enough bits to hold small integers. */ |
as long as pointers have enough bits to hold small integers. */ |
1356 |
|
|
1357 |
return first_wv; |
return first_wv; |
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. */ |
1366 |
|
static void |
1367 |
|
update_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 |
|
|
1396 |
|
|
1397 |
/* Set the contents of the menubar widgets of frame F. |
/* Set the contents of the menubar widgets of frame F. |
1398 |
The argument FIRST_TIME is currently ignored; |
The argument FIRST_TIME is currently ignored; |
1561 |
if (NILP (string)) |
if (NILP (string)) |
1562 |
break; |
break; |
1563 |
wv->name = (char *) SDATA (string); |
wv->name = (char *) SDATA (string); |
1564 |
|
update_submenu_strings (wv->contents); |
1565 |
wv = wv->next; |
wv = wv->next; |
1566 |
} |
} |
1567 |
|
|
1775 |
char *pane_string; |
char *pane_string; |
1776 |
pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME); |
pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME); |
1777 |
prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); |
prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); |
1778 |
#ifndef HAVE_MULTILINGUAL_MENU |
|
1779 |
if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name)) |
if (STRINGP (pane_name)) |
1780 |
{ |
{ |
1781 |
pane_name = ENCODE_SYSTEM (pane_name); |
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 |
|
|
1786 |
ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name); |
ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name); |
1787 |
} |
} |
1788 |
#endif |
|
1789 |
pane_string = (NILP (pane_name) |
pane_string = (NILP (pane_name) |
1790 |
? "" : (char *) SDATA (pane_name)); |
? "" : (char *) SDATA (pane_name)); |
1791 |
/* If there is just one top-level pane, put all its items directly |
/* If there is just one top-level pane, put all its items directly |
1834 |
selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED); |
selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED); |
1835 |
help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP); |
help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP); |
1836 |
|
|
1837 |
#ifndef HAVE_MULTILINGUAL_MENU |
if (STRINGP (item_name)) |
|
if (STRINGP (item_name) && STRING_MULTIBYTE (item_name)) |
|
1838 |
{ |
{ |
1839 |
item_name = ENCODE_SYSTEM (item_name); |
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 |
|
|
1844 |
ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name); |
ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name); |
1845 |
} |
} |
1846 |
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) |
|
1847 |
|
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) |
1848 |
{ |
{ |
1849 |
descrip = ENCODE_SYSTEM (descrip); |
descrip = ENCODE_SYSTEM (descrip); |
1850 |
ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip); |
ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip); |
1851 |
} |
} |
|
#endif /* not HAVE_MULTILINGUAL_MENU */ |
|
1852 |
|
|
1853 |
wv = xmalloc_widget_value (); |
wv = xmalloc_widget_value (); |
1854 |
if (prev_wv) |
if (prev_wv) |
1897 |
wv_sep->next = first_wv->contents; |
wv_sep->next = first_wv->contents; |
1898 |
wv_sep->help = Qnil; |
wv_sep->help = Qnil; |
1899 |
|
|
1900 |
#ifndef HAVE_MULTILINGUAL_MENU |
if (unicode_append_menu) |
1901 |
if (STRING_MULTIBYTE (title)) |
title = ENCODE_UTF_8 (title); |
1902 |
|
else if (STRING_MULTIBYTE (title)) |
1903 |
title = ENCODE_SYSTEM (title); |
title = ENCODE_SYSTEM (title); |
1904 |
#endif |
|
1905 |
wv_title->name = (char *) SDATA (title); |
wv_title->name = (char *) SDATA (title); |
1906 |
wv_title->enabled = TRUE; |
wv_title->enabled = TRUE; |
1907 |
wv_title->title = TRUE; |
wv_title->title = TRUE; |
2204 |
return AppendMenu (menu, MF_MENUBARBREAK, 0, NULL); |
return AppendMenu (menu, MF_MENUBARBREAK, 0, NULL); |
2205 |
} |
} |
2206 |
|
|
2207 |
|
/* UTF8: 0xxxxxxx, 110xxxxx 10xxxxxx, 1110xxxx, 10xxxxxx, 10xxxxxx */ |
2208 |
|
static void |
2209 |
|
utf8to16 (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 |
|
|
2247 |
static int |
static int |
2248 |
add_menu_item (HMENU menu, widget_value *wv, HMENU item) |
add_menu_item (HMENU menu, widget_value *wv, HMENU item) |
2249 |
{ |
{ |
2300 |
fuFlags |= MF_UNCHECKED; |
fuFlags |= MF_UNCHECKED; |
2301 |
} |
} |
2302 |
|
|
2303 |
return_value = |
if (unicode_append_menu && out_string) |
2304 |
AppendMenu (menu, |
{ |
2305 |
fuFlags, |
/* Convert out_string from UTF-8 to UTF-16-LE. */ |
2306 |
item != NULL ? (UINT) item : (UINT) wv->call_data, |
int utf8_len = strlen (out_string); |
2307 |
out_string ); |
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 |
|
} |
2329 |
|
|
2330 |
/* This must be done after the menu item is created. */ |
/* This must be done after the menu item is created. */ |
2331 |
if (!wv->title && wv->call_data != 0) |
if (!wv->title && wv->call_data != 0) |
2413 |
struct frame *f = x_window_to_frame (&one_w32_display_info, owner); |
struct frame *f = x_window_to_frame (&one_w32_display_info, owner); |
2414 |
Lisp_Object frame, help; |
Lisp_Object frame, help; |
2415 |
|
|
2416 |
// No help echo on owner-draw menu items. |
/* No help echo on owner-draw menu items. */ |
2417 |
if (flags & MF_OWNERDRAW || flags & MF_POPUP) |
if (flags & MF_OWNERDRAW || flags & MF_POPUP) |
2418 |
help = Qnil; |
help = Qnil; |
2419 |
else |
else |
2537 |
HMODULE user32 = GetModuleHandle ("user32.dll"); |
HMODULE user32 = GetModuleHandle ("user32.dll"); |
2538 |
get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA"); |
get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA"); |
2539 |
set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA"); |
set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA"); |
2540 |
|
unicode_append_menu = (AppendMenuW_Proc) GetProcAddress (user32, "AppendMenuW"); |
2541 |
} |
} |
2542 |
|
|
2543 |
/* arch-tag: 0eaed431-bb4e-4aac-a527-95a1b4f1fed0 |
/* arch-tag: 0eaed431-bb4e-4aac-a527-95a1b4f1fed0 |