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>
-#define DOC_STRINGS_IN_COMMENTS
+
#include "lisp.h"
#include "termhooks.h"
#include "keyboard.h"
#include "window.h"
#include "blockinput.h"
#include "buffer.h"
+#include "charset.h"
+#include "coding.h"
#ifdef MSDOS
#include "msdos.h"
extern XtAppContext Xt_app_con;
static Lisp_Object xdialog_show ();
-void popup_get_selection ();
-#endif
-
-#ifdef USE_X_TOOLKIT
+static void popup_get_selection ();
-/* 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
int, int, int *));
static void list_of_panes P_ ((Lisp_Object));
static void list_of_items P_ ((Lisp_Object));
+
+extern EMACS_TIME timer_check P_ ((int));
\f
/* This holds a Lisp vector that holds the results of decoding
the keymaps or alist-of-alists that specify a menu.
static Lisp_Object menu_items;
+/* If non-nil, means that the global vars defined here are already in use.
+ Used to detect cases where we try to re-enter this non-reentrant code. */
+static Lisp_Object menu_items_inuse;
+
/* Number of slots currently allocated in menu_items. */
static int menu_items_allocated;
menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
}
+ if (!NILP (menu_items_inuse))
+ error ("Trying to use a menu from within a menu-entry");
+ menu_items_inuse = Qt;
menu_items_used = 0;
menu_items_n_panes = 0;
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 ()
{
}
+static Lisp_Object
+unuse_menu_items (dummy)
+ int dummy;
+{
+ return menu_items_inuse = Qnil;
+}
+
/* Call when finished using the data for the current menu
in menu_items. */
menu_items = Qnil;
menu_items_allocated = 0;
}
+ xassert (NILP (menu_items_inuse));
}
/* Make the menu_items vector twice as large. */
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,
- /* 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
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))
+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;
+ int specpdl_count = SPECPDL_INDEX ();
struct gcpro gcpro1;
#ifdef HAVE_MENUS
}
}
- 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);
-
- XSETFRAME (Vmenu_updating_frame, f);
}
Vmenu_updating_frame = Qnil;
#endif /* HAVE_MENUS */
+ record_unwind_protect (unuse_menu_items, Qnil);
title = Qnil;
GCPRO1 (title);
{
/* We were given an old-fashioned menu. */
title = Fcar (menu);
- CHECK_STRING (title, 1);
+ CHECK_STRING (title);
list_of_panes (Fcdr (menu));
keymaps = 0;
}
+ unbind_to (specpdl_count, Qnil);
+
if (NILP (position))
{
discard_menu_items ();
#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.
+ 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.
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))
+\(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
Lisp_Object title;
char *error_name;
Lisp_Object selection;
+ int specpdl_count = SPECPDL_INDEX ();
/* Decode the dialog items from what was specified. */
title = Fcar (contents);
- CHECK_STRING (title, 1);
+ CHECK_STRING (title);
+ record_unwind_protect (unuse_menu_items, Qnil);
list_of_panes (Fcons (contents, Qnil));
selection = xdialog_show (f, 0, title, &error_name);
UNBLOCK_INPUT;
+ unbind_to (specpdl_count, Qnil);
discard_menu_items ();
if (error_name) error (error_name);
\f
#ifdef USE_X_TOOLKIT
+/* Define a queue to save up for later unreading
+ all X events that don't pertain to the menu. */
+struct event_queue
+ {
+ XEvent event;
+ struct event_queue *next;
+ };
+
+/* It is ok that this queue is a static variable,
+ because init_menu_items won't allow the menu mechanism
+ to be entered recursively. */
+static struct event_queue *popup_get_selection_queue;
+
+static Lisp_Object popup_get_selection_unwind ();
+
/* Loop in Xt until the menu pulldown or dialog popup has been
popped down (deactivated). This is used for x-popup-menu
- and x-popup-dialog; it is not used for the menu bar any more.
+ and x-popup-dialog; it is not used for the menu bar.
+
+ If DO_TIMERS is nonzero, run timers.
NOTE: All calls to popup_get_selection should be protected
with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */
-void
-popup_get_selection (initial_event, dpyinfo, id)
+static void
+popup_get_selection (initial_event, dpyinfo, id, do_timers)
XEvent *initial_event;
struct x_display_info *dpyinfo;
LWLIB_ID id;
+ int do_timers;
{
XEvent event;
-
- /* Define a queue to save up for later unreading
- all X events that don't pertain to the menu. */
- struct event_queue
- {
- XEvent event;
- struct event_queue *next;
- };
-
- struct event_queue *queue = NULL;
struct event_queue *queue_tmp;
+ int count = SPECPDL_INDEX ();
+
+ popup_get_selection_queue = NULL;
+
+ record_unwind_protect (popup_get_selection_unwind, Qnil);
if (initial_event)
event = *initial_event;
{
queue_tmp = (struct event_queue *) xmalloc (sizeof *queue_tmp);
queue_tmp->event = event;
- queue_tmp->next = queue;
- queue = queue_tmp;
+ queue_tmp->next = popup_get_selection_queue;
+ popup_get_selection_queue = queue_tmp;
}
else
XtDispatchEvent (&event);
- if (!popup_activated ())
+ /* If the event deactivated the menu, we are finished. */
+ if (!popup_activated_flag)
break;
+
+ /* If we have no events to run, consider timers. */
+ if (do_timers && !XtAppPending (Xt_app_con))
+ timer_check (1);
+
XtAppNextEvent (Xt_app_con, &event);
}
- /* Unread any events that we got but did not handle. */
- while (queue != NULL)
+ unbind_to (count, Qnil);
+}
+
+/* Unread any events that popup_get_selection read but did not handle. */
+
+static Lisp_Object
+popup_get_selection_unwind (ignore)
+ Lisp_Object ignore;
+{
+ while (popup_get_selection_queue != NULL)
{
- queue_tmp = queue;
+ struct event_queue *queue_tmp;
+ queue_tmp = popup_get_selection_queue;
XPutBackEvent (queue_tmp->event.xany.display, &queue_tmp->event);
- queue = queue_tmp->next;
+ popup_get_selection_queue = queue_tmp->next;
xfree ((char *)queue_tmp);
/* Cause these events to get read as soon as we UNBLOCK_INPUT. */
interrupt_input_pending = 1;
/* 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.
set_frame_menubar (f, 0, 1);
BLOCK_INPUT;
- XtDispatchEvent ((XEvent *) f->output_data.x->saved_menu_event);
+ XtDispatchEvent (f->output_data.x->saved_menu_event);
UNBLOCK_INPUT;
#ifdef USE_MOTIF
if (f->output_data.x->saved_menu_event->type == ButtonRelease)
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 in 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++)
{
- if (SYMBOLP (mapvec[i])
- || (CONSP (mapvec[i]) && !KEYMAPP (mapvec[i])))
+ if (!KEYMAPP (mapvec[i]))
{
/* Here we have a command at top level in the menu bar
as opposed to a submenu. */
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);
+ }
}
- /* 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, top_level_items;
+{
+ 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;
- /* 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. */
- i = previous_items;
- while (i < menu_items_used)
+ /* 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)
{
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, *submenu_n_panes;
+
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
specbind (Qdebug_on_next_call, Qnil);
record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
+ record_unwind_protect (unuse_menu_items, Qnil);
if (NILP (Voverriding_local_map_menu_flag))
{
specbind (Qoverriding_terminal_local_map, Qnil);
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_n_panes = (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_n_panes[i] = menu_items_n_panes;
+
+ 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)
+ {
+ 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)
prev_wv->next = wv;
else
prev_wv = wv;
}
- finish_menu_items ();
-
set_buffer_internal_1 (prev);
unbind_to (specpdl_count, Qnil);
if (i == menu_items_used && i == previous_menu_items_used && i != 0)
{
free_menubar_widget_value_tree (first_wv);
- menu_items = Qnil;
+ discard_menu_items ();
return;
}
string = XVECTOR (items)->contents[i + 1];
if (NILP (string))
break;
- wv->name = (char *) XSTRING (string)->data;
+ wv->name = (char *) SDATA (string);
wv = wv->next;
}
f->menu_bar_vector = menu_items;
f->menu_bar_items_used = menu_items_used;
- menu_items = Qnil;
+ discard_menu_items ();
}
else
{
/* 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;
}
popup_activated_flag = 1;
/* Process events that apply to the menu. */
- popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id);
+ popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 0);
/* fp turned off the following statement and wrote a comment
that it is unnecessary--that the menu has already disappeared.
popup_activated_flag = 0;
}
+/* ARG is the LWLIB ID of the dialog box, represented
+ as a Lisp object as (HIGHPART . LOWPART). */
+
+Lisp_Object
+xdialog_show_unwind (arg)
+ Lisp_Object arg;
+{
+ LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
+ | XINT (XCDR (arg)));
+ BLOCK_INPUT;
+ lw_destroy_all_widgets (id);
+ UNBLOCK_INPUT;
+ popup_activated_flag = 0;
+ return Qnil;
+}
+
static char * button_names [] = {
"button1", "button2", "button3", "button4", "button5",
"button6", "button7", "button8", "button9", "button10" };
{
int i, nb_buttons=0;
LWLIB_ID dialog_id;
- Widget menu;
char dialog_name[6];
widget_value *wv, *first_wv = 0, *prev_wv = 0;
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.
/* Actually create the dialog. */
dialog_id = widget_id_tick++;
- menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
- f->output_data.x->widget, 1, 0,
- dialog_selection_callback, 0, 0);
+ lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
+ f->output_data.x->widget, 1, 0,
+ dialog_selection_callback, 0, 0);
lw_modify_all_widgets (dialog_id, first_wv->contents, 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. */
+ /* Display the dialog box. */
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);
+ /* Process events that apply to the dialog box.
+ Also handle timers. */
+ {
+ int count = SPECPDL_INDEX ();
- lw_destroy_all_widgets (dialog_id);
+ /* xdialog_show_unwind is responsible for popping the dialog box down. */
+ record_unwind_protect (xdialog_show_unwind,
+ Fcons (make_number (dialog_id >> (4 * sizeof (LWLIB_ID))),
+ make_number (dialog_id & ~(-1 << (4 * sizeof (LWLIB_ID))))));
- /* Find the selected item, and its pane, to return
- the proper value. */
+ popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id, 1);
+
+ unbind_to (count, Qnil);
+ }
+
+ /* Find the selected item and pane, and return the corresponding value. */
if (menu_item_selection != 0)
{
Lisp_Object prefix;
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,
{
staticpro (&menu_items);
menu_items = Qnil;
+ menu_items_inuse = Qnil;
Qdebug_on_next_call = intern ("debug-on-next-call");
staticpro (&Qdebug_on_next_call);
- DEFVAR_LISP ("menu-updating-frame", &Vmenu_updating_frame
- /* Frame for which we are updating a menu.
+ 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;