X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/4b72b4f91122704b805e2696b2e9342226359de0..cd950da:/src/w32menu.c diff --git a/src/w32menu.c b/src/w32menu.c index 287062c702..d9ab8f5e51 100644 --- a/src/w32menu.c +++ b/src/w32menu.c @@ -1,13 +1,13 @@ /* 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 @@ -25,15 +25,10 @@ along with GNU Emacs. If not, see . */ #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 @@ -54,8 +49,6 @@ along with GNU Emacs. If not, see . */ #include #endif -#include "dispextern.h" - #include "w32common.h" /* for osinfo_cache */ #undef HAVE_DIALOGS /* TODO: Implement native dialogs. */ @@ -98,14 +91,12 @@ AppendMenuW_Proc unicode_append_menu = NULL; 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 @@ -168,7 +159,7 @@ w32_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) 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; @@ -219,9 +210,9 @@ menubar_selection_callback (struct frame *f, void * client_data) 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; @@ -291,7 +282,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) XSETFRAME (Vmenu_updating_frame, f); if (! menubar_widget) - deep_p = 1; + deep_p = true; if (deep_p) { @@ -390,7 +381,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool 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; } @@ -503,8 +494,10 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) /* 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 (); @@ -521,7 +514,7 @@ initialize_frame_menubar (struct frame *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. */ 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. @@ -573,7 +566,7 @@ w32_menu_show (struct frame *f, int x, int y, int menuflags, Lisp_Object *subprefix_stack = (Lisp_Object *) alloca (menu_items_used * word_size); int submenu_depth = 0; - int first_pane; + bool first_pane; *error = NULL; @@ -593,7 +586,7 @@ w32_menu_show (struct frame *f, int x, int y, int menuflags, 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; @@ -604,14 +597,14 @@ w32_menu_show (struct frame *f, int x, int y, int menuflags, 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) @@ -667,7 +660,7 @@ w32_menu_show (struct frame *f, int x, int y, int menuflags, save_wv = wv; prev_wv = 0; } - first_pane = 0; + first_pane = false; i += MENU_ITEMS_PANE_LENGTH; } else @@ -709,7 +702,7 @@ w32_menu_show (struct frame *f, int x, int y, int menuflags, 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; @@ -886,8 +879,9 @@ w32_dialog_show (struct frame *f, Lisp_Object title, /* 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; @@ -931,7 +925,7 @@ w32_dialog_show (struct frame *f, Lisp_Object title, { /* This is the boundary between left-side elts and right-side elts. Stop incrementing right_count. */ - boundary_seen = 1; + boundary_seen = true; i++; continue; } @@ -989,7 +983,7 @@ w32_dialog_show (struct frame *f, Lisp_Object title, /* 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); @@ -1040,25 +1034,25 @@ w32_dialog_show (struct frame *f, Lisp_Object title, 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))) @@ -1066,18 +1060,18 @@ is_simple_dialog (Lisp_Object contents) 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); @@ -1106,14 +1100,14 @@ simple_dialog_show (struct frame *f, Lisp_Object contents, Lisp_Object header) 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 { @@ -1142,7 +1136,7 @@ simple_dialog_show (struct frame *f, Lisp_Object contents, Lisp_Object header) 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 = ""; @@ -1355,7 +1349,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) 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, @@ -1404,17 +1398,21 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item) 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) { @@ -1475,11 +1473,24 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags) 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 { @@ -1490,7 +1501,10 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags) 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