summaryrefslogtreecommitdiff
path: root/drivers/tty/vt/vt.c
diff options
context:
space:
mode:
authorJiri Slaby <jslaby@suse.cz>2020-06-15 09:48:51 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-06-24 17:08:32 +0200
commit391536ab775bf7d17e20e11c6f24f88d605449b2 (patch)
treed35626ac439819e68b66e41bd5f297cf18053414 /drivers/tty/vt/vt.c
parent754bda9807f2fcc0fe32ebeaef9f6443b2151059 (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.c198
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:
&param) == 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);