linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] Enlarge the storage of chars in virtual terminal
@ 2010-05-26  6:55 Frank Pan
  2010-05-26  6:59 ` [PATCH 1/2] " Frank Pan
  2010-05-26 14:11 ` [PATCH 0/2] " Alan Cox
  0 siblings, 2 replies; 13+ messages in thread
From: Frank Pan @ 2010-05-26  6:55 UTC (permalink / raw)
  To: Alan Cox, Gerardo Exequiel Pozzi, Kay Sievers, Andrew Morton,
	Greg Kroah-Hartman, Catalin Marinas, Daniel Mack, Tejun Heo,
	Christoph Lameter, Jiri Slaby, Jochen Hein, Johannes Weiner,
	Dave Airlie, Pekka Enberg, Geert Uytterhoeven
  Cc: LKML

Greetings

The motivation is display much more characters on the
framebuffer console than 512. If this is done, foreign
languages can be easily rendered with currently supported
utf-8 encoding.

In order to display fonts with more than 512 chars,
the storage of one char in virtual terminal must be
enlarged. Currently vt holds one u16 for every character,
7 bits for attributes. The patches extend it into u32.

Virtual terminal is referenced by many other drivers.
If it has been changed, others must be changed as well.
Change all of them may spend 1 or more weeks, and the
patches include the change of fbcon. So I just put the
done part here and wish to have your advices.

Any reply is appreciated, thank you.

Frank Pan

 drivers/char/selection.c        |   26 ++--
 drivers/char/vc_screen.c        |    8 +-
 drivers/char/vt.c               |  250 ++++++++++++++++++++------------------
 drivers/video/console/bitblit.c |   33 +++--
 drivers/video/console/fbcon.c   |  256 ++++++++++++++++++++-------------------
 drivers/video/console/fbcon.h   |   16 ++--
 include/linux/console.h         |    8 +-
 include/linux/console_struct.h  |    8 +-
 include/linux/selection.h       |    6 +-
 include/linux/vt_buffer.h       |   15 ++-
 10 files changed, 327 insertions(+), 299 deletions(-)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/2] Enlarge the storage of chars in virtual terminal
  2010-05-26  6:55 [PATCH 0/2] Enlarge the storage of chars in virtual terminal Frank Pan
