]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/linux-2.6.16.27-utf8_input-1.patch
Pakfire laedt die Listen jetzt besser und hat eine veraenderte Oberflaeche bekommen.
[ipfire-2.x.git] / src / patches / linux-2.6.16.27-utf8_input-1.patch
CommitLineData
f59e1e88
MT
1Submitted by: Alexander E. Patrakov <patrakov@ums.usu.ru>
2Signed-off-by: Alexander E. Patrakov <patrakov@ums.usu.ru>
3Date: 2005-10-18
4Initial Package Version: 2.6.15
5Upstream Status: Rejected: they say it modifies the meaning of an existing ioctl
6Origin: http://chris.heathens.co.nz/linux/downloads/patches-2.6.4-cdh1.tar.gz
7 Porting to linux-2.6.16 by Alexander E. Patrakov
8Description: This patch fixes dead keys and copy/paste of non-ASCII characters
9 in UTF-8 mode on Linux console.
10 See more details about the original patch at:
11 http://chris.heathens.co.nz/linux/utf8.html
12
13diff -ur linux-2.6.15-rc6.orig/drivers/char/consolemap.c linux-2.6.15-rc6.my/drivers/char/consolemap.c
14--- linux-2.6.15-rc6.orig/drivers/char/consolemap.c 2005-12-25 10:00:12.000000000 +0500
15+++ linux-2.6.15-rc6.my/drivers/char/consolemap.c 2005-12-25 10:01:22.000000000 +0500
16@@ -178,6 +178,7 @@
17 unsigned long refcount;
18 unsigned long sum;
19 unsigned char *inverse_translations[4];
20+ u16 *inverse_trans_unicode;
21 int readonly;
22 };
23
24@@ -208,6 +209,41 @@
25 }
26 }
27
28+static void set_inverse_trans_unicode(struct vc_data *conp,
29+ struct uni_pagedir *p)
30+{
31+ int i, j, k, glyph;
32+ u16 **p1, *p2;
33+ u16 *q;
34+
35+ if (!p) return;
36+ q = p->inverse_trans_unicode;
37+ if (!q) {
38+ q = p->inverse_trans_unicode =
39+ kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
40+ if (!q)
41+ return;
42+ }
43+ memset(q, 0, MAX_GLYPH * sizeof(u16));
44+
45+ for (i = 0; i < 32; i++) {
46+ p1 = p->uni_pgdir[i];
47+ if (!p1)
48+ continue;
49+ for (j = 0; j < 32; j++) {
50+ p2 = p1[j];
51+ if (!p2)
52+ continue;
53+ for (k = 0; k < 64; k++) {
54+ glyph = p2[k];
55+ if (glyph >= 0 && glyph < MAX_GLYPH
56+ && q[glyph] < 32)
57+ q[glyph] = (i << 11) + (j << 6) + k;
58+ }
59+ }
60+ }
61+}
62+
63 unsigned short *set_translate(int m, struct vc_data *vc)
64 {
65 inv_translate[vc->vc_num] = m;
66@@ -218,19 +254,29 @@
67 * Inverse translation is impossible for several reasons:
68 * 1. The font<->character maps are not 1-1.
69 * 2. The text may have been written while a different translation map
70- * was active, or using Unicode.
71+ * was active.
72 * Still, it is now possible to a certain extent to cut and paste non-ASCII.
73 */
74-unsigned char inverse_translate(struct vc_data *conp, int glyph)
75+u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
76 {
77 struct uni_pagedir *p;
78+ int m;
79 if (glyph < 0 || glyph >= MAX_GLYPH)
80 return 0;
81- else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) ||
82- !p->inverse_translations[inv_translate[conp->vc_num]])
83+ else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc))
84 return glyph;
85- else
86- return p->inverse_translations[inv_translate[conp->vc_num]][glyph];
87+ else if (use_unicode) {
88+ if (!p->inverse_trans_unicode)
89+ return glyph;
90+ else
91+ return p->inverse_trans_unicode[glyph];
92+ } else {
93+ m = inv_translate[conp->vc_num];
94+ if (!p->inverse_translations[m])
95+ return glyph;
96+ else
97+ return p->inverse_translations[m][glyph];
98+ }
99 }
100
101 static void update_user_maps(void)
102@@ -244,6 +290,7 @@
103 p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
104 if (p && p != q) {
105 set_inverse_transl(vc_cons[i].d, p, USER_MAP);
106+ set_inverse_trans_unicode(vc_cons[i].d, p);
107 q = p;
108 }
109 }
110@@ -354,6 +401,10 @@
111 kfree(p->inverse_translations[i]);
112 p->inverse_translations[i] = NULL;
113 }
114+ if (p->inverse_trans_unicode) {
115+ kfree(p->inverse_trans_unicode);
116+ p->inverse_trans_unicode = NULL;
117+ }
118 }
119
120 void con_free_unimap(struct vc_data *vc)
121@@ -512,6 +563,7 @@
122
123 for (i = 0; i <= 3; i++)
124 set_inverse_transl(vc, p, i); /* Update all inverse translations */
125+ set_inverse_trans_unicode(vc, p);
126
127 return err;
128 }
129@@ -562,6 +614,7 @@
130
131 for (i = 0; i <= 3; i++)
132 set_inverse_transl(vc, p, i); /* Update all inverse translations */
133+ set_inverse_trans_unicode(vc, p);
134 dflt = p;
135 return err;
136 }
137@@ -618,6 +671,19 @@
138 p->readonly = rdonly;
139 }
140
141+/* may be called during an interrupt */
142+u32 conv_8bit_to_uni(unsigned char c)
143+{
144+ /*
145+ * Always use USER_MAP. This function is used by the keyboard,
146+ * which shouldn't be affected by G0/G1 switching, etc.
147+ * If the user map still contains default values, i.e. the
148+ * direct-to-font mapping, then assume user is using Latin1.
149+ */
150+ unsigned short uni = translations[USER_MAP][c];
151+ return uni == (0xf000 | c) ? c : uni;
152+}
153+
154 int
155 conv_uni_to_pc(struct vc_data *conp, long ucs)
156 {
157diff -ur linux-2.6.15-rc6.orig/drivers/char/keyboard.c linux-2.6.15-rc6.my/drivers/char/keyboard.c
158--- linux-2.6.15-rc6.orig/drivers/char/keyboard.c 2005-12-25 10:00:12.000000000 +0500
159+++ linux-2.6.15-rc6.my/drivers/char/keyboard.c 2005-12-25 10:01:22.000000000 +0500
160@@ -34,6 +34,7 @@
161 #include <linux/init.h>
162 #include <linux/slab.h>
163
164+#include <linux/consolemap.h>
165 #include <linux/kbd_kern.h>
166 #include <linux/kbd_diacr.h>
167 #include <linux/vt_kern.h>
168@@ -329,10 +330,9 @@
169 * Many other routines do put_queue, but I think either
170 * they produce ASCII, or they produce some user-assigned
171 * string, and in both cases we might assume that it is
172- * in utf-8 already. UTF-8 is defined for words of up to 31 bits,
173- * but we need only 16 bits here
174+ * in utf-8 already.
175 */
176-static void to_utf8(struct vc_data *vc, ushort c)
177+static void to_utf8(struct vc_data *vc, uint c)
178 {
179 if (c < 0x80)
180 /* 0******* */
181@@ -341,14 +341,33 @@
182 /* 110***** 10****** */
183 put_queue(vc, 0xc0 | (c >> 6));
184 put_queue(vc, 0x80 | (c & 0x3f));
185- } else {
186+ } else if (c < 0x10000) {
187+ if (c >= 0xD800 && c < 0xE000)
188+ return;
189+ if (c == 0xFFFF)
190+ return;
191 /* 1110**** 10****** 10****** */
192 put_queue(vc, 0xe0 | (c >> 12));
193 put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
194 put_queue(vc, 0x80 | (c & 0x3f));
195+ } else if (c < 0x110000) {
196+ /* 11110*** 10****** 10****** 10****** */
197+ put_queue(vc, 0xf0 | (c >> 18));
198+ put_queue(vc, 0x80 | ((c >> 12) & 0x3f));
199+ put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
200+ put_queue(vc, 0x80 | (c & 0x3f));
201 }
202 }
203
204+static void put_8bit(struct vc_data *vc, u8 c)
205+{
206+ if (kbd->kbdmode != VC_UNICODE || c < 32 || c == 127)
207+ /* Don't translate control chars */
208+ put_queue(vc, c);
209+ else
210+ to_utf8(vc, conv_8bit_to_uni(c));
211+}
212+
213 /*
214 * Called after returning from RAW mode or when changing consoles - recompute
215 * shift_down[] and shift_state from key_down[] maybe called when keymap is
216@@ -409,7 +428,7 @@
217 if (ch == ' ' || ch == d)
218 return d;
219
220- put_queue(vc, d);
221+ put_8bit(vc, d);
222 return ch;
223 }
224
225@@ -419,7 +438,7 @@
226 static void fn_enter(struct vc_data *vc, struct pt_regs *regs)
227 {
228 if (diacr) {
229- put_queue(vc, diacr);
230+ put_8bit(vc, diacr);
231 diacr = 0;
232 }
233 put_queue(vc, 13);
234@@ -628,7 +647,7 @@
235 diacr = value;
236 return;
237 }
238- put_queue(vc, value);
239+ put_8bit(vc, value);
240 }
241
242 /*
243@@ -774,7 +793,7 @@
244 /* kludge */
245 if (up_flag && shift_state != old_state && npadch != -1) {
246 if (kbd->kbdmode == VC_UNICODE)
247- to_utf8(vc, npadch & 0xffff);
248+ to_utf8(vc, npadch);
249 else
250 put_queue(vc, npadch & 0xff);
251 npadch = -1;
252diff -ur linux-2.6.15-rc6.orig/drivers/char/selection.c linux-2.6.15-rc6.my/drivers/char/selection.c
253--- linux-2.6.15-rc6.orig/drivers/char/selection.c 2005-12-25 10:00:12.000000000 +0500
254+++ linux-2.6.15-rc6.my/drivers/char/selection.c 2005-12-25 10:01:22.000000000 +0500
255@@ -20,6 +20,7 @@
256
257 #include <asm/uaccess.h>
258
259+#include <linux/kbd_kern.h>
260 #include <linux/vt_kern.h>
261 #include <linux/consolemap.h>
262 #include <linux/selection.h>
263@@ -34,6 +35,7 @@
264 /* Variables for selection control. */
265 /* Use a dynamic buffer, instead of static (Dec 1994) */
266 struct vc_data *sel_cons; /* must not be disallocated */
267+static int use_unicode;
268 static volatile int sel_start = -1; /* cleared by clear_selection */
269 static int sel_end;
270 static int sel_buffer_lth;
271@@ -54,10 +56,11 @@
272 complement_pos(sel_cons, where);
273 }
274
275-static unsigned char
276+static u16
277 sel_pos(int n)
278 {
279- return inverse_translate(sel_cons, screen_glyph(sel_cons, n));
280+ return inverse_translate(sel_cons, screen_glyph(sel_cons, n),
281+ use_unicode);
282 }
283
284 /* remove the current selection highlight, if any,
285@@ -86,8 +89,8 @@
286 0xFF7FFFFF /* latin-1 accented letters, not division sign */
287 };
288
289-static inline int inword(const unsigned char c) {
290- return ( inwordLut[c>>5] >> (c & 0x1F) ) & 1;
291+static inline int inword(const u16 c) {
292+ return c > 0xff || (( inwordLut[c>>5] >> (c & 0x1F) ) & 1);
293 }
294
295 /* set inwordLut contents. Invoked by ioctl(). */
296@@ -108,13 +111,36 @@
297 return (v > u) ? u : v;
298 }
299
300+/* stores the char in UTF8 and returns the number of bytes used (1-3) */
301+int store_utf8(u16 c, char *p)
302+{
303+ if (c < 0x80) {
304+ /* 0******* */
305+ p[0] = c;
306+ return 1;
307+ } else if (c < 0x800) {
308+ /* 110***** 10****** */
309+ p[0] = 0xc0 | (c >> 6);
310+ p[1] = 0x80 | (c & 0x3f);
311+ return 2;
312+ } else {
313+ /* 1110**** 10****** 10****** */
314+ p[0] = 0xe0 | (c >> 12);
315+ p[1] = 0x80 | ((c >> 6) & 0x3f);
316+ p[2] = 0x80 | (c & 0x3f);
317+ return 3;
318+ }
319+}
320+
321 /* set the current selection. Invoked by ioctl() or by kernel code. */
322 int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
323 {
324 struct vc_data *vc = vc_cons[fg_console].d;
325 int sel_mode, new_sel_start, new_sel_end, spc;
326 char *bp, *obp;
327- int i, ps, pe;
328+ int i, ps, pe, multiplier;
329+ u16 c;
330+ struct kbd_struct *kbd = kbd_table + fg_console;
331
332 poke_blanked_console();
333
334@@ -158,7 +184,8 @@
335 clear_selection();
336 sel_cons = vc_cons[fg_console].d;
337 }
338-
339+ use_unicode = kbd && kbd->kbdmode == VC_UNICODE;
340+
341 switch (sel_mode)
342 {
343 case TIOCL_SELCHAR: /* character-by-character selection */
344@@ -240,7 +267,8 @@
345 sel_end = new_sel_end;
346
347 /* Allocate a new buffer before freeing the old one ... */
348- bp = kmalloc((sel_end-sel_start)/2+1, GFP_KERNEL);
349+ multiplier = use_unicode ? 3 : 1; /* chars can take up to 3 bytes */
350+ bp = kmalloc((sel_end-sel_start)/2*multiplier+1, GFP_KERNEL);
351 if (!bp) {
352 printk(KERN_WARNING "selection: kmalloc() failed\n");
353 clear_selection();
354@@ -251,8 +279,12 @@
355
356 obp = bp;
357 for (i = sel_start; i <= sel_end; i += 2) {
358- *bp = sel_pos(i);
359- if (!isspace(*bp++))
360+ c = sel_pos(i);
361+ if (use_unicode)
362+ bp += store_utf8(c, bp);
363+ else
364+ *bp++ = c;
365+ if (!isspace(c))
366 obp = bp;
367 if (! ((i + 2) % vc->vc_size_row)) {
368 /* strip trailing blanks from line and add newline,
369diff -ur linux-2.6.15-rc6.orig/include/linux/consolemap.h linux-2.6.15-rc6.my/include/linux/consolemap.h
370--- linux-2.6.15-rc6.orig/include/linux/consolemap.h 2005-12-25 10:00:13.000000000 +0500
371+++ linux-2.6.15-rc6.my/include/linux/consolemap.h 2005-12-25 10:01:22.000000000 +0500
372@@ -10,6 +10,7 @@
373
374 struct vc_data;
375
376-extern unsigned char inverse_translate(struct vc_data *conp, int glyph);
377+extern u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode);
378 extern unsigned short *set_translate(int m, struct vc_data *vc);
379 extern int conv_uni_to_pc(struct vc_data *conp, long ucs);
380+extern u32 conv_8bit_to_uni(unsigned char c);