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) */