@ 2010-05-26  6:59 ` Frank Pan
  2010-05-26  7:02   ` [PATCH 2/2] " Frank Pan
  2010-05-26 14:11 ` [PATCH 0/2] " Alan Cox
  1 sibling, 1 reply; 13+ messages in thread
From: Frank Pan @ 2010-05-26  6:59 UTC (permalink / raw)
  To: Alan Cox, Gerardo Exequiel Pozzi, Kay Sievers, Andrew Morton,
	Greg Kroah-Hartman, Catalin Marinas, Daniel Mack, Tejun Heo,
	Christoph Lameter, Jiri Slaby, Jochen Hein, Johannes Weiner,
	Dave Airlie, Pekka Enberg, Geert Uytterhoeven
  Cc: LKML

Enlarge the storage of char in virtual terminal.

Signed-off-by: Frank Pan <frankpzh@gmail.com>
---
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index f97b9e8..200a790 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -158,8 +158,8 @@ int set_selection(const struct tiocl_selection
__user *sel, struct tty_struct *t
 	  ys = limit(ys, vc->vc_rows - 1);
 	  xe = limit(xe, vc->vc_cols - 1);
 	  ye = limit(ye, vc->vc_rows - 1);
-	  ps = ys * vc->vc_size_row + (xs << 1);
-	  pe = ye * vc->vc_size_row + (xe << 1);
+	  ps = ys * vc->vc_size_row + (xs << 2);
+	  pe = ye * vc->vc_size_row + (xe << 2);

 	  if (sel_mode == TIOCL_SELCLEAR) {
 	      /* useful for screendump without selection highlights */
@@ -194,7 +194,7 @@ int set_selection(const struct tiocl_selection
__user *sel, struct tty_struct *t
 			break;
 		case TIOCL_SELWORD:	/* word-by-word selection */
 			spc = isspace(sel_pos(ps));
-			for (new_sel_start = ps; ; ps -= 2)
+			for (new_sel_start = ps; ; ps -= 4)
 			{
 				if ((spc && !isspace(sel_pos(ps))) ||
 				    (!spc && !inword(sel_pos(ps))))
@@ -204,20 +204,20 @@ int set_selection(const struct tiocl_selection
__user *sel, struct tty_struct *t
 					break;
 			}
 			spc = isspace(sel_pos(pe));
-			for (new_sel_end = pe; ; pe += 2)
+			for (new_sel_end = pe; ; pe += 4)
 			{
 				if ((spc && !isspace(sel_pos(pe))) ||
 				    (!spc && !inword(sel_pos(pe))))
 					break;
 				new_sel_end = pe;
-				if (!((pe + 2) % vc->vc_size_row))
+				if (!((pe + 4) % vc->vc_size_row))
 					break;
 			}
 			break;
 		case TIOCL_SELLINE:	/* line-by-line selection */
 			new_sel_start = ps - ps % vc->vc_size_row;
 			new_sel_end = pe + vc->vc_size_row
-				    - pe % vc->vc_size_row - 2;
+				    - pe % vc->vc_size_row - 4;
 			break;
 		case TIOCL_SELPOINTER:
 			highlight_pointer(pe);
@@ -233,7 +233,7 @@ int set_selection(const struct tiocl_selection
__user *sel, struct tty_struct *t
 	if (new_sel_end > new_sel_start &&
 		!atedge(new_sel_end, vc->vc_size_row) &&
 		isspace(sel_pos(new_sel_end))) {
-		for (pe = new_sel_end + 2; ; pe += 2)
+		for (pe = new_sel_end + 4; ; pe += 4)
 			if (!isspace(sel_pos(pe)) ||
 			    atedge(pe, vc->vc_size_row))
 				break;
@@ -247,16 +247,16 @@ int set_selection(const struct tiocl_selection
__user *sel, struct tty_struct *t
 		if (new_sel_end == sel_end)	/* no action required */
 			return 0;
 		else if (new_sel_end > sel_end)	/* extend to right */
-			highlight(sel_end + 2, new_sel_end);
+			highlight(sel_end + 4, new_sel_end);
 		else				/* contract from right */
-			highlight(new_sel_end + 2, sel_end);
+			highlight(new_sel_end + 4, sel_end);
 	}
 	else if (new_sel_end == sel_end)
 	{
 		if (new_sel_start < sel_start)	/* extend to left */
-			highlight(new_sel_start, sel_start - 2);
+			highlight(new_sel_start, sel_start - 4);
 		else				/* contract from left */
-			highlight(sel_start, new_sel_start - 2);
+			highlight(sel_start, new_sel_start - 4);
 	}
 	else	/* some other case; start selection from scratch */
 	{
@@ -278,7 +278,7 @@ int set_selection(const struct tiocl_selection
__user *sel, struct tty_struct *t
 	sel_buffer = bp;

 	obp = bp;
-	for (i = sel_start; i <= sel_end; i += 2) {
+	for (i = sel_start; i <= sel_end; i += 4) {
 		c = sel_pos(i);
 		if (use_unicode)
 			bp += store_utf8(c, bp);
@@ -286,7 +286,7 @@ int set_selection(const struct tiocl_selection
__user *sel, struct tty_struct *t
 			*bp++ = c;
 		if (!isspace(c))
 			obp = bp;
-		if (! ((i + 2) % vc->vc_size_row)) {
+		if (! ((i + 4) % vc->vc_size_row)) {
 			/* strip trailing blanks from line and add newline,
 			   unless non-space at end of line. */
 			if (obp != bp) {
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index c1791a6..b4018b4 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -105,7 +105,7 @@ vcs_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
 	long pos;
 	long viewed, attr, read;
 	int col, maxcol;
-	unsigned short *org = NULL;
+	u32 *org = NULL;
 	ssize_t ret;

 	mutex_lock(&con_buf_mtx);
@@ -279,7 +279,7 @@ vcs_write(struct file *file, const char __user
*buf, size_t count, loff_t *ppos)
 	long viewed, attr, size, written;
 	char *con_buf0;
 	int col, maxcol;
-	u16 *org0 = NULL, *org = NULL;
+	u32 *org0 = NULL, *org = NULL;
 	size_t ret;

 	mutex_lock(&con_buf_mtx);
@@ -369,7 +369,7 @@ vcs_write(struct file *file, const char __user
*buf, size_t count, loff_t *ppos)

 				this_round--;
 				vcs_scr_writew(vc,
-					       (vcs_scr_readw(vc, org) & 0xff00) | c, org);
+					       (vcs_scr_readw(vc, org) & VT_BUF_ATTR_MASK) | c, org);
 				org++;
 				if (++col == maxcol) {
 					org = screen_pos(vc, p, viewed);
@@ -400,7 +400,7 @@ vcs_write(struct file *file, const char __user
*buf, size_t count, loff_t *ppos)
 					c = *con_buf0++;
 #ifdef __BIG_ENDIAN
 					vcs_scr_writew(vc, c |
-					     (vcs_scr_readw(vc, org) & 0xff00), org);
+					     (vcs_scr_readw(vc, org) & VT_BUF_ATTR_MASK), org);
 #else
 					vcs_scr_writew(vc, (c << 8) |
 					     (vcs_scr_readw(vc, org) & 0xff), org);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index bd1d116..2c5ebd4 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -267,14 +267,14 @@ static void notify_update(struct vc_data *vc)
 #define DO_UPDATE(vc)	(CON_IS_VISIBLE(vc) && !console_blanked)
 #endif

-static inline unsigned short *screenpos(struct vc_data *vc, int
offset, int viewed)
+static inline u32 *screenpos(struct vc_data *vc, int offset, int viewed)
 {
-	unsigned short *p;
+	u32 *p;
 	
 	if (!viewed)
-		p = (unsigned short *)(vc->vc_origin + offset);
+		p = (u32 *)(vc->vc_origin + offset);
 	else if (!vc->vc_sw->con_screen_pos)
-		p = (unsigned short *)(vc->vc_visible_origin + offset);
+		p = (u32 *)(vc->vc_visible_origin + offset);
 	else
 		p = vc->vc_sw->con_screen_pos(vc, offset);
 	return p;
@@ -293,7 +293,7 @@ void schedule_console_callback(void)

 static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
 {
-	unsigned short *d, *s;
+	u32 *d, *s;

 	if (t+nr >= b)
 		nr = b - t - 1;
@@ -301,8 +301,8 @@ static void scrup(struct vc_data *vc, unsigned int
t, unsigned int b, int nr)
 		return;
 	if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_UP, nr))
 		return;
-	d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
-	s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr));
+	d = (u32 *)(vc->vc_origin + vc->vc_size_row * t);
+	s = (u32 *)(vc->vc_origin + vc->vc_size_row * (t + nr));
 	scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row);
 	scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_video_erase_char,
 		    vc->vc_size_row * nr);
@@ -310,7 +310,7 @@ static void scrup(struct vc_data *vc, unsigned int
t, unsigned int b, int nr)

 static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
 {
-	unsigned short *s;
+	u32 *s;
 	unsigned int step;

 	if (t+nr >= b)
@@ -319,21 +319,21 @@ static void scrdown(struct vc_data *vc, unsigned
int t, unsigned int b, int nr)
 		return;
 	if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_DOWN, nr))
 		return;
-	s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
+	s = (u32 *)(vc->vc_origin + vc->vc_size_row * t);
 	step = vc->vc_cols * nr;
 	scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row);
-	scr_memsetw(s, vc->vc_video_erase_char, 2 * step);
+	scr_memsetw(s, vc->vc_video_erase_char, 4 * step);
 }

 static void do_update_region(struct vc_data *vc, unsigned long start,
int count)
 {
 #ifndef VT_BUF_VRAM_ONLY
 	unsigned int xx, yy, offset;
-	u16 *p;
+	u32 *p;

-	p = (u16 *) start;
+	p = (u32 *) start;
 	if (!vc->vc_sw->con_getxy) {
-		offset = (start - vc->vc_origin) / 2;
+		offset = (start - vc->vc_origin) / 4;
 		xx = offset % vc->vc_cols;
 		yy = offset / vc->vc_cols;
 	} else {
@@ -342,16 +342,16 @@ static void do_update_region(struct vc_data *vc,
unsigned long start, int count)
 		xx = nxx; yy = nyy;
 	}
 	for(;;) {
-		u16 attrib = scr_readw(p) & 0xff00;
+		u32 attrib = scr_readw(p) & VT_BUF_ATTR_MASK;
 		int startx = xx;
-		u16 *q = p;
+		u32 *q = p;
 		while (xx < vc->vc_cols && count) {
-			if (attrib != (scr_readw(p) & 0xff00)) {
+			if (attrib != (scr_readw(p) & VT_BUF_ATTR_MASK)) {
 				if (p > q)
 					vc->vc_sw->con_putcs(vc, q, p-q, yy, startx);
 				startx = xx;
 				q = p;
-				attrib = scr_readw(p) & 0xff00;
+				attrib = scr_readw(p) & VT_BUF_ATTR_MASK;
 			}
 			p++;
 			xx++;
@@ -364,7 +364,7 @@ static void do_update_region(struct vc_data *vc,
unsigned long start, int count)
 		xx = 0;
 		yy++;
 		if (vc->vc_sw->con_getxy) {
-			p = (u16 *)start;
+			p = (u32 *)start;
 			start = vc->vc_sw->con_getxy(vc, start, NULL, NULL);
 		}
 	}
@@ -411,7 +411,7 @@ static u8 build_attr(struct vc_data *vc, u8
_color, u8 _intensity, u8 _blink,
 		       (_reverse ? 8 : 0) |
 		       (_blink ? 0x80 : 0);
 	if (_italic)
-		a = (a & 0xF0) | vc->vc_itcolor;
+		a = (a & 0xf0) | vc->vc_itcolor;
 	else if (_underline)
 		a = (a & 0xf0) | vc->vc_ulcolor;
 	else if (_intensity == 0)
@@ -436,44 +436,51 @@ static void update_attr(struct vc_data *vc)
 	vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity,
 	              vc->vc_blink, vc->vc_underline,
 	              vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic);
-	vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1,
vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' ';
+	vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1,
+	              vc->vc_blink, 0, vc->vc_decscnm, 0) << VT_BUF_ATTR_SHIFT) | ' ';
 }

 /* Note: inverting the screen twice should revert to the original state */
 void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
 {
-	unsigned short *p;
+	u32 *p;

 	WARN_CONSOLE_UNLOCKED();

-	count /= 2;
+	count /= 4;
 	p = screenpos(vc, offset, viewed);
 	if (vc->vc_sw->con_invert_region)
 		vc->vc_sw->con_invert_region(vc, p, count);
 #ifndef VT_BUF_VRAM_ONLY
 	else {
-		u16 *q = p;
+		u32 *q = p;
 		int cnt = count;
-		u16 a;
+		u32 a;

 		if (!vc->vc_can_do_color) {
 			while (cnt--) {
 			    a = scr_readw(q);
-			    a ^= 0x0800;
+			    a ^= 0x08 << VT_BUF_ATTR_SHIFT;
 			    scr_writew(a, q);
 			    q++;
 			}
 		} else if (vc->vc_hi_font_mask == 0x100) {
 			while (cnt--) {
 				a = scr_readw(q);
-				a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4);
+				a = (a & ~VT_BUF_ATTR_MASK) |
+				  (a & (0x10 << VT_BUF_ATTR_SHIFT)) |
+				  ((a & (0xe0 << VT_BUF_ATTR_SHIFT)) >> 4) |
+				  ((a & (0x0e << VT_BUF_ATTR_SHIFT)) << 4);
 				scr_writew(a, q);
 				q++;
 			}
 		} else {
 			while (cnt--) {
 				a = scr_readw(q);
-				a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
+				a = (a & ~VT_BUF_ATTR_MASK) |
+				  (a & (0x88 << VT_BUF_ATTR_SHIFT)) |
+				  ((a & (0x70 << VT_BUF_ATTR_SHIFT)) >> 4) |
+				  ((a & (0x07 << VT_BUF_ATTR_SHIFT)) << 4);
 				scr_writew(a, q);
 				q++;
 			}
@@ -488,7 +495,7 @@ void invert_screen(struct vc_data *vc, int offset,
int count, int viewed)
 void complement_pos(struct vc_data *vc, int offset)
 {
 	static int old_offset = -1;
-	static unsigned short old;
+	static u32 old;
 	static unsigned short oldx, oldy;

 	WARN_CONSOLE_UNLOCKED();
@@ -504,15 +511,15 @@ void complement_pos(struct vc_data *vc, int offset)

 	if (offset != -1 && offset >= 0 &&
 	    offset < vc->vc_screenbuf_size) {
-		unsigned short new;
-		unsigned short *p;
+		u32 new;
+		u32 *p;
 		p = screenpos(vc, offset, 1);
 		old = scr_readw(p);
 		new = old ^ vc->vc_complement_mask;
 		scr_writew(new, p);
 		if (DO_UPDATE(vc)) {
-			oldx = (offset >> 1) % vc->vc_cols;
-			oldy = (offset >> 1) / vc->vc_cols;
+			oldx = (offset >> 2) % vc->vc_cols;
+			oldy = (offset >> 2) / vc->vc_cols;
 			vc->vc_sw->con_putc(vc, new, oldy, oldx);
 		}
 	}
@@ -521,18 +528,18 @@ void complement_pos(struct vc_data *vc, int offset)

 static void insert_char(struct vc_data *vc, unsigned int nr)
 {
-	unsigned short *p, *q = (unsigned short *)vc->vc_pos;
+	u32 *p, *q = (u32 *)vc->vc_pos;

 	p = q + vc->vc_cols - nr - vc->vc_x;
 	while (--p >= q)
 		scr_writew(scr_readw(p), p + nr);
-	scr_memsetw(q, vc->vc_video_erase_char, nr * 2);
+	scr_memsetw(q, vc->vc_video_erase_char, nr * 4);
 	vc->vc_need_wrap = 0;
 	if (DO_UPDATE(vc)) {
-		unsigned short oldattr = vc->vc_attr;
+		u8 oldattr = vc->vc_attr;
 		vc->vc_sw->con_bmove(vc, vc->vc_y, vc->vc_x, vc->vc_y, vc->vc_x + nr, 1,
 				     vc->vc_cols - vc->vc_x - nr);
-		vc->vc_attr = vc->vc_video_erase_char >> 8;
+		vc->vc_attr = vc->vc_video_erase_char >> VT_BUF_ATTR_SHIFT;
 		while (nr--)
 			vc->vc_sw->con_putc(vc, vc->vc_video_erase_char, vc->vc_y, vc->vc_x + nr);
 		vc->vc_attr = oldattr;
@@ -542,19 +549,19 @@ static void insert_char(struct vc_data *vc,
unsigned int nr)
 static void delete_char(struct vc_data *vc, unsigned int nr)
 {
 	unsigned int i = vc->vc_x;
-	unsigned short *p = (unsigned short *)vc->vc_pos;
+	u32 *p = (u32 *)vc->vc_pos;

 	while (++i <= vc->vc_cols - nr) {
-		scr_writew(scr_readw(p+nr), p);
+		scr_writew(scr_readw(p + nr), p);
 		p++;
 	}
-	scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
+	scr_memsetw(p, vc->vc_video_erase_char, nr * 4);
 	vc->vc_need_wrap = 0;
 	if (DO_UPDATE(vc)) {
-		unsigned short oldattr = vc->vc_attr;
+		u8 oldattr = vc->vc_attr;
 		vc->vc_sw->con_bmove(vc, vc->vc_y, vc->vc_x + nr, vc->vc_y, vc->vc_x, 1,
 				     vc->vc_cols - vc->vc_x - nr);
-		vc->vc_attr = vc->vc_video_erase_char >> 8;
+		vc->vc_attr = vc->vc_video_erase_char >> VT_BUF_ATTR_SHIFT;
 		while (nr--)
 			vc->vc_sw->con_putc(vc, vc->vc_video_erase_char, vc->vc_y,
 				     vc->vc_cols - 1 - nr);
@@ -562,21 +569,29 @@ static void delete_char(struct vc_data *vc,
unsigned int nr)
 	}
 }

-static int softcursor_original;
+static u32 softcursor_original;

 static void add_softcursor(struct vc_data *vc)
 {
-	int i = scr_readw((u16 *) vc->vc_pos);
+	u32 i = scr_readw((u32 *) vc->vc_pos);
 	u32 type = vc->vc_cursor_type;

-	if (! (type & 0x10)) return;
-	if (softcursor_original != -1) return;
+	if (! (type & 0x10))
+		return;
+	if (softcursor_original != -1)
+		return;
 	softcursor_original = i;
-	i |= ((type >> 8) & 0xff00 );
-	i ^= ((type) & 0xff00 );
-	if ((type & 0x20) && ((softcursor_original & 0x7000) == (i &
0x7000))) i ^= 0x7000;
-	if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700;
-	scr_writew(i, (u16 *) vc->vc_pos);
+	i |= (((type >> 16) & 0xff) << VT_BUF_ATTR_SHIFT);
+	i ^= (((type >> 8) & 0xff) << VT_BUF_ATTR_SHIFT);
+	if ((type & 0x20) &&
+	    ((softcursor_original & (0x70 << VT_BUF_ATTR_SHIFT)) ==
+	     (i & (0x70 << VT_BUF_ATTR_SHIFT))))
+		i ^= 0x70 << VT_BUF_ATTR_SHIFT;
+	if ((type & 0x40) &&
+	    ((i & (0x07 << VT_BUF_ATTR_SHIFT)) ==
+	     ((i & (0x70 << VT_BUF_ATTR_SHIFT)) >> 4)))
+		i ^= 0x07 << VT_BUF_ATTR_SHIFT;
+	scr_writew(i, (u32 *) vc->vc_pos);
 	if (DO_UPDATE(vc))
 		vc->vc_sw->con_putc(vc, i, vc->vc_y, vc->vc_x);
 }
@@ -584,7 +599,7 @@ static void add_softcursor(struct vc_data *vc)
 static void hide_softcursor(struct vc_data *vc)
 {
 	if (softcursor_original != -1) {
-		scr_writew(softcursor_original, (u16 *)vc->vc_pos);
+		scr_writew(softcursor_original, (u32 *)vc->vc_pos);
 		if (DO_UPDATE(vc))
 			vc->vc_sw->con_putc(vc, softcursor_original,
 					vc->vc_y, vc->vc_x);
@@ -625,7 +640,7 @@ static void set_origin(struct vc_data *vc)
 		vc->vc_origin = (unsigned long)vc->vc_screenbuf;
 	vc->vc_visible_origin = vc->vc_origin;
 	vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
-	vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x;
+	vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 4 * vc->vc_x;
 }

 static inline void save_screen(struct vc_data *vc)
@@ -642,12 +657,12 @@ static inline void save_screen(struct vc_data *vc)

 static void clear_buffer_attributes(struct vc_data *vc)
 {
-	unsigned short *p = (unsigned short *)vc->vc_origin;
-	int count = vc->vc_screenbuf_size / 2;
-	int mask = vc->vc_hi_font_mask | 0xff;
+	u32 *p = (u32 *)vc->vc_origin;
+	int count = vc->vc_screenbuf_size / 4;
+	u32 mask = ~VT_BUF_ATTR_MASK;

 	for (; count > 0; count--, p++) {
-		scr_writew((scr_readw(p)&mask) | (vc->vc_video_erase_char & ~mask), p);
+		scr_writew((scr_readw(p) & mask) | (vc->vc_video_erase_char & ~mask), p);
 	}
 }

@@ -699,7 +714,7 @@ void redraw_screen(struct vc_data *vc, int is_switch)
 			clear_buffer_attributes(vc);
 		}
 		if (update && vc->vc_mode != KD_GRAPHICS)
-			do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
+			do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 4);
 	}
 	set_cursor(vc);
 	if (is_switch) {
@@ -738,9 +753,9 @@ static void visual_init(struct vc_data *vc, int
num, int init)
 	vc->vc_can_do_color = 0;
 	vc->vc_sw->con_init(vc, init);
 	if (!vc->vc_complement_mask)
-		vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
+		vc->vc_complement_mask = (vc->vc_can_do_color ?	0x77 : 0x08) <<
VT_BUF_ATTR_SHIFT;
 	vc->vc_s_complement_mask = vc->vc_complement_mask;
-	vc->vc_size_row = vc->vc_cols << 1;
+	vc->vc_size_row = vc->vc_cols << 2;
 	vc->vc_screenbuf_size = vc->vc_rows * vc->vc_size_row;
 }

@@ -834,7 +849,7 @@ static int vc_do_resize(struct tty_struct *tty,
struct vc_data *vc,
 	unsigned int old_cols, old_rows, old_row_size, old_screen_size;
 	unsigned int new_cols, new_rows, new_row_size, new_screen_size;
 	unsigned int end, user;
-	unsigned short *newscreen;
+	u32 *newscreen;

 	WARN_CONSOLE_UNLOCKED();

@@ -849,7 +864,7 @@ static int vc_do_resize(struct tty_struct *tty,
struct vc_data *vc,

 	new_cols = (cols ? cols : vc->vc_cols);
 	new_rows = (lines ? lines : vc->vc_rows);
-	new_row_size = new_cols << 1;
+	new_row_size = new_cols << 2;
 	new_screen_size = new_row_size * new_rows;

 	if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
@@ -894,7 +909,7 @@ static int vc_do_resize(struct tty_struct *tty,
struct vc_data *vc,
 			 * Cursor is in no man's land, copy 1/2 screenful
 			 * from the top and bottom of cursor position
 			 */
-			old_origin += (vc->vc_y - new_rows/2) * old_row_size;
+			old_origin += (vc->vc_y - new_rows / 2) * old_row_size;
 			end = old_origin + (old_row_size * new_rows);
 		}
 	} else
@@ -908,8 +923,8 @@ static int vc_do_resize(struct tty_struct *tty,
struct vc_data *vc,
 	update_attr(vc);

 	while (old_origin < end) {
-		scr_memcpyw((unsigned short *) new_origin,
-			    (unsigned short *) old_origin, rlth);
+		scr_memcpyw((u32 *) new_origin,
+			    (u32 *) old_origin, rlth);
 		if (rrem)
 			scr_memsetw((void *)(new_origin + rlth),
 				    vc->vc_video_erase_char, rrem);
@@ -917,7 +932,7 @@ static int vc_do_resize(struct tty_struct *tty,
struct vc_data *vc,
 		new_origin += new_row_size;
 	}
 	if (new_scr_end > new_origin)
-		scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
+		scr_memsetw((u32 *)new_origin, vc->vc_video_erase_char,
 			    new_scr_end - new_origin);
 	kfree(vc->vc_screenbuf);
 	vc->vc_screenbuf = newscreen;
@@ -1072,7 +1087,7 @@ static void gotoxy(struct vc_data *vc, int
new_x, int new_y)
 		vc->vc_y = max_y - 1;
 	else
 		vc->vc_y = new_y;
-	vc->vc_pos = vc->vc_origin + vc->vc_y * vc->vc_size_row + (vc->vc_x<<1);
+	vc->vc_pos = vc->vc_origin + vc->vc_y * vc->vc_size_row + (vc->vc_x << 2);
 	vc->vc_need_wrap = 0;
 }

@@ -1127,7 +1142,7 @@ static void ri(struct vc_data *vc)

 static inline void cr(struct vc_data *vc)
 {
-	vc->vc_pos -= vc->vc_x << 1;
+	vc->vc_pos -= vc->vc_x << 2;
 	vc->vc_need_wrap = vc->vc_x = 0;
 	notify_write(vc, '\r');
 }
@@ -1135,7 +1150,7 @@ static inline void cr(struct vc_data *vc)
 static inline void bs(struct vc_data *vc)
 {
 	if (vc->vc_x) {
-		vc->vc_pos -= 2;
+		vc->vc_pos -= 4;
 		vc->vc_x--;
 		vc->vc_need_wrap = 0;
 		notify_write(vc, '\b');
@@ -1150,12 +1165,12 @@ static inline void del(struct vc_data *vc)
 static void csi_J(struct vc_data *vc, int vpar)
 {
 	unsigned int count;
-	unsigned short * start;
+	u32 *start;

 	switch (vpar) {
 		case 0:	/* erase from cursor to end of display */
-			count = (vc->vc_scr_end - vc->vc_pos) >> 1;
-			start = (unsigned short *)vc->vc_pos;
+			count = (vc->vc_scr_end - vc->vc_pos) >> 2;
+			start = (u32 *)vc->vc_pos;
 			if (DO_UPDATE(vc)) {
 				/* do in two stages */
 				vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1,
@@ -1166,8 +1181,8 @@ static void csi_J(struct vc_data *vc, int vpar)
 			}
 			break;
 		case 1:	/* erase from start to cursor */
-			count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1;
-			start = (unsigned short *)vc->vc_origin;
+			count = ((vc->vc_pos - vc->vc_origin) >> 2) + 1;
+			start = (u32 *)vc->vc_origin;
 			if (DO_UPDATE(vc)) {
 				/* do in two stages */
 				vc->vc_sw->con_clear(vc, 0, 0, vc->vc_y,
@@ -1178,7 +1193,7 @@ static void csi_J(struct vc_data *vc, int vpar)
 			break;
 		case 2: /* erase whole display */
 			count = vc->vc_cols * vc->vc_rows;
-			start = (unsigned short *)vc->vc_origin;
+			start = (u32 *)vc->vc_origin;
 			if (DO_UPDATE(vc))
 				vc->vc_sw->con_clear(vc, 0, 0,
 					      vc->vc_rows,
@@ -1187,32 +1202,32 @@ static void csi_J(struct vc_data *vc, int vpar)
 		default:
 			return;
 	}
-	scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
+	scr_memsetw(start, vc->vc_video_erase_char, 4 * count);
 	vc->vc_need_wrap = 0;
 }

 static void csi_K(struct vc_data *vc, int vpar)
 {
 	unsigned int count;
-	unsigned short * start;
+	u32 *start;

 	switch (vpar) {
 		case 0:	/* erase from cursor to end of line */
 			count = vc->vc_cols - vc->vc_x;
-			start = (unsigned short *)vc->vc_pos;
+			start = (u32 *)vc->vc_pos;
 			if (DO_UPDATE(vc))
 				vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1,
 						     vc->vc_cols - vc->vc_x);
 			break;
 		case 1:	/* erase from start of line to cursor */
-			start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1));
+			start = (u32 *)(vc->vc_pos - (vc->vc_x << 2));
 			count = vc->vc_x + 1;
 			if (DO_UPDATE(vc))
 				vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
 						     vc->vc_x + 1);
 			break;
 		case 2: /* erase whole line */
-			start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1));
+			start = (u32 *)(vc->vc_pos - (vc->vc_x << 2));
 			count = vc->vc_cols;
 			if (DO_UPDATE(vc))
 				vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
@@ -1221,7 +1236,7 @@ static void csi_K(struct vc_data *vc, int vpar)
 		default:
 			return;
 	}
-	scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
+	scr_memsetw(start, vc->vc_video_erase_char, 4 * count);
 	vc->vc_need_wrap = 0;
 }

@@ -1233,7 +1248,7 @@ static void csi_X(struct vc_data *vc, int vpar)
/* erase the following vpar posi
 		vpar++;
 	count = (vpar > vc->vc_cols - vc->vc_x) ? (vc->vc_cols - vc->vc_x) : vpar;

-	scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count);
+	scr_memsetw((u32 *)vc->vc_pos, vc->vc_video_erase_char, 4 * count);
 	if (DO_UPDATE(vc))
 		vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1, count);
 	vc->vc_need_wrap = 0;
@@ -1681,13 +1696,13 @@ static void do_con_trol(struct tty_struct
*tty, struct vc_data *vc, int c)
 		bs(vc);
 		return;
 	case 9:
-		vc->vc_pos -= (vc->vc_x << 1);
+		vc->vc_pos -= (vc->vc_x << 2);
 		while (vc->vc_x < vc->vc_cols - 1) {
 			vc->vc_x++;
 			if (vc->vc_tab_stop[vc->vc_x >> 5] & (1 << (vc->vc_x & 31)))
 				break;
 		}
-		vc->vc_pos += (vc->vc_x << 1);
+		vc->vc_pos += (vc->vc_x << 2);
 		notify_write(vc, '\t');
 		return;
 	case 10: case 11: case 12:
@@ -2008,11 +2023,11 @@ static void do_con_trol(struct tty_struct
*tty, struct vc_data *vc, int c)
 		if (c == '8') {
 			/* DEC screen alignment test. kludge :-) */
 			vc->vc_video_erase_char =
-				(vc->vc_video_erase_char & 0xff00) | 'E';
+				(vc->vc_video_erase_char & VT_BUF_ATTR_MASK) | 'E';
 			csi_J(vc, 2);
 			vc->vc_video_erase_char =
-				(vc->vc_video_erase_char & 0xff00) | ' ';
-			do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
+				(vc->vc_video_erase_char & VT_BUF_ATTR_MASK) | ' ';
+			do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 4);
 		}
 		return;
 	case ESsetG0:
@@ -2104,7 +2119,7 @@ static int do_con_write(struct tty_struct *tty,
const unsigned char *buf, int co
 #define FLUSH do { } while(0);
 #else
 #define FLUSH if (draw_x >= 0) { \
-	vc->vc_sw->con_putcs(vc, (u16 *)draw_from, (u16 *)draw_to - (u16
*)draw_from, vc->vc_y, draw_x); \
+	vc->vc_sw->con_putcs(vc, (u32 *)draw_from, (u32 *)draw_to - (u32
*)draw_from, vc->vc_y, draw_x); \
 	draw_x = -1; \
 	}
 #endif
@@ -2118,7 +2133,8 @@ static int do_con_write(struct tty_struct *tty,
const unsigned char *buf, int co
 	uint8_t rescan;
 	uint8_t inverse;
 	uint8_t width;
-	u16 himask, charmask;
+	u32 charmask = ~VT_BUF_ATTR_MASK;
+	uint8_t char_found;

 	if (in_interrupt())
 		return count;
@@ -2141,9 +2157,6 @@ static int do_con_write(struct tty_struct *tty,
const unsigned char *buf, int co
 	    return 0;
 	}

-	himask = vc->vc_hi_font_mask;
-	charmask = himask ? 0x1ff : 0xff;
-
 	/* undraw cursor first */
 	if (IS_FG(vc))
 		hide_cursor(vc);
@@ -2267,6 +2280,7 @@ rescan_last_byte:
 			/* Now try to find out how to display it */
 			tc = conv_uni_to_pc(vc, tc);
 			if (tc & ~charmask) {
+				char_found = 0;
 				if (tc == -1 || tc == -2) {
 				    continue; /* nothing to display */
 				}
@@ -2288,6 +2302,9 @@ rescan_last_byte:
 				    }
 				}
 			}
+			else {
+				char_found = 1;
+			}

 			if (!inverse) {
 				vc_attr = vc->vc_attr;
@@ -2312,26 +2329,31 @@ rescan_last_byte:
 				}
 				if (vc->vc_decim)
 					insert_char(vc, 1);
-				scr_writew(himask ?
-					     ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) +
(tc & 0xff) :
-					     (vc_attr << 8) + tc,
-					   (u16 *) vc->vc_pos);
+				scr_writew((vc_attr << VT_BUF_ATTR_SHIFT) + tc,
+					   (u32 *) vc->vc_pos);
 				if (DO_UPDATE(vc) && draw_x < 0) {
 					draw_x = vc->vc_x;
 					draw_from = vc->vc_pos;
 				}
 				if (vc->vc_x == vc->vc_cols - 1) {
 					vc->vc_need_wrap = vc->vc_decawm;
-					draw_to = vc->vc_pos + 2;
+					draw_to = vc->vc_pos + 4;
 				} else {
 					vc->vc_x++;
-					draw_to = (vc->vc_pos += 2);
+					draw_to = (vc->vc_pos += 4);
 				}

 				if (!--width) break;

-				tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */
-				if (tc < 0) tc = ' ';
+				if (char_found) {
+					/* The 2nd half of wide char is right after the 1st */
+					tc++;
+				}
+				else {
+					/* A space is printed in the second column */
+					tc = conv_uni_to_pc(vc, ' ');
+					if (tc < 0) tc = ' ';
+				}
 			}
 			notify_write(vc, c);

@@ -2473,7 +2495,7 @@ static void vt_console_print(struct console *co,
const char *b, unsigned count)
 	struct vc_data *vc = vc_cons[fg_console].d;
 	unsigned char c;
 	static DEFINE_SPINLOCK(printing_lock);
-	const ushort *start;
+	const u32 *start;
 	ushort cnt = 0;
 	ushort myx;
 	int kmsg_console;
@@ -2505,7 +2527,7 @@ static void vt_console_print(struct console *co,
const char *b, unsigned count)
 	if (IS_FG(vc))
 		hide_cursor(vc);

-	start = (ushort *)vc->vc_pos;
+	start = (u32 *)vc->vc_pos;

 	/* Contrived structure to try to emulate original need_wrap behaviour
 	 * Problems caused when we have need_wrap set on '\n' character */
@@ -2522,26 +2544,26 @@ static void vt_console_print(struct console
*co, const char *b, unsigned count)
 			}
 			if (c == 8) {		/* backspace */
 				bs(vc);
-				start = (ushort *)vc->vc_pos;
+				start = (u32 *)vc->vc_pos;
 				myx = vc->vc_x;
 				continue;
 			}
 			if (c != 13)
 				lf(vc);
 			cr(vc);
-			start = (ushort *)vc->vc_pos;
+			start = (u32 *)vc->vc_pos;
 			myx = vc->vc_x;
 			if (c == 10 || c == 13)
 				continue;
 		}
-		scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);
+		scr_writew((vc->vc_attr << VT_BUF_ATTR_SHIFT) + c, (u32 *)vc->vc_pos);
 		notify_write(vc, c);
 		cnt++;
 		if (myx == vc->vc_cols - 1) {
 			vc->vc_need_wrap = 1;
 			continue;
 		}
-		vc->vc_pos += 2;
+		vc->vc_pos += 4;
 		myx++;
 	}
 	if (cnt > 0) {
@@ -2843,7 +2865,7 @@ static void vc_init(struct vc_data *vc, unsigned int rows,

 	vc->vc_cols = cols;
 	vc->vc_rows = rows;
-	vc->vc_size_row = cols << 1;
+	vc->vc_size_row = cols << 2;
 	vc->vc_screenbuf_size = vc->vc_rows * vc->vc_size_row;

 	set_origin(vc);
@@ -4057,19 +4079,15 @@ int con_font_op(struct vc_data *vc, struct
console_font_op *op)
 /* used by selection */
 u16 screen_glyph(struct vc_data *vc, int offset)
 {
-	u16 w = scr_readw(screenpos(vc, offset, 1));
-	u16 c = w & 0xff;
-
-	if (w & vc->vc_hi_font_mask)
-		c |= 0x100;
-	return c;
+	u32 w = scr_readw(screenpos(vc, offset, 1));
+	return w & ~VT_BUF_ATTR_MASK;
 }
 EXPORT_SYMBOL_GPL(screen_glyph);

 /* used by vcs - note the word offset */
-unsigned short *screen_pos(struct vc_data *vc, int w_offset, int viewed)
+u32 *screen_pos(struct vc_data *vc, int w_offset, int viewed)
 {
-	return screenpos(vc, 2 * w_offset, viewed);
+	return screenpos(vc, 4 * w_offset, viewed);
 }

 void getconsxy(struct vc_data *vc, unsigned char *p)
@@ -4085,14 +4103,14 @@ void putconsxy(struct vc_data *vc, unsigned char *p)
 	set_cursor(vc);
 }

-u16 vcs_scr_readw(struct vc_data *vc, const u16 *org)
+u32 vcs_scr_readw(struct vc_data *vc, const u32 *org)
 {
 	if ((unsigned long)org == vc->vc_pos && softcursor_original != -1)
 		return softcursor_original;
 	return scr_readw(org);
 }

-void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org)
+void vcs_scr_writew(struct vc_data *vc, u32 val, u32 *org)
 {
 	scr_writew(val, org);
 	if ((unsigned long)org == vc->vc_pos) {
diff --git a/include/linux/console.h b/include/linux/console.h
index dcca533..ff374f9 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -34,8 +34,8 @@ struct consw {
 	void	(*con_init)(struct vc_data *, int);
 	void	(*con_deinit)(struct vc_data *);
 	void	(*con_clear)(struct vc_data *, int, int, int, int);
-	void	(*con_putc)(struct vc_data *, int, int, int);
-	void	(*con_putcs)(struct vc_data *, const unsigned short *, int, int, int);
+	void	(*con_putc)(struct vc_data *, u32, int, int);
+	void	(*con_putcs)(struct vc_data *, const u32 *, int, int, int);
 	void	(*con_cursor)(struct vc_data *, int);
 	int	(*con_scroll)(struct vc_data *, int, int, int, int);
 	void	(*con_bmove)(struct vc_data *, int, int, int, int, int, int);
@@ -52,8 +52,8 @@ struct consw {
 	int	(*con_set_origin)(struct vc_data *);
 	void	(*con_save_screen)(struct vc_data *);
 	u8	(*con_build_attr)(struct vc_data *, u8, u8, u8, u8, u8, u8);
-	void	(*con_invert_region)(struct vc_data *, u16 *, int);
-	u16    *(*con_screen_pos)(struct vc_data *, int);
+	void	(*con_invert_region)(struct vc_data *, u32 *, int);
+	u32    *(*con_screen_pos)(struct vc_data *, int);
 	unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);
 };

diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index 38fe59d..767596d 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -31,7 +31,7 @@ struct vc_data {
 	unsigned long	vc_visible_origin;	/* [!] Top of visible window */
 	unsigned int	vc_top, vc_bottom;	/* Scrolling region */
 	const struct consw *vc_sw;
-	unsigned short	*vc_screenbuf;		/* In-memory character/attribute buffer */
+	unsigned int	*vc_screenbuf;		/* In-memory character/attribute buffer */
 	unsigned int	vc_screenbuf_size;
 	unsigned char	vc_mode;		/* KD_TEXT, ... */
 	/* attributes for all characters on screen */
@@ -44,15 +44,15 @@ struct vc_data {
 	unsigned char	vc_halfcolor;		/* Color for half intensity mode */
 	/* cursor */
 	unsigned int	vc_cursor_type;
-	unsigned short	vc_complement_mask;	/* [#] Xor mask for mouse pointer */
-	unsigned short	vc_s_complement_mask;	/* Saved mouse pointer mask */
+	unsigned int	vc_complement_mask;	/* [#] Xor mask for mouse pointer */
+	unsigned int	vc_s_complement_mask;	/* Saved mouse pointer mask */
 	unsigned int	vc_x, vc_y;		/* Cursor position */
 	unsigned int	vc_saved_x, vc_saved_y;
 	unsigned long	vc_pos;			/* Cursor address */
 	/* fonts */	
 	unsigned short	vc_hi_font_mask;	/* [#] Attribute set for upper 256
chars of font or 0 if not supported */
 	struct console_font vc_font;		/* Current VC font set */
-	unsigned short	vc_video_erase_char;	/* Background erase character */
+	unsigned int	vc_video_erase_char;	/* Background erase character */
 	/* VT terminal data */
 	unsigned int	vc_state;		/* Escape sequence parser state */
 	unsigned int	vc_npar,vc_par[NPAR];	/* Parameters of current escape sequence */
diff --git a/include/linux/selection.h b/include/linux/selection.h
index 8cdaa11..6570574 100644
--- a/include/linux/selection.h
+++ b/include/linux/selection.h
@@ -29,7 +29,7 @@ extern int default_red[];
 extern int default_grn[];
 extern int default_blu[];

-extern unsigned short *screen_pos(struct vc_data *vc, int w_offset,
int viewed);
+extern u32 *screen_pos(struct vc_data *vc, int w_offset, int viewed);
 extern u16 screen_glyph(struct vc_data *vc, int offset);
 extern void complement_pos(struct vc_data *vc, int offset);
 extern void invert_screen(struct vc_data *vc, int offset, int count,
int shift);
@@ -37,7 +37,7 @@ extern void invert_screen(struct vc_data *vc, int
offset, int count, int shift);
 extern void getconsxy(struct vc_data *vc, unsigned char *p);
 extern void putconsxy(struct vc_data *vc, unsigned char *p);

-extern u16 vcs_scr_readw(struct vc_data *vc, const u16 *org);
-extern void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org);
+extern u32 vcs_scr_readw(struct vc_data *vc, const u32 *org);
+extern void vcs_scr_writew(struct vc_data *vc, u32 val, u32 *org);

 #endif
diff --git a/include/linux/vt_buffer.h b/include/linux/vt_buffer.h
index 057db7d..e4669fa 100644
--- a/include/linux/vt_buffer.h
+++ b/include/linux/vt_buffer.h
@@ -28,30 +28,30 @@
 #endif

 #ifndef VT_BUF_HAVE_MEMSETW
-static inline void scr_memsetw(u16 *s, u16 c, unsigned int count)
+static inline void scr_memsetw(u32 *s, u32 c, unsigned int count)
 {
-	count /= 2;
+	count /= 4;
 	while (count--)
 		scr_writew(c, s++);
 }
 #endif

 #ifndef VT_BUF_HAVE_MEMCPYW
-static inline void scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
+static inline void scr_memcpyw(u32 *d, const u32 *s, unsigned int count)
 {
-	count /= 2;
+	count /= 4;
 	while (count--)
 		scr_writew(scr_readw(s++), d++);
 }
 #endif

 #ifndef VT_BUF_HAVE_MEMMOVEW
-static inline void scr_memmovew(u16 *d, const u16 *s, unsigned int count)
+static inline void scr_memmovew(u32 *d, const u32 *s, unsigned int count)
 {
 	if (d < s)
 		scr_memcpyw(d, s, count);
 	else {
-		count /= 2;
+		count /= 4;
 		d += count;
 		s += count;
 		while (count--)
@@ -60,4 +60,7 @@ static inline void scr_memmovew(u16 *d, const u16
*s, unsigned int count)
 }
 #endif

+#define VT_BUF_ATTR_MASK 0xff000000
+#define VT_BUF_ATTR_SHIFT 24
+
 #endif

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/2] Enlarge the storage of chars in virtual terminal
  2010-05-26  6:59 ` [PATCH 1/2] " Frank Pan
