/* Menu support for GNU Emacs on the Microsoft Windows API.
- Copyright (C) 1986, 1988, 1993-1994, 1996, 1998-1999, 2001-2014 Free
+ Copyright (C) 1986, 1988, 1993-1994, 1996, 1998-1999, 2001-2016 Free
Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
#include "lisp.h"
#include "keyboard.h"
-#include "keymap.h"
#include "frame.h"
-#include "termhooks.h"
-#include "window.h"
#include "blockinput.h"
-#include "character.h"
#include "buffer.h"
-#include "charset.h"
-#include "coding.h"
+#include "coding.h" /* for ENCODE_SYSTEM */
#include "menu.h"
/* This may include sys/types.h, and that somehow loses
#include <sys/types.h>
#endif
-#include "dispextern.h"
-
#include "w32common.h" /* for osinfo_cache */
#undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
MessageBoxW_Proc unicode_message_box = NULL;
#endif /* NTGUI_UNICODE */
-Lisp_Object Qdebug_on_next_call, Qunsupported__w32_dialog;
-
void set_frame_menubar (struct frame *, bool, bool);
#ifdef HAVE_DIALOGS
static Lisp_Object w32_dialog_show (struct frame *, Lisp_Object, Lisp_Object, char **);
#else
-static int is_simple_dialog (Lisp_Object);
+static bool is_simple_dialog (Lisp_Object);
static Lisp_Object simple_dialog_show (struct frame *, Lisp_Object, Lisp_Object);
#endif
void
x_activate_menubar (struct frame *f)
{
- set_frame_menubar (f, 0, 1);
+ set_frame_menubar (f, false, true);
/* Lock out further menubar changes while active. */
f->output_data.w32->menubar_active = 1;
else
{
entry = AREF (vector, i + MENU_ITEMS_ITEM_VALUE);
- /* The EMACS_INT cast avoids a warning. There's no problem
+ /* The UINT_PTR cast avoids a warning. There's no problem
as long as pointers have enough bits to hold small integers. */
- if ((int) (EMACS_INT) client_data == i)
+ if ((int) (UINT_PTR) client_data == i)
{
int j;
struct input_event buf;
XSETFRAME (Vmenu_updating_frame, f);
if (! menubar_widget)
- deep_p = 1;
+ deep_p = true;
if (deep_p)
{
else
first_wv->contents = wv;
/* Don't set wv->name here; GC during the loop might relocate it. */
- wv->enabled = 1;
+ wv->enabled = true;
wv->button_type = BUTTON_TYPE_NONE;
prev_wv = wv;
}
/* Force the window size to be recomputed so that the frame's text
area remains the same, if menubar has just been created. */
if (old_widget == NULL)
- adjust_frame_size (f, FRAME_TEXT_WIDTH (f),
- FRAME_TEXT_HEIGHT (f), 2, 0, Qmenu_bar_lines);
+ {
+ windows_or_buffers_changed = 23;
+ adjust_frame_size (f, -1, -1, 2, false, Qmenu_bar_lines);
+ }
}
unblock_input ();
/* This function is called before the first chance to redisplay
the frame. It has to be, so the frame will have the right size. */
fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
- set_frame_menubar (f, 1, 1);
+ set_frame_menubar (f, true, true);
}
/* Get rid of the menu bar of frame F, and free its storage.
Lisp_Object *subprefix_stack
= (Lisp_Object *) alloca (menu_items_used * word_size);
int submenu_depth = 0;
- int first_pane;
+ bool first_pane;
*error = NULL;
wv = make_widget_value ("menu", NULL, true, Qnil);
wv->button_type = BUTTON_TYPE_NONE;
first_wv = wv;
- first_pane = 1;
+ first_pane = true;
/* Loop over all panes and items, filling in the tree. */
i = 0;
submenu_stack[submenu_depth++] = save_wv;
save_wv = prev_wv;
prev_wv = 0;
- first_pane = 1;
+ first_pane = false;
i++;
}
else if (EQ (AREF (menu_items, i), Qlambda))
{
prev_wv = save_wv;
save_wv = submenu_stack[--submenu_depth];
- first_pane = 0;
+ first_pane = false;
i++;
}
else if (EQ (AREF (menu_items, i), Qt)
save_wv = wv;
prev_wv = 0;
}
- first_pane = 0;
+ first_pane = false;
i += MENU_ITEMS_PANE_LENGTH;
}
else
wv->key = SSDATA (descrip);
/* Use the contents index as call_data, since we are
restricted to 16-bits. */
- wv->call_data = !NILP (def) ? (void *) (EMACS_INT) i : 0;
+ wv->call_data = !NILP (def) ? (void *) (UINT_PTR) i : 0;
if (NILP (type))
wv->button_type = BUTTON_TYPE_NONE;
/* Number of elements seen so far, before boundary. */
int left_count = 0;
- /* 1 means we've seen the boundary between left-hand elts and right-hand. */
- int boundary_seen = 0;
+ /* true means we've seen the boundary between left-hand elts and
+ right-hand. */
+ bool boundary_seen = false;
*error = NULL;
{
/* This is the boundary between left-side elts
and right-side elts. Stop incrementing right_count. */
- boundary_seen = 1;
+ boundary_seen = true;
i++;
continue;
}
/* Actually create the dialog. */
dialog_id = widget_id_tick++;
menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
- f->output_data.w32->widget, 1, 0,
+ f->output_data.w32->widget, true, 0,
dialog_selection_callback, 0);
lw_modify_all_widgets (dialog_id, first_wv->contents, TRUE);
anywhere in Emacs that uses the other specific dialog choices that
MessageBox provides. */
-static int
+static bool
is_simple_dialog (Lisp_Object contents)
{
Lisp_Object options;
Lisp_Object name, yes, no, other;
if (!CONSP (contents))
- return 0;
+ return false;
options = XCDR (contents);
yes = build_string ("Yes");
no = build_string ("No");
if (!CONSP (options))
- return 0;
+ return false;
name = XCAR (options);
if (!CONSP (name))
- return 0;
+ return false;
name = XCAR (name);
if (!NILP (Fstring_equal (name, yes)))
else if (!NILP (Fstring_equal (name, no)))
other = yes;
else
- return 0;
+ return false;
options = XCDR (options);
if (!CONSP (options))
- return 0;
+ return false;
name = XCAR (options);
if (!CONSP (name))
- return 0;
+ return false;
name = XCAR (name);
if (NILP (Fstring_equal (name, other)))
- return 0;
+ return false;
/* Check there are no more options. */
options = XCDR (options);
if (STRINGP (temp))
{
- char *utf8_text = SDATA (ENCODE_UTF_8 (temp));
+ char *utf8_text = SSDATA (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);
+ utf8to16 ((unsigned char *)utf8_text, utf8_len, text);
}
else
{
encoding so questions representable by the system codepage
are encoded properly. */
if (STRINGP (temp))
- text = SDATA (ENCODE_SYSTEM (temp));
+ text = SSDATA (ENCODE_SYSTEM (temp));
else
text = "";
else
utf16_string = SAFE_ALLOCA ((utf8_len + 1) * sizeof (WCHAR));
- utf8to16 (out_string, utf8_len, utf16_string);
+ utf8to16 ((unsigned char *)out_string, utf8_len, utf16_string);
return_value = unicode_append_menu (menu, fuFlags,
item != NULL ? (UINT_PTR) item
: (UINT_PTR) wv->call_data,
info.cbSize = sizeof (info);
info.fMask = MIIM_DATA;
- /* Set help string for menu item. Leave it as a Lisp_Object
- until it is ready to be displayed, since GC can happen while
- menus are active. */
+ /* Set help string for menu item. Leave it as a pointer to
+ a Lisp_String until it is ready to be displayed, since GC
+ can happen while menus are active. */
if (!NILP (wv->help))
{
+ /* We use XUNTAG below because in a 32-bit build
+ --with-wide-int we cannot pass a Lisp_Object
+ via a DWORD member of MENUITEMINFO. */
/* 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);
+ eassert (STRINGP (wv->help));
+ info.dwItemData = (ULONG_PTR) XUNTAG (wv->help, Lisp_String);
}
if (wv->button_type == BUTTON_TYPE_RADIO)
{
struct frame *f = x_window_to_frame (&one_w32_display_info, owner);
Lisp_Object frame, help;
- /* No help echo on owner-draw menu items, or when the keyboard is used
- to navigate the menus, since tooltips are distracting if they pop
- up elsewhere. */
- if (flags & MF_OWNERDRAW || flags & MF_POPUP
- || !(flags & MF_MOUSESELECT))
+ /* No help echo on owner-draw menu items, or when the keyboard
+ is used to navigate the menus, since tooltips are distracting
+ if they pop up elsewhere. */
+ if ((flags & MF_OWNERDRAW) || (flags & MF_POPUP)
+ || !(flags & MF_MOUSESELECT)
+ /* Ignore any dwItemData for menu items whose flags don't
+ have the MF_HILITE bit set. These are dwItemData that
+ Windows sends our way, but they aren't pointers to our
+ Lisp_String objects, so trying to create Lisp_Strings out
+ of them below and pass that to the keyboard queue will
+ crash Emacs when we try to display those "strings". It
+ is unclear why we get these dwItemData, or what they are:
+ sometimes they point to a wchar_t string that is the menu
+ title, sometimes to someting that doesn't look like text
+ at all. (The problematic data also comes with the 0x0800
+ bit set, but this bit is not documented, so we don't want
+ to depend on it.) */
+ || !(flags & MF_HILITE))
help = Qnil;
else
{
info.fMask = MIIM_DATA;
get_menu_item_info (menu, item, FALSE, &info);
- help = info.dwItemData ? XIL (info.dwItemData) : Qnil;
+ help =
+ info.dwItemData
+ ? make_lisp_ptr ((void *) info.dwItemData, Lisp_String)
+ : Qnil;
}
/* Store the help echo in the keyboard buffer as the X toolkit