/* Keyboard and mouse input; editor command loop.
-Copyright (C) 1985-1989, 1993-1997, 1999-2014 Free Software Foundation,
-Inc.
+Copyright (C) 1985-1989, 1993-1997, 1999-2014 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <config.h>
#include "sysstdio.h"
+#include <sys/stat.h>
#include "lisp.h"
#include "termchar.h"
#include "systime.h"
#include "atimer.h"
#include "process.h"
+#include "guile.h"
#include <errno.h>
#ifdef HAVE_PTHREAD
#include TERM_HEADER
#endif /* HAVE_WINDOW_SYSTEM */
+#include <gc.h> /* for GC_collect_a_little */
+
/* Variables for blockinput.h: */
/* Positive if interrupt input is blocked right now. */
/* For longjmp to where kbd input is being done. */
-static sys_jmp_buf getcjmp;
+static Lisp_Object getctag;
/* True while doing kbd input. */
bool waiting_for_input;
Lisp_Object Qundefined;
static Lisp_Object Qtimer_event_handler;
-/* read_key_sequence stores here the command definition of the
+/* `read_key_sequence' stores here the command definition of the
key sequence that it reads. */
static Lisp_Object read_key_sequence_cmd;
static Lisp_Object read_key_sequence_remapped;
static void recursive_edit_unwind (Lisp_Object buffer);
static Lisp_Object command_loop (void);
static Lisp_Object Qcommand_execute;
-struct timespec timer_check (void);
static void echo_now (void);
static ptrdiff_t echo_length (void);
/* Nonzero while interrupts are temporarily deferred during redisplay. */
bool interrupts_deferred;
-/* If we support a window system, turn on the code to poll periodically
- to detect C-g. It isn't actually used when doing interrupt input. */
-#ifdef HAVE_WINDOW_SYSTEM
-#define POLL_FOR_INPUT
-#endif
-
/* The time when Emacs started being idle. */
static struct timespec timer_idleness_start_time;
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 void restore_kboard_configuration (int);
Lisp_Object
recursive_edit_1 (void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object val;
if (command_loop_level > 0)
if (STRINGP (val))
xsignal1 (Qerror, val);
- return unbind_to (count, Qnil);
+ dynwind_end ();
+ return Qnil;
}
/* When an auto-save happens, record the "time", and don't do again soon. */
This function is called by the editor initialization to begin editing. */)
(void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object buffer;
/* If we enter while input is blocked, don't lock up here.
This may happen through the debugger during redisplay. */
- if (input_blocked_p ())
+ if (input_blocked_p ()) {
+ dynwind_end ();
return Qnil;
+ }
- command_loop_level++;
- update_mode_lines = 17;
-
- if (command_loop_level
+ if (command_loop_level >= 0
&& current_buffer != XBUFFER (XWINDOW (selected_window)->contents))
buffer = Fcurrent_buffer ();
else
buffer = Qnil;
+ /* Don't do anything interesting between the increment and the
+ record_unwind_protect! Otherwise, we could get distracted and
+ never decrement the counter again. */
+ command_loop_level++;
+ update_mode_lines = 17;
+ record_unwind_protect (recursive_edit_unwind, buffer);
+
/* If we leave recursive_edit_1 below with a `throw' for instance,
like it is done in the splash screen display, we have to
make sure that we restore single_kboard as command_loop_1
would have done if it were left normally. */
if (command_loop_level > 0)
temporarily_switch_to_single_kboard (SELECTED_FRAME ());
- record_unwind_protect (recursive_edit_unwind, buffer);
recursive_edit_1 ();
- return unbind_to (count, Qnil);
+ dynwind_end ();
+ return Qnil;
}
void
value to us. A value of nil means that command_loop_1 itself
returned due to end of file (or end of kbd macro). */
+static Lisp_Object
+command_loop_2_body (void *ignore)
+{
+ return command_loop_1 ();
+}
+
+static Lisp_Object
+command_loop_2_handler (void *ignore, SCM key, SCM args)
+{
+ return Fsignal (Qerror,
+ list3 (build_string ("Scheme error"), key, args));
+}
+
+static Lisp_Object
+command_loop_2_inner (void)
+{
+ return scm_c_with_throw_handler (SCM_BOOL_T,
+ command_loop_2_body, NULL,
+ command_loop_2_handler, NULL,
+ 0);
+}
+
static Lisp_Object
command_loop_2 (Lisp_Object ignore)
{
register Lisp_Object val;
do
- val = internal_condition_case (command_loop_1, Qerror, cmd_error);
+ val = internal_condition_case (command_loop_2_inner, Qerror, cmd_error);
while (!NILP (val));
return Qnil;
}
static Lisp_Object
-top_level_2 (void)
+top_level_2_body (void *ignore)
{
return Feval (Vtop_level, Qnil);
}
+static Lisp_Object
+top_level_2 (void)
+{
+ return scm_c_with_throw_handler (SCM_BOOL_T,
+ top_level_2_body, NULL,
+ command_loop_2_handler, NULL,
+ 0);
+}
+
static Lisp_Object
top_level_1 (Lisp_Object ignore)
{
xsignal1 (Quser_error, build_string (msg));
}
-_Noreturn
+/* _Noreturn will be added to prototype by make-docfile. */
DEFUN ("exit-recursive-edit", Fexit_recursive_edit, Sexit_recursive_edit, 0, 0, "",
doc: /* Exit from the innermost recursive edit or minibuffer. */)
(void)
user_error ("No recursive edit is in progress");
}
-_Noreturn
+/* _Noreturn will be added to prototype by make-docfile. */
DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0, 0, "",
doc: /* Abort the command that requested this recursive edit or minibuffer input. */)
(void)
}
}
-DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0,
+DEFUN ("call-with-track-mouse", Ftrack_mouse, Strack_mouse, 1, 1, 0,
doc: /* Evaluate BODY with mouse movement events enabled.
Within a `track-mouse' form, mouse motion generates input events that
you can read with `read-event'.
Normally, mouse motion is ignored.
usage: (track-mouse BODY...) */)
- (Lisp_Object args)
+ (Lisp_Object thunk)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object val;
record_unwind_protect (tracking_off, do_mouse_tracking);
do_mouse_tracking = Qt;
- val = Fprogn (args);
- return unbind_to (count, val);
+ val = call0 (thunk);
+ dynwind_end ();
+ return val;
}
/* If mouse has moved on some frame, return one of those frames.
If ignore_mouse_drag_p is non-zero, ignore (implicit) mouse movement
after resizing the tool-bar window. */
-#if !defined HAVE_WINDOW_SYSTEM || defined USE_GTK || defined HAVE_NS
-static
-#endif
bool ignore_mouse_drag_p;
static struct frame *
static int read_key_sequence (Lisp_Object *, int, Lisp_Object,
bool, bool, bool, bool);
-void safe_run_hooks (Lisp_Object);
static void adjust_point_for_property (ptrdiff_t, bool);
/* 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, ... */
{
/* Bind inhibit-quit to t so that C-g gets read in
rather than quitting back to the minibuffer. */
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
specbind (Qinhibit_quit, Qt);
sit_for (Vminibuffer_message_timeout, 0, 2);
message1 (0);
safe_run_hooks (Qecho_area_clear_hook);
- unbind_to (count, Qnil);
+ dynwind_end ();
/* If a C-g came in before, treat it as input now. */
if (!NILP (Vquit_flag))
Vthis_command_keys_shift_translated = Qnil;
/* Read next key sequence; i gets its length. */
- i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
+ i = read_key_sequence (keybuf, ARRAYELTS (keybuf),
Qnil, 0, 1, 1, 0);
/* A filter may have run while we were reading the input. */
/* Here for a command that isn't executed directly. */
#ifdef HAVE_WINDOW_SYSTEM
- ptrdiff_t scount = SPECPDL_INDEX ();
+ dynwind_begin ();
if (display_hourglass_p
&& NILP (Vexecuting_kbd_macro))
hourglass cursor anyway.
But don't cancel the hourglass within a macro
just because a command in the macro finishes. */
- if (NILP (Vexecuting_kbd_macro))
- unbind_to (scount, Qnil);
+ dynwind_end ();
#endif
}
kset_last_prefix_arg (current_kboard, Vcurrent_prefix_arg);
read_menu_command (void)
{
Lisp_Object keybuf[30];
- ptrdiff_t count = SPECPDL_INDEX ();
+ scm_dynwind_begin (0);
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],
+ i = read_key_sequence (keybuf, ARRAYELTS (keybuf),
Qnil, 0, 1, 1, 1);
- unbind_to (count, Qnil);
+ scm_dynwind_end ();
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
Fkill_emacs (Qnil);
/* FIXME: our `internal_condition_case' does not provide any way to pass data
to its body or to its handlers other than via globals such as
dynamically-bound variables ;-) */
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
specbind (Qinhibit_quit, hook);
run_hook_with_args (1, &hook, safe_run_hook_funcall);
- unbind_to (count, Qnil);
+ dynwind_end ();
}
\f
-/* Nonzero means polling for input is temporarily suppressed. */
-
-int poll_suppress_count;
-
-
#ifdef POLL_FOR_INPUT
/* Asynchronous timer for polling. */
static void
poll_for_input (struct atimer *timer)
{
- if (poll_suppress_count == 0)
- pending_signals = 1;
}
#endif /* POLL_FOR_INPUT */
poll_timer = start_atimer (ATIMER_CONTINUOUS, interval,
poll_for_input, NULL);
}
-
- /* Let the timer's callback function poll for input
- if this becomes zero. */
- --poll_suppress_count;
}
#endif
}
#endif
}
-/* Turn off polling. */
-
-void
-stop_polling (void)
-{
-#ifdef POLL_FOR_INPUT
- /* XXX This condition was (read_socket_hook && !interrupt_input),
- but read_socket_hook is not global anymore. Let's pretend that
- it's always set. */
- if (!interrupt_input)
- ++poll_suppress_count;
-#endif
-}
-
-/* Set the value of poll_suppress_count to COUNT
- and start or stop polling accordingly. */
-
-void
-set_poll_suppress_count (int count)
-{
-#ifdef POLL_FOR_INPUT
- if (count == 0 && poll_suppress_count != 0)
- {
- poll_suppress_count = 1;
- start_polling ();
- }
- else if (count != 0 && poll_suppress_count == 0)
- {
- stop_polling ();
- }
- poll_suppress_count = count;
-#endif
-}
-
/* Bind polling_period to a value at least N.
But don't decrease it. */
bind_polling_period (int n)
{
#ifdef POLL_FOR_INPUT
- EMACS_INT new = polling_period;
+ EMACS_INT new = max (polling_period, new);
if (n > new)
new = n;
stop_other_atimers (poll_timer);
- stop_polling ();
specbind (Qpolling_period, make_number (new));
/* Start a new alarm with the new period. */
start_polling ();
\f
/* Apply the control modifier to CHARACTER. */
-#ifndef HAVE_NTGUI
-static
-#endif
int
make_ctrl_char (int c)
{
/* Save the upper bits here. */
int upper = c & ~0177;
- if (! ASCII_BYTE_P (c))
+ if (! ASCII_CHAR_P (c))
return c |= ctrl_modifier;
c &= 0177;
\f
-/* Input of single characters from keyboard */
+/* Input of single characters from keyboard. */
static Lisp_Object kbd_buffer_get_event (KBOARD **kbp, bool *used_mouse_menu,
struct timespec *end_time);
Fset_window_configuration (window_config);
}
-#define STOP_POLLING \
-do { if (! polling_stopped_here) stop_polling (); \
- polling_stopped_here = 1; } while (0)
-
-#define RESUME_POLLING \
-do { if (polling_stopped_here) start_polling (); \
- polling_stopped_here = 0; } while (0)
-
static Lisp_Object
read_event_from_main_queue (struct timespec *end_time,
- sys_jmp_buf local_getcjmp,
+ Lisp_Object local_tag,
bool *used_mouse_menu)
{
Lisp_Object c = Qnil;
- sys_jmp_buf save_jump;
+ Lisp_Object save_tag = Qnil;
+ sys_jmp_buf *save_jump = xmalloc (sizeof *save_jump);
KBOARD *kb IF_LINT (= NULL);
start:
return c;
/* Actually read a character, waiting if necessary. */
- save_getcjmp (save_jump);
- restore_getcjmp (local_getcjmp);
+ save_tag = getctag;
+ getctag = local_tag;
if (!end_time)
timer_start_idle ();
c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time);
- restore_getcjmp (save_jump);
+ getctag = save_tag;
if (! NILP (c) && (kb != current_kboard))
{
to tty input. */
static Lisp_Object
read_decoded_event_from_main_queue (struct timespec *end_time,
- sys_jmp_buf local_getcjmp,
+ Lisp_Object local_getcjmp,
Lisp_Object prev_event,
bool *used_mouse_menu)
{
}
}
+static bool
+echo_keystrokes_p (void)
+{
+ return (FLOATP (Vecho_keystrokes) ? XFLOAT_DATA (Vecho_keystrokes) > 0.0
+ : INTEGERP (Vecho_keystrokes) ? XINT (Vecho_keystrokes) > 0 : false);
+}
+
/* 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 MAP is for menu prompting. MAP is a keymap.
+/* The argument MAP is a keymap for menu prompting.
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 t if we showed a menu and the user rejected it. */
+struct read_char_state
+{
+ int commandflag;
+ Lisp_Object map;
+ Lisp_Object prev_event;
+ bool *used_mouse_menu;
+ struct timespec *end_time;
+ Lisp_Object c;
+ Lisp_Object tag;
+ Lisp_Object local_tag;
+ Lisp_Object save_tag;
+ Lisp_Object previous_echo_area_message;
+ Lisp_Object also_record;
+ bool reread;
+ bool polling_stopped_here;
+ struct kboard *orig_kboard;
+};
+
+static Lisp_Object read_char_1 (bool, volatile struct read_char_state *);
+
+static Lisp_Object
+read_char_thunk (void *data)
+{
+ return read_char_1 (false, data);
+}
+
+static Lisp_Object
+read_char_handle_quit (void *data, Lisp_Object k)
+{
+ struct read_char_state *state = data;
+ /* Handle quits while reading the keyboard. */
+ /* We must have saved the outer value of getcjmp here,
+ so restore it now. */
+ getctag = state->save_tag;
+ XSETINT (state->c, quit_char);
+ internal_last_event_frame = selected_frame;
+ Vlast_event_frame = internal_last_event_frame;
+ /* If we report the quit char as an event,
+ don't do so more than once. */
+ if (!NILP (Vinhibit_quit))
+ Vquit_flag = Qnil;
+
+ {
+ KBOARD *kb = FRAME_KBOARD (XFRAME (selected_frame));
+ if (kb != current_kboard)
+ {
+ Lisp_Object last = KVAR (kb, kbd_queue);
+ /* We shouldn't get here if we were in single-kboard mode! */
+ if (single_kboard)
+ emacs_abort ();
+ if (CONSP (last))
+ {
+ while (CONSP (XCDR (last)))
+ last = XCDR (last);
+ if (!NILP (XCDR (last)))
+ emacs_abort ();
+ }
+ if (!CONSP (last))
+ kset_kbd_queue (kb, list1 (state->c));
+ else
+ XSETCDR (last, list1 (state->c));
+ kb->kbd_queue_has_data = 1;
+ current_kboard = kb;
+ /* This is going to exit from read_char
+ so we had better get rid of this frame's stuff. */
+ UNGCPRO;
+ return make_number (-2); /* wrong_kboard_jmpbuf */
+ }
+ }
+ return read_char_1 (true, state);
+}
+
+/* {{coccinelle:skip_start}} */
Lisp_Object
read_char (int commandflag, Lisp_Object map,
Lisp_Object prev_event,
bool *used_mouse_menu, struct timespec *end_time)
{
- Lisp_Object c;
- ptrdiff_t jmpcount;
- sys_jmp_buf local_getcjmp;
- sys_jmp_buf save_jump;
- Lisp_Object tem, save;
- volatile Lisp_Object previous_echo_area_message;
- volatile Lisp_Object also_record;
- volatile bool reread;
- struct gcpro gcpro1, gcpro2;
- bool volatile polling_stopped_here = 0;
- struct kboard *orig_kboard = current_kboard;
+ struct read_char_state *state = xmalloc (sizeof *state);
+
+ state->commandflag = commandflag;
+ state->map = map;
+ state->prev_event = prev_event;
+ state->used_mouse_menu = used_mouse_menu;
+ state->end_time = end_time;
+ state->c = Qnil;
+ state->local_tag = Qnil;
+ state->save_tag = Qnil;
+ state->previous_echo_area_message = Qnil;
+ state->also_record = Qnil;
+ state->reread = false;
+ state->polling_stopped_here = false;
+ state->orig_kboard = current_kboard;
- also_record = Qnil;
+ /* Make a longjmp point for quits to use, but don't alter getcjmp just yet.
+ We will do that below, temporarily for short sections of code,
+ when appropriate. local_getcjmp must be in effect
+ around any call to sit_for or kbd_buffer_get_event;
+ it *must not* be in effect when we call redisplay. */
-#if 0 /* This was commented out as part of fixing echo for C-u left. */
- before_command_key_count = this_command_key_count;
- before_command_echo_length = echo_length ();
-#endif
- c = Qnil;
- previous_echo_area_message = Qnil;
+ state->tag = state->local_tag = make_prompt_tag ();
- GCPRO2 (c, previous_echo_area_message);
+ return call_with_prompt (state->tag,
+ make_c_closure (read_char_thunk, state, 0, 0),
+ make_c_closure (read_char_handle_quit, state, 1, 0));
+}
+
+static Lisp_Object
+read_char_1 (bool jump, volatile struct read_char_state *state)
+{
+#define commandflag state->commandflag
+#define map state->map
+#define prev_event state->prev_event
+#define used_mouse_menu state->used_mouse_menu
+#define end_time state->end_time
+#define c state->c
+#define jmpcount state->jmpcount
+#define local_getcjmp state->local_tag
+#define save_jump state->save_tag
+#define previous_echo_area_message state->previous_echo_area_message
+#define also_record state->also_record
+#define reread state->reread
+#define polling_stopped_here state->polling_stopped_here
+#define orig_kboard state->orig_kboard
+#define save_getcjmp(x) (x = getctag)
+#define restore_getcjmp(x) (getctag = x)
+ Lisp_Object tem, save;
+
+ if (jump)
+ goto non_reread;
retry:
- reread = 0;
if (CONSP (Vunread_post_input_method_events))
{
c = XCAR (Vunread_post_input_method_events);
&& NILP (XCDR (c)))
c = XCAR (c);
- reread = 1;
+ reread = true;
goto reread_first;
}
+ else
+ reread = false;
+
if (CONSP (Vunread_command_events))
{
c = XCAR (Vunread_command_events);
Vunread_command_events = XCDR (Vunread_command_events);
- reread = 1;
-
/* Undo what sit-for did when it unread additional keys
inside universal-argument. */
- if (CONSP (c)
- && EQ (XCAR (c), Qt))
- {
- reread = 0;
- c = XCDR (c);
- }
+ if (CONSP (c) && EQ (XCAR (c), Qt))
+ c = XCDR (c);
+ else
+ reread = true;
/* Undo what read_char_x_menu_prompt did when it unread
additional keys returned by Fx_popup_menu. */
&& (SYMBOLP (XCAR (c)) || INTEGERP (XCAR (c)))
&& NILP (XCDR (c)))
c = XCAR (c);
- reread = 1;
+ reread = true;
goto reread_for_input_method;
}
goto exit;
}
- /* Make a longjmp point for quits to use, but don't alter getcjmp just yet.
- We will do that below, temporarily for short sections of code,
- when appropriate. local_getcjmp must be in effect
- around any call to sit_for or kbd_buffer_get_event;
- it *must not* be in effect when we call redisplay. */
-
- jmpcount = SPECPDL_INDEX ();
- if (sys_setjmp (local_getcjmp))
- {
- /* Handle quits while reading the keyboard. */
- /* We must have saved the outer value of getcjmp here,
- so restore it now. */
- restore_getcjmp (save_jump);
- unbind_to (jmpcount, Qnil);
- XSETINT (c, quit_char);
- internal_last_event_frame = selected_frame;
- Vlast_event_frame = internal_last_event_frame;
- /* If we report the quit char as an event,
- don't do so more than once. */
- if (!NILP (Vinhibit_quit))
- Vquit_flag = Qnil;
-
- {
- KBOARD *kb = FRAME_KBOARD (XFRAME (selected_frame));
- if (kb != current_kboard)
- {
- Lisp_Object last = KVAR (kb, kbd_queue);
- /* We shouldn't get here if we were in single-kboard mode! */
- if (single_kboard)
- emacs_abort ();
- 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;
- current_kboard = kb;
- /* This is going to exit from read_char
- so we had better get rid of this frame's stuff. */
- UNGCPRO;
- return make_number (-2); /* wrong_kboard_jmpbuf */
- }
- }
- goto non_reread;
- }
-
/* Start idle timers if no time limit is supplied. We don't do it
if a time limit is supplied to avoid an infinite recursion in the
situation where an idle timer calls `sit-for'. */
&& !current_kboard->immediate_echo
&& this_command_key_count > 0
&& ! noninteractive
- && (FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
- && NILP (Fzerop (Vecho_keystrokes))
+ && echo_keystrokes_p ()
&& (/* No message. */
NILP (echo_area_buffer[0])
/* Or empty message. */
/* If there is still no input available, ask for GC. */
if (!detect_input_pending_run_timers (0))
- maybe_gc ();
+ GC_collect_a_little ();
}
/* Notify the caller if an autosave hook, or a timer, sentinel or
{
c = XCAR (Vunread_command_events);
Vunread_command_events = XCDR (Vunread_command_events);
+
+ if (CONSP (c) && EQ (XCAR (c), Qt))
+ c = XCDR (c);
+ else
+ reread = true;
}
/* Read something from current KBOARD's side queue, if possible. */
wrong_kboard:
- STOP_POLLING;
-
if (NILP (c))
{
c = read_decoded_event_from_main_queue (end_time, local_getcjmp,
prev_event, used_mouse_menu);
- if (NILP(c) && end_time &&
- timespec_cmp (*end_time, current_timespec ()) <= 0)
+ if (NILP (c) && end_time
+ && timespec_cmp (*end_time, current_timespec ()) <= 0)
{
goto exit;
}
if (!end_time)
timer_stop_idle ();
- RESUME_POLLING;
if (NILP (c))
{
ptrdiff_t key_count;
bool key_count_reset;
struct gcpro gcpro1;
- ptrdiff_t count = SPECPDL_INDEX ();
/* Save the echo status. */
bool saved_immediate_echo = current_kboard->immediate_echo;
Lisp_Object saved_echo_string = KVAR (current_kboard, echo_string);
ptrdiff_t saved_echo_after_prompt = current_kboard->echo_after_prompt;
+ dynwind_begin ();
+
#if 0
if (before_command_restore_flag)
{
/* Call the input method. */
tem = call1 (Vinput_method_function, c);
- tem = unbind_to (count, tem);
+ dynwind_end ();
/* Restore the saved echoing state
and this_command_keys state. */
{
/* Don't echo mouse motion events. */
- if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
- && NILP (Fzerop (Vecho_keystrokes))
+ if (echo_keystrokes_p ()
&& ! (EVENT_HAS_PARAMETERS (c)
&& EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
{
/* Process the help character specially if enabled. */
if (!NILP (Vhelp_form) && help_char_p (c))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
help_form_saved_window_configs
= Fcons (Fcurrent_window_configuration (Qnil),
}
while (BUFFERP (c));
/* Remove the help from the frame. */
- unbind_to (count, Qnil);
+ dynwind_end ();
redisplay ();
if (EQ (c, make_number (040)))
}
exit:
- RESUME_POLLING;
RETURN_UNGCPRO (c);
-}
+#undef commandflag
+#undef map
+#undef prev_event
+#undef used_mouse_menu
+#undef end_time
+#undef c
+#undef jmpcount
+#undef local_getcjmp
+#undef save_jump
+#undef previous_echo_area_message
+#undef also_record
+#undef reread
+#undef polling_stopped_here
+#undef orig_kboard
+#undef save_getcjmp
+#undef restore_getcjmp
+}
+/* {{coccinelle:skip_end}} */
/* Record a key that came from a mouse menu.
Record it for echoing, for this-command-keys, and so on. */
#endif
/* Don't echo mouse motion events. */
- if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
- && NILP (Fzerop (Vecho_keystrokes)))
+ if (echo_keystrokes_p ())
{
echo_char (c);
unblock_input ();
}
}
-
-/* Copy out or in the info on where C-g should throw to.
- This is used when running Lisp code from within get_char,
- in case get_char is called recursively.
- See read_process_output. */
-
-static void
-save_getcjmp (sys_jmp_buf temp)
-{
- memcpy (temp, getcjmp, sizeof getcjmp);
-}
-
-static void
-restore_getcjmp (sys_jmp_buf temp)
-{
- memcpy (getcjmp, temp, sizeof getcjmp);
-}
\f
/* Low level keyboard/mouse input.
kbd_buffer_store_event places events in kbd_buffer, and
*kbd_store_ptr = *event;
++kbd_store_ptr;
#ifdef subprocesses
- if (kbd_buffer_nr_stored () > KBD_BUFFER_SIZE/2 && ! kbd_on_hold_p ())
+ if (kbd_buffer_nr_stored () > KBD_BUFFER_SIZE / 2
+ && ! kbd_on_hold_p ())
{
/* Don't read keyboard input until we have processed kbd_buffer.
This happens when pasting text longer than KBD_BUFFER_SIZE/2. */
hold_keyboard_input ();
if (!noninteractive)
ignore_sigio ();
- stop_polling ();
}
#endif /* subprocesses */
}
/* Start reading input again because we have processed enough to
be able to accept new events again. */
unhold_keyboard_input ();
- start_polling ();
}
#endif /* subprocesses */
{
if (NILP (AREF (chosen_timer, 0)))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object old_deactivate_mark = Vdeactivate_mark;
/* Mark the timer as triggered to prevent problems if the lisp
call1 (Qtimer_event_handler, chosen_timer);
Vdeactivate_mark = old_deactivate_mark;
timers_run++;
- unbind_to (count, Qnil);
+ dynwind_end ();
/* Since we have handled the event,
we don't need to tell the caller to wake up and do it. */
/* It's a click in window WINDOW at frame coordinates (X,Y) */
struct window *w = XWINDOW (window);
Lisp_Object string_info = Qnil;
- ptrdiff_t textpos = -1;
+ ptrdiff_t textpos = 0;
int col = -1, row = -1;
int dx = -1, dy = -1;
int width = -1, height = -1;
&object, &dx, &dy, &width, &height);
if (STRINGP (string))
string_info = Fcons (string, make_number (charpos));
- textpos = (w == XWINDOW (selected_window)
- && current_buffer == XBUFFER (w->contents))
- ? PT : marker_position (w->pointm);
+ textpos = -1;
xret = wx;
yret = wy;
/* For clicks in the text area, fringes, or margins, call
buffer_posn_from_coords to extract TEXTPOS, the buffer
position nearest to the click. */
- if (textpos < 0)
+ if (!textpos)
{
Lisp_Object string2, object2 = Qnil;
struct display_pos p;
}
#endif
- /* Object info */
+ /* Object info. */
extra_info
= list3 (object,
Fcons (make_number (dx), make_number (dy)),
Fcons (make_number (width), make_number (height)));
- /* String info */
+ /* String info. */
extra_info = Fcons (string_info,
- Fcons (make_number (textpos),
+ Fcons (textpos < 0 ? Qnil : make_number (textpos),
Fcons (Fcons (make_number (col),
make_number (row)),
extra_info)));
case NON_ASCII_KEYSTROKE_EVENT:
button_down_time = 0;
- for (i = 0; i < sizeof (lispy_accent_codes) / sizeof (int); i++)
+ for (i = 0; i < ARRAYELTS (lispy_accent_codes); i++)
if (event->code == lispy_accent_codes[i])
return modify_event_symbol (i,
event->modifiers,
Qfunction_key, Qnil,
lispy_accent_keys, &accent_key_syms,
- (sizeof (lispy_accent_keys)
- / sizeof (lispy_accent_keys[0])));
+ ARRAYELTS (lispy_accent_keys));
#if 0
#ifdef XK_kana_A
event->modifiers & ~shift_modifier,
Qfunction_key, Qnil,
lispy_kana_keys, &func_key_syms,
- (sizeof (lispy_kana_keys)
- / sizeof (lispy_kana_keys[0])));
+ ARRAYELTS (lispy_kana_keys));
#endif /* XK_kana_A */
#endif /* 0 */
event->modifiers,
Qfunction_key, Qnil,
iso_lispy_function_keys, &func_key_syms,
- (sizeof (iso_lispy_function_keys)
- / sizeof (iso_lispy_function_keys[0])));
+ ARRAYELTS (iso_lispy_function_keys));
#endif
/* Handle system-specific or unknown keysyms. */
if (event->code & (1 << 28)
|| event->code - FUNCTION_KEY_OFFSET < 0
|| (event->code - FUNCTION_KEY_OFFSET
- >= sizeof lispy_function_keys / sizeof *lispy_function_keys)
+ >= ARRAYELTS (lispy_function_keys))
|| !lispy_function_keys[event->code - FUNCTION_KEY_OFFSET])
{
/* We need to use an alist rather than a vector as the cache
event->modifiers,
Qfunction_key, Qnil,
lispy_function_keys, &func_key_syms,
- (sizeof (lispy_function_keys)
- / sizeof (lispy_function_keys[0])));
+ ARRAYELTS (lispy_function_keys));
#ifdef HAVE_NTGUI
case MULTIMEDIA_KEY_EVENT:
- if (event->code < (sizeof (lispy_multimedia_keys)
- / sizeof (lispy_multimedia_keys[0]))
+ if (event->code < ARRAYELTS (lispy_multimedia_keys)
&& event->code > 0 && lispy_multimedia_keys[event->code])
{
return modify_event_symbol (event->code, event->modifiers,
Qfunction_key, Qnil,
lispy_multimedia_keys, &func_key_syms,
- (sizeof (lispy_multimedia_keys)
- / sizeof (lispy_multimedia_keys[0])));
+ ARRAYELTS (lispy_multimedia_keys));
}
return Qnil;
#endif
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, "alt", "super", "hyper", "shift", "control", "meta"
};
-#define NUM_MOD_NAMES (sizeof (modifier_names) / sizeof (modifier_names[0]))
+#define NUM_MOD_NAMES ARRAYELTS (modifier_names)
static Lisp_Object modifier_symbols;
event.arg = Qnil;
/* Make sure no interrupt happens while storing the event. */
-#ifdef USABLE_SIGIO
- if (interrupt_input)
- kbd_buffer_store_event (&event);
- else
-#endif
- {
- stop_polling ();
- kbd_buffer_store_event (&event);
- start_polling ();
- }
+ kbd_buffer_store_event (&event);
}
}
}
}
+ /* If there was no error, make sure the pointer
+ is visible for all frames on this terminal. */
+ if (nr >= 0)
+ {
+ Lisp_Object tail, frame;
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ struct frame *f = XFRAME (frame);
+ if (FRAME_TERMINAL (f) == t)
+ frame_make_pointer_visible (f);
+ }
+ }
+
if (hold_quit.kind != NO_EVENT)
kbd_buffer_store_event (&hold_quit);
}
if (err && !nread)
nread = -1;
- frame_make_pointer_visible ();
-
return nread;
}
/* End critical section.
If doing signal-driven input, and a signal came in when input was
- blocked, reinvoke the signal handler now to deal with it. */
+ blocked, reinvoke the signal handler now to deal with it.
+
+ It will also process queued input, if it was not read before.
+ When a longer code sequence does not use block/unblock input
+ at all, the whole input gathered up to the next call to
+ unblock_input will be processed inside that call. */
void
unblock_input (void)
}
\f
-static void menu_bar_item (Lisp_Object, Lisp_Object, Lisp_Object, void*);
+static void menu_bar_item (Lisp_Object, Lisp_Object, Lisp_Object, void *);
static Lisp_Object menu_bar_one_keymap_changed_items;
/* These variables hold the vector under construction within
static int menu_bar_items_index;
-static const char* separator_names[] = {
+static const char *separator_names[] = {
"space",
"no-line",
"single-line",
{
int i = menu_bar_items_index;
if (i + 4 > ASIZE (menu_bar_items_vector))
- menu_bar_items_vector =
- larger_vector (menu_bar_items_vector, 4, -1);
+ menu_bar_items_vector
+ = larger_vector (menu_bar_items_vector, 4, -1);
/* Add this item. */
ASET (menu_bar_items_vector, i, Qnil); i++;
ASET (menu_bar_items_vector, i, Qnil); i++;
Lisp_Object
menu_item_eval_property (Lisp_Object sexpr)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object val;
specbind (Qinhibit_redisplay, Qt);
val = internal_condition_case_1 (eval_dyn, sexpr, Qerror,
menu_item_eval_property_1);
- return unbind_to (count, val);
+ dynwind_end ();
+ return val;
}
/* This function parses a menu item and leaves the result in the
(such as lmenu.el set it up), check if the
original command matches the cached command. */
&& !(SYMBOLP (def)
- && EQ (tem, XSYMBOL (def)->function))))
+ && EQ (tem, SYMBOL_FUNCTION (def)))))
keys = Qnil;
}
/* Function prototypes. */
static void init_tool_bar_items (Lisp_Object);
-static void process_tool_bar_item (Lisp_Object, Lisp_Object, Lisp_Object, void*);
+static void process_tool_bar_item (Lisp_Object, Lisp_Object, Lisp_Object,
+ void *);
static bool parse_tool_bar_item (Lisp_Object, Lisp_Object);
static void append_tool_bar_item (void);
const char *capt = STRINGP (tcapt) ? SSDATA (tcapt) : "";
ptrdiff_t max_lbl =
2 * max (0, min (tool_bar_max_label_size, STRING_BYTES_BOUND / 2));
- char *buf = xmalloc (max_lbl + 1);
+ char *buf = xmalloc_atomic (max_lbl + 1);
Lisp_Object new_lbl;
ptrdiff_t caption_len = strlen (capt);
/* Handle a symbol whose function definition is a keymap
or an array. */
if (SYMBOLP (next) && !NILP (Ffboundp (next))
- && (ARRAYP (XSYMBOL (next)->function)
- || KEYMAPP (XSYMBOL (next)->function)))
- next = Fautoload_do_load (XSYMBOL (next)->function, next, Qnil);
+ && (ARRAYP (SYMBOL_FUNCTION (next))
+ || KEYMAPP (SYMBOL_FUNCTION (next))))
+ next = Fautoload_do_load (SYMBOL_FUNCTION (next),
+ next, Qnil);
/* If the keymap gives a function, not an
array, then call the function with one arg and use
bool dont_downcase_last, bool can_return_switch_frame,
bool fix_current_buffer, bool prevent_redisplay)
{
- ptrdiff_t count = SPECPDL_INDEX ();
-
/* How many keys there are in the current key sequence. */
int t;
struct gcpro gcpro1;
+ dynwind_begin ();
+
GCPRO1 (fake_prefixed_keys);
raw_keybuf_count = 0;
echo_now ();
}
else if (cursor_in_echo_area
- && (FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
- && NILP (Fzerop (Vecho_keystrokes)))
+ && echo_keystrokes_p ())
/* This doesn't put in a dash if the echo buffer is empty, so
you don't always see a dash hanging out in the minibuffer. */
echo_dash ();
{
key = keybuf[t];
add_command_key (key);
- if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
- && NILP (Fzerop (Vecho_keystrokes))
+ if (echo_keystrokes_p ()
&& current_kboard->immediate_echo)
{
echo_add_key (key);
Just return -1. */
if (EQ (key, Qt))
{
- unbind_to (count, Qnil);
+ dynwind_end ();
UNGCPRO;
return -1;
}
first_unbound = min (t, first_unbound);
head = EVENT_HEAD (key);
- if (help_char_p (head) && t > 0)
- {
- read_key_sequence_cmd = Vprefix_help_command;
- keybuf[t++] = key;
- last_nonmenu_event = key;
- /* The Microsoft C compiler can't handle the goto that
- would go here. */
- dummyflag = 1;
- break;
- }
if (SYMBOLP (head))
{
goto replay_sequence;
}
+
+ if (NILP (current_binding)
+ && help_char_p (EVENT_HEAD (key)) && t > 1)
+ {
+ read_key_sequence_cmd = Vprefix_help_command;
+ /* The Microsoft C compiler can't handle the goto that
+ would go here. */
+ dummyflag = 1;
+ break;
+ }
+
/* If KEY is not defined in any of the keymaps,
and cannot be part of a function key or translation,
and is a shifted function key,
: Qnil;
unread_switch_frame = delayed_switch_frame;
- unbind_to (count, Qnil);
+ dynwind_end ();
/* Don't downcase the last character if the caller says don't.
Don't downcase it if the result is undefined, either. */
Better ideas? */
for (; t < mock_input; t++)
{
- if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
- && NILP (Fzerop (Vecho_keystrokes)))
+ if (echo_keystrokes_p ())
echo_char (keybuf[t]);
add_command_key (keybuf[t]);
}
Lisp_Object keybuf[30];
register int i;
struct gcpro gcpro1;
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
if (!NILP (prompt))
CHECK_STRING (prompt);
memset (keybuf, 0, sizeof keybuf);
GCPRO1 (keybuf[0]);
- gcpro1.nvars = (sizeof keybuf / sizeof (keybuf[0]));
+ gcpro1.nvars = ARRAYELTS (keybuf);
if (NILP (continue_echo))
{
cancel_hourglass ();
#endif
- i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])),
+ i = read_key_sequence (keybuf, ARRAYELTS (keybuf),
prompt, ! NILP (dont_downcase_last),
! NILP (can_return_switch_frame), 0, 0);
QUIT;
}
UNGCPRO;
- return unbind_to (count,
- ((allow_string ? make_event_array : Fvector)
- (i, keybuf)));
+ Lisp_Object tem0 = ((allow_string ? make_event_array : Fvector) (i, keybuf));
+ dynwind_end ();
+ return tem0;
}
DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 5, 0,
"FOpen dribble file: ",
doc: /* Start writing all keyboard characters to a dribble file called FILE.
If FILE is nil, close any open dribble file.
-The file will be closed when Emacs exits. */)
+The file will be closed when Emacs exits.
+
+Be aware that this records ALL characters you type!
+This may include sensitive information such as passwords. */)
(Lisp_Object file)
{
if (dribble)
}
if (!NILP (file))
{
+ int fd;
+ Lisp_Object encfile;
+
file = Fexpand_file_name (file, Qnil);
- dribble = emacs_fopen (SSDATA (file), "w");
+ encfile = ENCODE_FILE (file);
+ fd = emacs_open (SSDATA (encfile), O_WRONLY | O_CREAT | O_EXCL, 0600);
+ if (fd < 0 && errno == EEXIST && unlink (SSDATA (encfile)) == 0)
+ fd = emacs_open (SSDATA (encfile), O_WRONLY | O_CREAT | O_EXCL, 0600);
+ dribble = fd < 0 ? 0 : fdopen (fd, "w");
if (dribble == 0)
report_file_error ("Opening dribble", file);
}
On such systems, Emacs starts a subshell instead of suspending. */)
(Lisp_Object stuffstring)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
int old_height, old_width;
int width, height;
struct gcpro gcpro1;
sys_subshell ();
else
sys_suspend ();
- unbind_to (count, Qnil);
+ dynwind_end ();
/* Check if terminal/window size has changed.
Note that this is not useful when we are running directly
handle_interrupt (bool in_signal_handler)
{
char c;
- sigset_t blocked;
- sigemptyset (&blocked);
- sigaddset (&blocked, SIGINT);
cancel_echoing ();
/* If SIGINT isn't blocked, don't let us be interrupted by
a SIGINT. It might be harmful due to non-reentrancy
in I/O functions. */
+ sigset_t blocked;
+ sigemptyset (&blocked);
+ sigaddset (&blocked, SIGINT);
pthread_sigmask (SIG_BLOCK, &blocked, 0);
}
is used. Note that [Enter] is not echoed by dos. */
cursor_to (SELECTED_FRAME (), 0, 0);
#endif
- /* It doesn't work to autosave while GC is in progress;
- the code used for auto-saving doesn't cope with the mark bit. */
- if (!gc_in_progress)
- {
- printf ("Auto-save? (y or n) ");
- fflush (stdout);
- if (((c = getchar ()) & ~040) == 'Y')
- {
- Fdo_auto_save (Qt, Qnil);
+ printf ("Auto-save? (y or n) ");
+ fflush (stdout);
+ if (((c = getchar ()) & ~040) == 'Y')
+ {
+ Fdo_auto_save (Qt, Qnil);
#ifdef MSDOS
- printf ("\r\nAuto-save done");
+ printf ("\r\nAuto-save done");
#else /* not MSDOS */
- printf ("Auto-save done\n");
-#endif /* not MSDOS */
- }
- while (c != '\n') c = getchar ();
- }
- else
- {
- /* During GC, it must be safe to reenable quitting again. */
- Vinhibit_quit = Qnil;
-#ifdef MSDOS
- printf ("\r\n");
+ printf ("Auto-save done\n");
#endif /* not MSDOS */
- printf ("Garbage collection in progress; cannot auto-save now\r\n");
- printf ("but will instead do a real quit after garbage collection ends\r\n");
- fflush (stdout);
- }
+ }
+ while (c != '\n') c = getchar ();
#ifdef MSDOS
printf ("\r\nAbort? (y or n) ");
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
immediate_quit = 0;
- pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
+ pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
saved = gl_state;
GCPRO4 (saved.object, saved.global_code,
saved.current_syntax_table, saved.old_prop);
}
}
- pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
+ pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
/* TODO: The longjmp in this call throws the NS event loop integration off,
and it seems to do fine without this. Probably some attention
do_switch_frame (make_lispy_switch_frame (internal_last_event_frame),
0, 0, Qnil);
- sys_longjmp (getcjmp, 1);
+ abort_to_prompt (getctag, SCM_EOL);
}
\f
DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,
if (new_interrupt_input != interrupt_input)
{
-#ifdef POLL_FOR_INPUT
- stop_polling ();
-#endif
#ifndef DOS_NT
/* this causes startup screen to be restored and messes with the mouse */
reset_all_sys_modes ();
#endif
#ifdef POLL_FOR_INPUT
- poll_suppress_count = 1;
start_polling ();
#endif
}
}
XSETFASTINT (val[3], quit_char);
- return Flist (sizeof (val) / sizeof (val[0]), val);
+ return Flist (ARRAYELTS (val), val);
}
DEFUN ("posn-at-x-y", Fposn_at_x_y, Sposn_at_x_y, 2, 4, 0,
#ifdef POLL_FOR_INPUT
poll_timer = NULL;
- poll_suppress_count = 1;
start_polling ();
#endif
}
void
syms_of_keyboard (void)
{
+#include "keyboard.x"
+
pending_funcalls = Qnil;
staticpro (&pending_funcalls);
{
int i;
- int len = sizeof (head_table) / sizeof (head_table[0]);
+ int len = ARRAYELTS (head_table);
for (i = 0; i < len; i++)
{
staticpro (&button_down_location);
mouse_syms = Fmake_vector (make_number (5), Qnil);
staticpro (&mouse_syms);
- wheel_syms = Fmake_vector (make_number (sizeof (lispy_wheel_names)
- / sizeof (lispy_wheel_names[0])),
+ wheel_syms = Fmake_vector (make_number (ARRAYELTS (lispy_wheel_names)),
Qnil);
staticpro (&wheel_syms);
{
int i;
- int len = sizeof (modifier_names) / sizeof (modifier_names[0]);
+ int len = ARRAYELTS (modifier_names);
modifier_symbols = Fmake_vector (make_number (len), Qnil);
for (i = 0; i < len; i++)
help_form_saved_window_configs = Qnil;
staticpro (&help_form_saved_window_configs);
- defsubr (&Scurrent_idle_time);
- defsubr (&Sevent_symbol_parse_modifiers);
- defsubr (&Sevent_convert_list);
- defsubr (&Sread_key_sequence);
- defsubr (&Sread_key_sequence_vector);
- defsubr (&Srecursive_edit);
- defsubr (&Strack_mouse);
- defsubr (&Sinput_pending_p);
- defsubr (&Srecent_keys);
- defsubr (&Sthis_command_keys);
- defsubr (&Sthis_command_keys_vector);
- defsubr (&Sthis_single_command_keys);
- defsubr (&Sthis_single_command_raw_keys);
- defsubr (&Sreset_this_command_lengths);
- defsubr (&Sclear_this_command_keys);
- defsubr (&Ssuspend_emacs);
- 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);
- defsubr (&Sset_input_interrupt_mode);
- defsubr (&Sset_output_flow_control);
- defsubr (&Sset_input_meta_mode);
- defsubr (&Sset_quit_char);
- defsubr (&Sset_input_mode);
- defsubr (&Scurrent_input_mode);
- defsubr (&Sposn_at_point);
- defsubr (&Sposn_at_x_y);
-
DEFVAR_LISP ("last-command-event", last_command_event,
doc: /* Last input event that was part of a command. */);
Buffer modification stores t in this variable. */);
Vdeactivate_mark = Qnil;
DEFSYM (Qdeactivate_mark, "deactivate-mark");
+ Fmake_variable_buffer_local (Qdeactivate_mark);
DEFVAR_LISP ("pre-command-hook", Vpre_command_hook,
doc: /* Normal hook run before each command is executed.
initial_define_lispy_key (Vspecial_event_map, "focus-out",
"handle-focus-out");
}
-
-/* Mark the pointers in the kboard objects.
- Called by Fgarbage_collect. */
-void
-mark_kboards (void)
-{
- KBOARD *kb;
- Lisp_Object *p;
- for (kb = all_kboards; kb; kb = kb->next_kboard)
- {
- if (kb->kbd_macro_buffer)
- for (p = kb->kbd_macro_buffer; p < kb->kbd_macro_ptr; p++)
- mark_object (*p);
- mark_object (KVAR (kb, Voverriding_terminal_local_map));
- mark_object (KVAR (kb, Vlast_command));
- mark_object (KVAR (kb, Vreal_last_command));
- mark_object (KVAR (kb, Vkeyboard_translate_table));
- mark_object (KVAR (kb, Vlast_repeatable_command));
- mark_object (KVAR (kb, Vprefix_arg));
- mark_object (KVAR (kb, Vlast_prefix_arg));
- mark_object (KVAR (kb, kbd_queue));
- mark_object (KVAR (kb, defining_kbd_macro));
- mark_object (KVAR (kb, Vlast_kbd_macro));
- mark_object (KVAR (kb, Vsystem_key_alist));
- mark_object (KVAR (kb, system_key_syms));
- mark_object (KVAR (kb, Vwindow_system));
- mark_object (KVAR (kb, Vinput_decode_map));
- mark_object (KVAR (kb, Vlocal_function_key_map));
- mark_object (KVAR (kb, Vdefault_minibuffer_frame));
- mark_object (KVAR (kb, echo_string));
- }
- {
- struct input_event *event;
- for (event = kbd_fetch_ptr; event != kbd_store_ptr; event++)
- {
- if (event == kbd_buffer + KBD_BUFFER_SIZE)
- event = kbd_buffer;
- /* These two special event types has no Lisp_Objects to mark. */
- if (event->kind != SELECTION_REQUEST_EVENT
- && event->kind != SELECTION_CLEAR_EVENT)
- {
- mark_object (event->x);
- mark_object (event->y);
- mark_object (event->frame_or_window);
- mark_object (event->arg);
- }
- }
- }
-}