@ 2010-05-26  7:02   ` Frank Pan
  0 siblings, 0 replies; 13+ messages in thread
From: Frank Pan @ 2010-05-26  7:02 UTC (permalink / raw)
  To: Alan Cox, Gerardo Exequiel Pozzi, Kay Sievers, Andrew Morton,
	Greg Kroah-Hartman, Catalin Marinas, Daniel Mack, Tejun Heo,
	Christoph Lameter, Jiri Slaby, Jochen Hein, Johannes Weiner,
	Dave Airlie, Pekka Enberg, Geert Uytterhoeven
  Cc: LKML

Change fbcon to fit the new virtual terminal.

Signed-off-by: Frank Pan <frankpzh@gmail.com>
---
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index af88651..5534c4f 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -61,7 +61,7 @@ static void bit_bmove(struct vc_data *vc, struct
fb_info *info, int sy,
 static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy,
 		      int sx, int height, int width)
 {
-	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
+	int bgshift = vc->vc_hi_font_mask ? 5 : 4;
 	struct fb_fillrect region;

 	region.color = attr_bgcol_ec(bgshift, vc, info);
@@ -75,17 +75,19 @@ static void bit_clear(struct vc_data *vc, struct
fb_info *info, int sy,
 }

 static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
-				     const u16 *s, u32 attr, u32 cnt,
+				     const u32 *s, u32 attr, u32 cnt,
 				     u32 d_pitch, u32 s_pitch, u32 cellsize,
 				     struct fb_image *image, u8 *buf, u8 *dst)
 {
-	u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+	u32 ch;
 	u32 idx = vc->vc_font.width >> 3;
 	u8 *src;

 	while (cnt--) {
-		src = vc->vc_font.data + (scr_readw(s++)&
-					  charmask)*cellsize;
+		ch = scr_readw(s++) & ~VT_BUF_ATTR_MASK;
+		if (ch >= vc->vc_font.charcount)
+			ch = vc->vc_font.charcount - 1;
+		src = vc->vc_font.data + ch * cellsize;

 		if (attr) {
 			update_attr(buf, src, attr, vc);
@@ -106,21 +108,23 @@ static inline void bit_putcs_aligned(struct
vc_data *vc, struct fb_info *info,
 }

 static inline void bit_putcs_unaligned(struct vc_data *vc,
-				       struct fb_info *info, const u16 *s,
+				       struct fb_info *info, const u32 *s,
 				       u32 attr, u32 cnt, u32 d_pitch,
 				       u32 s_pitch, u32 cellsize,
 				       struct fb_image *image, u8 *buf,
 				       u8 *dst)
 {
-	u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+	u32 ch;
 	u32 shift_low = 0, mod = vc->vc_font.width % 8;
 	u32 shift_high = 8;
 	u32 idx = vc->vc_font.width >> 3;
 	u8 *src;

 	while (cnt--) {
-		src = vc->vc_font.data + (scr_readw(s++)&
-					  charmask)*cellsize;
+		ch = scr_readw(s++) & ~VT_BUF_ATTR_MASK;
+		if (ch >= vc->vc_font.charcount)
+			ch = vc->vc_font.charcount - 1;
+		src = vc->vc_font.data + ch * cellsize;

 		if (attr) {
 			update_attr(buf, src, attr, vc);
@@ -141,7 +145,7 @@ static inline void bit_putcs_unaligned(struct vc_data *vc,
 }

 static void bit_putcs(struct vc_data *vc, struct fb_info *info,
-		      const unsigned short *s, int count, int yy, int xx,
+		      const u32 *s, int count, int yy, int xx,
 		      int fg, int bg)
 {
 	struct fb_image image;
@@ -205,7 +209,7 @@ static void bit_putcs(struct vc_data *vc, struct
fb_info *info,
 static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
 			      int bottom_only)
 {
-	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
+	int bgshift = vc->vc_hi_font_mask ? 5 : 4;
 	unsigned int cw = vc->vc_font.width;
 	unsigned int ch = vc->vc_font.height;
 	unsigned int rw = info->var.xres - (vc->vc_cols*cw);
@@ -239,12 +243,13 @@ static void bit_cursor(struct vc_data *vc,
struct fb_info *info, int mode,
 {
 	struct fb_cursor cursor;
 	struct fbcon_ops *ops = info->fbcon_par;
-	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-	int w = DIV_ROUND_UP(vc->vc_font.width, 8), c;
+	u32 charmask = ~VT_BUF_ATTR_MASK;
+	int w = DIV_ROUND_UP(vc->vc_font.width, 8);
 	int y = real_y(ops->p, vc->vc_y);
 	int attribute, use_sw = (vc->vc_cursor_type & 0x10);
 	int err = 1;
 	char *src;
+	u32 c;

 	cursor.set = 0;

@@ -257,7 +262,7 @@ static void bit_cursor(struct vc_data *vc, struct
fb_info *info, int mode,
 			y += softback_lines;
 	}

- 	c = scr_readw((u16 *) vc->vc_pos);
+ 	c = scr_readw((u32 *) vc->vc_pos);
 	attribute = get_attribute(info, c);
 	src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));

diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index b0a3fa0..e51de79 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -143,7 +143,7 @@ static const struct consw fb_con;

 #define CM_SOFTBACK	(8)

-#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) +
(delta) * vc->vc_size_row)
+#define advance_row(p, delta) (u32 *)((unsigned long)(p) + (delta) *
vc->vc_size_row)

 static int fbcon_set_origin(struct vc_data *);

@@ -163,8 +163,8 @@ static void fbcon_init(struct vc_data *vc, int init);
 static void fbcon_deinit(struct vc_data *vc);
 static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
 			int width);
-static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos);
-static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
+static void fbcon_putc(struct vc_data *vc, u32 c, int ypos, int xpos);
+static void fbcon_putcs(struct vc_data *vc, const u32 *s,
 			int count, int ypos, int xpos);
 static void fbcon_clear_margins(struct vc_data *vc, int bottom_only);
 static void fbcon_cursor(struct vc_data *vc, int mode);
@@ -287,20 +287,20 @@ static inline int fbcon_is_inactive(struct
vc_data *vc, struct fb_info *info)
 }

 static inline int get_color(struct vc_data *vc, struct fb_info *info,
-	      u16 c, int is_fg)
+	      u32 c, int is_fg)
 {
 	int depth = fb_get_color_depth(&info->var, &info->fix);
 	int color = 0;

 	if (console_blanked) {
-		unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+		u32 charmask = ~VT_BUF_ATTR_MASK;

 		c = vc->vc_video_erase_char & charmask;
 	}

 	if (depth != 1)
-		color = (is_fg) ? attr_fgcol((vc->vc_hi_font_mask) ? 9 : 8, c)
-			: attr_bgcol((vc->vc_hi_font_mask) ? 13 : 12, c);
+		color = is_fg ? attr_fgcol((vc->vc_hi_font_mask == 0x100) ? 1 : 0, c)
+			: attr_bgcol((vc->vc_hi_font_mask == 0x100) ? 5 : 4, c);

 	switch (depth) {
 	case 1:
@@ -371,7 +371,7 @@ static void fb_flashcursor(struct work_struct *work)
 	struct fbcon_ops *ops = info->fbcon_par;
 	struct display *p;
 	struct vc_data *vc = NULL;
-	int c;
+	u32 c;
 	int mode;

 	acquire_console_sem();
@@ -386,7 +386,7 @@ static void fb_flashcursor(struct work_struct *work)
 	}

 	p = &fb_display[vc->vc_num];
-	c = scr_readw((u16 *) vc->vc_pos);
+	c = scr_readw((u32 *) vc->vc_pos);
 	mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
 		CM_ERASE : CM_DRAW;
 	ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1),
@@ -565,7 +565,7 @@ static void fbcon_prepare_logo(struct vc_data *vc,
struct fb_info *info,
 	/* Need to make room for the logo */
 	struct fbcon_ops *ops = info->fbcon_par;
 	int cnt, erase = vc->vc_video_erase_char, step;
-	unsigned short *save = NULL, *r, *q;
+	u32 *save = NULL, *r, *q;
 	int logo_height;

 	if (info->flags & FBINFO_MODULE) {
@@ -581,20 +581,20 @@ static void fbcon_prepare_logo(struct vc_data
*vc, struct fb_info *info,
 		erase &= ~0x400;
 	logo_height = fb_prepare_logo(info, ops->rotate);
 	logo_lines = DIV_ROUND_UP(logo_height, vc->vc_font.height);
-	q = (unsigned short *) (vc->vc_origin +
+	q = (u32 *) (vc->vc_origin +
 				vc->vc_size_row * rows);
 	step = logo_lines * cols;
 	for (r = q - logo_lines * cols; r < q; r++)
 		if (scr_readw(r) != vc->vc_video_erase_char)
 			break;
 	if (r != q && new_rows >= rows + logo_lines) {
-		save = kmalloc(logo_lines * new_cols * 2, GFP_KERNEL);
+		save = kmalloc(logo_lines * new_cols * 4, GFP_KERNEL);
 		if (save) {
 			int i = cols < new_cols ? cols : new_cols;
-			scr_memsetw(save, erase, logo_lines * new_cols * 2);
+			scr_memsetw(save, erase, logo_lines * new_cols * 4);
 			r = q - step;
 			for (cnt = 0; cnt < logo_lines; cnt++, r += i)
-				scr_memcpyw(save + cnt * new_cols, r, 2 * i);
+				scr_memcpyw(save + cnt * new_cols, r, 4 * i);
 			r = q;
 		}
 	}
@@ -615,7 +615,7 @@ static void fbcon_prepare_logo(struct vc_data *vc,
struct fb_info *info,
 			vc->vc_pos += lines * vc->vc_size_row;
 		}
 	}
-	scr_memsetw((unsigned short *) vc->vc_origin,
+	scr_memsetw((u32 *) vc->vc_origin,
 		    erase,
 		    vc->vc_size_row * logo_lines);

@@ -625,10 +625,10 @@ static void fbcon_prepare_logo(struct vc_data
*vc, struct fb_info *info,
 	}

 	if (save) {
-		q = (unsigned short *) (vc->vc_origin +
+		q = (u32 *) (vc->vc_origin +
 					vc->vc_size_row *
 					rows);
-		scr_memcpyw(q, save, logo_lines * new_cols * 2);
+		scr_memcpyw(q, save, logo_lines * new_cols * 4);
 		vc->vc_y += logo_lines;
 		vc->vc_pos += logo_lines * vc->vc_size_row;
 		kfree(save);
@@ -1050,6 +1050,7 @@ static void fbcon_init(struct vc_data *vc, int init)
 						    fvc->vc_font.data);
 			vc->vc_font.width = fvc->vc_font.width;
 			vc->vc_font.height = fvc->vc_font.height;
+			vc->vc_font.charcount = fvc->vc_font.charcount;
 			p->userfont = t->userfont;

 			if (p->userfont)
@@ -1074,7 +1075,7 @@ static void fbcon_init(struct vc_data *vc, int init)
 		charcnt = FNTCHARCNT(p->fontdata);

 	vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
-	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
+	vc->vc_complement_mask = (vc->vc_can_do_color ? 0x77 : 0x08) <<
VT_BUF_ATTR_SHIFT;
 	if (charcnt == 256) {
 		vc->vc_hi_font_mask = 0;
 	} else {
@@ -1251,7 +1252,8 @@ static void fbcon_clear(struct vc_data *vc, int
sy, int sx, int height,
 		ops->clear(vc, info, real_y(p, sy), sx, height, width);
 }

-static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
+
+static void fbcon_putcs(struct vc_data *vc, const u32 *s,
 			int count, int ypos, int xpos)
 {
 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
@@ -1264,9 +1266,9 @@ static void fbcon_putcs(struct vc_data *vc,
const unsigned short *s,
 			   get_color(vc, info, scr_readw(s), 0));
 }

-static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
+static void fbcon_putc(struct vc_data *vc, u32 c, int ypos, int xpos)
 {
-	unsigned short chr;
+	u32 chr;

 	scr_writew(c, &chr);
 	fbcon_putcs(vc, &chr, 1, ypos, xpos);
@@ -1286,7 +1288,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct fbcon_ops *ops = info->fbcon_par;
 	int y;
- 	int c = scr_readw((u16 *) vc->vc_pos);
+ 	u32 c = scr_readw((u32 *) vc->vc_pos);

 	if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
 		return;
@@ -1342,6 +1344,7 @@ static void fbcon_set_disp(struct fb_info *info,
struct fb_var_screeninfo *var,
 		vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
 		vc->vc_font.width = (*default_mode)->vc_font.width;
 		vc->vc_font.height = (*default_mode)->vc_font.height;
+		vc->vc_font.charcount = (*default_mode)->vc_font.charcount;
 		p->userfont = t->userfont;
 		if (p->userfont)
 			REFCOUNT(p->fontdata)++;
@@ -1356,7 +1359,7 @@ static void fbcon_set_disp(struct fb_info *info,
struct fb_var_screeninfo *var,
 	fb_set_var(info, var);
 	ops->var = info->var;
 	vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
-	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
+	vc->vc_complement_mask = (vc->vc_can_do_color ? 0x77 : 0x08) <<
VT_BUF_ATTR_SHIFT;
 	if (charcnt == 256) {
 		vc->vc_hi_font_mask = 0;
 	} else {
@@ -1521,13 +1524,13 @@ static void fbcon_redraw_softback(struct
vc_data *vc, struct display *p,
 				  long delta)
 {
 	int count = vc->vc_rows;
-	unsigned short *d, *s;
+	u32 *d, *s;
 	unsigned long n;
 	int line = 0;

-	d = (u16 *) softback_curr;
-	if (d == (u16 *) softback_in)
-		d = (u16 *) vc->vc_origin;
+	d = (u32 *) softback_curr;
+	if (d == (u32 *) softback_in)
+		d = (u32 *) vc->vc_origin;
 	n = softback_curr + delta * vc->vc_size_row;
 	softback_lines -= delta;
 	if (delta < 0) {
@@ -1559,22 +1562,22 @@ static void fbcon_redraw_softback(struct
vc_data *vc, struct display *p,
 	if (n == softback_curr)
 		return;
 	softback_curr = n;
-	s = (u16 *) softback_curr;
-	if (s == (u16 *) softback_in)
-		s = (u16 *) vc->vc_origin;
+	s = (u32 *) softback_curr;
+	if (s == (u32 *) softback_in)
+		s = (u32 *) vc->vc_origin;
 	while (count--) {
-		unsigned short *start;
-		unsigned short *le;
-		unsigned short c;
+		u32 *start;
+		u32 *le;
+		u32 c;
 		int x = 0;
-		unsigned short attr = 1;
+		u32 attr = 1;

 		start = s;
 		le = advance_row(s, 1);
 		do {
 			c = scr_readw(s);
-			if (attr != (c & 0xff00)) {
-				attr = c & 0xff00;
+			if (attr != (c & VT_BUF_ATTR_MASK)) {
+				attr = c & VT_BUF_ATTR_MASK;
 				if (s > start) {
 					fbcon_putcs(vc, start, s - start,
 						    line, x);
@@ -1599,34 +1602,33 @@ static void fbcon_redraw_softback(struct
vc_data *vc, struct display *p,
 		if (s > start)
 			fbcon_putcs(vc, start, s - start, line, x);
 		line++;
-		if (d == (u16 *) softback_end)
-			d = (u16 *) softback_buf;
-		if (d == (u16 *) softback_in)
-			d = (u16 *) vc->vc_origin;
-		if (s == (u16 *) softback_end)
-			s = (u16 *) softback_buf;
-		if (s == (u16 *) softback_in)
-			s = (u16 *) vc->vc_origin;
+		if (d == (u32 *) softback_end)
+			d = (u32 *) softback_buf;
+		if (d == (u32 *) softback_in)
+			d = (u32 *) vc->vc_origin;
+		if (s == (u32 *) softback_end)
+			s = (u32 *) softback_buf;
+		if (s == (u32 *) softback_in)
+			s = (u32 *) vc->vc_origin;
 	}
 }

 static void fbcon_redraw_move(struct vc_data *vc, struct display *p,
 			      int line, int count, int dy)
 {
-	unsigned short *s = (unsigned short *)
-		(vc->vc_origin + vc->vc_size_row * line);
+	u32 *s = (u32 *)(vc->vc_origin + vc->vc_size_row * line);

 	while (count--) {
-		unsigned short *start = s;
-		unsigned short *le = advance_row(s, 1);
-		unsigned short c;
+		u32 *start = s;
+		u32 *le = advance_row(s, 1);
+		u32 c;
 		int x = 0;
-		unsigned short attr = 1;
+		u32 attr = 1;

 		do {
 			c = scr_readw(s);
-			if (attr != (c & 0xff00)) {
-				attr = c & 0xff00;
+			if (attr != (c & VT_BUF_ATTR_MASK)) {
+				attr = c & VT_BUF_ATTR_MASK;
 				if (s > start) {
 					fbcon_putcs(vc, start, s - start,
 						    dy, x);
@@ -1648,15 +1650,14 @@ static void fbcon_redraw_blit(struct vc_data
*vc, struct fb_info *info,
 			struct display *p, int line, int count, int ycount)
 {
 	int offset = ycount * vc->vc_cols;
-	unsigned short *d = (unsigned short *)
-	    (vc->vc_origin + vc->vc_size_row * line);
-	unsigned short *s = d + offset;
+	u32 *d = (u32 *)(vc->vc_origin + vc->vc_size_row * line);
+	u32 *s = d + offset;
 	struct fbcon_ops *ops = info->fbcon_par;

 	while (count--) {
-		unsigned short *start = s;
-		unsigned short *le = advance_row(s, 1);
-		unsigned short c;
+		u32 *start = s;
+		u32 *le = advance_row(s, 1);
+		u32 c;
 		int x = 0;

 		do {
@@ -1697,21 +1698,20 @@ static void fbcon_redraw_blit(struct vc_data
*vc, struct fb_info *info,
 static void fbcon_redraw(struct vc_data *vc, struct display *p,
 			 int line, int count, int offset)
 {
-	unsigned short *d = (unsigned short *)
-	    (vc->vc_origin + vc->vc_size_row * line);
-	unsigned short *s = d + offset;
+	u32 *d = (u32 *)(vc->vc_origin + vc->vc_size_row * line);
+	u32 *s = d + offset;

 	while (count--) {
-		unsigned short *start = s;
-		unsigned short *le = advance_row(s, 1);
-		unsigned short c;
+		u32 *start = s;
+		u32 *le = advance_row(s, 1);
+		u32 c;
 		int x = 0;
-		unsigned short attr = 1;
+		u32 attr = 1;

 		do {
 			c = scr_readw(s);
-			if (attr != (c & 0xff00)) {
-				attr = c & 0xff00;
+			if (attr != (c & VT_BUF_ATTR_MASK)) {
+				attr = c & VT_BUF_ATTR_MASK;
 				if (s > start) {
 					fbcon_putcs(vc, start, s - start,
 						    line, x);
@@ -1743,8 +1743,8 @@ static void fbcon_redraw(struct vc_data *vc,
struct display *p,
 		else {
 			line--;
 			/* NOTE: We subtract two lines from these pointers */
-			s -= vc->vc_size_row;
-			d -= vc->vc_size_row;
+			s -= vc->vc_cols * 2;
+			d -= vc->vc_cols * 2;
 		}
 	}
 }
@@ -1752,14 +1752,14 @@ static void fbcon_redraw(struct vc_data *vc,
struct display *p,
 static inline void fbcon_softback_note(struct vc_data *vc, int t,
 				       int count)
 {
-	unsigned short *p;
+	u32 *p;

 	if (vc->vc_num != fg_console)
 		return;
-	p = (unsigned short *) (vc->vc_origin + t * vc->vc_size_row);
+	p = (u32 *) (vc->vc_origin + t * vc->vc_size_row);

 	while (count) {
-		scr_memcpyw((u16 *) softback_in, p, vc->vc_size_row);
+		scr_memcpyw((u32 *) softback_in, p, vc->vc_size_row);
 		count--;
 		p = advance_row(p, 1);
 		softback_in += vc->vc_size_row;
@@ -1805,9 +1805,9 @@ static int fbcon_scroll(struct vc_data *vc, int
t, int b, int dir,
 			fbcon_redraw_blit(vc, info, p, t, b - t - count,
 				     count);
 			fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
-			scr_memsetw((unsigned short *) (vc->vc_origin +
-							vc->vc_size_row *
-							(b - count)),
+			scr_memsetw((u32 *) (vc->vc_origin +
+						vc->vc_size_row *
+						(b - count)),
 				    vc->vc_video_erase_char,
 				    vc->vc_size_row * count);
 			return 1;
@@ -1877,9 +1877,9 @@ static int fbcon_scroll(struct vc_data *vc, int
t, int b, int dir,
 			fbcon_redraw(vc, p, t, b - t - count,
 				     count * vc->vc_cols);
 			fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
-			scr_memsetw((unsigned short *) (vc->vc_origin +
-							vc->vc_size_row *
-							(b - count)),
+			scr_memsetw((u32 *) (vc->vc_origin +
+						vc->vc_size_row *
+						(b - count)),
 				    vc->vc_video_erase_char,
 				    vc->vc_size_row * count);
 			return 1;
@@ -1896,9 +1896,9 @@ static int fbcon_scroll(struct vc_data *vc, int
t, int b, int dir,
 			fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
 				     -count);
 			fbcon_clear(vc, t, 0, count, vc->vc_cols);
-			scr_memsetw((unsigned short *) (vc->vc_origin +
-							vc->vc_size_row *
-							t),
+			scr_memsetw((u32 *) (vc->vc_origin +
+						vc->vc_size_row *
+						t),
 				    vc->vc_video_erase_char,
 				    vc->vc_size_row * count);
 			return 1;
@@ -1966,9 +1966,9 @@ static int fbcon_scroll(struct vc_data *vc, int
t, int b, int dir,
 			fbcon_redraw(vc, p, b - 1, b - t - count,
 				     -count * vc->vc_cols);
 			fbcon_clear(vc, t, 0, count, vc->vc_cols);
-			scr_memsetw((unsigned short *) (vc->vc_origin +
-							vc->vc_size_row *
-							t),
+			scr_memsetw((u32 *) (vc->vc_origin +
+						vc->vc_size_row *
+						t),
 				    vc->vc_video_erase_char,
 				    vc->vc_size_row * count);
 			return 1;
@@ -2225,7 +2225,7 @@ static int fbcon_switch(struct vc_data *vc)
 	}

 	vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
-	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
+	vc->vc_complement_mask = (vc->vc_can_do_color ? 0x77 : 0x08) <<
VT_BUF_ATTR_SHIFT;

 	if (p->userfont)
 		charcnt = FNTCHARCNT(vc->vc_font.data);
@@ -2281,9 +2281,8 @@ static void fbcon_generic_blank(struct vc_data
*vc, struct fb_info *info,
 	struct fb_event event;

 	if (blank) {
-		unsigned short charmask = vc->vc_hi_font_mask ?
-			0x1ff : 0xff;
-		unsigned short oldc;
+		u32 charmask = VT_BUF_ATTR_MASK;
+		u32 oldc;

 		oldc = vc->vc_video_erase_char;
 		vc->vc_video_erase_char &= charmask;
@@ -2418,6 +2417,7 @@ static int fbcon_do_set_font(struct vc_data *vc,
int w, int h,
 		REFCOUNT(data)++;
 	vc->vc_font.width = w;
 	vc->vc_font.height = h;
+	vc->vc_font.charcount = cnt;
 	if (vc->vc_hi_font_mask && cnt == 256) {
 		vc->vc_hi_font_mask = 0;
 		if (vc->vc_can_do_color) {
@@ -2427,18 +2427,18 @@ static int fbcon_do_set_font(struct vc_data
*vc, int w, int h,
 			
 		/* ++Edmund: reorder the attribute bits */
 		if (vc->vc_can_do_color) {
-			unsigned short *cp =
-			    (unsigned short *) vc->vc_origin;
-			int count = vc->vc_screenbuf_size / 2;
-			unsigned short c;
+			u32 *cp = (u32 *) vc->vc_origin;
+			int count = vc->vc_screenbuf_size / 4;
+			u32 c;
 			for (; count > 0; count--, cp++) {
 				c = scr_readw(cp);
-				scr_writew(((c & 0xfe00) >> 1) |
-					   (c & 0xff), cp);
+				scr_writew(((c & VT_BUF_ATTR_MASK) >> 1) |
+					   (c & ~VT_BUF_ATTR_MASK), cp);
 			}
 			c = vc->vc_video_erase_char;
 			vc->vc_video_erase_char =
-			    ((c & 0xfe00) >> 1) | (c & 0xff);
+				((c & VT_BUF_ATTR_MASK) >> 1) |
+				(c & ~VT_BUF_ATTR_MASK);
 			vc->vc_attr >>= 1;
 		}
 	} else if (!vc->vc_hi_font_mask && cnt == 512) {
@@ -2450,28 +2450,26 @@ static int fbcon_do_set_font(struct vc_data
*vc, int w, int h,
 			
 		/* ++Edmund: reorder the attribute bits */
 		{
-			unsigned short *cp =
-			    (unsigned short *) vc->vc_origin;
-			int count = vc->vc_screenbuf_size / 2;
-			unsigned short c;
+			u32 *cp = (u32 *) vc->vc_origin;
+			int count = vc->vc_screenbuf_size / 4;
+			u32 c;
 			for (; count > 0; count--, cp++) {
-				unsigned short newc;
+				u32 newc;
 				c = scr_readw(cp);
 				if (vc->vc_can_do_color)
-					newc =
-					    ((c & 0xff00) << 1) | (c &
-								   0xff);
+					newc = ((c & VT_BUF_ATTR_MASK) << 1) |
+						(c & ~VT_BUF_ATTR_MASK);
 				else
-					newc = c & ~0x100;
+					newc = c;
 				scr_writew(newc, cp);
 			}
 			c = vc->vc_video_erase_char;
 			if (vc->vc_can_do_color) {
 				vc->vc_video_erase_char =
-				    ((c & 0xff00) << 1) | (c & 0xff);
+					((c & VT_BUF_ATTR_MASK) << 1) |
+					(c & ~VT_BUF_ATTR_MASK);
 				vc->vc_attr <<= 1;
-			} else
-				vc->vc_video_erase_char = c & ~0x100;
+			}
 		}

 	}
@@ -2641,21 +2639,21 @@ static int fbcon_set_palette(struct vc_data
*vc, unsigned char *table)
 	return fb_set_cmap(&palette_cmap, info);
 }

-static u16 *fbcon_screen_pos(struct vc_data *vc, int offset)
+static u32 *fbcon_screen_pos(struct vc_data *vc, int offset)
 {
 	unsigned long p;
 	int line;
 	
 	if (vc->vc_num != fg_console || !softback_lines)
-		return (u16 *) (vc->vc_origin + offset);
+		return (u32 *) (vc->vc_origin + offset);
 	line = offset / vc->vc_size_row;
 	if (line >= softback_lines)
-		return (u16 *) (vc->vc_origin + offset -
+		return (u32 *) (vc->vc_origin + offset -
 				softback_lines * vc->vc_size_row);
 	p = softback_curr + offset;
 	if (p >= softback_end)
 		p += softback_buf - softback_end;
-	return (u16 *) p;
+	return (u32 *) p;
 }

 static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos,
@@ -2665,22 +2663,22 @@ static unsigned long fbcon_getxy(struct
vc_data *vc, unsigned long pos,
 	int x, y;

 	if (pos >= vc->vc_origin && pos < vc->vc_scr_end) {
-		unsigned long offset = (pos - vc->vc_origin) / 2;
+		unsigned long offset = (pos - vc->vc_origin) / 4;

 		x = offset % vc->vc_cols;
 		y = offset / vc->vc_cols;
 		if (vc->vc_num == fg_console)
 			y += softback_lines;
-		ret = pos + (vc->vc_cols - x) * 2;
+		ret = pos + (vc->vc_cols - x) * 4;
 	} else if (vc->vc_num == fg_console && softback_lines) {
 		unsigned long offset = pos - softback_curr;

 		if (pos < softback_curr)
 			offset += softback_end - softback_buf;
-		offset /= 2;
+		offset /= 4;
 		x = offset % vc->vc_cols;
 		y = offset / vc->vc_cols;
-		ret = pos + (vc->vc_cols - x) * 2;
+		ret = pos + (vc->vc_cols - x) * 4;
 		if (ret == softback_end)
 			ret = softback_buf;
 		if (ret == softback_in)
@@ -2699,23 +2697,27 @@ static unsigned long fbcon_getxy(struct
vc_data *vc, unsigned long pos,

 /* As we might be inside of softback, we may work with non-contiguous buffer,
    that's why we have to use a separate routine. */
-static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt)
+static void fbcon_invert_region(struct vc_data *vc, u32 * p, int cnt)
 {
 	while (cnt--) {
-		u16 a = scr_readw(p);
+		u32 a = scr_readw(p);
 		if (!vc->vc_can_do_color)
-			a ^= 0x0800;
+			a ^= 0x08 << VT_BUF_ATTR_SHIFT;
 		else if (vc->vc_hi_font_mask == 0x100)
-			a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) |
-			    (((a) & 0x0e00) << 4);
+			a = (a & ~VT_BUF_ATTR_MASK) |
+				(a & (0x10 << VT_BUF_ATTR_SHIFT)) |
+				((a & (0xe0 << VT_BUF_ATTR_SHIFT)) >> 4) |
+				((a & (0x0e << VT_BUF_ATTR_SHIFT)) << 4);
 		else
-			a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) |
-			    (((a) & 0x0700) << 4);
+			a = (a & ~VT_BUF_ATTR_MASK) |
+				(a & (0x88 << VT_BUF_ATTR_SHIFT)) |
+				((a & (0x70 << VT_BUF_ATTR_SHIFT)) >> 4) |
+				((a & (0x07 << VT_BUF_ATTR_SHIFT)) << 4);
 		scr_writew(a, p++);
-		if (p == (u16 *) softback_end)
-			p = (u16 *) softback_buf;
-		if (p == (u16 *) softback_in)
-			p = (u16 *) vc->vc_origin;
+		if (p == (u32 *) softback_end)
+			p = (u32 *) softback_buf;
+		if (p == (u32 *) softback_in)
+			p = (u32 *) vc->vc_origin;
 	}
 }

@@ -2751,7 +2753,7 @@ static int fbcon_scrolldelta(struct vc_data *vc,
int lines)
 						p = softback_end;
 					p -= vc->vc_size_row;
 					q -= vc->vc_size_row;
-					scr_memcpyw((u16 *) q, (u16 *) p,
+					scr_memcpyw((u32 *) q, (u32 *) p,
 						    vc->vc_size_row);
 				}
 				softback_in = softback_curr = p;
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 89a3468..c773878 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -57,7 +57,7 @@ struct fbcon_ops {
 	void (*clear)(struct vc_data *vc, struct fb_info *info, int sy,
 		      int sx, int height, int width);
 	void (*putcs)(struct vc_data *vc, struct fb_info *info,
-		      const unsigned short *s, int count, int yy, int xx,
+		      const u32 *s, int count, int yy, int xx,
 		      int fg, int bg);
 	void (*clear_margins)(struct vc_data *vc, struct fb_info *info,
 			      int bottom_only);
@@ -90,19 +90,19 @@ struct fbcon_ops {

 /* Color */
 #define attr_fgcol(fgshift,s)    \
-	(((s) >> (fgshift)) & 0x0f)
+	(((s) >> (fgshift + VT_BUF_ATTR_SHIFT)) & 0x0f)
 #define attr_bgcol(bgshift,s)    \
-	(((s) >> (bgshift)) & 0x0f)
+	(((s) >> (bgshift + VT_BUF_ATTR_SHIFT)) & 0x0f)

 /* Monochrome */
 #define attr_bold(s) \
-	((s) & 0x200)
+	((s) & (0x2 << VT_BUF_ATTR_SHIFT))
 #define attr_reverse(s) \
-	((s) & 0x800)
+	((s) & (0x8 << VT_BUF_ATTR_SHIFT))
 #define attr_underline(s) \
-	((s) & 0x400)
+	((s) & (0x4 << VT_BUF_ATTR_SHIFT))
 #define attr_blink(s) \
-	((s) & 0x8000)
+	((s) & (0x80 << VT_BUF_ATTR_SHIFT))
 	

 static inline int mono_col(const struct fb_info *info)
@@ -231,7 +231,7 @@ static inline int real_y(struct display *p, int ypos)
 }


-static inline int get_attribute(struct fb_info *info, u16 c)
+static inline int get_attribute(struct fb_info *info, u32 c)
 {
 	int attribute = 0;

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] Enlarge the storage of chars in virtual terminal
  2010-05-26  6:55 [PATCH 0/2] Enlarge the storage of chars in virtual terminal Frank Pan
  2010-05-26  6:59 ` [PATCH 1/2] " Frank Pan
