{
item = Fcar (tail);
if (STRINGP (item))
- push_menu_item (item, Qnil, Qnil);
+ push_menu_item (item, Qnil, Qnil, Qnil);
else
{
CHECK_CONS (item, 0);
}
}
\f
-DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 1, 2, 0,
+DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
"Pop up a deck-of-cards menu and return user's selection.\n\
POSITION is a position specification. This is either a mouse button event\n\
or a list ((XOFFSET YOFFSET) WINDOW)\n\
if (EQ (position, Qt))
{
/* Use the mouse's current position. */
- FRAME_PTR new_f;
+ FRAME_PTR new_f = 0;
Lisp_Object bar_window;
int part;
unsigned long time;
- (*mouse_position_hook) (&new_f, &bar_window, &part, &x, &y, &time);
- XSET (window, Lisp_Frame, new_f);
+ if (new_f != 0)
+ XSET (window, Lisp_Frame, new_f);
+ else
+ {
+ window = selected_window;
+ XFASTINT (x) = 0;
+ XFASTINT (y) = 0;
+ }
}
else
{
return selection;
}
-DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 1, 2, 0,
+DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 2, 0,
"Pop up a dialog box and return user's selection.\n\
-POSITION is a position specification. This is either a mouse button event\n\
-or a list ((XOFFSET YOFFSET) WINDOW)\n\
-where XOFFSET and YOFFSET are positions in characters from the top left\n\
-corner of WINDOW's frame. (WINDOW may be a frame object instead of a window.)\n\
-This controls the position of the center of the first line\n\
-in the first pane of the menu, not the top left of the menu as a whole.\n\
-If POSITION is t, it means to use the current mouse position.\n\
-\n\
-MENU is a specifier for a menu. For the simplest case, MENU is a keymap.\n\
-The menu items come from key bindings that have a menu string as well as\n\
-a definition; actually, the \"definition\" in such a key binding looks like\n\
-\(STRING . REAL-DEFINITION). To give the menu a title, put a string into\n\
-the keymap as a top-level element.\n\n\
-You can also use a list of keymaps as MENU.\n\
- Then each keymap makes a separate pane.\n\
-When MENU is a keymap or a list of keymaps, the return value\n\
-is a list of events.\n\n\
-Alternatively, you can specify a menu of multiple panes\n\
- with a list of the form (TITLE PANE1 PANE2...),\n\
-where each pane is a list of form (TITLE ITEM1 ITEM2...).\n\
-Each ITEM is normally a cons cell (STRING . VALUE);\n\
-but a string can appear as an item--that makes a nonselectable line\n\
-in the menu.\n\
-With this form of menu, the return value is VALUE from the chosen item.\n\
+POSITION specifies which frame to use.\n\
+This is normally a mouse button event or a window or frame.\n\
+If POSITION is t, it means to use the frame the mouse is on.\n\
+The dialog box appears in the middle of the specified frame.\n\
\n\
-If POSITION is nil, don't display the menu at all, just precalculate the\n\
-cached information about equivalent key sequences.")
- (position, menu)
- Lisp_Object position, menu;
+CONTENTS specifies the alternatives to display in the dialog box.\n\
+It is a list of the form (TITLE ITEM1 ITEM2...).\n\
+Each ITEM is a cons cell (STRING . VALUE).\n\
+The return value is VALUE from the chosen item.")
+ (position, contents)
+ Lisp_Object position, contents;
{
-#ifndef USE_X_TOOLKIT
- return Fx_popup_menu (position, menu);
-#else
- int number_of_panes, panes;
- Lisp_Object keymap, tem;
- int xpos, ypos;
- Lisp_Object title;
- char *error_name;
- Lisp_Object selection;
- int i, j;
FRAME_PTR f;
- Lisp_Object x, y, window;
- int keymaps = 0;
- int menubarp = 0;
- struct gcpro gcpro1;
+ Lisp_Object window;
check_x ();
- if (! NILP (position))
+ /* Decode the first argument: find the window or frame to use. */
+ if (EQ (position, Qt))
{
- /* Decode the first argument: find the window and the coordinates. */
- if (EQ (position, Qt))
- {
- /* Use the mouse's current position. */
- FRAME_PTR new_f;
- Lisp_Object bar_window;
- int part;
- unsigned long time;
-
- (*mouse_position_hook) (&new_f, &bar_window, &part, &x, &y, &time);
- XSET (window, Lisp_Frame, new_f);
- }
-
- CHECK_NUMBER (x, 0);
- CHECK_NUMBER (y, 0);
-
- /* Decode where to put the menu. */
-
- if (XTYPE (window) == Lisp_Frame)
- {
- f = XFRAME (window);
+ /* Use the mouse's current position. */
+ FRAME_PTR new_f = 0;
+ Lisp_Object bar_window;
+ int part;
+ unsigned long time;
+ Lisp_Object x, y;
- xpos = 0;
- ypos = 0;
- }
- else if (XTYPE (window) == Lisp_Window)
- {
- CHECK_LIVE_WINDOW (window, 0);
- f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
+ (*mouse_position_hook) (&new_f, &bar_window, &part, &x, &y, &time);
- xpos = (FONT_WIDTH (f->display.x->font) * XWINDOW (window)->left);
- ypos = (FONT_HEIGHT (f->display.x->font) * XWINDOW (window)->top);
- }
+ if (new_f != 0)
+ XSET (window, Lisp_Frame, new_f);
else
- /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
- but I don't want to make one now. */
- CHECK_WINDOW (window, 0);
-
- xpos += XINT (x);
- ypos += XINT (y);
+ window = selected_window;
}
-
- title = Qnil;
- GCPRO1 (title);
-
- /* Decode the dialog items from what was specified. */
+ else if (CONSP (position))
{
- /* We were given an old-fashioned menu. */
- title = Fcar (menu);
- CHECK_STRING (title, 1);
+ Lisp_Object tem;
+ tem = Fcar (position);
+ if (XTYPE (tem) == Lisp_Cons)
+ window = Fcar (Fcdr (position));
+ else
+ {
+ tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
+ window = Fcar (tem); /* POSN_WINDOW (tem) */
+ }
+ }
+ else if (WINDOWP (position) || FRAMEP (position))
+ window = position;
- list_of_panes (Fcdr (menu));
+ /* Decode where to put the menu. */
- keymaps = 0;
- }
-
- if (NILP (position))
+ if (XTYPE (window) == Lisp_Frame)
+ f = XFRAME (window);
+ else if (XTYPE (window) == Lisp_Window)
{
- discard_menu_items ();
- UNGCPRO;
- return Qnil;
+ CHECK_LIVE_WINDOW (window, 0);
+ f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
}
+ else
+ /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
+ but I don't want to make one now. */
+ CHECK_WINDOW (window, 0);
- /* Display them in a dialog box. */
- BLOCK_INPUT;
+#ifndef USE_X_TOOLKIT
+ /* Display a menu with these alternatives
+ in the middle of frame F. */
+ {
+ Lisp_Object x, y, frame, newpos;
+ XSET (frame, Lisp_Frame, f);
+ XSET (x, Lisp_Int, x_pixel_width (f) / 2);
+ XSET (y, Lisp_Int, x_pixel_height (f) / 2);
+ newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil));
+
+ return Fx_popup_menu (newpos,
+ Fcons (Fcar (contents), Fcons (contents, Qnil)));
+ }
+#else
+ {
+ Lisp_Object title;
+ char *error_name;
+ Lisp_Object selection;
- selection = xdialog_show (f, xpos, ypos, menubarp,
- keymaps, title, &error_name);
- UNBLOCK_INPUT;
+ /* Decode the dialog items from what was specified. */
+ title = Fcar (contents);
+ CHECK_STRING (title, 1);
- discard_menu_items ();
+ list_of_panes (Fcons (contents, Qnil));
- UNGCPRO;
+ /* Display them in a dialog box. */
+ BLOCK_INPUT;
+ selection = xdialog_show (f, 0, 0, title, &error_name);
+ UNBLOCK_INPUT;
- if (error_name) error (error_name);
- return selection;
+ discard_menu_items ();
+
+ if (error_name) error (error_name);
+ return selection;
+ }
#endif
}
\f
extern void EmacsFrameSetCharSize ();
static void
-update_one_frame_psheets (f)
+update_frame_menubar (f)
FRAME_PTR f;
{
struct x_display *x = f->display.x;
}
void
-set_frame_menubar (f)
+set_frame_menubar (f, first_time)
FRAME_PTR f;
+ int first_time;
{
Widget menubar_widget = f->display.x->menubar_widget;
int id = (int) f;
wv->enabled = 1;
save_wv = first_wv = wv;
- items = FRAME_MENU_BAR_ITEMS (f);
+ if (NILP (items = FRAME_MENU_BAR_ITEMS (f)))
+ items = FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
for (i = 0; i < XVECTOR (items)->size; i += 3)
{
free_menubar_widget_value_tree (first_wv);
- update_one_frame_psheets (f);
+ /* Don't update the menubar the first time it is created via x_window. */
+ if (!first_time)
+ update_frame_menubar (f);
UNBLOCK_INPUT;
}
UNBLOCK_INPUT;
}
}
+/* Called from Fx_create_frame to create the inital menubar of a frame
+ before it is mapped, so that the window is mapped with the menubar already
+ there instead of us tacking it on later and thrashing the window after it
+ is visible. */
+void
+initialize_frame_menubar (f)
+ FRAME_PTR f;
+{
+ set_frame_menubar (f, 1);
+}
\f
/* Nonzero if position X, Y relative to inside of frame F
is in some other menu bar item. */
dispatch_dummy_expose (f->display.x->menubar_widget, x, y);
}
-#if 0 /* No need to do that. The menu has disappeared. */
+ /* fp turned off the following statement and wrote a comment
+ that it is unnecessary--that the menu has already disappeared.
+ I observer that is not so. -- rms. */
/* Make sure the menu disappears. */
lw_destroy_all_widgets (menu_id);
-#endif
/* Unread any events that we got but did not handle. */
while (queue != NULL)
"button6", "button7", "button8", "button9", "button10" };
static Lisp_Object
-xdialog_show (f, x, y, menubarp, keymaps, title, error)
+xdialog_show (f, menubarp, keymaps, title, error)
FRAME_PTR f;
- int x;
- int y;
int menubarp;
int keymaps;
Lisp_Object title;
int dialog_id;
Widget menu;
XlwMenuWidget menubar = (XlwMenuWidget) f->display.x->menubar_widget;
+ char dialog_name[6];
/* This is the menu bar item (if any) that led to this menu. */
widget_value *menubar_item = 0;
*error = NULL;
+ if (menu_items_n_panes > 1)
+ {
+ *error = "Multiple panes in dialog box";
+ return Qnil;
+ }
+
/* Create a tree of widget_value objects
representing the text label and buttons. */
{
descrip
= XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
+ if (NILP (item_name))
+ {
+ free_menubar_widget_value_tree (first_wv);
+ *error = "Submenu in dialog items";
+ return Qnil;
+ }
+ if (nb_buttons >= 10)
+ {
+ free_menubar_widget_value_tree (first_wv);
+ *error = "Too many dialog items";
+ return Qnil;
+ }
+
wv = malloc_widget_value ();
prev_wv->next = wv;
- wv->name = (char *) button_names [nb_buttons];
+ wv->name = (char *) button_names[nb_buttons];
if (!NILP (descrip))
wv->key = XSTRING (descrip)->data;
wv->value = XSTRING (item_name)->data;
}
wv = malloc_widget_value ();
- wv->name = "Q2BR1";
+ wv->name = dialog_name;
+
+ /* 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';
+ dialog_name[1] = '0' + nb_buttons;
+ dialog_name[2] = 'B';
+ dialog_name[3] = 'R';
+ dialog_name[4] = '0' + nb_buttons / 2;
+ dialog_name[5] = 0;
wv->contents = first_wv;
first_wv = wv;
menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
f->display.x->widget, 1, 0,
dialog_selection_callback, 0);
+#if 0 /* This causes crashes, and seems to be redundant -- rms. */
lw_modify_all_widgets (dialog_id, first_wv, True);
- lw_modify_all_widgets (dialog_id, first_wv->contents, True);
+#endif
+ lw_modify_all_widgets (dialog_id, first_wv->contents->next, True);
/* Free the widget_value objects we used to specify the contents. */
free_menubar_widget_value_tree (first_wv);
/* No selection has been chosen yet. */
menu_item_selection = 0;
-
/* Display the menu. */
lw_pop_up_all_widgets (dialog_id);
}
if (ulx < 0) x -= ulx;
if (uly < 0) y -= uly;
-
+
+ XMenuSetAEQ (menu, TRUE);
XMenuSetFreeze (menu, TRUE);
pane = selidx = 0;