the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* X pop-up deck-of-cards menu facility for gnuemacs.
+/* X pop-up deck-of-cards menu facility for GNU Emacs.
*
* Written by Jon Arnold and Roman Budzianowski
* Mods and rewrite by Robert Krawitz
#include <signal.h>
#include <stdio.h>
+
#include "lisp.h"
#include "termhooks.h"
#include "keyboard.h"
+#include "keymap.h"
#include "frame.h"
#include "window.h"
#include "blockinput.h"
#include "buffer.h"
+#include "charset.h"
+#include "coding.h"
#ifdef MSDOS
#include "msdos.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))
-
#ifndef TRUE
#define TRUE 1
#define FALSE 0
static Lisp_Object xdialog_show ();
void popup_get_selection ();
-#endif
-#ifdef USE_X_TOOLKIT
-
-/* Define HAVE_BOXES if meus can handle radio and toggle buttons. */
+/* Define HAVE_BOXES if menus can handle radio and toggle buttons. */
#define HAVE_BOXES 1
#endif
menu_items_submenu_depth = 0;
}
-/* Call at the end of generating the data in menu_items.
- This fills in the number of items in the last pane. */
+/* Call at the end of generating the data in menu_items. */
static void
finish_menu_items ()
XVECTOR (menu_items)->contents[menu_items_used++] = Qquote;
}
-/* Start a new menu pane in menu_items..
+/* Start a new menu pane in menu_items.
NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */
static void
P is the number of panes we have made so far. */
for (mapno = 0; mapno < nmaps; mapno++)
single_keymap_panes (keymaps[mapno],
- map_prompt (keymaps[mapno]), Qnil, notreal, 10);
+ Fkeymap_prompt (keymaps[mapno]), Qnil, notreal, 10);
finish_menu_items ();
}
Lisp_Object elt, pane_name, pane_data;
elt = Fcar (tail);
pane_name = Fcar (elt);
- CHECK_STRING (pane_name, 0);
+ CHECK_STRING (pane_name);
push_menu_pane (pane_name, Qnil);
pane_data = Fcdr (elt);
- CHECK_CONS (pane_data, 0);
+ CHECK_CONS (pane_data);
list_of_items (pane_data);
}
push_left_right_boundary ();
else
{
- CHECK_CONS (item, 0);
+ CHECK_CONS (item);
item1 = Fcar (item);
- CHECK_STRING (item1, 1);
+ CHECK_STRING (item1);
push_menu_item (item1, Qt, Fcdr (item), Qt, Qnil, Qnil, Qnil, Qnil);
}
}
}
\f
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\
-where XOFFSET and YOFFSET are positions in pixels 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\
-If REAL-DEFINITION is nil, that puts a nonselectable string in the menu.\n\
-Otherwise, REAL-DEFINITION should be a valid key binding definition.\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\
-\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\
-\n\
-If POSITION is nil, don't display the menu at all, just precalculate the\n\
-cached information about equivalent key sequences.")
- (position, menu)
+ doc: /* Pop up a deck-of-cards menu and return user's selection.
+POSITION is a position specification. This is either a mouse button event
+or a list ((XOFFSET YOFFSET) WINDOW)
+where XOFFSET and YOFFSET are positions in pixels from the top left
+corner of WINDOW's frame. (WINDOW may be a frame object instead of a window.)
+This controls the position of the center of the first line
+in the first pane of the menu, not the top left of the menu as a whole.
+If POSITION is t, it means to use the current mouse position.
+
+MENU is a specifier for a menu. For the simplest case, MENU is a keymap.
+The menu items come from key bindings that have a menu string as well as
+a definition; actually, the "definition" in such a key binding looks like
+\(STRING . REAL-DEFINITION). To give the menu a title, put a string into
+the keymap as a top-level element.
+
+If REAL-DEFINITION is nil, that puts a nonselectable string in the menu.
+Otherwise, REAL-DEFINITION should be a valid key binding definition.
+
+You can also use a list of keymaps as MENU.
+ Then each keymap makes a separate pane.
+When MENU is a keymap or a list of keymaps, the return value
+is a list of events.
+
+Alternatively, you can specify a menu of multiple panes
+ with a list of the form (TITLE PANE1 PANE2...),
+where each pane is a list of form (TITLE ITEM1 ITEM2...).
+Each ITEM is normally a cons cell (STRING . VALUE);
+but a string can appear as an item--that makes a nonselectable line
+in the menu.
+With this form of menu, the return value is VALUE from the chosen item.
+
+If POSITION is nil, don't display the menu at all, just precalculate the
+cached information about equivalent key sequences. */)
+ (position, menu)
Lisp_Object position, menu;
{
Lisp_Object keymap, tem;
Lisp_Object title;
char *error_name;
Lisp_Object selection;
- struct frame *f = NULL;
+ FRAME_PTR f = NULL;
Lisp_Object x, y, window;
int keymaps = 0;
int for_click = 0;
}
}
- CHECK_NUMBER (x, 0);
- CHECK_NUMBER (y, 0);
+ CHECK_NUMBER (x);
+ CHECK_NUMBER (y);
/* Decode where to put the menu. */
}
else if (WINDOWP (window))
{
- CHECK_LIVE_WINDOW (window, 0);
+ CHECK_LIVE_WINDOW (window);
f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
- xpos = (FONT_WIDTH (f->output_data.x->font)
+ xpos = (FONT_WIDTH (FRAME_FONT (f))
* XFASTINT (XWINDOW (window)->left));
- ypos = (f->output_data.x->line_height
+ ypos = (FRAME_LINE_HEIGHT (f)
* XFASTINT (XWINDOW (window)->top));
}
else
/* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
but I don't want to make one now. */
- CHECK_WINDOW (window, 0);
+ CHECK_WINDOW (window);
xpos += XINT (x);
ypos += XINT (y);
/* Search for a string appearing directly as an element of the keymap.
That string is the title of the menu. */
- prompt = map_prompt (keymap);
+ prompt = Fkeymap_prompt (keymap);
if (NILP (title) && !NILP (prompt))
title = prompt;
maps[i++] = keymap = get_keymap (Fcar (tem), 1, 0);
- prompt = map_prompt (keymap);
+ prompt = Fkeymap_prompt (keymap);
if (NILP (title) && !NILP (prompt))
title = prompt;
}
{
/* We were given an old-fashioned menu. */
title = Fcar (menu);
- CHECK_STRING (title, 1);
+ CHECK_STRING (title);
list_of_panes (Fcdr (menu));
#ifdef HAVE_MENUS
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 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\
-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.\n\n\
-An ITEM may also be just a string--that makes a nonselectable item.\n\
-An ITEM may also be nil--that means to put all preceding items\n\
-on the left of the dialog box and all following items on the right.\n\
-\(By default, approximately half appear on each side.)")
- (position, contents)
+ 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.
+If POSITION is t, it means to use the frame the mouse is on.
+The dialog box appears in the middle of the specified frame.
+
+CONTENTS specifies the alternatives to display in the dialog box.
+It is a list of the form (TITLE ITEM1 ITEM2...).
+Each ITEM is a cons cell (STRING . VALUE).
+The return value is VALUE from the chosen item.
+
+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;
{
- struct frame * f = NULL;
+ FRAME_PTR f = NULL;
Lisp_Object window;
check_x ();
/* Use the mouse's current position. */
FRAME_PTR new_f = SELECTED_FRAME ();
Lisp_Object bar_window;
- int part;
+ enum scroll_bar_part part;
unsigned long time;
Lisp_Object x, y;
f = XFRAME (window);
else if (WINDOWP (window))
{
- CHECK_LIVE_WINDOW (window, 0);
+ CHECK_LIVE_WINDOW (window);
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);
+ CHECK_WINDOW (window);
#ifndef USE_X_TOOLKIT
/* Display a menu with these alternatives
/* Decode the dialog items from what was specified. */
title = Fcar (contents);
- CHECK_STRING (title, 1);
+ CHECK_STRING (title);
list_of_panes (Fcons (contents, Qnil));
struct frame *f;
Lisp_Object frame, help;
- help = wv && wv->help ? build_string (wv->help) : Qnil;
+ help = wv ? wv->help : Qnil;
/* Determine the frame for the help event. */
f = menubar_id_to_frame (id);
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
first_wv = wv;
save_wv = 0;
prev_wv = 0;
/* Create a new pane. */
Lisp_Object pane_name, prefix;
char *pane_string;
+
pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
+
#ifndef HAVE_MULTILINGUAL_MENU
if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
- pane_name = string_make_unibyte (pane_name);
+ {
+ pane_name = ENCODE_SYSTEM (pane_name);
+ AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
+ }
#endif
pane_string = (NILP (pane_name)
? "" : (char *) XSTRING (pane_name)->data);
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
}
save_wv = wv;
prev_wv = 0;
Lisp_Object item_name, enable, descrip, def, type, selected;
Lisp_Object help;
- 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];
- type = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_TYPE];
- selected = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_SELECTED];
- help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
+ item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
+ enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
+ descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
+ def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
+ type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
+ 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))
- item_name = string_make_unibyte (item_name);
+ {
+ item_name = ENCODE_SYSTEM (item_name);
+ AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
+ }
+
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
- descrip = string_make_unibyte (descrip);
-#endif
+ {
+ descrip = ENCODE_SYSTEM (descrip);
+ AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
+ }
+#endif /* not HAVE_MULTILINGUAL_MENU */
wv = xmalloc_widget_value ();
if (prev_wv)
abort ();
wv->selected = !NILP (selected);
- if (STRINGP (help))
- wv->help = XSTRING (help)->data;
-
+ if (! STRINGP (help))
+ help = Qnil;
+
+ wv->help = help;
+
prev_wv = wv;
i += MENU_ITEMS_ITEM_LENGTH;
Lisp_Object items;
widget_value *wv, *first_wv, *prev_wv = 0;
int i;
+
LWLIB_ID id;
XSETFRAME (Vmenu_updating_frame, f);
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
first_wv = wv;
if (deep_p)
inhibit_garbage_collection ();
/* Save the frame's previous menu bar contents data. */
- bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
- previous_menu_items_used * sizeof (Lisp_Object));
+ if (previous_menu_items_used)
+ bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
+ previous_menu_items_used * sizeof (Lisp_Object));
/* Fill in the current menu bar contents. */
menu_items = f->menu_bar_vector;
- menu_items_allocated = XVECTOR (menu_items)->size;
+ menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
init_menu_items ();
for (i = 0; i < XVECTOR (items)->size; i += 4)
{
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
/* This prevents lwlib from assuming this
menu item is really supposed to be empty. */
/* The EMACS_INT cast avoids a warning.
BLOCK_INPUT;
#ifdef USE_MOTIF
- XtVaGetValues (f->output_data.x->widget, XtNx, &x0, XtNy, &y0, NULL);
+ if (f->output_data.x->widget)
+ XtVaGetValues (f->output_data.x->widget, XtNx, &x0, XtNy, &y0, NULL);
#endif
lw_destroy_all_widgets ((LWLIB_ID) f->output_data.x->id);
f->output_data.x->menubar_widget = NULL;
#ifdef USE_MOTIF
- XtVaGetValues (f->output_data.x->widget, XtNx, &x1, XtNy, &y1, NULL);
- if (x1 == 0 && y1 == 0)
- XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);
+ if (f->output_data.x->widget)
+ {
+ XtVaGetValues (f->output_data.x->widget, XtNx, &x1, XtNy, &y1, NULL);
+ if (x1 == 0 && y1 == 0)
+ XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);
+ }
#endif
UNBLOCK_INPUT;
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
+ wv->help =Qnil;
first_wv = wv;
first_pane = 1;
/* Create a new pane. */
Lisp_Object pane_name, prefix;
char *pane_string;
- pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
- prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
+
+ pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
+ prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
+
#ifndef HAVE_MULTILINGUAL_MENU
- if (!NILP (pane_name) && STRING_MULTIBYTE (pane_name))
- pane_name = string_make_unibyte (pane_name);
+ if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
+ {
+ pane_name = ENCODE_SYSTEM (pane_name);
+ AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
+ }
#endif
pane_string = (NILP (pane_name)
? "" : (char *) XSTRING (pane_name)->data);
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
save_wv = wv;
prev_wv = 0;
}
{
/* Create a new item within current pane. */
Lisp_Object item_name, enable, descrip, def, type, selected, help;
- 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];
- type = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_TYPE];
- selected = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_SELECTED];
- help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
+ item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
+ enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
+ descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
+ def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
+ type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
+ 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))
- item_name = string_make_unibyte (item_name);
+ {
+ item_name = ENCODE_SYSTEM (item_name);
+ AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
+ }
+
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
- item_name = string_make_unibyte (descrip);
-#endif
+ {
+ descrip = ENCODE_SYSTEM (descrip);
+ AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
+ }
+#endif /* not HAVE_MULTILINGUAL_MENU */
wv = xmalloc_widget_value ();
if (prev_wv)
abort ();
wv->selected = !NILP (selected);
- if (STRINGP (help))
- wv->help = XSTRING (help)->data;
-
+
+ if (! STRINGP (help))
+ help = Qnil;
+
+ wv->help = help;
+
prev_wv = wv;
i += MENU_ITEMS_ITEM_LENGTH;
wv_sep2->name = "--";
wv_sep2->next = first_wv->contents;
+ wv_sep2->help = Qnil;
wv_sep1->name = "--";
wv_sep1->next = wv_sep2;
+ wv_sep1->help = Qnil;
#ifndef HAVE_MULTILINGUAL_MENU
if (STRING_MULTIBYTE (title))
- title = string_make_unibyte (title);
+ title = ENCODE_SYSTEM (title);
#endif
+
wv_title->name = (char *) XSTRING (title)->data;
- wv_title->enabled = True;
+ wv_title->enabled = TRUE;
wv_title->button_type = BUTTON_TYPE_NONE;
wv_title->next = wv_sep1;
+ wv_title->help = Qnil;
first_wv->contents = wv_title;
}
prev_wv->name++;
prev_wv->enabled = 1;
prev_wv->name = "message";
+ prev_wv->help = Qnil;
first_wv = prev_wv;
/* Loop over all panes and items, filling in the tree. */
wv->value = (char *) XSTRING (item_name)->data;
wv->call_data = (void *) &XVECTOR (menu_items)->contents[i];
wv->enabled = !NILP (enable);
+ wv->help = Qnil;
prev_wv = wv;
if (! boundary_seen)
wv = xmalloc_widget_value ();
wv->name = dialog_name;
-
+ wv->help = Qnil;
/* Dialog boxes use a really stupid name encoding
which specifies how many buttons to use
and how many buttons are on the right.
pane_name = first_item[MENU_ITEMS_PANE_NAME];
else if (EQ (first_item[0], Qquote))
/* This shouldn't happen, see xmenu_show. */
- pane_name = build_string ("");
+ pane_name = empty_string;
else
pane_name = first_item[MENU_ITEMS_ITEM_NAME];
/* All set and ready to fly. */
XMenuRecompute (FRAME_X_DISPLAY (f), menu);
- dispwidth = DisplayWidth (FRAME_X_DISPLAY (f),
- XScreenNumberOfScreen (FRAME_X_SCREEN (f)));
- dispheight = DisplayHeight (FRAME_X_DISPLAY (f),
- XScreenNumberOfScreen (FRAME_X_SCREEN (f)));
+ dispwidth = DisplayWidth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f));
+ dispheight = DisplayHeight (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f));
x = min (x, dispwidth);
y = min (y, dispheight);
x = max (x, 1);
staticpro (&Qdebug_on_next_call);
DEFVAR_LISP ("menu-updating-frame", &Vmenu_updating_frame,
- "Frame for which we are updating a menu.\n\
-The enable predicate for a menu command should check this variable.");
+ doc: /* Frame for which we are updating a menu.
+The enable predicate for a menu command should check this variable. */);
Vmenu_updating_frame = Qnil;
#ifdef USE_X_TOOLKIT