/* X Communication module for terminals which understand the X protocol.
-Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2011
+Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2012
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <config.h>
-#if 0 /* Why was this included? And without syssignal.h? */
-/* On 4.3 this loses if it comes after xterm.h. */
-#include <signal.h>
-#endif
-
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
#include "keyboard.h"
#include "termhooks.h"
#include "window.h"
#include "blockinput.h"
+#include "character.h"
#include "buffer.h"
#include "charset.h"
#include "coding.h"
#ifdef USE_GTK
#include "gtkutil.h"
+#ifdef HAVE_GTK3
+#include "xgselect.h"
+#endif
#endif
#include "menu.h"
int dummy;
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
BLOCK_INPUT;
}
else if (CONSP (position))
{
- Lisp_Object tem;
- tem = Fcar (position);
+ Lisp_Object tem = XCAR (position);
if (CONSP (tem))
- window = Fcar (Fcdr (position));
+ window = Fcar (XCDR (position));
else
{
- tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
+ tem = Fcar (XCDR (position)); /* EVENT_START (position) */
window = Fcar (tem); /* POSN_WINDOW (tem) */
}
}
)
{
EMACS_TIME next_time = timer_check (), *ntp;
- long secs = EMACS_SECS (next_time);
- long usecs = EMACS_USECS (next_time);
SELECT_TYPE read_fds;
struct x_display_info *dpyinfo;
int n = 0;
XFlush (dpyinfo->display);
}
- if (secs < 0 && usecs < 0)
+ if (! EMACS_TIME_VALID_P (next_time))
ntp = 0;
else
ntp = &next_time;
- select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, ntp);
+#ifdef HAVE_GTK3
+ /* Gtk3 have arrows on menus when they don't fit. When the
+ pointer is over an arrow, a timeout scrolls it a bit. Use
+ xg_select so that timeout gets triggered. */
+ xg_select (n + 1, &read_fds, NULL, NULL, ntp, NULL);
+#else
+ pselect (n + 1, &read_fds, NULL, NULL, ntp, NULL);
+#endif
}
}
#endif /* ! MSDOS */
x_activate_menubar (FRAME_PTR f)
{
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
if (!f->output_data.x->saved_menu_event->type)
return;
/* This callback is invoked when a dialog or menu is finished being
used and has been unposted. */
-#ifdef USE_GTK
static void
-popup_deactivate_callback (GtkWidget *widget, gpointer client_data)
-{
- popup_activated_flag = 0;
-}
+popup_deactivate_callback (
+#ifdef USE_GTK
+ GtkWidget *widget, gpointer client_data
#else
-static void
-popup_deactivate_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
+ Widget widget, LWLIB_ID id, XtPointer client_data
+#endif
+ )
{
popup_activated_flag = 0;
}
-#endif
/* Function that finds the frame for WIDGET and shows the HELP text
int columns, rows;
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
x = f->output_data.x;
int *submenu_top_level_items, *submenu_n_panes;
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
menubar_widget = f->output_data.x->menubar_widget;
else if (!f->output_data.x->saved_menu_event && !deep_p)
{
deep_p = 1;
- f->output_data.x->saved_menu_event = (XEvent*)xmalloc (sizeof (XEvent));
+ f->output_data.x->saved_menu_event = xmalloc (sizeof (XEvent));
f->output_data.x->saved_menu_event->type = 0;
}
ptrdiff_t 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
- * sizeof (Lisp_Object));
+ = alloca (previous_menu_items_used * sizeof *previous_items);
int subitems;
/* If we are making a new widget, its contents are empty,
if (! NILP (Vlucid_menu_bar_dirty_flag))
call0 (Qrecompute_lucid_menubar);
safe_run_hooks (Qmenu_bar_update_hook);
- FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
+ fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
items = FRAME_MENU_BAR_ITEMS (f);
/* Save the frame's previous menu bar contents data. */
if (previous_menu_items_used)
memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
- previous_menu_items_used * sizeof (Lisp_Object));
+ previous_menu_items_used * word_size);
/* 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;
subitems = ASIZE (items) / 4;
- submenu_start = (int *) alloca ((subitems + 1) * sizeof (int));
- submenu_end = (int *) alloca (subitems * sizeof (int));
- submenu_n_panes = (int *) alloca (subitems * sizeof (int));
- submenu_top_level_items = (int *) alloca (subitems * sizeof (int));
+ submenu_start = alloca ((subitems + 1) * sizeof *submenu_start);
+ submenu_end = alloca (subitems * sizeof *submenu_end);
+ submenu_n_panes = alloca (subitems * sizeof *submenu_n_panes);
+ submenu_top_level_items = alloca (subitems
+ * sizeof *submenu_top_level_items);
init_menu_items ();
for (i = 0; i < subitems; i++)
{
Lisp_Object key, string, maps;
- key = XVECTOR (items)->contents[4 * i];
- string = XVECTOR (items)->contents[4 * i + 1];
- maps = XVECTOR (items)->contents[4 * i + 2];
+ key = AREF (items, 4 * i);
+ string = AREF (items, 4 * i + 1);
+ maps = AREF (items, 4 * i + 2);
if (NILP (string))
break;
/* Compare the new menu items with the ones computed last time. */
for (i = 0; i < previous_menu_items_used; i++)
if (menu_items_used == i
- || (!EQ (previous_items[i], XVECTOR (menu_items)->contents[i])))
+ || (!EQ (previous_items[i], AREF (menu_items, i))))
break;
if (i == menu_items_used && i == previous_menu_items_used && i != 0)
{
}
/* The menu items are different, so store them in the frame. */
- f->menu_bar_vector = menu_items;
+ fset_menu_bar_vector (f, menu_items);
f->menu_bar_items_used = menu_items_used;
/* This undoes save_menu_items. */
for (i = 0; i < ASIZE (items); i += 4)
{
Lisp_Object string;
- string = XVECTOR (items)->contents[i + 1];
+ string = AREF (items, i + 1);
if (NILP (string))
break;
wv->name = SSDATA (string);
{
Lisp_Object string;
- string = XVECTOR (items)->contents[i + 1];
+ string = AREF (items, i + 1);
if (NILP (string))
break;
{
/* This function is called before the first chance to redisplay
the frame. It has to be, so the frame will have the right size. */
- FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
+ fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
set_frame_menubar (f, 1, 1);
}
Widget menubar_widget;
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
menubar_widget = f->output_data.x->menubar_widget;
#ifdef USE_MOTIF
/* Removing the menu bar magically changes the shell widget's x
and y position of (0, 0) which, when the menu bar is turned
- on again, leads to pull-down menuss appearing in strange
+ on again, leads to pull-down menus appearing in strange
positions near the upper-left corner of the display. This
happens only with some window managers like twm and ctwm,
but not with other like Motif's mwm or kwm, because the
GtkMenuPositionFunc pos_func = 0; /* Pop up at pointer. */
struct next_popup_x_y popup_x_y;
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ int use_pos_func = ! for_click;
+
+#ifdef HAVE_GTK3
+ /* Always use position function for Gtk3. Otherwise menus may become
+ too small to show anything. */
+ use_pos_func = 1;
+#endif
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
xg_crazy_callback_abort = 1;
menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
G_CALLBACK (menu_highlight_callback));
xg_crazy_callback_abort = 0;
- if (! for_click)
+ if (use_pos_func)
{
/* Not invoked by a click. pop up at x/y. */
pos_func = menu_position_func;
i = 0; /* gtk_menu_popup needs this to be 0 for a non-button popup. */
}
- else
+
+ if (for_click)
{
for (i = 0; i < 5; i++)
if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
Widget menu;
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
#ifdef USE_LUCID
apply_systemfont_to_menu (f, f->output_data.x->widget);
#endif /* not USE_GTK */
+static Lisp_Object
+cleanup_widget_value_tree (Lisp_Object arg)
+{
+ struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
+ widget_value *wv = p->pointer;
+
+ free_menubar_widget_value_tree (wv);
+
+ return Qnil;
+}
+
Lisp_Object
xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
Lisp_Object title, const char **error_name, Time timestamp)
int i;
widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
widget_value **submenu_stack
- = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
+ = alloca (menu_items_used * sizeof *submenu_stack);
Lisp_Object *subprefix_stack
- = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
+ = alloca (menu_items_used * sizeof *subprefix_stack);
int submenu_depth = 0;
int first_pane;
+ ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
*error_name = NULL;
i = 0;
while (i < menu_items_used)
{
- if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
+ if (EQ (AREF (menu_items, i), Qnil))
{
submenu_stack[submenu_depth++] = save_wv;
save_wv = prev_wv;
first_pane = 1;
i++;
}
- else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
+ else if (EQ (AREF (menu_items, i), Qlambda))
{
prev_wv = save_wv;
save_wv = submenu_stack[--submenu_depth];
first_pane = 0;
i++;
}
- else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
+ else if (EQ (AREF (menu_items, i), Qt)
&& submenu_depth != 0)
i += MENU_ITEMS_PANE_LENGTH;
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
- else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
+ else if (EQ (AREF (menu_items, i), Qquote))
i += 1;
- else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
+ else if (EQ (AREF (menu_items, i), Qt))
{
/* Create a new pane. */
Lisp_Object pane_name, prefix;
save_wv->next = wv;
else
first_wv->contents = wv;
- wv->name = pane_string;
+ wv->name = (char *) pane_string;
if (keymaps && !NILP (prefix))
wv->name++;
wv->value = 0;
/* 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->call_data = !NILP (def) ? aref_addr (menu_items, i) : 0;
wv->enabled = !NILP (enable);
if (NILP (type))
else if (EQ (type, QCradio))
wv->button_type = BUTTON_TYPE_RADIO;
else
- abort ();
+ emacs_abort ();
wv->selected = !NILP (selected);
/* No selection has been chosen yet. */
menu_item_selection = 0;
+ /* Make sure to free the widget_value objects we used to specify the
+ contents even with longjmp. */
+ record_unwind_protect (cleanup_widget_value_tree,
+ make_save_value (first_wv, 0));
+
/* Actually create and show the menu until popped down. */
create_and_show_popup_menu (f, first_wv, x, y, for_click, timestamp);
- /* Free the widget_value objects we used to specify the contents. */
- free_menubar_widget_value_tree (first_wv);
+ unbind_to (specpdl_count, Qnil);
/* Find the selected item, and its pane, to return
the proper value. */
i = 0;
while (i < menu_items_used)
{
- if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
+ if (EQ (AREF (menu_items, i), Qnil))
{
subprefix_stack[submenu_depth++] = prefix;
prefix = entry;
i++;
}
- else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
+ else if (EQ (AREF (menu_items, i), Qlambda))
{
prefix = subprefix_stack[--submenu_depth];
i++;
}
- else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
+ else if (EQ (AREF (menu_items, i), Qt))
{
prefix
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
+ = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
i += MENU_ITEMS_PANE_LENGTH;
}
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
- else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
+ else if (EQ (AREF (menu_items, i), Qquote))
i += 1;
else
{
entry
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
- if (menu_item_selection == &XVECTOR (menu_items)->contents[i])
+ = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
+ if (menu_item_selection == aref_addr (menu_items, i))
{
if (keymaps != 0)
{
GtkWidget *menu;
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
menu = xg_create_widget ("dialog", first_wv->name, f, first_wv,
G_CALLBACK (dialog_selection_callback),
LWLIB_ID dialog_id;
if (!FRAME_X_P (f))
- abort ();
+ emacs_abort ();
dialog_id = widget_id_tick++;
#ifdef USE_LUCID
/* 1 means we've seen the boundary between left-hand elts and right-hand. */
int boundary_seen = 0;
+ ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+
if (! FRAME_X_P (f))
- abort ();
+ emacs_abort ();
*error_name = NULL;
{
Lisp_Object pane_name, prefix;
const char *pane_string;
- pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME];
- prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX];
+ pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME);
+ prefix = AREF (menu_items, MENU_ITEMS_PANE_PREFIX);
pane_string = (NILP (pane_name)
? "" : SSDATA (pane_name));
prev_wv = xmalloc_widget_value ();
- prev_wv->value = pane_string;
+ prev_wv->value = (char *) pane_string;
if (keymaps && !NILP (prefix))
prev_wv->name++;
prev_wv->enabled = 1;
/* Create a new item within current pane. */
Lisp_Object item_name, enable, descrip;
- item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
- enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
+ item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
+ enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
descrip
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
+ = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
if (NILP (item_name))
{
if (!NILP (descrip))
wv->key = SSDATA (descrip);
wv->value = SSDATA (item_name);
- wv->call_data = (void *) &XVECTOR (menu_items)->contents[i];
+ wv->call_data = aref_addr (menu_items, i);
wv->enabled = !NILP (enable);
wv->help = Qnil;
prev_wv = wv;
/* No selection has been chosen yet. */
menu_item_selection = 0;
+ /* Make sure to free the widget_value objects we used to specify the
+ contents even with longjmp. */
+ record_unwind_protect (cleanup_widget_value_tree,
+ make_save_value (first_wv, 0));
+
/* Actually create and show the dialog. */
create_and_show_dialog (f, first_wv);
- /* Free the widget_value objects we used to specify the contents. */
- free_menubar_widget_value_tree (first_wv);
+ unbind_to (specpdl_count, Qnil);
/* Find the selected item, and its pane, to return
the proper value. */
{
Lisp_Object entry;
- if (EQ (XVECTOR (menu_items)->contents[i], Qt))
+ if (EQ (AREF (menu_items, i), Qt))
{
prefix
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
+ = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
i += MENU_ITEMS_PANE_LENGTH;
}
- else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
+ else if (EQ (AREF (menu_items, i), Qquote))
{
/* This is the boundary between left-side elts and
right-side elts. */
else
{
entry
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
- if (menu_item_selection == &XVECTOR (menu_items)->contents[i])
+ = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
+ if (menu_item_selection == aref_addr (menu_items, i))
{
if (keymaps != 0)
{
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
if (! FRAME_X_P (f) && ! FRAME_MSDOS_P (f))
- abort ();
+ emacs_abort ();
*error_name = 0;
if (menu_items_n_panes == 0)
lpane = XM_FAILURE;
while (i < menu_items_used)
{
- if (EQ (XVECTOR (menu_items)->contents[i], Qt))
+ if (EQ (AREF (menu_items, i), Qt))
{
/* Create a new pane. */
Lisp_Object pane_name, prefix;
maxlines = max (maxlines, lines);
lines = 0;
- 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);
pane_string = (NILP (pane_name)
? "" : SSDATA (pane_name));
if (keymaps && !NILP (prefix))
while (j < menu_items_used)
{
Lisp_Object item;
- item = XVECTOR (menu_items)->contents[j];
+ item = AREF (menu_items, j);
if (EQ (item, Qt))
break;
if (NILP (item))
}
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
- else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
+ else if (EQ (AREF (menu_items, i), Qquote))
i += 1;
else
{
char *item_data;
char const *help_string;
- item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
- enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
+ item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
+ enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
descrip
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
- help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
+ = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
+ help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
help_string = STRINGP (help) ? SSDATA (help) : NULL;
if (!NILP (descrip))
{
/* if alloca is fast, use that to make the space,
to reduce gc needs. */
- item_data = (char *) alloca (maxwidth + SBYTES (descrip) + 1);
+ item_data = alloca (maxwidth + SBYTES (descrip) + 1);
memcpy (item_data, SSDATA (item_name), SBYTES (item_name));
for (j = SCHARS (item_name); j < maxwidth; j++)
item_data[j] = ' ';
i = 0;
while (i < menu_items_used)
{
- if (EQ (XVECTOR (menu_items)->contents[i], Qt))
+ if (EQ (AREF (menu_items, i), Qt))
{
if (pane == 0)
pane_prefix
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
+ = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
pane--;
i += MENU_ITEMS_PANE_LENGTH;
}
if (selidx == 0)
{
entry
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
+ = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
if (keymaps != 0)
{
entry = Fcons (entry, Qnil);
/* Detect if a dialog or menu has been posted. MSDOS has its own
implementation on msdos.c. */
-int
+int ATTRIBUTE_CONST
popup_activated (void)
{
return popup_activated_flag;