Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4.1 utf8 #217

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions drivers/tty/vt/selection.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ static inline void highlight_pointer(const int where)
static u16
sel_pos(int n)
{
return inverse_translate(sel_cons, screen_glyph(sel_cons, n),
use_unicode);
return screen_glyph(sel_cons, n);
}

/**
Expand Down Expand Up @@ -322,6 +321,8 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
}
obp = bp;
}
if (c > 0x80)
i += 2;
}
sel_buffer_lth = bp - sel_buffer;
return 0;
Expand Down
109 changes: 89 additions & 20 deletions drivers/tty/vt/vt.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,20 @@ static inline unsigned short *screenpos(struct vc_data *vc, int offset, int view
return p;
}

static inline unsigned short *screenpos_utf8(struct vc_data *vc, int offset, int viewed)
{
unsigned short *p;

if (!viewed)
p = (unsigned short *)(vc->vc_origin + offset + vc->vc_screenbuf_size);
else if (!vc->vc_sw->con_screen_pos)
p = (unsigned short *)(vc->vc_visible_origin + offset + vc->vc_screenbuf_size);
else
p = vc->vc_sw->con_screen_pos(vc, -offset - 1);
return p;
}


/* Called from the keyboard irq path.. */
static inline void scrolldelta(int lines)
{
Expand Down Expand Up @@ -324,6 +338,11 @@ static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int 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);
d += (vc->vc_screenbuf_size >> 1);
s += (vc->vc_screenbuf_size >> 1);
scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row);
scr_memsetw(d + (b - t - nr) * vc->vc_cols, 0,
vc->vc_size_row * nr);
}

static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
Expand All @@ -341,6 +360,9 @@ static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
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);
s += (vc->vc_screenbuf_size >> 1);
scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row);
scr_memsetw(s, 0, 2 * step);
}

static void do_update_region(struct vc_data *vc, unsigned long start, int count)
Expand Down Expand Up @@ -509,14 +531,16 @@ void complement_pos(struct vc_data *vc, int offset)
static int old_offset = -1;
static unsigned short old;
static unsigned short oldx, oldy;
static unsigned short *p_ext = NULL;
static unsigned short old_ext = 0;

WARN_CONSOLE_UNLOCKED();

if (old_offset != -1 && old_offset >= 0 &&
old_offset < vc->vc_screenbuf_size) {
scr_writew(old, screenpos(vc, old_offset, 1));
if (DO_UPDATE(vc))
vc->vc_sw->con_putc(vc, old, oldy, oldx);
vc->vc_sw->con_putc(vc, (old_ext << 16)|old, oldy, oldx);
notify_update(vc);
}

