#include "blockinput.h"
#include "puresize.h"
+#ifdef MSDOS
+#include "msdos.h"
+#endif
+
#ifdef HAVE_X_WINDOWS
/* This may include sys/types.h, and that somehow loses
if this is not done before the other system files. */
#include "dispextern.h"
#ifdef HAVE_X_WINDOWS
-#include "../oldXMenu/XMenu.h"
-#endif
-
#ifdef USE_X_TOOLKIT
#include <X11/Xlib.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include "../lwlib/lwlib.h"
-#endif /* USE_X_TOOLKIT */
+#else /* not USE_X_TOOLKIT */
+#include "../oldXMenu/XMenu.h"
+#endif /* not USE_X_TOOLKIT */
+#endif /* HAVE_X_WINDOWS */
#define min(x,y) (((x) < (y)) ? (x) : (y))
#define max(x,y) (((x) > (y)) ? (x) : (y))
Each pane is described by 3 elements in the vector:
t, the pane name, the pane's prefix key.
- Then follow the pane's items, with 4 elements per item:
+ Then follow the pane's items, with 5 elements per item:
the item string, the enable flag, the item's value,
- and the equivalent keyboard key's description string.
+ the definition, and the equivalent keyboard key's description string.
In some cases, multiple levels of menus may be described.
A single vector slot containing nil indicates the start of a submenu.
#define MENU_ITEMS_ITEM_ENABLE 1
#define MENU_ITEMS_ITEM_VALUE 2
#define MENU_ITEMS_ITEM_EQUIV_KEY 3
-#define MENU_ITEMS_ITEM_LENGTH 4
+#define MENU_ITEMS_ITEM_DEFINITION 4
+#define MENU_ITEMS_ITEM_LENGTH 5
static Lisp_Object menu_items;
Xt on behalf of one of the widget sets. */
static int popup_activated_flag;
+/* This holds a Lisp vector
+ which contains frames that have menu bars.
+ Each frame that has a menu bar is found at some index in this vector
+ and the menu bar widget refers to the frame through that index. */
+static Lisp_Object frame_vector;
+\f
+/* Return the index of FRAME in frame_vector.
+ If FRAME isn't in frame_vector yet, put it in,
+ lengthening the vector if necessary. */
+
+static int
+frame_vector_add_frame (f)
+ FRAME_PTR *f;
+{
+ int length = XVECTOR (frame_vector)->size;
+ int i, empty = -1;
+ Lisp_Object new, frame;
+
+ XSETFRAME (frame, f);
+
+ for (i = 0; i < length; i++)
+ {
+ if (EQ (frame, XVECTOR (frame_vector)->contents[i]))
+ return i;
+ if (NILP (XVECTOR (frame_vector)->contents[i]))
+ empty = i;
+ }
+
+ if (empty >= 0)
+ {
+ XVECTOR (frame_vector)->contents[empty] = frame;
+ return empty;
+ }
+
+ new = Fmake_vector (make_number (length * 2), Qnil);
+ bcopy (XVECTOR (frame_vector)->contents,
+ XVECTOR (new)->contents, sizeof (Lisp_Object) * length);
+
+ XVECTOR (frame_vector)->contents[length] = frame;
+ return length;
+}
\f
/* Initialize the menu_items structure if we haven't already done so.
Also mark it as currently empty. */
/* Push one menu item into the current pane.
NAME is the string to display. ENABLE if non-nil means
this item can be selected. KEY is the key generated by
- choosing this item. EQUIV is the textual description
- of the keyboard equivalent for this item (or nil if none). */
+ choosing this item, or nil if this item doesn't really have a definition.
+ DEF is the definition of this item.
+ EQUIV is the textual description of the keyboard equivalent for
+ this item (or nil if none). */
static void
-push_menu_item (name, enable, key, equiv)
- Lisp_Object name, enable, key, equiv;
+push_menu_item (name, enable, key, def, equiv)
+ Lisp_Object name, enable, key, def, equiv;
{
if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
grow_menu_items ();
XVECTOR (menu_items)->contents[menu_items_used++] = enable;
XVECTOR (menu_items)->contents[menu_items_used++] = key;
XVECTOR (menu_items)->contents[menu_items_used++] = equiv;
+ XVECTOR (menu_items)->contents[menu_items_used++] = def;
}
\f
/* Figure out the current keyboard equivalent of a menu item ITEM1.
{
changed = 1;
descrip = Qnil;
- savedkey = Fwhere_is_internal (def, Qnil, Qt, Qnil);
/* If the command is an alias for another
(such as easymenu.el and lmenu.el set it up),
see if the original command name has equivalent keys. */
if (SYMBOLP (def) && SYMBOLP (XSYMBOL (def)->function))
savedkey = Fwhere_is_internal (XSYMBOL (def)->function,
Qnil, Qt, Qnil);
+ else
+ /* Otherwise look up the specified command itself.
+ We don't try both, because that makes easymenu menus slow. */
+ savedkey = Fwhere_is_internal (def, Qnil, Qt, Qnil);
- if (VECTORP (savedkey)
- && EQ (XVECTOR (savedkey)->contents[0], Qmenu_bar))
- savedkey = Qnil;
- /* Reject two-key sequences that start with a mouse click.
- These are probably menu items. */
- if (VECTORP (savedkey)
- && XVECTOR (savedkey)->size > 1
- && SYMBOLP (XVECTOR (savedkey)->contents[0]))
- {
- Lisp_Object tem;
-
- tem = Fget (XVECTOR (savedkey)->contents[0], Qevent_kind);
- if (EQ (tem, Qmouse_click))
- savedkey = Qnil;
- }
if (!NILP (savedkey))
{
descrip = Fkey_description (savedkey);
item_string = concat2 (item_string,
build_string (" >"));
#endif
- push_menu_item (item_string, enabled, XCONS (item)->car,
+ /* If definition is nil, pass nil as the key. */
+ push_menu_item (item_string, enabled,
+ XCONS (item)->car, def,
descrip);
#ifdef USE_X_TOOLKIT
/* Display a submenu using the toolkit. */
item_string = concat2 (item_string,
build_string (" >"));
#endif
+ /* If definition is nil, pass nil as the key. */
push_menu_item (item_string, enabled, character,
- descrip);
+ def, descrip);
#ifdef USE_X_TOOLKIT
if (! NILP (submap))
{
{
item = Fcar (tail);
if (STRINGP (item))
- push_menu_item (item, Qnil, Qnil, Qnil);
+ push_menu_item (item, Qnil, Qnil, Qt, Qnil);
else if (NILP (item))
push_left_right_boundary ();
else
CHECK_CONS (item, 0);
item1 = Fcar (item);
CHECK_STRING (item1, 1);
- push_menu_item (item1, Qt, Fcdr (item), Qnil);
+ push_menu_item (item1, Qt, Fcdr (item), Qt, Qnil);
}
}
}
Lisp_Object x, y, window;
int keymaps = 0;
int menubarp = 0;
+ int for_click = 0;
struct gcpro gcpro1;
if (! NILP (position))
if (EQ (position, Qt))
{
/* Use the mouse's current position. */
- FRAME_PTR new_f = 0;
+ FRAME_PTR new_f = selected_frame;
Lisp_Object bar_window;
int part;
unsigned long time;
if (mouse_position_hook)
- (*mouse_position_hook) (&new_f, &bar_window, &part, &x, &y, &time);
+ (*mouse_position_hook) (&new_f, 1, &bar_window,
+ &part, &x, &y, &time);
if (new_f != 0)
XSETFRAME (window, new_f);
else
}
else
{
+ for_click = 1;
tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
window = Fcar (tem); /* POSN_WINDOW (tem) */
tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
/* Display them in a menu. */
BLOCK_INPUT;
- selection = xmenu_show (f, xpos, ypos, menubarp,
+ selection = xmenu_show (f, xpos, ypos, menubarp, for_click,
keymaps, title, &error_name);
UNBLOCK_INPUT;
{
#if 0 /* Using the frame the mouse is on may not be right. */
/* Use the mouse's current position. */
- FRAME_PTR new_f = 0;
+ FRAME_PTR new_f = selected_frame;
Lisp_Object bar_window;
int part;
unsigned long time;
Lisp_Object x, y;
- (*mouse_position_hook) (&new_f, &bar_window, &part, &x, &y, &time);
+ (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time);
if (new_f != 0)
XSETFRAME (window, new_f);
XtPointer client_data;
{
Lisp_Object prefix;
- FRAME_PTR f = (FRAME_PTR) id;
+ FRAME_PTR f = XFRAME (XVECTOR (frame_vector)->contents[id]);
Lisp_Object vector;
Lisp_Object *subprefix_stack;
int submenu_depth = 0;
}
else if (EQ (XVECTOR (vector)->contents[i], Qt))
{
- prefix
- = XVECTOR (vector)->contents[i + MENU_ITEMS_PANE_PREFIX];
+ prefix = XVECTOR (vector)->contents[i + MENU_ITEMS_PANE_PREFIX];
i += MENU_ITEMS_PANE_LENGTH;
}
else
{
- entry
- = XVECTOR (vector)->contents[i + MENU_ITEMS_ITEM_VALUE];
- if ((int) client_data == i)
+ entry = XVECTOR (vector)->contents[i + MENU_ITEMS_ITEM_VALUE];
+ /* The EMACS_INT 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)
{
int j;
struct input_event buf;
+ Lisp_Object frame;
+ XSETFRAME (frame, f);
buf.kind = menu_bar_event;
- buf.frame_or_window = Qmenu_bar;
+ buf.frame_or_window = Fcons (frame, Qmenu_bar);
kbd_buffer_store_event (&buf);
for (j = 0; j < submenu_depth; j++)
if (!NILP (subprefix_stack[j]))
{
buf.kind = menu_bar_event;
- buf.frame_or_window = subprefix_stack[j];
+ buf.frame_or_window = Fcons (frame, subprefix_stack[j]);
kbd_buffer_store_event (&buf);
}
if (!NILP (prefix))
{
buf.kind = menu_bar_event;
- buf.frame_or_window = prefix;
+ buf.frame_or_window = Fcons (frame, prefix);
kbd_buffer_store_event (&buf);
}
buf.kind = menu_bar_event;
- buf.frame_or_window = entry;
+ buf.frame_or_window = Fcons (frame, entry);
kbd_buffer_store_event (&buf);
return;
else
{
/* Create a new item within current pane. */
- Lisp_Object item_name, enable, descrip;
+ Lisp_Object item_name, enable, descrip, def;
item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
descrip
= XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
+ def = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_DEFINITION];
wv = malloc_widget_value ();
if (prev_wv)
if (!NILP (descrip))
wv->key = (char *) XSTRING (descrip)->data;
wv->value = 0;
- wv->call_data = (void *) i;
+ /* The EMACS_INT cast avoids a warning. There's no problem
+ as long as pointers have enough bits to hold small integers. */
+ wv->call_data = (!NILP (def) ? (void *) (EMACS_INT) i : 0);
wv->enabled = !NILP (enable);
prev_wv = wv;
int first_time;
{
Widget menubar_widget = f->display.x->menubar_widget;
- int id = (int) f;
- Lisp_Object tail, items;
+ Lisp_Object tail, items, frame;
widget_value *wv, *first_wv, *prev_wv = 0;
int i;
+ int id;
+
+ id = frame_vector_add_frame (f);
BLOCK_INPUT;
int id;
menubar_widget = f->display.x->menubar_widget;
- id = (int) f;
if (menubar_widget)
{
+ id = frame_vector_add_frame (f);
BLOCK_INPUT;
lw_destroy_all_widgets (id);
+ XVECTOR (frame_vector)->contents[id] = Qnil;
UNBLOCK_INPUT;
}
}
/* F is the frame the menu is for.
X and Y are the frame-relative specified position,
relative to the inside upper left corner of the frame F.
- MENUBARP is 1 if the click that asked for this menu came from the menu bar.
+ MENUBARP is 1 if this menu came from the menu bar.
+ FOR_CLICK if this menu was invoked for a mouse click.
KEYMAPS is 1 if this menu was specified with keymaps;
in that case, we return a list containing the chosen item's value
and perhaps also the pane's prefix.
}
static Lisp_Object
-xmenu_show (f, x, y, menubarp, keymaps, title, error)
+xmenu_show (f, x, y, menubarp, for_click, keymaps, title, error)
FRAME_PTR f;
int x;
int y;
- int menubarp; /* Dummy parameter for Xt version of
- xmenu_show() */
+ int menubarp; /* This arg is unused in Xt version. */
+ int for_click;
int keymaps;
Lisp_Object title;
char **error;
else
{
/* Create a new item within current pane. */
- Lisp_Object item_name, enable, descrip;
+ Lisp_Object item_name, enable, descrip, def;
item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
descrip
= XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
+ def = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_DEFINITION];
wv = malloc_widget_value ();
if (prev_wv)
if (!NILP (descrip))
wv->key = (char *) XSTRING (descrip)->data;
wv->value = 0;
- wv->call_data = (void *) &XVECTOR (menu_items)->contents[i];
+ /* If this item has a null value,
+ make the call_data null so that it won't display a box
+ when the mouse is on it. */
+ wv->call_data
+ = (!NILP (def) ? (void *) &XVECTOR (menu_items)->contents[i] : 0);
wv->enabled = !NILP (enable);
prev_wv = wv;
LWLIB_ID id;
XtPointer client_data;
{
- if ((int)client_data != -1)
+ /* The EMACS_INT 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 != -1)
menu_item_selection = (Lisp_Object *) client_data;
BLOCK_INPUT;
lw_destroy_all_widgets (id);
#else /* not USE_X_TOOLKIT */
static Lisp_Object
-xmenu_show (f, x, y, menubarp, keymaps, title, error)
+xmenu_show (f, x, y, menubarp, for_click, keymaps, title, error)
FRAME_PTR f;
int x, y;
- int keymaps;
int menubarp;
+ int for_click;
+ int keymaps;
Lisp_Object title;
char **error;
{
status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx,
x, y, ButtonReleaseMask, &datap);
+
+
+ /* Assume the mouse has moved out of the X window.
+ If it has actually moved in, we will get an EnterNotify. */
+ x_mouse_leave ();
+
switch (status)
{
case XM_SUCCESS:
widget_id_tick = (1<<16);
#endif
+ staticpro (&frame_vector);
+ frame_vector = Fmake_vector (make_number (10), Qnil);
+
defsubr (&Sx_popup_menu);
defsubr (&Sx_popup_dialog);
}