#include "lisp.h"
#include "termhooks.h"
#include "macros.h"
+#include "keyboard.h"
#include "frame.h"
#include "window.h"
#include "commands.h"
#include "charset.h"
#include "disptab.h"
#include "dispextern.h"
-#include "keyboard.h"
#include "syntax.h"
#include "intervals.h"
#include "blockinput.h"
/* Include systime.h after xterm.h to avoid double inclusion of time.h. */
#include "systime.h"
+#ifndef USE_CRT_DLL
extern int errno;
+#endif
/* Variables for blockinput.h: */
extern char *pending_malloc_warning;
/* Circular buffer for pre-read keyboard input. */
+
static struct input_event kbd_buffer[KBD_BUFFER_SIZE];
-/* Vector to GCPRO the frames and windows mentioned in kbd_buffer.
+/* Vector to GCPRO the Lisp objects referenced from kbd_buffer.
The interrupt-level event handlers will never enqueue an event on a
frame which is not in Vframe_list, and once an event is dequeued,
Similar things happen when an event on a scroll bar is enqueued; the
window may be deleted while the event is in the queue.
- So, we use this vector to protect the frame_or_window field in the
- event queue. That way, they'll be dequeued as dead frames or
- windows, but still valid lisp objects.
+ So, we use this vector to protect the Lisp_Objects in the event
+ queue. That way, they'll be dequeued as dead frames or windows,
+ but still valid Lisp objects.
If kbd_buffer[i].kind != no_event, then
- (XVECTOR (kbd_buffer_frame_or_window)->contents[i]
- == kbd_buffer[i].frame_or_window. */
-static Lisp_Object kbd_buffer_frame_or_window;
+
+ AREF (kbd_buffer_gcpro, 2 * i) == kbd_buffer[i].frame_or_window.
+ AREF (kbd_buffer_gcpro, 2 * i + 1) == kbd_buffer[i].arg. */
+
+static Lisp_Object kbd_buffer_gcpro;
/* Pointer to next available character in kbd_buffer.
If kbd_fetch_ptr == kbd_store_ptr, the buffer is empty.
point to the boundary of the region. But, if a command sets this
valiable to non-nil, we suppress this point adjustment. This
variable is set to nil before reading a command. */
+
Lisp_Object Vdisable_point_adjustment;
/* If non-nil, always disable point adjustment. */
+
Lisp_Object Vglobal_disable_point_adjustment;
\f
/* Function for init_keyboard to call with no args (if nonzero). */
void (*keyboard_init_hook) ();
-static int read_avail_input ();
-static void get_input_pending ();
-static int readable_events ();
+static int read_avail_input P_ ((int));
+static void get_input_pending P_ ((int *, int));
+static int readable_events P_ ((int));
+static Lisp_Object read_char_x_menu_prompt P_ ((int, Lisp_Object *,
+ Lisp_Object, int *));
static Lisp_Object read_char_x_menu_prompt ();
-static Lisp_Object read_char_minibuf_menu_prompt ();
-static Lisp_Object make_lispy_event ();
+static Lisp_Object read_char_minibuf_menu_prompt P_ ((int, int,
+ Lisp_Object *));
+static Lisp_Object make_lispy_event P_ ((struct input_event *));
#ifdef HAVE_MOUSE
-static Lisp_Object make_lispy_movement ();
+static Lisp_Object make_lispy_movement P_ ((struct frame *, Lisp_Object,
+ enum scroll_bar_part,
+ Lisp_Object, Lisp_Object,
+ unsigned long));
#endif
-static Lisp_Object modify_event_symbol ();
-static Lisp_Object make_lispy_switch_frame ();
+static Lisp_Object modify_event_symbol P_ ((int, unsigned, Lisp_Object,
+ Lisp_Object, char **,
+ Lisp_Object *, unsigned));
+static Lisp_Object make_lispy_switch_frame P_ ((Lisp_Object));
+static int parse_solitary_modifier P_ ((Lisp_Object));
static int parse_solitary_modifier ();
+static void save_getcjmp P_ ((jmp_buf));
static void save_getcjmp ();
-static void restore_getcjmp ();
+static void restore_getcjmp P_ ((jmp_buf));
static Lisp_Object apply_modifiers P_ ((int, Lisp_Object));
+static void clear_event P_ ((struct input_event *));
/* Nonzero means don't try to suspend even if the operating system seems
to support it. */
if (check_display
&& PT > BEGV && PT < ZV
&& get_property_and_range (PT, Qdisplay, &val, &start, &end, Qnil)
+ && display_prop_intangible_p (val)
&& start < PT && end > PT
&& (last_pt <= start || last_pt >= end))
{
safe_run_hooks_error (data)
Lisp_Object data;
{
- Fset (Vinhibit_quit, Qnil);
+ return Fset (Vinhibit_quit, Qnil);
}
/* If we get an error while running the hook, cause the hook variable
return c;
}
+/* Display help echo in the echo area.
+
+ HELP a string means display that string, HELP nil means clear the
+ help echo. If HELP is a function, call it with OBJECT and POS as
+ arguments; the function should return a help string or nil for
+ none. For all other types of HELP evaluate it to obtain a string.
+
+ WINDOW is the window in which the help was generated, if any.
+ It is nil if not in a window.
+
+ If OBJECT is a buffer, POS is the position in the buffer where the
+ `help-echo' text property was found.
+
+ If OBJECT is an overlay, that overlay has a `help-echo' property,
+ and POS is the position in the overlay's buffer under the mouse.
+
+ If OBJECT is a string (an overlay string or a string displayed with
+ the `display' property). POS is the position in that string under
+ the mouse.
+
+ OK_TO_IVERWRITE_KEYSTROKE_ECHO non-zero means it's okay if the help
+ echo overwrites a keystroke echo currently displayed in the echo
+ area.
+
+ Note: this function may only be called with HELP nil or a string
+ from X code running asynchronously. */
+
+void
+show_help_echo (help, window, object, pos, ok_to_overwrite_keystroke_echo)
+ Lisp_Object help, window, object, pos;
+ int ok_to_overwrite_keystroke_echo;
+{
+ if (!NILP (help) && !STRINGP (help))
+ {
+ if (FUNCTIONP (help))
+ {
+ Lisp_Object args[4];
+ args[0] = help;
+ args[1] = window;
+ args[2] = object;
+ args[3] = pos;
+ help = call_function (4, args);
+ }
+ else
+ help = eval_form (help);
+
+ if (!STRINGP (help))
+ return;
+ }
+
+ if (STRINGP (help) || NILP (help))
+ {
+ if (!NILP (Vshow_help_function))
+ call1 (Vshow_help_function, help);
+ else if (/* Don't overwrite minibuffer contents. */
+ !MINI_WINDOW_P (XWINDOW (selected_window))
+ /* Don't overwrite a keystroke echo. */
+ && (NILP (echo_message_buffer)
+ || ok_to_overwrite_keystroke_echo)
+ /* Don't overwrite a prompt. */
+ && !cursor_in_echo_area)
+ {
+ if (STRINGP (help))
+ {
+ int count = specpdl_ptr - specpdl;
+ specbind (Qmessage_truncate_lines, Qt);
+ message3_nolog (help, XSTRING (help)->size,
+ STRING_MULTIBYTE (help));
+ unbind_to (count, Qnil);
+ }
+ else
+ message (0);
+ }
+ }
+}
+
\f
/* Input of single characters from keyboard */
/* Display help if not echoing. */
if (CONSP (c) && EQ (XCAR (c), Qhelp_echo))
{
- Lisp_Object msg;
-
- msg = XCDR (XCDR (c));
-
- if (!NILP (Vshow_help_function))
- call1 (Vshow_help_function, msg);
- else if (/* Don't overwrite minibuffer contents. */
- !MINI_WINDOW_P (XWINDOW (selected_window))
- /* Don't overwrite a keystroke echo. */
- && NILP (echo_message_buffer)
- /* Don't overwrite a prompt. */
- && !cursor_in_echo_area)
- {
- if (STRINGP (msg))
- message3_nolog (msg, XSTRING (msg)->size, STRING_MULTIBYTE (msg));
- else
- message (0);
- }
-
+ /* (help-echo FRAME HELP WINDOW OBJECT POS). */
+ Lisp_Object help, object, position, window;
+ help = Fnth (make_number (2), c);
+ window = Fnth (make_number (3), c);
+ object = Fnth (make_number (4), c);
+ position = Fnth (make_number (5), c);
+ show_help_echo (help, window, object, position, 0);
goto retry;
}
get_input_pending (&input_pending, 1);
}
}
+ return Qnil;
}
DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0,
{
sp->kind = no_event;
sp->frame_or_window = Qnil;
+ sp->arg = Qnil;
}
}
return;
Discard the event if it would fill the last slot. */
if (kbd_fetch_ptr - 1 != kbd_store_ptr)
{
+ int idx;
+
+#if 0 /* The selection_request_event case looks bogus, and it's error
+ prone to assign individual members for other events, in case
+ the input_event structure is changed. --2000-07-13, gerd. */
struct input_event *sp = kbd_store_ptr;
sp->kind = event->kind;
if (event->kind == selection_request_event)
bcopy (event, (char *) sp, sizeof (*event));
}
else
+
{
sp->code = event->code;
sp->part = event->part;
sp->frame_or_window = event->frame_or_window;
+ sp->arg = event->arg;
sp->modifiers = event->modifiers;
sp->x = event->x;
sp->y = event->y;
sp->timestamp = event->timestamp;
}
- (XVECTOR (kbd_buffer_frame_or_window)->contents[kbd_store_ptr
- - kbd_buffer]
- = event->frame_or_window);
+#else
+ *kbd_store_ptr = *event;
+#endif
- kbd_store_ptr++;
+ idx = 2 * (kbd_store_ptr - kbd_buffer);
+ ASET (kbd_buffer_gcpro, idx, event->frame_or_window);
+ ASET (kbd_buffer_gcpro, idx + 1, event->arg);
+ ++kbd_store_ptr;
}
}
+
+
+/* Generate HELP_EVENT input_events in BUFP which has roon for
+ SIZE events. If there's not enough room in BUFP, ignore this
+ event.
+
+ HELP is the help form.
+
+ FRAME is the frame on which the help is generated. OBJECT is the
+ Lisp object where the help was found (a buffer, a string, an
+ overlay, or nil if neither from a string nor from a buffer. POS is
+ the position within OBJECT where the help was found.
+
+ Value is the number of input_events generated. */
+
+int
+gen_help_event (bufp, size, help, frame, window, object, pos)
+ struct input_event *bufp;
+ int size;
+ Lisp_Object help, frame, object, window;
+ int pos;
+{
+ int nevents_stored = 0;
+
+ if (size >= 2)
+ {
+ bufp->kind = HELP_EVENT;
+ bufp->frame_or_window = frame;
+ bufp->arg = object;
+ bufp->x = make_number (pos);
+ bufp->code = 0;
+
+ ++bufp;
+ bufp->kind = HELP_EVENT;
+ bufp->frame_or_window = WINDOWP (window) ? window : frame;
+ bufp->arg = help;
+ bufp->code = 1;
+ nevents_stored = 2;
+ }
+
+ return nevents_stored;
+}
+
+
+/* Store HELP_EVENTs for HELP on FRAME in the input queue. */
+
+void
+kbd_buffer_store_help_event (frame, help)
+ Lisp_Object frame, help;
+{
+ struct input_event event;
+
+ event.kind = HELP_EVENT;
+ event.frame_or_window = frame;
+ event.arg = Qnil;
+ event.x = make_number (0);
+ event.code = 0;
+ kbd_buffer_store_event (&event);
+
+ event.kind = HELP_EVENT;
+ event.frame_or_window = frame;
+ event.arg = help;
+ event.x = make_number (0);
+ event.code = 1;
+ kbd_buffer_store_event (&event);
+}
+
\f
/* Discard any mouse events in the event buffer by setting them to
no_event. */
}
}
}
+
+
+/* Return non-zero if there are any real events waiting in the event
+ buffer, not counting `no_event's.
+
+ If DISCARD is non-zero, discard no_event events at the front of
+ the input queue, possibly leaving the input queue empty if there
+ are no real input events. */
+
+int
+kbd_buffer_events_waiting (discard)
+ int discard;
+{
+ struct input_event *sp;
+
+ for (sp = kbd_fetch_ptr;
+ sp != kbd_store_ptr && sp->kind == no_event;
+ ++sp)
+ {
+ if (sp == kbd_buffer + KBD_BUFFER_SIZE)
+ sp = kbd_buffer;
+ }
+
+ if (discard)
+ kbd_fetch_ptr = sp;
+
+ return sp != kbd_store_ptr && sp->kind != no_event;
+}
+
\f
+/* Clear input event EVENT. */
+
+static INLINE void
+clear_event (event)
+ struct input_event *event;
+{
+ int idx = 2 * (event - kbd_buffer);
+ ASET (kbd_buffer_gcpro, idx, Qnil);
+ ASET (kbd_buffer_gcpro, idx + 1, Qnil);
+ event->kind = no_event;
+}
+
+
/* Read one event from the event buffer, waiting if necessary.
The value is a Lisp object representing the event.
The value is nil for an event that should be ignored,
kbd_fetch_ptr = event + 1;
else if (event->kind == HELP_EVENT)
{
- /* The car of event->frame_or_window is a frame,
- the cdr is the help to display. */
- obj = Fcons (Qhelp_echo, event->frame_or_window);
+ /* There are always two HELP_EVENTs in the input queue. */
+ Lisp_Object object, position, help, frame, window;
+
+ xassert (event->code == 0);
+ frame = event->frame_or_window;
+ object = event->arg;
+ position = event->x;
+ clear_event (event);
+
+ kbd_fetch_ptr = event + 1;
+ event = ((kbd_fetch_ptr < kbd_buffer + KBD_BUFFER_SIZE)
+ ? kbd_fetch_ptr
+ : kbd_buffer);
+ xassert (event->code == 1);
+ help = event->arg;
+ window = event->frame_or_window;
+ if (!WINDOWP (window))
+ window = Qnil;
+ obj = Fcons (Qhelp_echo,
+ list5 (frame, help, window, object, position));
+ clear_event (event);
+ kbd_fetch_ptr = event + 1;
+ }
+ else if (event->kind == FOCUS_IN_EVENT)
+ {
+ /* Notification of a FocusIn event. The frame receiving the
+ focus is in event->frame_or_window. Generate a
+ switch-frame event if necessary. */
+ Lisp_Object frame, focus;
+
+ frame = event->frame_or_window;
+ focus = FRAME_FOCUS_FRAME (XFRAME (frame));
+ if (FRAMEP (focus))
+ frame = focus;
+
+ if (!EQ (frame, internal_last_event_frame)
+ && !EQ (frame, selected_frame))
+ obj = make_lispy_switch_frame (frame);
+ internal_last_event_frame = frame;
kbd_fetch_ptr = event + 1;
}
- /* If this event is on a different frame, return a switch-frame this
- time, and leave the event in the queue for next time. */
else
{
+ /* If this event is on a different frame, return a switch-frame this
+ time, and leave the event in the queue for next time. */
Lisp_Object frame;
Lisp_Object focus;
if (NILP (obj))
{
+ int idx;
+
obj = make_lispy_event (event);
+
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
/* If this was a menu selection, then set the flag to inhibit
writing to last_nonmenu_event. Don't do this if the event
we're returning is (menu-bar), though; that indicates the
beginning of the menu sequence, and we might as well leave
that as the `event with parameters' for this selection. */
- if ((event->kind == menu_bar_event
- || event->kind == TOOL_BAR_EVENT)
- && !(CONSP (obj) && EQ (XCAR (obj), Qmenu_bar))
- && !(CONSP (obj) && EQ (XCAR (obj), Qtool_bar))
- && used_mouse_menu)
+ if (used_mouse_menu
+ && !EQ (event->frame_or_window, event->arg)
+ && (event->kind == MENU_BAR_EVENT
+ || event->kind == TOOL_BAR_EVENT))
*used_mouse_menu = 1;
#endif
/* Wipe out this event, to catch bugs. */
- event->kind = no_event;
- XVECTOR (kbd_buffer_frame_or_window)->contents[event - kbd_buffer] = Qnil;
-
+ clear_event (event);
kbd_fetch_ptr = event + 1;
}
}
return lispy_c;
}
+ case multibyte_char_keystroke:
+ {
+ Lisp_Object lispy_c;
+
+ XSETFASTINT (lispy_c, event->code);
+ return lispy_c;
+ }
+
/* A function key. The symbol may need to have modifier prefixes
tacked onto it. */
case non_ascii_keystroke:
int pixcolumn, pixrow;
column -= XINT (XWINDOW (window)->left);
row -= XINT (XWINDOW (window)->top);
- glyph_to_pixel_coords (f, column, row, &pixcolumn, &pixrow);
+ glyph_to_pixel_coords (XWINDOW(window), column, row,
+ &pixcolumn, &pixrow);
XSETINT (event->x, pixcolumn);
XSETINT (event->y, pixrow);
#endif /* HAVE_MOUSE */
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
- case menu_bar_event:
- /* The event value is in the cdr of the frame_or_window slot. */
- if (!CONSP (event->frame_or_window))
- abort ();
- return XCDR (event->frame_or_window);
+ case MENU_BAR_EVENT:
+ if (EQ (event->arg, event->frame_or_window))
+ /* This is the prefix key. We translate this to
+ `(menu_bar)' because the code in keyboard.c for menu
+ events, which we use, relies on this. */
+ return Fcons (Qmenu_bar, Qnil);
+ return event->arg;
#endif
case TOOL_BAR_EVENT:
- {
- Lisp_Object key;
- if (!CONSP (event->frame_or_window))
- abort ();
- key = XCDR (event->frame_or_window);
- if (SYMBOLP (key))
- key = apply_modifiers (event->modifiers, key);
- return key;
- }
-
- case user_signal:
+ if (EQ (event->arg, event->frame_or_window))
+ /* This is the prefix key. We translate this to
+ `(tool_bar)' because the code in keyboard.c for menu
+ events, which we use, relies on this. */
+ return Fcons (Qtool_bar, Qnil);
+ else if (SYMBOLP (event->arg))
+ return apply_modifiers (event->modifiers, event->arg);
+ return event->arg;
+
+ case USER_SIGNAL_EVENT:
/* A user signal. */
return *lispy_user_signals[event->code];
Alternatively, NAME_ALIST_OR_STEM is either an alist mapping codes
into symbol names, or a string specifying a name stem used to
- contruct a symbol name or the form `STEM-N', where N is the decimal
+ construct a symbol name or the form `STEM-N', where N is the decimal
representation of SYMBOL_NUM. NAME_ALIST_OR_STEM is used if it is
non-nil; otherwise NAME_TABLE is used.
event.kind = buffer_switch_event;
event.frame_or_window = Qnil;
+ event.arg = Qnil;
#ifdef subprocesses
/* We don't need a buffer-switch event unless Emacs is waiting for input.
buf[i].code = cbuf[i];
buf[i].frame_or_window = selected_frame;
+ buf[i].arg = Qnil;
}
}
}
else
{
- /* No, so use major and minor mode keymaps. */
+ /* No, so use major and minor mode keymaps and keymap property. */
+ int extra_maps = 2;
+ Lisp_Object map = get_local_map (PT, current_buffer, keymap);
+ if (!NILP (map))
+ extra_maps = 3;
nmaps = current_minor_maps (NULL, &tmaps);
- maps = (Lisp_Object *) alloca ((nmaps + 2) * sizeof (maps[0]));
+ maps = (Lisp_Object *) alloca ((nmaps + extra_maps)
+ * sizeof (maps[0]));
bcopy (tmaps, maps, nmaps * sizeof (maps[0]));
- maps[nmaps++] = get_local_map (PT, current_buffer);
+ if (!NILP (map))
+ maps[nmaps++] = get_local_map (PT, current_buffer, keymap);
+ maps[nmaps++] = get_local_map (PT, current_buffer, local_map);
}
maps[nmaps++] = current_global_map;
}
item = XCDR (item);
}
- /* Maybee key binding cache. */
+ /* Maybe key binding cache. */
if (CONSP (item) && CONSP (XCAR (item))
&& (NILP (XCAR (XCAR (item)))
|| VECTORP (XCAR (XCAR (item)))))
}
else
{
- /* No, so use major and minor mode keymaps. */
+ /* No, so use major and minor mode keymaps and keymap property. */
+ int extra_maps = 2;
+ Lisp_Object map = get_local_map (PT, current_buffer, keymap);
+ if (!NILP (map))
+ extra_maps = 3;
nmaps = current_minor_maps (NULL, &tmaps);
- maps = (Lisp_Object *) alloca ((nmaps + 2) * sizeof (maps[0]));
+ maps = (Lisp_Object *) alloca ((nmaps + extra_maps)
+ * sizeof (maps[0]));
bcopy (tmaps, maps, nmaps * sizeof (maps[0]));
- maps[nmaps++] = get_local_map (PT, current_buffer);
+ if (!NILP (map))
+ maps[nmaps++] = get_local_map (PT, current_buffer, keymap);
+ maps[nmaps++] = get_local_map (PT, current_buffer, local_map);
}
/* Add global keymap at the end. */
char_matches = (XINT (upcased_event) == XSTRING (s)->data[0]
|| XINT (downcased_event) == XSTRING (s)->data[0]);
if (! char_matches)
- desc = Fsingle_key_description (event);
+ desc = Fsingle_key_description (event, Qnil);
tem
= XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ];
followed by the corresponding non-meta character.
Put the results into DEFS, since we are going to alter that anyway.
Do not alter CURRENT or NEXT. */
- if (INTEGERP (key) && (XINT (key) & CHAR_META))
+ if (INTEGERP (key) && (XUINT (key) & CHAR_META))
{
for (i = 0; i < nmaps; i++)
if (! NILP (current[i]))
else
map = current[i];
- defs[i] = get_keyelt (access_keymap (map, key, 1, 0), 0);
+ defs[i] = get_keyelt (access_keymap (map, key, 1, 0), 1);
if (! NILP (defs[i]))
first_binding = i;
}
/* The local map to start out with at start of key sequence. */
Lisp_Object orig_local_map;
+ /* The map from the `keymap' property to start out with at start of
+ key sequence. */
+ Lisp_Object orig_keymap;
+
/* 1 if we have already considered switching to the local-map property
of the place where a mouse click occurred. */
int localized_local_map = 0;
&junk);
#endif /* GOBBLE_FIRST_EVENT */
- orig_local_map = get_local_map (PT, current_buffer);
+ orig_local_map = get_local_map (PT, current_buffer, local_map);
+ orig_keymap = get_local_map (PT, current_buffer, keymap);
/* We jump here when the key sequence has been thoroughly changed, and
we need to rescan it starting from the beginning. When we jump here,
}
else
{
+ int extra_maps = 2;
nmaps = current_minor_maps (0, &maps);
- if (nmaps + 2 > nmaps_allocated)
+ if (!NILP (orig_keymap))
+ extra_maps = 3;
+ if (nmaps + extra_maps > nmaps_allocated)
{
- submaps = (Lisp_Object *) alloca ((nmaps+2) * sizeof (submaps[0]));
- defs = (Lisp_Object *) alloca ((nmaps+2) * sizeof (defs[0]));
- nmaps_allocated = nmaps + 2;
+ submaps = (Lisp_Object *) alloca ((nmaps+extra_maps)
+ * sizeof (submaps[0]));
+ defs = (Lisp_Object *) alloca ((nmaps+extra_maps)
+ * sizeof (defs[0]));
+ nmaps_allocated = nmaps + extra_maps;
}
bcopy (maps, submaps, nmaps * sizeof (submaps[0]));
+ if (!NILP (orig_keymap))
+ submaps[nmaps++] = orig_keymap;
submaps[nmaps++] = orig_local_map;
}
submaps[nmaps++] = current_global_map;
interrupted_kboard->kbd_queue);
}
mock_input = 0;
- orig_local_map = get_local_map (PT, current_buffer);
+ orig_local_map = get_local_map (PT, current_buffer, local_map);
+ orig_keymap = get_local_map (PT, current_buffer, keymap);
goto replay_sequence;
}
#endif
Fset_buffer (XWINDOW (selected_window)->buffer);
}
- orig_local_map = get_local_map (PT, current_buffer);
+ orig_local_map = get_local_map (PT, current_buffer, local_map);
+ orig_keymap = get_local_map (PT, current_buffer, keymap);
goto replay_sequence;
}
keybuf[t++] = key;
mock_input = t;
Vquit_flag = Qnil;
- orig_local_map = get_local_map (PT, current_buffer);
+ orig_local_map = get_local_map (PT, current_buffer, local_map);
+ orig_keymap = get_local_map (PT, current_buffer, keymap);
goto replay_sequence;
}
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
Fkill_emacs (Qnil);
- set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
- orig_local_map = get_local_map (PT, current_buffer);
+ set_buffer_internal (XBUFFER (XWINDOW
+ (window)->buffer)
+);
+ orig_local_map = get_local_map (PT, current_buffer,
+ local_map);
+ orig_keymap = get_local_map (PT, current_buffer, keymap);
goto replay_sequence;
}
if (INTEGERP (pos)
&& XINT (pos) >= BEG && XINT (pos) <= Z)
{
- map_here = get_local_map (XINT (pos), current_buffer);
+ map_here = get_local_map (XINT (pos),
+ current_buffer, local_map);
if (!EQ (map_here, orig_local_map))
{
orig_local_map = map_here;
keybuf[t] = key;
mock_input = t + 1;
+ goto replay_sequence;
+ }
+ map_here = get_local_map (XINT (pos),
+ current_buffer, keymap);
+ if (!EQ (map_here, orig_keymap))
+ {
+ orig_keymap = map_here;
+ keybuf[t] = key;
+ mock_input = t + 1;
+
goto replay_sequence;
}
}
reconsider the key sequence with that keymap. */
if (CONSP (POSN_STRING (EVENT_START (key))))
{
- Lisp_Object string, pos, map;
+ Lisp_Object string, pos, map, map2;
string = POSN_STRING (EVENT_START (key));
pos = XCDR (string);
string = XCAR (string);
-
- if (XINT (pos) >= 0
- && XINT (pos) < XSTRING (string)->size
- && (map = Fget_text_property (pos, Qlocal_map,
- string),
- !NILP (map)))
- {
- orig_local_map = map;
- goto replay_sequence;
- }
+ if (XINT (pos) >= 0
+ && XINT (pos) < XSTRING (string)->size)
+ {
+ map = Fget_text_property (pos, Qlocal_map, string);
+ if (!NILP (map))
+ orig_local_map = map;
+ map2 = Fget_text_property (pos, Qkeymap, string);
+ if (!NILP (map2))
+ orig_keymap = map2;
+ if (!NILP (map) || !NILP (map2))
+ goto replay_sequence;
+ }
}
goto replay_key;
key = keybuf[fkey_end++];
/* Look up meta-characters by prefixing them
with meta_prefix_char. I hate this. */
- if (INTEGERP (key) && XINT (key) & meta_modifier)
+ if (INTEGERP (key) && XUINT (key) & meta_modifier)
{
fkey_next
= get_keymap_1
key = keybuf[keytran_end++];
/* Look up meta-characters by prefixing them
with meta_prefix_char. I hate this. */
- if (INTEGERP (key) && XINT (key) & meta_modifier)
+ if (INTEGERP (key) && XUINT (key) & meta_modifier)
{
keytran_next
= get_keymap_1
}
else
{
- /* No, so use major and minor mode keymaps. */
+ /* No, so use major and minor mode keymaps and keymap property. */
+ int extra_maps = 2;
+ Lisp_Object map = get_local_map (PT, current_buffer, keymap);
+ if (!NILP (map))
+ extra_maps = 3;
nmaps = current_minor_maps (NULL, &tmaps);
- maps = (Lisp_Object *) xmalloc ((nmaps + 2) * sizeof (maps[0]));
+ maps = (Lisp_Object *) alloca ((nmaps + extra_maps)
+ * sizeof (maps[0]));
bcopy (tmaps, maps, nmaps * sizeof (maps[0]));
- maps[nmaps++] = get_local_map (PT, current_buffer);
+ if (!NILP (map))
+ maps[nmaps++] = get_local_map (PT, current_buffer, keymap);
+ maps[nmaps++] = get_local_map (PT, current_buffer, local_map);
}
maps[nmaps++] = current_global_map;
discard_tty_input ();
kbd_fetch_ptr = kbd_store_ptr;
- Ffillarray (kbd_buffer_frame_or_window, Qnil);
+ Ffillarray (kbd_buffer_gcpro, Qnil);
input_pending = 0;
return Qnil;
stuff_char (*p++);
stuff_char ('\n');
}
+
/* Anything we have read ahead, put back for the shell to read. */
/* ?? What should this do when we have multiple keyboards??
Should we ignore anything that was typed in at the "wrong" kboard? */
for (; kbd_fetch_ptr != kbd_store_ptr; kbd_fetch_ptr++)
{
+ int idx;
+
if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE)
kbd_fetch_ptr = kbd_buffer;
if (kbd_fetch_ptr->kind == ascii_keystroke)
stuff_char (kbd_fetch_ptr->code);
+
kbd_fetch_ptr->kind = no_event;
- (XVECTOR (kbd_buffer_frame_or_window)->contents[kbd_fetch_ptr
- - kbd_buffer]
- = Qnil);
+ idx = 2 * (kbd_fetch_ptr - kbd_buffer);
+ ASET (kbd_buffer_gcpro, idx, Qnil);
+ ASET (kbd_buffer_gcpro, idx + 1, Qnil);
}
+
input_pending = 0;
#endif
#endif /* BSD_SYSTEM and not BSD4_1 */
}
/* This routine is called at interrupt level in response to C-G.
- If interrupt_input, this is the handler for SIGINT.
- Otherwise, it is called from kbd_buffer_store_event,
- in handling SIGIO or SIGTINT.
+
+ If interrupt_input, this is the handler for SIGINT. Otherwise, it
+ is called from kbd_buffer_store_event, in handling SIGIO or
+ SIGTINT.
- If `waiting_for_input' is non zero, then unless `echoing' is nonzero,
- immediately throw back to read_char.
+ If `waiting_for_input' is non zero, then unless `echoing' is
+ nonzero, immediately throw back to read_char.
- Otherwise it sets the Lisp variable quit-flag not-nil.
- This causes eval to throw, when it gets a chance.
- If quit-flag is already non-nil, it stops the job right away. */
+ Otherwise it sets the Lisp variable quit-flag not-nil. This causes
+ eval to throw, when it gets a chance. If quit-flag is already
+ non-nil, it stops the job right away. */
SIGTYPE
interrupt_signal (signalnum) /* If we don't have an argument, */
recent_keys_index = 0;
kbd_fetch_ptr = kbd_buffer;
kbd_store_ptr = kbd_buffer;
- kbd_buffer_frame_or_window
- = Fmake_vector (make_number (KBD_BUFFER_SIZE), Qnil);
+ kbd_buffer_gcpro = Fmake_vector (make_number (2 * KBD_BUFFER_SIZE), Qnil);
#ifdef HAVE_MOUSE
do_mouse_tracking = Qnil;
#endif
wipe_kboard (current_kboard);
init_kboard (current_kboard);
- if (initialized)
- Ffillarray (kbd_buffer_frame_or_window, Qnil);
-
- kbd_buffer_frame_or_window
- = Fmake_vector (make_number (KBD_BUFFER_SIZE), Qnil);
if (!noninteractive && !read_socket_hook && NILP (Vwindow_system))
{
signal (SIGINT, interrupt_signal);
Fset (Qinput_method_exit_on_first_char, Qnil);
Fset (Qinput_method_use_echo_area, Qnil);
+ last_point_position_buffer = Qnil;
+
{
struct event_head *p;
Fset (Qextended_command_history, Qnil);
staticpro (&Qextended_command_history);
- kbd_buffer_frame_or_window
- = Fmake_vector (make_number (KBD_BUFFER_SIZE), Qnil);
- staticpro (&kbd_buffer_frame_or_window);
+ kbd_buffer_gcpro = Fmake_vector (make_number (2 * KBD_BUFFER_SIZE), Qnil);
+ staticpro (&kbd_buffer_gcpro);
accent_key_syms = Qnil;
staticpro (&accent_key_syms);