@ 2010-05-26 14:11 ` Alan Cox
  2010-05-27  6:00   ` Frank Pan
  2010-05-27 13:41   ` Olivier Galibert
  1 sibling, 2 replies; 13+ messages in thread
From: Alan Cox @ 2010-05-26 14:11 UTC (permalink / raw)
  To: Frank Pan
  Cc: Gerardo Exequiel Pozzi, Kay Sievers, Andrew Morton,
	Greg Kroah-Hartman, Catalin Marinas, Daniel Mack, Tejun Heo,
	Christoph Lameter, Jiri Slaby, Jochen Hein, Johannes Weiner,
	Dave Airlie, Pekka Enberg, Geert Uytterhoeven, LKML

On Wed, 26 May 2010 14:55:04 +0800
Frank Pan <frankpzh@gmail.com> wrote:

> Greetings
> 
> The motivation is display much more characters on the
> framebuffer console than 512. If this is done, foreign
> languages can be easily rendered with currently supported
> utf-8 encoding.

This has been suggested a couple of times but unfortunately it's not
enough to use bigger fonts. Rendering many non western languages is far
far more complex. In addition the text mode vt driver is limited to 512
symbols by the hardware.

Doing it right means putting the entirity of Pango into the kernel. I'd
rather not do that when the job can be done better via a user space
application and pty/tty pair.

Alan

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] Enlarge the storage of chars in virtual terminal
  2010-05-26 14:11 ` [PATCH 0/2] " Alan Cox
