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 = vc->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 = '?';

				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);

		if (himask)
			tc = ((tc & 0x100) ? himask : 0) |
			      (tc &  0xff);
		tc |= (vc_attr << 8) & ~himask;

		scr_writew(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;
}
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 = vc->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;
	}

	 
	tc = conv_uni_to_pc(vc, tc);
	if (tc & ~charmask) {
		if (tc == -1 || tc == -2)
			return -1;  

		 
		if ((!vc->vc_utf || vc->vc_disp_ctrl || c < 128) &&
				!(c & ~charmask)) {
			 
			tc = c;
		} else {
			 
			tc = conv_uni_to_pc(vc, 0xfffd);
			if (tc < 0) {
				inverse = true;
				tc = conv_uni_to_pc(vc, '?');
				if (tc < 0)
					tc = '?';

				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);

		if (himask)
			tc = ((tc & 0x100) ? himask : 0) |
			      (tc &  0xff);
		tc |= (vc_attr << 8) & ~himask;

		scr_writew(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, ' ');
		if (tc < 0)
			tc = ' ';
		next_c = ' ';
	}
	notify_write(vc, c);

	if (inverse)
		con_flush(vc, draw);

	return 0;
}