diff options
author | Jiri Slaby <jslaby@suse.cz> | 2020-06-15 09:48:51 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-06-24 17:08:32 +0200 |
commit | 391536ab775bf7d17e20e11c6f24f88d605449b2 (patch) | |
tree | d35626ac439819e68b66e41bd5f297cf18053414 /drivers/tty/vt/vt.c | |
parent | 754bda9807f2fcc0fe32ebeaef9f6443b2151059 (diff) |
vc: move normal char processing from do_con_write
vc_con_write_normal now handles the complex normal characters
processing. It is no longer a part of do_con_write. So this patch makes
do_con_write pretty clean and obvious.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20200615074910.19267-19-jslaby@suse.cz
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/vt/vt.c')
-rw-r--r-- | drivers/tty/vt/vt.c | 198 |
1 files changed, 109 insertions, 89 deletions
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 45d32844e61b..893f72dc812c 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2726,21 +2726,116 @@ static bool vc_is_control(struct vc_data *vc, int tc, int c) return false; } +static int vc_con_write_normal(struct vc_data *vc, int tc, int c, + struct vc_draw_region *draw) +{ + int next_c; + unsigned char vc_attr; + u16 himask = vc->vc_hi_font_mask, charmask = himask ? 0x1ff : 0xff; + u8 width = 1; + bool inverse = false; + + if (vc->vc_utf && !vc->vc_disp_ctrl) { + if (is_double_width(c)) + width = 2; + } + + /* Now try to find out how to display it */ + tc = conv_uni_to_pc(vc, tc); + if (tc & ~charmask) { + if (tc == -1 || tc == -2) + return -1; /* nothing to display */ + + /* Glyph not found */ + if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && + !(c & ~charmask)) { + /* + * In legacy mode use the glyph we get by a 1:1 + * mapping. + * This would make absolutely no sense with Unicode in + * mind, but do this for ASCII characters since a font + * may lack Unicode mapping info and we don't want to + * end up with having question marks only. + */ + tc = c; + } else { + /* + * Display U+FFFD. If it's not found, display an inverse + * question mark. + */ + tc = conv_uni_to_pc(vc, 0xfffd); + if (tc < 0) { + inverse = true; + tc = conv_uni_to_pc(vc, '?'); + if (tc < 0) + tc = '?'; + } + } + } + + if (!inverse) { + vc_attr = vc->vc_attr; + } else { + vc_attr = vc_invert_attr(vc); + con_flush(vc, draw); + } + + next_c = c; + while (1) { + if (vc->vc_need_wrap || vc->vc_decim) + con_flush(vc, draw); + if (vc->vc_need_wrap) { + cr(vc); + lf(vc); + } + if (vc->vc_decim) + insert_char(vc, 1); + vc_uniscr_putc(vc, next_c); + scr_writew(himask ? + ((vc_attr << 8) & ~himask) + + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : + (vc_attr << 8) + tc, + (u16 *)vc->vc_pos); + if (con_should_update(vc) && draw->x < 0) { + draw->x = vc->state.x; + draw->from = vc->vc_pos; + } + if (vc->state.x == vc->vc_cols - 1) { + vc->vc_need_wrap = vc->vc_decawm; + draw->to = vc->vc_pos + 2; + } else { + vc->state.x++; + draw->to = (vc->vc_pos += 2); + } + + if (!--width) + break; + + /* A space is printed in the second column */ + tc = conv_uni_to_pc(vc, ' '); + if (tc < 0) + tc = ' '; + next_c = ' '; + } + notify_write(vc, c); + + if (inverse) + con_flush(vc, draw); + + return 0; +} + /* acquires console_lock */ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct vc_draw_region draw = { .x = -1, }; - int c, next_c, tc, n = 0; + int c, tc, n = 0; unsigned int currcons; struct vc_data *vc; - unsigned char vc_attr; struct vt_notifier_param param; - u16 himask, charmask; - u8 width; bool rescan; - bool inverse; if (in_interrupt()) return count; @@ -2761,8 +2856,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 (con_is_fg(vc)) @@ -2778,8 +2871,6 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co rescan_last_byte: c = orig; rescan = false; - inverse = false; - width = 1; tc = vc_translate(vc, &c, &rescan); if (tc == -1) @@ -2790,88 +2881,17 @@ rescan_last_byte: ¶m) == NOTIFY_STOP) continue; - if (!vc_is_control(vc, tc, c)) { - if (vc->vc_utf && !vc->vc_disp_ctrl) { - if (is_double_width(c)) - width = 2; - } - /* Now try to find out how to display it */ - tc = conv_uni_to_pc(vc, tc); - if (tc & ~charmask) { - if (tc == -1 || tc == -2) { - continue; /* nothing to display */ - } - /* Glyph not found */ - if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) { - /* In legacy mode use the glyph we get by a 1:1 mapping. - This would make absolutely no sense with Unicode in mind, - but do this for ASCII characters since a font may lack - Unicode mapping info and we don't want to end up with - having question marks only. */ - tc = c; - } else { - /* Display U+FFFD. If it's not found, display an inverse question mark. */ - tc = conv_uni_to_pc(vc, 0xfffd); - if (tc < 0) { - inverse = true; - tc = conv_uni_to_pc(vc, '?'); - if (tc < 0) tc = '?'; - } - } - } - - if (!inverse) { - vc_attr = vc->vc_attr; - } else { - vc_attr = vc_invert_attr(vc); - con_flush(vc, &draw); - } - - next_c = c; - while (1) { - if (vc->vc_need_wrap || vc->vc_decim) - con_flush(vc, &draw); - if (vc->vc_need_wrap) { - cr(vc); - lf(vc); - } - if (vc->vc_decim) - insert_char(vc, 1); - vc_uniscr_putc(vc, next_c); - scr_writew(himask ? - ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : - (vc_attr << 8) + tc, - (u16 *) vc->vc_pos); - if (con_should_update(vc) && draw.x < 0) { - draw.x = vc->state.x; - draw.from = vc->vc_pos; - } - if (vc->state.x == vc->vc_cols - 1) { - vc->vc_need_wrap = vc->vc_decawm; - draw.to = vc->vc_pos + 2; - } else { - vc->state.x++; - draw.to = (vc->vc_pos += 2); - } - - if (!--width) break; - - tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */ - if (tc < 0) tc = ' '; - next_c = ' '; - } - notify_write(vc, c); - - if (inverse) - con_flush(vc, &draw); - - if (rescan) - goto rescan_last_byte; - + if (vc_is_control(vc, tc, c)) { + con_flush(vc, &draw); + do_con_trol(tty, vc, orig); continue; } - con_flush(vc, &draw); - do_con_trol(tty, vc, orig); + + if (vc_con_write_normal(vc, tc, c, &draw) < 0) + continue; + + if (rescan) + goto rescan_last_byte; } con_flush(vc, &draw); vc_uniscr_debug_check(vc); |