diff options
author | Jan Engelhardt <jengelh@linux01.gwdg.de> | 2007-07-16 02:40:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-16 12:05:46 -0400 |
commit | 759448f459234bfcf34b82471f0dba77a9aca498 (patch) | |
tree | 61cbf8501bdad78c03e034072791fbf3e0436d43 /drivers/char/keyboard.c | |
parent | aa0ac36518be648dda3a32f0b37a8b2b546e1b24 (diff) |
Kernel utf-8 handling
This patch fixes dead keys and copy/paste of non-ASCII characters in UTF-8
mode on Linux console. See more details about the original patch at:
http://chris.heathens.co.nz/linux/utf8.html
Already posted on
(Oldest) http://lkml.org/lkml/2003/5/31/148
http://lkml.org/lkml/2005/12/24/69
(Recent) http://lkml.org/lkml/2006/8/7/75
[bunk@stusta.de: make drivers/char/selection.c:store_utf8() static]
Signed-off-by: Jan Engelhardt <jengelh@gmx.de>
Cc: Alexander E. Patrakov <patrakov@ums.usu.ru>
Cc: Dmitry Torokhov <dtor@mail.ru>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
Cc: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/keyboard.c')
-rw-r--r-- | drivers/char/keyboard.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 90965b4def5c..2ce0af1bd588 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -24,6 +24,7 @@ | |||
24 | * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik) | 24 | * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik) |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/consolemap.h> | ||
27 | #include <linux/module.h> | 28 | #include <linux/module.h> |
28 | #include <linux/sched.h> | 29 | #include <linux/sched.h> |
29 | #include <linux/tty.h> | 30 | #include <linux/tty.h> |
@@ -308,10 +309,9 @@ static void applkey(struct vc_data *vc, int key, char mode) | |||
308 | * Many other routines do put_queue, but I think either | 309 | * Many other routines do put_queue, but I think either |
309 | * they produce ASCII, or they produce some user-assigned | 310 | * they produce ASCII, or they produce some user-assigned |
310 | * string, and in both cases we might assume that it is | 311 | * string, and in both cases we might assume that it is |
311 | * in utf-8 already. UTF-8 is defined for words of up to 31 bits, | 312 | * in utf-8 already. |
312 | * but we need only 16 bits here | ||
313 | */ | 313 | */ |
314 | static void to_utf8(struct vc_data *vc, ushort c) | 314 | static void to_utf8(struct vc_data *vc, uint c) |
315 | { | 315 | { |
316 | if (c < 0x80) | 316 | if (c < 0x80) |
317 | /* 0******* */ | 317 | /* 0******* */ |
@@ -320,11 +320,21 @@ static void to_utf8(struct vc_data *vc, ushort c) | |||
320 | /* 110***** 10****** */ | 320 | /* 110***** 10****** */ |
321 | put_queue(vc, 0xc0 | (c >> 6)); | 321 | put_queue(vc, 0xc0 | (c >> 6)); |
322 | put_queue(vc, 0x80 | (c & 0x3f)); | 322 | put_queue(vc, 0x80 | (c & 0x3f)); |
323 | } else { | 323 | } else if (c < 0x10000) { |
324 | if (c >= 0xD800 && c < 0xE000) | ||
325 | return; | ||
326 | if (c == 0xFFFF) | ||
327 | return; | ||
324 | /* 1110**** 10****** 10****** */ | 328 | /* 1110**** 10****** 10****** */ |
325 | put_queue(vc, 0xe0 | (c >> 12)); | 329 | put_queue(vc, 0xe0 | (c >> 12)); |
326 | put_queue(vc, 0x80 | ((c >> 6) & 0x3f)); | 330 | put_queue(vc, 0x80 | ((c >> 6) & 0x3f)); |
327 | put_queue(vc, 0x80 | (c & 0x3f)); | 331 | put_queue(vc, 0x80 | (c & 0x3f)); |
332 | } else if (c < 0x110000) { | ||
333 | /* 11110*** 10****** 10****** 10****** */ | ||
334 | put_queue(vc, 0xf0 | (c >> 18)); | ||
335 | put_queue(vc, 0x80 | ((c >> 12) & 0x3f)); | ||
336 | put_queue(vc, 0x80 | ((c >> 6) & 0x3f)); | ||
337 | put_queue(vc, 0x80 | (c & 0x3f)); | ||
328 | } | 338 | } |
329 | } | 339 | } |
330 | 340 | ||
@@ -393,7 +403,7 @@ static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch) | |||
393 | return d; | 403 | return d; |
394 | 404 | ||
395 | if (kbd->kbdmode == VC_UNICODE) | 405 | if (kbd->kbdmode == VC_UNICODE) |
396 | to_utf8(vc, d); | 406 | to_utf8(vc, conv_8bit_to_uni(d)); |
397 | else if (d < 0x100) | 407 | else if (d < 0x100) |
398 | put_queue(vc, d); | 408 | put_queue(vc, d); |
399 | 409 | ||
@@ -407,7 +417,7 @@ static void fn_enter(struct vc_data *vc) | |||
407 | { | 417 | { |
408 | if (diacr) { | 418 | if (diacr) { |
409 | if (kbd->kbdmode == VC_UNICODE) | 419 | if (kbd->kbdmode == VC_UNICODE) |
410 | to_utf8(vc, diacr); | 420 | to_utf8(vc, conv_8bit_to_uni(diacr)); |
411 | else if (diacr < 0x100) | 421 | else if (diacr < 0x100) |
412 | put_queue(vc, diacr); | 422 | put_queue(vc, diacr); |
413 | diacr = 0; | 423 | diacr = 0; |
@@ -617,7 +627,7 @@ static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag) | |||
617 | return; | 627 | return; |
618 | } | 628 | } |
619 | if (kbd->kbdmode == VC_UNICODE) | 629 | if (kbd->kbdmode == VC_UNICODE) |
620 | to_utf8(vc, value); | 630 | to_utf8(vc, conv_8bit_to_uni(value)); |
621 | else if (value < 0x100) | 631 | else if (value < 0x100) |
622 | put_queue(vc, value); | 632 | put_queue(vc, value); |
623 | } | 633 | } |
@@ -775,7 +785,7 @@ static void k_shift(struct vc_data *vc, unsigned char value, char up_flag) | |||
775 | /* kludge */ | 785 | /* kludge */ |
776 | if (up_flag && shift_state != old_state && npadch != -1) { | 786 | if (up_flag && shift_state != old_state && npadch != -1) { |
777 | if (kbd->kbdmode == VC_UNICODE) | 787 | if (kbd->kbdmode == VC_UNICODE) |
778 | to_utf8(vc, npadch & 0xffff); | 788 | to_utf8(vc, npadch); |
779 | else | 789 | else |
780 | put_queue(vc, npadch & 0xff); | 790 | put_queue(vc, npadch & 0xff); |
781 | npadch = -1; | 791 | npadch = -1; |