/* X Communication module for terminals which understand the X protocol.
-Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2014 Free Software
+Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2015 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
#include "menu.h"
-#ifndef TRUE
-#define TRUE 1
-#endif /* no TRUE */
-
-static Lisp_Object Qdebug_on_next_call;
-
+\f
/* Flag which when set indicates a dialog or menu has been posted by
Xt on behalf of one of the widget sets. */
static int popup_activated_flag;
/* Set menu_items_inuse so no other popup menu or dialog is created. */
void
-x_menu_set_in_use (int in_use)
+x_menu_set_in_use (bool in_use)
{
menu_items_inuse = in_use ? Qt : Qnil;
popup_activated_flag = in_use;
with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */
static void
-popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo, LWLIB_ID id, int do_timers)
+popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo,
+ LWLIB_ID id, bool do_timers)
{
XEvent event;
block_input ();
if (FRAME_EXTERNAL_MENU_BAR (f))
- set_frame_menubar (f, 0, 1);
+ set_frame_menubar (f, false, true);
menubar = FRAME_X_OUTPUT (f)->menubar_widget;
if (menubar)
{
Window child;
- bool error_p = 0;
+ bool error_p = false;
x_catch_errors (FRAME_X_DISPLAY (f));
memset (&ev, 0, sizeof ev);
f = decode_window_system_frame (frame);
if (FRAME_EXTERNAL_MENU_BAR (f))
- set_frame_menubar (f, 0, 1);
+ set_frame_menubar (f, false, true);
menubar = FRAME_X_OUTPUT (f)->menubar_widget;
if (menubar)
Used for popup menus and dialogs. */
static void
-popup_widget_loop (int do_timers, GtkWidget *widget)
+popup_widget_loop (bool do_timers, GtkWidget *widget)
{
++popup_activated_flag;
return;
#endif
- set_frame_menubar (f, 0, 1);
+ set_frame_menubar (f, false, true);
block_input ();
popup_activated_flag = 1;
#ifdef USE_GTK
kbd_buffer_store_help_event (frame, help);
}
else
- {
-#if 0 /* This code doesn't do anything useful. ++kfs */
- /* WIDGET is the popup menu. It's parent is the frame's
- widget. See which frame that is. */
- xt_or_gtk_widget frame_widget = XtParent (widget);
- Lisp_Object tail;
-
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
- {
- frame = XCAR (tail);
- if (FRAMEP (frame)
- && (f = XFRAME (frame),
- FRAME_X_P (f) && f->output_data.x->widget == frame_widget))
- break;
- }
-#endif
- show_help_echo (help, Qnil, Qnil, Qnil);
- }
+ show_help_echo (help, Qnil, Qnil, Qnil);
}
/* Callback called when menu items are highlighted/unhighlighted
selected in a radio group. If this variable is set to a non-zero
value, we are creating menus and don't want callbacks right now.
*/
-static int xg_crazy_callback_abort;
+static bool xg_crazy_callback_abort;
/* This callback is called from the menu bar pulldown menu
when the user makes a selection.
xg_update_frame_menubar (f);
#else
struct x_output *x;
-/** int columns, rows; **/
eassert (FRAME_X_P (f));
return;
block_input ();
- /* Save the size of the frame because the pane widget doesn't accept
- to resize itself. So force it. */
-/** columns = FRAME_COLS (f); **/
-/** rows = FRAME_LINES (f); **/
/* Do the voodoo which means "I'm changing lots of things, don't try
to refigure sizes until I'm done." */
XtManageChild (x->edit_widget);
lw_refigure_widget (x->column_widget, True);
- /* Force the pane widget to resize itself with the right values. */
-/** EmacsFrameSetCharSize (x->edit_widget, columns, rows); **/
- adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 2, 0);
+ /* Force the pane widget to resize itself. */
+ int new_height = -1;
+#ifdef USE_LUCID
+ /* For reasons I don't know Lucid wants to add one pixel to the frame
+ height when adding the menu bar. Compensate that here. */
+ new_height = FRAME_TEXT_HEIGHT (f) - 1;
+#endif /* USE_LUCID */
+ adjust_frame_size (f, -1, new_height, 2, false, Qmenu_bar_lines);
unblock_input ();
-#endif
+#endif /* USE_GTK */
}
#ifdef USE_LUCID
#endif
if (! menubar_widget)
- deep_p = 1;
+ deep_p = true;
/* Make the first call for any given frame always go deep. */
else if (!f->output_data.x->saved_menu_event && !deep_p)
{
- deep_p = 1;
+ deep_p = true;
f->output_data.x->saved_menu_event = xmalloc (sizeof (XEvent));
f->output_data.x->saved_menu_event->type = 0;
}
-#ifdef USE_GTK
- /* If we have detached menus, we must update deep so detached menus
- also gets updated. */
- deep_p = deep_p || xg_have_tear_offs (f);
-#endif
-
if (deep_p)
{
/* Make a widget-value tree representing the entire menu trees. */
else
first_wv->contents = wv;
/* Don't set wv->name here; GC during the loop might relocate it. */
- wv->enabled = 1;
+ wv->enabled = true;
wv->button_type = BUTTON_TYPE_NONE;
prev_wv = wv;
}
block_input ();
#ifdef USE_GTK
- xg_crazy_callback_abort = 1;
+ xg_crazy_callback_abort = true;
if (menubar_widget)
{
/* The fourth arg is DEEP_P, which says to consider the entire
menubar_widget = lw_create_widget ("menubar", "menubar", id,
first_wv,
f->output_data.x->column_widget,
- 0,
+ false,
popup_activate_callback,
menubar_selection_callback,
popup_deactivate_callback,
+ f->output_data.x->menubar_widget->core.border_width)
: 0);
-#if 1 /* Experimentally, we now get the right results
+#ifdef USE_LUCID
+ /* Experimentally, we now get the right results
for -geometry -0-0 without this. 24 Aug 96, rms.
Maybe so, but the menu bar size is missing the pixels so the
WM size hints are off by these pixels. Jan D, oct 2009. */
-#ifdef USE_LUCID
if (FRAME_EXTERNAL_MENU_BAR (f))
{
Dimension ibw = 0;
menubar_size += ibw;
}
#endif /* USE_LUCID */
-#endif /* 1 */
FRAME_MENUBAR_HEIGHT (f) = menubar_size;
}
update_frame_menubar (f);
#ifdef USE_GTK
- xg_crazy_callback_abort = 0;
+ xg_crazy_callback_abort = false;
#endif
unblock_input ();
/* This function is called before the first chance to redisplay
the frame. It has to be, so the frame will have the right size. */
fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
- set_frame_menubar (f, 1, 1);
+ set_frame_menubar (f, true, true);
}
free_frame_menubar (struct frame *f)
{
Widget menubar_widget;
+#ifdef USE_MOTIF
+ /* Motif automatically shrinks the frame in lw_destroy_all_widgets.
+ If we want to preserve the old height, calculate it now so we can
+ restore it below. */
+ int old_height = FRAME_TEXT_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f);
+#endif
eassert (FRAME_X_P (f));
if (f->output_data.x->widget)
{
+ int new_height = -1;
#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 (frame_inhibit_resize (f, false, Qmenu_bar_lines))
+ new_height = old_height;
+#endif /* USE_MOTIF */
+ adjust_frame_size (f, -1, new_height, 2, false, Qmenu_bar_lines);
+ }
+ else
+ {
+#ifdef USE_MOTIF
+ if (frame_inhibit_resize (f, false, Qmenu_bar_lines))
+ adjust_frame_size (f, -1, old_height, 1, false, Qmenu_bar_lines);
#endif
- adjust_frame_size (f, FRAME_TEXT_WIDTH (f),
- FRAME_TEXT_HEIGHT (f), 2, 0);
- /*
- if (frame_inhibit_resize (f, 0))
- change_frame_size (f, 0, 0, 0, 0, 0, 1);
- else
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f),
- FRAME_TEXT_HEIGHT (f), 1);
- */
}
+
unblock_input ();
}
}
#ifdef HAVE_GTK3
/* Always use position function for Gtk3. Otherwise menus may become
too small to show anything. */
- use_pos_func = 1;
+ use_pos_func = true;
#endif
eassert (FRAME_X_P (f));
- xg_crazy_callback_abort = 1;
+ xg_crazy_callback_abort = true;
menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
G_CALLBACK (popup_selection_callback),
G_CALLBACK (popup_deactivate_callback),
G_CALLBACK (menu_highlight_callback));
- xg_crazy_callback_abort = 0;
+ xg_crazy_callback_abort = false;
if (use_pos_func)
{
+ Window dummy_window;
+
/* Not invoked by a click. pop up at x/y. */
pos_func = menu_position_func;
/* Adjust coordinates to be root-window-relative. */
- x += f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
- y += f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
+ block_input ();
+ XTranslateCoordinates (FRAME_X_DISPLAY (f),
+
+ /* From-window, to-window. */
+ FRAME_X_WINDOW (f),
+ FRAME_DISPLAY_INFO (f)->root_window,
+
+ /* From-position, to-position. */
+ x, y, &x, &y,
+ /* Child of win. */
+ &dummy_window);
+ unblock_input ();
popup_x_y.x = x;
popup_x_y.y = y;
popup_x_y.f = f;
two. show_help_echo uses this to detect popup menus. */
popup_activated_flag = 1;
/* Process events that apply to the menu. */
- popup_widget_loop (1, menu);
+ popup_widget_loop (true, menu);
}
unbind_to (specpdl_count, Qnil);
menu_id = widget_id_tick++;
menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
- f->output_data.x->widget, 1, 0,
+ f->output_data.x->widget, true, 0,
popup_selection_callback,
popup_deactivate_callback,
menu_highlight_callback);
event->type = ButtonPress;
event->serial = 0;
- event->send_event = 0;
+ event->send_event = false;
event->display = FRAME_X_DISPLAY (f);
event->time = CurrentTime;
event->root = FRAME_DISPLAY_INFO (f)->root_window;
record_unwind_protect_int (pop_down_menu, (int) menu_id);
/* Process events that apply to the menu. */
- popup_get_selection (0, FRAME_DISPLAY_INFO (f), menu_id, 1);
+ popup_get_selection (0, FRAME_DISPLAY_INFO (f), menu_id, true);
unbind_to (specpdl_count, Qnil);
}
= alloca (menu_items_used * sizeof *subprefix_stack);
int submenu_depth = 0;
- int first_pane;
-
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
eassert (FRAME_X_P (f));
wv = make_widget_value ("menu", NULL, true, Qnil);
wv->button_type = BUTTON_TYPE_NONE;
first_wv = wv;
- first_pane = 1;
+ bool first_pane = true;
/* Loop over all panes and items, filling in the tree. */
i = 0;
submenu_stack[submenu_depth++] = save_wv;
save_wv = prev_wv;
prev_wv = 0;
- first_pane = 1;
+ first_pane = true;
i++;
}
else if (EQ (AREF (menu_items, i), Qlambda))
{
prev_wv = save_wv;
save_wv = submenu_stack[--submenu_depth];
- first_pane = 0;
+ first_pane = false;
i++;
}
else if (EQ (AREF (menu_items, i), Qt)
save_wv = wv;
prev_wv = 0;
}
- first_pane = 0;
+ first_pane = false;
i += MENU_ITEMS_PANE_LENGTH;
}
else
gtk_widget_show_all (menu);
/* Process events that apply to the menu. */
- popup_widget_loop (1, menu);
+ popup_widget_loop (true, menu);
unbind_to (specpdl_count, Qnil);
}
apply_systemfont_to_dialog (f->output_data.x->widget);
#endif
lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
- f->output_data.x->widget, 1, 0,
+ f->output_data.x->widget, true, 0,
dialog_selection_callback, 0, 0);
lw_modify_all_widgets (dialog_id, first_wv->contents, True);
/* Display the dialog box. */
record_unwind_protect_int (pop_down_menu, (int) dialog_id);
- popup_get_selection (0, FRAME_DISPLAY_INFO (f), dialog_id, 1);
+ popup_get_selection (0, FRAME_DISPLAY_INFO (f), dialog_id, true);
unbind_to (count, Qnil);
}
/* Number of elements seen so far, before boundary. */
int left_count = 0;
- /* 1 means we've seen the boundary between left-hand elts and right-hand. */
- int boundary_seen = 0;
+ /* Whether we've seen the boundary between left-hand elts and right-hand. */
+ bool boundary_seen = false;
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
{
/* This is the boundary between left-side elts
and right-side elts. Stop incrementing right_count. */
- boundary_seen = 1;
+ boundary_seen = true;
i++;
continue;
}
Window root;
XMenu *menu;
int pane, selidx, lpane, status;
- Lisp_Object entry, pane_prefix;
+ Lisp_Object entry = Qnil;
+ Lisp_Object pane_prefix;
char *datap;
int ulx, uly, width, height;
int dispwidth, dispheight;
return Qnil;
}
+ USE_SAFE_ALLOCA;
block_input ();
/* Figure out which root window F is on. */
if (menu == NULL)
{
*error_name = "Can't create menu";
- unblock_input ();
- return Qnil;
+ goto return_entry;
}
/* Don't GC while we prepare and show the menu,
if ((menuflags & MENU_KEYMAPS) && !NILP (prefix))
pane_string++;
- lpane = XMenuAddPane (FRAME_X_DISPLAY (f), menu, pane_string, TRUE);
+ lpane = XMenuAddPane (FRAME_X_DISPLAY (f), menu, pane_string, true);
if (lpane == XM_FAILURE)
{
XMenuDestroy (FRAME_X_DISPLAY (f), menu);
*error_name = "Can't create pane";
- unblock_input ();
- return Qnil;
+ goto return_entry;
}
i += MENU_ITEMS_PANE_LENGTH;
if (!NILP (descrip))
{
- /* if alloca is fast, use that to make the space,
- to reduce gc needs. */
- item_data = alloca (maxwidth + SBYTES (descrip) + 1);
+ item_data = SAFE_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] = ' ';
{
XMenuDestroy (FRAME_X_DISPLAY (f), menu);
*error_name = "Can't add selection to menu";
- unblock_input ();
- return Qnil;
+ goto return_entry;
}
i += MENU_ITEMS_ITEM_LENGTH;
lines++;
y += 1.5*height/(maxlines+2);
}
- XMenuSetAEQ (menu, TRUE);
- XMenuSetFreeze (menu, TRUE);
+ XMenuSetAEQ (menu, true);
+ XMenuSetFreeze (menu, true);
pane = selidx = 0;
#ifndef MSDOS
status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx,
x, y, ButtonReleaseMask, &datap,
menu_help_callback);
- entry = pane_prefix = Qnil;
+ pane_prefix = Qnil;
switch (status)
{
break;
}
+ return_entry:
unblock_input ();
- unbind_to (specpdl_count, Qnil);
-
- return entry;
+ SAFE_FREE ();
+ return unbind_to (specpdl_count, entry);
}
#endif /* not USE_X_TOOLKIT */
/* Detect if a dialog or menu has been posted. MSDOS has its own
implementation on msdos.c. */
-int ATTRIBUTE_CONST
+int
popup_activated (void)
{
return popup_activated_flag;