Author: jim Date: 2006-01-18 08:58:57 -0700 (Wed, 18 Jan 2006) New Revision: 1357
Added: trunk/linux/linux-2.6.15.1-utf8_input-1.patch Modified: trunk/ Log: [EMAIL PROTECTED]: jim | 2006-01-17 22:09:39 -0800 Added: linux-2.6.15.1-utf8_input-1.patch Property changes on: trunk ___________________________________________________________________ Name: svk:merge - cc2644d5-6cf8-0310-b111-c40428001e49:/patches:1695 + cc2644d5-6cf8-0310-b111-c40428001e49:/patches:1698 Added: trunk/linux/linux-2.6.15.1-utf8_input-1.patch =================================================================== --- trunk/linux/linux-2.6.15.1-utf8_input-1.patch 2006-01-18 15:57:42 UTC (rev 1356) +++ trunk/linux/linux-2.6.15.1-utf8_input-1.patch 2006-01-18 15:58:57 UTC (rev 1357) @@ -0,0 +1,335 @@ +Submitted by: Alexander E. Patrakov +Date: 2005-10-18 +Initial Package Version: 2.6.15 +Upstream Status: Rejected: they say it modifies the meaning of an existing ioctl +Origin: http://chris.heathens.co.nz/linux/downloads/patches-2.6.4-cdh1.tar.gz + Porting to linux-2.6.12.5 by Alexander E. Patrakov + Porting to linux-2.6.15 +Description: 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 + +diff -Naur linux-2.6.15.1.orig/drivers/char/consolemap.c linux-2.6.15.1/drivers/char/consolemap.c +--- linux-2.6.15.1.orig/drivers/char/consolemap.c 2006-01-15 06:16:02.000000000 +0000 ++++ linux-2.6.15.1/drivers/char/consolemap.c 2006-01-18 06:00:08.000000000 +0000 +@@ -178,6 +178,7 @@ + unsigned long refcount; + unsigned long sum; + unsigned char *inverse_translations[4]; ++ u16 *inverse_trans_unicode; + int readonly; + }; + +@@ -208,6 +209,41 @@ + } + } + ++static void set_inverse_trans_unicode(struct vc_data *conp, ++ struct uni_pagedir *p) ++{ ++ int i, j, k, glyph; ++ u16 **p1, *p2; ++ u16 *q; ++ ++ if (!p) return; ++ q = p->inverse_trans_unicode; ++ if (!q) { ++ q = p->inverse_trans_unicode = ++ kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL); ++ if (!q) ++ return; ++ } ++ memset(q, 0, MAX_GLYPH * sizeof(u16)); ++ ++ for (i = 0; i < 32; i++) { ++ p1 = p->uni_pgdir[i]; ++ if (!p1) ++ continue; ++ for (j = 0; j < 32; j++) { ++ p2 = p1[j]; ++ if (!p2) ++ continue; ++ for (k = 0; k < 64; k++) { ++ glyph = p2[k]; ++ if (glyph >= 0 && glyph < MAX_GLYPH ++ && q[glyph] < 32) ++ q[glyph] = (i << 11) + (j << 6) + k; ++ } ++ } ++ } ++} ++ + unsigned short *set_translate(int m, struct vc_data *vc) + { + inv_translate[vc->vc_num] = m; +@@ -218,19 +254,29 @@ + * Inverse translation is impossible for several reasons: + * 1. The font<->character maps are not 1-1. + * 2. The text may have been written while a different translation map +- * was active, or using Unicode. ++ * was active. + * Still, it is now possible to a certain extent to cut and paste non-ASCII. + */ +-unsigned char inverse_translate(struct vc_data *conp, int glyph) ++u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode) + { + struct uni_pagedir *p; ++ int m; + if (glyph < 0 || glyph >= MAX_GLYPH) + return 0; +- else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) || +- !p->inverse_translations[inv_translate[conp->vc_num]]) ++ else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc)) + return glyph; +- else +- return p->inverse_translations[inv_translate[conp->vc_num]][glyph]; ++ else if (use_unicode) { ++ if (!p->inverse_trans_unicode) ++ return glyph; ++ else ++ return p->inverse_trans_unicode[glyph]; ++ } else { ++ m = inv_translate[conp->vc_num]; ++ if (!p->inverse_translations[m]) ++ return glyph; ++ else ++ return p->inverse_translations[m][glyph]; ++ } + } + + static void update_user_maps(void) +@@ -244,6 +290,7 @@ + p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc; + if (p && p != q) { + set_inverse_transl(vc_cons[i].d, p, USER_MAP); ++ set_inverse_trans_unicode(vc_cons[i].d, p); + q = p; + } + } +@@ -354,6 +401,10 @@ + kfree(p->inverse_translations[i]); + p->inverse_translations[i] = NULL; + } ++ if (p->inverse_trans_unicode) { ++ kfree(p->inverse_trans_unicode); ++ p->inverse_trans_unicode = NULL; ++ } + } + + void con_free_unimap(struct vc_data *vc) +@@ -512,6 +563,7 @@ + + for (i = 0; i <= 3; i++) + set_inverse_transl(vc, p, i); /* Update all inverse translations */ ++ set_inverse_trans_unicode(vc, p); + + return err; + } +@@ -562,6 +614,7 @@ + + for (i = 0; i <= 3; i++) + set_inverse_transl(vc, p, i); /* Update all inverse translations */ ++ set_inverse_trans_unicode(vc, p); + dflt = p; + return err; + } +@@ -618,6 +671,19 @@ + p->readonly = rdonly; + } + ++/* may be called during an interrupt */ ++u32 conv_8bit_to_uni(unsigned char c) ++{ ++ /* ++ * Always use USER_MAP. This function is used by the keyboard, ++ * which shouldn't be affected by G0/G1 switching, etc. ++ * If the user map still contains default values, i.e. the ++ * direct-to-font mapping, then assume user is using Latin1. ++ */ ++ unsigned short uni = translations[USER_MAP][c]; ++ return uni == (0xf000 | c) ? c : uni; ++} ++ + int + conv_uni_to_pc(struct vc_data *conp, long ucs) + { +diff -Naur linux-2.6.15.1.orig/drivers/char/keyboard.c linux-2.6.15.1/drivers/char/keyboard.c +--- linux-2.6.15.1.orig/drivers/char/keyboard.c 2006-01-15 06:16:02.000000000 +0000 ++++ linux-2.6.15.1/drivers/char/keyboard.c 2006-01-18 05:58:11.000000000 +0000 +@@ -34,6 +34,7 @@ + #include <linux/init.h> + #include <linux/slab.h> + ++#include <linux/consolemap.h> + #include <linux/kbd_kern.h> + #include <linux/kbd_diacr.h> + #include <linux/vt_kern.h> +@@ -349,6 +350,15 @@ + } + } + ++static void put_8bit(struct vc_data *vc, u8 c) ++{ ++ if (kbd->kbdmode != VC_UNICODE || c < 32 || c == 127) ++ /* Don't translate control chars */ ++ put_queue(vc, c); ++ else ++ to_utf8(vc, conv_8bit_to_uni(c)); ++} ++ + /* + * Called after returning from RAW mode or when changing consoles - recompute + * shift_down[] and shift_state from key_down[] maybe called when keymap is +@@ -409,7 +419,7 @@ + if (ch == ' ' || ch == d) + return d; + +- put_queue(vc, d); ++ put_8bit(vc, d); + return ch; + } + +@@ -419,7 +429,7 @@ + static void fn_enter(struct vc_data *vc, struct pt_regs *regs) + { + if (diacr) { +- put_queue(vc, diacr); ++ put_8bit(vc, diacr); + diacr = 0; + } + put_queue(vc, 13); +@@ -628,7 +638,7 @@ + diacr = value; + return; + } +- put_queue(vc, value); ++ put_8bit(vc, value); + } + + /* +diff -Naur linux-2.6.15.1.orig/drivers/char/selection.c linux-2.6.15.1/drivers/char/selection.c +--- linux-2.6.15.1.orig/drivers/char/selection.c 2006-01-15 06:16:02.000000000 +0000 ++++ linux-2.6.15.1/drivers/char/selection.c 2006-01-18 05:58:12.000000000 +0000 +@@ -20,6 +20,7 @@ + + #include <asm/uaccess.h> + ++#include <linux/kbd_kern.h> + #include <linux/vt_kern.h> + #include <linux/consolemap.h> + #include <linux/selection.h> +@@ -34,6 +35,7 @@ + /* Variables for selection control. */ + /* Use a dynamic buffer, instead of static (Dec 1994) */ + struct vc_data *sel_cons; /* must not be disallocated */ ++static int use_unicode; + static volatile int sel_start = -1; /* cleared by clear_selection */ + static int sel_end; + static int sel_buffer_lth; +@@ -54,10 +56,8 @@ + complement_pos(sel_cons, where); + } + +-static unsigned char +-sel_pos(int n) +-{ +- return inverse_translate(sel_cons, screen_glyph(sel_cons, n)); ++static u16 sel_pos(int n) { ++ return inverse_translate(sel_cons, screen_glyph(sel_cons, n), use_unicode); + } + + /* remove the current selection highlight, if any, +@@ -86,8 +86,8 @@ + 0xFF7FFFFF /* latin-1 accented letters, not division sign */ + }; + +-static inline int inword(const unsigned char c) { +- return ( inwordLut[c>>5] >> (c & 0x1F) ) & 1; ++static inline int inword(const u16 c) { ++ return c > 0xff || ((inwordLut[c >> 5] >> (c & 0x1F)) & 1); + } + + /* set inwordLut contents. Invoked by ioctl(). */ +@@ -108,13 +108,35 @@ + return (v > u) ? u : v; + } + ++/* stores the char in UTF8 and returns the number of bytes used (1-3) */ ++int store_utf8(u16 c, char *p) { ++ if (c < 0x80) { ++ /* 0******* */ ++ p[0] = c; ++ return 1; ++ } else if (c < 0x800) { ++ /* 110***** 10****** */ ++ p[0] = 0xc0 | (c >> 6); ++ p[1] = 0x80 | (c & 0x3f); ++ return 2; ++ } else { ++ /* 1110**** 10****** 10****** */ ++ p[0] = 0xe0 | (c >> 12); ++ p[1] = 0x80 | ((c >> 6) & 0x3f); ++ p[2] = 0x80 | (c & 0x3f); ++ return 3; ++ } ++} ++ + /* set the current selection. Invoked by ioctl() or by kernel code. */ + int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) + { + struct vc_data *vc = vc_cons[fg_console].d; + int sel_mode, new_sel_start, new_sel_end, spc; + char *bp, *obp; +- int i, ps, pe; ++ int i, ps, pe, multiplier; ++ u16 c; ++ struct kbd_struct *kbd = kbd_table + fg_console; + + poke_blanked_console(); + +@@ -158,6 +180,7 @@ + clear_selection(); + sel_cons = vc_cons[fg_console].d; + } ++ use_unicode = kbd && kbd->kbdmode == VC_UNICODE; + + switch (sel_mode) + { +@@ -240,7 +263,8 @@ + sel_end = new_sel_end; + + /* Allocate a new buffer before freeing the old one ... */ +- bp = kmalloc((sel_end-sel_start)/2+1, GFP_KERNEL); ++ multiplier = use_unicode ? 3 : 1; /* chars can take up to 3 bytes */ ++ bp = kmalloc((sel_end-sel_start)/2*multiplier+1, GFP_KERNEL); + if (!bp) { + printk(KERN_WARNING "selection: kmalloc() failed\n"); + clear_selection(); +@@ -251,8 +275,12 @@ + + obp = bp; + for (i = sel_start; i <= sel_end; i += 2) { +- *bp = sel_pos(i); +- if (!isspace(*bp++)) ++ c = sel_pos(i); ++ if (use_unicode) ++ bp += store_utf8(c, bp); ++ else ++ *bp++ = c; ++ if (!isspace(c)) + obp = bp; + if (! ((i + 2) % vc->vc_size_row)) { + /* strip trailing blanks from line and add newline, +diff -Naur linux-2.6.15.1.orig/include/linux/consolemap.h linux-2.6.15.1/include/linux/consolemap.h +--- linux-2.6.15.1.orig/include/linux/consolemap.h 2006-01-15 06:16:02.000000000 +0000 ++++ linux-2.6.15.1/include/linux/consolemap.h 2006-01-18 05:58:12.000000000 +0000 +@@ -10,6 +10,7 @@ + + struct vc_data; + +-extern unsigned char inverse_translate(struct vc_data *conp, int glyph); ++extern u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode); + extern unsigned short *set_translate(int m, struct vc_data *vc); + extern int conv_uni_to_pc(struct vc_data *conp, long ucs); ++extern u32 conv_8bit_to_uni(unsigned char c); -- http://linuxfromscratch.org/mailman/listinfo/patches FAQ: http://www.linuxfromscratch.org/faq/ Unsubscribe: See the above information page
