Commit a7eb9b0f authored by Stefan Monnier's avatar Stefan Monnier

Don't apply keyboard decoding to unread-command-events.

* src/keyboard.c: Apply keyboard decoding only to events that come directly
from the tty, not from unread-command-events (bug#14368).
(read_event_from_main_queue): New function, extracted from read_char).
(read_decoded_char): Remove.
(read_decoded_event_from_main_queue): New function to replace it.
(read_char): Use it.
(read_key_sequence): Use read_char rather than read_decoded_char.

Fixes: debbugs:14403
parent fe1eb856
2013-05-23 Stefan Monnier <monnier@iro.umontreal.ca>
* keyboard.c: Apply keyboard decoding only to events that come directly
from the tty, not from unread-command-events (bug#14368).
(read_event_from_main_queue): New function, extracted from read_char).
(read_decoded_char): Remove.
(read_decoded_event_from_main_queue): New function to replace it.
(read_char): Use it.
(read_key_sequence): Use read_char rather than read_decoded_char.
* keyboard.c (read_decoded_char): Don't decode under w32 (bug#14403).
2013-05-22 Barry OReilly <gundaetiapo@gmail.com> (tiny change)
......
......@@ -2222,6 +2222,157 @@ do { if (! polling_stopped_here) stop_polling (); \
do { if (polling_stopped_here) start_polling (); \
polling_stopped_here = 0; } while (0)
static Lisp_Object
read_event_from_main_queue (EMACS_TIME *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 && EMACS_TIME_LE (*end_time, current_emacs_time ()))
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, Fcons (c, Qnil));
else
XSETCDR (last, Fcons (c, Qnil));
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));
}
/* FIXME: Decode tty keyboard input here. */
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 (EMACS_TIME *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. */
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.
......@@ -2739,68 +2890,20 @@ read_char (int commandflag, Lisp_Object map,
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);
c = read_decoded_event_from_main_queue (end_time, local_getcjmp,
prev_event, used_mouse_menu);
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;
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:
......@@ -8690,76 +8793,6 @@ test_undefined (Lisp_Object binding)
&& EQ (Fcommand_remapping (binding, Qnil, Qnil), Qundefined)));
}
/* Like `read_char' but applies keyboard-coding-system to tty input. */
static Lisp_Object
read_decoded_char (int commandflag, Lisp_Object map,
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_char (commandflag, map, prev_event, used_mouse_menu, NULL);
#ifdef WINDOWSNT
/* w32_console already returns decoded events. */
return nextevt;
#else
struct frame *frame = XFRAME (selected_frame);
struct terminal *terminal = frame->terminal;
if (!((FRAME_TERMCAP_P (frame) || FRAME_MSDOS_P (frame))
&& (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 sequence of keys that ends with a non prefix character,
storing it in KEYBUF, a buffer of size BUFSIZE.
Prompt with PROMPT.
......@@ -9037,9 +9070,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
{
KBOARD *interrupted_kboard = current_kboard;
struct frame *interrupted_frame = SELECTED_FRAME ();
key = read_decoded_char (NILP (prompt),
current_binding, last_nonmenu_event,
&used_mouse_menu);
key = read_char (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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment