summaryrefslogtreecommitdiff
path: root/src/keyboard.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/keyboard.c')
-rw-r--r--src/keyboard.c170
1 files changed, 140 insertions, 30 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index f24d86e8833..15c7f5ff8c6 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -75,6 +75,12 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
# pragma GCC diagnostic ignored "-Wclobbered"
#endif
+#ifdef WINDOWSNT
+char const DEV_TTY[] = "CONOUT$";
+#else
+char const DEV_TTY[] = "/dev/tty";
+#endif
+
/* Variables for blockinput.h: */
/* Positive if interrupt input is blocked right now. */
@@ -142,9 +148,6 @@ static Lisp_Object regular_top_level_message;
static sys_jmp_buf getcjmp;
-/* True while doing kbd input. */
-bool waiting_for_input;
-
/* True while displaying for echoing. Delays C-g throwing. */
static bool echoing;
@@ -696,7 +699,7 @@ recursive_edit_1 (void)
val = command_loop ();
if (EQ (val, Qt))
- Fsignal (Qquit, Qnil);
+ quit ();
/* Handle throw from read_minibuf when using minibuffer
while it's active but we're in another window. */
if (STRINGP (val))
@@ -2135,7 +2138,7 @@ read_event_from_main_queue (struct timespec *end_time,
{
Lisp_Object c = Qnil;
sys_jmp_buf save_jump;
- KBOARD *kb IF_LINT (= NULL);
+ KBOARD *kb;
start:
@@ -2159,9 +2162,9 @@ read_event_from_main_queue (struct timespec *end_time,
if (CONSP (last))
{
while (CONSP (XCDR (last)))
- last = XCDR (last);
+ last = XCDR (last);
if (!NILP (XCDR (last)))
- emacs_abort ();
+ emacs_abort ();
}
if (!CONSP (last))
kset_kbd_queue (kb, list1 (c));
@@ -2206,8 +2209,8 @@ read_decoded_event_from_main_queue (struct timespec *end_time,
Lisp_Object prev_event,
bool *used_mouse_menu)
{
-#define MAX_ENCODED_BYTES 16
#ifndef WINDOWSNT
+#define MAX_ENCODED_BYTES 16
Lisp_Object events[MAX_ENCODED_BYTES];
int n = 0;
#endif
@@ -2568,6 +2571,9 @@ read_char (int commandflag, Lisp_Object map,
so restore it now. */
restore_getcjmp (save_jump);
pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+#if THREADS_ENABLED
+ maybe_reacquire_global_lock ();
+#endif
unbind_to (jmpcount, Qnil);
XSETINT (c, quit_char);
internal_last_event_frame = selected_frame;
@@ -2847,7 +2853,16 @@ read_char (int commandflag, Lisp_Object map,
last_input_event = c;
call4 (Qcommand_execute, tem, Qnil, Fvector (1, &last_input_event), Qt);
- if (CONSP (c) && EQ (XCAR (c), Qselect_window) && !end_time)
+ if (CONSP (c)
+ && (EQ (XCAR (c), Qselect_window)
+#ifdef HAVE_DBUS
+ || EQ (XCAR (c), Qdbus_event)
+#endif
+#ifdef USE_FILE_NOTIFY
+ || EQ (XCAR (c), Qfile_notify)
+#endif
+ || EQ (XCAR (c), Qconfig_changed_event))
+ && !end_time)
/* We stopped being idle for this event; undo that. This
prevents automatic window selection (under
mouse-autoselect-window) from acting as a real input event, for
@@ -3552,14 +3567,23 @@ kbd_buffer_store_buffered_event (union buffered_input_event *event,
#endif /* subprocesses */
}
+ Lisp_Object ignore_event;
+
+ switch (event->kind)
+ {
+ case FOCUS_IN_EVENT: ignore_event = Qfocus_in; break;
+ case FOCUS_OUT_EVENT: ignore_event = Qfocus_out; break;
+ case HELP_EVENT: ignore_event = Qhelp_echo; break;
+ case ICONIFY_EVENT: ignore_event = Qiconify_frame; break;
+ case DEICONIFY_EVENT: ignore_event = Qmake_frame_visible; break;
+ case SELECTION_REQUEST_EVENT: ignore_event = Qselection_request; break;
+ default: ignore_event = Qnil; break;
+ }
+
/* If we're inside while-no-input, and this event qualifies
as input, set quit-flag to cause an interrupt. */
if (!NILP (Vthrow_on_input)
- && event->kind != FOCUS_IN_EVENT
- && event->kind != FOCUS_OUT_EVENT
- && event->kind != HELP_EVENT
- && event->kind != ICONIFY_EVENT
- && event->kind != DEICONIFY_EVENT)
+ && NILP (Fmemq (ignore_event, Vwhile_no_input_ignore_events)))
{
Vquit_flag = Vthrow_on_input;
/* If we're inside a function that wants immediate quits,
@@ -3897,6 +3921,16 @@ kbd_buffer_get_event (KBOARD **kbp,
kbd_fetch_ptr = event + 1;
}
#endif
+
+#ifdef HAVE_NTGUI
+ else if (event->kind == END_SESSION_EVENT)
+ {
+ /* Make an event (end-session). */
+ obj = list1 (Qend_session);
+ kbd_fetch_ptr = event + 1;
+ }
+#endif
+
#if defined (HAVE_X11) || defined (HAVE_NTGUI) \
|| defined (HAVE_NS)
else if (event->kind == ICONIFY_EVENT)
@@ -5392,6 +5426,36 @@ make_lispy_event (struct input_event *event)
{
c &= 0377;
eassert (c == event->code);
+ }
+
+ /* Caps-lock shouldn't affect interpretation of key chords:
+ Control+s should produce C-s whether caps-lock is on or
+ not. And Control+Shift+s should produce C-S-s whether
+ caps-lock is on or not. */
+ if (event->modifiers & ~shift_modifier)
+ {
+ /* This is a key chord: some non-shift modifier is
+ depressed. */
+
+ if (uppercasep (c) &&
+ !(event->modifiers & shift_modifier))
+ {
+ /* Got a capital letter without a shift. The caps
+ lock is on. Un-capitalize the letter. */
+ c = downcase (c);
+ }
+ else if (lowercasep (c) &&
+ (event->modifiers & shift_modifier))
+ {
+ /* Got a lower-case letter even though shift is
+ depressed. The caps lock is on. Capitalize the
+ letter. */
+ c = upcase (c);
+ }
+ }
+
+ if (event->kind == ASCII_KEYSTROKE_EVENT)
+ {
/* Turn ASCII characters into control characters
when proper. */
if (event->modifiers & ctrl_modifier)
@@ -5984,7 +6048,6 @@ make_lispy_event (struct input_event *event)
}
#endif
-
#if defined HAVE_INOTIFY || defined HAVE_KQUEUE || defined HAVE_GFILENOTIFY
case FILE_NOTIFY_EVENT:
{
@@ -6603,7 +6666,12 @@ has the same base event type and all the specified modifiers. */)
int
parse_solitary_modifier (Lisp_Object symbol)
{
- Lisp_Object name = SYMBOL_NAME (symbol);
+ Lisp_Object name;
+
+ if (!SYMBOLP (symbol))
+ return 0;
+
+ name = SYMBOL_NAME (symbol);
switch (SREF (name, 0))
{
@@ -6884,7 +6952,10 @@ tty_read_avail_input (struct terminal *terminal,
the kbd_buffer can really hold. That may prevent loss
of characters on some systems when input is stuffed at us. */
unsigned char cbuf[KBD_BUFFER_SIZE - 1];
- int n_to_read, i;
+#ifndef WINDOWSNT
+ int n_to_read;
+#endif
+ int i;
struct tty_display_info *tty = terminal->display_info.tty;
int nread = 0;
#ifdef subprocesses
@@ -7560,7 +7631,7 @@ menu_item_eval_property_1 (Lisp_Object arg)
/* If we got a quit from within the menu computation,
quit all the way out of it. This takes care of C-] in the debugger. */
if (CONSP (arg) && EQ (XCAR (arg), Qquit))
- Fsignal (Qquit, Qnil);
+ quit ();
return Qnil;
}
@@ -8833,7 +8904,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
/* The length of the echo buffer when we started reading, and
the length of this_command_keys when we started reading. */
- ptrdiff_t echo_start IF_LINT (= 0);
+ ptrdiff_t echo_start UNINIT;
ptrdiff_t keys_start;
Lisp_Object current_binding = Qnil;
@@ -8881,7 +8952,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
While we're reading, we keep the event here. */
Lisp_Object delayed_switch_frame;
- Lisp_Object original_uppercase IF_LINT (= Qnil);
+ Lisp_Object original_uppercase UNINIT;
int original_uppercase_position = -1;
/* Gets around Microsoft compiler limitations. */
@@ -8991,7 +9062,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
while those allow us to restart the entire key sequence,
echo_local_start and keys_local_start allow us to throw away
just one key. */
- ptrdiff_t echo_local_start IF_LINT (= 0);
+ ptrdiff_t echo_local_start UNINIT;
int keys_local_start;
Lisp_Object new_binding;
@@ -10026,11 +10097,9 @@ DEFUN ("recursion-depth", Frecursion_depth, Srecursion_depth, 0, 0, 0,
doc: /* Return the current depth in recursive edits. */)
(void)
{
- Lisp_Object temp;
- /* Wrap around reliably on integer overflow. */
- EMACS_INT sum = (command_loop_level & INTMASK) + (minibuf_level & INTMASK);
- XSETINT (temp, sum);
- return temp;
+ EMACS_INT sum;
+ INT_ADD_WRAPV (command_loop_level, minibuf_level, &sum);
+ return make_number (sum);
}
DEFUN ("open-dribble-file", Fopen_dribble_file, Sopen_dribble_file, 1, 1,
@@ -10215,7 +10284,7 @@ static void
handle_interrupt_signal (int sig)
{
/* See if we have an active terminal on our controlling tty. */
- struct terminal *terminal = get_named_terminal ("/dev/tty");
+ struct terminal *terminal = get_named_terminal (DEV_TTY);
if (!terminal)
{
/* If there are no frames there, let's pretend that we are a
@@ -10284,7 +10353,7 @@ handle_interrupt (bool in_signal_handler)
cancel_echoing ();
/* XXX This code needs to be revised for multi-tty support. */
- if (!NILP (Vquit_flag) && get_named_terminal ("/dev/tty"))
+ if (!NILP (Vquit_flag) && get_named_terminal (DEV_TTY))
{
if (! in_signal_handler)
{
@@ -10322,6 +10391,9 @@ handle_interrupt (bool in_signal_handler)
is used. Note that [Enter] is not echoed by dos. */
cursor_to (SELECTED_FRAME (), 0, 0);
#endif
+
+ write_stdout ("Emacs is resuming after an emergency escape.\n");
+
/* 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)
@@ -10383,7 +10455,7 @@ handle_interrupt (bool in_signal_handler)
immediate_quit = false;
pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
saved = gl_state;
- Fsignal (Qquit, Qnil);
+ quit ();
gl_state = saved;
}
else
@@ -10580,7 +10652,7 @@ process.
See also `current-input-mode'. */)
(Lisp_Object quit)
{
- struct terminal *t = get_named_terminal ("/dev/tty");
+ struct terminal *t = get_named_terminal (DEV_TTY);
struct tty_display_info *tty;
if (!t)
@@ -10727,11 +10799,19 @@ The `posn-' functions access elements of such lists. */)
{
Lisp_Object x = XCAR (tem);
Lisp_Object y = XCAR (XCDR (tem));
+ Lisp_Object aux_info = XCDR (XCDR (tem));
+ int y_coord = XINT (y);
/* Point invisible due to hscrolling? X can be -1 when a
newline in a R2L line overflows into the left fringe. */
if (XINT (x) < -1)
return Qnil;
+ if (!NILP (aux_info) && y_coord < 0)
+ {
+ int rtop = XINT (XCAR (aux_info));
+
+ y = make_number (y_coord + rtop);
+ }
tem = Fposn_at_x_y (x, y, window, Qnil);
}
@@ -10988,6 +11068,7 @@ syms_of_keyboard (void)
#ifdef HAVE_NTGUI
DEFSYM (Qlanguage_change, "language-change");
+ DEFSYM (Qend_session, "end-session");
#endif
#ifdef HAVE_DBUS
@@ -11092,6 +11173,7 @@ syms_of_keyboard (void)
DEFSYM (Qiconify_frame, "iconify-frame");
DEFSYM (Qmake_frame_visible, "make-frame-visible");
DEFSYM (Qselect_window, "select-window");
+ DEFSYM (Qselection_request, "selection-request");
{
int i;
@@ -11729,8 +11811,32 @@ Currently, the only supported values for this
variable are `sigusr1' and `sigusr2'. */);
Vdebug_on_event = intern_c_string ("sigusr2");
+ DEFVAR_BOOL ("attempt-stack-overflow-recovery",
+ attempt_stack_overflow_recovery,
+ doc: /* If non-nil, attempt to recover from C stack
+overflow. This recovery is unsafe and may lead to deadlocks or data
+corruption, but it usually works and may preserve modified buffers
+that would otherwise be lost. If nil, treat stack overflow like any
+other kind of crash. */);
+ attempt_stack_overflow_recovery = true;
+
+ DEFVAR_BOOL ("attempt-orderly-shutdown-on-fatal-signal",
+ attempt_orderly_shutdown_on_fatal_signal,
+ doc: /* If non-nil, attempt to perform an orderly
+shutdown when Emacs receives a fatal signal (e.g., a crash).
+This cleanup is unsafe and may lead to deadlocks or data corruption,
+but it usually works and may preserve modified buffers that would
+otherwise be lost. If nil, crash immediately in response to fatal
+signals. */);
+ attempt_orderly_shutdown_on_fatal_signal = true;
+
/* Create the initial keyboard. Qt means 'unset'. */
initial_kboard = allocate_kboard (Qt);
+
+ DEFVAR_LISP ("while-no-input-ignore-events",
+ Vwhile_no_input_ignore_events,
+ doc: /* Ignored events from while-no-input. */);
+ Vwhile_no_input_ignore_events = Qnil;
}
void
@@ -11744,6 +11850,10 @@ keys_of_keyboard (void)
initial_define_lispy_key (Vspecial_event_map, "delete-frame",
"handle-delete-frame");
+#ifdef HAVE_NTGUI
+ initial_define_lispy_key (Vspecial_event_map, "end-session",
+ "kill-emacs");
+#endif
initial_define_lispy_key (Vspecial_event_map, "ns-put-working-text",
"ns-put-working-text");
initial_define_lispy_key (Vspecial_event_map, "ns-unput-working-text",