@ 2010-05-27  6:00   ` Frank Pan
  2010-05-27  6:52     ` Tejun Heo
  2010-05-27 10:57     ` Alan Cox
  2010-05-27 13:41   ` Olivier Galibert
  1 sibling, 2 replies; 13+ messages in thread
From: Frank Pan @ 2010-05-27  6:00 UTC (permalink / raw)
  To: Alan Cox
  Cc: Gerardo Exequiel Pozzi, Kay Sievers, Andrew Morton,
	Greg Kroah-Hartman, Catalin Marinas, Daniel Mack, Tejun Heo,
	Christoph Lameter, Jiri Slaby, Jochen Hein, Johannes Weiner,
	Dave Airlie, Pekka Enberg, Geert Uytterhoeven, LKML

[-- Attachment #1: Type: text/plain, Size: 1541 bytes --]

Thanks for reply.

> This has been suggested a couple of times but unfortunately it's not
> enough to use bigger fonts. Rendering many non western languages is far
> far more complex. In addition the text mode vt driver is limited to 512
> symbols by the hardware.
Why is it complex? IMHO Rendering non-western languages is nothing more than
rendering 2 ASCII chars. The current mainline kernel already rendered these
chars with right width(but with 0xfffd glyph), and also has unicode mapping
support. Without fixing other drivers, the work on fbcon is merely breaking
the 512 limit.

The hardware limitation can be done in vgacon/mgacon/... drivers. They set
the fonts, they have right to refuse fonts with more than 512 chars.
Breaking lower level limitations won't impact them.

> Doing it right means putting the entirity of Pango into the kernel. I'd
> rather not do that when the job can be done better via a user space
> application and pty/tty pair.
IMHO A user space application doing such thing is just re-implementation of
virtual terminal support, without the 512 limitation. Why does we keeping
re-inventing the wheel?

I've already done the rendering, with this patch, removing several font size
limitations, and a user space font loader using PIO_FONTX ioctl.
It's much easier than pango, because the font is fixed on width and height.

Just an enlargement on a data structure can provide such a good feature
(important to console lovers like me), why not?

-- 
Frank Pan

Computer Science and Technology
Tsinghua University

[-- Attachment #2: Screenshot.png --]
[-- Type: image/png, Size: 49787 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] Enlarge the storage of chars in virtual terminal
  2010-05-27  6:00   ` Frank Pan
@ 2010-05-27  6:52     ` Tejun Heo
  2010-05-27  8:59       ` Frank Pan
  2010-05-27 10:57     ` Alan Cox
  1 sibling, 1 reply; 13+ messages in thread
From: Tejun Heo @ 2010-05-27  6:52 UTC (permalink / raw)
  To: Frank Pan
  Cc: Alan Cox, Gerardo Exequiel Pozzi, Kay Sievers, Andrew Morton,
	Greg Kroah-Hartman, Catalin Marinas, Daniel Mack,
	Christoph Lameter, Jiri Slaby, Jochen Hein, Johannes Weiner,
	Dave Airlie, Pekka Enberg, Geert Uytterhoeven, LKML

Hello,

On 05/27/2010 08:00 AM, Frank Pan wrote:
>> This has been suggested a couple of times but unfortunately it's not
>> enough to use bigger fonts. Rendering many non western languages is far
>> far more complex. In addition the text mode vt driver is limited to 512
>> symbols by the hardware.
>
> Why is it complex? IMHO Rendering non-western languages is nothing more than
> rendering 2 ASCII chars.

That's only true for CJK.  There are other scripts which are more
difficult to render properly.  e.g. In mixed English Arabic text,
English needs to be rendered left-to-right as usual while Arabic needs
to be rendered right-to-left.  Indic rendering is also known to be
very tricky.  Even on full desktop environment, only Gnome + Pango and
Visat/7 get everything right.

  http://en.wikipedia.org/wiki/Wikipedia%3AEnabling_complex_text_support_for_Indic_scripts

And then, if you think about multilingual terminal, output is only one
half of the story.  You gotta be able to input something too and in
many scripts, input handling needs to interact constantly with
rendering, which means that the kernel will also need to supply input
framework, at which point I start to wonder whether the whole thing is
just too complicated.

Why do we need a separate in-kernel implementation of unicode
rendering and multilingual input system at all?  What's the use case
other than "I just want to use console"?

Thanks.

-- 
tejun

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] Enlarge the storage of chars in virtual terminal
  2010-05-27  6:52     ` Tejun Heo
@ 2010-05-27  8:59       ` Frank Pan
  2010-05-27  9:30         ` Tejun Heo
  0 siblings, 1 reply; 13+ messages in thread
From: Frank Pan @ 2010-05-27  8:59 UTC (permalink / raw)
  To: Tejun Heo
  Cc: Alan Cox, Gerardo Exequiel Pozzi, Kay Sievers, Andrew Morton,
	Greg Kroah-Hartman, Catalin Marinas, Daniel Mack,
	Christoph Lameter, Jiri Slaby, Jochen Hein, Johannes Weiner,
	Dave Airlie, Pekka Enberg, Geert Uytterhoeven, LKML

Greetings,

> That's only true for CJK.  There are other scripts which are more
> difficult to render properly.  e.g. In mixed English Arabic text,
> English needs to be rendered left-to-right as usual while Arabic needs
> to be rendered right-to-left.  Indic rendering is also known to be
> very tricky.  Even on full desktop environment, only Gnome + Pango and
> Visat/7 get everything right.

You are right, I've missed a big count of languages.
Nonetheless, the vt already identified several ranges in the unicode
space, and made them 2 times wide as ASCII chars.
My idea depends on this.

OTOH, I think nobody expect the console can render scripts so nice
as it written on a piece of paper. Compare with the console now,
people seeing their home language scripts is better than seeing question
marks(?). Although they may in wrong order, although the resolution
is not enough for part of scripts, but one can see the content of
a file, a web page, which is rendered into pages of question marks
now.

Yes, It's not so perfect, but it's much better than question marks.

> And then, if you think about multilingual terminal, output is only one
> half of the story.  You gotta be able to input something too and in
> many scripts, input handling needs to interact constantly with
> rendering, which means that the kernel will also need to supply input
> framework, at which point I start to wonder whether the whole thing is
> just too complicated.

Agree. Input method is much complex than a data structure expanding.

I don't know about other languages, but I bet the thing goes like:
one press one or more keys, (choose the char he/she really want to, )?
and commit an input.
We need not to implement the whole thing inside kernel, a user space
app can catch keyboard inputs and push unicode chars into the tty.
The only change should be done in kernel is reserve a space on screen
for the potential char choosing, which is really easy to do in any
console drivers(report a smaller height/width).

> What's the use case other than "I just want to use console"?

Many times I type startx is just for checking time of a meeting
(in a CJK web page, etc).
Many times I've found emails in mutt with question marks, I must
open a X and a terminal in X, and mutt in terminal in X.
Is there anything worse?

Thanks.

-- 
Frank Pan

Computer Science and Technology
Tsinghua University

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] Enlarge the storage of chars in virtual terminal
  2010-05-27  8:59       ` Frank Pan
@ 2010-05-27  9:30         ` Tejun Heo
  2010-05-27 12:53           ` Frank Pan
  0 siblings, 1 reply; 13+ messages in thread
From: Tejun Heo @ 2010-05-27  9:30 UTC (permalink / raw)
  To: Frank Pan
  Cc: Alan Cox, Gerardo Exequiel Pozzi, Kay Sievers, Andrew Morton,
	Greg Kroah-Hartman, Catalin Marinas, Daniel Mack,
	Christoph Lameter, Jiri Slaby, Jochen Hein, Johannes Weiner,
	Dave Airlie, Pekka Enberg, Geert Uytterhoeven, LKML

Hello,

On 05/27/2010 10:59 AM, Frank Pan wrote:
> You are right, I've missed a big count of languages.
> Nonetheless, the vt already identified several ranges in the unicode
> space, and made them 2 times wide as ASCII chars.
> My idea depends on this.

Hmmm... I see.

>> And then, if you think about multilingual terminal, output is only one
>> half of the story.  You gotta be able to input something too and in
>> many scripts, input handling needs to interact constantly with
>> rendering, which means that the kernel will also need to supply input
>> framework, at which point I start to wonder whether the whole thing is
>> just too complicated.
> 
> Agree. Input method is much complex than a data structure expanding.
> 
> I don't know about other languages, but I bet the thing goes like:
> one press one or more keys, (choose the char he/she really want to, )?
> and commit an input.
> We need not to implement the whole thing inside kernel, a user space
> app can catch keyboard inputs and push unicode chars into the tty.
> The only change should be done in kernel is reserve a space on screen
> for the potential char choosing, which is really easy to do in any
> console drivers(report a smaller height/width).

I'm not an export on the issue but if I'm not mistaken it gets more
complex than that.  It took quite some time to solve the problem
properly even on full desktop envs.

>> What's the use case other than "I just want to use console"?
> 
> Many times I type startx is just for checking time of a meeting
> (in a CJK web page, etc).
> Many times I've found emails in mutt with question marks, I must
> open a X and a terminal in X, and mutt in terminal in X.

And other than yourself, how many would such users be?  What's your
reason for not using X other than "console looks cooler"?  Even if you
have some valid reason to not use X and absolutely have to have
multilingual support, what prevents you from using fb based terminals
like jfbterm which already works with input and all without
introducing any i18n related complexities into kernel?  To me, it
seems like low activiy on jfbterm seems to show the low demand for
such feature.  So, just use X.

> Is there anything worse?

Sure, there are plenty of worse things.  :-)

