diff options
| author | Stefan Monnier | 2013-05-23 13:25:42 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2013-05-23 13:25:42 -0400 |
| commit | a7eb9b0fbeeaa24d803355fd90d462809916a2d8 (patch) | |
| tree | 4696206f7fcaf47c38cea418a47ceeb4bb2f0264 /src | |
| parent | fe1eb856c5457a220c7c9cc96030247aaad2a0a3 (diff) | |
| download | emacs-a7eb9b0fbeeaa24d803355fd90d462809916a2d8.tar.gz emacs-a7eb9b0fbeeaa24d803355fd90d462809916a2d8.zip | |
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
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 8 | ||||
| -rw-r--r-- | src/keyboard.c | 291 |
2 files changed, 170 insertions, 129 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 8f97659db33..1d2af4b2a7d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,13 @@ | |||
| 1 | 2013-05-23 Stefan Monnier <monnier@iro.umontreal.ca> | 1 | 2013-05-23 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 2 | ||
| 3 | * keyboard.c: Apply keyboard decoding only to events that come directly | ||
| 4 | from the tty, not from unread-command-events (bug#14368). | ||
| 5 | (read_event_from_main_queue): New function, extracted from read_char). | ||
| 6 | (read_decoded_char): Remove. | ||
| 7 | (read_decoded_event_from_main_queue): New function to replace it. | ||
| 8 | (read_char): Use it. | ||
| 9 | (read_key_sequence): Use read_char rather than read_decoded_char. | ||
| 10 | |||
| 3 | * keyboard.c (read_decoded_char): Don't decode under w32 (bug#14403). | 11 | * keyboard.c (read_decoded_char): Don't decode under w32 (bug#14403). |
| 4 | 12 | ||
| 5 | 2013-05-22 Barry OReilly <gundaetiapo@gmail.com> (tiny change) | 13 | 2013-05-22 Barry OReilly <gundaetiapo@gmail.com> (tiny change) |
diff --git a/src/keyboard.c b/src/keyboard.c index 7f863269a7e..c9ba39769cd 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -2222,6 +2222,157 @@ do { if (! polling_stopped_here) stop_polling (); \ | |||
| 2222 | do { if (polling_stopped_here) start_polling (); \ | 2222 | do { if (polling_stopped_here) start_polling (); \ |
| 2223 | polling_stopped_here = 0; } while (0) | 2223 | polling_stopped_here = 0; } while (0) |
| 2224 | 2224 | ||
| 2225 | static Lisp_Object | ||
| 2226 | read_event_from_main_queue (EMACS_TIME *end_time, | ||
| 2227 | sys_jmp_buf local_getcjmp, | ||
| 2228 | bool *used_mouse_menu) | ||
| 2229 | { | ||
| 2230 | Lisp_Object c = Qnil; | ||
| 2231 | sys_jmp_buf save_jump; | ||
| 2232 | KBOARD *kb IF_LINT (= NULL); | ||
| 2233 | |||
| 2234 | start: | ||
| 2235 | |||
| 2236 | /* Read from the main queue, and if that gives us something we can't use yet, | ||
| 2237 | we put it on the appropriate side queue and try again. */ | ||
| 2238 | |||
| 2239 | if (end_time && EMACS_TIME_LE (*end_time, current_emacs_time ())) | ||
| 2240 | return c; | ||
| 2241 | |||
| 2242 | /* Actually read a character, waiting if necessary. */ | ||
| 2243 | save_getcjmp (save_jump); | ||
| 2244 | restore_getcjmp (local_getcjmp); | ||
| 2245 | if (!end_time) | ||
| 2246 | timer_start_idle (); | ||
| 2247 | c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time); | ||
| 2248 | restore_getcjmp (save_jump); | ||
| 2249 | |||
| 2250 | if (! NILP (c) && (kb != current_kboard)) | ||
| 2251 | { | ||
| 2252 | Lisp_Object last = KVAR (kb, kbd_queue); | ||
| 2253 | if (CONSP (last)) | ||
| 2254 | { | ||
| 2255 | while (CONSP (XCDR (last))) | ||
| 2256 | last = XCDR (last); | ||
| 2257 | if (!NILP (XCDR (last))) | ||
| 2258 | emacs_abort (); | ||
| 2259 | } | ||
| 2260 | if (!CONSP (last)) | ||
| 2261 | kset_kbd_queue (kb, Fcons (c, Qnil)); | ||
| 2262 | else | ||
| 2263 | XSETCDR (last, Fcons (c, Qnil)); | ||
| 2264 | kb->kbd_queue_has_data = 1; | ||
| 2265 | c = Qnil; | ||
| 2266 | if (single_kboard) | ||
| 2267 | goto start; | ||
| 2268 | current_kboard = kb; | ||
| 2269 | /* This is going to exit from read_char | ||
| 2270 | so we had better get rid of this frame's stuff. */ | ||
| 2271 | return make_number (-2); | ||
| 2272 | } | ||
| 2273 | |||
| 2274 | /* Terminate Emacs in batch mode if at eof. */ | ||
| 2275 | if (noninteractive && INTEGERP (c) && XINT (c) < 0) | ||
| 2276 | Fkill_emacs (make_number (1)); | ||
| 2277 | |||
| 2278 | if (INTEGERP (c)) | ||
| 2279 | { | ||
| 2280 | /* Add in any extra modifiers, where appropriate. */ | ||
| 2281 | if ((extra_keyboard_modifiers & CHAR_CTL) | ||
| 2282 | || ((extra_keyboard_modifiers & 0177) < ' ' | ||
| 2283 | && (extra_keyboard_modifiers & 0177) != 0)) | ||
| 2284 | XSETINT (c, make_ctrl_char (XINT (c))); | ||
| 2285 | |||
| 2286 | /* Transfer any other modifier bits directly from | ||
| 2287 | extra_keyboard_modifiers to c. Ignore the actual character code | ||
| 2288 | in the low 16 bits of extra_keyboard_modifiers. */ | ||
| 2289 | XSETINT (c, XINT (c) | (extra_keyboard_modifiers & ~0xff7f & ~CHAR_CTL)); | ||
| 2290 | } | ||
| 2291 | |||
| 2292 | /* FIXME: Decode tty keyboard input here. */ | ||
| 2293 | return c; | ||
| 2294 | } | ||
| 2295 | |||
| 2296 | |||
| 2297 | |||
| 2298 | /* Like `read_event_from_main_queue' but applies keyboard-coding-system | ||
| 2299 | to tty input. */ | ||
| 2300 | static Lisp_Object | ||
| 2301 | read_decoded_event_from_main_queue (EMACS_TIME *end_time, | ||
| 2302 | sys_jmp_buf local_getcjmp, | ||
| 2303 | Lisp_Object prev_event, | ||
| 2304 | bool *used_mouse_menu) | ||
| 2305 | { | ||
| 2306 | #define MAX_ENCODED_BYTES 16 | ||
| 2307 | Lisp_Object events[MAX_ENCODED_BYTES]; | ||
| 2308 | int n = 0; | ||
| 2309 | while (true) | ||
| 2310 | { | ||
| 2311 | Lisp_Object nextevt | ||
| 2312 | = read_event_from_main_queue (end_time, local_getcjmp, | ||
| 2313 | used_mouse_menu); | ||
| 2314 | #ifdef WINDOWSNT | ||
| 2315 | /* w32_console already returns decoded events. */ | ||
| 2316 | return nextevt; | ||
| 2317 | #else | ||
| 2318 | struct frame *frame = XFRAME (selected_frame); | ||
| 2319 | struct terminal *terminal = frame->terminal; | ||
| 2320 | if (!((FRAME_TERMCAP_P (frame) || FRAME_MSDOS_P (frame)) | ||
| 2321 | /* Don't apply decoding if we're just reading a raw event | ||
| 2322 | (e.g. reading bytes sent by the xterm to specify the position | ||
| 2323 | of a mouse click). */ | ||
| 2324 | && (!EQ (prev_event, Qt)) | ||
| 2325 | && (TERMINAL_KEYBOARD_CODING (terminal)->common_flags | ||
| 2326 | & CODING_REQUIRE_DECODING_MASK))) | ||
| 2327 | return nextevt; /* No decoding needed. */ | ||
| 2328 | else | ||
| 2329 | { | ||
| 2330 | int meta_key = terminal->display_info.tty->meta_key; | ||
| 2331 | eassert (n < MAX_ENCODED_BYTES); | ||
| 2332 | events[n++] = nextevt; | ||
| 2333 | if (NATNUMP (nextevt) | ||
| 2334 | && XINT (nextevt) < (meta_key == 1 ? 0x80 : 0x100)) | ||
| 2335 | { /* An encoded byte sequence, let's try to decode it. */ | ||
| 2336 | struct coding_system *coding | ||
| 2337 | = TERMINAL_KEYBOARD_CODING (terminal); | ||
| 2338 | unsigned char *src = alloca (n); | ||
| 2339 | int i; | ||
| 2340 | for (i = 0; i < n; i++) | ||
| 2341 | src[i] = XINT (events[i]); | ||
| 2342 | if (meta_key != 2) | ||
| 2343 | for (i = 0; i < n; i++) | ||
| 2344 | src[i] &= ~0x80; | ||
| 2345 | coding->destination = alloca (n * 4); | ||
| 2346 | coding->dst_bytes = n * 4; | ||
| 2347 | decode_coding_c_string (coding, src, n, Qnil); | ||
| 2348 | eassert (coding->produced_char <= n); | ||
| 2349 | if (coding->produced_char == 0) | ||
| 2350 | { /* The encoded sequence is incomplete. */ | ||
| 2351 | if (n < MAX_ENCODED_BYTES) /* Avoid buffer overflow. */ | ||
| 2352 | continue; /* Read on! */ | ||
| 2353 | } | ||
| 2354 | else | ||
| 2355 | { | ||
| 2356 | const unsigned char *p = coding->destination; | ||
| 2357 | eassert (coding->carryover_bytes == 0); | ||
| 2358 | n = 0; | ||
| 2359 | while (n < coding->produced_char) | ||
| 2360 | events[n++] = make_number (STRING_CHAR_ADVANCE (p)); | ||
| 2361 | } | ||
| 2362 | } | ||
| 2363 | /* Now `events' should hold decoded events. | ||
| 2364 | Normally, n should be equal to 1, but better not rely on it. | ||
| 2365 | We can only return one event here, so return the first we | ||
| 2366 | had and keep the others (if any) for later. */ | ||
| 2367 | while (n > 1) | ||
| 2368 | Vunread_command_events | ||
| 2369 | = Fcons (events[--n], Vunread_command_events); | ||
| 2370 | return events[0]; | ||
| 2371 | } | ||
| 2372 | #endif | ||
| 2373 | } | ||
| 2374 | } | ||
| 2375 | |||
| 2225 | /* Read a character from the keyboard; call the redisplay if needed. */ | 2376 | /* Read a character from the keyboard; call the redisplay if needed. */ |
| 2226 | /* commandflag 0 means do not autosave, but do redisplay. | 2377 | /* commandflag 0 means do not autosave, but do redisplay. |
| 2227 | -1 means do not redisplay, but do autosave. | 2378 | -1 means do not redisplay, but do autosave. |
| @@ -2739,68 +2890,20 @@ read_char (int commandflag, Lisp_Object map, | |||
| 2739 | 2890 | ||
| 2740 | STOP_POLLING; | 2891 | STOP_POLLING; |
| 2741 | 2892 | ||
| 2742 | /* Finally, we read from the main queue, | ||
| 2743 | and if that gives us something we can't use yet, we put it on the | ||
| 2744 | appropriate side queue and try again. */ | ||
| 2745 | |||
| 2746 | if (NILP (c)) | 2893 | if (NILP (c)) |
| 2747 | { | 2894 | { |
| 2748 | KBOARD *kb IF_LINT (= NULL); | 2895 | c = read_decoded_event_from_main_queue (end_time, local_getcjmp, |
| 2749 | 2896 | prev_event, used_mouse_menu); | |
| 2750 | if (end_time && EMACS_TIME_LE (*end_time, current_emacs_time ())) | 2897 | if (end_time && EMACS_TIME_LE (*end_time, current_emacs_time ())) |
| 2751 | goto exit; | 2898 | goto exit; |
| 2752 | 2899 | if (EQ (c, make_number (-2))) | |
| 2753 | /* Actually read a character, waiting if necessary. */ | 2900 | { |
| 2754 | save_getcjmp (save_jump); | ||
| 2755 | restore_getcjmp (local_getcjmp); | ||
| 2756 | if (!end_time) | ||
| 2757 | timer_start_idle (); | ||
| 2758 | c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time); | ||
| 2759 | restore_getcjmp (save_jump); | ||
| 2760 | |||
| 2761 | if (! NILP (c) && (kb != current_kboard)) | ||
| 2762 | { | ||
| 2763 | Lisp_Object last = KVAR (kb, kbd_queue); | ||
| 2764 | if (CONSP (last)) | ||
| 2765 | { | ||
| 2766 | while (CONSP (XCDR (last))) | ||
| 2767 | last = XCDR (last); | ||
| 2768 | if (!NILP (XCDR (last))) | ||
| 2769 | emacs_abort (); | ||
| 2770 | } | ||
| 2771 | if (!CONSP (last)) | ||
| 2772 | kset_kbd_queue (kb, Fcons (c, Qnil)); | ||
| 2773 | else | ||
| 2774 | XSETCDR (last, Fcons (c, Qnil)); | ||
| 2775 | kb->kbd_queue_has_data = 1; | ||
| 2776 | c = Qnil; | ||
| 2777 | if (single_kboard) | ||
| 2778 | goto wrong_kboard; | ||
| 2779 | current_kboard = kb; | ||
| 2780 | /* This is going to exit from read_char | 2901 | /* This is going to exit from read_char |
| 2781 | so we had better get rid of this frame's stuff. */ | 2902 | so we had better get rid of this frame's stuff. */ |
| 2782 | UNGCPRO; | 2903 | UNGCPRO; |
| 2783 | return make_number (-2); | 2904 | return c; |
| 2784 | } | 2905 | } |
| 2785 | } | 2906 | } |
| 2786 | |||
| 2787 | /* Terminate Emacs in batch mode if at eof. */ | ||
| 2788 | if (noninteractive && INTEGERP (c) && XINT (c) < 0) | ||
| 2789 | Fkill_emacs (make_number (1)); | ||
| 2790 | |||
| 2791 | if (INTEGERP (c)) | ||
| 2792 | { | ||
| 2793 | /* Add in any extra modifiers, where appropriate. */ | ||
| 2794 | if ((extra_keyboard_modifiers & CHAR_CTL) | ||
| 2795 | || ((extra_keyboard_modifiers & 0177) < ' ' | ||
| 2796 | && (extra_keyboard_modifiers & 0177) != 0)) | ||
| 2797 | XSETINT (c, make_ctrl_char (XINT (c))); | ||
| 2798 | |||
| 2799 | /* Transfer any other modifier bits directly from | ||
| 2800 | extra_keyboard_modifiers to c. Ignore the actual character code | ||
| 2801 | in the low 16 bits of extra_keyboard_modifiers. */ | ||
| 2802 | XSETINT (c, XINT (c) | (extra_keyboard_modifiers & ~0xff7f & ~CHAR_CTL)); | ||
| 2803 | } | ||
| 2804 | 2907 | ||
| 2805 | non_reread: | 2908 | non_reread: |
| 2806 | 2909 | ||
| @@ -8690,76 +8793,6 @@ test_undefined (Lisp_Object binding) | |||
| 8690 | && EQ (Fcommand_remapping (binding, Qnil, Qnil), Qundefined))); | 8793 | && EQ (Fcommand_remapping (binding, Qnil, Qnil), Qundefined))); |
| 8691 | } | 8794 | } |
| 8692 | 8795 | ||
| 8693 | /* Like `read_char' but applies keyboard-coding-system to tty input. */ | ||
| 8694 | static Lisp_Object | ||
| 8695 | read_decoded_char (int commandflag, Lisp_Object map, | ||
| 8696 | Lisp_Object prev_event, bool *used_mouse_menu) | ||
| 8697 | { | ||
| 8698 | #define MAX_ENCODED_BYTES 16 | ||
| 8699 | Lisp_Object events[MAX_ENCODED_BYTES]; | ||
| 8700 | int n = 0; | ||
| 8701 | while (true) | ||
| 8702 | { | ||
| 8703 | Lisp_Object nextevt | ||
| 8704 | = read_char (commandflag, map, prev_event, used_mouse_menu, NULL); | ||
| 8705 | #ifdef WINDOWSNT | ||
| 8706 | /* w32_console already returns decoded events. */ | ||
| 8707 | return nextevt; | ||
| 8708 | #else | ||
| 8709 | struct frame *frame = XFRAME (selected_frame); | ||
| 8710 | struct terminal *terminal = frame->terminal; | ||
| 8711 | if (!((FRAME_TERMCAP_P (frame) || FRAME_MSDOS_P (frame)) | ||
| 8712 | && (TERMINAL_KEYBOARD_CODING (terminal)->common_flags | ||
| 8713 | & CODING_REQUIRE_DECODING_MASK))) | ||
| 8714 | return nextevt; /* No decoding needed. */ | ||
| 8715 | else | ||
| 8716 | { | ||
| 8717 | int meta_key = terminal->display_info.tty->meta_key; | ||
| 8718 | eassert (n < MAX_ENCODED_BYTES); | ||
| 8719 | events[n++] = nextevt; | ||
| 8720 | if (NATNUMP (nextevt) | ||
| 8721 | && XINT (nextevt) < (meta_key == 1 ? 0x80 : 0x100)) | ||
| 8722 | { /* An encoded byte sequence, let's try to decode it. */ | ||
| 8723 | struct coding_system *coding | ||
| 8724 | = TERMINAL_KEYBOARD_CODING (terminal); | ||
| 8725 | unsigned char *src = alloca (n); | ||
| 8726 | int i; | ||
| 8727 | for (i = 0; i < n; i++) | ||
| 8728 | src[i] = XINT (events[i]); | ||
| 8729 | if (meta_key != 2) | ||
| 8730 | for (i = 0; i < n; i++) | ||
| 8731 | src[i] &= ~0x80; | ||
| 8732 | coding->destination = alloca (n * 4); | ||
| 8733 | coding->dst_bytes = n * 4; | ||
| 8734 | decode_coding_c_string (coding, src, n, Qnil); | ||
| 8735 | eassert (coding->produced_char <= n); | ||
| 8736 | if (coding->produced_char == 0) | ||
| 8737 | { /* The encoded sequence is incomplete. */ | ||
| 8738 | if (n < MAX_ENCODED_BYTES) /* Avoid buffer overflow. */ | ||
| 8739 | continue; /* Read on! */ | ||
| 8740 | } | ||
| 8741 | else | ||
| 8742 | { | ||
| 8743 | const unsigned char *p = coding->destination; | ||
| 8744 | eassert (coding->carryover_bytes == 0); | ||
| 8745 | n = 0; | ||
| 8746 | while (n < coding->produced_char) | ||
| 8747 | events[n++] = make_number (STRING_CHAR_ADVANCE (p)); | ||
| 8748 | } | ||
| 8749 | } | ||
| 8750 | /* Now `events' should hold decoded events. | ||
| 8751 | Normally, n should be equal to 1, but better not rely on it. | ||
| 8752 | We can only return one event here, so return the first we | ||
| 8753 | had and keep the others (if any) for later. */ | ||
| 8754 | while (n > 1) | ||
| 8755 | Vunread_command_events | ||
| 8756 | = Fcons (events[--n], Vunread_command_events); | ||
| 8757 | return events[0]; | ||
| 8758 | } | ||
| 8759 | #endif | ||
| 8760 | } | ||
| 8761 | } | ||
| 8762 | |||
| 8763 | /* Read a sequence of keys that ends with a non prefix character, | 8796 | /* Read a sequence of keys that ends with a non prefix character, |
| 8764 | storing it in KEYBUF, a buffer of size BUFSIZE. | 8797 | storing it in KEYBUF, a buffer of size BUFSIZE. |
| 8765 | Prompt with PROMPT. | 8798 | Prompt with PROMPT. |
| @@ -9037,9 +9070,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, | |||
| 9037 | { | 9070 | { |
| 9038 | KBOARD *interrupted_kboard = current_kboard; | 9071 | KBOARD *interrupted_kboard = current_kboard; |
| 9039 | struct frame *interrupted_frame = SELECTED_FRAME (); | 9072 | struct frame *interrupted_frame = SELECTED_FRAME (); |
| 9040 | key = read_decoded_char (NILP (prompt), | 9073 | key = read_char (NILP (prompt), |
| 9041 | current_binding, last_nonmenu_event, | 9074 | current_binding, last_nonmenu_event, |
| 9042 | &used_mouse_menu); | 9075 | &used_mouse_menu, NULL); |
| 9043 | if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */ | 9076 | if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */ |
| 9044 | /* When switching to a new tty (with a new keyboard), | 9077 | /* When switching to a new tty (with a new keyboard), |
| 9045 | read_char returns the new buffer, rather than -2 | 9078 | read_char returns the new buffer, rather than -2 |