/* Keyboard and mouse input; editor command loop.
-Copyright (C) 1985-1989, 1993-1997, 1999-2012 Free Software Foundation, Inc.
+Copyright (C) 1985-1989, 1993-1997, 1999-2013 Free Software Foundation,
+Inc.
This file is part of GNU Emacs.
#include <config.h>
-#define BLOCKINPUT_INLINE EXTERN_INLINE
-#define KEYBOARD_INLINE EXTERN_INLINE
-
-#include <stdio.h>
+#include "sysstdio.h"
#include "lisp.h"
#include "termchar.h"
#include TERM_HEADER
#endif /* HAVE_WINDOW_SYSTEM */
-/* Variables for blockinput.h: */
+/* Variables for blockinput.h: */
/* Positive if interrupt input is blocked right now. */
volatile int interrupt_input_blocked;
KBOARD *initial_kboard;
KBOARD *current_kboard;
-KBOARD *all_kboards;
+static KBOARD *all_kboards;
/* True in the single-kboard state, false in the any-kboard state. */
static bool single_kboard;
/* The value of point when the last command was started. */
static ptrdiff_t last_point_position;
-/* The buffer that was current when the last command was started. */
-static Lisp_Object last_point_position_buffer;
-
-/* The window that was selected when the last command was started. */
-static Lisp_Object last_point_position_window;
-
/* 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
generate switch-frame events. This may be cleared by functions
'volatile' here. */
Lisp_Object internal_last_event_frame;
-/* The timestamp of the last input event we received from the X server.
- X Windows wants this for selection ownership. */
-Time last_event_timestamp;
-
static Lisp_Object Qx_set_selection, Qhandle_switch_frame;
static Lisp_Object Qhandle_select_window;
Lisp_Object QPRIMARY;
static Lisp_Object Qmouse_movement;
static Lisp_Object Qscroll_bar_movement;
Lisp_Object Qswitch_frame;
+static Lisp_Object Qfocus_in, Qfocus_out;
static Lisp_Object Qdelete_frame;
static Lisp_Object Qiconify_frame;
static Lisp_Object Qmake_frame_visible;
static Lisp_Object Qselect_window;
Lisp_Object Qhelp_echo;
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
static Lisp_Object Qmouse_fixup_help_message;
-#endif
/* Symbols to denote kinds of events. */
static Lisp_Object Qfunction_key;
#ifdef HAVE_DBUS
static Lisp_Object Qdbus_event;
#endif
+#ifdef USE_FILE_NOTIFY
+static Lisp_Object Qfile_notify;
+#endif /* USE_FILE_NOTIFY */
static Lisp_Object Qconfig_changed_event;
/* Lisp_Object Qmouse_movement; - also an event header */
/* Symbols to use for parts of windows. */
Lisp_Object Qmode_line;
Lisp_Object Qvertical_line;
+Lisp_Object Qright_divider, Qbottom_divider;
static Lisp_Object Qvertical_scroll_bar;
Lisp_Object Qmenu_bar;
-static Lisp_Object recursive_edit_unwind (Lisp_Object buffer);
+static Lisp_Object Qecho_keystrokes;
+
+static void recursive_edit_unwind (Lisp_Object buffer);
static Lisp_Object command_loop (void);
-static Lisp_Object Qextended_command_history;
-EMACS_TIME timer_check (void);
+static Lisp_Object Qcommand_execute;
+struct timespec timer_check (void);
static void echo_now (void);
static ptrdiff_t echo_length (void);
/* Incremented whenever a timer is run. */
unsigned timers_run;
-/* Address (if not 0) of EMACS_TIME to zero out if a SIGIO interrupt
+/* Address (if not 0) of struct timespec to zero out if a SIGIO interrupt
happens. */
-EMACS_TIME *input_available_clear_time;
+struct timespec *input_available_clear_time;
/* True means use SIGIO interrupts; false means use CBREAK mode.
Default is true if INTERRUPT_INPUT is defined. */
/* The time when Emacs started being idle. */
-static EMACS_TIME timer_idleness_start_time;
+static struct timespec timer_idleness_start_time;
/* After Emacs stops being idle, this saves the last value
of timer_idleness_start_time from when it was idle. */
-static EMACS_TIME timer_last_idleness_start_time;
+static struct timespec timer_last_idleness_start_time;
\f
/* Global variable declarations. */
static bool get_input_pending (int);
static bool readable_events (int);
-static Lisp_Object read_char_x_menu_prompt (ptrdiff_t, Lisp_Object *,
+static Lisp_Object read_char_x_menu_prompt (Lisp_Object,
Lisp_Object, bool *);
-static Lisp_Object read_char_minibuf_menu_prompt (int, ptrdiff_t,
- Lisp_Object *);
+static Lisp_Object read_char_minibuf_menu_prompt (int, Lisp_Object);
static Lisp_Object make_lispy_event (struct input_event *);
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
static Lisp_Object make_lispy_movement (struct frame *, Lisp_Object,
enum scroll_bar_part,
Lisp_Object, Lisp_Object,
Time);
-#endif
static Lisp_Object modify_event_symbol (ptrdiff_t, int, Lisp_Object,
Lisp_Object, const char *const *,
Lisp_Object *, ptrdiff_t);
static Lisp_Object make_lispy_switch_frame (Lisp_Object);
+static Lisp_Object make_lispy_focus_in (Lisp_Object);
+#ifdef HAVE_WINDOW_SYSTEM
+static Lisp_Object make_lispy_focus_out (Lisp_Object);
+#endif /* HAVE_WINDOW_SYSTEM */
static bool help_char_p (Lisp_Object);
static void save_getcjmp (sys_jmp_buf);
static void restore_getcjmp (sys_jmp_buf);
static Lisp_Object apply_modifiers (int, Lisp_Object);
static void clear_event (struct input_event *);
-static Lisp_Object restore_kboard_configuration (Lisp_Object);
+static void restore_kboard_configuration (int);
#ifdef USABLE_SIGIO
static void deliver_input_available_signal (int signo);
#endif
}
\f
-/* Add C to the echo string, if echoing is going on.
- C can be a character, which is printed prettily ("M-C-x" and all that
- jazz), or a symbol, whose name is printed. */
+/* Add C to the echo string, without echoing it immediately. C can be
+ a character, which is pretty-printed, or a symbol, whose name is
+ printed. */
static void
-echo_char (Lisp_Object c)
+echo_add_key (Lisp_Object c)
{
- if (current_kboard->immediate_echo)
- {
- int size = KEY_DESCRIPTION_SIZE + 100;
- char *buffer = alloca (size);
- char *ptr = buffer;
- Lisp_Object echo_string;
+ int size = KEY_DESCRIPTION_SIZE + 100;
+ char *buffer = alloca (size);
+ char *ptr = buffer;
+ Lisp_Object echo_string;
- echo_string = KVAR (current_kboard, echo_string);
+ echo_string = KVAR (current_kboard, echo_string);
- /* If someone has passed us a composite event, use its head symbol. */
- c = EVENT_HEAD (c);
+ /* If someone has passed us a composite event, use its head symbol. */
+ c = EVENT_HEAD (c);
- if (INTEGERP (c))
+ if (INTEGERP (c))
+ ptr = push_key_description (XINT (c), ptr);
+ else if (SYMBOLP (c))
+ {
+ Lisp_Object name = SYMBOL_NAME (c);
+ int nbytes = SBYTES (name);
+
+ if (size - (ptr - buffer) < nbytes)
{
- ptr = push_key_description (XINT (c), ptr);
+ int offset = ptr - buffer;
+ size = max (2 * size, size + nbytes);
+ buffer = alloca (size);
+ ptr = buffer + offset;
}
- else if (SYMBOLP (c))
- {
- Lisp_Object name = SYMBOL_NAME (c);
- int nbytes = SBYTES (name);
- if (size - (ptr - buffer) < nbytes)
- {
- int offset = ptr - buffer;
- size = max (2 * size, size + nbytes);
- buffer = alloca (size);
- ptr = buffer + offset;
- }
+ ptr += copy_text (SDATA (name), (unsigned char *) ptr, nbytes,
+ STRING_MULTIBYTE (name), 1);
+ }
- ptr += copy_text (SDATA (name), (unsigned char *) ptr, nbytes,
- STRING_MULTIBYTE (name), 1);
- }
+ if ((NILP (echo_string) || SCHARS (echo_string) == 0)
+ && help_char_p (c))
+ {
+ const char *text = " (Type ? for further options)";
+ int len = strlen (text);
- if ((NILP (echo_string) || SCHARS (echo_string) == 0)
- && help_char_p (c))
+ if (size - (ptr - buffer) < len)
{
- const char *text = " (Type ? for further options)";
- int len = strlen (text);
-
- if (size - (ptr - buffer) < len)
- {
- int offset = ptr - buffer;
- size += len;
- buffer = alloca (size);
- ptr = buffer + offset;
- }
-
- memcpy (ptr, text, len);
- ptr += len;
+ int offset = ptr - buffer;
+ size += len;
+ buffer = alloca (size);
+ ptr = buffer + offset;
}
- /* Replace a dash from echo_dash with a space, otherwise
- add a space at the end as a separator between keys. */
- if (STRINGP (echo_string)
- && SCHARS (echo_string) > 1)
- {
- Lisp_Object last_char, prev_char, idx;
+ memcpy (ptr, text, len);
+ ptr += len;
+ }
- idx = make_number (SCHARS (echo_string) - 2);
- prev_char = Faref (echo_string, idx);
+ /* Replace a dash from echo_dash with a space, otherwise add a space
+ at the end as a separator between keys. */
+ if (STRINGP (echo_string) && SCHARS (echo_string) > 1)
+ {
+ Lisp_Object last_char, prev_char, idx;
- idx = make_number (SCHARS (echo_string) - 1);
- last_char = Faref (echo_string, idx);
+ idx = make_number (SCHARS (echo_string) - 2);
+ prev_char = Faref (echo_string, idx);
- /* We test PREV_CHAR to make sure this isn't the echoing
- of a minus-sign. */
- if (XINT (last_char) == '-' && XINT (prev_char) != ' ')
- Faset (echo_string, idx, make_number (' '));
- else
- echo_string = concat2 (echo_string, build_string (" "));
- }
- else if (STRINGP (echo_string))
+ idx = make_number (SCHARS (echo_string) - 1);
+ last_char = Faref (echo_string, idx);
+
+ /* We test PREV_CHAR to make sure this isn't the echoing of a
+ minus-sign. */
+ if (XINT (last_char) == '-' && XINT (prev_char) != ' ')
+ Faset (echo_string, idx, make_number (' '));
+ else
echo_string = concat2 (echo_string, build_string (" "));
+ }
+ else if (STRINGP (echo_string) && SCHARS (echo_string) > 0)
+ echo_string = concat2 (echo_string, build_string (" "));
+
+ kset_echo_string
+ (current_kboard,
+ concat2 (echo_string, make_string (buffer, ptr - buffer)));
+}
- kset_echo_string
- (current_kboard,
- concat2 (echo_string, make_string (buffer, ptr - buffer)));
+/* Add C to the echo string, if echoing is going on. C can be a
+ character or a symbol. */
+static void
+echo_char (Lisp_Object c)
+{
+ if (current_kboard->immediate_echo)
+ {
+ echo_add_key (c);
echo_now ();
}
}
/* Temporarily add a dash to the end of the echo string if it's not
- empty, so that it serves as a mini-prompt for the very next character. */
+ empty, so that it serves as a mini-prompt for the very next
+ character. */
static void
echo_dash (void)
}
echoing = 1;
- message3_nolog (KVAR (current_kboard, echo_string),
- SBYTES (KVAR (current_kboard, echo_string)),
- STRING_MULTIBYTE (KVAR (current_kboard, echo_string)));
+ /* FIXME: Use call (Qmessage) so it can be advised (e.g. emacspeak). */
+ message3_nolog (KVAR (current_kboard, echo_string));
echoing = 0;
/* Record in what buffer we echoed, and from which kboard. */
return Qnil;
command_loop_level++;
- update_mode_lines = 1;
+ update_mode_lines = 17;
if (command_loop_level
- && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
+ && current_buffer != XBUFFER (XWINDOW (selected_window)->contents))
buffer = Fcurrent_buffer ();
else
buffer = Qnil;
return unbind_to (count, Qnil);
}
-Lisp_Object
+void
recursive_edit_unwind (Lisp_Object buffer)
{
if (BUFFERP (buffer))
Fset_buffer (buffer);
command_loop_level--;
- update_mode_lines = 1;
- return Qnil;
+ update_mode_lines = 18;
}
\f
from which further input is accepted. If F is non-nil, set its
KBOARD as the current keyboard.
- This function uses record_unwind_protect to return to the previous
+ This function uses record_unwind_protect_int to return to the previous
state later.
If Emacs is already in single_kboard mode, and F's keyboard is
else if (f != NULL)
current_kboard = FRAME_KBOARD (f);
single_kboard = 1;
- record_unwind_protect (restore_kboard_configuration,
- (was_locked ? Qt : Qnil));
+ record_unwind_protect_int (restore_kboard_configuration, was_locked);
}
#if 0 /* This function is not needed anymore. */
{
if (single_kboard)
push_kboard (current_kboard);
- record_unwind_protect (restore_kboard_configuration,
- (single_kboard ? Qt : Qnil));
+ record_unwind_protect_int (restore_kboard_configuration, single_kboard);
}
#endif
-static Lisp_Object
-restore_kboard_configuration (Lisp_Object was_locked)
+static void
+restore_kboard_configuration (int was_locked)
{
- if (NILP (was_locked))
- single_kboard = 0;
- else
+ single_kboard = was_locked;
+ if (was_locked)
{
struct kboard *prev = current_kboard;
- single_kboard = 1;
pop_kboard ();
/* The pop should not change the kboard. */
if (single_kboard && current_kboard != prev)
emacs_abort ();
}
- return Qnil;
}
\f
void
cmd_error_internal (Lisp_Object data, const char *context)
{
- struct frame *sf = SELECTED_FRAME ();
-
/* The immediate context is not interesting for Quits,
since they are asynchronous. */
if (EQ (XCAR (data), Qquit))
call3 (Vcommand_error_function, data,
context ? build_string (context) : empty_unibyte_string,
Vsignaling_function);
+
+ Vsignaling_function = Qnil;
+}
+
+DEFUN ("command-error-default-function", Fcommand_error_default_function,
+ Scommand_error_default_function, 3, 3, 0,
+ doc: /* Produce default output for unhandled error message.
+Default value of `command-error-function'. */)
+ (Lisp_Object data, Lisp_Object context, Lisp_Object signal)
+{
+ struct frame *sf = SELECTED_FRAME ();
+
+ CHECK_STRING (context);
+
/* If the window system or terminal frame hasn't been initialized
yet, or we're not interactive, write the message to stderr and exit. */
- else if (!sf->glyphs_initialized_p
+ if (!sf->glyphs_initialized_p
/* The initial frame is a special non-displaying frame. It
will be current in daemon mode when there are no frames
to display, and in non-daemon mode before the real frame
|| noninteractive)
{
print_error_message (data, Qexternal_debugging_output,
- context, Vsignaling_function);
+ SSDATA (context), signal);
Fterpri (Qexternal_debugging_output);
Fkill_emacs (make_number (-1));
}
message_log_maybe_newline ();
bitch_at_user ();
- print_error_message (data, Qt, context, Vsignaling_function);
+ print_error_message (data, Qt, SSDATA (context), signal);
}
-
- Vsignaling_function = Qnil;
+ return Qnil;
}
-\f
-Lisp_Object command_loop_1 (void);
+
static Lisp_Object command_loop_2 (Lisp_Object);
static Lisp_Object top_level_1 (Lisp_Object);
value to us. A value of nil means that command_loop_1 itself
returned due to end of file (or end of kbd macro). */
-Lisp_Object
+static Lisp_Object
command_loop_2 (Lisp_Object ignore)
{
register Lisp_Object val;
return Feval (Vtop_level, Qnil);
}
-Lisp_Object
+static Lisp_Object
top_level_1 (Lisp_Object ignore)
{
- /* On entry to the outer level, run the startup file */
+ /* On entry to the outer level, run the startup file. */
if (!NILP (Vtop_level))
internal_condition_case (top_level_2, Qerror, cmd_error);
else if (!NILP (Vpurify_flag))
- message ("Bare impure Emacs (standard Lisp code not loaded)");
+ message1 ("Bare impure Emacs (standard Lisp code not loaded)");
else
- message ("Bare Emacs (standard Lisp code not loaded)");
+ message1 ("Bare Emacs (standard Lisp code not loaded)");
return Qnil;
}
user_error ("No recursive edit is in progress");
}
\f
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
-
/* Restore mouse tracking enablement. See Ftrack_mouse for the only use
of this function. */
-static Lisp_Object
+static void
tracking_off (Lisp_Object old_value)
{
do_mouse_tracking = old_value;
get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW);
}
}
- return Qnil;
}
DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0,
#endif
bool ignore_mouse_drag_p;
-static FRAME_PTR
+static struct frame *
some_mouse_moved (void)
{
Lisp_Object tail, frame;
return 0;
}
-#endif /* HAVE_MOUSE || HAVE_GPM */
\f
/* This is the actual command reading loop,
sans error-handling encapsulation. */
static int read_key_sequence (Lisp_Object *, int, Lisp_Object,
- bool, bool, bool);
+ bool, bool, bool, bool);
void safe_run_hooks (Lisp_Object);
static void adjust_point_for_property (ptrdiff_t, bool);
-/* Cancel hourglass from protect_unwind.
- ARG is not used. */
-#ifdef HAVE_WINDOW_SYSTEM
-static Lisp_Object
-cancel_hourglass_unwind (Lisp_Object arg)
-{
- cancel_hourglass ();
- return Qnil;
-}
-#endif
-
/* The last boundary auto-added to buffer-undo-list. */
Lisp_Object last_undo_boundary;
+extern Lisp_Object Qregion_extract_function;
+
/* FIXME: This is wrong rather than test window-system, we should call
a new set-selection, which will then dispatch to x-set-selection, or
tty-set-selection, or w32-set-selection, ... */
Fkill_emacs (Qnil);
/* Make sure the current window's buffer is selected. */
- set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
+ set_buffer_internal (XBUFFER (XWINDOW (selected_window)->contents));
/* Display any malloc warning that just came out. Use while because
displaying one warning can cause another. */
Vdeactivate_mark = Qnil;
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
-
/* Don't ignore mouse movements for more than a single command
loop. (This flag is set in xdisp.c whenever the tool bar is
resized, because the resize moves text up or down, and would
generate false mouse drag events if we don't ignore them.) */
ignore_mouse_drag_p = 0;
-#endif
/* If minibuffer on and echo area in use,
wait a short time and redraw minibuffer. */
sit_for (Vminibuffer_message_timeout, 0, 2);
/* Clear the echo area. */
- message2 (0, 0, 0);
+ message1 (0);
safe_run_hooks (Qecho_area_clear_hook);
unbind_to (count, Qnil);
if (!NILP (Vquit_flag))
{
Vquit_flag = Qnil;
- Vunread_command_events = Fcons (make_number (quit_char), Qnil);
+ Vunread_command_events = list1 (make_number (quit_char));
}
}
/* Read next key sequence; i gets its length. */
i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
- Qnil, 0, 1, 1);
+ Qnil, 0, 1, 1, 0);
/* A filter may have run while we were reading the input. */
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
Fkill_emacs (Qnil);
- set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
+ set_buffer_internal (XBUFFER (XWINDOW (selected_window)->contents));
++num_input_keys;
{
struct buffer *b;
XWINDOW (selected_window)->force_start = 0;
- b = XBUFFER (XWINDOW (selected_window)->buffer);
+ b = XBUFFER (XWINDOW (selected_window)->contents);
BUF_BEG_UNCHANGED (b) = BUF_END_UNCHANGED (b) = 0;
}
prev_buffer = current_buffer;
prev_modiff = MODIFF;
last_point_position = PT;
- last_point_position_window = selected_window;
- XSETBUFFER (last_point_position_buffer, prev_buffer);
/* By default, we adjust point to a boundary of a region that
has such a property that should be treated intangible
already_adjusted = 0;
if (NILP (Vthis_command))
- {
- /* nil means key is undefined. */
- Lisp_Object keys = Fvector (i, keybuf);
- keys = Fkey_description (keys, Qnil);
- bitch_at_user ();
- message_with_string ("%s is undefined", keys, 0);
- kset_defining_kbd_macro (current_kboard, Qnil);
- update_mode_lines = 1;
- /* If this is a down-mouse event, don't reset prefix-arg;
- pass it to the command run by the up event. */
- if (EVENT_HAS_PARAMETERS (last_command_event))
- {
- Lisp_Object breakdown
- = parse_modifiers (EVENT_HEAD (last_command_event));
- int modifiers = XINT (XCAR (XCDR (breakdown)));
- if (!(modifiers & down_modifier))
- kset_prefix_arg (current_kboard, Qnil);
- }
- else
- kset_prefix_arg (current_kboard, Qnil);
- }
+ /* nil means key is undefined. */
+ call0 (Qundefined);
else
{
/* Here for a command that isn't executed directly. */
if (display_hourglass_p
&& NILP (Vexecuting_kbd_macro))
{
- record_unwind_protect (cancel_hourglass_unwind, Qnil);
+ record_unwind_protect_void (cancel_hourglass);
start_hourglass ();
}
#endif
= (EQ (undo, BVAR (current_buffer, undo_list))
? Qnil : BVAR (current_buffer, undo_list));
}
- Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil);
+ call1 (Qcommand_execute, Vthis_command);
#ifdef HAVE_WINDOW_SYSTEM
/* Do not check display_hourglass_p here, because
- Fcommand_execute could change it, but we should cancel
+ `command-execute' could change it, but we should cancel
hourglass cursor anyway.
But don't cancel the hourglass within a macro
just because a command in the macro finishes. */
&& NILP (Fmemq (Vthis_command,
Vselection_inhibit_update_commands)))
{
- ptrdiff_t beg =
- XINT (Fmarker_position (BVAR (current_buffer, mark)));
- ptrdiff_t end = PT;
- if (beg < end)
- call2 (Qx_set_selection, QPRIMARY,
- make_buffer_string (beg, end, 0));
- else if (beg > end)
- call2 (Qx_set_selection, QPRIMARY,
- make_buffer_string (end, beg, 0));
- /* Don't set empty selections. */
+ Lisp_Object txt
+ = call1 (Fsymbol_value (Qregion_extract_function), Qnil);
+ if (XINT (Flength (txt)) > 0)
+ /* Don't set empty selections. */
+ call2 (Qx_set_selection, QPRIMARY, txt);
}
if (current_buffer != prev_buffer || MODIFF != prev_modiff)
cluster to prevent automatic composition. To recover
the automatic composition, we must update the
display. */
- windows_or_buffers_changed++;
+ windows_or_buffers_changed = 21;
if (!already_adjusted)
adjust_point_for_property (last_point_position,
MODIFF != prev_modiff);
}
}
+Lisp_Object
+read_menu_command (void)
+{
+ Lisp_Object keybuf[30];
+ ptrdiff_t count = SPECPDL_INDEX ();
+ int i;
+
+ /* We don't want to echo the keystrokes while navigating the
+ menus. */
+ specbind (Qecho_keystrokes, make_number (0));
+
+ i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
+ Qnil, 0, 1, 1, 1);
+
+ unbind_to (count, Qnil);
+
+ if (! FRAME_LIVE_P (XFRAME (selected_frame)))
+ Fkill_emacs (Qnil);
+ if (i == 0 || i == -1)
+ return Qt;
+
+ return read_key_sequence_cmd;
+}
+
/* Adjust point to a boundary of a region that has such a property
that should be treated intangible. For the moment, we check
`composition', `display' and `invisible' properties.
than skip both boundaries. However, this code
also stops anywhere in a non-sticky text-property,
which breaks (e.g.) Org mode. */
- && (val = get_pos_property (make_number (end),
- Qinvisible, Qnil),
+ && (val = Fget_pos_property (make_number (end),
+ Qinvisible, Qnil),
TEXT_PROP_MEANS_INVISIBLE (val))
#endif
&& !NILP (val = get_char_property_and_overlay
}
while (beg > BEGV
#if 0
- && (val = get_pos_property (make_number (beg),
- Qinvisible, Qnil),
+ && (val = Fget_pos_property (make_number (beg),
+ Qinvisible, Qnil),
TEXT_PROP_MEANS_INVISIBLE (val))
#endif
&& !NILP (val = get_char_property_and_overlay
to the other end would mean moving backwards and thus
could lead to an infinite loop. */
;
- else if (val = get_pos_property (make_number (PT),
- Qinvisible, Qnil),
+ else if (val = Fget_pos_property (make_number (PT),
+ Qinvisible, Qnil),
TEXT_PROP_MEANS_INVISIBLE (val)
- && (val = get_pos_property
- (make_number (PT == beg ? end : beg),
- Qinvisible, Qnil),
+ && (val = (Fget_pos_property
+ (make_number (PT == beg ? end : beg),
+ Qinvisible, Qnil)),
!TEXT_PROP_MEANS_INVISIBLE (val)))
(check_composition = check_display = 1,
SET_PT (PT == beg ? end : beg));
= CONSP (Vinhibit_quit) ? XCAR (Vinhibit_quit) : Vinhibit_quit;
Lisp_Object fun = CONSP (Vinhibit_quit) ? XCDR (Vinhibit_quit) : Qnil;
Lisp_Object args[4];
- args[0] = build_string ("Error in %s (%s): %S");
+ args[0] = build_string ("Error in %s (%S): %S");
args[1] = hook;
args[2] = fun;
args[3] = error_data;
static struct atimer *poll_timer;
-/* Poll for input, so that we catch a C-g if it comes in. This
- function is called from x_make_frame_visible, see comment
- there. */
-
+/* Poll for input, so that we catch a C-g if it comes in. */
void
poll_for_input_1 (void)
{
/* If poll timer doesn't exist, are we need one with
a different interval, start a new one. */
if (poll_timer == NULL
- || EMACS_SECS (poll_timer->interval) != polling_period)
+ || poll_timer->interval.tv_sec != polling_period)
{
time_t period = max (1, min (polling_period, TYPE_MAXIMUM (time_t)));
- EMACS_TIME interval = make_emacs_time (period, 0);
+ struct timespec interval = make_timespec (period, 0);
if (poll_timer)
cancel_atimer (poll_timer);
\f
/* Apply the control modifier to CHARACTER. */
+#ifndef HAVE_NTGUI
+static
+#endif
int
make_ctrl_char (int c)
{
return;
}
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
if (!noninteractive && STRINGP (help))
{
/* The mouse-fixup-help-message Lisp function can call
This causes trouble if we are trying to read a mouse motion
event (i.e., if we are inside a `track-mouse' form), so we
restore the mouse_moved flag. */
- FRAME_PTR f = NILP (do_mouse_tracking) ? NULL : some_mouse_moved ();
+ struct frame *f = NILP (do_mouse_tracking) ? NULL : some_mouse_moved ();
help = call1 (Qmouse_fixup_help_message, help);
if (f)
f->mouse_moved = 1;
}
-#endif
if (STRINGP (help) || NILP (help))
{
/* Input of single characters from keyboard */
static Lisp_Object kbd_buffer_get_event (KBOARD **kbp, bool *used_mouse_menu,
- EMACS_TIME *end_time);
+ struct timespec *end_time);
static void record_char (Lisp_Object c);
static Lisp_Object help_form_saved_window_configs;
-static Lisp_Object
-read_char_help_form_unwind (Lisp_Object arg)
+static void
+read_char_help_form_unwind (void)
{
Lisp_Object window_config = XCAR (help_form_saved_window_configs);
help_form_saved_window_configs = XCDR (help_form_saved_window_configs);
if (!NILP (window_config))
Fset_window_configuration (window_config);
- return Qnil;
}
#define STOP_POLLING \
do { if (polling_stopped_here) start_polling (); \
polling_stopped_here = 0; } while (0)
-/* read a character from the keyboard; call the redisplay if needed */
+static Lisp_Object
+read_event_from_main_queue (struct timespec *end_time,
+ sys_jmp_buf local_getcjmp,
+ bool *used_mouse_menu)
+{
+ Lisp_Object c = Qnil;
+ sys_jmp_buf save_jump;
+ KBOARD *kb IF_LINT (= NULL);
+
+ start:
+
+ /* Read from the main queue, and if that gives us something we can't use yet,
+ we put it on the appropriate side queue and try again. */
+
+ if (end_time && timespec_cmp (*end_time, current_timespec ()) <= 0)
+ return c;
+
+ /* Actually read a character, waiting if necessary. */
+ save_getcjmp (save_jump);
+ restore_getcjmp (local_getcjmp);
+ if (!end_time)
+ timer_start_idle ();
+ c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time);
+ restore_getcjmp (save_jump);
+
+ if (! NILP (c) && (kb != current_kboard))
+ {
+ Lisp_Object last = KVAR (kb, kbd_queue);
+ if (CONSP (last))
+ {
+ while (CONSP (XCDR (last)))
+ last = XCDR (last);
+ if (!NILP (XCDR (last)))
+ emacs_abort ();
+ }
+ if (!CONSP (last))
+ kset_kbd_queue (kb, list1 (c));
+ else
+ XSETCDR (last, list1 (c));
+ kb->kbd_queue_has_data = 1;
+ c = Qnil;
+ if (single_kboard)
+ goto start;
+ current_kboard = kb;
+ /* This is going to exit from read_char
+ so we had better get rid of this frame's stuff. */
+ return make_number (-2);
+ }
+
+ /* Terminate Emacs in batch mode if at eof. */
+ if (noninteractive && INTEGERP (c) && XINT (c) < 0)
+ Fkill_emacs (make_number (1));
+
+ if (INTEGERP (c))
+ {
+ /* Add in any extra modifiers, where appropriate. */
+ if ((extra_keyboard_modifiers & CHAR_CTL)
+ || ((extra_keyboard_modifiers & 0177) < ' '
+ && (extra_keyboard_modifiers & 0177) != 0))
+ XSETINT (c, make_ctrl_char (XINT (c)));
+
+ /* Transfer any other modifier bits directly from
+ extra_keyboard_modifiers to c. Ignore the actual character code
+ in the low 16 bits of extra_keyboard_modifiers. */
+ XSETINT (c, XINT (c) | (extra_keyboard_modifiers & ~0xff7f & ~CHAR_CTL));
+ }
+
+ return c;
+}
+
+
+
+/* Like `read_event_from_main_queue' but applies keyboard-coding-system
+ to tty input. */
+static Lisp_Object
+read_decoded_event_from_main_queue (struct timespec *end_time,
+ sys_jmp_buf local_getcjmp,
+ Lisp_Object prev_event,
+ bool *used_mouse_menu)
+{
+#define MAX_ENCODED_BYTES 16
+ Lisp_Object events[MAX_ENCODED_BYTES];
+ int n = 0;
+ while (true)
+ {
+ Lisp_Object nextevt
+ = read_event_from_main_queue (end_time, local_getcjmp,
+ used_mouse_menu);
+#ifdef WINDOWSNT
+ /* w32_console already returns decoded events. It either reads
+ Unicode characters from the Windows keyboard input, or
+ converts characters encoded in the current codepage into
+ Unicode. See w32inevt.c:key_event, near its end. */
+ return nextevt;
+#else
+ struct frame *frame = XFRAME (selected_frame);
+ struct terminal *terminal = frame->terminal;
+ if (!((FRAME_TERMCAP_P (frame) || FRAME_MSDOS_P (frame))
+ /* Don't apply decoding if we're just reading a raw event
+ (e.g. reading bytes sent by the xterm to specify the position
+ of a mouse click). */
+ && (!EQ (prev_event, Qt))
+ && (TERMINAL_KEYBOARD_CODING (terminal)->common_flags
+ & CODING_REQUIRE_DECODING_MASK)))
+ return nextevt; /* No decoding needed. */
+ else
+ {
+ int meta_key = terminal->display_info.tty->meta_key;
+ eassert (n < MAX_ENCODED_BYTES);
+ events[n++] = nextevt;
+ if (NATNUMP (nextevt)
+ && XINT (nextevt) < (meta_key == 1 ? 0x80 : 0x100))
+ { /* An encoded byte sequence, let's try to decode it. */
+ struct coding_system *coding
+ = TERMINAL_KEYBOARD_CODING (terminal);
+ unsigned char *src = alloca (n);
+ int i;
+ for (i = 0; i < n; i++)
+ src[i] = XINT (events[i]);
+ if (meta_key != 2)
+ for (i = 0; i < n; i++)
+ src[i] &= ~0x80;
+ coding->destination = alloca (n * 4);
+ coding->dst_bytes = n * 4;
+ decode_coding_c_string (coding, src, n, Qnil);
+ eassert (coding->produced_char <= n);
+ if (coding->produced_char == 0)
+ { /* The encoded sequence is incomplete. */
+ if (n < MAX_ENCODED_BYTES) /* Avoid buffer overflow. */
+ continue; /* Read on! */
+ }
+ else
+ {
+ const unsigned char *p = coding->destination;
+ eassert (coding->carryover_bytes == 0);
+ n = 0;
+ while (n < coding->produced_char)
+ events[n++] = make_number (STRING_CHAR_ADVANCE (p));
+ }
+ }
+ /* Now `events' should hold decoded events.
+ Normally, n should be equal to 1, but better not rely on it.
+ We can only return one event here, so return the first we
+ had and keep the others (if any) for later. */
+ while (n > 1)
+ Vunread_command_events
+ = Fcons (events[--n], Vunread_command_events);
+ return events[0];
+ }
+#endif
+ }
+}
+
+/* Read a character from the keyboard; call the redisplay if needed. */
/* commandflag 0 means do not autosave, but do redisplay.
-1 means do not redisplay, but do autosave.
+ -2 means do neither.
1 means do both. */
-/* The arguments MAPS and NMAPS are for menu prompting.
- MAPS is an array of keymaps; NMAPS is the length of MAPS.
+/* The arguments MAP is for menu prompting. MAP is a keymap.
PREV_EVENT is the previous input event, or nil if we are reading
the first event of a key sequence (or not reading a key sequence).
Value is -2 when we find input on another keyboard. A second call
to read_char will read it.
- If END_TIME is non-null, it is a pointer to an EMACS_TIME
+ If END_TIME is non-null, it is a pointer to a struct timespec
specifying the maximum time to wait until. If no input arrives by
that time, stop waiting and return nil.
Value is t if we showed a menu and the user rejected it. */
Lisp_Object
-read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
+read_char (int commandflag, Lisp_Object map,
Lisp_Object prev_event,
- bool *used_mouse_menu, EMACS_TIME *end_time)
+ bool *used_mouse_menu, struct timespec *end_time)
{
Lisp_Object c;
ptrdiff_t jmpcount;
goto reread_first;
}
- /* if redisplay was requested */
+ /* If redisplay was requested. */
if (commandflag >= 0)
{
bool echo_current = EQ (echo_message_buffer, echo_area_buffer[0]);
user-visible, such as X selection_request events. */
if (input_pending
|| detect_input_pending_run_timers (0))
- swallow_events (0); /* may clear input_pending */
+ swallow_events (0); /* May clear input_pending. */
/* Redisplay if no pending input. */
while (!input_pending)
if (/* There currently is something in the echo area. */
!NILP (echo_area_buffer[0])
- && (/* And it's either not from echoing. */
- !EQ (echo_area_buffer[0], echo_message_buffer)
- /* Or it's an echo from a different kboard. */
- || echo_kboard != current_kboard
+ && (/* It's an echo from a different kboard. */
+ echo_kboard != current_kboard
/* Or we explicitly allow overwriting whatever there is. */
|| ok_to_echo_at_next_pause == NULL))
cancel_echoing ();
menu prompting. If EVENT_HAS_PARAMETERS then we are reading
after a mouse event so don't try a minibuf menu. */
c = Qnil;
- if (nmaps > 0 && INTERACTIVE
+ if (KEYMAPP (map) && INTERACTIVE
&& !NILP (prev_event) && ! EVENT_HAS_PARAMETERS (prev_event)
/* Don't bring up a menu if we already have another event. */
&& NILP (Vunread_command_events)
&& !detect_input_pending_run_timers (0))
{
- c = read_char_minibuf_menu_prompt (commandflag, nmaps, maps);
+ c = read_char_minibuf_menu_prompt (commandflag, map);
if (INTEGERP (c) && XINT (c) == -2)
return c; /* wrong_kboard_jmpbuf */
emacs_abort ();
}
if (!CONSP (last))
- kset_kbd_queue (kb, Fcons (c, Qnil));
+ kset_kbd_queue (kb, list1 (c));
else
- XSETCDR (last, Fcons (c, Qnil));
+ XSETCDR (last, list1 (c));
kb->kbd_queue_has_data = 1;
current_kboard = kb;
/* This is going to exit from read_char
/* Maybe auto save due to number of keystrokes. */
- if (commandflag != 0
+ if (commandflag != 0 && commandflag != -2
&& auto_save_interval > 0
&& num_nonmacro_input_events - last_auto_save > max (auto_save_interval, 20)
&& !detect_input_pending_run_timers (0))
because the recursive call of read_char in read_char_minibuf_menu_prompt
does not pass on any keymaps. */
- if (nmaps > 0 && INTERACTIVE
+ if (KEYMAPP (map) && INTERACTIVE
&& !NILP (prev_event)
&& EVENT_HAS_PARAMETERS (prev_event)
&& !EQ (XCAR (prev_event), Qmenu_bar)
/* Don't bring up a menu if we already have another event. */
&& NILP (Vunread_command_events))
{
- c = read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu);
+ c = read_char_x_menu_prompt (map, prev_event, used_mouse_menu);
/* Now that we have read an event, Emacs is not idle. */
if (!end_time)
9 at 200k, 11 at 300k, and 12 at 500k. It is 15 at 1 meg. */
/* Auto save if enough time goes by without input. */
- if (commandflag != 0
+ if (commandflag != 0 && commandflag != -2
&& num_nonmacro_input_events > last_auto_save
&& INTEGERP (Vauto_save_timeout)
&& XINT (Vauto_save_timeout) > 0)
{
Lisp_Object tem0;
- EMACS_INT timeout = (delay_level
- * min (XFASTINT (Vauto_save_timeout) / 4,
- MOST_POSITIVE_FIXNUM / delay_level));
+ EMACS_INT timeout = XFASTINT (Vauto_save_timeout);
+
+ timeout = min (timeout, MOST_POSITIVE_FIXNUM / delay_level * 4);
+ timeout = delay_level * timeout / 4;
save_getcjmp (save_jump);
restore_getcjmp (local_getcjmp);
tem0 = sit_for (make_number (timeout), 1, 1);
STOP_POLLING;
- /* Finally, we read from the main queue,
- and if that gives us something we can't use yet, we put it on the
- appropriate side queue and try again. */
-
if (NILP (c))
{
- KBOARD *kb IF_LINT (= NULL);
-
- if (end_time && EMACS_TIME_LE (*end_time, current_emacs_time ()))
- goto exit;
-
- /* Actually read a character, waiting if necessary. */
- save_getcjmp (save_jump);
- restore_getcjmp (local_getcjmp);
- if (!end_time)
- timer_start_idle ();
- c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time);
- restore_getcjmp (save_jump);
-
- if (! NILP (c) && (kb != current_kboard))
- {
- Lisp_Object last = KVAR (kb, kbd_queue);
- if (CONSP (last))
- {
- while (CONSP (XCDR (last)))
- last = XCDR (last);
- if (!NILP (XCDR (last)))
- emacs_abort ();
- }
- if (!CONSP (last))
- kset_kbd_queue (kb, Fcons (c, Qnil));
- else
- XSETCDR (last, Fcons (c, Qnil));
- kb->kbd_queue_has_data = 1;
- c = Qnil;
- if (single_kboard)
- goto wrong_kboard;
- current_kboard = kb;
+ c = read_decoded_event_from_main_queue (end_time, local_getcjmp,
+ prev_event, used_mouse_menu);
+ if (end_time && timespec_cmp (*end_time, current_timespec ()) <= 0)
+ goto exit;
+ if (EQ (c, make_number (-2)))
+ {
/* This is going to exit from read_char
so we had better get rid of this frame's stuff. */
UNGCPRO;
- return make_number (-2);
- }
- }
-
- /* Terminate Emacs in batch mode if at eof. */
- if (noninteractive && INTEGERP (c) && XINT (c) < 0)
- Fkill_emacs (make_number (1));
-
- if (INTEGERP (c))
- {
- /* Add in any extra modifiers, where appropriate. */
- if ((extra_keyboard_modifiers & CHAR_CTL)
- || ((extra_keyboard_modifiers & 0177) < ' '
- && (extra_keyboard_modifiers & 0177) != 0))
- XSETINT (c, make_ctrl_char (XINT (c)));
-
- /* Transfer any other modifier bits directly from
- extra_keyboard_modifiers to c. Ignore the actual character code
- in the low 16 bits of extra_keyboard_modifiers. */
- XSETINT (c, XINT (c) | (extra_keyboard_modifiers & ~0xff7f & ~CHAR_CTL));
- }
+ return c;
+ }
+ }
non_reread:
{
struct buffer *prev_buffer = current_buffer;
last_input_event = c;
- Fcommand_execute (tem, Qnil, Fvector (1, &last_input_event), Qt);
+ call4 (Qcommand_execute, tem, Qnil, Fvector (1, &last_input_event), Qt);
if (CONSP (c) && EQ (XCAR (c), Qselect_window) && !end_time)
/* We stopped being idle for this event; undo that. This
if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar))
{
/* Change menu-bar to (menu-bar) as the event "position". */
- POSN_SET_POSN (EVENT_START (c), Fcons (posn, Qnil));
+ POSN_SET_POSN (EVENT_START (c), list1 (posn));
also_record = c;
Vunread_command_events = Fcons (c, Vunread_command_events);
/* If we are not reading a key sequence,
never use the echo area. */
- if (maps == 0)
+ if (!KEYMAPP (map))
{
specbind (Qinput_method_use_echo_area, Qt);
}
last_input_event = c;
num_input_events++;
- /* Process the help character specially if enabled */
+ /* Process the help character specially if enabled. */
if (!NILP (Vhelp_form) && help_char_p (c))
{
ptrdiff_t count = SPECPDL_INDEX ();
help_form_saved_window_configs
= Fcons (Fcurrent_window_configuration (Qnil),
help_form_saved_window_configs);
- record_unwind_protect (read_char_help_form_unwind, Qnil);
+ record_unwind_protect_void (read_char_help_form_unwind);
call0 (Qhelp_form_show);
cancel_echoing ();
do
{
- c = read_char (0, 0, 0, Qnil, 0, NULL);
+ c = read_char (0, Qnil, Qnil, 0, NULL);
if (EVENT_HAS_PARAMETERS (c)
&& EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_click))
XSETCAR (help_form_saved_window_configs, Qnil);
}
while (BUFFERP (c));
- /* Remove the help from the frame */
+ /* Remove the help from the frame. */
unbind_to (count, Qnil);
redisplay ();
{
cancel_echoing ();
do
- c = read_char (0, 0, 0, Qnil, 0, NULL);
+ c = read_char (0, Qnil, Qnil, 0, NULL);
while (BUFFERP (c));
}
}
/* Record this character as part of the current key. */
add_command_key (c);
- /* Re-reading in the middle of a command */
+ /* Re-reading in the middle of a command. */
last_input_event = c;
num_input_events++;
}
return 1;
}
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
if (!(flags & READABLE_EVENTS_IGNORE_SQUEEZABLES)
&& !NILP (do_mouse_tracking) && some_mouse_moved ())
return 1;
-#endif
if (single_kboard)
{
if (current_kboard->kbd_queue_has_data)
if (single_kboard && kb != current_kboard)
{
kset_kbd_queue
- (kb, Fcons (make_lispy_switch_frame (event->frame_or_window),
- Fcons (make_number (c), Qnil)));
+ (kb, list2 (make_lispy_switch_frame (event->frame_or_window),
+ make_number (c)));
kb->kbd_queue_has_data = 1;
for (sp = kbd_fetch_ptr; sp != kbd_store_ptr; sp++)
{
Vlast_event_frame = focus;
}
- last_event_timestamp = event->timestamp;
-
handle_interrupt (0);
return;
}
static Lisp_Object
kbd_buffer_get_event (KBOARD **kbp,
bool *used_mouse_menu,
- EMACS_TIME *end_time)
+ struct timespec *end_time)
{
Lisp_Object obj;
if (kbd_fetch_ptr != kbd_store_ptr)
break;
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
if (!NILP (do_mouse_tracking) && some_mouse_moved ())
break;
-#endif
/* If the quit flag is set, then read_char will return
quit_char, so that counts as "available input." */
#endif
if (kbd_fetch_ptr != kbd_store_ptr)
break;
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
if (!NILP (do_mouse_tracking) && some_mouse_moved ())
break;
-#endif
if (end_time)
{
- EMACS_TIME now = current_emacs_time ();
- if (EMACS_TIME_LE (*end_time, now))
+ struct timespec now = current_timespec ();
+ if (timespec_cmp (*end_time, now) <= 0)
return Qnil; /* Finished waiting. */
else
{
- EMACS_TIME duration = sub_emacs_time (*end_time, now);
- wait_reading_process_output (min (EMACS_SECS (duration),
+ struct timespec duration = timespec_sub (*end_time, now);
+ wait_reading_process_output (min (duration.tv_sec,
WAIT_READING_MAX),
- EMACS_NSECS (duration),
+ duration.tv_nsec,
-1, 1, Qnil, NULL, 0);
}
}
else
- wait_reading_process_output (0, 0, -1, 1, Qnil, NULL, 0);
+ {
+ bool do_display = true;
+
+ if (FRAME_TERMCAP_P (SELECTED_FRAME ()))
+ {
+ struct tty_display_info *tty = CURTTY ();
+
+ /* When this TTY is displaying a menu, we must prevent
+ any redisplay, because we modify the frame's glyph
+ matrix behind the back of the display engine. */
+ if (tty->showing_menu)
+ do_display = false;
+ }
+
+ wait_reading_process_output (0, 0, -1, do_display, Qnil, NULL, 0);
+ }
if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
gobble_input ();
? kbd_fetch_ptr
: kbd_buffer);
- last_event_timestamp = event->timestamp;
-
*kbp = event_to_kboard (event);
if (*kbp == 0)
*kbp = current_kboard; /* Better than returning null ptr? */
else if (event->kind == NS_TEXT_EVENT)
{
if (event->code == KEY_NS_PUT_WORKING_TEXT)
- obj = Fcons (intern ("ns-put-working-text"), Qnil);
+ obj = list1 (intern ("ns-put-working-text"));
else
- obj = Fcons (intern ("ns-unput-working-text"), Qnil);
+ obj = list1 (intern ("ns-unput-working-text"));
kbd_fetch_ptr = event + 1;
if (used_mouse_menu)
*used_mouse_menu = 1;
else if (event->kind == DELETE_WINDOW_EVENT)
{
/* Make an event (delete-frame (FRAME)). */
- obj = Fcons (event->frame_or_window, Qnil);
- obj = Fcons (Qdelete_frame, Fcons (obj, Qnil));
+ obj = list2 (Qdelete_frame, list1 (event->frame_or_window));
kbd_fetch_ptr = event + 1;
}
#endif
else if (event->kind == ICONIFY_EVENT)
{
/* Make an event (iconify-frame (FRAME)). */
- obj = Fcons (event->frame_or_window, Qnil);
- obj = Fcons (Qiconify_frame, Fcons (obj, Qnil));
+ obj = list2 (Qiconify_frame, list1 (event->frame_or_window));
kbd_fetch_ptr = event + 1;
}
else if (event->kind == DEICONIFY_EVENT)
{
/* Make an event (make-frame-visible (FRAME)). */
- obj = Fcons (event->frame_or_window, Qnil);
- obj = Fcons (Qmake_frame_visible, Fcons (obj, Qnil));
+ obj = list2 (Qmake_frame_visible, list1 (event->frame_or_window));
kbd_fetch_ptr = event + 1;
}
#endif
#ifdef HAVE_NTGUI
else if (event->kind == LANGUAGE_CHANGE_EVENT)
{
- /* Make an event (language-change (FRAME CODEPAGE LANGUAGE-ID)). */
- obj = Fcons (Qlanguage_change,
- list3 (event->frame_or_window,
- make_number (event->code),
- make_number (event->modifiers)));
+ /* Make an event (language-change FRAME CODEPAGE LANGUAGE-ID). */
+ obj = list4 (Qlanguage_change,
+ event->frame_or_window,
+ make_number (event->code),
+ make_number (event->modifiers));
kbd_fetch_ptr = event + 1;
}
#endif
+#ifdef USE_FILE_NOTIFY
+ else if (event->kind == FILE_NOTIFY_EVENT)
+ {
+#ifdef HAVE_W32NOTIFY
+ /* Make an event (file-notify (DESCRIPTOR ACTION FILE) CALLBACK). */
+ obj = list3 (Qfile_notify,
+ list3 (make_number (event->code),
+ XCAR (event->arg),
+ XCDR (event->arg)),
+ event->frame_or_window);
+#else
+ obj = make_lispy_event (event);
+#endif
+ kbd_fetch_ptr = event + 1;
+ }
+#endif /* USE_FILE_NOTIFY */
else if (event->kind == SAVE_SESSION_EVENT)
{
- obj = Fcons (Qsave_session, Fcons (event->arg, Qnil));
+ obj = list2 (Qsave_session, event->arg);
kbd_fetch_ptr = event + 1;
}
/* Just discard these, by returning nil.
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;
+ 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 (
+#ifdef HAVE_X11
+ ! NILP (event->arg)
+ &&
+#endif
+ !EQ (frame, internal_last_event_frame)
+ && !EQ (frame, selected_frame))
+ obj = make_lispy_switch_frame (frame);
+ else
+ obj = make_lispy_focus_in (frame);
+
+ internal_last_event_frame = frame;
+ kbd_fetch_ptr = event + 1;
+ }
+ else if (event->kind == FOCUS_OUT_EVENT)
+ {
+#ifdef HAVE_WINDOW_SYSTEM
+
+ Display_Info *di;
+ Lisp_Object frame = event->frame_or_window;
+ bool focused = false;
+
+ for (di = x_display_list; di && ! focused; di = di->next)
+ focused = di->x_highlight_frame != 0;
+
+ if (!focused)
+ obj = make_lispy_focus_out (frame);
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
+ kbd_fetch_ptr = event + 1;
+ }
#ifdef HAVE_DBUS
else if (event->kind == DBUS_EVENT)
{
}
}
}
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
/* Try generating a mouse motion event. */
else if (!NILP (do_mouse_tracking) && some_mouse_moved ())
{
- FRAME_PTR f = some_mouse_moved ();
+ struct frame *f = some_mouse_moved ();
Lisp_Object bar_window;
enum scroll_bar_part part;
Lisp_Object x, y;
if (!NILP (x) && NILP (obj))
obj = make_lispy_movement (f, bar_window, part, x, y, t);
}
-#endif /* HAVE_MOUSE || HAVE GPM */
else
/* We were promised by the above while loop that there was
something for us to read! */
else
kbd_fetch_ptr++;
- /* X wants last_event_timestamp for selection ownership. */
- last_event_timestamp = copy.timestamp;
input_pending = readable_events (0);
x_handle_selection_event (©);
#else
static void
timer_start_idle (void)
{
- Lisp_Object timers;
-
/* If we are already in the idle state, do nothing. */
- if (EMACS_TIME_VALID_P (timer_idleness_start_time))
+ if (timespec_valid_p (timer_idleness_start_time))
return;
- timer_idleness_start_time = current_emacs_time ();
+ timer_idleness_start_time = current_timespec ();
timer_last_idleness_start_time = timer_idleness_start_time;
/* Mark all idle-time timers as once again candidates for running. */
- for (timers = Vtimer_idle_list; CONSP (timers); timers = XCDR (timers))
- {
- Lisp_Object timer;
-
- timer = XCAR (timers);
-
- if (!VECTORP (timer) || ASIZE (timer) != 9)
- continue;
- ASET (timer, 0, Qnil);
- }
+ call0 (intern ("internal-timer-start-idle"));
}
/* Record that Emacs is no longer idle, so stop running idle-time timers. */
static void
timer_stop_idle (void)
{
- timer_idleness_start_time = invalid_emacs_time ();
+ timer_idleness_start_time = invalid_timespec ();
}
/* Resume idle timer from last idle start time. */
static void
timer_resume_idle (void)
{
- if (EMACS_TIME_VALID_P (timer_idleness_start_time))
+ if (timespec_valid_p (timer_idleness_start_time))
return;
timer_idleness_start_time = timer_last_idleness_start_time;
/* Return true if TIMER is a valid timer, placing its value into *RESULT. */
static bool
-decode_timer (Lisp_Object timer, EMACS_TIME *result)
+decode_timer (Lisp_Object timer, struct timespec *result)
{
Lisp_Object *vector;
In that case we return 0 to indicate that a new timer_check_2 call
should be done. */
-static EMACS_TIME
+static struct timespec
timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
{
- EMACS_TIME nexttime;
- EMACS_TIME now;
- EMACS_TIME idleness_now;
+ struct timespec nexttime;
+ struct timespec now;
+ struct timespec idleness_now;
Lisp_Object chosen_timer;
struct gcpro gcpro1;
- nexttime = invalid_emacs_time ();
+ nexttime = invalid_timespec ();
chosen_timer = Qnil;
GCPRO1 (chosen_timer);
if (CONSP (timers) || CONSP (idle_timers))
{
- now = current_emacs_time ();
- idleness_now = (EMACS_TIME_VALID_P (timer_idleness_start_time)
- ? sub_emacs_time (now, timer_idleness_start_time)
- : make_emacs_time (0, 0));
+ now = current_timespec ();
+ idleness_now = (timespec_valid_p (timer_idleness_start_time)
+ ? timespec_sub (now, timer_idleness_start_time)
+ : make_timespec (0, 0));
}
while (CONSP (timers) || CONSP (idle_timers))
{
Lisp_Object timer = Qnil, idle_timer = Qnil;
- EMACS_TIME timer_time, idle_timer_time;
- EMACS_TIME difference;
- EMACS_TIME timer_difference = invalid_emacs_time ();
- EMACS_TIME idle_timer_difference = invalid_emacs_time ();
+ struct timespec timer_time, idle_timer_time;
+ struct timespec difference;
+ struct timespec timer_difference = invalid_timespec ();
+ struct timespec idle_timer_difference = invalid_timespec ();
bool ripe, timer_ripe = 0, idle_timer_ripe = 0;
/* Set TIMER and TIMER_DIFFERENCE
continue;
}
- timer_ripe = EMACS_TIME_LE (timer_time, now);
+ timer_ripe = timespec_cmp (timer_time, now) <= 0;
timer_difference = (timer_ripe
- ? sub_emacs_time (now, timer_time)
- : sub_emacs_time (timer_time, now));
+ ? timespec_sub (now, timer_time)
+ : timespec_sub (timer_time, now));
}
/* Likewise for IDLE_TIMER and IDLE_TIMER_DIFFERENCE
continue;
}
- idle_timer_ripe = EMACS_TIME_LE (idle_timer_time, idleness_now);
- idle_timer_difference =
- (idle_timer_ripe
- ? sub_emacs_time (idleness_now, idle_timer_time)
- : sub_emacs_time (idle_timer_time, idleness_now));
+ idle_timer_ripe = timespec_cmp (idle_timer_time, idleness_now) <= 0;
+ idle_timer_difference
+ = (idle_timer_ripe
+ ? timespec_sub (idleness_now, idle_timer_time)
+ : timespec_sub (idle_timer_time, idleness_now));
}
/* Decide which timer is the next timer,
and set CHOSEN_TIMER, DIFFERENCE, and RIPE accordingly.
Also step down the list where we found that timer. */
- if (EMACS_TIME_VALID_P (timer_difference)
- && (! EMACS_TIME_VALID_P (idle_timer_difference)
+ if (timespec_valid_p (timer_difference)
+ && (! timespec_valid_p (idle_timer_difference)
|| idle_timer_ripe < timer_ripe
|| (idle_timer_ripe == timer_ripe
- && (timer_ripe
- ? EMACS_TIME_LT (idle_timer_difference,
+ && ((timer_ripe
+ ? timespec_cmp (idle_timer_difference,
timer_difference)
- : EMACS_TIME_LT (timer_difference,
- idle_timer_difference)))))
+ : timespec_cmp (timer_difference,
+ idle_timer_difference))
+ < 0))))
{
chosen_timer = timer;
timers = XCDR (timers);
return 0 to indicate that. */
}
- nexttime = make_emacs_time (0, 0);
+ nexttime = make_timespec (0, 0);
break;
}
else
As long as any timer is ripe, we run it. */
-EMACS_TIME
+struct timespec
timer_check (void)
{
- EMACS_TIME nexttime;
+ struct timespec nexttime;
Lisp_Object timers, idle_timers;
struct gcpro gcpro1, gcpro2;
/* Always consider the ordinary timers. */
timers = Fcopy_sequence (Vtimer_list);
/* Consider the idle timers only if Emacs is idle. */
- if (EMACS_TIME_VALID_P (timer_idleness_start_time))
+ if (timespec_valid_p (timer_idleness_start_time))
idle_timers = Fcopy_sequence (Vtimer_idle_list);
else
idle_timers = Qnil;
{
nexttime = timer_check_2 (timers, idle_timers);
}
- while (EMACS_SECS (nexttime) == 0 && EMACS_NSECS (nexttime) == 0);
+ while (nexttime.tv_sec == 0 && nexttime.tv_nsec == 0);
UNGCPRO;
return nexttime;
PSEC is a multiple of the system clock resolution. */)
(void)
{
- if (EMACS_TIME_VALID_P (timer_idleness_start_time))
- return make_lisp_time (sub_emacs_time (current_emacs_time (),
- timer_idleness_start_time));
+ if (timespec_valid_p (timer_idleness_start_time))
+ return make_lisp_time (timespec_sub (current_timespec (),
+ timer_idleness_start_time));
return Qnil;
}
if (STRINGP (string))
string_info = Fcons (string, make_number (charpos));
textpos = (w == XWINDOW (selected_window)
- && current_buffer == XBUFFER (w->buffer))
- ? PT : XMARKER (w->pointm)->charpos;
+ && current_buffer == XBUFFER (w->contents))
+ ? PT : marker_position (w->pointm);
xret = wx;
yret = wy;
dy = yret = wy;
}
/* Nothing special for part == ON_SCROLL_BAR. */
+ else if (part == ON_RIGHT_DIVIDER)
+ {
+ posn = Qright_divider;
+ width = WINDOW_RIGHT_DIVIDER_WIDTH (w);
+ dx = xret = wx;
+ dy = yret = wy;
+ }
+ else if (part == ON_BOTTOM_DIVIDER)
+ {
+ posn = Qbottom_divider;
+ width = WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+ dx = xret = wx;
+ dy = yret = wy;
+ }
/* For clicks in the text area, fringes, or margins, call
buffer_posn_from_coords to extract TEXTPOS, the buffer
extra_info))));
}
-/* Given a struct input_event, build the lisp event which represents
- it. If EVENT is 0, build a mouse movement event from the mouse
- movement buffer, which should have a movement event in it.
+/* Return non-zero if F is a GUI frame that uses some toolkit-managed
+ menu bar. This really means that Emacs draws and manages the menu
+ bar as part of its normal display, and therefore can compute its
+ geometry. */
+static bool
+toolkit_menubar_in_use (struct frame *f)
+{
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI)
+ return !(!FRAME_WINDOW_P (f));
+#else
+ return false;
+#endif
+}
+
+/* Given a struct input_event, build the lisp event which represents
+ it. If EVENT is 0, build a mouse movement event from the mouse
+ movement buffer, which should have a movement event in it.
Note that events must be passed to this function in the order they
are received; this function stores the location of button presses
return Qnil;
#endif
-#ifdef HAVE_MOUSE
/* A mouse click. Figure out where it is, decide whether it's
a press, click or drag, and build the appropriate structure. */
case MOUSE_CLICK_EVENT:
+#ifdef HAVE_GPM
+ case GPM_CLICK_EVENT:
+#endif
#ifndef USE_TOOLKIT_SCROLL_BARS
case SCROLL_BAR_CLICK_EVENT:
#endif
position = Qnil;
/* Build the position as appropriate for this mouse click. */
- if (event->kind == MOUSE_CLICK_EVENT)
+ if (event->kind == MOUSE_CLICK_EVENT
+#ifdef HAVE_GPM
+ || event->kind == GPM_CLICK_EVENT
+#endif
+ )
{
struct frame *f = XFRAME (event->frame_or_window);
-#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
int row, column;
-#endif
/* Ignore mouse events that were made on frame that
have been deleted. */
if (! FRAME_LIVE_P (f))
return Qnil;
-#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
/* EVENT->x and EVENT->y are frame-relative pixel
coordinates at this place. Under old redisplay, COLUMN
and ROW are set to frame relative glyph coordinates
which are then used to determine whether this click is
in a menu (non-toolkit version). */
- pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
- &column, &row, NULL, 1);
-
- /* In the non-toolkit version, clicks on the menu bar
- are ordinary button events in the event buffer.
- Distinguish them, and invoke the menu.
-
- (In the toolkit version, the toolkit handles the menu bar
- and Emacs doesn't know about it until after the user
- makes a selection.) */
- if (row >= 0 && row < FRAME_MENU_BAR_LINES (f)
- && (event->modifiers & down_modifier))
+ if (!toolkit_menubar_in_use (f))
{
- Lisp_Object items, item;
-
- /* Find the menu bar item under `column'. */
- item = Qnil;
- items = FRAME_MENU_BAR_ITEMS (f);
- for (i = 0; i < ASIZE (items); i += 4)
+ pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
+ &column, &row, NULL, 1);
+
+ /* In the non-toolkit version, clicks on the menu bar
+ are ordinary button events in the event buffer.
+ Distinguish them, and invoke the menu.
+
+ (In the toolkit version, the toolkit handles the
+ menu bar and Emacs doesn't know about it until
+ after the user makes a selection.) */
+ if (row >= 0 && row < FRAME_MENU_BAR_LINES (f)
+ && (event->modifiers & down_modifier))
{
- Lisp_Object pos, string;
- string = AREF (items, i + 1);
- pos = AREF (items, i + 3);
- if (NILP (string))
- break;
- if (column >= XINT (pos)
- && column < XINT (pos) + SCHARS (string))
+ Lisp_Object items, item;
+
+ /* Find the menu bar item under `column'. */
+ item = Qnil;
+ items = FRAME_MENU_BAR_ITEMS (f);
+ for (i = 0; i < ASIZE (items); i += 4)
{
- item = AREF (items, i);
- break;
+ Lisp_Object pos, string;
+ string = AREF (items, i + 1);
+ pos = AREF (items, i + 3);
+ if (NILP (string))
+ break;
+ if (column >= XINT (pos)
+ && column < XINT (pos) + SCHARS (string))
+ {
+ item = AREF (items, i);
+ break;
+ }
}
- }
- /* ELisp manual 2.4b says (x y) are window relative but
- code says they are frame-relative. */
- position
- = Fcons (event->frame_or_window,
- Fcons (Qmenu_bar,
- Fcons (Fcons (event->x, event->y),
- Fcons (make_number (event->timestamp),
- Qnil))));
+ /* ELisp manual 2.4b says (x y) are window
+ relative but code says they are
+ frame-relative. */
+ position = list4 (event->frame_or_window,
+ Qmenu_bar,
+ Fcons (event->x, event->y),
+ make_number (event->timestamp));
- return Fcons (item, Fcons (position, Qnil));
+ return list2 (item, position);
+ }
}
-#endif /* not USE_X_TOOLKIT && not USE_GTK && not HAVE_NS */
position = make_lispy_position (f, event->x, event->y,
event->timestamp);
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)))));
+ position = list5 (window, Qvertical_scroll_bar,
+ portion_whole, make_number (event->timestamp),
+ part);
}
#endif /* not USE_TOOLKIT_SCROLL_BARS */
&mouse_syms,
ASIZE (mouse_syms));
if (event->modifiers & drag_modifier)
- return Fcons (head,
- Fcons (start_pos,
- Fcons (position,
- Qnil)));
+ return list3 (head, start_pos, position);
else if (event->modifiers & (double_modifier | triple_modifier))
- return Fcons (head,
- Fcons (position,
- Fcons (make_number (double_click_count),
- Qnil)));
+ return list3 (head, position, make_number (double_click_count));
else
- return Fcons (head,
- Fcons (position,
- Qnil));
+ return list2 (head, position);
}
}
}
if (event->modifiers & (double_modifier | triple_modifier))
- return Fcons (head,
- Fcons (position,
- Fcons (make_number (double_click_count),
- Qnil)));
+ return list3 (head, position, make_number (double_click_count));
else
- return Fcons (head,
- Fcons (position,
- Qnil));
+ return list2 (head, position);
}
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)))));
+ position = list5 (window, Qvertical_scroll_bar, portion_whole,
+ make_number (event->timestamp), part);
/* Always treat scroll bar events as clicks. */
event->modifiers |= click_modifier;
Vlispy_mouse_stem,
NULL, &mouse_syms,
ASIZE (mouse_syms));
- return Fcons (head, Fcons (position, Qnil));
+ return list2 (head, position);
}
#endif /* USE_TOOLKIT_SCROLL_BARS */
case DRAG_N_DROP_EVENT:
{
- FRAME_PTR f;
+ struct frame *f;
Lisp_Object head, position;
Lisp_Object files;
Qdrag_n_drop, Qnil,
lispy_drag_n_drop_names,
&drag_n_drop_syms, 1);
- return Fcons (head,
- Fcons (position,
- Fcons (files,
- Qnil)));
+ return list3 (head, position, files);
}
-#endif /* HAVE_MOUSE */
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
|| defined (HAVE_NS) || defined (USE_GTK)
/* 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 list1 (Qmenu_bar);
return event->arg;
#endif
case SELECT_WINDOW_EVENT:
/* Make an event (select-window (WINDOW)). */
- return Fcons (Qselect_window,
- Fcons (Fcons (event->frame_or_window, Qnil),
- Qnil));
+ return list2 (Qselect_window, list1 (event->frame_or_window));
case TOOL_BAR_EVENT:
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 tool bar
events, which we use, relies on this. */
- return Fcons (Qtool_bar, Qnil);
+ return list1 (Qtool_bar);
else if (SYMBOLP (event->arg))
return apply_modifiers (event->modifiers, event->arg);
return event->arg;
}
#endif /* HAVE_DBUS */
- case CONFIG_CHANGED_EVENT:
- return Fcons (Qconfig_changed_event,
- Fcons (event->arg,
- Fcons (event->frame_or_window, Qnil)));
-#ifdef HAVE_GPM
- case GPM_CLICK_EVENT:
+#if defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY
+ case FILE_NOTIFY_EVENT:
{
- FRAME_PTR f = XFRAME (event->frame_or_window);
- Lisp_Object head, position;
- Lisp_Object *start_pos_ptr;
- Lisp_Object start_pos;
- int button = event->code;
-
- if (button >= ASIZE (button_down_location))
- {
- ptrdiff_t incr = button - ASIZE (button_down_location) + 1;
- button_down_location = larger_vector (button_down_location,
- incr, -1);
- mouse_syms = larger_vector (mouse_syms, incr, -1);
- }
-
- start_pos_ptr = aref_addr (button_down_location, button);
- start_pos = *start_pos_ptr;
-
- position = make_lispy_position (f, event->x, event->y,
- event->timestamp);
-
- if (event->modifiers & down_modifier)
- *start_pos_ptr = Fcopy_alist (position);
- else if (event->modifiers & (up_modifier | drag_modifier))
- {
- if (!CONSP (start_pos))
- return Qnil;
- event->modifiers &= ~up_modifier;
- }
-
- head = modify_event_symbol (button,
- event->modifiers,
- Qmouse_click, Vlispy_mouse_stem,
- NULL,
- &mouse_syms,
- ASIZE (mouse_syms));
+ return Fcons (Qfile_notify, event->arg);
+ }
+#endif /* defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY */
- if (event->modifiers & drag_modifier)
- return Fcons (head,
- Fcons (start_pos,
- Fcons (position,
- Qnil)));
- else if (event->modifiers & double_modifier)
- return Fcons (head,
- Fcons (position,
- Fcons (make_number (2),
- Qnil)));
- else if (event->modifiers & triple_modifier)
- return Fcons (head,
- Fcons (position,
- Fcons (make_number (3),
- Qnil)));
- else
- return Fcons (head,
- Fcons (position,
- Qnil));
- }
-#endif /* HAVE_GPM */
+ case CONFIG_CHANGED_EVENT:
+ return list3 (Qconfig_changed_event,
+ event->arg, event->frame_or_window);
/* The 'kind' field of the event is something we don't recognize. */
default:
}
}
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
-
static Lisp_Object
-make_lispy_movement (FRAME_PTR frame, Lisp_Object bar_window, enum scroll_bar_part part,
+make_lispy_movement (struct frame *frame, Lisp_Object bar_window, enum scroll_bar_part part,
Lisp_Object x, Lisp_Object y, Time t)
{
/* Is it a scroll bar movement? */
Lisp_Object part_sym;
part_sym = *scroll_bar_parts[(int) part];
- return Fcons (Qscroll_bar_movement,
- Fcons (list5 (bar_window,
- Qvertical_scroll_bar,
- Fcons (x, y),
- make_number (t),
- part_sym),
- Qnil));
+ return list2 (Qscroll_bar_movement,
+ list5 (bar_window,
+ Qvertical_scroll_bar,
+ Fcons (x, y),
+ make_number (t),
+ part_sym));
}
/* Or is it an ordinary mouse movement? */
else
}
}
-#endif /* HAVE_MOUSE || HAVE GPM */
-
/* Construct a switch frame event. */
static Lisp_Object
make_lispy_switch_frame (Lisp_Object frame)
{
- return Fcons (Qswitch_frame, Fcons (frame, Qnil));
+ return list2 (Qswitch_frame, frame);
}
-\f
+
+static Lisp_Object
+make_lispy_focus_in (Lisp_Object frame)
+{
+ return list2 (Qfocus_in, frame);
+}
+
+#ifdef HAVE_WINDOW_SYSTEM
+
+static Lisp_Object
+make_lispy_focus_out (Lisp_Object frame)
+{
+ return list2 (Qfocus_out, frame);
+}
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
/* Manipulating modifiers. */
/* Parse the name of SYMBOL, and return the set of modifiers it contains.
Lisp_Object elements;
if (INTEGERP (symbol))
- return (Fcons (make_number (KEY_TO_CHAR (symbol)),
- Fcons (make_number (XINT (symbol) & CHAR_MODIFIER_MASK),
- Qnil)));
+ return list2i (KEY_TO_CHAR (symbol), XINT (symbol) & CHAR_MODIFIER_MASK);
else if (!SYMBOLP (symbol))
return Qnil;
if (modifiers & ~INTMASK)
emacs_abort ();
XSETFASTINT (mask, modifiers);
- elements = Fcons (unmodified, Fcons (mask, Qnil));
+ elements = list2 (unmodified, mask);
/* Cache the parsing results on SYMBOL. */
Fput (symbol, Qevent_symbol_element_mask,
the caches:
XSETFASTINT (idx, modifiers);
Fput (new_symbol, Qevent_symbol_element_mask,
- Fcons (base, Fcons (idx, Qnil)));
+ list2 (base, idx));
Fput (new_symbol, Qevent_symbol_elements,
Fcons (base, lispy_modifier_list (modifiers)));
Sadly, this is only correct if `base' is indeed a base event,
else if (SYMBOLP (base))
return apply_modifiers (modifiers, base);
else
- {
- error ("Invalid base event");
- return Qnil;
- }
+ error ("Invalid base event");
}
/* Try to recognize SYMBOL as a modifier name.
void
record_asynch_buffer_change (void)
{
- struct input_event event;
- Lisp_Object tem;
- EVENT_INIT (event);
-
- event.kind = BUFFER_SWITCH_EVENT;
- event.frame_or_window = Qnil;
- event.arg = Qnil;
-
/* We don't need a buffer-switch event unless Emacs is waiting for input.
The purpose of the event is to make read_key_sequence look up the
keymaps again. If we aren't in read_key_sequence, we don't need one,
and the event could cause trouble by messing up (input-pending-p).
Note: Fwaiting_for_user_input_p always returns nil when async
subprocesses aren't supported. */
- tem = Fwaiting_for_user_input_p ();
- if (NILP (tem))
- return;
+ if (!NILP (Fwaiting_for_user_input_p ()))
+ {
+ struct input_event event;
- /* Make sure no interrupt happens while storing the event. */
+ EVENT_INIT (event);
+ event.kind = BUFFER_SWITCH_EVENT;
+ event.frame_or_window = Qnil;
+ event.arg = Qnil;
+
+ /* Make sure no interrupt happens while storing the event. */
#ifdef USABLE_SIGIO
- if (interrupt_input)
- kbd_buffer_store_event (&event);
- else
+ if (interrupt_input)
+ kbd_buffer_store_event (&event);
+ else
#endif
- {
- stop_polling ();
- kbd_buffer_store_event (&event);
- start_polling ();
+ {
+ stop_polling ();
+ kbd_buffer_store_event (&event);
+ start_polling ();
+ }
}
}
-\f
+
/* Read any terminal input already buffered up by the system
into the kbd_buffer, but do not wait.
hold_quit.kind = NO_EVENT;
/* No need for FIONREAD or fcntl; just say don't wait. */
- while (0 < (nr = (*t->read_socket_hook) (t, &hold_quit)))
+ while ((nr = (*t->read_socket_hook) (t, &hold_quit)) > 0)
nread += nr;
if (nr == -1) /* Not OK to read input now. */
return nread;
}
-static void
-decode_keyboard_code (struct tty_display_info *tty,
- struct coding_system *coding,
- unsigned char *buf, int nbytes)
-{
- unsigned char *src = buf;
- const unsigned char *p;
- int i;
-
- if (nbytes == 0)
- return;
- if (tty->meta_key != 2)
- for (i = 0; i < nbytes; i++)
- buf[i] &= ~0x80;
- if (coding->carryover_bytes > 0)
- {
- src = alloca (coding->carryover_bytes + nbytes);
- memcpy (src, coding->carryover, coding->carryover_bytes);
- memcpy (src + coding->carryover_bytes, buf, nbytes);
- nbytes += coding->carryover_bytes;
- }
- coding->destination = alloca (nbytes * 4);
- coding->dst_bytes = nbytes * 4;
- decode_coding_c_string (coding, src, nbytes, Qnil);
- if (coding->produced_char == 0)
- return;
- for (i = 0, p = coding->destination; i < coding->produced_char; i++)
- {
- struct input_event event_buf;
-
- EVENT_INIT (event_buf);
- event_buf.code = STRING_CHAR_ADVANCE (p);
- event_buf.kind =
- (ASCII_CHAR_P (event_buf.code)
- ? ASCII_KEYSTROKE_EVENT : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
- /* See the comment in tty_read_avail_input. */
- event_buf.frame_or_window = tty->top_frame;
- event_buf.arg = Qnil;
- kbd_buffer_store_event (&event_buf);
- }
-}
-
/* This is the tty way of reading available input.
Note that each terminal device has its own `struct terminal' object,
/* XXX I think the following code should be moved to separate hook
functions in system-dependent files. */
#ifdef WINDOWSNT
+ /* FIXME: AFAIK, tty_read_avail_input is not used under w32 since the non-GUI
+ code sets read_socket_hook to w32_console_read_socket instead! */
return 0;
#else /* not WINDOWSNT */
if (! tty->term_initted) /* In case we get called during bootstrap. */
{
nread = emacs_read (fileno (tty->input), (char *) cbuf, n_to_read);
/* POSIX infers that processes which are not in the session leader's
- process group won't get SIGHUP's at logout time. BSDI adheres to
+ process group won't get SIGHUPs at logout time. BSDI adheres to
this part standard and returns -1 from read (0) with errno==EIO
when the control tty is taken away.
Jeffrey Honig <jch@bsdi.com> says this is generally safe. */
an EAGAIN error. Does anybody know of a situation
where a retry is actually needed? */
#if 0
- nread < 0 && (errno == EAGAIN
-#ifdef EFAULT
- || errno == EFAULT
-#endif
+ nread < 0 && (errno == EAGAIN || errno == EFAULT
#ifdef EBADSLT
|| errno == EBADSLT
#endif
#endif /* not MSDOS */
#endif /* not WINDOWSNT */
- if (TERMINAL_KEYBOARD_CODING (terminal)->common_flags
- & CODING_REQUIRE_DECODING_MASK)
- {
- struct coding_system *coding = TERMINAL_KEYBOARD_CODING (terminal);
- int from;
-
- /* Decode the key sequence except for those with meta
- modifiers. */
- for (i = from = 0; ; i++)
- if (i == nread || (tty->meta_key == 1 && (cbuf[i] & 0x80)))
- {
- struct input_event buf;
-
- decode_keyboard_code (tty, coding, cbuf + from, i - from);
- if (i == nread)
- break;
-
- EVENT_INIT (buf);
- buf.kind = ASCII_KEYSTROKE_EVENT;
- buf.modifiers = meta_modifier;
- buf.code = cbuf[i] & ~0x80;
- /* See the comment below. */
- buf.frame_or_window = tty->top_frame;
- buf.arg = Qnil;
- kbd_buffer_store_event (&buf);
- from = i + 1;
- }
- return nread;
- }
-
for (i = 0; i < nread; i++)
{
struct input_event buf;
}
/* Undo any number of BLOCK_INPUT calls down to level LEVEL,
- and also (if the level is now 0) reinvoke any pending signal. */
+ and reinvoke any pending signal if the level is now 0 and
+ a fatal error is not already in progress. */
void
unblock_input_to (int level)
interrupt_input_blocked = level;
if (level == 0)
{
- if (pending_signals)
+ if (pending_signals && !fatal_error_in_progress)
process_pending_signals ();
}
else if (level < 0)
pending_signals = 1;
if (input_available_clear_time)
- *input_available_clear_time = make_emacs_time (0, 0);
+ *input_available_clear_time = make_timespec (0, 0);
}
static void
/* Tell wait_reading_process_output that it needs to wake
up and look around. */
if (input_available_clear_time)
- *input_available_clear_time = make_emacs_time (0, 0);
+ *input_available_clear_time = make_timespec (0, 0);
}
break;
}
Lisp_Object *tmaps;
/* Should overriding-terminal-local-map and overriding-local-map apply? */
- if (!NILP (Voverriding_local_map_menu_flag))
+ if (!NILP (Voverriding_local_map_menu_flag)
+ && !NILP (Voverriding_local_map))
{
/* Yes, use them (if non-nil) as well as the global map. */
maps = alloca (3 * sizeof (maps[0]));
Lisp_Object tem;
ptrdiff_t nminor;
nminor = current_minor_maps (NULL, &tmaps);
- maps = alloca ((nminor + 3) * sizeof *maps);
+ maps = alloca ((nminor + 4) * sizeof *maps);
nmaps = 0;
+ tem = KVAR (current_kboard, Voverriding_terminal_local_map);
+ if (!NILP (tem) && !NILP (Voverriding_local_map_menu_flag))
+ maps[nmaps++] = tem;
if (tem = get_local_map (PT, current_buffer, Qkeymap), !NILP (tem))
maps[nmaps++] = tem;
memcpy (maps + nmaps, tmaps, nminor * sizeof (maps[0]));
ASET (menu_bar_items_vector, i, key); i++;
ASET (menu_bar_items_vector, i,
AREF (item_properties, ITEM_PROPERTY_NAME)); i++;
- ASET (menu_bar_items_vector, i, Fcons (item, Qnil)); i++;
+ ASET (menu_bar_items_vector, i, list1 (item)); i++;
ASET (menu_bar_items_vector, i, make_number (0)); i++;
menu_bar_items_index = i;
}
to process. */
/* Should overriding-terminal-local-map and overriding-local-map apply? */
- if (!NILP (Voverriding_local_map_menu_flag))
+ if (!NILP (Voverriding_local_map_menu_flag)
+ && !NILP (Voverriding_local_map))
{
/* Yes, use them (if non-nil) as well as the global map. */
maps = alloca (3 * sizeof *maps);
Lisp_Object tem;
ptrdiff_t nminor;
nminor = current_minor_maps (NULL, &tmaps);
- maps = alloca ((nminor + 3) * sizeof *maps);
+ maps = alloca ((nminor + 4) * sizeof *maps);
nmaps = 0;
+ tem = KVAR (current_kboard, Voverriding_terminal_local_map);
+ if (!NILP (tem) && !NILP (Voverriding_local_map_menu_flag))
+ maps[nmaps++] = tem;
if (tem = get_local_map (PT, current_buffer, Qkeymap), !NILP (tem))
maps[nmaps++] = tem;
memcpy (maps + nmaps, tmaps, nminor * sizeof (maps[0]));
/* As an exception, allow old-style menu separators. */
if (STRINGP (XCAR (item)))
- item = Fcons (XCAR (item), Qnil);
+ item = list1 (XCAR (item));
else if (!EQ (XCAR (item), Qmenu_item)
|| (item = XCDR (item), !CONSP (item)))
return 0;
#if !defined (USE_GTK) && !defined (HAVE_NS)
/* If we use build_desired_tool_bar_string to render the
tool bar, the separator is rendered as an image. */
- PROP (TOOL_BAR_ITEM_IMAGES)
- = menu_item_eval_property (Vtool_bar_separator_image_expression);
- PROP (TOOL_BAR_ITEM_ENABLED_P) = Qnil;
- PROP (TOOL_BAR_ITEM_SELECTED_P) = Qnil;
- PROP (TOOL_BAR_ITEM_CAPTION) = Qnil;
+ set_prop (TOOL_BAR_ITEM_IMAGES,
+ (menu_item_eval_property
+ (Vtool_bar_separator_image_expression)));
+ set_prop (TOOL_BAR_ITEM_ENABLED_P, Qnil);
+ set_prop (TOOL_BAR_ITEM_SELECTED_P, Qnil);
+ set_prop (TOOL_BAR_ITEM_CAPTION, Qnil);
#endif
return 1;
}
static void
append_tool_bar_item (void)
{
- ptrdiff_t incr =
- (ntool_bar_items
- - (ASIZE (tool_bar_items_vector) - TOOL_BAR_ITEM_NSLOTS));
+ ptrdiff_t incr
+ = (ntool_bar_items
+ - (ASIZE (tool_bar_items_vector) - TOOL_BAR_ITEM_NSLOTS));
/* Enlarge tool_bar_items_vector if necessary. */
- if (0 < incr)
- tool_bar_items_vector
- = larger_vector (tool_bar_items_vector, incr, -1);
+ if (incr > 0)
+ tool_bar_items_vector = larger_vector (tool_bar_items_vector, incr, -1);
/* Append entries from tool_bar_item_properties to the end of
tool_bar_items_vector. */
\f
-/* Read a character using menus based on maps in the array MAPS.
- NMAPS is the length of MAPS. Return nil if there are no menus in the maps.
+/* Read a character using menus based on the keymap MAP.
+ Return nil if there are no menus in the maps.
Return t if we displayed a menu but the user rejected it.
PREV_EVENT is the previous input event, or nil if we are reading
and do auto-saving in the inner call of read_char. */
static Lisp_Object
-read_char_x_menu_prompt (ptrdiff_t nmaps, Lisp_Object *maps,
+read_char_x_menu_prompt (Lisp_Object map,
Lisp_Object prev_event, bool *used_mouse_menu)
{
-#ifdef HAVE_MENUS
- ptrdiff_t mapno;
-#endif
-
if (used_mouse_menu)
*used_mouse_menu = 0;
- /* Use local over global Menu maps */
+ /* Use local over global Menu maps. */
if (! menu_prompting)
return Qnil;
- /* Optionally disregard all but the global map. */
- if (inhibit_local_menu_bar_menus)
- {
- maps += (nmaps - 1);
- nmaps = 1;
- }
-
-#ifdef HAVE_MENUS
/* If we got to this point via a mouse click,
use a real menu for mouse selection. */
if (EVENT_HAS_PARAMETERS (prev_event)
&& !EQ (XCAR (prev_event), Qtool_bar))
{
/* Display the menu and get the selection. */
- Lisp_Object *realmaps = alloca (nmaps * sizeof *realmaps);
Lisp_Object value;
- ptrdiff_t nmaps1 = 0;
- /* Use the maps that are not nil. */
- for (mapno = 0; mapno < nmaps; mapno++)
- if (!NILP (maps[mapno]))
- realmaps[nmaps1++] = maps[mapno];
-
- value = Fx_popup_menu (prev_event, Flist (nmaps1, realmaps));
+ value = Fx_popup_menu (prev_event, get_keymap (map, 0, 1));
if (CONSP (value))
{
Lisp_Object tem;
*used_mouse_menu = 1;
return value;
}
-#endif /* HAVE_MENUS */
return Qnil ;
}
-/* Buffer in use so far for the minibuf prompts for menu keymaps.
- We make this bigger when necessary, and never free it. */
-static char *read_char_minibuf_menu_text;
-/* Size of that buffer. */
-static ptrdiff_t read_char_minibuf_menu_width;
-
static Lisp_Object
read_char_minibuf_menu_prompt (int commandflag,
- ptrdiff_t nmaps, Lisp_Object *maps)
+ Lisp_Object map)
{
- ptrdiff_t mapno;
register Lisp_Object name;
ptrdiff_t nlength;
/* FIXME: Use the minibuffer's frame width. */
ptrdiff_t idx = -1;
bool nobindings = 1;
Lisp_Object rest, vector;
- char *menu;
+ Lisp_Object prompt_strings = Qnil;
vector = Qnil;
- name = Qnil;
if (! menu_prompting)
return Qnil;
- /* Get the menu name from the first map that has one (a prompt string). */
- for (mapno = 0; mapno < nmaps; mapno++)
- {
- name = Fkeymap_prompt (maps[mapno]);
- if (!NILP (name))
- break;
- }
+ map = get_keymap (map, 0, 1);
+ name = Fkeymap_prompt (map);
/* If we don't have any menus, just read a character normally. */
if (!STRINGP (name))
return Qnil;
- /* Make sure we have a big enough buffer for the menu text. */
- width = max (width, SBYTES (name));
- if (STRING_BYTES_BOUND - 4 < width)
- memory_full (SIZE_MAX);
- if (width + 4 > read_char_minibuf_menu_width)
- {
- read_char_minibuf_menu_text
- = xrealloc (read_char_minibuf_menu_text, width + 4);
- read_char_minibuf_menu_width = width + 4;
- }
- menu = read_char_minibuf_menu_text;
+#define PUSH_C_STR(str, listvar) \
+ listvar = Fcons (build_unibyte_string (str), listvar)
/* Prompt string always starts with map's prompt, and a space. */
- strcpy (menu, SSDATA (name));
- nlength = SBYTES (name);
- menu[nlength++] = ':';
- menu[nlength++] = ' ';
- menu[nlength] = 0;
+ prompt_strings = Fcons (name, prompt_strings);
+ PUSH_C_STR (": ", prompt_strings);
+ nlength = SCHARS (name) + 2;
- /* Start prompting at start of first map. */
- mapno = 0;
- rest = maps[mapno];
+ rest = map;
/* Present the documented bindings, a line at a time. */
while (1)
{
bool notfirst = 0;
+ Lisp_Object menu_strings = prompt_strings;
ptrdiff_t i = nlength;
Lisp_Object obj;
Lisp_Object orig_defn_macro;
{
Lisp_Object elt;
- /* If reached end of map, start at beginning of next map. */
+ /* FIXME: Use map_keymap to handle new keymap formats. */
+
+ /* At end of map, wrap around if just starting,
+ or end this line if already have something on it. */
if (NILP (rest))
{
- mapno++;
- /* At end of last map, wrap around to first map if just starting,
- or end this line if already have something on it. */
- if (mapno == nmaps)
- {
- mapno = 0;
- if (notfirst || nobindings) break;
- }
- rest = maps[mapno];
+ if (notfirst || nobindings)
+ break;
+ else
+ rest = map;
}
/* Look at the next element of the map. */
/* Punctuate between strings. */
if (notfirst)
{
- strcpy (menu + i, ", ");
+ PUSH_C_STR (", ", menu_strings);
i += 2;
}
notfirst = 1;
{
/* Add as much of string as fits. */
thiswidth = min (SCHARS (desc), width - i);
- memcpy (menu + i, SDATA (desc), thiswidth);
+ menu_strings
+ = Fcons (Fsubstring (desc, make_number (0),
+ make_number (thiswidth)),
+ menu_strings);
i += thiswidth;
- strcpy (menu + i, " = ");
+ PUSH_C_STR (" = ", menu_strings);
i += 3;
}
/* Add as much of string as fits. */
thiswidth = min (SCHARS (s), width - i);
- memcpy (menu + i, SDATA (s), thiswidth);
+ menu_strings
+ = Fcons (Fsubstring (s, make_number (0),
+ make_number (thiswidth)),
+ menu_strings);
i += thiswidth;
- menu[i] = 0;
}
else
{
/* If this element does not fit, end the line now,
and save the element for the next line. */
- strcpy (menu + i, "...");
+ PUSH_C_STR ("...", menu_strings);
break;
}
}
}
/* Prompt with that and read response. */
- message2_nolog (menu, strlen (menu),
- ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
+ message3_nolog (apply1 (intern ("concat"), Fnreverse (menu_strings)));
- /* Make believe its not a keyboard macro in case the help char
+ /* Make believe it's not a keyboard macro in case the help char
is pressed. Help characters are not recorded because menu prompting
- is not used on replay.
- */
+ is not used on replay. */
orig_defn_macro = KVAR (current_kboard, defining_kbd_macro);
kset_defining_kbd_macro (current_kboard, Qnil);
do
- obj = read_char (commandflag, 0, 0, Qt, 0, NULL);
+ obj = read_char (commandflag, Qnil, Qt, 0, NULL);
while (BUFFERP (obj));
kset_defining_kbd_macro (current_kboard, orig_defn_macro);
- if (!INTEGERP (obj))
- return obj;
- else if (XINT (obj) == -2)
+ if (!INTEGERP (obj) || XINT (obj) == -2)
return obj;
if (! EQ (obj, menu_prompt_more_char)
store_kbd_macro_char (obj);
return obj;
}
- /* Help char - go round again */
+ /* Help char - go round again. */
}
}
\f
/* Reading key sequences. */
-/* Follow KEY in the maps in CURRENT[0..NMAPS-1], placing its bindings
- in DEFS[0..NMAPS-1]. Set NEXT[i] to DEFS[i] if DEFS[i] is a
- keymap, or nil otherwise. Return the index of the first keymap in
- which KEY has any binding, or NMAPS if no map has a binding.
-
- If KEY is a meta ASCII character, treat it like meta-prefix-char
- followed by the corresponding non-meta character. Keymaps in
- CURRENT with non-prefix bindings for meta-prefix-char become nil in
- NEXT.
-
- If KEY has no bindings in any of the CURRENT maps, NEXT is left
- unmodified.
-
- NEXT may be the same array as CURRENT. */
-
-static int
-follow_key (Lisp_Object key, ptrdiff_t nmaps, Lisp_Object *current,
- Lisp_Object *defs, Lisp_Object *next)
+static Lisp_Object
+follow_key (Lisp_Object keymap, Lisp_Object key)
{
- ptrdiff_t i, first_binding;
-
- first_binding = nmaps;
- for (i = nmaps - 1; i >= 0; i--)
- {
- if (! NILP (current[i]))
- {
- defs[i] = access_keymap (current[i], key, 1, 0, 1);
- if (! NILP (defs[i]))
- first_binding = i;
- }
- else
- defs[i] = Qnil;
- }
-
- /* Given the set of bindings we've found, produce the next set of maps. */
- if (first_binding < nmaps)
- for (i = 0; i < nmaps; i++)
- next[i] = NILP (defs[i]) ? Qnil : get_keymap (defs[i], 0, 1);
+ return access_keymap (get_keymap (keymap, 0, 1),
+ key, 1, 0, 1);
+}
- return first_binding;
+static Lisp_Object
+active_maps (Lisp_Object first_event)
+{
+ Lisp_Object position
+ = CONSP (first_event) ? CAR_SAFE (XCDR (first_event)) : Qnil;
+ return Fcons (Qkeymap, Fcurrent_active_maps (Qt, position));
}
/* Structure used to keep track of partial application of key remapping
barf--don't ignore it.
(To ignore it safely, we would need to gcpro a bunch of
other variables.) */
- if (! (VECTORP (next) || STRINGP (next)))
+ if (! (NILP (next) || VECTORP (next) || STRINGP (next)))
error ("Function %s returns invalid key sequence",
SSDATA (SYMBOL_NAME (tem)));
}
static bool
test_undefined (Lisp_Object binding)
{
- return (EQ (binding, Qundefined)
- || (!NILP (binding) && SYMBOLP (binding)
+ return (NILP (binding)
+ || EQ (binding, Qundefined)
+ || (SYMBOLP (binding)
&& EQ (Fcommand_remapping (binding, Qnil, Qnil), Qundefined)));
}
Echo starting immediately unless `prompt' is 0.
+ If PREVENT_REDISPLAY is non-zero, avoid redisplay by calling
+ read_char with a suitable COMMANDFLAG argument.
+
Where a key sequence ends depends on the currently active keymaps.
These include any minor mode keymaps active in the current buffer,
the current buffer's local map, and the global map.
static int
read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
bool dont_downcase_last, bool can_return_switch_frame,
- bool fix_current_buffer)
+ bool fix_current_buffer, bool prevent_redisplay)
{
- Lisp_Object from_string;
ptrdiff_t count = SPECPDL_INDEX ();
/* How many keys there are in the current key sequence. */
ptrdiff_t echo_start IF_LINT (= 0);
ptrdiff_t keys_start;
- /* The number of keymaps we're scanning right now, and the number of
- keymaps we have allocated space for. */
- ptrdiff_t nmaps;
- ptrdiff_t nmaps_allocated = 0;
-
- /* defs[0..nmaps-1] are the definitions of KEYBUF[0..t-1] in
- the current keymaps. */
- Lisp_Object *defs = NULL;
+ Lisp_Object current_binding = Qnil;
+ Lisp_Object first_event = Qnil;
- /* submaps[0..nmaps-1] are the prefix definitions of KEYBUF[0..t-1]
- in the current keymaps, or nil where it is not a prefix. */
- Lisp_Object *submaps = NULL;
-
- /* 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;
-
- /* Positive if we have already considered switching to the local-map property
- of the place where a mouse click occurred. */
- int localized_local_map = 0;
-
- /* The index in submaps[] of the first keymap that has a binding for
- this key sequence. In other words, the lowest i such that
- submaps[i] is non-nil. */
- ptrdiff_t first_binding;
/* Index of the first key that has no binding.
It is useless to try fkey.start larger than that. */
int first_unbound;
While we're reading, we keep the event here. */
Lisp_Object delayed_switch_frame;
- /* See the comment below... */
-#if defined (GOBBLE_FIRST_EVENT)
- Lisp_Object first_event;
-#endif
-
Lisp_Object original_uppercase IF_LINT (= Qnil);
int original_uppercase_position = -1;
/* List of events for which a fake prefix key has been generated. */
Lisp_Object fake_prefixed_keys = Qnil;
-#if defined (GOBBLE_FIRST_EVENT)
- int junk;
-#endif
-
struct gcpro gcpro1;
GCPRO1 (fake_prefixed_keys);
{
if (!NILP (prompt))
{
- /* Install the string STR as the beginning of the string of
- echoing, so that it serves as a prompt for the next
+ /* Install the string PROMPT as the beginning of the string
+ of echoing, so that it serves as a prompt for the next
character. */
kset_echo_string (current_kboard, prompt);
current_kboard->echo_after_prompt = SCHARS (prompt);
keys_start = this_command_key_count;
this_single_command_key_start = keys_start;
-#if defined (GOBBLE_FIRST_EVENT)
- /* This doesn't quite work, because some of the things that read_char
- does cannot safely be bypassed. It seems too risky to try to make
- this work right. */
-
- /* Read the first char of the sequence specially, before setting
- up any keymaps, in case a filter runs and switches buffers on us. */
- first_event = read_char (NILP (prompt), 0, submaps, last_nonmenu_event,
- &junk, NULL);
-#endif /* GOBBLE_FIRST_EVENT */
-
- orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
- orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
- from_string = Qnil;
-
/* We jump here when we need to reinitialize fkey and keytran; this
happens if we switch keyboards between rescans. */
replay_entire_sequence:
keybuf with its symbol, or if the sequence starts with a mouse
click and we need to switch buffers, we jump back here to rebuild
the initial keymaps from the current buffer. */
- nmaps = 0;
-
- if (!NILP (KVAR (current_kboard, Voverriding_terminal_local_map)))
- {
- if (2 > nmaps_allocated)
- {
- submaps = alloca (2 * sizeof *submaps);
- defs = alloca (2 * sizeof *defs);
- nmaps_allocated = 2;
- }
- submaps[nmaps++] = KVAR (current_kboard, Voverriding_terminal_local_map);
- }
- else if (!NILP (Voverriding_local_map))
- {
- if (2 > nmaps_allocated)
- {
- submaps = alloca (2 * sizeof *submaps);
- defs = alloca (2 * sizeof *defs);
- nmaps_allocated = 2;
- }
- submaps[nmaps++] = Voverriding_local_map;
- }
- else
- {
- ptrdiff_t nminor;
- ptrdiff_t total;
- Lisp_Object *maps;
-
- nminor = current_minor_maps (0, &maps);
- total = nminor + (!NILP (orig_keymap) ? 3 : 2);
-
- if (total > nmaps_allocated)
- {
- submaps = alloca (total * sizeof *submaps);
- defs = alloca (total * sizeof *defs);
- nmaps_allocated = total;
- }
-
- if (!NILP (orig_keymap))
- submaps[nmaps++] = orig_keymap;
-
- memcpy (submaps + nmaps, maps, nminor * sizeof (submaps[0]));
-
- nmaps += nminor;
-
- submaps[nmaps++] = orig_local_map;
- }
- submaps[nmaps++] = current_global_map;
-
- /* Find an accurate initial value for first_binding. */
- for (first_binding = 0; first_binding < nmaps; first_binding++)
- if (! NILP (submaps[first_binding]))
- break;
+ current_binding = active_maps (first_event);
/* Start from the beginning in keybuf. */
t = 0;
/* If the best binding for the current key sequence is a keymap, or
we may be looking at a function key's escape sequence, keep on
reading. */
- while (first_binding < nmaps
+ while (!NILP (current_binding)
/* Keep reading as long as there's a prefix binding. */
- ? !NILP (submaps[first_binding])
+ ? KEYMAPP (current_binding)
/* Don't return in the middle of a possible function key sequence,
if the only bindings we found were via case conversion.
Thus, if ESC O a has a function-key-map translation
just one key. */
ptrdiff_t echo_local_start IF_LINT (= 0);
int keys_local_start;
- ptrdiff_t local_first_binding;
+ Lisp_Object new_binding;
eassert (indec.end == t || (indec.end > t && indec.end <= mock_input));
eassert (indec.start <= indec.end);
if (INTERACTIVE)
echo_local_start = echo_length ();
keys_local_start = this_command_key_count;
- local_first_binding = first_binding;
replay_key:
/* These are no-ops, unless we throw away a keystroke below and
if (INTERACTIVE && t < mock_input)
echo_truncate (echo_local_start);
this_command_key_count = keys_local_start;
- first_binding = local_first_binding;
/* By default, assume each event is "real". */
last_real_key_start = t;
key = keybuf[t];
add_command_key (key);
if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
- && NILP (Fzerop (Vecho_keystrokes)))
- echo_char (key);
+ && NILP (Fzerop (Vecho_keystrokes))
+ && current_kboard->immediate_echo)
+ {
+ echo_add_key (key);
+ echo_dash ();
+ }
}
/* If not, we should actually read a character. */
{
KBOARD *interrupted_kboard = current_kboard;
struct frame *interrupted_frame = SELECTED_FRAME ();
- key = read_char (NILP (prompt), nmaps,
- (Lisp_Object *) submaps, last_nonmenu_event,
- &used_mouse_menu, NULL);
+ /* Calling read_char with COMMANDFLAG = -2 avoids
+ redisplay in read_char and its subroutines. */
+ key = read_char (prevent_redisplay ? -2 : NILP (prompt),
+ current_binding, last_nonmenu_event,
+ &used_mouse_menu, NULL);
if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */
/* When switching to a new tty (with a new keyboard),
read_char returns the new buffer, rather than -2
KVAR (interrupted_kboard, kbd_queue)));
}
mock_input = 0;
- orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
- orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
goto replay_entire_sequence;
}
}
{
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
Fkill_emacs (Qnil);
- if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
- Fset_buffer (XWINDOW (selected_window)->buffer);
+ if (XBUFFER (XWINDOW (selected_window)->contents)
+ != current_buffer)
+ Fset_buffer (XWINDOW (selected_window)->contents);
}
- orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
- orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
goto replay_sequence;
}
keybuf[t++] = key;
mock_input = t;
Vquit_flag = Qnil;
- orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
- orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
goto replay_sequence;
}
}
}
+ if (NILP (first_event))
+ {
+ first_event = key;
+ /* Even if first_event does not specify a particular
+ window/position, it's important to recompute the maps here
+ since a long time might have passed since we entered
+ read_key_sequence, and a timer (or process-filter or
+ special-event-map, ...) might have switched the current buffer
+ or the selected window from under us in the mean time. */
+ if (fix_current_buffer
+ && (XBUFFER (XWINDOW (selected_window)->contents)
+ != current_buffer))
+ Fset_buffer (XWINDOW (selected_window)->contents);
+ current_binding = active_maps (first_event);
+ }
+
GROW_RAW_KEYBUF;
ASET (raw_keybuf, raw_keybuf_count, key);
raw_keybuf_count++;
or when user programs play with this-command-keys. */
if (EVENT_HAS_PARAMETERS (key))
{
- Lisp_Object kind;
- Lisp_Object string;
-
- kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
+ Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
if (EQ (kind, Qmouse_click))
{
- Lisp_Object window, posn;
-
- window = POSN_WINDOW (EVENT_START (key));
- posn = POSN_POSN (EVENT_START (key));
+ Lisp_Object window = POSN_WINDOW (EVENT_START (key));
+ Lisp_Object posn = POSN_POSN (EVENT_START (key));
if (CONSP (posn)
|| (!NILP (fake_prefixed_keys)
not the current buffer. If we're at the
beginning of a key sequence, switch buffers. */
if (WINDOWP (window)
- && BUFFERP (XWINDOW (window)->buffer)
- && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
+ && BUFFERP (XWINDOW (window)->contents)
+ && XBUFFER (XWINDOW (window)->contents) != current_buffer)
{
ASET (raw_keybuf, raw_keybuf_count, key);
raw_keybuf_count++;
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,
- Qlocal_map);
- orig_keymap = get_local_map (PT, current_buffer,
- Qkeymap);
+ set_buffer_internal (XBUFFER (XWINDOW (window)->contents));
goto replay_sequence;
}
-
- /* For a mouse click, get the local text-property keymap
- of the place clicked on, rather than point. */
- if (CONSP (XCDR (key))
- && ! localized_local_map)
- {
- Lisp_Object map_here, start, pos;
-
- localized_local_map = 1;
- start = EVENT_START (key);
-
- if (CONSP (start) && POSN_INBUFFER_P (start))
- {
- pos = POSN_BUFFER_POSN (start);
- if (INTEGERP (pos)
- && XINT (pos) >= BEGV
- && XINT (pos) <= ZV)
- {
- map_here = get_local_map (XINT (pos),
- current_buffer,
- Qlocal_map);
- if (!EQ (map_here, orig_local_map))
- {
- orig_local_map = map_here;
- ++localized_local_map;
- }
-
- map_here = get_local_map (XINT (pos),
- current_buffer,
- Qkeymap);
- if (!EQ (map_here, orig_keymap))
- {
- orig_keymap = map_here;
- ++localized_local_map;
- }
-
- if (localized_local_map > 1)
- {
- keybuf[t] = key;
- mock_input = t + 1;
-
- goto replay_sequence;
- }
- }
- }
- }
}
/* Expand mode-line and scroll-bar events into two events:
prevent proper action when the event is pushed
back into unread-command-events. */
fake_prefixed_keys = Fcons (key, fake_prefixed_keys);
-
- /* If on a mode line string with a local keymap,
- reconsider the key sequence with that keymap. */
- if (string = POSN_STRING (EVENT_START (key)),
- (CONSP (string) && STRINGP (XCAR (string))))
- {
- Lisp_Object pos, map, map2;
-
- pos = XCDR (string);
- string = XCAR (string);
- if (XINT (pos) >= 0
- && XINT (pos) < SCHARS (string))
- {
- 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;
}
- else if (NILP (from_string)
- && (string = POSN_STRING (EVENT_START (key)),
- (CONSP (string) && STRINGP (XCAR (string)))))
- {
- /* For a click on a string, i.e. overlay string or a
- string displayed via the `display' property,
- consider `local-map' and `keymap' properties of
- that string. */
- Lisp_Object pos, map, map2;
-
- pos = XCDR (string);
- string = XCAR (string);
- if (XINT (pos) >= 0
- && XINT (pos) < SCHARS (string))
- {
- 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))
- {
- from_string = string;
- keybuf[t++] = key;
- mock_input = t;
- goto replay_sequence;
- }
- }
- }
}
else if (CONSP (XCDR (key))
&& CONSP (EVENT_START (key))
if (bufsize - t <= 1)
error ("Key sequence too long");
keybuf[t] = posn;
- keybuf[t+1] = key;
+ keybuf[t + 1] = key;
/* Zap the position in key, so we know that we've
expanded it, and don't try to do so again. */
- POSN_SET_POSN (EVENT_START (key),
- Fcons (posn, Qnil));
+ POSN_SET_POSN (EVENT_START (key), list1 (posn));
mock_input = t + 2;
goto replay_sequence;
/* We have finally decided that KEY is something we might want
to look up. */
- first_binding = (follow_key (key,
- nmaps - first_binding,
- submaps + first_binding,
- defs + first_binding,
- submaps + first_binding)
- + first_binding);
+ new_binding = follow_key (current_binding, key);
/* If KEY wasn't bound, we'll try some fallbacks. */
- if (first_binding < nmaps)
+ if (!NILP (new_binding))
/* This is needed for the following scenario:
event 0: a down-event that gets dropped by calling replay_key.
event 1: some normal prefix like C-h.
new_head
= apply_modifiers (modifiers, XCAR (breakdown));
- new_click
- = Fcons (new_head, Fcons (EVENT_START (key), Qnil));
-
- /* Look for a binding for this new key. follow_key
- promises that it didn't munge submaps the
- last time we called it, since key was unbound. */
- first_binding
- = (follow_key (new_click,
- nmaps - local_first_binding,
- submaps + local_first_binding,
- defs + local_first_binding,
- submaps + local_first_binding)
- + local_first_binding);
+ new_click = list2 (new_head, EVENT_START (key));
+
+ /* Look for a binding for this new key. */
+ new_binding = follow_key (current_binding, new_click);
/* If that click is bound, go for it. */
- if (first_binding < nmaps)
+ if (!NILP (new_binding))
{
+ current_binding = new_binding;
key = new_click;
break;
}
}
}
}
+ current_binding = new_binding;
keybuf[t++] = key;
/* Normally, last_nonmenu_event gets the previous key we read.
}
}
- if (first_binding < nmaps
- && NILP (submaps[first_binding])
- && !test_undefined (defs[first_binding])
+ if (!KEYMAPP (current_binding)
+ && !test_undefined (current_binding)
&& indec.start >= t)
/* There is a binding and it's not a prefix.
(and it doesn't have any input-decode-map translation pending).
first_binding >= nmaps) we don't want
to apply this function-key-mapping. */
fkey.end + 1 == t
- && (first_binding >= nmaps
- || test_undefined (defs[first_binding])),
+ && (test_undefined (current_binding)),
&diff, prompt);
UNGCPRO;
if (done)
and cannot be part of a function key or translation,
and is an upper case letter
use the corresponding lower-case letter instead. */
- if (first_binding >= nmaps
+ if (NILP (current_binding)
&& /* indec.start >= t && fkey.start >= t && */ keytran.start >= t
&& INTEGERP (key)
&& ((CHARACTERP (make_number (XINT (key) & ~CHAR_MODIFIER_MASK))
and cannot be part of a function key or translation,
and is a shifted function key,
use the corresponding unshifted function key instead. */
- if (first_binding >= nmaps
+ if (NILP (current_binding)
&& /* indec.start >= t && fkey.start >= t && */ keytran.start >= t)
{
Lisp_Object breakdown = parse_modifiers (key);
}
}
if (!dummyflag)
- read_key_sequence_cmd = (first_binding < nmaps
- ? defs[first_binding]
- : Qnil);
+ read_key_sequence_cmd = current_binding;
read_key_sequence_remapped
/* Remap command through active keymaps.
Do the remapping here, before the unbind_to so it uses the keymaps
/* Don't downcase the last character if the caller says don't.
Don't downcase it if the result is undefined, either. */
- if ((dont_downcase_last || first_binding >= nmaps)
+ if ((dont_downcase_last || NILP (current_binding))
&& t > 0
&& t - 1 == original_uppercase_position)
{
return t;
}
-DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 5, 0,
- doc: /* Read a sequence of keystrokes and return as a string or vector.
-The sequence is sufficient to specify a non-prefix command in the
-current local and global maps.
-
-First arg PROMPT is a prompt string. If nil, do not prompt specially.
-Second (optional) arg CONTINUE-ECHO, if non-nil, means this key echos
-as a continuation of the previous key.
-
-The third (optional) arg DONT-DOWNCASE-LAST, if non-nil, means do not
-convert the last event to lower case. (Normally any upper case event
-is converted to lower case if the original event is undefined and the lower
-case equivalent is defined.) A non-nil value is appropriate for reading
-a key sequence to be defined.
-
-A C-g typed while in this function is treated like any other character,
-and `quit-flag' is not set.
-
-If the key sequence starts with a mouse click, then the sequence is read
-using the keymaps of the buffer of the window clicked in, not the buffer
-of the selected window as normal.
-
-`read-key-sequence' drops unbound button-down events, since you normally
-only care about the click or drag events which follow them. If a drag
-or multi-click event is unbound, but the corresponding click event would
-be bound, `read-key-sequence' turns the event into a click event at the
-drag's starting position. This means that you don't have to distinguish
-between click and drag, double, or triple events unless you want to.
-
-`read-key-sequence' prefixes mouse events on mode lines, the vertical
-lines separating windows, and scroll bars with imaginary keys
-`mode-line', `vertical-line', and `vertical-scroll-bar'.
-
-Optional fourth argument CAN-RETURN-SWITCH-FRAME non-nil means that this
-function will process a switch-frame event if the user switches frames
-before typing anything. If the user switches frames in the middle of a
-key sequence, or at the start of the sequence but CAN-RETURN-SWITCH-FRAME
-is nil, then the event will be put off until after the current key sequence.
-
-`read-key-sequence' checks `function-key-map' for function key
-sequences, where they wouldn't conflict with ordinary bindings. See
-`function-key-map' for more details.
-
-The optional fifth argument CMD-LOOP, if non-nil, means
-that this key sequence is being read by something that will
-read commands one after another. It should be nil if the caller
-will read just one key sequence. */)
- (Lisp_Object prompt, Lisp_Object continue_echo, Lisp_Object dont_downcase_last, Lisp_Object can_return_switch_frame, Lisp_Object cmd_loop)
+static Lisp_Object
+read_key_sequence_vs (Lisp_Object prompt, Lisp_Object continue_echo,
+ Lisp_Object dont_downcase_last,
+ Lisp_Object can_return_switch_frame,
+ Lisp_Object cmd_loop, bool allow_string)
{
Lisp_Object keybuf[30];
register int i;
memset (keybuf, 0, sizeof keybuf);
GCPRO1 (keybuf[0]);
- gcpro1.nvars = (sizeof keybuf/sizeof (keybuf[0]));
+ gcpro1.nvars = (sizeof keybuf / sizeof (keybuf[0]));
if (NILP (continue_echo))
{
cancel_hourglass ();
#endif
- i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])),
+ i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])),
prompt, ! NILP (dont_downcase_last),
- ! NILP (can_return_switch_frame), 0);
+ ! NILP (can_return_switch_frame), 0, 0);
#if 0 /* The following is fine for code reading a key sequence and
then proceeding with a lengthy computation, but it's not good
QUIT;
}
UNGCPRO;
- return unbind_to (count, make_event_array (i, keybuf));
+ return unbind_to (count,
+ ((allow_string ? make_event_array : Fvector)
+ (i, keybuf)));
}
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,
- Sread_key_sequence_vector, 1, 5, 0,
- doc: /* Like `read-key-sequence' but always return a vector. */)
- (Lisp_Object prompt, Lisp_Object continue_echo, Lisp_Object dont_downcase_last, Lisp_Object can_return_switch_frame, Lisp_Object cmd_loop)
-{
- Lisp_Object keybuf[30];
- register int i;
- struct gcpro gcpro1;
- ptrdiff_t count = SPECPDL_INDEX ();
-
- if (!NILP (prompt))
- CHECK_STRING (prompt);
- QUIT;
-
- specbind (Qinput_method_exit_on_first_char,
- (NILP (cmd_loop) ? Qt : Qnil));
- specbind (Qinput_method_use_echo_area,
- (NILP (cmd_loop) ? Qt : Qnil));
-
- memset (keybuf, 0, sizeof keybuf);
- GCPRO1 (keybuf[0]);
- gcpro1.nvars = (sizeof keybuf / sizeof (keybuf[0]));
-
- if (NILP (continue_echo))
- {
- this_command_key_count = 0;
- this_command_key_count_reset = 0;
- this_single_command_key_start = 0;
- }
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (display_hourglass_p)
- cancel_hourglass ();
-#endif
-
- i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])),
- prompt, ! NILP (dont_downcase_last),
- ! NILP (can_return_switch_frame), 0);
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (display_hourglass_p)
- start_hourglass ();
-#endif
-
- if (i == -1)
- {
- Vquit_flag = Qt;
- QUIT;
- }
- UNGCPRO;
- return unbind_to (count, Fvector (i, keybuf));
-}
-\f
-DEFUN ("command-execute", Fcommand_execute, Scommand_execute, 1, 4, 0,
- doc: /* Execute CMD as an editor command.
-CMD must be a symbol that satisfies the `commandp' predicate.
-Optional second arg RECORD-FLAG non-nil
-means unconditionally put this command in `command-history'.
-Otherwise, that is done only if an arg is read using the minibuffer.
-The argument KEYS specifies the value to use instead of (this-command-keys)
-when reading the arguments; if it is nil, (this-command-keys) is used.
-The argument SPECIAL, if non-nil, means that this command is executing
-a special event, so ignore the prefix argument and don't clear it. */)
- (Lisp_Object cmd, Lisp_Object record_flag, Lisp_Object keys, Lisp_Object special)
-{
- register Lisp_Object final;
- register Lisp_Object tem;
- Lisp_Object prefixarg;
-
- debug_on_next_call = 0;
-
- if (NILP (special))
- {
- prefixarg = KVAR (current_kboard, Vprefix_arg);
- Vcurrent_prefix_arg = prefixarg;
- kset_prefix_arg (current_kboard, Qnil);
- }
- else
- prefixarg = Qnil;
+DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 5, 0,
+ doc: /* Read a sequence of keystrokes and return as a string or vector.
+The sequence is sufficient to specify a non-prefix command in the
+current local and global maps.
- if (SYMBOLP (cmd))
- {
- tem = Fget (cmd, Qdisabled);
- if (!NILP (tem))
- {
- tem = Fsymbol_value (Qdisabled_command_function);
- if (!NILP (tem))
- return Frun_hooks (1, &Qdisabled_command_function);
- }
- }
+First arg PROMPT is a prompt string. If nil, do not prompt specially.
+Second (optional) arg CONTINUE-ECHO, if non-nil, means this key echos
+as a continuation of the previous key.
- while (1)
- {
- final = Findirect_function (cmd, Qnil);
+The third (optional) arg DONT-DOWNCASE-LAST, if non-nil, means do not
+convert the last event to lower case. (Normally any upper case event
+is converted to lower case if the original event is undefined and the lower
+case equivalent is defined.) A non-nil value is appropriate for reading
+a key sequence to be defined.
- if (CONSP (final) && (tem = Fcar (final), EQ (tem, Qautoload)))
- {
- struct gcpro gcpro1, gcpro2;
+A C-g typed while in this function is treated like any other character,
+and `quit-flag' is not set.
- GCPRO2 (cmd, prefixarg);
- Fautoload_do_load (final, cmd, Qnil);
- UNGCPRO;
- }
- else
- break;
- }
+If the key sequence starts with a mouse click, then the sequence is read
+using the keymaps of the buffer of the window clicked in, not the buffer
+of the selected window as normal.
- if (STRINGP (final) || VECTORP (final))
- {
- /* If requested, place the macro in the command history. For
- other sorts of commands, call-interactively takes care of
- this. */
- if (!NILP (record_flag))
- {
- Vcommand_history
- = Fcons (Fcons (Qexecute_kbd_macro,
- Fcons (final, Fcons (prefixarg, Qnil))),
- Vcommand_history);
+`read-key-sequence' drops unbound button-down events, since you normally
+only care about the click or drag events which follow them. If a drag
+or multi-click event is unbound, but the corresponding click event would
+be bound, `read-key-sequence' turns the event into a click event at the
+drag's starting position. This means that you don't have to distinguish
+between click and drag, double, or triple events unless you want to.
- /* Don't keep command history around forever. */
- if (NUMBERP (Vhistory_length) && XINT (Vhistory_length) > 0)
- {
- tem = Fnthcdr (Vhistory_length, Vcommand_history);
- if (CONSP (tem))
- XSETCDR (tem, Qnil);
- }
- }
+`read-key-sequence' prefixes mouse events on mode lines, the vertical
+lines separating windows, and scroll bars with imaginary keys
+`mode-line', `vertical-line', and `vertical-scroll-bar'.
- return Fexecute_kbd_macro (final, prefixarg, Qnil);
- }
+Optional fourth argument CAN-RETURN-SWITCH-FRAME non-nil means that this
+function will process a switch-frame event if the user switches frames
+before typing anything. If the user switches frames in the middle of a
+key sequence, or at the start of the sequence but CAN-RETURN-SWITCH-FRAME
+is nil, then the event will be put off until after the current key sequence.
- if (CONSP (final) || SUBRP (final) || COMPILEDP (final))
- /* Don't call Fcall_interactively directly because we want to make
- sure the backtrace has an entry for `call-interactively'.
- For the same reason, pass `cmd' rather than `final'. */
- return call3 (Qcall_interactively, cmd, record_flag, keys);
+`read-key-sequence' checks `function-key-map' for function key
+sequences, where they wouldn't conflict with ordinary bindings. See
+`function-key-map' for more details.
- return Qnil;
+The optional fifth argument CMD-LOOP, if non-nil, means
+that this key sequence is being read by something that will
+read commands one after another. It should be nil if the caller
+will read just one key sequence. */)
+ (Lisp_Object prompt, Lisp_Object continue_echo, Lisp_Object dont_downcase_last, Lisp_Object can_return_switch_frame, Lisp_Object cmd_loop)
+{
+ return read_key_sequence_vs (prompt, continue_echo, dont_downcase_last,
+ can_return_switch_frame, cmd_loop, true);
}
-
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,
+ Sread_key_sequence_vector, 1, 5, 0,
+ doc: /* Like `read-key-sequence' but always return a vector. */)
+ (Lisp_Object prompt, Lisp_Object continue_echo, Lisp_Object dont_downcase_last, Lisp_Object can_return_switch_frame, Lisp_Object cmd_loop)
+{
+ return read_key_sequence_vs (prompt, continue_echo, dont_downcase_last,
+ can_return_switch_frame, cmd_loop, false);
+}
\f
/* Return true if input events are pending. */
get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW);
if (old_timers_run != timers_run && do_display)
- {
- redisplay_preserve_echo_area (8);
- /* The following fixes a bug when using lazy-lock with
- lazy-lock-defer-on-the-fly set to t, i.e. when fontifying
- from an idle timer function. The symptom of the bug is that
- the cursor sometimes doesn't become visible until the next X
- event is processed. --gerd. */
- {
- Lisp_Object tail, frame;
- FOR_EACH_FRAME (tail, frame)
- if (FRAME_RIF (XFRAME (frame)))
- FRAME_RIF (XFRAME (frame))->flush_display (XFRAME (frame));
- }
- }
+ redisplay_preserve_echo_area (8);
return input_pending;
}
return (!NILP (Vunread_command_events));
}
-
-DEFUN ("input-pending-p", Finput_pending_p, Sinput_pending_p, 0, 0, 0,
+DEFUN ("input-pending-p", Finput_pending_p, Sinput_pending_p, 0, 1, 0,
doc: /* Return t if command input is currently available with no wait.
Actually, the value is nil only if we can be sure that no input is available;
-if there is a doubt, the value is t. */)
- (void)
+if there is a doubt, the value is t.
+
+If CHECK-TIMERS is non-nil, timers that are ready to run will do so. */)
+ (Lisp_Object check_timers)
{
if (!NILP (Vunread_command_events)
|| !NILP (Vunread_post_input_method_events)
/* Process non-user-visible events (Bug#10195). */
process_special_events ();
- return (get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW
+ return (get_input_pending ((NILP (check_timers)
+ ? 0 : READABLE_EVENTS_DO_TIMERS_NOW)
| READABLE_EVENTS_FILTER_EVENTS)
? Qt : Qnil);
}
The value is always a vector. */)
(void)
{
- return Fvector (raw_keybuf_count,
- (XVECTOR (raw_keybuf)->contents));
+ return Fvector (raw_keybuf_count, XVECTOR (raw_keybuf)->contents);
}
DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,
if (!NILP (file))
{
file = Fexpand_file_name (file, Qnil);
- dribble = fopen (SSDATA (file), "w");
+ dribble = emacs_fopen (SSDATA (file), "w");
if (dribble == 0)
- report_file_error ("Opening dribble", Fcons (file, Qnil));
+ report_file_error ("Opening dribble", file);
}
return Qnil;
}
end_kbd_macro ();
}
- update_mode_lines++;
-
Vunread_command_events = Qnil;
discard_tty_input ();
reset_all_sys_modes ();
/* sys_suspend can get an error if it tries to fork a subshell
and the system resources aren't available for that. */
- record_unwind_protect ((Lisp_Object (*) (Lisp_Object)) init_all_sys_modes,
- Qnil);
+ record_unwind_protect_void (init_all_sys_modes);
stuff_buffered_input (stuffstring);
if (cannot_suspend)
sys_subshell ();
with a window system; but suspend should be disabled in that case. */
get_tty_size (fileno (CURTTY ()->input), &width, &height);
if (width != old_width || height != old_height)
- change_frame_size (SELECTED_FRAME (), height, width, 0, 0, 0);
+ change_frame_size (SELECTED_FRAME (), width, height, 0, 0, 0, 0);
/* Run suspend-resume-hook. */
hook = intern ("suspend-resume-hook");
}
\f
void
-set_waiting_for_input (EMACS_TIME *time_to_clear)
+set_waiting_for_input (struct timespec *time_to_clear)
{
input_available_clear_time = time_to_clear;
fflush (stdout);
reset_all_sys_modes ();
-#ifdef SIGTSTP /* Support possible in later USG versions */
+#ifdef SIGTSTP
/*
* On systems which can suspend the current process and return to the original
* shell, this command causes the user to end up back at the shell.
if (tty->flow_control != !NILP (flow))
{
#ifndef DOS_NT
- /* this causes startup screen to be restored and messes with the mouse */
+ /* This causes startup screen to be restored and messes with the mouse. */
reset_sys_modes (tty);
#endif
return tem;
}
-\f
-/*
- * Set up a new kboard object with reasonable initial values.
- */
-void
-init_kboard (KBOARD *kb)
+/* Set up a new kboard object with reasonable initial values.
+ TYPE is a window system for which this keyboard is used. */
+
+static void
+init_kboard (KBOARD *kb, Lisp_Object type)
{
kset_overriding_terminal_local_map (kb, Qnil);
kset_last_command (kb, Qnil);
kb->reference_count = 0;
kset_system_key_alist (kb, Qnil);
kset_system_key_syms (kb, Qnil);
- kset_window_system (kb, Qt); /* Unset. */
+ kset_window_system (kb, type);
kset_input_decode_map (kb, Fmake_sparse_keymap (Qnil));
kset_local_function_key_map (kb, Fmake_sparse_keymap (Qnil));
Fset_keymap_parent (KVAR (kb, Vlocal_function_key_map), Vfunction_key_map);
kset_default_minibuffer_frame (kb, Qnil);
}
+/* Allocate and basically initialize keyboard
+ object to use with window system TYPE. */
+
+KBOARD *
+allocate_kboard (Lisp_Object type)
+{
+ KBOARD *kb = xmalloc (sizeof *kb);
+
+ init_kboard (kb, type);
+ kb->next_kboard = all_kboards;
+ all_kboards = kb;
+ return kb;
+}
+
/*
* Destroy the contents of a kboard object, but not the object itself.
* We use this just before deleting it, or if we're going to initialize
immediate_quit = 0;
quit_char = Ctl ('g');
Vunread_command_events = Qnil;
- timer_idleness_start_time = invalid_emacs_time ();
+ timer_idleness_start_time = invalid_timespec ();
total_keys = 0;
recent_keys_index = 0;
kbd_fetch_ptr = kbd_buffer;
kbd_store_ptr = kbd_buffer;
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
do_mouse_tracking = Qnil;
-#endif
input_pending = 0;
interrupt_input_blocked = 0;
pending_signals = 0;
current_kboard = initial_kboard;
/* Re-initialize the keyboard again. */
wipe_kboard (current_kboard);
- init_kboard (current_kboard);
/* A value of nil for Vwindow_system normally means a tty, but we also use
it for the initial terminal since there is no window system there. */
- kset_window_system (current_kboard, Qnil);
+ init_kboard (current_kboard, Qnil);
if (!noninteractive)
{
{&Qmouse_movement, "mouse-movement", &Qmouse_movement},
{&Qscroll_bar_movement, "scroll-bar-movement", &Qmouse_movement},
{&Qswitch_frame, "switch-frame", &Qswitch_frame},
+ {&Qfocus_in, "focus-in", &Qfocus_in},
+ {&Qfocus_out, "focus-out", &Qfocus_out},
{&Qdelete_frame, "delete-frame", &Qdelete_frame},
{&Qiconify_frame, "iconify-frame", &Qiconify_frame},
{&Qmake_frame_visible, "make-frame-visible", &Qmake_frame_visible},
DEFSYM (Qdbus_event, "dbus-event");
#endif
+#ifdef USE_FILE_NOTIFY
+ DEFSYM (Qfile_notify, "file-notify");
+#endif /* USE_FILE_NOTIFY */
+
DEFSYM (QCenable, ":enable");
DEFSYM (QCvisible, ":visible");
DEFSYM (QChelp, ":help");
DEFSYM (Qvertical_line, "vertical-line");
DEFSYM (Qvertical_scroll_bar, "vertical-scroll-bar");
DEFSYM (Qmenu_bar, "menu-bar");
+ DEFSYM (Qright_divider, "right-divider");
+ DEFSYM (Qbottom_divider, "bottom-divider");
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
DEFSYM (Qmouse_fixup_help_message, "mouse-fixup-help-message");
-#endif
DEFSYM (Qabove_handle, "above-handle");
DEFSYM (Qhandle, "handle");
DEFSYM (Qhelp_form_show, "help-form-show");
+ DEFSYM (Qecho_keystrokes, "echo-keystrokes");
+
Fset (Qinput_method_exit_on_first_char, Qnil);
Fset (Qinput_method_use_echo_area, Qnil);
- last_point_position_buffer = Qnil;
- last_point_position_window = Qnil;
-
{
int i;
int len = sizeof (head_table) / sizeof (head_table[0]);
*p->var = intern_c_string (p->name);
staticpro (p->var);
Fput (*p->var, Qevent_kind, *p->kind);
- Fput (*p->var, Qevent_symbol_elements, Fcons (*p->var, Qnil));
+ Fput (*p->var, Qevent_symbol_elements, list1 (*p->var));
}
}
raw_keybuf = Fmake_vector (make_number (30), Qnil);
staticpro (&raw_keybuf);
- DEFSYM (Qextended_command_history, "extended-command-history");
- Fset (Qextended_command_history, Qnil);
+ DEFSYM (Qcommand_execute, "command-execute");
accent_key_syms = Qnil;
staticpro (&accent_key_syms);
defsubr (&Sread_key_sequence);
defsubr (&Sread_key_sequence_vector);
defsubr (&Srecursive_edit);
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
defsubr (&Strack_mouse);
-#endif
defsubr (&Sinput_pending_p);
- defsubr (&Scommand_execute);
defsubr (&Srecent_keys);
defsubr (&Sthis_command_keys);
defsubr (&Sthis_command_keys_vector);
defsubr (&Sabort_recursive_edit);
defsubr (&Sexit_recursive_edit);
defsubr (&Srecursion_depth);
+ defsubr (&Scommand_error_default_function);
defsubr (&Stop_level);
defsubr (&Sdiscard_input);
defsubr (&Sopen_dribble_file);
to count as a drag. */);
double_click_fuzz = 3;
- DEFVAR_BOOL ("inhibit-local-menu-bar-menus", inhibit_local_menu_bar_menus,
- doc: /* Non-nil means inhibit local map menu bar menus. */);
- inhibit_local_menu_bar_menus = 0;
-
DEFVAR_INT ("num-input-keys", num_input_keys,
doc: /* Number of complete key sequences read as input so far.
This includes key sequences read from keyboard macros.
DEFVAR_KBOARD ("overriding-terminal-local-map",
Voverriding_terminal_local_map,
- doc: /* Per-terminal keymap that overrides all other local keymaps.
-If this variable is non-nil, it is used as a keymap instead of the
-buffer's local map, and the minor mode keymaps and text property keymaps.
-It also replaces `overriding-local-map'.
+ doc: /* Per-terminal keymap that takes precedence over all other keymaps.
This variable is intended to let commands such as `universal-argument'
set up a different keymap for reading the next command.
See Info node `(elisp)Multiple Terminals'. */);
DEFVAR_LISP ("overriding-local-map", Voverriding_local_map,
- doc: /* Keymap that overrides all other local keymaps.
+ doc: /* Keymap that overrides almost all other local keymaps.
If this variable is non-nil, it is used as a keymap--replacing the
buffer's local map, the minor mode keymaps, and char property keymaps. */);
Voverriding_local_map = Qnil;
DEFVAR_LISP ("special-event-map", Vspecial_event_map,
doc: /* Keymap defining bindings for special events to execute at low level. */);
- Vspecial_event_map = Fcons (intern_c_string ("keymap"), Qnil);
+ Vspecial_event_map = list1 (intern_c_string ("keymap"));
DEFVAR_LISP ("track-mouse", do_mouse_tracking,
doc: /* Non-nil means generate motion events for mouse motion. */);
and its return value (a key sequence) is used.
The events that come from bindings in `input-decode-map' are not
-themselves looked up in `input-decode-map'.
-
-This variable is keyboard-local. */);
+themselves looked up in `input-decode-map'. */);
DEFVAR_LISP ("function-key-map", Vfunction_key_map,
doc: /* The parent keymap of all `local-function-key-map' instances.
DEFVAR_LISP ("key-translation-map", Vkey_translation_map,
doc: /* Keymap of key translations that can override keymaps.
-This keymap works like `function-key-map', but comes after that,
-and its non-prefix bindings override ordinary bindings.
-Another difference is that it is global rather than keyboard-local. */);
+This keymap works like `input-decode-map', but comes after `function-key-map'.
+Another difference is that it is global rather than terminal-local. */);
Vkey_translation_map = Fmake_sparse_keymap (Qnil);
DEFVAR_LISP ("deferred-action-list", Vdeferred_action_list,
Vthrow_on_input = Qnil;
DEFVAR_LISP ("command-error-function", Vcommand_error_function,
- doc: /* If non-nil, function to output error messages.
-The arguments are the error data, a list of the form
- (SIGNALED-CONDITIONS . SIGNAL-DATA)
-such as just as `condition-case' would bind its variable to,
-the context (a string which normally goes at the start of the message),
-and the Lisp function within which the error was signaled. */);
- Vcommand_error_function = Qnil;
+ doc: /* Function to output error messages.
+Called with three arguments:
+- the error data, a list of the form (SIGNALED-CONDITION . SIGNAL-DATA)
+ such as what `condition-case' would bind its variable to,
+- the context (a string which normally goes at the start of the message),
+- the Lisp function within which the error was signaled. */);
+ Vcommand_error_function = intern ("command-error-default-function");
DEFVAR_LISP ("enable-disabled-menus-and-buttons",
Venable_disabled_menus_and_buttons,
Vsaved_region_selection,
doc: /* Contents of active region prior to buffer modification.
If `select-active-regions' is non-nil, Emacs sets this to the
-text in the region before modifying the buffer. The next
-`deactivate-mark' call uses this to set the window selection. */);
+text in the region before modifying the buffer. The next call to
+the function `deactivate-mark' uses this to set the window selection. */);
Vsaved_region_selection = Qnil;
DEFVAR_LISP ("selection-inhibit-update-commands",
variable are `sigusr1' and `sigusr2'. */);
Vdebug_on_event = intern_c_string ("sigusr2");
- /* Create the initial keyboard. */
- initial_kboard = xmalloc (sizeof *initial_kboard);
- init_kboard (initial_kboard);
- /* Vwindow_system is left at t for now. */
- initial_kboard->next_kboard = all_kboards;
- all_kboards = initial_kboard;
+ /* Create the initial keyboard. Qt means 'unset'. */
+ initial_kboard = allocate_kboard (Qt);
}
void
"dbus-handle-event");
#endif
+#ifdef USE_FILE_NOTIFY
+ /* Define a special event which is raised for notification callback
+ functions. */
+ initial_define_lispy_key (Vspecial_event_map, "file-notify",
+ "file-notify-handle-event");
+#endif /* USE_FILE_NOTIFY */
+
initial_define_lispy_key (Vspecial_event_map, "config-changed-event",
"ignore");
#if defined (WINDOWSNT)
initial_define_lispy_key (Vspecial_event_map, "language-change",
"ignore");
#endif
+ initial_define_lispy_key (Vspecial_event_map, "focus-in",
+ "handle-focus-in");
+ initial_define_lispy_key (Vspecial_event_map, "focus-out",
+ "handle-focus-out");
}
/* Mark the pointers in the kboard objects.