Thanks.

-- 
tejun

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] Enlarge the storage of chars in virtual terminal
  2010-05-27  6:00   ` Frank Pan
  2010-05-27  6:52     ` Tejun Heo
@ 2010-05-27 10:57     ` Alan Cox
  2010-05-27 13:15       ` Frank Pan
  1 sibling, 1 reply; 13+ messages in thread
From: Alan Cox @ 2010-05-27 10:57 UTC (permalink / raw)
  To: Frank Pan
  Cc: Gerardo Exequiel Pozzi, Kay Sievers, Andrew Morton,
	Greg Kroah-Hartman, Catalin Marinas, Daniel Mack, Tejun Heo,
	Christoph Lameter, Jiri Slaby, Jochen Hein, Johannes Weiner,
	Dave Airlie, Pekka Enberg, Geert Uytterhoeven, LKML

> Why is it complex?

You'd have to take that up with the orthographers and historians

> IMHO Rendering non-western languages is nothing
> more than rendering 2 ASCII chars. The current mainline kernel

It is a lot more. Things like arabic vowel handling for example, or
mixed direction text.

> IMHO A user space application doing such thing is just
> re-implementation of virtual terminal support, without the 512
> limitation. Why does we keeping re-inventing the wheel?

Pango does the job. Pango is the wheel.