Expand All @@ -527,13 +551,15 @@ void complement_pos(struct vc_data *vc, int offset)
unsigned short new;
unsigned short *p;
p = screenpos(vc, offset, 1);
p_ext = screenpos_utf8(vc, offset, 1);
old = scr_readw(p);
old_ext = scr_readw(p_ext);
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;
vc->vc_sw->con_putc(vc, new, oldy, oldx);
vc->vc_sw->con_putc(vc, (old_ext << 16)|new, oldy, oldx);
}
notify_update(vc);
}
Expand Down Expand Up @@ -781,7 +807,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
visual_init(vc, currcons, 1);
if (!*vc->vc_uni_pagedir_loc)
con_set_default_unimap(vc);
vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size * 2, GFP_KERNEL);
if (!vc->vc_screenbuf) {
kfree(vc);
vc_cons[currcons].d = NULL;
Expand Down Expand Up @@ -841,7 +867,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
{
unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
unsigned long end;
unsigned int old_rows, old_row_size;
unsigned int old_rows, old_row_size,old_screen_size;
unsigned int new_cols, new_rows, new_row_size, new_screen_size;
unsigned int user;
unsigned short *newscreen;
Expand All @@ -861,11 +887,12 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
new_rows = (lines ? lines : vc->vc_rows);
new_row_size = new_cols << 1;
new_screen_size = new_row_size * new_rows;
old_screen_size = old_rows * old_row_size;

if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
return 0;

newscreen = kmalloc(new_screen_size, GFP_USER);
newscreen = kmalloc(new_screen_size * 2, GFP_USER);
if (!newscreen)
return -ENOMEM;

Expand Down Expand Up @@ -912,15 +939,23 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
while (old_origin < end) {
scr_memcpyw((unsigned short *) new_origin,
(unsigned short *) old_origin, rlth);
if (rrem)
scr_memcpyw((unsigned short *) new_origin + (new_screen_size >> 1),
(unsigned short *) old_origin + (old_screen_size >> 1), rlth);
if (rrem){
scr_memsetw((void *)(new_origin + rlth),
vc->vc_video_erase_char, rrem);
scr_memsetw((void *)(new_origin + rlth + (new_screen_size)),
vc->vc_video_erase_char, rrem);
}
old_origin += old_row_size;
new_origin += new_row_size;
}
if (new_scr_end > new_origin)
if (new_scr_end > new_origin){
scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
new_scr_end - new_origin);
scr_memsetw((void *)new_origin + (new_screen_size), vc->vc_video_erase_char,
new_scr_end - new_origin);
}
kfree(vc->vc_screenbuf);
vc->vc_screenbuf = newscreen;
vc->vc_screenbuf_size = new_screen_size;
Expand Down Expand Up @@ -2214,6 +2249,8 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
rescan = 0;
inverse = 0;
width = 1;
vc->vc_utf = 1;
vc->vc_disp_ctrl = 0;

/* Do no translation at all in control states */
if (vc->vc_state != ESnormal) {
Expand Down Expand Up @@ -2281,7 +2318,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
continue;
}
}
/* Nothing to do if an ASCII byte was received */

}
/* End of UTF-8 decoding. */
/* c is the received character, or U+FFFD for invalid sequences. */
Expand Down Expand Up @@ -2367,10 +2404,30 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
}
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);

