Commit 391536ab authored by Jiri Slaby's avatar Jiri Slaby Committed by Greg Kroah-Hartman
Browse files

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: default avatarJiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20200615074910.19267-19-jslaby@suse.cz


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 754bda98
Loading
Loading
Loading
Loading
+109 −89
Original line number Diff line number Diff line
@@ -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)
		if (vc_is_control(vc, tc, c)) {
			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 = ' ';
			do_con_trol(tty, vc, orig);
			continue;
		}
			notify_write(vc, c);

			if (inverse)
				con_flush(vc, &draw);
		if (vc_con_write_normal(vc, tc, c, &draw) < 0)
			continue;

		if (rescan)
			goto rescan_last_byte;

			continue;
		}
		con_flush(vc, &draw);
		do_con_trol(tty, vc, orig);
	}
	con_flush(vc, &draw);
	vc_uniscr_debug_check(vc);