Kernel code is unpageable, privileged and unable to doing things
trivially like dynamic font management. It's the wrong place for this
kind of stuff because doing fonts right and especially doing language
rendering right is *hard*.

Alan

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] Enlarge the storage of chars in virtual terminal
  2010-05-27  9:30         ` Tejun Heo
@ 2010-05-27 12:53           ` Frank Pan
  0 siblings, 0 replies; 13+ messages in thread
From: Frank Pan @ 2010-05-27 12:53 UTC (permalink / raw)
  To: Tejun Heo
  Cc: Alan Cox, Gerardo Exequiel Pozzi, Kay Sievers, Andrew Morton,
	Greg Kroah-Hartman, Catalin Marinas, Daniel Mack,
	Christoph Lameter, Jiri Slaby, Jochen Hein, Johannes Weiner,
	Dave Airlie, Pekka Enberg, Geert Uytterhoeven, LKML

Greetings,

> I'm not an export on the issue but if I'm not mistaken it gets more
> complex than that.  It took quite some time to solve the problem
> properly even on full desktop envs.
Maybe the issue on full desktop envs comes from different frameworks?
(gtk, qt, etc...)
On tty, it's just a char device. It may have difficulties, but unknown before
totally implement it. AFAIK, it's easier than desktop envs.

> And other than yourself, how many would such users be?  What's your
> reason for not using X other than "console looks cooler"?  Even if you
> have some valid reason to not use X and absolutely have to have
> multilingual support, what prevents you from using fb based terminals
> like jfbterm which already works with input and all without
> introducing any i18n related complexities into kernel?  To me, it
> seems like low activiy on jfbterm seems to show the low demand for
> such feature.  So, just use X.
Not everyone likes X. Forcing one who think X is a huge thing using X
even when checking emails is... too bad. People may have their own
choice, I think.