if(is_double_width(c) && width==2)
{
tc = 0xFF;
scr_writew(himask ?
((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
(vc_attr << 8) + tc,
(u16 *) vc->vc_pos);
scr_writew(c, (u16 *) vc->vc_pos + (vc->vc_screenbuf_size >> 1));
}else if(is_double_width(c) && width==1){
tc = 0xFE;
scr_writew(himask ?
((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
(vc_attr << 8) + tc,
(u16 *) vc->vc_pos);
scr_writew(c, (u16 *) vc->vc_pos + (vc->vc_screenbuf_size >> 1));
}else{
scr_writew(himask ?
((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
(vc_attr << 8) + tc,
(u16 *) vc->vc_pos);
scr_writew(c, (u16 *) vc->vc_pos + (vc->vc_screenbuf_size >> 1));
}

if (DO_UPDATE(vc) && draw_x < 0) {
draw_x = vc->vc_x;
draw_from = vc->vc_pos;
Expand All @@ -2387,11 +2444,12 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co

tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */
if (tc < 0) tc = ' ';
}
notify_write(vc, c);

if (inverse) {
FLUSH
notify_write(vc, c);

if (inverse) {
FLUSH
}
}

if (rescan) {
Expand Down Expand Up @@ -2986,7 +3044,7 @@ static int __init con_init(void)
INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
tty_port_init(&vc->port);
visual_init(vc, currcons, 1);
vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size * 2, GFP_NOWAIT);
vc_init(vc, vc->vc_rows, vc->vc_cols,
currcons || !vc->vc_sw->con_save_screen);
}
Expand Down Expand Up @@ -4182,6 +4240,11 @@ static int con_font_copy(struct vc_data *vc, struct console_font_op *op)

int con_font_op(struct vc_data *vc, struct console_font_op *op)
{
/* IF WE ENABLE CJK font, I won't let you guys set console font any way until
we found a way to set console font that is unicode capable
*/
if(vc->vc_font.charcount > op->charcount)
return 0;
switch (op->op) {
case KD_FONT_OP_SET:
return con_font_set(vc, op);
Expand All @@ -4205,9 +4268,15 @@ 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;
u16 c_utf8 = scr_readw(screenpos_utf8(vc, offset, 1));

if ( (c == 0xff || c == 0xfe) && c_utf8 != 0){
return c_utf8;
}else{
if (w & vc->vc_hi_font_mask)
c |= 0x100;
return c;
}
}
EXPORT_SYMBOL_GPL(screen_glyph);

Expand Down
1 change: 1 addition & 0 deletions drivers/video/console/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
config FRAMEBUFFER_CONSOLE_ROTATION
bool "Framebuffer Console Rotation"
depends on FRAMEBUFFER_CONSOLE
depends on !FONT_16x16_CJK
help
Enable display rotation for the framebuffer console. This is done
in software and may be significantly slower than a normally oriented
Expand Down
1 change: 1 addition & 0 deletions drivers/video/console/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# 5 Aug 1999, James Simmons, <mailto:jsimmons@users.sf.net>
# Rewritten to use lists instead of if-statements.

# Font handling
obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o
obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o
obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o
Expand Down
57 changes: 49 additions & 8 deletions drivers/video/console/bitblit.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* more details.
*/

#include <linux/font.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
Expand Down Expand Up @@ -43,6 +44,21 @@ static void update_attr(u8 *dst, u8 *src, int attribute,
}
}

static inline u16 utf8_pos(struct vc_data *vc, const unsigned short *utf8)
{
unsigned long p = (long)utf8;
if (p >= vc->vc_origin && p < vc->vc_scr_end) {
return scr_readw((unsigned short *)(p + vc->vc_screenbuf_size));
} else if (vc->vc_num == fg_console && fbcon_is_softback(utf8)){
return scr_readw((unsigned short *)(p + fbcon_softback_size));
} else {
u16 extra_c;
int c = *(int*)utf8;
extra_c = (c >> 16 ) & 0x0000ffff;
return extra_c;
}
}

static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int dy, int dx, int height, int width)
{
Expand Down Expand Up @@ -74,6 +90,34 @@ static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy,
info->fbops->fb_fillrect(info, &region);
}

u8 * font_bits(struct vc_data *vc, const u16 *s,u32 cellsize,
u16 charmask)
{
u32 utf8_c;

u8 *src = vc->vc_font.data + (scr_readw(s)&
charmask)*cellsize;

utf8_c = utf8_pos(vc, s);

if( utf8_c <= vc->vc_font.charcount)
{
/*
* decide left-half char or right-half char.
* Since non-English chars may double weight
*/
switch (scr_readw(s) & charmask) {
case 0xff:
src = vc->vc_font.data + (utf8_c * cellsize *2 );
break;
case 0xfe:
src = vc->vc_font.data + (utf8_c * cellsize *2 + cellsize);
break;
}
}
return src;
}

static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
const u16 *s, u32 attr, u32 cnt,
u32 d_pitch, u32 s_pitch, u32 cellsize,
Expand All @@ -84,14 +128,12 @@ static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
u8 *src;

while (cnt--) {
src = vc->vc_font.data + (scr_readw(s++)&
charmask)*cellsize;
src = font_bits(vc,s++,cellsize,charmask);

if (attr) {
update_attr(buf, src, attr, vc);
src = buf;
}

if (likely(idx == 1))
__fb_pad_aligned_buffer(dst, d_pitch, src, idx,
image->height);
Expand Down Expand Up @@ -119,14 +161,11 @@ static inline void bit_putcs_unaligned(struct vc_data *vc,
u8 *src;

while (cnt--) {
src = vc->vc_font.data + (scr_readw(s++)&
charmask)*cellsize;

src = font_bits(vc,s++,cellsize,charmask);
if (attr) {
update_attr(buf, src, attr, vc);
src = buf;
}

fb_pad_unaligned_buffer(dst, d_pitch, src, idx,
image->height, shift_high,
shift_low, mod);
Expand Down Expand Up @@ -245,6 +284,8 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
int err = 1;
char *src;

int cellsize = DIV_ROUND_UP(vc->vc_font.width,8) * vc->vc_font.height;

cursor.set = 0;

if (softback_lines) {
Expand All @@ -258,7 +299,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,

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

if (ops->cursor_state.image.data != src ||
ops->cursor_reset) {
Expand Down
Loading