[PATCH] bug fix & improvvement for console

Stanislav V. Voronyi (stas@cnti.uanet.kharkov.ua)
Wed, 16 Dec 1998 14:28:39 +0200


This is patch for console which consist from two logical
part: one for selection and another for keyboard. To my mind this patch
must be usefull for people who widely use non-ASCII chars (cyrillic,
greek, hebrew, etc).

Patch for selection fix bug in inverse_translate which
broke selection of 8-bit chars if I use different console mapping
on multiconsole (f.e. ISO Latin 1 for one ('\033(B') & User Map on another
('\033(K'). Also I add possibilities to cut/paste in UTF mode.
With this patch I can freely cut on normal console and paste
to UTF one (if keyboard in VC_UNICODE mode). Also possible
cut from normal, paste to normal;
........ UTF, ........... normal;
........ UTF, ........... UTF absolutely free.

Patch for keyboard.c intended to allow use only one
keyboard map for both XLATE & UNICODE(UTF-8) mode where all
non ASCII symbols described as an Unicode symbols. Translate
from Unicode to ASCII in XLATE mode use the same translation
tables as in selection & console. This way for translation
(Unicode->conv_uni_to_pc->inverse_translate->ASCII) make this
translation correct with any combination of used console
font/mapping tables without adding special translating table
for keyboard.

SY, Stanislav Voronyi.

------------------ Patch here -------------------------------

diff -u --recursive linux-2.1.131.d/drivers/char/console.c linux-2.1.131.n/drivers/char/console.c
--- linux-2.1.131.d/drivers/char/console.c Mon Dec 14 02:25:09 1998
+++ linux-2.1.131.n/drivers/char/console.c Wed Dec 16 02:17:52 1998
@@ -1029,7 +1029,7 @@
*/
translate = set_translate(charset == 0
? G0_charset
- : G1_charset);
+ : G1_charset,currcons);
disp_ctrl = 0;
toggle_meta = 0;
break;
@@ -1037,7 +1037,7 @@
* Select first alternate font, lets
* chars < 32 be displayed as ROM chars.
*/
- translate = set_translate(IBMPC_MAP);
+ translate = set_translate(IBMPC_MAP,currcons);
disp_ctrl = 1;
toggle_meta = 0;
break;
@@ -1045,7 +1045,7 @@
* Select second alternate font, toggle
* high bit before displaying as ROM char.
*/
- translate = set_translate(IBMPC_MAP);
+ translate = set_translate(IBMPC_MAP,currcons);
disp_ctrl = 1;
toggle_meta = 1;
break;
@@ -1328,7 +1328,7 @@
color = s_color;
G0_charset = saved_G0;
G1_charset = saved_G1;
- translate = set_translate(charset ? G1_charset : G0_charset);
+ translate = set_translate(charset ? G1_charset : G0_charset,currcons);
update_attr(currcons);
need_wrap = 0;
}
@@ -1343,7 +1343,7 @@
bottom = video_num_lines;
vc_state = ESnormal;
ques = 0;
- translate = set_translate(LAT1_MAP);
+ translate = set_translate(LAT1_MAP,currcons);
G0_charset = LAT1_MAP;
G1_charset = GRAF_MAP;
charset = 0;
@@ -1426,12 +1426,12 @@
return;
case 14:
charset = 1;
- translate = set_translate(G1_charset);
+ translate = set_translate(G1_charset,currcons);
disp_ctrl = 1;
return;
case 15:
charset = 0;
- translate = set_translate(G0_charset);
+ translate = set_translate(G0_charset,currcons);
disp_ctrl = 0;
return;
case 24: case 26:
@@ -1738,7 +1738,7 @@
else if (c == 'K')
G0_charset = USER_MAP;
if (charset == 0)
- translate = set_translate(G0_charset);
+ translate = set_translate(G0_charset,currcons);
vc_state = ESnormal;
return;
case ESsetG1:
@@ -1751,7 +1751,7 @@
else if (c == 'K')
G1_charset = USER_MAP;
if (charset == 1)
- translate = set_translate(G1_charset);
+ translate = set_translate(G1_charset,currcons);
vc_state = ESnormal;
return;
default:
diff -u --recursive linux-2.1.131.d/drivers/char/consolemap.c linux-2.1.131.n/drivers/char/consolemap.c
--- linux-2.1.131.d/drivers/char/consolemap.c Mon Dec 14 00:01:05 1998
+++ linux-2.1.131.n/drivers/char/consolemap.c Wed Dec 16 02:17:52 1998
@@ -7,6 +7,8 @@
* aeb, 950210
*
* Support for multiple unimaps by Jakub Jelinek <jj@ultra.linux.cz>, July 1998
+ *
+ * Fix bug in inverse translation. Stanislav Voronyi <stas@cnti.uanet.kharkov.ua>, Dec 1998
*/

