diff options
| author | Eli Zaretskii | 2012-07-28 19:57:57 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2012-07-28 19:57:57 +0300 |
| commit | 01bd1b0df605d644ae31e8f1f81d926a5d8c7099 (patch) | |
| tree | 4831ac9d45815c50fe276079dd5edb7cb8e63ef8 /src | |
| parent | a5c66610be0d94045c417dde54f8ffadd26977b5 (diff) | |
| download | emacs-01bd1b0df605d644ae31e8f1f81d926a5d8c7099.tar.gz emacs-01bd1b0df605d644ae31e8f1f81d926a5d8c7099.zip | |
Fix non-ASCII input in non-GUI frames on MS-Windows. (Bug#12055)
src/w32inevt.c: Include w32inevt.h.
(w32_read_console_input): New inline function, calls either
ReadConsoleInputA or ReadConsoleInputW, depending on the value of
w32_console_unicode_input.
(fill_queue): Call w32_read_console_input instead of ReadConsoleInput.
(w32_kbd_patch_key, key_event): Use the codepage returned by
GetConsoleCP, rather than the ANSI codepage returned by GetLocaleInfo.
(key_event): use uChar.UnicodeChar only if
w32_console_unicode_input is non-zero.
src/w32console.c: Include w32heap.h.
<w32_console_unicode_input>: New global variable.
(initialize_w32_display): Set w32_console_unicode_input to 1 on NT
family of Windows, zero otherwise.
src/w32inevt.h: Declare w32_console_unicode_input.
lisp/international/mule-cmds.el (set-locale-environment): In a
console session on MS-Windows, set up keyboard and terminal
encoding from the OEM codepage, not the ANSI codepage.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 18 | ||||
| -rw-r--r-- | src/w32console.c | 7 | ||||
| -rw-r--r-- | src/w32inevt.c | 46 | ||||
| -rw-r--r-- | src/w32inevt.h | 2 |
4 files changed, 57 insertions, 16 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 8d0e7caf4ea..6457fc2209b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,23 @@ | |||
| 1 | 2012-07-28 Eli Zaretskii <eliz@gnu.org> | 1 | 2012-07-28 Eli Zaretskii <eliz@gnu.org> |
| 2 | 2 | ||
| 3 | Fix non-ASCII input in non-GUI frames on MS-Windows. (Bug#12055) | ||
| 4 | * w32inevt.c: Include w32inevt.h. | ||
| 5 | (w32_read_console_input): New inline function, calls either | ||
| 6 | ReadConsoleInputA or ReadConsoleInputW, depending on the value of | ||
| 7 | w32_console_unicode_input. | ||
| 8 | (fill_queue): Call w32_read_console_input instead of ReadConsoleInput. | ||
| 9 | (w32_kbd_patch_key, key_event): Use the codepage returned by | ||
| 10 | GetConsoleCP, rather than the ANSI codepage returned by GetLocaleInfo. | ||
| 11 | (key_event): use uChar.UnicodeChar only if | ||
| 12 | w32_console_unicode_input is non-zero. | ||
| 13 | |||
| 14 | * w32console.c: Include w32heap.h. | ||
| 15 | <w32_console_unicode_input>: New global variable. | ||
| 16 | (initialize_w32_display): Set w32_console_unicode_input to 1 on NT | ||
| 17 | family of Windows, zero otherwise. | ||
| 18 | |||
| 19 | * w32inevt.h: Declare w32_console_unicode_input. | ||
| 20 | |||
| 3 | * xdisp.c (init_iterator): Don't reference tip_frame in a build | 21 | * xdisp.c (init_iterator): Don't reference tip_frame in a build |
| 4 | --without-x. (Bug#11742) | 22 | --without-x. (Bug#11742) |
| 5 | 23 | ||
diff --git a/src/w32console.c b/src/w32console.c index 42d89cca6d7..c3a1c5d86b3 100644 --- a/src/w32console.c +++ b/src/w32console.c | |||
| @@ -37,6 +37,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 37 | #include "termhooks.h" | 37 | #include "termhooks.h" |
| 38 | #include "termchar.h" | 38 | #include "termchar.h" |
| 39 | #include "dispextern.h" | 39 | #include "dispextern.h" |
| 40 | #include "w32heap.h" /* for os_subtype */ | ||
| 40 | #include "w32inevt.h" | 41 | #include "w32inevt.h" |
| 41 | 42 | ||
| 42 | /* from window.c */ | 43 | /* from window.c */ |
| @@ -67,6 +68,7 @@ static CONSOLE_CURSOR_INFO prev_console_cursor; | |||
| 67 | #endif | 68 | #endif |
| 68 | 69 | ||
| 69 | HANDLE keyboard_handle; | 70 | HANDLE keyboard_handle; |
| 71 | int w32_console_unicode_input; | ||
| 70 | 72 | ||
| 71 | 73 | ||
| 72 | /* Setting this as the ctrl handler prevents emacs from being killed when | 74 | /* Setting this as the ctrl handler prevents emacs from being killed when |
| @@ -786,6 +788,11 @@ initialize_w32_display (struct terminal *term) | |||
| 786 | info.srWindow.Left); | 788 | info.srWindow.Left); |
| 787 | } | 789 | } |
| 788 | 790 | ||
| 791 | if (os_subtype == OS_NT) | ||
| 792 | w32_console_unicode_input = 1; | ||
| 793 | else | ||
| 794 | w32_console_unicode_input = 0; | ||
| 795 | |||
| 789 | /* Setup w32_display_info structure for this frame. */ | 796 | /* Setup w32_display_info structure for this frame. */ |
| 790 | 797 | ||
| 791 | w32_initialize_display_info (build_string ("Console")); | 798 | w32_initialize_display_info (build_string ("Console")); |
diff --git a/src/w32inevt.c b/src/w32inevt.c index a85fdbbe435..8d041194ca1 100644 --- a/src/w32inevt.c +++ b/src/w32inevt.c | |||
| @@ -41,6 +41,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 41 | #include "termchar.h" | 41 | #include "termchar.h" |
| 42 | #include "w32heap.h" | 42 | #include "w32heap.h" |
| 43 | #include "w32term.h" | 43 | #include "w32term.h" |
| 44 | #include "w32inevt.h" | ||
| 44 | 45 | ||
| 45 | /* stdin, from w32console.c */ | 46 | /* stdin, from w32console.c */ |
| 46 | extern HANDLE keyboard_handle; | 47 | extern HANDLE keyboard_handle; |
| @@ -61,6 +62,15 @@ static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue; | |||
| 61 | /* Temporarily store lead byte of DBCS input sequences. */ | 62 | /* Temporarily store lead byte of DBCS input sequences. */ |
| 62 | static char dbcs_lead = 0; | 63 | static char dbcs_lead = 0; |
| 63 | 64 | ||
| 65 | static inline BOOL | ||
| 66 | w32_read_console_input (HANDLE h, INPUT_RECORD *rec, DWORD recsize, | ||
| 67 | DWORD *waiting) | ||
| 68 | { | ||
| 69 | return (w32_console_unicode_input | ||
| 70 | ? ReadConsoleInputW (h, rec, recsize, waiting) | ||
| 71 | : ReadConsoleInputA (h, rec, recsize, waiting)); | ||
| 72 | } | ||
| 73 | |||
| 64 | static int | 74 | static int |
| 65 | fill_queue (BOOL block) | 75 | fill_queue (BOOL block) |
| 66 | { | 76 | { |
| @@ -80,8 +90,8 @@ fill_queue (BOOL block) | |||
| 80 | return 0; | 90 | return 0; |
| 81 | } | 91 | } |
| 82 | 92 | ||
| 83 | rc = ReadConsoleInput (keyboard_handle, event_queue, EVENT_QUEUE_SIZE, | 93 | rc = w32_read_console_input (keyboard_handle, event_queue, EVENT_QUEUE_SIZE, |
| 84 | &events_waiting); | 94 | &events_waiting); |
| 85 | if (!rc) | 95 | if (!rc) |
| 86 | return -1; | 96 | return -1; |
| 87 | queue_ptr = event_queue; | 97 | queue_ptr = event_queue; |
| @@ -224,7 +234,7 @@ w32_kbd_patch_key (KEY_EVENT_RECORD *event) | |||
| 224 | #endif | 234 | #endif |
| 225 | 235 | ||
| 226 | /* On NT, call ToUnicode instead and then convert to the current | 236 | /* On NT, call ToUnicode instead and then convert to the current |
| 227 | locale's default codepage. */ | 237 | console input codepage. */ |
| 228 | if (os_subtype == OS_NT) | 238 | if (os_subtype == OS_NT) |
| 229 | { | 239 | { |
| 230 | WCHAR buf[128]; | 240 | WCHAR buf[128]; |
| @@ -233,14 +243,9 @@ w32_kbd_patch_key (KEY_EVENT_RECORD *event) | |||
| 233 | keystate, buf, 128, 0); | 243 | keystate, buf, 128, 0); |
| 234 | if (isdead > 0) | 244 | if (isdead > 0) |
| 235 | { | 245 | { |
| 236 | char cp[20]; | 246 | int cpId = GetConsoleCP (); |
| 237 | int cpId; | ||
| 238 | 247 | ||
| 239 | event->uChar.UnicodeChar = buf[isdead - 1]; | 248 | event->uChar.UnicodeChar = buf[isdead - 1]; |
| 240 | |||
| 241 | GetLocaleInfo (GetThreadLocale (), | ||
| 242 | LOCALE_IDEFAULTANSICODEPAGE, cp, 20); | ||
| 243 | cpId = atoi (cp); | ||
| 244 | isdead = WideCharToMultiByte (cpId, 0, buf, isdead, | 249 | isdead = WideCharToMultiByte (cpId, 0, buf, isdead, |
| 245 | ansi_code, 4, NULL, NULL); | 250 | ansi_code, 4, NULL, NULL); |
| 246 | } | 251 | } |
| @@ -447,26 +452,34 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) | |||
| 447 | } | 452 | } |
| 448 | else if (event->uChar.AsciiChar > 0) | 453 | else if (event->uChar.AsciiChar > 0) |
| 449 | { | 454 | { |
| 455 | /* Pure ASCII characters < 128. */ | ||
| 450 | emacs_ev->kind = ASCII_KEYSTROKE_EVENT; | 456 | emacs_ev->kind = ASCII_KEYSTROKE_EVENT; |
| 451 | emacs_ev->code = event->uChar.AsciiChar; | 457 | emacs_ev->code = event->uChar.AsciiChar; |
| 452 | } | 458 | } |
| 453 | else if (event->uChar.UnicodeChar > 0) | 459 | else if (event->uChar.UnicodeChar > 0 |
| 460 | && w32_console_unicode_input) | ||
| 454 | { | 461 | { |
| 462 | /* Unicode codepoint; only valid if we are using Unicode | ||
| 463 | console input mode. */ | ||
| 455 | emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; | 464 | emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; |
| 456 | emacs_ev->code = event->uChar.UnicodeChar; | 465 | emacs_ev->code = event->uChar.UnicodeChar; |
| 457 | } | 466 | } |
| 458 | else | 467 | else |
| 459 | { | 468 | { |
| 460 | /* Fallback for non-Unicode versions of Windows. */ | 469 | /* Fallback handling of non-ASCII characters for non-Unicode |
| 470 | versions of Windows, and for non-Unicode input on NT | ||
| 471 | family of Windows. Only characters in the current | ||
| 472 | console codepage are supported by this fallback. */ | ||
| 461 | wchar_t code; | 473 | wchar_t code; |
| 462 | char dbcs[2]; | 474 | char dbcs[2]; |
| 463 | char cp[20]; | ||
| 464 | int cpId; | 475 | int cpId; |
| 465 | 476 | ||
| 466 | /* Get the codepage to interpret this key with. */ | 477 | /* Get the current console input codepage to interpret this |
| 467 | GetLocaleInfo (GetThreadLocale (), | 478 | key with. Note that the system defaults for the OEM |
| 468 | LOCALE_IDEFAULTANSICODEPAGE, cp, 20); | 479 | codepage could have been changed by calling SetConsoleCP |
| 469 | cpId = atoi (cp); | 480 | or w32-set-console-codepage, so using GetLocaleInfo to |
| 481 | get LOCALE_IDEFAULTCODEPAGE is not TRT here. */ | ||
| 482 | cpId = GetConsoleCP (); | ||
| 470 | 483 | ||
| 471 | dbcs[0] = dbcs_lead; | 484 | dbcs[0] = dbcs_lead; |
| 472 | dbcs[1] = event->uChar.AsciiChar; | 485 | dbcs[1] = event->uChar.AsciiChar; |
| @@ -501,6 +514,7 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) | |||
| 501 | } | 514 | } |
| 502 | else | 515 | else |
| 503 | { | 516 | { |
| 517 | /* Function keys and other non-character keys. */ | ||
| 504 | emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT; | 518 | emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT; |
| 505 | emacs_ev->code = event->wVirtualKeyCode; | 519 | emacs_ev->code = event->wVirtualKeyCode; |
| 506 | } | 520 | } |
diff --git a/src/w32inevt.h b/src/w32inevt.h index d228637abfb..5386f2aa96c 100644 --- a/src/w32inevt.h +++ b/src/w32inevt.h | |||
| @@ -19,6 +19,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 19 | #ifndef EMACS_W32INEVT_H | 19 | #ifndef EMACS_W32INEVT_H |
| 20 | #define EMACS_W32INEVT_H | 20 | #define EMACS_W32INEVT_H |
| 21 | 21 | ||
| 22 | extern int w32_console_unicode_input; | ||
| 23 | |||
| 22 | extern int w32_console_read_socket (struct terminal *term, int numchars, | 24 | extern int w32_console_read_socket (struct terminal *term, int numchars, |
| 23 | struct input_event *hold_quit); | 25 | struct input_event *hold_quit); |
| 24 | extern void w32_console_mouse_position (FRAME_PTR *f, int insist, | 26 | extern void w32_console_mouse_position (FRAME_PTR *f, int insist, |