diff options
Diffstat (limited to 'src/w32menu.c')
-rw-r--r-- | src/w32menu.c | 202 |
1 files changed, 102 insertions, 100 deletions
diff --git a/src/w32menu.c b/src/w32menu.c index 82536c984b4..ff6bd977bea 100644 --- a/src/w32menu.c +++ b/src/w32menu.c @@ -59,8 +59,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ HMENU current_popup_menu; -void syms_of_w32menu (); -void globals_of_w32menu (); +void syms_of_w32menu (void); +void globals_of_w32menu (void); typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) ( IN HMENU, @@ -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; @@ -90,16 +96,19 @@ extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; extern Lisp_Object Qmenu_bar_update_hook; -void set_frame_menubar P_ ((FRAME_PTR, int, int)); +void set_frame_menubar (FRAME_PTR, int, int); #ifdef HAVE_DIALOGS -static Lisp_Object w32_dialog_show P_ ((FRAME_PTR, int, Lisp_Object, char**)); +static Lisp_Object w32_dialog_show (FRAME_PTR, int, Lisp_Object, char**); #else -static int is_simple_dialog P_ ((Lisp_Object)); -static Lisp_Object simple_dialog_show P_ ((FRAME_PTR, Lisp_Object, Lisp_Object)); +static int is_simple_dialog (Lisp_Object); +static Lisp_Object simple_dialog_show (FRAME_PTR, Lisp_Object, Lisp_Object); #endif -void w32_free_menu_strings P_ ((HWND)); +static void utf8to16 (unsigned char *, int, WCHAR *); +static int fill_in_menu (HMENU, widget_value *); + +void w32_free_menu_strings (HWND); /* This is set nonzero after the user activates the menu bar, and set @@ -111,31 +120,6 @@ void w32_free_menu_strings P_ ((HWND)); int pending_menu_activation; - -/* Return the frame whose ->output_data.w32->menubar_widget equals - ID, or 0 if none. */ - -static struct frame * -menubar_id_to_frame (id) - HMENU id; -{ - Lisp_Object tail, frame; - FRAME_PTR f; - - for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail)) - { - frame = XCAR (tail); - if (!FRAMEP (frame)) - continue; - f = XFRAME (frame); - if (!FRAME_WINDOW_P (f)) - continue; - if (f->output_data.w32->menubar_widget == id) - return f; - } - return 0; -} - #ifdef HAVE_MENUS DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0, @@ -157,8 +141,7 @@ on the left of the dialog box and all following items on the right. If HEADER is non-nil, the frame title for the box is "Information", otherwise it is "Question". */) - (position, contents, header) - Lisp_Object position, contents, header; + (Lisp_Object position, Lisp_Object contents, Lisp_Object header) { FRAME_PTR f = NULL; Lisp_Object window; @@ -276,8 +259,7 @@ otherwise it is "Question". */) This way we can safely execute Lisp code. */ void -x_activate_menubar (f) - FRAME_PTR f; +x_activate_menubar (FRAME_PTR f) { set_frame_menubar (f, 0, 1); @@ -386,10 +368,7 @@ menubar_selection_callback (FRAME_PTR f, void * client_data) it is set the first time this is called, from initialize_frame_menubar. */ void -set_frame_menubar (f, first_time, deep_p) - FRAME_PTR f; - int first_time; - int deep_p; +set_frame_menubar (FRAME_PTR f, int first_time, int deep_p) { HMENU menubar_widget = f->output_data.w32->menubar_widget; Lisp_Object items; @@ -442,12 +421,8 @@ set_frame_menubar (f, first_time, deep_p) set_buffer_internal_1 (XBUFFER (buffer)); - /* Run the Lucid hook. */ + /* Run the hooks. */ safe_run_hooks (Qactivate_menubar_hook); - /* If it has changed current-menubar from previous value, - really recompute the menubar from the value. */ - if (! NILP (Vlucid_menu_bar_dirty_flag)) - call0 (Qrecompute_lucid_menubar); safe_run_hooks (Qmenu_bar_update_hook); FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); @@ -455,8 +430,8 @@ set_frame_menubar (f, first_time, deep_p) /* Save the frame's previous menu bar contents data. */ if (previous_menu_items_used) - bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items, - previous_menu_items_used * sizeof (Lisp_Object)); + memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents, + previous_menu_items_used * sizeof (Lisp_Object)); /* Fill in menu_items with the current menu bar contents. This can evaluate Lisp code. */ @@ -648,8 +623,7 @@ set_frame_menubar (f, first_time, deep_p) is visible. */ void -initialize_frame_menubar (f) - FRAME_PTR f; +initialize_frame_menubar (FRAME_PTR f) { /* This function is called before the first chance to redisplay the frame. It has to be, so the frame will have the right size. */ @@ -661,8 +635,7 @@ initialize_frame_menubar (f) This is used when deleting a frame, and when turning off the menu bar. */ void -free_frame_menubar (f) - FRAME_PTR f; +free_frame_menubar (FRAME_PTR f) { BLOCK_INPUT; @@ -694,7 +667,7 @@ free_frame_menubar (f) Lisp_Object w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps, - Lisp_Object title, char **error) + Lisp_Object title, const char **error) { int i; int menu_item_selection; @@ -1020,11 +993,9 @@ static char * button_names [] = { "button6", "button7", "button8", "button9", "button10" }; static Lisp_Object -w32_dialog_show (f, keymaps, title, header, error) - FRAME_PTR f; - int keymaps; - Lisp_Object title, header; - char **error; +w32_dialog_show (FRAME_PTR f, int keymaps, + Lisp_Object title, Lisp_Object header, + char **error) { int i, nb_buttons = 0; char dialog_name[6]; @@ -1214,8 +1185,7 @@ w32_dialog_show (f, keymaps, title, header, error) MessageBox provides. */ static int -is_simple_dialog (contents) - Lisp_Object contents; +is_simple_dialog (Lisp_Object contents) { Lisp_Object options = XCDR (contents); Lisp_Object name, yes, no, other; @@ -1251,36 +1221,77 @@ is_simple_dialog (contents) } static Lisp_Object -simple_dialog_show (f, contents, header) - FRAME_PTR f; - Lisp_Object contents, header; +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; - if (NILP (header)) + /* 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. */ + + /* 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"); @@ -1317,10 +1328,9 @@ simple_dialog_show (f, contents, header) /* Is this item a separator? */ static int -name_is_separator (name) - char *name; +name_is_separator (const char *name) { - char *start = name; + const char *start = name; /* Check if name string consists of only dashes ('-'). */ while (*name == '-') name++; @@ -1330,13 +1340,6 @@ name_is_separator (name) return (*name == '\0' || start + 2 == name); } -/* Indicate boundary between left and right. */ -static int -add_left_right_boundary (HMENU menu) -{ - return AppendMenu (menu, MF_MENUBARBREAK, 0, NULL); -} - /* UTF8: 0xxxxxxx, 110xxxxx 10xxxxxx, 1110xxxx, 10xxxxxx, 10xxxxxx */ static void utf8to16 (unsigned char * src, int len, WCHAR * dest) @@ -1405,7 +1408,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) strcat (out_string, wv->key); } else - out_string = wv->name; + out_string = (char *)wv->name; /* Quote any special characters within the menu item's text and key binding. */ @@ -1534,7 +1537,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) if (set_menu_item_info) { MENUITEMINFO info; - bzero (&info, sizeof (info)); + memset (&info, 0, sizeof (info)); info.cbSize = sizeof (info); info.fMask = MIIM_DATA; @@ -1566,7 +1569,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) } /* Construct native Windows menu(bar) based on widget_value tree. */ -int +static int fill_in_menu (HMENU menu, widget_value *wv) { int items_added = 0; @@ -1617,7 +1620,7 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags) { MENUITEMINFO info; - bzero (&info, sizeof (info)); + memset (&info, 0, sizeof (info)); info.cbSize = sizeof (info); info.fMask = MIIM_DATA; get_menu_item_info (menu, item, FALSE, &info); @@ -1648,14 +1651,13 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags) /* Free memory used by owner-drawn strings. */ static void -w32_free_submenu_strings (menu) - HMENU menu; +w32_free_submenu_strings (HMENU menu) { int i, num = GetMenuItemCount (menu); for (i = 0; i < num; i++) { MENUITEMINFO info; - bzero (&info, sizeof (info)); + memset (&info, 0, sizeof (info)); info.cbSize = sizeof (info); info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_SUBMENU; @@ -1677,8 +1679,7 @@ w32_free_submenu_strings (menu) } void -w32_free_menu_strings (hwnd) - HWND hwnd; +w32_free_menu_strings (HWND hwnd) { HMENU menu = current_popup_menu; @@ -1702,7 +1703,7 @@ w32_free_menu_strings (hwnd) DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0, doc: /* Return t if a menu or popup dialog is active on selected frame. */) - () + (void) { #ifdef HAVE_MENUS FRAME_PTR f; @@ -1714,7 +1715,7 @@ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_ } void -syms_of_w32menu () +syms_of_w32menu (void) { globals_of_w32menu (); @@ -1737,13 +1738,14 @@ syms_of_w32menu () is non zero. */ void -globals_of_w32menu () +globals_of_w32menu (void) { /* See if Get/SetMenuItemInfo functions are available. */ HMODULE user32 = GetModuleHandle ("user32.dll"); 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 |