/* Menu support for GNU Emacs on the Microsoft W32 API.
- Copyright (C) 1986, 88, 93, 94, 96, 98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1986, 1988, 1993, 1994, 1996, 1998, 1999, 2001, 2002,
+ 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include <config.h>
#include <signal.h>
#include "dispextern.h"
-#undef HAVE_MULTILINGUAL_MENU
#undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
/******************************************************************/
typedef struct _widget_value
{
/* name of widget */
+ Lisp_Object lname;
char* name;
/* value (meaning depend on widget type) */
char* value;
- /* keyboard equivalent. no implications for XtTranslations */
+ /* keyboard equivalent. no implications for XtTranslations */
+ Lisp_Object lkey;
char* key;
/* Help string or nil if none.
GC finds this string through the frame's menu_bar_vector
static HMENU current_popup_menu;
-FARPROC get_menu_item_info;
-FARPROC set_menu_item_info;
+void syms_of_w32menu ();
+void globals_of_w32menu ();
-Lisp_Object Vmenu_updating_frame;
+typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) (
+ IN HMENU,
+ IN UINT,
+ IN BOOL,
+ IN OUT LPMENUITEMINFOA);
+typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) (
+ IN HMENU,
+ IN UINT,
+ IN BOOL,
+ IN LPCMENUITEMINFOA);
+
+GetMenuItemInfoA_Proc get_menu_item_info = NULL;
+SetMenuItemInfoA_Proc set_menu_item_info = NULL;
+AppendMenuW_Proc unicode_append_menu = NULL;
Lisp_Object Qdebug_on_next_call;
+extern Lisp_Object Vmenu_updating_frame;
+
extern Lisp_Object Qmenu_bar;
-extern Lisp_Object Qmouse_click, Qevent_kind;
extern Lisp_Object QCtoggle, QCradio;
/* Current depth within submenus. */
static int menu_items_submenu_depth;
-/* Flag which when set indicates a dialog or menu has been posted by
- Xt on behalf of one of the widget sets. */
-static int popup_activated_flag;
-
static int next_menubar_widget_id;
/* This is set nonzero after the user activates the menu bar, and set
\f
/* This is a subroutine of single_keymap_panes that handles one
keymap entry.
- KEY is a key in a keymap and ITEM is its binding.
+ KEY is a key in a keymap and ITEM is its binding.
PENDING_MAPS_PTR points to a list of keymaps waiting to be made into
separate panes.
If NOTREAL is nonzero, only check for equivalent key bindings, don't
Lisp_Object map, item_string, enabled;
struct gcpro gcpro1, gcpro2;
int res;
-
+
/* Parse the menu item and leave the result in item_properties. */
GCPRO2 (key, item);
res = parse_menu_item (item, notreal, 0);
return; /* Not a menu item. */
map = AREF (item_properties, ITEM_PROPERTY_MAP);
-
+
if (notreal)
{
/* We don't want to make a menu, just traverse the keymaps to
}
enabled = AREF (item_properties, ITEM_PROPERTY_ENABLE);
- item_string = AREF (item_properties, ITEM_PROPERTY_NAME);
+ item_string = AREF (item_properties, ITEM_PROPERTY_NAME);
if (!NILP (map) && SREF (item_string, 0) == '@')
{
CHECK_LIVE_WINDOW (window);
f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
- xpos = (FONT_WIDTH (FRAME_FONT (f))
- * XFASTINT (XWINDOW (window)->left));
- ypos = (FRAME_LINE_HEIGHT (f)
- * XFASTINT (XWINDOW (window)->top));
+ xpos = WINDOW_LEFT_EDGE_X (XWINDOW (window));
+ ypos = WINDOW_TOP_EDGE_Y (XWINDOW (window));
}
else
/* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
XSETFRAME (Vmenu_updating_frame, f);
}
- Vmenu_updating_frame = Qnil;
+ else
+ Vmenu_updating_frame = Qnil;
#endif /* HAVE_MENUS */
title = Qnil;
keymaps = 0;
}
-
+
if (NILP (position))
{
discard_menu_items ();
}
#ifdef HAVE_MENUS
- /* If resources from a previous popup menu exist yet, does nothing
- until the `menu_free_timer' has freed them (see w32fns.c).
+ /* If resources from a previous popup menu still exist, does nothing
+ until the `menu_free_timer' has freed them (see w32fns.c). This
+ can occur if you press ESC or click outside a menu without selecting
+ a menu item.
*/
if (current_popup_menu)
{
discard_menu_items ();
UNGCPRO;
return Qnil;
- }
-
+ }
+
/* Display them in a menu. */
BLOCK_INPUT;
UNBLOCK_INPUT;
discard_menu_items ();
+ w32_free_menu_strings (FRAME_W32_WINDOW (f));
+
#endif /* HAVE_MENUS */
UNGCPRO;
#ifdef HAVE_MENUS
-DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 2, 0,
+DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0,
doc: /* Pop up a dialog box and return user's selection.
POSITION specifies which frame to use.
This is normally a mouse button event or a window or frame.
An ITEM may also be just a string--that makes a nonselectable item.
An ITEM may also be nil--that means to put all preceding items
on the left of the dialog box and all following items on the right.
-\(By default, approximately half appear on each side.) */)
- (position, contents)
- Lisp_Object position, contents;
+\(By default, approximately half appear on each side.)
+
+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;
{
FRAME_PTR f = NULL;
Lisp_Object window;
/* Display them in a dialog box. */
BLOCK_INPUT;
- selection = w32_dialog_show (f, 0, title, &error_name);
+ selection = w32_dialog_show (f, 0, title, header, &error_name);
UNBLOCK_INPUT;
discard_menu_items ();
But first we recompute the menu bar contents (the whole tree).
This way we can safely execute Lisp code. */
-
+
void
x_activate_menubar (f)
FRAME_PTR f;
int j;
struct input_event buf;
Lisp_Object frame;
+ EVENT_INIT (buf);
XSETFRAME (frame, f);
buf.kind = MENU_BAR_EVENT;
widget_value *wv;
{
if (! wv) return;
-
+
wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
if (wv->contents && (wv->contents != (widget_value*)1))
Qnil, Qnil, Qnil, Qnil);
}
else
- single_keymap_panes (mapvec[i], item_name, item_key, 0, 10);
+ {
+ Lisp_Object prompt;
+ prompt = Fkeymap_prompt (mapvec[i]);
+ single_keymap_panes (mapvec[i],
+ !NILP (prompt) ? prompt : item_name,
+ item_key, 0, 10);
+ }
}
-
+
return top_level_items;
}
static widget_value *
digest_single_submenu (start, end, top_level_items)
- int start, end;
+ int start, end, top_level_items;
{
widget_value *wv, *prev_wv, *save_wv, *first_wv;
int i;
first_wv = wv;
save_wv = 0;
prev_wv = 0;
-
- /* Loop over all panes and items made during this call
- and construct a tree of widget_value objects.
- Ignore the panes and items made by previous calls to
- single_submenu, even though those are also in menu_items. */
+
+ /* Loop over all panes and items made by the preceding call
+ to parse_single_submenu and construct a tree of widget_value objects.
+ Ignore the panes and items used by previous calls to
+ digest_single_submenu, even though those are also in menu_items. */
i = start;
while (i < end)
{
pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
-#ifndef HAVE_MULTILINGUAL_MENU
- if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
+ if (STRINGP (pane_name))
{
- pane_name = ENCODE_SYSTEM (pane_name);
+ if (unicode_append_menu)
+ /* Encode as UTF-8 for now. */
+ pane_name = ENCODE_UTF_8 (pane_name);
+ else if (STRING_MULTIBYTE (pane_name))
+ pane_name = ENCODE_SYSTEM (pane_name);
+
ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
}
-#endif
+
pane_string = (NILP (pane_name)
? "" : (char *) SDATA (pane_name));
/* If there is just one top-level pane, put all its items directly
save_wv->next = wv;
else
first_wv->contents = wv;
- wv->name = pane_string;
- /* Ignore the @ that means "separate pane".
- This is a kludge, but this isn't worth more time. */
- if (!NILP (prefix) && wv->name[0] == '@')
- wv->name++;
- wv->value = 0;
+ wv->lname = pane_name;
+ /* Set value to 1 so update_submenu_strings can handle '@' */
+ wv->value = (char *) 1;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
wv->help = Qnil;
selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
-#ifndef HAVE_MULTILINGUAL_MENU
- if (STRING_MULTIBYTE (item_name))
+ if (STRINGP (item_name))
{
- item_name = ENCODE_SYSTEM (item_name);
+ if (unicode_append_menu)
+ item_name = ENCODE_UTF_8 (item_name);
+ else if (STRING_MULTIBYTE (item_name))
+ item_name = ENCODE_SYSTEM (item_name);
+
ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
}
descrip = ENCODE_SYSTEM (descrip);
ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
}
-#endif /* not HAVE_MULTILINGUAL_MENU */
wv = xmalloc_widget_value ();
- if (prev_wv)
+ if (prev_wv)
prev_wv->next = wv;
else
save_wv->contents = wv;
- wv->name = (char *) SDATA (item_name);
+ wv->lname = item_name;
if (!NILP (descrip))
- wv->key = (char *) SDATA (descrip);
+ wv->lkey = descrip;
wv->value = 0;
/* The EMACS_INT cast avoids a warning. There's no problem
as long as pointers have enough bits to hold small integers. */
return first_wv;
}
+
+
+/* Walk through the widget_value tree starting at FIRST_WV and update
+ the char * pointers from the corresponding lisp values.
+ We do this after building the whole tree, since GC may happen while the
+ tree is constructed, and small strings are relocated. So we must wait
+ until no GC can happen before storing pointers into lisp values. */
+static void
+update_submenu_strings (first_wv)
+ widget_value *first_wv;
+{
+ widget_value *wv;
+
+ for (wv = first_wv; wv; wv = wv->next)
+ {
+ if (wv->lname && ! NILP (wv->lname))
+ {
+ wv->name = SDATA (wv->lname);
+
+ /* Ignore the @ that means "separate pane".
+ This is a kludge, but this isn't worth more time. */
+ if (wv->value == (char *)1)
+ {
+ if (wv->name[0] == '@')
+ wv->name++;
+ wv->value = 0;
+ }
+ }
+
+ if (wv->lkey && ! NILP (wv->lkey))
+ wv->key = SDATA (wv->lkey);
+
+ if (wv->contents)
+ update_submenu_strings (wv->contents);
+ }
+}
+
\f
/* Set the contents of the menubar widgets of frame F.
The argument FIRST_TIME is currently ignored;
widget_value *wv, *first_wv, *prev_wv = 0;
int i, last_i;
int *submenu_start, *submenu_end;
- int *submenu_top_level_items;
+ int *submenu_top_level_items, *submenu_n_panes;
/* We must not change the menubar when actually in use. */
if (f->output_data.w32->menubar_active)
because it is not reentrant. */
specbind (Qdebug_on_next_call, Qnil);
- record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
+ record_unwind_save_match_data ();
+
if (NILP (Voverriding_local_map_menu_flag))
{
specbind (Qoverriding_terminal_local_map, Qnil);
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 *));
init_menu_items ();
menu_items_n_panes = 0;
submenu_top_level_items[i]
= parse_single_submenu (key, string, maps);
+ submenu_n_panes[i] = menu_items_n_panes;
submenu_end[i] = menu_items_used;
}
for (i = 0; i < last_i; i += 4)
{
+ menu_items_n_panes = submenu_n_panes[i];
wv = digest_single_submenu (submenu_start[i], submenu_end[i],
submenu_top_level_items[i]);
- if (prev_wv)
+ if (prev_wv)
prev_wv->next = wv;
else
first_wv->contents = wv;
if (NILP (string))
break;
wv->name = (char *) SDATA (string);
+ update_submenu_strings (wv->contents);
wv = wv->next;
}
This value just has to be different from small integers. */
wv->call_data = (void *) (EMACS_INT) (-1);
- if (prev_wv)
+ if (prev_wv)
prev_wv->next = wv;
else
first_wv->contents = wv;
f->output_data.w32->menubar_widget = menubar_widget;
SetMenu (FRAME_W32_WINDOW (f), f->output_data.w32->menubar_widget);
- /* Causes flicker when menu bar is updated
+ /* Causes flicker when menu bar is updated
DrawMenuBar (FRAME_W32_WINDOW (f)); */
/* 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)
- x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
+ x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
}
UNBLOCK_INPUT;
wv->help = Qnil;
first_wv = wv;
first_pane = 1;
-
+
/* Loop over all panes and items, filling in the tree. */
i = 0;
while (i < menu_items_used)
char *pane_string;
pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
-#ifndef HAVE_MULTILINGUAL_MENU
- if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
+
+ if (STRINGP (pane_name))
{
- pane_name = ENCODE_SYSTEM (pane_name);
+ if (unicode_append_menu)
+ pane_name = ENCODE_UTF_8 (pane_name);
+ else if (STRING_MULTIBYTE (pane_name))
+ pane_name = ENCODE_SYSTEM (pane_name);
+
ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
}
-#endif
+
pane_string = (NILP (pane_name)
? "" : (char *) SDATA (pane_name));
/* If there is just one top-level pane, put all its items directly
selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
-#ifndef HAVE_MULTILINGUAL_MENU
- if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
+ if (STRINGP (item_name))
{
- item_name = ENCODE_SYSTEM (item_name);
+ if (unicode_append_menu)
+ item_name = ENCODE_UTF_8 (item_name);
+ else if (STRING_MULTIBYTE (item_name))
+ item_name = ENCODE_SYSTEM (item_name);
+
ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
}
- if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
+
+ if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
{
descrip = ENCODE_SYSTEM (descrip);
ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
}
-#endif /* not HAVE_MULTILINGUAL_MENU */
wv = xmalloc_widget_value ();
- if (prev_wv)
+ if (prev_wv)
prev_wv->next = wv;
- else
+ else
save_wv->contents = wv;
wv->name = (char *) SDATA (item_name);
if (!NILP (descrip))
wv_sep->next = first_wv->contents;
wv_sep->help = Qnil;
-#ifndef HAVE_MULTILINGUAL_MENU
- if (STRING_MULTIBYTE (title))
+ if (unicode_append_menu)
+ title = ENCODE_UTF_8 (title);
+ else if (STRING_MULTIBYTE (title))
title = ENCODE_SYSTEM (title);
-#endif
+
wv_title->name = (char *) SDATA (title);
wv_title->enabled = TRUE;
wv_title->title = TRUE;
menu_item_selection = 0;
/* Display the menu. */
- menu_item_selection = SendMessage (FRAME_W32_WINDOW (f),
+ menu_item_selection = SendMessage (FRAME_W32_WINDOW (f),
WM_EMACS_TRACKPOPUPMENU,
(WPARAM)menu, (LPARAM)&pos);
}
}
}
+ else if (!for_click)
+ /* Make "Cancel" equivalent to C-g. */
+ Fsignal (Qquit, Qnil);
return Qnil;
}
"button6", "button7", "button8", "button9", "button10" };
static Lisp_Object
-w32_dialog_show (f, keymaps, title, error)
+w32_dialog_show (f, keymaps, title, header, error)
FRAME_PTR f;
int keymaps;
- Lisp_Object title;
+ Lisp_Object title, header;
char **error;
{
int i, nb_buttons=0;
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));
+ ? "" : (char *) SDATA (pane_name));
prev_wv = xmalloc_widget_value ();
prev_wv->value = pane_string;
if (keymaps && !NILP (prefix))
prev_wv->name = "message";
prev_wv->help = Qnil;
first_wv = prev_wv;
-
+
/* Loop over all panes and items, filling in the tree. */
i = MENU_ITEMS_PANE_LENGTH;
while (i < menu_items_used)
{
-
+
/* Create a new item within current pane. */
Lisp_Object item_name, enable, descrip, help;
enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
-
+
if (NILP (item_name))
{
free_menubar_widget_value_tree (first_wv);
wv->name = dialog_name;
wv->help = Qnil;
+ /* Frame title: 'Q' = Question, 'I' = Information.
+ Can also have 'E' = Error if, one day, we want
+ a popup for errors. */
+ if (NILP(header))
+ dialog_name[0] = 'Q';
+ else
+ dialog_name[0] = 'I';
+
/* Dialog boxes use a really stupid name encoding
which specifies how many buttons to use
- and how many buttons are on the right.
- The Q means something also. */
- dialog_name[0] = 'Q';
+ and how many buttons are on the right. */
dialog_name[1] = '0' + nb_buttons;
dialog_name[2] = 'B';
dialog_name[3] = 'R';
/* Display the menu. */
lw_pop_up_all_widgets (dialog_id);
- popup_activated_flag = 1;
/* Process events that apply to the menu. */
popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id);
- lw_destroy_all_widgets (dialog_id);
+ lw_destroy_all_widgets (dialog_id);
/* Find the selected item, and its pane, to return
the proper value. */
}
}
}
+ else
+ /* Make "Cancel" equivalent to C-g. */
+ Fsignal (Qquit, Qnil);
return Qnil;
}
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;
+ dest++; src++; len--;
+ }
+ /* Since we might get >3 byte sequences which we don't handle, ignore the extra parts. */
+ else if (*src < 0xC0)
+ {
+ src++; len--;
+ }
+ /* 2 char UTF-8 sequence. */
+ else if (*src < 0xE0)
+ {
+ *dest = (WCHAR) (((*src & 0x1f) << 6)
+ | (*(src + 1) & 0x3f));
+ src += 2; len -= 2; dest++;
+ }
+ else if (*src < 0xF0)
+ {
+ *dest = (WCHAR) (((*src & 0x0f) << 12)
+ | ((*(src + 1) & 0x3f) << 6)
+ | (*(src + 2) & 0x3f));
+ src += 3; len -= 3; dest++;
+ }
+ else /* Not encodable. Insert Unicode Substitution char. */
+ {
+ *dest = (WCHAR) 0xfffd;
+ src++; len--; dest++;
+ }
+ }
+ *dest = 0;
+}
+
static int
add_menu_item (HMENU menu, widget_value *wv, HMENU item)
{
fuFlags = MF_SEPARATOR;
out_string = NULL;
}
- else
+ else
{
if (wv->enabled)
fuFlags = MF_STRING;
fuFlags |= MF_UNCHECKED;
}
- return_value =
- AppendMenu (menu,
- fuFlags,
- item != NULL ? (UINT) item : (UINT) wv->call_data,
- out_string );
+ if (unicode_append_menu && out_string)
+ {
+ /* Convert out_string from UTF-8 to UTF-16-LE. */
+ int utf8_len = strlen (out_string);
+ WCHAR * utf16_string;
+ if (fuFlags & MF_OWNERDRAW)
+ utf16_string = local_alloc ((utf8_len + 1) * sizeof (WCHAR));
+ else
+ utf16_string = 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,
+ utf16_string);
+ if (!return_value)
+ {
+ /* 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
+ happen the first time a menu is used, the encoding is
+ of minor importance compared with menus not working at all. */
+ return_value =
+ AppendMenu (menu, fuFlags,
+ item != NULL ? (UINT) item: (UINT) wv->call_data,
+ out_string);
+ /* Don't use unicode menus in future. */
+ unicode_append_menu = NULL;
+ }
+
+ if (unicode_append_menu && (fuFlags & MF_OWNERDRAW))
+ local_free (out_string);
+ }
+ else
+ {
+ return_value =
+ AppendMenu (menu,
+ fuFlags,
+ item != NULL ? (UINT) item : (UINT) wv->call_data,
+ out_string );
+ }
/* This must be done after the menu item is created. */
if (!wv->title && wv->call_data != 0)
/* 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. */
- if (wv->help)
- info.dwItemData = (DWORD) wv->help;
-
+ if (!NILP (wv->help))
+#ifdef USE_LISP_UNION_TYPE
+ info.dwItemData = (DWORD) (wv->help).i;
+#else
+ info.dwItemData = (DWORD) (wv->help);
+#endif
if (wv->button_type == BUTTON_TYPE_RADIO)
{
/* CheckMenuRadioItem allows us to differentiate TOGGLE and
return 1;
}
-int
-popup_activated ()
-{
- /* popup_activated_flag not actually used on W32 */
- return 0;
-}
-
/* Display help string for currently pointed to menu item. Not
supported on NT 3.51 and earlier, as GetMenuItemInfo is not
available. */
struct frame *f = x_window_to_frame (&one_w32_display_info, owner);
Lisp_Object frame, help;
- // No help echo on owner-draw menu items.
- if (flags & MF_OWNERDRAW || flags & MF_POPUP)
+ /* 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))
help = Qnil;
else
{
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
}
/* Store the help echo in the keyboard buffer as the X toolkit
#endif /* HAVE_MENUS */
-\f
-syms_of_w32menu ()
+/* The following is used by delayed window autoselection. */
+
+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. */)
+ ()
{
- /* See if Get/SetMenuItemInfo functions are available. */
- HMODULE user32 = GetModuleHandle ("user32.dll");
- get_menu_item_info = GetProcAddress (user32, "GetMenuItemInfoA");
- set_menu_item_info = GetProcAddress (user32, "SetMenuItemInfoA");
+#ifdef HAVE_MENUS
+ FRAME_PTR f;
+ f = SELECTED_FRAME ();
+ return (f->output_data.w32->menubar_active > 0) ? Qt : Qnil;
+#else
+ return Qnil;
+#endif /* HAVE_MENUS */
+}
+void syms_of_w32menu ()
+{
+ globals_of_w32menu ();
staticpro (&menu_items);
menu_items = Qnil;
Qdebug_on_next_call = intern ("debug-on-next-call");
staticpro (&Qdebug_on_next_call);
- DEFVAR_LISP ("menu-updating-frame", &Vmenu_updating_frame,
- doc: /* Frame for which we are updating a menu.
-The enable predicate for a menu command should check this variable. */);
- Vmenu_updating_frame = Qnil;
-
defsubr (&Sx_popup_menu);
+ defsubr (&Smenu_or_popup_active_p);
#ifdef HAVE_MENUS
defsubr (&Sx_popup_dialog);
#endif
}
+
+/*
+ globals_of_w32menu is used to initialize those global variables that
+ must always be initialized on startup even when the global variable
+ initialized is non zero (see the function main in emacs.c).
+ globals_of_w32menu is called from syms_of_w32menu when the global
+ variable initialized is 0 and directly from main when initialized
+ is non zero.
+ */
+void globals_of_w32menu ()
+{
+ /* 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");
+}
+
+/* arch-tag: 0eaed431-bb4e-4aac-a527-95a1b4f1fed0
+ (do not change this comment) */