A brief view of jfbterm tells me it's a good thing, and the source code
tells me that it does almost the same thing in vt: esc char handling,
terminal configuration, etc. Plus, pcf parsing and encoding identification.
That's why I think we are re-inventing the wheel. Kernel do esc char
handling, kernel do terminal configuration, kernel do utf-8 decoding,
kernel do dynamic font changing. Why don't we just enlarge the glyphs
a font can have, so all the things go well?

Thanks for reply.

-- 
Frank Pan

Computer Science and Technology
Tsinghua University

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] Enlarge the storage of chars in virtual terminal
  2010-05-27 10:57     ` Alan Cox
@ 2010-05-27 13:15       ` Frank Pan
  0 siblings, 0 replies; 13+ messages in thread
From: Frank Pan @ 2010-05-27 13:15 UTC (permalink / raw)
  To: Alan Cox
  Cc: Gerardo Exequiel Pozzi, Kay Sievers, Andrew Morton,
	Greg Kroah-Hartman, Catalin Marinas, Daniel Mack, Tejun Heo,
	Christoph Lameter, Jiri Slaby, Jochen Hein, Johannes Weiner,
	Dave Airlie, Pekka Enberg, Geert Uytterhoeven, LKML

Greetings,

> It is a lot more. Things like arabic vowel handling for example, or
> mixed direction text.
> Pango does the job. Pango is the wheel.
I may haven't represent my idea clearly. No one wishes that fbcon can
do as good as pango. The important thing is, question marks have no
information, but scripts which may have placement issues have as
much information as the one rendered by pango.

> Kernel code is unpageable, privileged and unable to doing things
> trivially like dynamic font management. It's the wrong place for this
> kind of stuff because doing fonts right and especially doing language
> rendering right is *hard*.
Umm... maybe use bitblit instead of render is better? The current
mainline kernel already has features of font replacing, utf-8 decoding,
and "wide" char identification. Plenty of utf-8 bitmap fonts disperse on
the world, they just have more than 512 glyphs so vt cannot handle them,
Trust me, It's nothing more than provide a larger storage.

Thanks for reply.

-- 
Frank Pan

Computer Science and Technology
Tsinghua University

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] Enlarge the storage of chars in virtual terminal
  2010-05-26 14:11 ` [PATCH 0/2] " Alan Cox
  2010-05-27  6:00   ` Frank Pan
@ 2010-05-27 13:41   ` Olivier Galibert
  2010-05-27 13:46     ` Frank Pan
  1 sibling, 1 reply; 13+ messages in thread
From: Olivier Galibert @ 2010-05-27 13:41 UTC (permalink / raw)
  To: Alan Cox
  Cc: Frank Pan, Gerardo Exequiel Pozzi, Kay Sievers, Andrew Morton,
	Greg Kroah-Hartman, Catalin Marinas, Daniel Mack, Tejun Heo,
	Christoph Lameter, Jiri Slaby, Jochen Hein, Johannes Weiner,
	Dave Airlie, Pekka Enberg, Geert Uytterhoeven, LKML

On Wed, May 26, 2010 at 03:11:52PM +0100, Alan Cox wrote:
> On Wed, 26 May 2010 14:55:04 +0800
> Frank Pan <frankpzh@gmail.com> wrote:
> 
> > Greetings
> > 
> > The motivation is display much more characters on the
> > framebuffer console than 512. If this is done, foreign
> > languages can be easily rendered with currently supported
> > utf-8 encoding.
> 
> This has been suggested a couple of times but unfortunately it's not
> enough to use bigger fonts. Rendering many non western languages is far
> far more complex. In addition the text mode vt driver is limited to 512
> symbols by the hardware.

The Unicode book should be required reading for anyone who starts
talking about displaying utf-8/unicode text.  It's a *very*
interesting book with way more than code charts in it[1].

  OG.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] Enlarge the storage of chars in virtual terminal
  2010-05-27 13:41   ` Olivier Galibert
@ 2010-05-27 13:46     ` Frank Pan
  0 siblings, 0 replies; 13+ messages in thread
From: Frank Pan @ 2010-05-27 13:46 UTC (permalink / raw)
  To: Olivier Galibert
  Cc: Alan Cox, Gerardo Exequiel Pozzi, Kay Sievers, Andrew Morton,
	Greg Kroah-Hartman, Catalin Marinas, Daniel Mack, Tejun Heo,
	Christoph Lameter, Jiri Slaby, Jochen Hein, Johannes Weiner,
	Dave Airlie, Pekka Enberg, Geert Uytterhoeven, LKML

Greetings,

> The Unicode book should be required reading for anyone who starts
> talking about displaying utf-8/unicode text.  It's a *very*
> interesting book with way more than code charts in it[1].
You mean "The Unicode Standard, Version 5.0"?
Oh such a hugh brick. :) What's it about? History?
I'll read it tomorrow in the library.

-- 
Frank Pan

Computer Science and Technology
Tsinghua University

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2010-05-27 13:54 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-26  6:55 [PATCH 0/2] Enlarge the storage of chars in virtual terminal Frank Pan
2010-05-26  6:59 ` [PATCH 1/2] " Frank Pan
2010-05-26  7:02   ` [PATCH 2/2] " Frank Pan
2010-05-26 14:11 ` [PATCH 0/2] " Alan Cox
2010-05-27  6:00   ` Frank Pan
2010-05-27  6:52     ` Tejun Heo
2010-05-27  8:59       ` Frank Pan
2010-05-27  9:30         ` Tejun Heo
2010-05-27 12:53           ` Frank Pan
2010-05-27 10:57     ` Alan Cox
2010-05-27 13:15       ` Frank Pan
2010-05-27 13:41   ` Olivier Galibert
2010-05-27 13:46     ` Frank Pan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).