aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/keyboard.c
diff options
context:
space:
mode:
authorJan Engelhardt <jengelh@linux01.gwdg.de>2007-07-16 02:40:40 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-16 12:05:46 -0400
commit759448f459234bfcf34b82471f0dba77a9aca498 (patch)
tree61cbf8501bdad78c03e034072791fbf3e0436d43 /drivers/char/keyboard.c
parentaa0ac36518be648dda3a32f0b37a8b2b546e1b24 (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.c26
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 */
314static void to_utf8(struct vc_data *vc, ushort c) 314static 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;