#include <linux/kd.h>
@@ -167,7 +169,7 @@

#define MAX_GLYPH 512 /* Max possible glyph value */

-static int inv_translate;
+static int inv_translate[MAX_NR_CONSOLES];

struct uni_pagedir {
u16 **uni_pgdir[32];
@@ -204,9 +206,9 @@
}
}

-unsigned short *set_translate(int m)
+unsigned short *set_translate(int m,int currcons)
{
- inv_translate = m;
+ inv_translate[currcons] = m;
return translations[m];
}

@@ -220,14 +222,13 @@
unsigned char inverse_translate(struct vc_data *conp, int glyph)
{
struct uni_pagedir *p;
-
if (glyph < 0 || glyph >= MAX_GLYPH)
return 0;
else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) ||
- !p->inverse_translations[inv_translate])
+ !p->inverse_translations[inv_translate[conp->vc_num]])
return glyph;
else
- return p->inverse_translations[inv_translate][glyph];
+ return p->inverse_translations[inv_translate[conp->vc_num]][glyph];
}

static void update_user_maps(void)
diff -u --recursive linux-2.1.131.d/drivers/char/keyboard.c linux-2.1.131.n/drivers/char/keyboard.c
--- linux-2.1.131.d/drivers/char/keyboard.c Mon Dec 14 03:10:16 1998
+++ linux-2.1.131.n/drivers/char/keyboard.c Wed Dec 16 02:17:52 1998
@@ -21,6 +21,7 @@
*
* 27-05-97: Added support for the Magic SysRq Key (Martin Mares)
* 30-07-98: Dead keys redone, aeb@cwi.nl.
+ * 16-12-98: Add translation Unicode keysyms to ASCII when keyboard in XLATE mode, stas@cnti.uanet.kharkov.ua
*/

#include <linux/config.h>
@@ -41,6 +42,17 @@
#include <linux/kbd_ll.h>
#include <linux/sysrq.h>

+/*
+ * Four lines bellow added for support translation unicode
+ * symbols to ASCII through console unicode table when
+ * keyboard in XLATE mode, but in keymap U+xxxx symbols
+ * persent
+ */
+#include <linux/console_struct.h>
+extern int fg_console;
+extern struct vc vc_cons[];
+extern conv_uni_to_pc(struct vc_data *conp, long ucs);
+
#define SIZE(x) (sizeof(x)/sizeof((x)[0]))

