/* X Communication module for terminals which understand the X protocol.
- Copyright (C) 1986, 88, 93, 94, 96, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1986, 88, 93, 94, 96, 99, 2000, 2001
+ Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <stdio.h>
#include "lisp.h"
#include "termhooks.h"
+#include "keyboard.h"
#include "frame.h"
#include "window.h"
-#include "keyboard.h"
#include "blockinput.h"
#include "buffer.h"
#ifdef HAVE_X_WINDOWS
#undef HAVE_MULTILINGUAL_MENU
#ifdef USE_X_TOOLKIT
+#include "widget.h"
#include <X11/Xlib.h>
#include <X11/IntrinsicP.h>
#include <X11/CoreP.h>
#endif /* not USE_X_TOOLKIT */
#endif /* HAVE_X_WINDOWS */
-#ifdef USE_MOTIF
-#include <Xm/Xm.h> /* for LESSTIF_VERSION */
-#endif
-
#define min(x,y) (((x) < (y)) ? (x) : (y))
#define max(x,y) (((x) > (y)) ? (x) : (y))
static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object));
-static Lisp_Object xmenu_show ();
-static void keymap_panes ();
-static void single_keymap_panes ();
-static void single_menu_item ();
-static void list_of_panes ();
-static void list_of_items ();
+static int update_frame_menubar P_ ((struct frame *));
+static Lisp_Object xmenu_show P_ ((struct frame *, int, int, int, int,
+ Lisp_Object, char **));
+static void keymap_panes P_ ((Lisp_Object *, int, int));
+static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
+ int, int));
+static void single_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object *,
+ int, int, int *));
+static void list_of_panes P_ ((Lisp_Object));
+static void list_of_items P_ ((Lisp_Object));
\f
/* This holds a Lisp vector that holds the results of decoding
the keymaps or alist-of-alists that specify a menu.
Lisp_Object position, menu;
{
Lisp_Object keymap, tem;
- int xpos, ypos;
+ int xpos = 0, ypos = 0;
Lisp_Object title;
char *error_name;
Lisp_Object selection;
- FRAME_PTR f;
+ struct frame *f = NULL;
Lisp_Object x, y, window;
int keymaps = 0;
int for_click = 0;
/* Decode the first argument: find the window and the coordinates. */
if (EQ (position, Qt)
- || (CONSP (position) && EQ (XCAR (position), Qmenu_bar)))
+ || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
+ || EQ (XCAR (position), Qtool_bar))))
{
/* Use the mouse's current position. */
FRAME_PTR new_f = SELECTED_FRAME ();
/* Decode the menu items from what was specified. */
- keymap = Fkeymapp (menu);
- tem = Qnil;
- if (CONSP (menu))
- tem = Fkeymapp (Fcar (menu));
- if (!NILP (keymap))
+ keymap = get_keymap (menu, 0, 0);
+ if (CONSP (keymap))
{
/* We were given a keymap. Extract menu info from the keymap. */
Lisp_Object prompt;
- keymap = get_keymap (menu);
/* Extract the detailed info to make one pane. */
keymap_panes (&menu, 1, NILP (position));
keymaps = 1;
}
- else if (!NILP (tem))
+ else if (CONSP (menu) && KEYMAPP (XCAR (menu)))
{
/* We were given a list of keymaps. */
int nmaps = XFASTINT (Flength (menu));
{
Lisp_Object prompt;
- maps[i++] = keymap = get_keymap (Fcar (tem));
+ maps[i++] = keymap = get_keymap (Fcar (tem), 1, 0);
prompt = map_prompt (keymap);
if (NILP (title) && !NILP (prompt))
(position, contents)
Lisp_Object position, contents;
{
- FRAME_PTR f;
+ struct frame * f = NULL;
Lisp_Object window;
check_x ();
/* Decode the first argument: find the window or frame to use. */
if (EQ (position, Qt)
- || (CONSP (position) && EQ (XCAR (position), Qmenu_bar)))
+ || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
+ || EQ (XCAR (position), Qtool_bar))))
{
#if 0 /* Using the frame the mouse is on may not be right. */
/* Use the mouse's current position. */
&& (event.xany.display != dpyinfo->display
|| x_non_menubar_window_to_frame (dpyinfo, event.xany.window)))
{
- queue_tmp = (struct event_queue *) malloc (sizeof (struct event_queue));
-
- if (queue_tmp != NULL)
- {
- queue_tmp->event = event;
- queue_tmp->next = queue;
- queue = queue_tmp;
- }
+ queue_tmp = (struct event_queue *) xmalloc (sizeof *queue_tmp);
+ queue_tmp->event = event;
+ queue_tmp->next = queue;
+ queue = queue_tmp;
}
else
XtDispatchEvent (&event);
LWLIB_ID id;
XtPointer client_data;
{
-#ifdef USE_MOTIF
- ++popup_activated_flag;
-#else
popup_activated_flag = 1;
-#endif
}
/* This callback is invoked when a dialog or menu is finished being
LWLIB_ID id;
XtPointer client_data;
{
-#ifdef USE_MOTIF
- --popup_activated_flag;
-#else
popup_activated_flag = 0;
-#endif
}
/* Lwlib callback called when menu items are highlighted/unhighlighted
if (!f)
return;
+ entry = Qnil;
subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * sizeof (Lisp_Object));
vector = f->menu_bar_vector;
prefix = Qnil;
for (i = 0; i < len; i++)
{
if (SYMBOLP (mapvec[i])
- || (CONSP (mapvec[i])
- && NILP (Fkeymapp (mapvec[i]))))
+ || (CONSP (mapvec[i]) && !KEYMAPP (mapvec[i])))
{
/* Here we have a command at top level in the menu bar
as opposed to a submenu. */
/* 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 = string_make_unibyte (pane_name);
+ AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
+ }
#endif
pane_string = (NILP (pane_name)
? "" : (char *) XSTRING (pane_name)->data);
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 = string_make_unibyte (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 = string_make_unibyte (descrip);
+ AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
+ }
+#endif /* not HAVE_MULTILINGUAL_MENU */
wv = xmalloc_widget_value ();
if (prev_wv)
return first_wv;
}
-\f
-extern void EmacsFrameSetCharSize ();
-/* Recompute all the widgets of frame F, when the menu bar
- has been changed. */
-static void
+\f
+/* Recompute all the widgets of frame F, when the menu bar has been
+ changed. Value is non-zero if widgets were updated. */
+
+static int
update_frame_menubar (f)
FRAME_PTR f;
{
struct x_output *x = f->output_data.x;
int columns, rows;
- int menubar_changed;
- /* We assume the menubar contents has changed if the global flag is set,
- or if the current buffer has changed, or if the menubar has never
- been updated before.
- */
- menubar_changed = (x->menubar_widget
- && !XtIsManaged (x->menubar_widget));
-
- if (! (menubar_changed))
- return;
+ if (!x->menubar_widget || XtIsManaged (x->menubar_widget))
+ return 0;
BLOCK_INPUT;
- /* Save the size of the frame because the pane widget doesn't accept to
- resize itself. So force it. */
+ /* Save the size of the frame because the pane widget doesn't accept
+ to resize itself. So force it. */
columns = f->width;
rows = f->height;
- /* Do the voodoo which means "I'm changing lots of things, don't try to
- refigure sizes until I'm done." */
+ /* Do the voodoo which means "I'm changing lots of things, don't try
+ to refigure sizes until I'm done." */
lw_refigure_widget (x->column_widget, False);
- /* the order in which children are managed is the top to
- bottom order in which they are displayed in the paned window.
- First, remove the text-area widget.
- */
+ /* The order in which children are managed is the top to bottom
+ order in which they are displayed in the paned window. First,
+ remove the text-area widget. */
XtUnmanageChild (x->edit_widget);
- /* remove the menubar that is there now, and put up the menubar that
- should be there.
- */
- if (menubar_changed)
- {
- XtManageChild (x->menubar_widget);
- XtMapWidget (x->menubar_widget);
- XtVaSetValues (x->menubar_widget, XtNmappedWhenManaged, 1, NULL);
- }
+ /* Remove the menubar that is there now, and put up the menubar that
+ should be there. */
+ XtManageChild (x->menubar_widget);
+ XtMapWidget (x->menubar_widget);
+ XtVaSetValues (x->menubar_widget, XtNmappedWhenManaged, 1, NULL);
/* Re-manage the text-area widget, and then thrash the sizes. */
XtManageChild (x->edit_widget);
- x_set_menu_resources_from_menu_face (f, x->menubar_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);
UNBLOCK_INPUT;
+ return 1;
}
/* Set the contents of the menubar widgets of frame F.
set_buffer_internal_1 (XBUFFER (buffer));
/* Run the Lucid hook. */
- call1 (Vrun_hooks, Qactivate_menubar_hook);
+ safe_run_hooks (Qactivate_menubar_hook);
+
/* If it has changed current-menubar from previous value,
really recompute the menubar from the value. */
if (! NILP (Vlucid_menu_bar_dirty_flag))
set_frame_menubar (f, 1, 1);
}
+
/* Get rid of the menu bar of frame F, and free its storage.
This is used when deleting a frame, and when turning off the menu bar. */
if (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
+ 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
+ latter generate ConfigureNotify events when the menu bar
+ is switched off, which fixes the shell position. */
+ Position x0, y0, x1, y1;
+#endif
+
BLOCK_INPUT;
+
+#ifdef USE_MOTIF
+ 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
+ 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;
}
}
/* 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 = string_make_unibyte (pane_name);
+ AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
+ }
#endif
pane_string = (NILP (pane_name)
? "" : (char *) XSTRING (pane_name)->data);
{
/* 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 = string_make_unibyte (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 = string_make_unibyte (descrip);
+ AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
+ }
+#endif /* not HAVE_MULTILINGUAL_MENU */
wv = xmalloc_widget_value ();
if (prev_wv)
if (STRING_MULTIBYTE (title))
title = string_make_unibyte (title);
#endif
+
wv_title->name = (char *) XSTRING (title)->data;
wv_title->enabled = True;
wv_title->button_type = BUTTON_TYPE_NONE;
/* Display the menu. */
lw_popup_menu (menu, (XEvent *) &dummy);
- x_set_menu_resources_from_menu_face (f, menu);
popup_activated_flag = 1;
/* Process events that apply to the menu. */
popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id);
-#ifdef LESSTIF_VERSION
- /* Nov 1998: For an unknown reason a button grab remains active
- after the popup menu has gone. */
- XUngrabButton (XtDisplay (f->output_data.x->widget),
- AnyButton, AnyModifier,
- XtWindow (f->output_data.x->widget));
- XUngrabButton (XtDisplay (f->output_data.x->edit_widget),
- AnyButton, AnyModifier,
- XtWindow (f->output_data.x->edit_widget));
-#endif /* LESSTIF_VERSION */
-
/* fp turned off the following statement and wrote a comment
that it is unnecessary--that the menu has already disappeared.
Nowadays the menu disappears ok, all right, but
{
Lisp_Object prefix, entry;
- prefix = Qnil;
+ prefix = entry = Qnil;
i = 0;
while (i < menu_items_used)
{
= XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
i += MENU_ITEMS_PANE_LENGTH;
}
+ else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
+ {
+ /* This is the boundary between left-side elts and
+ right-side elts. */
+ ++i;
+ }
else
{
entry
/* 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);