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 "window.h"
#include "blockinput.h"
#include "buffer.h"
+#include "charset.h"
+#include "coding.h"
#ifdef MSDOS
#include "msdos.h"
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
enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE];
item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME];
- if (!NILP (map) && XSTRING (item_string)->data[0] == '@')
+ if (!NILP (map) && SREF (item_string, 0) == '@')
{
if (!NILP (enabled))
/* An enabled separate pane. Remember this to handle it later. */
index++; /* Skip a left, right divider. */
else
{
- if (!submenu && XSTRING (tem)->data[0] != '\0'
- && XSTRING (tem)->data[0] != '-')
+ if (!submenu && SREF (tem, 0) != '\0'
+ && SREF (tem, 0) != '-')
XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME]
= concat2 (build_string (" "), tem);
index += MENU_ITEMS_ITEM_LENGTH;
prefix = build_string (NILP (selected) ? "( ) " : "(*) ");
}
/* Not a button. If we have earlier buttons, then we need a prefix. */
- else if (!*notbuttons_ptr && XSTRING (item_string)->data[0] != '\0'
- && XSTRING (item_string)->data[0] != '-')
+ else if (!*notbuttons_ptr && SREF (item_string, 0) != '\0'
+ && SREF (item_string, 0) != '-')
prefix = build_string (" ");
if (!NILP (prefix))
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,
- doc: /* Pop up a deck-of-cards menu and return user's selection.
+ 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
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);
{
/* 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,
- doc: /* Pop up a dialog box and return user's selection.
+ 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.
(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));
/* Activate the menu bar of frame F.
This is called from keyboard.c when it gets the
- menu_bar_activate_event out of the Emacs event queue.
+ MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
To activate the menu bar, we use the X button-press event
that was saved in saved_menu_event.
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);
UNBLOCK_INPUT;
}
\f
-/* Return a tree of widget_value structures for a menu bar item
+/* Set up data i menu_items for a menu bar item
whose event type is ITEM_KEY (with string ITEM_NAME)
and whose contents come from the list of keymaps MAPS. */
-static widget_value *
-single_submenu (item_key, item_name, maps)
+static int
+parse_single_submenu (item_key, item_name, maps)
Lisp_Object item_key, item_name, maps;
{
- widget_value *wv, *prev_wv, *save_wv, *first_wv;
- int i;
- int submenu_depth = 0;
Lisp_Object length;
int len;
Lisp_Object *mapvec;
- widget_value **submenu_stack;
- int previous_items = menu_items_used;
+ int i;
int top_level_items = 0;
length = Flength (maps);
maps = Fcdr (maps);
}
- menu_items_n_panes = 0;
-
/* Loop over the given keymaps, making a pane for each map.
But don't make a pane that is empty--ignore that map instead. */
for (i = 0; i < len; i++)
single_keymap_panes (mapvec[i], item_name, item_key, 0, 10);
}
- /* Create a tree of widget_value objects
- representing the panes and their items. */
+ return top_level_items;
+}
+
+/* Create a tree of widget_value objects
+ representing the panes and items
+ in menu_items starting at index START, up to index END. */
+
+static widget_value *
+digest_single_submenu (start, end, top_level_items)
+ int start, end;
+{
+ widget_value *wv, *prev_wv, *save_wv, *first_wv;
+ int i;
+ int submenu_depth = 0;
+ widget_value **submenu_stack;
submenu_stack
= (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
first_wv = wv;
save_wv = 0;
prev_wv = 0;
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. */
- i = previous_items;
- while (i < menu_items_used)
+ i = start;
+ while (i < end)
{
if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
{
#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);
+ ? "" : (char *) SDATA (pane_name));
/* If there is just one top-level pane, put all its items directly
under the top-level menu. */
if (menu_items_n_panes == 1)
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
}
save_wv = wv;
prev_wv = 0;
#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);
+ descrip = ENCODE_SYSTEM (descrip);
AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
}
#endif /* not HAVE_MULTILINGUAL_MENU */
else
save_wv->contents = wv;
- wv->name = (char *) XSTRING (item_name)->data;
+ wv->name = (char *) SDATA (item_name);
if (!NILP (descrip))
- wv->key = (char *) XSTRING (descrip)->data;
+ wv->key = (char *) SDATA (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. */
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;
return first_wv;
}
-
-
\f
/* Recompute all the widgets of frame F, when the menu bar has been
changed. Value is non-zero if widgets were updated. */
Widget menubar_widget = f->output_data.x->menubar_widget;
Lisp_Object items;
widget_value *wv, *first_wv, *prev_wv = 0;
- int i;
+ int i, last_i;
+ int *submenu_start, *submenu_end;
+ int *submenu_top_level_items;
+
LWLIB_ID id;
XSETFRAME (Vmenu_updating_frame, f);
f->output_data.x->saved_menu_event->type = 0;
}
- wv = xmalloc_widget_value ();
- wv->name = "menubar";
- wv->value = 0;
- wv->enabled = 1;
- wv->button_type = BUTTON_TYPE_NONE;
- first_wv = wv;
-
if (deep_p)
{
/* Make a widget-value tree representing the entire menu trees. */
struct buffer *prev = current_buffer;
Lisp_Object buffer;
- int specpdl_count = specpdl_ptr - specpdl;
+ int specpdl_count = SPECPDL_INDEX ();
int previous_menu_items_used = f->menu_bar_items_used;
Lisp_Object *previous_items
= (Lisp_Object *) alloca (previous_menu_items_used
items = FRAME_MENU_BAR_ITEMS (f);
- inhibit_garbage_collection ();
-
/* Save the frame's previous menu bar contents data. */
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. */
+ /* Fill in menu_items with the current menu bar contents.
+ This can evaluate Lisp code. */
menu_items = f->menu_bar_vector;
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_top_level_items
+ = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
init_menu_items ();
for (i = 0; i < XVECTOR (items)->size; i += 4)
{
Lisp_Object key, string, maps;
+ last_i = i;
+
key = XVECTOR (items)->contents[i];
string = XVECTOR (items)->contents[i + 1];
maps = XVECTOR (items)->contents[i + 2];
if (NILP (string))
break;
- wv = single_submenu (key, string, maps);
+ submenu_start[i] = menu_items_used;
+
+ menu_items_n_panes = 0;
+ submenu_top_level_items[i]
+ = parse_single_submenu (key, string, maps);
+
+ submenu_end[i] = menu_items_used;
+ }
+
+ finish_menu_items ();
+
+ /* Convert menu_items into widget_value trees
+ to display the menu. This cannot evaluate Lisp code. */
+
+ wv = xmalloc_widget_value ();
+ wv->name = "menubar";
+ wv->value = 0;
+ wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
+ first_wv = wv;
+
+ for (i = 0; i < last_i; i += 4)
+ {
+ wv = digest_single_submenu (submenu_start[i], submenu_end[i],
+ submenu_top_level_items[i]);
if (prev_wv)
prev_wv->next = wv;
else
prev_wv = wv;
}
- finish_menu_items ();
-
set_buffer_internal_1 (prev);
unbind_to (specpdl_count, Qnil);
string = XVECTOR (items)->contents[i + 1];
if (NILP (string))
break;
- wv->name = (char *) XSTRING (string)->data;
+ wv->name = (char *) SDATA (string);
wv = wv->next;
}
/* Make a widget-value tree containing
just the top level menu bar strings. */
+ wv = xmalloc_widget_value ();
+ wv->name = "menubar";
+ wv->value = 0;
+ wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
+ first_wv = wv;
+
items = FRAME_MENU_BAR_ITEMS (f);
for (i = 0; i < XVECTOR (items)->size; i += 4)
{
break;
wv = xmalloc_widget_value ();
- wv->name = (char *) XSTRING (string)->data;
+ wv->name = (char *) SDATA (string);
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.
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
+ wv->help =Qnil;
first_wv = wv;
first_pane = 1;
#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);
+ ? "" : (char *) SDATA (pane_name));
/* If there is just one top-level pane, put all its items directly
under the top-level menu. */
if (menu_items_n_panes == 1)
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
save_wv = wv;
prev_wv = 0;
}
#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))
{
- descrip = string_make_unibyte (descrip);
+ descrip = ENCODE_SYSTEM (descrip);
AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
}
#endif /* not HAVE_MULTILINGUAL_MENU */
prev_wv->next = wv;
else
save_wv->contents = wv;
- wv->name = (char *) XSTRING (item_name)->data;
+ wv->name = (char *) SDATA (item_name);
if (!NILP (descrip))
- wv->key = (char *) XSTRING (descrip)->data;
+ wv->key = (char *) SDATA (descrip);
wv->value = 0;
/* If this item has a null value,
make the call_data null so that it won't display a box
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->name = (char *) SDATA (title);
+ 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;
}
pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME];
prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX];
pane_string = (NILP (pane_name)
- ? "" : (char *) XSTRING (pane_name)->data);
+ ? "" : (char *) SDATA (pane_name));
prev_wv = xmalloc_widget_value ();
prev_wv->value = pane_string;
if (keymaps && !NILP (prefix))
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. */
prev_wv->next = wv;
wv->name = (char *) button_names[nb_buttons];
if (!NILP (descrip))
- wv->key = (char *) XSTRING (descrip)->data;
- wv->value = (char *) XSTRING (item_name)->data;
+ wv->key = (char *) SDATA (descrip);
+ wv->value = (char *) SDATA (item_name);
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];
pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
pane_string = (NILP (pane_name)
- ? "" : (char *) XSTRING (pane_name)->data);
+ ? "" : (char *) SDATA (pane_name));
if (keymaps && !NILP (prefix))
pane_string++;
j++;
continue;
}
- width = STRING_BYTES (XSTRING (item));
+ width = SBYTES (item);
if (width > maxwidth)
maxwidth = width;
descrip
= XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
- help_string = STRINGP (help) ? XSTRING (help)->data : NULL;
+ help_string = STRINGP (help) ? SDATA (help) : NULL;
if (!NILP (descrip))
{
- int gap = maxwidth - STRING_BYTES (XSTRING (item_name));
+ int gap = maxwidth - SBYTES (item_name);
#ifdef C_ALLOCA
Lisp_Object spacer;
spacer = Fmake_string (make_number (gap), make_number (' '));
item_name = concat2 (item_name, spacer);
item_name = concat2 (item_name, descrip);
- item_data = XSTRING (item_name)->data;
+ item_data = SDATA (item_name);
#else
/* if alloca is fast, use that to make the space,
to reduce gc needs. */
item_data
= (unsigned char *) alloca (maxwidth
- + STRING_BYTES (XSTRING (descrip)) + 1);
- bcopy (XSTRING (item_name)->data, item_data,
- STRING_BYTES (XSTRING (item_name)));
- for (j = XSTRING (item_name)->size; j < maxwidth; j++)
+ + SBYTES (descrip) + 1);
+ bcopy (SDATA (item_name), item_data,
+ SBYTES (item_name));
+ for (j = SCHARS (item_name); j < maxwidth; j++)
item_data[j] = ' ';
- bcopy (XSTRING (descrip)->data, item_data + j,
- STRING_BYTES (XSTRING (descrip)));
- item_data[j + STRING_BYTES (XSTRING (descrip))] = 0;
+ bcopy (SDATA (descrip), item_data + j,
+ SBYTES (descrip));
+ item_data[j + SBYTES (descrip)] = 0;
#endif
}
else
- item_data = XSTRING (item_name)->data;
+ item_data = SDATA (item_name);
if (XMenuAddSelection (FRAME_X_DISPLAY (f),
menu, lpane, 0, item_data,