#ifndef KBD_DEFMODE
@@ -301,7 +313,14 @@
} else {
/* maybe only if (kbd->kbdmode == VC_UNICODE) ? */
if (!up_flag && !raw_mode)
- to_utf8(keysym);
+ if (kbd->kbdmode == VC_UNICODE)
+ to_utf8(keysym);
+ else if (kbd->kbdmode == VC_XLATE) { /* translate unicode to ASCII */
+ int c = inverse_translate(vc_cons[fg_console].d,
+ conv_uni_to_pc(vc_cons[fg_console].d, keysym));
+ if (c > 0)
+ put_queue(c);
+ }
}
} else {
/* maybe beep? */
diff -u --recursive linux-2.1.131.d/drivers/char/selection.c linux-2.1.131.n/drivers/char/selection.c
--- linux-2.1.131.d/drivers/char/selection.c Sun Dec 13 23:23:27 1998
+++ linux-2.1.131.n/drivers/char/selection.c Wed Dec 16 02:17:52 1998
@@ -9,6 +9,8 @@
* 'int sel_loadlut(const unsigned long arg)'
*
* Now that /dev/vcs exists, most of this can disappear again.
+ *
+ * Add paste in UTF-8 if keyboard in UNICODE mode, Stanislav Voronyi <stas@cnti.uanet.kharkov.ua>, Dec 1998
*/

#include <linux/module.h>
@@ -23,6 +25,7 @@
#include <linux/vt_kern.h>
#include <linux/consolemap.h>
#include <linux/console_struct.h>
+#include <linux/kbd_kern.h>
#include <linux/selection.h>

#ifndef MIN
@@ -40,7 +43,7 @@
static volatile int sel_start = -1; /* cleared by clear_selection */
static int sel_end;
static int sel_buffer_lth = 0;
-static char *sel_buffer = NULL;
+static unsigned char * sel_buffer = NULL;

/* clear_selection, highlight and highlight_pointer can be called
from interrupt (via scrollback/front) */
@@ -119,7 +122,7 @@
int set_selection(const unsigned long arg, struct tty_struct *tty, int user)
{
int sel_mode, new_sel_start, new_sel_end, spc;
- char *bp, *obp;
+ unsigned char *bp, *obp;
int i, ps, pe;
unsigned int currcons = fg_console;

@@ -295,9 +298,45 @@
int paste_selection(struct tty_struct *tty)
{
struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
- int pasted = 0, count;
+ int pasted = 0, count, utf_mode = 0;
struct wait_queue wait = { current, NULL };
-
+ unsigned char *new_buffer = NULL;
+ int i, j, new_buffer_lth = 0;
+ ushort unicode;
+
+ if (kbd_table[vt->vc_num].kbdmode == VC_UNICODE){
+ for (i=0;i < sel_buffer_lth;i++)
+ if ((sel_buffer[i]&0x80) == 0)
+ new_buffer_lth++;
+ else if (vc_cons[vt->vc_num].d->vc_translate[sel_buffer[i]] < 0x800)
+ new_buffer_lth+=2;
+ else
+ new_buffer_lth+=3;
+ if( new_buffer_lth == sel_buffer_lth)
+ goto no_utf;
+ utf_mode = 1;
+ new_buffer = kmalloc(new_buffer_lth, GFP_KERNEL);
+ if (!new_buffer) {
+ printk(KERN_WARNING "selection: kmalloc() failed\n");
+ return -ENOMEM;
+ }
+ for (i=0,j=0;i < sel_buffer_lth;i++,j++) {
+ if ((sel_buffer[i]&0x80) == 0)
+ new_buffer[j]=sel_buffer[i];
+ else {
+ unicode = vc_cons[vt->vc_num].d->vc_translate[sel_buffer[i]];
+ if (unicode < 0x800) { /* 110XXXXX 10XXXXXX */
+ new_buffer[j++] = (0xc0 | (unicode >> 6));
+ new_buffer[j] = (0x80 | (unicode & 0x3f));
+ } else { /* 1110XXXX 10XXXXXX 10XXXXXX */
+ new_buffer[j++] = (0xe0 | (unicode >> 12));
+ new_buffer[j++] = (0x80 | ((unicode >> 6) & 0x3f));
+ new_buffer[j] = (0x80 | (unicode & 0x3f));
+ }
+ }
+ }
+ }
+no_utf:
poke_blanked_console();
add_wait_queue(&vt->paste_wait, &wait);
while (sel_buffer && sel_buffer_lth > pasted) {
@@ -306,11 +345,13 @@
schedule();
continue;
}
- count = sel_buffer_lth - pasted;
+ count = utf_mode?new_buffer_lth:sel_buffer_lth - pasted;
count = MIN(count, tty->ldisc.receive_room(tty));
- tty->ldisc.receive_buf(tty, sel_buffer + pasted, 0, count);
+ tty->ldisc.receive_buf(tty, utf_mode?new_buffer:sel_buffer + pasted, 0, count);
pasted += count;
}
+ if (new_buffer)
+ kfree(new_buffer);
remove_wait_queue(&vt->paste_wait, &wait);
current->state = TASK_RUNNING;
return 0;
diff -u --recursive linux-2.1.131.d/include/linux/consolemap.h linux-2.1.131.n/include/linux/consolemap.h
--- linux-2.1.131.d/include/linux/consolemap.h Mon Dec 14 03:02:40 1998
+++ linux-2.1.131.n/include/linux/consolemap.h Mon Dec 14 02:32:06 1998
@@ -11,5 +11,5 @@
struct vc_data;

extern unsigned char inverse_translate(struct vc_data *conp, int glyph);
-extern unsigned short *set_translate(int m);
+extern unsigned short *set_translate(int m,int currcons);
extern int conv_uni_to_pc(struct vc_data *conp, long ucs);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/