From 1c9b41290f206173f1031572094ec6373c265c0b Mon Sep 17 00:00:00 2001 From: Jason Rumney Date: Fri, 13 Aug 2010 22:54:32 +0800 Subject: [PATCH] Fix for bug#5629: Use unicode message box if available. * w32menu.c (simple_dialog_show): Use unicode message box if available. (MessageBoxW_Proc): New function typedef. (unicode-message-box): New function pointer. (globals_of_w32menu): Import it from user32.dll. --- src/ChangeLog | 7 +++++ src/w32menu.c | 84 +++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 75 insertions(+), 16 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 69b1e9866d5..f13e5105368 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2010-08-13 Jason Rumney + + * w32menu.c (simple_dialog_show): Use unicode message box if available. + (MessageBoxW_Proc): New function typedef. + (unicode-message-box): New function pointer. + (globals_of_w32menu): Import it from user32.dll. (Bug#5629) + 2010-08-13 Jan Djärv * frame.h (Qtool_bar_position): Declare. diff --git a/src/w32menu.c b/src/w32menu.c index 0aaca5e234e..1146843bec8 100644 --- a/src/w32menu.c +++ b/src/w32menu.c @@ -72,10 +72,16 @@ typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) ( IN UINT, IN BOOL, IN LPCMENUITEMINFOA); +typedef int (WINAPI * MessageBoxW_Proc) ( + IN HWND window, + IN WCHAR *text, + IN WCHAR *caption, + IN UINT type); GetMenuItemInfoA_Proc get_menu_item_info = NULL; SetMenuItemInfoA_Proc set_menu_item_info = NULL; AppendMenuW_Proc unicode_append_menu = NULL; +MessageBoxW_Proc unicode_message_box = NULL; Lisp_Object Qdebug_on_next_call; @@ -99,6 +105,8 @@ static int is_simple_dialog (Lisp_Object); static Lisp_Object simple_dialog_show (FRAME_PTR, Lisp_Object, Lisp_Object); #endif +static void utf8to16 (unsigned char *, int, WCHAR *); + void w32_free_menu_strings (HWND); @@ -1220,30 +1228,73 @@ simple_dialog_show (FRAME_PTR f, Lisp_Object contents, Lisp_Object header) { int answer; UINT type; - char *text, *title; Lisp_Object lispy_answer = Qnil, temp = XCAR (contents); - if (STRINGP (temp)) - text = SDATA (temp); - else - text = ""; + type = MB_YESNO; + + /* Since we only handle Yes/No dialogs, and we already checked + is_simple_dialog, we don't need to worry about checking contents + to see what type of dialog to use. */ - if (NILP (header)) + /* Use unicode if possible, so any language can be displayed. */ + if (unicode_message_box) { - title = "Question"; - type = MB_ICONQUESTION; + WCHAR *text, *title; + + if (STRINGP (temp)) + { + char *utf8_text = SDATA (ENCODE_UTF_8 (temp)); + /* Be pessimistic about the number of characters needed. + Remember characters outside the BMP will take more than + one utf16 word, so we cannot simply use the character + length of temp. */ + int utf8_len = strlen (utf8_text); + text = alloca ((utf8_len + 1) * sizeof (WCHAR)); + utf8to16 (utf8_text, utf8_len, text); + } + else + { + text = L""; + } + + if (NILP (header)) + { + title = L"Question"; + type |= MB_ICONQUESTION; + } + else + { + title = L"Information"; + type |= MB_ICONINFORMATION; + } + + answer = unicode_message_box (FRAME_W32_WINDOW (f), text, title, type); } else { - title = "Information"; - type = MB_ICONINFORMATION; - } - type |= MB_YESNO; + char *text, *title; - /* Since we only handle Yes/No dialogs, and we already checked - is_simple_dialog, we don't need to worry about checking contents - to see what type of dialog to use. */ - answer = MessageBox (FRAME_W32_WINDOW (f), text, title, type); + /* Fall back on ANSI message box, but at least use system + encoding so questions representable by the system codepage + are encoded properly. */ + if (STRINGP (temp)) + text = SDATA (ENCODE_SYSTEM (temp)); + else + text = ""; + + if (NILP (header)) + { + title = "Question"; + type |= MB_ICONQUESTION; + } + else + { + title = "Information"; + type |= MB_ICONINFORMATION; + } + + answer = MessageBox (FRAME_W32_WINDOW (f), text, title, type); + } if (answer == IDYES) lispy_answer = build_string ("Yes"); @@ -1697,6 +1748,7 @@ globals_of_w32menu (void) get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA"); set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA"); unicode_append_menu = (AppendMenuW_Proc) GetProcAddress (user32, "AppendMenuW"); + unicode_message_box = (MessageBoxW_Proc) GetProcAddress (user32, "MessageBoxW"); } /* arch-tag: 0eaed431-bb4e-4aac-a527-95a1b4f1fed0 -- 2.39.2