r1357 - in trunk: . linux

jim at linuxfromscratch.org jim at linuxfromscratch.org
Wed Jan 18 07:59:06 PST 2006


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:
 r1698 at server:  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);




More information about the patches mailing list