X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/5df4f04cd32af723742c81095b38ae83b3c2b462..b97f22cdad55a0964758cef3a19ce3fa1098657d:/src/w32menu.c diff --git a/src/w32menu.c b/src/w32menu.c index d85a17e5b8..36bf9574fd 100644 --- a/src/w32menu.c +++ b/src/w32menu.c @@ -1,6 +1,5 @@ -/* Menu support for GNU Emacs on the Microsoft W32 API. - Copyright (C) 1986, 1988, 1993, 1994, 1996, 1998, 1999, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 +/* Menu support for GNU Emacs on the Microsoft Windows API. + Copyright (C) 1986, 1988, 1993-1994, 1996, 1998-1999, 2001-2012 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -22,7 +21,6 @@ along with GNU Emacs. If not, see . */ #include #include -#include #include #include "lisp.h" @@ -32,9 +30,9 @@ along with GNU Emacs. If not, see . */ #include "termhooks.h" #include "window.h" #include "blockinput.h" +#include "character.h" #include "buffer.h" #include "charset.h" -#include "character.h" #include "coding.h" #include "menu.h" @@ -42,6 +40,14 @@ along with GNU Emacs. If not, see . */ if this is not done before the other system files. */ #include "w32term.h" +/* Cygwin does not support the multibyte string functions declared in + * mbstring.h below --- but that's okay: because Cygwin is + * UNICODE-only, we don't need to use these functions anyway. */ + +#ifndef NTGUI_UNICODE +#include +#endif /* !NTGUI_UNICODE */ + /* Load sys/types.h if not already loaded. In some systems loading it twice is suicidal. */ #ifndef makedev @@ -50,6 +56,8 @@ along with GNU Emacs. If not, see . */ #include "dispextern.h" +#include "w32common.h" /* for osinfo_cache */ + #undef HAVE_DIALOGS /* TODO: Implement native dialogs. */ #ifndef TRUE @@ -59,8 +67,8 @@ along with GNU Emacs. If not, see . */ 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,34 +80,40 @@ 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); + +#ifdef NTGUI_UNICODE +#define get_menu_item_info GetMenuItemInfoA +#define set_menu_item_info SetMenuItemInfoA +#define unicode_append_menu AppendMenuW +#define unicode_message_box MessageBoxW +#else /* !NTGUI_UNICODE */ 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; +#endif /* NTGUI_UNICODE */ Lisp_Object Qdebug_on_next_call; -extern Lisp_Object Qmenu_bar; - -extern Lisp_Object QCtoggle, QCradio; - -extern Lisp_Object Voverriding_local_map; -extern Lisp_Object Voverriding_local_map_menu_flag; - -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, bool, bool); #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 +125,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 +146,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; @@ -175,7 +163,7 @@ otherwise it is "Question". */) FRAME_PTR new_f = SELECTED_FRAME (); Lisp_Object bar_window; enum scroll_bar_part part; - unsigned long time; + Time time; Lisp_Object x, y; (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time); @@ -189,13 +177,12 @@ otherwise it is "Question". */) } else if (CONSP (position)) { - Lisp_Object tem; - tem = Fcar (position); + Lisp_Object tem = XCAR (position); if (CONSP (tem)) - window = Fcar (Fcdr (position)); + window = Fcar (XCDR (position)); else { - tem = Fcar (Fcdr (position)); /* EVENT_START (position) */ + tem = Fcar (XCDR (position)); /* EVENT_START (position) */ window = Fcar (tem); /* POSN_WINDOW (tem) */ } } @@ -250,9 +237,9 @@ otherwise it is "Question". */) list_of_panes (Fcons (contents, Qnil)); /* Display them in a dialog box. */ - BLOCK_INPUT; + block_input (); selection = w32_dialog_show (f, 0, title, header, &error_name); - UNBLOCK_INPUT; + unblock_input (); discard_menu_items (); FRAME_X_DISPLAY_INFO (f)->grabbed = 0; @@ -276,8 +263,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); @@ -305,7 +291,7 @@ menubar_selection_callback (FRAME_PTR f, void * client_data) if (!f) return; entry = Qnil; - subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * sizeof (Lisp_Object)); + subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * word_size); vector = f->menu_bar_vector; prefix = Qnil; i = 0; @@ -386,10 +372,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, bool first_time, bool deep_p) { HMENU menubar_widget = f->output_data.w32->menubar_widget; Lisp_Object items; @@ -415,11 +398,11 @@ set_frame_menubar (f, first_time, deep_p) struct buffer *prev = current_buffer; Lisp_Object buffer; - int specpdl_count = SPECPDL_INDEX (); + ptrdiff_t specpdl_count = SPECPDL_INDEX (); int previous_menu_items_used = f->menu_bar_items_used; Lisp_Object *previous_items = (Lisp_Object *) alloca (previous_menu_items_used - * sizeof (Lisp_Object)); + * word_size); /* If we are making a new widget, its contents are empty, do always reinitialize them. */ @@ -442,21 +425,17 @@ 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)); + fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f))); items = FRAME_MENU_BAR_ITEMS (f); /* 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 * word_size); /* Fill in menu_items with the current menu bar contents. This can evaluate Lisp code. */ @@ -464,11 +443,10 @@ set_frame_menubar (f, first_time, deep_p) menu_items = f->menu_bar_vector; menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0; - submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); - submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); - submenu_n_panes = (int *) alloca (XVECTOR (items)->size * sizeof (int)); - submenu_top_level_items - = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); + submenu_start = (int *) alloca (ASIZE (items) * sizeof (int)); + submenu_end = (int *) alloca (ASIZE (items) * sizeof (int)); + submenu_n_panes = (int *) alloca (ASIZE (items) * sizeof (int)); + submenu_top_level_items = (int *) alloca (ASIZE (items) * sizeof (int)); init_menu_items (); for (i = 0; i < ASIZE (items); i += 4) { @@ -537,7 +515,7 @@ set_frame_menubar (f, first_time, deep_p) return; } - f->menu_bar_vector = menu_items; + fset_menu_bar_vector (f, menu_items); f->menu_bar_items_used = menu_items_used; /* This undoes save_menu_items. */ @@ -555,7 +533,7 @@ set_frame_menubar (f, first_time, deep_p) string = AREF (items, i + 1); if (NILP (string)) break; - wv->name = (char *) SDATA (string); + wv->name = SSDATA (string); update_submenu_strings (wv->contents); wv = wv->next; } @@ -583,7 +561,7 @@ set_frame_menubar (f, first_time, deep_p) break; wv = xmalloc_widget_value (); - wv->name = (char *) SDATA (string); + wv->name = SSDATA (string); wv->value = 0; wv->enabled = 1; wv->button_type = BUTTON_TYPE_NONE; @@ -609,7 +587,7 @@ set_frame_menubar (f, first_time, deep_p) /* Create or update the menu bar widget. */ - BLOCK_INPUT; + block_input (); if (menubar_widget) { @@ -639,7 +617,7 @@ set_frame_menubar (f, first_time, deep_p) x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f)); } - UNBLOCK_INPUT; + unblock_input (); } /* Called from Fx_create_frame to create the initial menubar of a frame @@ -648,12 +626,11 @@ 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. */ - FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); + fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f))); set_frame_menubar (f, 1, 1); } @@ -661,10 +638,9 @@ 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; + block_input (); { HMENU old = GetMenu (FRAME_W32_WINDOW (f)); @@ -673,7 +649,7 @@ free_frame_menubar (f) DestroyMenu (old); } - UNBLOCK_INPUT; + unblock_input (); } @@ -694,7 +670,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; @@ -704,7 +680,7 @@ w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps, widget_value **submenu_stack = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); Lisp_Object *subprefix_stack - = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object)); + = (Lisp_Object *) alloca (menu_items_used * word_size); int submenu_depth = 0; int first_pane; @@ -775,7 +751,7 @@ w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps, } pane_string = (NILP (pane_name) - ? "" : (char *) SDATA (pane_name)); + ? "" : SSDATA (pane_name)); /* If there is just one top-level pane, put all its items directly under the top-level menu. */ if (menu_items_n_panes == 1) @@ -843,9 +819,9 @@ w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps, prev_wv->next = wv; else save_wv->contents = wv; - wv->name = (char *) SDATA (item_name); + wv->name = SSDATA (item_name); if (!NILP (descrip)) - wv->key = (char *) SDATA (descrip); + wv->key = SSDATA (descrip); wv->value = 0; /* Use the contents index as call_data, since we are restricted to 16-bits. */ @@ -859,7 +835,7 @@ w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps, else if (EQ (type, QCradio)) wv->button_type = BUTTON_TYPE_RADIO; else - abort (); + emacs_abort (); wv->selected = !NILP (selected); @@ -891,7 +867,7 @@ w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps, else if (STRING_MULTIBYTE (title)) title = ENCODE_SYSTEM (title); - wv_title->name = (char *) SDATA (title); + wv_title->name = SSDATA (title); wv_title->enabled = TRUE; wv_title->title = TRUE; wv_title->button_type = BUTTON_TYPE_NONE; @@ -1020,11 +996,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]; @@ -1053,7 +1027,7 @@ w32_dialog_show (f, keymaps, title, header, error) pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME); prefix = AREF (menu_items, MENU_ITEMS_PANE_PREFIX); pane_string = (NILP (pane_name) - ? "" : (char *) SDATA (pane_name)); + ? "" : SSDATA (pane_name)); prev_wv = xmalloc_widget_value (); prev_wv->value = pane_string; if (keymaps && !NILP (prefix)) @@ -1101,9 +1075,9 @@ w32_dialog_show (f, keymaps, title, header, error) prev_wv->next = wv; wv->name = (char *) button_names[nb_buttons]; if (!NILP (descrip)) - wv->key = (char *) SDATA (descrip); - wv->value = (char *) SDATA (item_name); - wv->call_data = (void *) &AREF (menu_items, i); + wv->key = SSDATA (descrip); + wv->value = SSDATA (item_name); + wv->call_data = aref_addr (menu_items, i); wv->enabled = !NILP (enable); wv->help = Qnil; prev_wv = wv; @@ -1214,21 +1188,25 @@ 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 options; Lisp_Object name, yes, no, other; + if (!CONSP (contents)) + return 0; + options = XCDR (contents); + yes = build_string ("Yes"); no = build_string ("No"); if (!CONSP (options)) return 0; - name = XCAR (XCAR (options)); - if (!CONSP (options)) + name = XCAR (options); + if (!CONSP (name)) return 0; + name = XCAR (name); if (!NILP (Fstring_equal (name, yes))) other = no; @@ -1241,7 +1219,10 @@ is_simple_dialog (contents) if (!CONSP (options)) return 0; - name = XCAR (XCAR (options)); + name = XCAR (options); + if (!CONSP (name)) + return 0; + name = XCAR (name); if (NILP (Fstring_equal (name, other))) return 0; @@ -1251,36 +1232,79 @@ 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; + USE_SAFE_ALLOCA; + + 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 = SAFE_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); + SAFE_FREE (); } 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"); @@ -1315,35 +1339,12 @@ simple_dialog_show (f, contents, header) #endif /* !HAVE_DIALOGS */ -/* Is this item a separator? */ -static int -name_is_separator (name) - char *name; -{ - char *start = name; - - /* Check if name string consists of only dashes ('-'). */ - while (*name == '-') name++; - /* Separators can also be of the form "--:TripleSuperMegaEtched" - or "--deep-shadow". We don't implement them yet, se we just treat - them like normal separators. */ - 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) { while (len > 0) { - int utf16; if (*src < 0x80) { *dest = (WCHAR) *src; @@ -1384,8 +1385,9 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) char *out_string, *p, *q; int return_value; size_t nlen, orig_len; + USE_SAFE_ALLOCA; - if (name_is_separator (wv->name)) + if (menu_separator_name_p (wv->name)) { fuFlags = MF_SEPARATOR; out_string = NULL; @@ -1399,13 +1401,13 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) if (wv->key != NULL) { - out_string = alloca (strlen (wv->name) + strlen (wv->key) + 2); + out_string = SAFE_ALLOCA (strlen (wv->name) + strlen (wv->key) + 2); strcpy (out_string, wv->name); strcat (out_string, "\t"); 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. */ @@ -1419,6 +1421,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) nlen++; } } +#ifndef NTGUI_UNICODE else { /* If encoded with the system codepage, use multibyte string @@ -1429,11 +1432,12 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) nlen++; } } +#endif /* !NTGUI_UNICODE */ if (nlen > orig_len) { p = out_string; - out_string = alloca (nlen + 1); + out_string = SAFE_ALLOCA (nlen + 1); q = out_string; while (*p) { @@ -1443,6 +1447,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) *q++ = *p; *q++ = *p++; } +#ifndef NTGUI_UNICODE else { if (_mbsnextc (p) == '&') @@ -1454,6 +1459,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) p = _mbsinc (p); q = _mbsinc (q); } +#endif /* !NTGUI_UNICODE */ } *q = '\0'; } @@ -1469,7 +1475,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) out_string = (char *) local_alloc (strlen (wv->name) + 1); strcpy (out_string, wv->name); #ifdef MENU_DEBUG - DebPrint ("Menu: allocing %ld for owner-draw", out_string); + DebPrint ("Menu: allocating %ld for owner-draw", out_string); #endif fuFlags = MF_OWNERDRAW | MF_DISABLED; } @@ -1493,16 +1499,18 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) if (fuFlags & MF_OWNERDRAW) utf16_string = local_alloc ((utf8_len + 1) * sizeof (WCHAR)); else - utf16_string = alloca ((utf8_len + 1) * sizeof (WCHAR)); + utf16_string = SAFE_ALLOCA ((utf8_len + 1) * sizeof (WCHAR)); utf8to16 (out_string, utf8_len, utf16_string); return_value = unicode_append_menu (menu, fuFlags, - item != NULL ? (UINT) item - : (UINT) wv->call_data, + item != NULL ? (UINT_PTR) item + : (UINT_PTR) wv->call_data, utf16_string); + +#ifndef NTGUI_UNICODE /* Fallback does not apply when always UNICODE */ if (!return_value) { - /* On W9x/ME, unicode menus are not supported, though AppendMenuW + /* On W9x/ME, Unicode menus are not supported, though AppendMenuW apparently does exist at least in some cases and appears to be stubbed out to do nothing. out_string is UTF-8, but since our standard menus are in English and this is only going to @@ -1510,11 +1518,15 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) of minor importance compared with menus not working at all. */ return_value = AppendMenu (menu, fuFlags, - item != NULL ? (UINT) item: (UINT) wv->call_data, + item != NULL ? (UINT_PTR) item: (UINT_PTR) wv->call_data, out_string); - /* Don't use unicode menus in future. */ - unicode_append_menu = NULL; + /* Don't use Unicode menus in future, unless this is Windows + NT or later, where a failure of AppendMenuW does NOT mean + Unicode menus are unsupported. */ + if (osinfo_cache.dwPlatformId != VER_PLATFORM_WIN32_NT) + unicode_append_menu = NULL; } +#endif /* NTGUI_UNICODE */ if (unicode_append_menu && (fuFlags & MF_OWNERDRAW)) local_free (out_string); @@ -1524,7 +1536,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) return_value = AppendMenu (menu, fuFlags, - item != NULL ? (UINT) item : (UINT) wv->call_data, + item != NULL ? (UINT_PTR) item : (UINT_PTR) wv->call_data, out_string ); } @@ -1534,7 +1546,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; @@ -1542,11 +1554,14 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) until it is ready to be displayed, since GC can happen while menus are active. */ if (!NILP (wv->help)) -#ifdef USE_LISP_UNION_TYPE - info.dwItemData = (DWORD) (wv->help).i; -#else - info.dwItemData = (DWORD) (wv->help); -#endif + { + /* As of Jul-2012, w32api headers say that dwItemData + has DWORD type, but that's a bug: it should actually + be ULONG_PTR, which is correct for 32-bit and 64-bit + Windows alike. MSVC headers get it right; hopefully, + MinGW headers will, too. */ + info.dwItemData = (ULONG_PTR) XLI (wv->help); + } if (wv->button_type == BUTTON_TYPE_RADIO) { /* CheckMenuRadioItem allows us to differentiate TOGGLE and @@ -1558,19 +1573,18 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) } set_menu_item_info (menu, - item != NULL ? (UINT) item : (UINT) wv->call_data, + item != NULL ? (UINT_PTR) item : (UINT_PTR) wv->call_data, FALSE, &info); } } + SAFE_FREE (); return return_value; } /* 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; - for ( ; wv != NULL; wv = wv->next) { if (wv->contents) @@ -1617,17 +1631,12 @@ 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); -#ifdef USE_LISP_UNION_TYPE - help = info.dwItemData ? (Lisp_Object) ((EMACS_INT) info.dwItemData) - : Qnil; -#else - help = info.dwItemData ? (Lisp_Object) info.dwItemData : Qnil; -#endif + help = info.dwItemData ? XIL (info.dwItemData) : Qnil; } /* Store the help echo in the keyboard buffer as the X toolkit @@ -1642,20 +1651,19 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags) else /* X version has a loop through frames here, which doesn't appear to do anything, unless it has some side effect. */ - show_help_echo (help, Qnil, Qnil, Qnil, 1); + show_help_echo (help, Qnil, Qnil, Qnil); } } /* 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 +1685,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 +1709,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 +1721,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,14 +1744,14 @@ syms_of_w32menu () is non zero. */ void -globals_of_w32menu () +globals_of_w32menu (void) { +#ifndef NTGUI_UNICODE /* 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"); +#endif /* !NTGUI_UNICODE */ } - -/* arch-tag: 0eaed431-bb4e-4aac-a527-95a1b4f1fed0 - (do not change this comment) */