instead of the actual command. */
Lisp_Object this_command;
+/* The value of point when the last command was executed. */
+int last_point_position;
+
#ifdef MULTI_FRAME
/* The frame in which the last input event occurred, or Qmacro if the
last event came from a macro. We use this to determine when to
/* Where to append more text to echobuf if we want to. */
static char *echoptr;
+/* Nonzero means don't try to suspend even if the operating system seems
+ to support it. */
+static int cannot_suspend;
+
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
if (this_command_key_count >= size)
{
- Lisp_Object new_keys = Fmake_vector (make_number (size * 2), Qnil);
+ Lisp_Object new_keys;
+ new_keys = Fmake_vector (make_number (size * 2), Qnil);
bcopy (XVECTOR (this_command_keys)->contents,
XVECTOR (new_keys)->contents,
size * sizeof (Lisp_Object));
waiting_for_input = 0;
cancel_echoing ();
- /* Don't clear out last_command at the beginning of a macro. */
- if (XTYPE (Vexecuting_macro) != Lisp_String)
- last_command = Qt;
-
nonundocount = 0;
no_redisplay = 0;
this_command_key_count = 0;
/* Make sure this hook runs after commands that get errors and
throw to top level. */
- if (!NILP (Vpost_command_hook))
+ if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
{
/* If we get an error during the post-command-hook,
cause post-command-hook to be nil. */
Vpost_command_hook = Vcommand_hook_internal;
}
+ /* Do this after running Vpost_command_hook, for consistency. */
+ last_command = this_command;
+
while (1)
{
/* Install chars successfully executed in kbd macro. */
&& !NILP (Ffboundp (Qrecompute_lucid_menubar)))
call0 (Qrecompute_lucid_menubar);
-#if 0 /* This is done in xdisp.c now. */
-#ifdef MULTI_FRAME
- for (tem = Vframe_list; CONSP (tem); tem = XCONS (tem)->cdr)
- {
- struct frame *f = XFRAME (XCONS (tem)->car);
- struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
-
- /* If the user has switched buffers or windows, we need to
- recompute to reflect the new bindings. But we'll
- recompute when update_mode_lines is set too; that means
- that people can use force-mode-line-update to request
- that the menu bar be recomputed. The adverse effect on
- the rest of the redisplay algorithm is about the same as
- windows_or_buffers_changed anyway. */
- if (windows_or_buffers_changed
- || update_mode_lines
- || (XFASTINT (w->last_modified) < MODIFF
- && (XFASTINT (w->last_modified)
- <= XBUFFER (w->buffer)->save_modified)))
- {
- struct buffer *prev = current_buffer;
- current_buffer = XBUFFER (w->buffer);
- FRAME_MENU_BAR_ITEMS (f) = menu_bar_items ();
- current_buffer = prev;
- }
- }
-#endif /* MULTI_FRAME */
-#endif /* 0 */
-
/* Read next key sequence; i gets its length. */
i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])), Qnil);
prev_buffer = current_buffer;
prev_modiff = MODIFF;
+ last_point_position = PT;
/* Execute the command. */
this_command = cmd;
- if (!NILP (Vpre_command_hook))
+ if (!NILP (Vpre_command_hook) && !NILP (Vrun_hooks))
{
/* If we get an error during the pre-command-hook,
cause pre-command-hook to be nil. */
if (dp)
{
- Lisp_Object obj = DISP_CHAR_VECTOR (dp, lose);
+ Lisp_Object obj;
+ obj = DISP_CHAR_VECTOR (dp, lose);
if (XTYPE (obj) == Lisp_Vector
&& XVECTOR (obj)->size == 1
&& (XTYPE (obj = XVECTOR (obj)->contents[0])
}
directly_done: ;
- if (!NILP (Vpost_command_hook))
- call1 (Vrun_hooks, Qpost_command_hook);
+ if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
+ {
+ /* If we get an error during the post-command-hook,
+ cause post-command-hook to be nil. */
+ Vcommand_hook_internal = Vpost_command_hook;
+ Vpost_command_hook = Qnil;
+
+ call1 (Vrun_hooks, Qcommand_hook_internal);
+
+ Vpost_command_hook = Vcommand_hook_internal;
+ }
/* If there is a prefix argument,
1) We don't want last_command to be ``universal-argument''
this_command_key_count = 0;
}
- if (!NILP (current_buffer->mark_active))
+ if (!NILP (current_buffer->mark_active) && !NILP (Vrun_hooks))
{
if (!NILP (Vdeactivate_mark) && !NILP (Vtransient_mark_mode))
{
putc (XINT (c), dribble);
else
{
- Lisp_Object dribblee = c;
+ Lisp_Object dribblee;
/* If it's a structured event, take the event header. */
- dribblee = EVENT_HEAD (dribblee);
+ dribblee = EVENT_HEAD (c);
if (XTYPE (dribblee) == Lisp_Symbol)
{
internal_with_output_to_temp_buffer ("*Help*", print_help, tem0);
cancel_echoing ();
- c = read_char (0, 0, 0, Qnil, 0);
+ do
+ c = read_char (0, 0, 0, Qnil, 0);
+ while (XTYPE (c) == Lisp_Buffer);
/* Remove the help from the frame */
unbind_to (count, Qnil);
prepare_menu_bars ();
if (EQ (c, make_number (040)))
{
cancel_echoing ();
- c = read_char (0, 0, 0, Qnil, 0);
+ do
+ c = read_char (0, 0, 0, Qnil, 0);
+ while (XTYPE (c) == Lisp_Buffer);
}
}
get returned to Emacs as an event, the next event read
will set Vlast_event_frame again, so this is safe to do. */
{
- Lisp_Object focus
- = FRAME_FOCUS_FRAME (XFRAME (event->frame_or_window));
+ Lisp_Object focus;
+ focus = FRAME_FOCUS_FRAME (XFRAME (event->frame_or_window));
if (NILP (focus))
internal_last_event_frame = event->frame_or_window;
else
wait_reading_process_input (0, 0, minus_one, 1);
if (!interrupt_input && EVENT_QUEUES_EMPTY)
- {
- read_avail_input (0);
- }
+ /* Pass 1 for EXPECT since we just waited to have input. */
+ read_avail_input (1);
}
#endif /* not VMS */
}
else
{
#ifdef MULTI_FRAME
- Lisp_Object frame = event->frame_or_window;
+ Lisp_Object frame;
Lisp_Object focus;
+ frame = event->frame_or_window;
if (XTYPE (frame) == Lisp_Window)
frame = WINDOW_FRAME (XWINDOW (frame));
frames. */
if (f)
{
- Lisp_Object frame = FRAME_FOCUS_FRAME (f);
+ Lisp_Object frame;
+ frame = FRAME_FOCUS_FRAME (f);
if (NILP (frame))
XSET (frame, Lisp_Frame, f);
\f
/* Caches for modify_event_symbol. */
static Lisp_Object accent_key_syms;
-static Lisp_Object vendor_key_syms;
+static Lisp_Object system_key_syms;
static Lisp_Object func_key_syms;
static Lisp_Object mouse_syms;
-Lisp_Object Vvendor_key_alist;
+Lisp_Object Vsystem_key_alist;
/* This is a list of keysym codes for special "accent" characters.
It parallels lispy_accent_keys. */
(sizeof (lispy_accent_keys)
/ sizeof (lispy_accent_keys[0])));
- /* Handle vendor-specific keysyms. */
+ /* Handle system-specific keysyms. */
if (event->code & (1 << 28))
{
/* We need to use an alist rather than a vector as the cache
since we can't make a vector long enuf. */
- if (NILP (vendor_key_syms))
- vendor_key_syms = Fcons (Qnil, Qnil);
+ if (NILP (system_key_syms))
+ system_key_syms = Fcons (Qnil, Qnil);
return modify_event_symbol (event->code & 0xffffff,
event->modifiers,
- Qfunction_key, Vvendor_key_alist,
- 0, &vendor_key_syms, 0xffffff);
+ Qfunction_key, Vsystem_key_alist,
+ 0, &system_key_syms, 0xffffff);
}
return modify_event_symbol (event->code - 0xff00,
{
int part;
FRAME_PTR f = XFRAME (event->frame_or_window);
- Lisp_Object window
- = window_from_coordinates (f, XINT (event->x), XINT (event->y),
- &part);
+ Lisp_Object window;
Lisp_Object posn;
+ int row, column;
+
+ pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
+ &column, &row, 0, 0);
#ifdef USE_X_TOOLKIT
if (FRAME_EXTERNAL_MENU_BAR (f) && XINT (event->y) == -1)
+#else
+ if (row < FRAME_MENU_BAR_LINES (f))
+#endif
{
+ Lisp_Object items, item;
+
+#ifdef USE_X_TOOLKIT
/* The click happened in the menubar.
Look for the menu item selected. */
- Lisp_Object items = map_event_to_object(event, f);
+ item = map_event_to_object (event, f);
+
XFASTINT (event->y) = 1;
#else /* not USE_X_TOOLKIT */
- if (XINT (event->y) < FRAME_MENU_BAR_LINES (f))
- {
int hpos;
- Lisp_Object items;
+ int i;
+
items = FRAME_MENU_BAR_ITEMS (f);
- for (; CONSP (items); items = XCONS (items)->cdr)
+ for (i = 0; i < XVECTOR (items)->size; i += 3)
{
Lisp_Object pos, string;
- pos = Fcdr (Fcdr (Fcar (items)));
- string = Fcar (Fcdr (Fcar (items)));
- if (XINT (event->x) >= XINT (pos)
- && XINT (event->x) < XINT (pos) + XSTRING (string)->size)
+ string = XVECTOR (items)->contents[i + 1];
+ pos = XVECTOR (items)->contents[i + 2];
+ if (NILP (string))
break;
+ if (column >= XINT (pos)
+ && column < XINT (pos) + XSTRING (string)->size)
+ {
+ item = XVECTOR (items)->contents[i];
+ break;
+ }
}
#endif /* not USE_X_TOOLKIT */
+
position
= Fcons (event->frame_or_window,
Fcons (Qmenu_bar,
Fcons (make_number (event->timestamp),
Qnil))));
- if (CONSP (items))
- return Fcons (Fcar (Fcar (items)),
- Fcons (position, Qnil));
- else
- return Fcons (Qnil, Fcons (position, Qnil));
+ return Fcons (item, Fcons (position, Qnil));
}
- else if (XTYPE (window) != Lisp_Window)
+
+ window = window_from_coordinates (f, column, row, &part);
+
+ if (XTYPE (window) != Lisp_Window)
posn = Qnil;
else
{
- XSETINT (event->x,
- (XINT (event->x) - XINT (XWINDOW (window)->left)));
- XSETINT (event->y,
- (XINT (event->y) - XINT (XWINDOW (window)->top)));
+ int pixcolumn, pixrow;
+ column -= XINT (XWINDOW (window)->left);
+ row -= XINT (XWINDOW (window)->top);
+ glyph_to_pixel_coords (f, column, row, &pixcolumn, &pixrow);
+ XSETINT (event->x, pixcolumn);
+ XSETINT (event->y, pixrow);
if (part == 1)
posn = Qmode_line;
else
XSET (posn, Lisp_Int,
buffer_posn_from_coords (XWINDOW (window),
- XINT (event->x),
- XINT (event->y)));
+ column, row));
}
position
}
else
{
- Lisp_Object window = event->frame_or_window;
- Lisp_Object portion_whole = Fcons (event->x, event->y);
- Lisp_Object part = *scroll_bar_parts[(int) event->part];
+ Lisp_Object window;
+ Lisp_Object portion_whole;
+ Lisp_Object part;
+
+ window = event->frame_or_window;
+ portion_whole = Fcons (event->x, event->y);
+ part = *scroll_bar_parts[(int) event->part];
position =
Fcons (window,
Fcons (Qvertical_scroll_bar,
Fcons (portion_whole,
Fcons (make_number (event->timestamp),
- Fcons (part,
- Qnil)))));
+ Fcons (part, Qnil)))));
}
start_pos_ptr = &XVECTOR (button_down_location)->contents[button];
{
/* The third element of every position should be the (x,y)
pair. */
- Lisp_Object down = Fnth (make_number (2), start_pos);
+ Lisp_Object down;
+ down = Fnth (make_number (2), start_pos);
if (EQ (event->x, XCONS (down)->car)
&& EQ (event->y, XCONS (down)->cdr))
{
{
/* Get the symbol we should use for the mouse click. */
- Lisp_Object head
- = modify_event_symbol (button,
- event->modifiers,
- Qmouse_click, Qnil,
- lispy_mouse_names, &mouse_syms,
- (sizeof (lispy_mouse_names)
- / sizeof (lispy_mouse_names[0])));
-
+ Lisp_Object head;
+
+ head = modify_event_symbol (button,
+ event->modifiers,
+ Qmouse_click, Qnil,
+ lispy_mouse_names, &mouse_syms,
+ (sizeof (lispy_mouse_names)
+ / sizeof (lispy_mouse_names[0])));
if (event->modifiers & drag_modifier)
return Fcons (head,
Fcons (start_pos,
/* Is it a scroll bar movement? */
if (frame && ! NILP (bar_window))
{
- Lisp_Object part_sym = *scroll_bar_parts[(int) part];
+ Lisp_Object part_sym;
+ part_sym = *scroll_bar_parts[(int) part];
return Fcons (Qscroll_bar_movement,
(Fcons (Fcons (bar_window,
Fcons (Qvertical_scroll_bar,
else
{
int area;
- Lisp_Object window =
- (frame
- ? window_from_coordinates (frame, XINT (x), XINT (y), &area)
- : Qnil);
+ Lisp_Object window;
Lisp_Object posn;
+ int column, row;
+
+ pixel_to_glyph_coords (frame, XINT (x), XINT (y), &column, &row, 0, 0);
+
+ if (frame)
+ window = window_from_coordinates (frame, column, row, &area);
+ else
+ window = Qnil;
if (XTYPE (window) == Lisp_Window)
{
- XSETINT (x, XINT (x) - XINT (XWINDOW (window)->left));
- XSETINT (y, XINT (y) - XINT (XWINDOW (window)->top));
+ int pixcolumn, pixrow;
+ column -= XINT (XWINDOW (window)->left);
+ row -= XINT (XWINDOW (window)->top);
+ glyph_to_pixel_coords (frame, column, row, &pixcolumn, &pixrow);
+ XSETINT (x, pixcolumn);
+ XSETINT (y, pixrow);
if (area == 1)
posn = Qmode_line;
posn = Qvertical_line;
else
XSET (posn, Lisp_Int,
- buffer_posn_from_coords (XWINDOW (window),
- XINT (x), XINT (y)));
+ buffer_posn_from_coords (XWINDOW (window), column, row));
}
else if (frame != 0)
{
}
{
- Lisp_Object new_name = make_uninit_string (mod_len + base_len);
+ Lisp_Object new_name;
+ new_name = make_uninit_string (mod_len + base_len);
bcopy (new_mods, XSTRING (new_name)->data, mod_len);
bcopy (base, XSTRING (new_name)->data + mod_len, base_len);
parse_modifiers (symbol)
Lisp_Object symbol;
{
- Lisp_Object elements = Fget (symbol, Qevent_symbol_element_mask);
+ Lisp_Object elements;
+ elements = Fget (symbol, Qevent_symbol_element_mask);
if (CONSP (elements))
return elements;
else
{
int end;
int modifiers = parse_modifiers_uncached (symbol, &end);
- Lisp_Object unmodified
- = Fintern (make_string (XSYMBOL (symbol)->name->data + end,
- XSYMBOL (symbol)->name->size - end),
- Qnil);
+ Lisp_Object unmodified;
Lisp_Object mask;
+ unmodified = Fintern (make_string (XSYMBOL (symbol)->name->data + end,
+ XSYMBOL (symbol)->name->size - end),
+ Qnil);
+
if (modifiers & ~((1<<VALBITS) - 1))
abort ();
XFASTINT (mask) = modifiers;
Qevent_kind set right as well. */
if (NILP (Fget (new_symbol, Qevent_kind)))
{
- Lisp_Object kind = Fget (base, Qevent_kind);
+ Lisp_Object kind;
+ kind = Fget (base, Qevent_kind);
if (! NILP (kind))
Fput (new_symbol, Qevent_kind, kind);
}
{
/* It's hopefully okay to write the code this way, since everything
will soon be in caches, and no consing will be done at all. */
- Lisp_Object parsed = parse_modifiers (symbol);
+ Lisp_Object parsed;
+ parsed = parse_modifiers (symbol);
return apply_modifiers (XCONS (XCONS (parsed)->cdr)->car,
XCONS (parsed)->car);
}
Fix it for 19.23. */
/* Retry the read if it is interrupted. */
if (nread >= 0
-#ifdef EFAULT
- || ! (errno == EAGAIN || errno == EFAULT
-#else
|| ! (errno == EAGAIN
+#ifdef EFAULT
+ || errno == EFAULT
#endif
#ifdef EBADSLT
|| errno == EBADSLT
return Qnil;
}
-static Lisp_Object menu_bar_item ();
-static Lisp_Object menu_bar_one_keymap ();
+static void menu_bar_item ();
+static void menu_bar_one_keymap ();
+
+/* These variables hold the vector under construction within
+ menu_bar_items and its subroutines, and the current index
+ for storing into that vector. */
+static Lisp_Object menu_bar_items_vector;
+static Lisp_Object menu_bar_items_index;
-/* Return a list of menu items for a menu bar, appropriate
- to the current buffer.
- The elements have the form (KEY STRING . nil). */
+/* Return a vector of menu items for a menu bar, appropriate
+ to the current buffer. Each item has three elements in the vector:
+ KEY STRING nil.
+
+ OLD is an old vector we can optionally reuse, or nil. */
Lisp_Object
-menu_bar_items ()
+menu_bar_items (old)
+ Lisp_Object old;
{
/* The number of keymaps we're scanning right now, and the number of
keymaps we have allocated space for. */
int mapno;
Lisp_Object oquit;
+ int i;
+
+ struct gcpro gcpro1;
+
/* In order to build the menus, we need to call the keymap
accessors. They all call QUIT. But this function is called
during redisplay, during which a quit is fatal. So inhibit
oquit = Vinhibit_quit;
Vinhibit_quit = Qt;
+ if (!NILP (old))
+ menu_bar_items_vector = old;
+ else
+ menu_bar_items_vector = Fmake_vector (make_number (24), Qnil);
+ menu_bar_items_index = 0;
+
+ GCPRO1 (menu_bar_items_vector);
+
/* Build our list of keymaps.
If we recognize a function key and replace its escape sequence in
keybuf with its symbol, or if the sequence starts with a mouse
tem = Fkeymapp (def);
if (!NILP (tem))
- result = menu_bar_one_keymap (def, result);
+ menu_bar_one_keymap (def);
}
+ /* Move to the end those items that should be at the end. */
+
for (tail = Vmenu_bar_final_items; CONSP (tail); tail = XCONS (tail)->cdr)
{
- Lisp_Object elt;
+ int i;
+ int end = menu_bar_items_index;
+
+ for (i = 0; i < end; i += 3)
+ if (EQ (XCONS (tail)->car, XVECTOR (menu_bar_items_vector)->contents[i]))
+ {
+ Lisp_Object tem0, tem1, tem2;
+ /* Move the item at index I to the end,
+ shifting all the others forward. */
+ tem0 = XVECTOR (menu_bar_items_vector)->contents[i + 0];
+ tem1 = XVECTOR (menu_bar_items_vector)->contents[i + 1];
+ tem2 = XVECTOR (menu_bar_items_vector)->contents[i + 2];
+ if (end > i + 3)
+ bcopy (&XVECTOR (menu_bar_items_vector)->contents[i + 3],
+ &XVECTOR (menu_bar_items_vector)->contents[i],
+ (end - i - 3) * sizeof (Lisp_Object));
+ XVECTOR (menu_bar_items_vector)->contents[end - 3] = tem0;
+ XVECTOR (menu_bar_items_vector)->contents[end - 2] = tem1;
+ XVECTOR (menu_bar_items_vector)->contents[end - 1] = tem2;
+ break;
+ }
+ }
- elt = Fassq (XCONS (tail)->car, result);
- if (!NILP (elt))
- result = Fcons (elt, Fdelq (elt, result));
+ /* Add nil, nil, nil at the end. */
+ i = menu_bar_items_index;
+ if (i + 3 > XVECTOR (menu_bar_items_vector)->size)
+ {
+ Lisp_Object tem;
+ int newsize = 2 * i;
+ tem = Fmake_vector (make_number (2 * i), Qnil);
+ bcopy (XVECTOR (menu_bar_items_vector)->contents,
+ XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
+ menu_bar_items_vector = tem;
}
+ /* Add this item. */
+ XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
+ XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
+ XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
+ menu_bar_items_index = i;
- result = Fnreverse (result);
Vinhibit_quit = oquit;
- return result;
+ UNGCPRO;
+ return menu_bar_items_vector;
}
\f
/* Scan one map KEYMAP, accumulating any menu items it defines
- that have not yet been seen in RESULT. Return the updated RESULT. */
+ that have not yet been seen in RESULT. Return the updated RESULT.
+ *OLD is the frame's old menu bar list; we swipe elts from that
+ to avoid consing. */
-static Lisp_Object
-menu_bar_one_keymap (keymap, result)
- Lisp_Object keymap, result;
+static void
+menu_bar_one_keymap (keymap)
+ Lisp_Object keymap;
{
Lisp_Object tail, item, key, binding, item_string, table;
{
item_string = XCONS (binding)->car;
if (XTYPE (item_string) == Lisp_String)
- result = menu_bar_item (key, item_string,
- Fcdr (binding), result);
+ menu_bar_item (key, item_string, Fcdr (binding));
}
else if (EQ (binding, Qundefined))
- result = menu_bar_item (key, item_string,
- binding, result);
+ menu_bar_item (key, item_string, binding);
}
else if (XTYPE (item) == Lisp_Vector)
{
{
item_string = XCONS (binding)->car;
if (XTYPE (item_string) == Lisp_String)
- result = menu_bar_item (key, item_string,
- Fcdr (binding), result);
+ menu_bar_item (key, item_string, Fcdr (binding));
}
else if (EQ (binding, Qundefined))
- result = menu_bar_item (key, item_string,
- binding, result);
+ menu_bar_item (key, item_string, binding);
}
}
}
-
- return result;
}
+/* This is used as the handler when calling internal_condition_case_1. */
+
static Lisp_Object
-menu_bar_item (key, item_string, def, result)
- Lisp_Object key, item_string, def, result;
+menu_bar_item_1 (arg)
+ Lisp_Object arg;
+{
+ return Qnil;
+}
+
+static void
+menu_bar_item (key, item_string, def)
+ Lisp_Object key, item_string, def;
{
Lisp_Object tem;
Lisp_Object enabled;
+ int i;
if (EQ (def, Qundefined))
{
/* If a map has an explicit nil as definition,
discard any previously made menu bar item. */
- tem = Fassq (key, result);
- return Fdelq (tem, result);
+
+ for (i = 0; i < menu_bar_items_index; i += 3)
+ if (EQ (key, XVECTOR (menu_bar_items_vector)->contents[i]))
+ {
+ if (menu_bar_items_index > i + 3)
+ bcopy (&XVECTOR (menu_bar_items_vector)->contents[i + 3],
+ &XVECTOR (menu_bar_items_vector)->contents[i],
+ (menu_bar_items_index - i - 3) * sizeof (Lisp_Object));
+ menu_bar_items_index -= 3;
+ return;
+ }
}
/* See if this entry is enabled. */
Otherwise, enable if value is not nil. */
tem = Fget (def, Qmenu_enable);
if (!NILP (tem))
- enabled = Feval (tem);
+ /* (condition-case nil (eval tem)
+ (error nil)) */
+ enabled = internal_condition_case_1 (Feval, tem, Qerror,
+ menu_bar_item_1);
}
- /* Add an entry for this key and string
- if there is none yet. */
- tem = Fassq (key, result);
- if (!NILP (enabled) && NILP (tem))
- result = Fcons (Fcons (key, Fcons (item_string, Qnil)), result);
+ /* Ignore this item if it's not enabled. */
+ if (NILP (enabled))
+ return;
+
+ /* If there's already such an item, don't make another. */
+ for (i = 0; i < menu_bar_items_index; i += 3)
+ if (EQ (key, XVECTOR (menu_bar_items_vector)->contents[i]))
+ break;
- return result;
+ /* If we did not find this item, add it at the end. */
+ if (i == menu_bar_items_index)
+ {
+ /* If vector is too small, get a bigger one. */
+ if (i + 3 > XVECTOR (menu_bar_items_vector)->size)
+ {
+ Lisp_Object tem;
+ int newsize = 2 * i;
+ tem = Fmake_vector (make_number (2 * i), Qnil);
+ bcopy (XVECTOR (menu_bar_items_vector)->contents,
+ XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
+ menu_bar_items_vector = tem;
+ }
+ /* Add this item. */
+ XVECTOR (menu_bar_items_vector)->contents[i++] = key;
+ XVECTOR (menu_bar_items_vector)->contents[i++] = item_string;
+ XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
+ menu_bar_items_index = i;
+ }
}
\f
/* Read a character using menus based on maps in the array MAPS.
*/
orig_defn_macro = defining_kbd_macro ;
defining_kbd_macro = 0 ;
- obj = read_char (commandflag, 0, 0, Qnil, 0);
+ do
+ obj = read_char (commandflag, 0, 0, Qnil, 0);
+ while (XTYPE (obj) == Lisp_Buffer);
defining_kbd_macro = orig_defn_macro ;
if (XTYPE (obj) != Lisp_Int)
goto done;
}
+ /* If the current buffer has been changed from under us, the
+ keymap may have changed, so replay the sequence. */
+ if (XTYPE (key) == Lisp_Buffer)
+ {
+ mock_input = t;
+ goto replay_sequence;
+ }
+
/* If we have a quit that was typed in another frame, and
quit_throw_to_read_char switched buffers,
replay to get the right keymap. */
Vquit_flag = Qnil;
goto replay_sequence;
}
-
+
Vquit_flag = Qnil;
}
or when user programs play with this-command-keys. */
if (EVENT_HAS_PARAMETERS (key))
{
- Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
+ Lisp_Object kind;
+ kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
if (EQ (kind, Qmouse_click))
{
- Lisp_Object window = POSN_WINDOW (EVENT_START (key));
- Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key));
+ Lisp_Object window, posn;
+ window = POSN_WINDOW (EVENT_START (key));
+ posn = POSN_BUFFER_POSN (EVENT_START (key));
if (XTYPE (posn) == Lisp_Cons)
{
/* We're looking at the second event of a
}
else
{
- Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key));
+ Lisp_Object posn;
+ posn = POSN_BUFFER_POSN (EVENT_START (key));
/* Handle menu-bar events:
insert the dummy prefix event `menu-bar'. */
if (EQ (posn, Qmenu_bar))
if (t + 1 >= bufsize)
error ("key sequence too long");
/* Run the Lucid hook. */
- call1 (Vrun_hooks, Qactivate_menubar_hook);
+ if (!NILP (Vrun_hooks))
+ call1 (Vrun_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))
/* If KEY wasn't bound, we'll try some fallbacks. */
if (first_binding >= nmaps)
{
- Lisp_Object head = EVENT_HEAD (key);
+ Lisp_Object head;
+ head = EVENT_HEAD (key);
if (EQ (head, Vhelp_char))
{
read_key_sequence_cmd = Vprefix_help_command;
if (XTYPE (head) == Lisp_Symbol)
{
- Lisp_Object breakdown = parse_modifiers (head);
- int modifiers = XINT (XCONS (XCONS (breakdown)->cdr)->car);
+ Lisp_Object breakdown;
+ int modifiers;
+ breakdown = parse_modifiers (head);
+ modifiers = XINT (XCONS (XCONS (breakdown)->cdr)->car);
/* Attempt to reduce an unbound mouse event to a simpler
event that is bound:
Drags reduce to clicks.
if (XTYPE (cmd) == Lisp_Symbol)
{
tem = Fget (cmd, Qdisabled);
- if (!NILP (tem))
+ if (!NILP (tem) && !NILP (Vrun_hooks))
return call1 (Vrun_hooks, Qdisabled_command_hook);
}
Lisp_Object saved_keys;
struct gcpro gcpro1;
- saved_keys = Fthis_command_keys ();
+ saved_keys = Fvector (this_command_key_count,
+ XVECTOR (this_command_keys)->contents);
buf[0] = 0;
GCPRO1 (saved_keys);
function, followed by a RET. */
{
struct Lisp_String *str;
+ Lisp_Object *keys;
int i;
Lisp_Object tem;
this_command_key_count = 0;
- str = XSTRING (saved_keys);
- for (i = 0; i < str->size; i++)
- {
- XFASTINT (tem) = str->data[i];
- add_command_key (tem);
- }
+ keys = XVECTOR (saved_keys)->contents;
+ for (i = 0; i < XVECTOR (saved_keys)->size; i++)
+ add_command_key (keys[i]);
str = XSTRING (function);
for (i = 0; i < str->size; i++)
\f
DEFUN ("suspend-emacs", Fsuspend_emacs, Ssuspend_emacs, 0, 1, "",
"Stop Emacs and return to superior process. You can resume later.\n\
-On systems that don't have job control, run a subshell instead.\n\n\
+If `cannot-suspend' is non-nil, or if the system doesn't support job\n\
+control, run a subshell instead.\n\n\
If optional arg STUFFSTRING is non-nil, its characters are stuffed\n\
to be read as terminal input by Emacs's parent, after suspension.\n\
\n\
and the system resources aren't available for that. */
record_unwind_protect (init_sys_modes, 0);
stuff_buffered_input (stuffstring);
- sys_suspend ();
+ if (cannot_suspend)
+ sys_subshell ();
+ else
+ sys_suspend ();
unbind_to (count, Qnil);
/* Check if terminal/window size has changed.
and applies even for keys that have ordinary bindings.");
Vkey_translation_map = Qnil;
+ DEFVAR_BOOL ("cannot-suspend", &cannot_suspend,
+ "Non-nil means to always spawn a subshell instead of suspending,\n\
+even if the operating system has support for stopping a process.");
+ cannot_suspend = 0;
+
DEFVAR_BOOL ("menu-prompting", &menu_prompting,
"Non-nil means prompt with menus when appropriate.\n\
This is done when reading from a keymap that has a prompt string,\n\
Buffer modification stores t in this variable.");
Vdeactivate_mark = Qnil;
+ DEFVAR_LISP ("command-hook-internal", &Vcommand_hook_internal,
+ "Temporary storage of pre-command-hook or post-command-hook.");
+ Vcommand_hook_internal = Qnil;
+
DEFVAR_LISP ("pre-command-hook", &Vpre_command_hook,
"Normal hook run before each command is executed.");
Vpre_command_hook = Qnil;
DEFVAR_BOOL ("track-mouse", &do_mouse_tracking,
"*Non-nil means generate motion events for mouse motion.");
- DEFVAR_LISP ("vendor-key-alist", &Vvendor_key_alist,
- "Alist of vendor-specific X windows key symbols.\n\
+ DEFVAR_LISP ("system-key-alist", &Vsystem_key_alist,
+ "Alist of system-specific X windows key symbols.\n\
Each element should have the form (N . SYMBOL) where N is the\n\
-numeric keysym code (sans the \"vendor-specific\" bit 1<<28)\n\
+numeric keysym code (sans the \"system-specific\" bit 1<<28)\n\
and SYMBOL is its name.");
Vmenu_bar_final_items = Qnil;
}