156337Skato/*-
256337Skato * Copyright (c) 1999 FreeBSD(98) Porting Team.
356337Skato * All rights reserved.
456337Skato *
556337Skato * Redistribution and use in source and binary forms, with or without
656337Skato * modification, are permitted provided that the following conditions
756337Skato * are met:
856337Skato * 1. Redistributions of source code must retain the above copyright
956337Skato *    notice, this list of conditions and the following disclaimer as
1056337Skato *    the first lines of this file unmodified.
1156337Skato * 2. Redistributions in binary form must reproduce the above copyright
1256337Skato *    notice, this list of conditions and the following disclaimer in the
1356337Skato *    documentation and/or other materials provided with the distribution.
1456337Skato *
1556337Skato * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
1656337Skato * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1756337Skato * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1856337Skato * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
1956337Skato * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2056337Skato * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2156337Skato * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2256337Skato * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2356337Skato * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2456337Skato * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2556337Skato */
2656337Skato
27332815Snyan#include <sys/cdefs.h>
28332815Snyan__FBSDID("$FreeBSD: stable/11/sys/pc98/cbus/scterm-sck.c 332815 2018-04-20 12:40:05Z nyan $");
29332815Snyan
3056337Skato#include "opt_syscons.h"
3156337Skato
3256337Skato#include <sys/param.h>
3356337Skato#include <sys/systm.h>
3456337Skato#include <sys/kernel.h>
35130070Sphk#include <sys/module.h>
3656337Skato#include <sys/consio.h>
3756337Skato
3856337Skato#include <machine/pc/display.h>
3956337Skato
4056337Skato#include <dev/syscons/syscons.h>
41186681Sed#include <pc98/cbus/sctermvar.h>
4256337Skato
4356337Skato#define MAX_ESC_PAR	5
4456337Skato
4556337Skato#ifdef KANJI
4656337Skato#define IS_KTYPE_ASCII_or_HANKAKU(A)	(!((A) & 0xee))
4756337Skato#define IS_KTYPE_KANA(A)		((A) & 0x11)
4856337Skato#define KTYPE_MASK_CTRL(A)		((A) &= 0xF0)
4956337Skato#endif /* KANJI */
5056337Skato
5156337Skato/* attribute flags */
5256337Skatotypedef struct {
5356337Skato	u_short		fg;			/* foreground color */
5456337Skato	u_short		bg;			/* background color */
5556337Skato} color_t;
5656337Skato
5756337Skatotypedef struct {
5856337Skato	int		flags;
5956337Skato#define SCTERM_BUSY	(1 << 0)
6056337Skato	int		esc;
6156337Skato	int		num_param;
6256337Skato	int		last_param;
6356337Skato	int		param[MAX_ESC_PAR];
6456337Skato	int		saved_xpos;
6556337Skato	int		saved_ypos;
6656337Skato
6756337Skato#ifdef KANJI
6856337Skato	u_char		kanji_1st_char;
6956337Skato	u_char		kanji_type;
7056337Skato#define KTYPE_ASCII	0			/* ASCII */
7156337Skato#define KTYPE_KANA	1			/* HANKAKU */
7256337Skato#define KTYPE_JKANA	0x10			/* JIS HANKAKU */
7356337Skato#define KTYPE_7JIS	0x20			/* JIS */
7456337Skato#define KTYPE_SJIS	2			/* Shift JIS */
7556337Skato#define KTYPE_UJIS	4			/* UJIS */
7656337Skato#define KTYPE_SUKANA	3			/* Shift JIS or UJIS HANKAKU */
7756337Skato#define KTYPE_SUJIS	6			/* SHift JIS or UJIS */
7856337Skato#define KTYPE_KANIN	0x80			/* Kanji Invoke sequence */
7956337Skato#define KTYPE_ASCIN	0x40			/* ASCII Invoke sequence */
8056337Skato#endif /* KANJI */
8156337Skato
8256337Skato	int		attr_mask;		/* current logical attr mask */
8356337Skato#define NORMAL_ATTR	0x00
8456337Skato#define BLINK_ATTR	0x01
8556337Skato#define BOLD_ATTR	0x02
8656337Skato#define UNDERLINE_ATTR	0x04
8756337Skato#define REVERSE_ATTR	0x08
8856337Skato#define FG_CHANGED	0x10
8956337Skato#define BG_CHANGED	0x20
9056337Skato	int		cur_attr;		/* current hardware attr word */
9156337Skato	color_t		cur_color;		/* current hardware color */
9256337Skato	color_t		std_color;		/* normal hardware color */
9356337Skato	color_t		rev_color;		/* reverse hardware color */
9456337Skato	color_t		dflt_std_color;		/* default normal color */
9556337Skato	color_t		dflt_rev_color;		/* default reverse color */
9656337Skato} term_stat;
9756337Skato
98199171Sedstatic sc_term_init_t		scterm_init;
99199171Sedstatic sc_term_term_t		scterm_term;
100199171Sedstatic sc_term_puts_t		scterm_puts;
101199171Sedstatic sc_term_ioctl_t		scterm_ioctl;
102199171Sedstatic sc_term_reset_t		scterm_reset;
10356337Skatostatic sc_term_default_attr_t	scterm_default_attr;
104199171Sedstatic sc_term_clear_t		scterm_clear;
105199171Sedstatic sc_term_notify_t		scterm_notify;
106199171Sedstatic sc_term_input_t		scterm_input;
107199171Sedstatic sc_term_fkeystr_t	scterm_fkeystr;
10856337Skato
10956337Skatostatic sc_term_sw_t sc_term_sc = {
11056337Skato	{ NULL, NULL },
11158381Snyan	"sck",					/* emulator name */
11258381Snyan	"syscons kanji terminal",		/* description */
11358381Snyan	"*",					/* matching renderer, any :-) */
11458381Snyan	sizeof(term_stat),			/* softc size */
11556337Skato	0,
11656337Skato	scterm_init,
11756337Skato	scterm_term,
11856337Skato	scterm_puts,
11956337Skato	scterm_ioctl,
12056337Skato	scterm_reset,
12156337Skato	scterm_default_attr,
12256337Skato	scterm_clear,
12356337Skato	scterm_notify,
12456337Skato	scterm_input,
125199171Sed	scterm_fkeystr,
12656337Skato};
12756337Skato
12856337SkatoSCTERM_MODULE(sc, sc_term_sc);
12956337Skato
13056337Skatostatic term_stat	reserved_term_stat;
13156337Skatostatic int		default_kanji = UJIS;
13256337Skatostatic void		scterm_scan_esc(scr_stat *scp, term_stat *tcp,
13356337Skato					u_char c);
13456337Skatostatic int		mask2attr(term_stat *tcp);
13556337Skato
13690012Snyan#ifdef KANJI
137228471Sedstatic inline u_char
13890012Snyaniskanji1(u_char mode, u_char c)
13990012Snyan{
14090465Snyan	if (c > 0x80) {
14190465Snyan		if ((c >= 0xa1) && (c <= 0xdf)) {
14290465Snyan			if (default_kanji == UJIS) {
14390465Snyan				/* UJIS */
14490465Snyan				return KTYPE_UJIS;
14590465Snyan			}
14690465Snyan			if (default_kanji == SJIS) {
14790465Snyan				/* SJIS HANKAKU */
14890465Snyan				return KTYPE_KANA;
14990465Snyan			}
15090465Snyan		}
15190012Snyan
15290465Snyan		if (c <= 0x9f) {
15390465Snyan			if (c == 0x8e) {
15490465Snyan				/* SJIS or UJIS HANKAKU */
15590465Snyan				return KTYPE_SUKANA;
15690465Snyan			}
15790012Snyan
15890465Snyan			/* SJIS */
15990465Snyan			default_kanji = SJIS;
16090465Snyan			return KTYPE_SJIS;
16190465Snyan		}
16290012Snyan
16390465Snyan		if ((c >= 0xe0) && (c <= 0xef)) {
16490465Snyan			/* SJIS or UJIS */
16590465Snyan			return KTYPE_SUJIS;
16690465Snyan		}
16790012Snyan
16890465Snyan		if ((c >= 0xf0) && (c <= 0xfe)) {
16990465Snyan			/* UJIS */
17090465Snyan			default_kanji = UJIS;
17190465Snyan			return KTYPE_UJIS;
17290465Snyan		}
17390465Snyan	} else {
17490465Snyan		if ((mode == KTYPE_7JIS) && (c >= 0x21) && (c <= 0x7e)) {
17590465Snyan			/* JIS */
17690465Snyan			default_kanji = UJIS;
17790465Snyan			return KTYPE_7JIS;
17890465Snyan		}
17990012Snyan
18090465Snyan		if ((mode == KTYPE_JKANA) && (c >= 0x21) && (c <= 0x5f)) {
18190465Snyan			/* JIS HANKAKU */
18290465Snyan			default_kanji = UJIS;
18390465Snyan			return KTYPE_JKANA;
18490465Snyan		}
18590465Snyan	}
18690012Snyan
18790465Snyan	return KTYPE_ASCII;
18890012Snyan}
18990012Snyan
190228471Sedstatic inline u_char
19190012Snyaniskanji2(u_char mode, u_char c)
19290012Snyan{
19390467Snyan	switch (mode) {
19490467Snyan	case KTYPE_7JIS:
19590467Snyan		if ((c >= 0x21) && (c <= 0x7e)) {
19690467Snyan			/* JIS */
19790467Snyan			return KTYPE_7JIS;
19890467Snyan		}
19990467Snyan		break;
20090467Snyan	case KTYPE_SJIS:
20190467Snyan		if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) {
20290467Snyan			/* SJIS */
20390467Snyan			return KTYPE_SJIS;
20490467Snyan		}
20590467Snyan		break;
20690467Snyan	case KTYPE_UJIS:
20790467Snyan		if ((c >= 0xa1) && (c <= 0xfe)) {
20890467Snyan			/* UJIS */
20990467Snyan			return KTYPE_UJIS;
21090467Snyan		}
21190467Snyan		break;
21290467Snyan	case KTYPE_SUKANA:
21390467Snyan		if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) {
21490467Snyan			/* UJIS HANKAKU */
21590467Snyan			return KTYPE_KANA;
21690467Snyan		}
21790467Snyan		if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) {
21890467Snyan			/* SJIS */
21990467Snyan			default_kanji = SJIS;
22090467Snyan			return KTYPE_SJIS;
22190467Snyan		}
22290467Snyan		break;
22390467Snyan	case KTYPE_SUJIS:
22490467Snyan		if ((c >= 0x40) && (c <= 0xa0) && (c != 0x7f)) {
22590467Snyan			/* SJIS */
22690467Snyan			default_kanji = SJIS;
22790467Snyan			return KTYPE_SJIS;
22890467Snyan		}
22990467Snyan		if ((c == 0xfd) || (c == 0xfe)) {
23090467Snyan			/* UJIS */
23190467Snyan			default_kanji = UJIS;
23290467Snyan			return KTYPE_UJIS;
23390467Snyan		}
23490467Snyan		if ((c >= 0xa1) && (c <= 0xfc)) {
23590467Snyan			if (default_kanji == SJIS)
23690467Snyan				return KTYPE_SJIS;
23790467Snyan			if (default_kanji == UJIS)
23890467Snyan				return KTYPE_UJIS;
23990467Snyan		}
24090467Snyan		break;
24190012Snyan	}
24290467Snyan
24390467Snyan	return KTYPE_ASCII;
24490012Snyan}
24590012Snyan
24690012Snyan/*
24790012Snyan * JIS X0208-83 keisen conversion table
24890012Snyan */
24990012Snyanstatic u_short keiConv[32] = {
25090012Snyan	0x240c, 0x260c, 0x300c, 0x340c, 0x3c0c, 0x380c, 0x400c, 0x500c,
25190012Snyan	0x480c, 0x580c, 0x600c, 0x250c, 0x270c, 0x330c, 0x370c, 0x3f0c,
25290012Snyan	0x3b0c, 0x470c, 0x570c, 0x4f0c, 0x5f0c, 0x6f0c, 0x440c, 0x530c,
25390012Snyan	0x4c0c, 0x5b0c, 0x630c, 0x410c, 0x540c, 0x490c, 0x5c0c, 0x660c
25490012Snyan};
25590012Snyan
25690012Snyanstatic u_short
25790012Snyankanji_convert(u_char mode, u_char h, u_char l)
25890012Snyan{
25990467Snyan	u_short tmp, high, low, c;
26090012Snyan
26190467Snyan	high = (u_short) h;
26290467Snyan	low  = (u_short) l;
26390467Snyan
26490467Snyan	switch (mode) {
26590467Snyan	case KTYPE_SJIS: /* SHIFT JIS */
26690467Snyan		if (low >= 0xe0) {
26790467Snyan			low -= 0x40;
26890467Snyan		}
26990467Snyan		low = (low - 0x81) * 2 + 0x21;
27090467Snyan		if (high > 0x7f) {
27190467Snyan			high--;
27290467Snyan		}
27390467Snyan		if (high > 0x9d) {
27490467Snyan			low++;
27590467Snyan			high -= 0x9e - 0x21;
27690467Snyan		} else {
27790467Snyan			high -= 0x40 - 0x21;
27890467Snyan		}
27990467Snyan		high &= 0x7F;
28090467Snyan		low  &= 0x7F;
28190467Snyan		tmp = ((high << 8) | low) - 0x20;
28290467Snyan		break;
28390467Snyan	case KTYPE_7JIS: /* JIS */
28490467Snyan	case KTYPE_UJIS: /* UJIS */
28590467Snyan		high &= 0x7F;
28690467Snyan		low &= 0x7F;
28790467Snyan		tmp = ((high << 8) | low) - 0x20;
28890467Snyan		break;
28990467Snyan	default:
29090467Snyan		tmp = 0;
29190467Snyan		break;
29290012Snyan	}
29390012Snyan
29490467Snyan	/* keisen */
29590467Snyan	c = ((tmp & 0xff) << 8) | (tmp >> 8);
29690467Snyan	/* 0x2821 .. 0x2840 */
29790467Snyan	if (0x0821 <= c && c <= 0x0840)
29890467Snyan		tmp = keiConv[c - 0x0821];
29990012Snyan
30090467Snyan	return (tmp);
30190012Snyan}
30290012Snyan#endif /* KANJI */
30390012Snyan
30456337Skatostatic int
30556337Skatoscterm_init(scr_stat *scp, void **softc, int code)
30656337Skato{
30756337Skato	term_stat *tcp;
30856337Skato
30956337Skato	if (*softc == NULL) {
31056337Skato		if (reserved_term_stat.flags & SCTERM_BUSY)
31156337Skato			return EINVAL;
31256337Skato		*softc = &reserved_term_stat;
31356337Skato	}
31456337Skato	tcp = *softc;
31556337Skato
31656337Skato	switch (code) {
31756337Skato	case SC_TE_COLD_INIT:
31856337Skato		bzero(tcp, sizeof(*tcp));
31956337Skato		tcp->flags = SCTERM_BUSY;
32056337Skato		tcp->esc = 0;
32156337Skato		tcp->saved_xpos = -1;
32256337Skato		tcp->saved_ypos = -1;
32356337Skato#ifdef KANJI
32456337Skato		tcp->kanji_1st_char = 0;
32556337Skato		tcp->kanji_type = KTYPE_ASCII;
32656337Skato#endif
32756337Skato		tcp->attr_mask = NORMAL_ATTR;
32856337Skato		/* XXX */
32956337Skato		tcp->dflt_std_color.fg = SC_NORM_ATTR & 0x0f;
33056337Skato		tcp->dflt_std_color.bg = (SC_NORM_ATTR >> 4) & 0x0f;
33156337Skato		tcp->dflt_rev_color.fg = SC_NORM_REV_ATTR & 0x0f;
33256337Skato		tcp->dflt_rev_color.bg = (SC_NORM_REV_ATTR >> 4) & 0x0f;
33356337Skato		tcp->std_color = tcp->dflt_std_color;
33456337Skato		tcp->rev_color = tcp->dflt_rev_color;
33556337Skato		tcp->cur_color = tcp->std_color;
33656337Skato		tcp->cur_attr = mask2attr(tcp);
33756337Skato		++sc_term_sc.te_refcount;
33856337Skato		break;
33956337Skato
34056337Skato	case SC_TE_WARM_INIT:
34156337Skato		tcp->esc = 0;
34256337Skato		tcp->saved_xpos = -1;
34356337Skato		tcp->saved_ypos = -1;
34457136Skato#if 0
34556337Skato		tcp->std_color = tcp->dflt_std_color;
34656337Skato		tcp->rev_color = tcp->dflt_rev_color;
34757136Skato#endif
34856337Skato		tcp->cur_color = tcp->std_color;
34956337Skato		tcp->cur_attr = mask2attr(tcp);
35056337Skato		break;
35156337Skato	}
35256337Skato
35356337Skato	return 0;
35456337Skato}
35556337Skato
35656337Skatostatic int
35756337Skatoscterm_term(scr_stat *scp, void **softc)
35856337Skato{
35956337Skato	if (*softc == &reserved_term_stat) {
36056337Skato		*softc = NULL;
36156337Skato		bzero(&reserved_term_stat, sizeof(reserved_term_stat));
36256337Skato	}
36356337Skato	--sc_term_sc.te_refcount;
36456337Skato	return 0;
36556337Skato}
36656337Skato
36756337Skatostatic void
36856337Skatoscterm_scan_esc(scr_stat *scp, term_stat *tcp, u_char c)
36956337Skato{
37056337Skato	static u_char ansi_col[16] = {
37156337Skato		FG_BLACK,     FG_RED,          FG_GREEN,      FG_BROWN,
37256337Skato		FG_BLUE,      FG_MAGENTA,      FG_CYAN,       FG_LIGHTGREY,
37356337Skato		FG_DARKGREY,  FG_LIGHTRED,     FG_LIGHTGREEN, FG_YELLOW,
37456337Skato		FG_LIGHTBLUE, FG_LIGHTMAGENTA, FG_LIGHTCYAN,  FG_WHITE
37558381Snyan	};
37681231Snyan	static int cattrs[] = {
37781231Snyan		0,					/* block */
37881231Snyan		CONS_BLINK_CURSOR,			/* blinking block */
37981231Snyan		CONS_CHAR_CURSOR,			/* underline */
38081231Snyan		CONS_CHAR_CURSOR | CONS_BLINK_CURSOR,	/* blinking underline */
38181231Snyan		CONS_RESET_CURSOR,			/* reset to default */
38281231Snyan		CONS_HIDDEN_CURSOR,			/* hide cursor */
38381231Snyan	};
38481231Snyan	static int tcattrs[] = {
38581231Snyan		CONS_RESET_CURSOR | CONS_LOCAL_CURSOR,	/* normal */
38681231Snyan		CONS_HIDDEN_CURSOR | CONS_LOCAL_CURSOR,	/* invisible */
38781231Snyan		CONS_BLINK_CURSOR | CONS_LOCAL_CURSOR,	/* very visible */
38881231Snyan	};
38956337Skato	sc_softc_t *sc;
39081231Snyan	int v0, v1, v2;
39156337Skato	int i, n;
39256337Skato
39358381Snyan	i = n = 0;
39458381Snyan	sc = scp->sc;
39558381Snyan	if (tcp->esc == 1) {	/* seen ESC */
39659778Snyan#ifdef KANJI
39759778Snyan		switch (tcp->kanji_type) {
39859778Snyan		case KTYPE_KANIN:	/* Kanji Invoke sequence */
39959778Snyan			switch (c) {
40059778Snyan			case 'B':
40159778Snyan			case '@':
40259778Snyan				tcp->kanji_type = KTYPE_7JIS;
40359778Snyan				tcp->esc = 0;
40459778Snyan				tcp->kanji_1st_char = 0;
40559778Snyan				return;
40659778Snyan			default:
40759778Snyan				tcp->kanji_type = KTYPE_ASCII;
40859778Snyan				tcp->esc = 0;
40959778Snyan				break;
41059778Snyan			}
41159778Snyan			break;
41259778Snyan		case KTYPE_ASCIN:	/* Ascii Invoke sequence */
41359778Snyan			switch (c) {
41459778Snyan			case 'J':
41559778Snyan			case 'B':
41659778Snyan			case 'H':
41759778Snyan				tcp->kanji_type = KTYPE_ASCII;
41859778Snyan				tcp->esc = 0;
41959778Snyan				tcp->kanji_1st_char = 0;
42059778Snyan				return;
42159778Snyan			case 'I':
42259778Snyan				tcp->kanji_type = KTYPE_JKANA;
42359778Snyan				tcp->esc = 0;
42459778Snyan				tcp->kanji_1st_char = 0;
42559778Snyan				return;
42659778Snyan			default:
42759778Snyan				tcp->kanji_type = KTYPE_ASCII;
42859778Snyan				tcp->esc = 0;
42959778Snyan				break;
43059778Snyan			}
43159778Snyan			break;
43259778Snyan		default:
43359778Snyan			break;
43459778Snyan		}
43559778Snyan#endif
43658381Snyan		switch (c) {
43756337Skato
43858381Snyan		case '7':	/* Save cursor position */
43958381Snyan			tcp->saved_xpos = scp->xpos;
44058381Snyan			tcp->saved_ypos = scp->ypos;
44158381Snyan			break;
44256337Skato
44358381Snyan		case '8':	/* Restore saved cursor position */
44458381Snyan			if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0)
44558381Snyan				sc_move_cursor(scp, tcp->saved_xpos,
44658381Snyan					       tcp->saved_ypos);
44758381Snyan			break;
44856337Skato
44958381Snyan		case '[':	/* Start ESC [ sequence */
45058381Snyan			tcp->esc = 2;
45158381Snyan			tcp->last_param = -1;
45258381Snyan			for (i = tcp->num_param; i < MAX_ESC_PAR; i++)
45358381Snyan				tcp->param[i] = 1;
45458381Snyan			tcp->num_param = 0;
45558381Snyan			return;
45656337Skato
45756337Skato#ifdef KANJI
45858381Snyan		case '$':	/* Kanji Invoke sequence */
45958381Snyan			tcp->kanji_type = KTYPE_KANIN;
46058381Snyan			return;
46156337Skato#endif
46256337Skato
46358381Snyan		case 'M':	/* Move cursor up 1 line, scroll if at top */
46458381Snyan			sc_term_up_scroll(scp, 1, sc->scr_map[0x20],
46558381Snyan					  tcp->cur_attr, 0, 0);
46658381Snyan			break;
467153110Sru#ifdef notyet
46858381Snyan		case 'Q':
46958381Snyan			tcp->esc = 4;
47058381Snyan			return;
47156337Skato#endif
47264021Snyan		case 'c':       /* reset */
47364021Snyan			tcp->attr_mask = NORMAL_ATTR;
47464021Snyan			tcp->cur_color = tcp->std_color
47564021Snyan				       = tcp->dflt_std_color;
47664021Snyan			tcp->rev_color = tcp->dflt_rev_color;
47764021Snyan			tcp->cur_attr = mask2attr(tcp);
47881231Snyan			sc_change_cursor_shape(scp,
47981231Snyan			    CONS_RESET_CURSOR | CONS_LOCAL_CURSOR, -1, -1);
48058381Snyan			sc_clear_screen(scp);
48158381Snyan			break;
48256337Skato
48358381Snyan		case '(':	/* iso-2022: designate 94 character set to G0 */
48456337Skato#ifdef KANJI
48558381Snyan			tcp->kanji_type = KTYPE_ASCIN;
48656337Skato#else
48758381Snyan			tcp->esc = 5;
48856337Skato#endif
48958381Snyan			return;
49056337Skato		}
49158381Snyan	} else if (tcp->esc == 2) {	/* seen ESC [ */
49258381Snyan		if (c >= '0' && c <= '9') {
49358381Snyan			if (tcp->num_param < MAX_ESC_PAR) {
49458381Snyan				if (tcp->last_param != tcp->num_param) {
49558381Snyan					tcp->last_param = tcp->num_param;
49658381Snyan					tcp->param[tcp->num_param] = 0;
49758381Snyan				} else {
49858381Snyan					tcp->param[tcp->num_param] *= 10;
49958381Snyan				}
50058381Snyan				tcp->param[tcp->num_param] += c - '0';
50158381Snyan				return;
50258381Snyan			}
50358381Snyan		}
50458381Snyan		tcp->num_param = tcp->last_param + 1;
50558381Snyan		switch (c) {
50656337Skato
50758381Snyan		case ';':
50858381Snyan			if (tcp->num_param < MAX_ESC_PAR)
50958381Snyan				return;
51058381Snyan			break;
51156337Skato
51258381Snyan		case '=':
51358381Snyan			tcp->esc = 3;
51458381Snyan			tcp->last_param = -1;
51558381Snyan			for (i = tcp->num_param; i < MAX_ESC_PAR; i++)
51658381Snyan				tcp->param[i] = 1;
51758381Snyan			tcp->num_param = 0;
51858381Snyan			return;
51956337Skato
52058381Snyan		case 'A':	/* up n rows */
52158381Snyan			sc_term_up(scp, tcp->param[0], 0);
52258381Snyan			break;
52356337Skato
52458381Snyan		case 'B':	/* down n rows */
52558381Snyan			sc_term_down(scp, tcp->param[0], 0);
52658381Snyan			break;
52756337Skato
52858381Snyan		case 'C':	/* right n columns */
52958381Snyan			sc_term_right(scp, tcp->param[0]);
53058381Snyan			break;
53156337Skato
53258381Snyan		case 'D':	/* left n columns */
53358381Snyan			sc_term_left(scp, tcp->param[0]);
53458381Snyan			break;
53556337Skato
53658381Snyan		case 'E':	/* cursor to start of line n lines down */
53758381Snyan			n = tcp->param[0];
53858381Snyan			if (n < 1)
53958381Snyan				n = 1;
54058381Snyan			sc_move_cursor(scp, 0, scp->ypos + n);
54158381Snyan			break;
54256337Skato
54358381Snyan		case 'F':	/* cursor to start of line n lines up */
54458381Snyan			n = tcp->param[0];
54558381Snyan			if (n < 1)
54658381Snyan				n = 1;
54758381Snyan			sc_move_cursor(scp, 0, scp->ypos - n);
54858381Snyan			break;
54956337Skato
55058381Snyan		case 'f':	/* Cursor move */
55158381Snyan		case 'H':
55258381Snyan			if (tcp->num_param == 0)
55358381Snyan				sc_move_cursor(scp, 0, 0);
55458381Snyan			else if (tcp->num_param == 2)
55558381Snyan				sc_move_cursor(scp, tcp->param[1] - 1,
55658381Snyan					       tcp->param[0] - 1);
55758381Snyan			break;
55856337Skato
55958381Snyan		case 'J':	/* Clear all or part of display */
56058381Snyan			if (tcp->num_param == 0)
56158381Snyan				n = 0;
56258381Snyan			else
56358381Snyan				n = tcp->param[0];
56458381Snyan			sc_term_clr_eos(scp, n, sc->scr_map[0x20],
56558381Snyan					tcp->cur_attr);
56658381Snyan			break;
56756337Skato
56858381Snyan		case 'K':	/* Clear all or part of line */
56958381Snyan			if (tcp->num_param == 0)
57058381Snyan				n = 0;
57158381Snyan			else
57258381Snyan				n = tcp->param[0];
57358381Snyan			sc_term_clr_eol(scp, n, sc->scr_map[0x20],
57458381Snyan					tcp->cur_attr);
57558381Snyan			break;
57656337Skato
57758381Snyan		case 'L':	/* Insert n lines */
57858381Snyan			sc_term_ins_line(scp, scp->ypos, tcp->param[0],
57958381Snyan					 sc->scr_map[0x20], tcp->cur_attr, 0);
58058381Snyan			break;
58156337Skato
58258381Snyan		case 'M':	/* Delete n lines */
58358381Snyan			sc_term_del_line(scp, scp->ypos, tcp->param[0],
58458381Snyan					 sc->scr_map[0x20], tcp->cur_attr, 0);
58558381Snyan			break;
58656337Skato
58758381Snyan		case 'P':	/* Delete n chars */
58858381Snyan			sc_term_del_char(scp, tcp->param[0],
58958381Snyan					 sc->scr_map[0x20], tcp->cur_attr);
59058381Snyan			break;
59156337Skato
59258381Snyan		case '@':	/* Insert n chars */
59358381Snyan			sc_term_ins_char(scp, tcp->param[0],
59458381Snyan					 sc->scr_map[0x20], tcp->cur_attr);
59558381Snyan			break;
59656337Skato
59758381Snyan		case 'S':	/* scroll up n lines */
59858381Snyan			sc_term_del_line(scp, 0, tcp->param[0],
59958381Snyan					 sc->scr_map[0x20], tcp->cur_attr, 0);
60058381Snyan			break;
60156337Skato
60258381Snyan		case 'T':	/* scroll down n lines */
60358381Snyan			sc_term_ins_line(scp, 0, tcp->param[0],
60458381Snyan					 sc->scr_map[0x20], tcp->cur_attr, 0);
60558381Snyan			break;
60656337Skato
60758381Snyan		case 'X':	/* erase n characters in line */
60858381Snyan			n = tcp->param[0];
60958381Snyan			if (n < 1)
61058381Snyan				n = 1;
61158381Snyan			if (n > scp->xsize - scp->xpos)
61258381Snyan				n = scp->xsize - scp->xpos;
61358381Snyan			sc_vtb_erase(&scp->vtb, scp->cursor_pos, n,
61458381Snyan				     sc->scr_map[0x20], tcp->cur_attr);
61558381Snyan			mark_for_update(scp, scp->cursor_pos);
61658381Snyan			mark_for_update(scp, scp->cursor_pos + n - 1);
61758381Snyan			break;
61856337Skato
61958381Snyan		case 'Z':	/* move n tabs backwards */
62058381Snyan			sc_term_backtab(scp, tcp->param[0]);
62158381Snyan			break;
62256337Skato
62358381Snyan		case '`':	/* move cursor to column n */
62458381Snyan			sc_term_col(scp, tcp->param[0]);
62558381Snyan			break;
62656337Skato
62758381Snyan		case 'a':	/* move cursor n columns to the right */
62858381Snyan			sc_term_right(scp, tcp->param[0]);
62958381Snyan			break;
63056337Skato
63158381Snyan		case 'd':	/* move cursor to row n */
63258381Snyan			sc_term_row(scp, tcp->param[0]);
63358381Snyan			break;
63456337Skato
63558381Snyan		case 'e':	/* move cursor n rows down */
63658381Snyan			sc_term_down(scp, tcp->param[0], 0);
63758381Snyan			break;
63856337Skato
63958381Snyan		case 'm':	/* change attribute */
64058381Snyan			if (tcp->num_param == 0) {
64158381Snyan				tcp->attr_mask = NORMAL_ATTR;
64258381Snyan				tcp->cur_color = tcp->std_color;
64358381Snyan				tcp->cur_attr = mask2attr(tcp);
64458381Snyan				break;
64558381Snyan			}
64658381Snyan			for (i = 0; i < tcp->num_param; i++) {
64758381Snyan				switch (n = tcp->param[i]) {
64858381Snyan				case 0:	/* back to normal */
64958381Snyan					tcp->attr_mask = NORMAL_ATTR;
65058381Snyan					tcp->cur_color = tcp->std_color;
65158381Snyan					tcp->cur_attr = mask2attr(tcp);
65258381Snyan					break;
65358381Snyan				case 1:	/* bold */
65458381Snyan					tcp->attr_mask |= BOLD_ATTR;
65558381Snyan					tcp->cur_attr = mask2attr(tcp);
65658381Snyan					break;
65758381Snyan				case 4:	/* underline */
65858381Snyan					tcp->attr_mask |= UNDERLINE_ATTR;
65958381Snyan					tcp->cur_attr = mask2attr(tcp);
66058381Snyan					break;
66158381Snyan				case 5:	/* blink */
66258381Snyan					tcp->attr_mask |= BLINK_ATTR;
66358381Snyan					tcp->cur_attr = mask2attr(tcp);
66458381Snyan					break;
66564021Snyan				case 7: /* reverse */
66658381Snyan					tcp->attr_mask |= REVERSE_ATTR;
66758381Snyan					tcp->cur_attr = mask2attr(tcp);
66858381Snyan					break;
66964021Snyan				case 22: /* remove bold (or dim) */
67064021Snyan					tcp->attr_mask &= ~BOLD_ATTR;
67164021Snyan					tcp->cur_attr = mask2attr(tcp);
67264021Snyan					break;
67364021Snyan				case 24: /* remove underline */
67464021Snyan					tcp->attr_mask &= ~UNDERLINE_ATTR;
67564021Snyan					tcp->cur_attr = mask2attr(tcp);
67664021Snyan					break;
67764021Snyan				case 25: /* remove blink */
67864021Snyan					tcp->attr_mask &= ~BLINK_ATTR;
67964021Snyan					tcp->cur_attr = mask2attr(tcp);
68064021Snyan					break;
68164021Snyan				case 27: /* remove reverse */
68264021Snyan					tcp->attr_mask &= ~REVERSE_ATTR;
68364021Snyan					tcp->cur_attr = mask2attr(tcp);
68464021Snyan					break;
68564021Snyan				case 30: case 31: /* set ansi fg color */
68658381Snyan				case 32: case 33: case 34:
68758381Snyan				case 35: case 36: case 37:
68858381Snyan					tcp->attr_mask |= FG_CHANGED;
68958381Snyan					tcp->cur_color.fg = ansi_col[n - 30];
69058381Snyan					tcp->cur_attr = mask2attr(tcp);
69158381Snyan					break;
69264021Snyan				case 39: /* restore fg color back to normal */
69364021Snyan					tcp->attr_mask &= ~(FG_CHANGED|BOLD_ATTR);
69461950Snyan					tcp->cur_color.fg = tcp->std_color.fg;
69561950Snyan					tcp->cur_attr = mask2attr(tcp);
69661950Snyan					break;
69764021Snyan				case 40: case 41: /* set ansi bg color */
69858381Snyan				case 42: case 43: case 44:
69958381Snyan				case 45: case 46: case 47:
70058381Snyan					tcp->attr_mask |= BG_CHANGED;
70158381Snyan					tcp->cur_color.bg = ansi_col[n - 40];
70258381Snyan					tcp->cur_attr = mask2attr(tcp);
70358381Snyan					break;
70464021Snyan				case 49: /* restore bg color back to normal */
70561950Snyan					tcp->attr_mask &= ~BG_CHANGED;
70661950Snyan					tcp->cur_color.bg = tcp->std_color.bg;
70761950Snyan					tcp->cur_attr = mask2attr(tcp);
70861950Snyan					break;
70958381Snyan				}
71058381Snyan			}
71158381Snyan			break;
71256337Skato
71358381Snyan		case 's':	/* Save cursor position */
71458381Snyan			tcp->saved_xpos = scp->xpos;
71558381Snyan			tcp->saved_ypos = scp->ypos;
71658381Snyan			break;
71756337Skato
71858381Snyan		case 'u':	/* Restore saved cursor position */
71958381Snyan			if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0)
72058381Snyan				sc_move_cursor(scp, tcp->saved_xpos,
72158381Snyan					       tcp->saved_ypos);
72258381Snyan			break;
72356337Skato
72458381Snyan		case 'x':
72558381Snyan			if (tcp->num_param == 0)
72658381Snyan				n = 0;
72758381Snyan			else
72858381Snyan				n = tcp->param[0];
72958381Snyan			switch (n) {
73064021Snyan			case 0: /* reset colors and attributes back to normal */
73158381Snyan				tcp->attr_mask = NORMAL_ATTR;
73288392Snyan				tcp->cur_color = tcp->std_color
73388392Snyan					       = tcp->dflt_std_color;
73458381Snyan				tcp->rev_color = tcp->dflt_rev_color;
73558381Snyan				tcp->cur_attr = mask2attr(tcp);
73658381Snyan				break;
73758381Snyan			case 1:	/* set ansi background */
73858381Snyan				tcp->attr_mask &= ~BG_CHANGED;
73988392Snyan				tcp->cur_color.bg = tcp->std_color.bg
74088392Snyan						  = ansi_col[tcp->param[1] & 0x0f];
74158381Snyan				tcp->cur_attr = mask2attr(tcp);
74258381Snyan				break;
74358381Snyan			case 2:	/* set ansi foreground */
74458381Snyan				tcp->attr_mask &= ~FG_CHANGED;
74588392Snyan				tcp->cur_color.fg = tcp->std_color.fg
74688392Snyan						  = ansi_col[tcp->param[1] & 0x0f];
74758381Snyan				tcp->cur_attr = mask2attr(tcp);
74858381Snyan				break;
74964021Snyan			case 3: /* set adapter attribute directly */
75058381Snyan				tcp->attr_mask &= ~(FG_CHANGED | BG_CHANGED);
75188392Snyan				tcp->cur_color.fg = tcp->std_color.fg
75288392Snyan						  = tcp->param[1] & 0x0f;
75388392Snyan				tcp->cur_color.bg = tcp->std_color.bg
75488392Snyan						  = (tcp->param[1] >> 4) & 0x0f;
75558381Snyan				tcp->cur_attr = mask2attr(tcp);
75658381Snyan				break;
75764021Snyan			case 5: /* set ansi reverse background */
75888392Snyan				tcp->rev_color.bg = ansi_col[tcp->param[1] & 0x0f];
75958381Snyan				tcp->cur_attr = mask2attr(tcp);
76058381Snyan				break;
76164021Snyan			case 6: /* set ansi reverse foreground */
76288392Snyan				tcp->rev_color.fg = ansi_col[tcp->param[1] & 0x0f];
76358381Snyan				tcp->cur_attr = mask2attr(tcp);
76458381Snyan				break;
76564021Snyan			case 7: /* set adapter reverse attribute directly */
76658381Snyan				tcp->rev_color.fg = tcp->param[1] & 0x0f;
76758381Snyan				tcp->rev_color.bg = (tcp->param[1] >> 4) & 0x0f;
76858381Snyan				tcp->cur_attr = mask2attr(tcp);
76958381Snyan				break;
77058381Snyan			}
77158381Snyan			break;
77256337Skato
77358381Snyan		case 'z':	/* switch to (virtual) console n */
77458381Snyan			if (tcp->num_param == 1)
77558381Snyan				sc_switch_scr(sc, tcp->param[0]);
77658381Snyan			break;
77756337Skato		}
77858381Snyan	} else if (tcp->esc == 3) {	/* seen ESC [0-9]+ = */
77958381Snyan		if (c >= '0' && c <= '9') {
78058381Snyan			if (tcp->num_param < MAX_ESC_PAR) {
78158381Snyan				if (tcp->last_param != tcp->num_param) {
78258381Snyan					tcp->last_param = tcp->num_param;
78358381Snyan					tcp->param[tcp->num_param] = 0;
78458381Snyan				} else {
78558381Snyan					tcp->param[tcp->num_param] *= 10;
78658381Snyan				}
78758381Snyan				tcp->param[tcp->num_param] += c - '0';
78858381Snyan				return;
78958381Snyan			}
79058381Snyan		}
79158381Snyan		tcp->num_param = tcp->last_param + 1;
79258381Snyan		switch (c) {
79356337Skato
79458381Snyan		case ';':
79558381Snyan			if (tcp->num_param < MAX_ESC_PAR)
79658381Snyan				return;
79758381Snyan			break;
79856337Skato
79958381Snyan		case 'A':   /* set display border color */
80058381Snyan			if (tcp->num_param == 1) {
80158381Snyan				scp->border=tcp->param[0] & 0xff;
80258381Snyan				if (scp == sc->cur_scp)
80358381Snyan					sc_set_border(scp, scp->border);
80458381Snyan			}
80558381Snyan			break;
80656337Skato
80758381Snyan		case 'B':   /* set bell pitch and duration */
80858381Snyan			if (tcp->num_param == 2) {
80958381Snyan				scp->bell_pitch = tcp->param[0];
81078811Snyan				scp->bell_duration =
81178811Snyan				    (tcp->param[1] * hz + 99) / 100;
81258381Snyan			}
81358381Snyan			break;
81456337Skato
81581231Snyan		case 'C':   /* set global/parmanent cursor type & shape */
81658381Snyan			i = spltty();
81781231Snyan			n = tcp->num_param;
81881231Snyan			v0 = tcp->param[0];
81981231Snyan			v1 = tcp->param[1];
82081231Snyan			v2 = tcp->param[2];
82181231Snyan			switch (n) {
82281231Snyan			case 1:	/* flags only */
823298352Spfg				if (v0 < nitems(cattrs))
82481231Snyan					v0 = cattrs[v0];
82581231Snyan				else	/* backward compatibility */
82681231Snyan					v0 = cattrs[v0 & 0x3];
82781231Snyan				sc_change_cursor_shape(scp, v0, -1, -1);
82881231Snyan				break;
82981231Snyan			case 2:
83081231Snyan				v2 = 0;
83181231Snyan				v0 &= 0x1f;	/* backward compatibility */
83281231Snyan				v1 &= 0x1f;
83381231Snyan				/* FALL THROUGH */
83481231Snyan			case 3:	/* base and height */
83581231Snyan				if (v2 == 0)	/* count from top */
83681231Snyan					sc_change_cursor_shape(scp, -1,
83781231Snyan					    scp->font_size - v1 - 1,
83881231Snyan					    v1 - v0 + 1);
83981231Snyan				else if (v2 == 1) /* count from bottom */
84081231Snyan					sc_change_cursor_shape(scp, -1,
84181231Snyan					    v0, v1 - v0 + 1);
84281231Snyan				break;
84358381Snyan			}
84458381Snyan			splx(i);
84558381Snyan			break;
84656337Skato
84764021Snyan		case 'F':   /* set adapter foreground */
84858381Snyan			if (tcp->num_param == 1) {
84958381Snyan				tcp->attr_mask &= ~FG_CHANGED;
85088392Snyan				tcp->cur_color.fg = tcp->std_color.fg
85188392Snyan						  = tcp->param[0] & 0x0f;
85258381Snyan				tcp->cur_attr = mask2attr(tcp);
85358381Snyan			}
85458381Snyan			break;
85556337Skato
85664021Snyan		case 'G':   /* set adapter background */
85758381Snyan			if (tcp->num_param == 1) {
85858381Snyan				tcp->attr_mask &= ~BG_CHANGED;
85988392Snyan				tcp->cur_color.bg = tcp->std_color.bg
86088392Snyan						  = tcp->param[0] & 0x0f;
86158381Snyan				tcp->cur_attr = mask2attr(tcp);
86258381Snyan			}
86358381Snyan			break;
86456337Skato
86564021Snyan		case 'H':   /* set adapter reverse foreground */
86658381Snyan			if (tcp->num_param == 1) {
86758381Snyan				tcp->rev_color.fg = tcp->param[0] & 0x0f;
86858381Snyan				tcp->cur_attr = mask2attr(tcp);
86958381Snyan			}
87058381Snyan			break;
87156337Skato
87264021Snyan		case 'I':   /* set adapter reverse background */
87358381Snyan			if (tcp->num_param == 1) {
87458381Snyan				tcp->rev_color.bg = tcp->param[0] & 0x0f;
87558381Snyan				tcp->cur_attr = mask2attr(tcp);
87658381Snyan			}
87758381Snyan			break;
87881231Snyan
87981231Snyan		case 'S':   /* set local/temporary cursor type & shape */
88081231Snyan			i = spltty();
88181231Snyan			n = tcp->num_param;
88281231Snyan			v0 = tcp->param[0];
88381231Snyan			switch (n) {
88481231Snyan			case 0:
88581231Snyan				v0 = 0;
88681231Snyan				/* FALL THROUGH */
88781231Snyan			case 1:
888298352Spfg				if (v0 < nitems(tcattrs))
88981231Snyan					sc_change_cursor_shape(scp,
89081231Snyan					    tcattrs[v0], -1, -1);
89181231Snyan				break;
89281231Snyan			}
89381231Snyan			splx(i);
89481231Snyan			break;
89558381Snyan		}
896153110Sru#ifdef notyet
89758381Snyan	} else if (tcp->esc == 4) {	/* seen ESC Q */
89858381Snyan		/* to be filled */
89956337Skato#endif
90058381Snyan	} else if (tcp->esc == 5) {	/* seen ESC ( */
90158381Snyan		switch (c) {
90258381Snyan		case 'B':   /* iso-2022: desginate ASCII into G0 */
90358381Snyan			break;
90458381Snyan		/* other items to be filled */
90558381Snyan		default:
90658381Snyan			break;
90758381Snyan		}
90856337Skato	}
90958381Snyan	tcp->esc = 0;
91056337Skato}
91156337Skato
91256337Skatostatic void
913332815Snyanscterm_puts(scr_stat *scp, u_char *buf, int len)
91456337Skato{
91588392Snyan	term_stat *tcp;
91688392Snyan	u_char *ptr;
91756337Skato#ifdef KANJI
91856337Skato	u_short kanji_code;
91956337Skato#endif
92056337Skato
92188392Snyan	tcp = scp->ts;
92288392Snyan	ptr = buf;
92356337Skatooutloop:
92458381Snyan	scp->sc->write_in_progress++;
92556337Skato
92658381Snyan	if (tcp->esc) {
92758381Snyan		scterm_scan_esc(scp, tcp, *ptr++);
92858381Snyan		len--;
92958381Snyan	} else if (PRINTABLE(*ptr)) {     /* Print only printables */
93058381Snyan		vm_offset_t p;
93158381Snyan		u_char *map;
93258381Snyan		int attr;
93358381Snyan		int i;
93490465Snyan		int cnt;
93556337Skato#ifdef KANJI
93658381Snyan		u_char c;
93756337Skato#endif
93856337Skato
93958381Snyan		p = sc_vtb_pointer(&scp->vtb, scp->cursor_pos);
94058381Snyan		map = scp->sc->scr_map;
94158381Snyan		attr = tcp->cur_attr;
94256337Skato
94356337Skato#ifdef KANJI
94458381Snyan		c = *ptr;
94558381Snyan		if (tcp->kanji_1st_char == 0) {
94658381Snyan		    tcp->kanji_type = iskanji1(tcp->kanji_type, c);
94758381Snyan		    if (!IS_KTYPE_ASCII_or_HANKAKU(tcp->kanji_type)) {
94858381Snyan			/* not Ascii & not HANKAKU */
94958381Snyan			tcp->kanji_1st_char = c;
95058381Snyan			goto kanji_end;
95190465Snyan		    } else if (tcp->kanji_type == KTYPE_ASCII) {
95290465Snyan			cnt = imin(len, scp->xsize - scp->xpos);
95390465Snyan			i = cnt;
95490465Snyan			do {
95590465Snyan			    p = sc_vtb_putchar(&scp->vtb, p, map[c], attr);
95690465Snyan			    c = *++ptr;
95790465Snyan			    --i;
95890465Snyan			} while (i > 0 && PRINTABLE(c) &&
95990465Snyan				 iskanji1(tcp->kanji_type, c) == KTYPE_ASCII);
96090465Snyan
96190465Snyan			len -= cnt - i;
96290465Snyan			mark_for_update(scp, scp->cursor_pos);
96390465Snyan			scp->cursor_pos += cnt - i;
96490465Snyan			mark_for_update(scp, scp->cursor_pos - 1);
96590465Snyan			scp->xpos += cnt - i;
96690465Snyan			KTYPE_MASK_CTRL(tcp->kanji_type);
96790465Snyan			goto ascii_end;
96856337Skato		    }
96958381Snyan		} else {
97058381Snyan		    if ((tcp->kanji_type =
97158381Snyan			 iskanji2(tcp->kanji_type, c)) & 0xee) {
97258381Snyan			/* print kanji on TEXT VRAM */
97358381Snyan			kanji_code = kanji_convert(tcp->kanji_type, c,
97458381Snyan						   tcp->kanji_1st_char);
97558381Snyan			mark_for_update(scp, scp->cursor_pos);
97658381Snyan			for (i = 0; i < 2; i++) {
97758381Snyan			    /* *cursor_pos = (kanji_code | (i*0x80)); */
97858381Snyan			    p = sc_vtb_putchar(&scp->vtb, p,
97958381Snyan			       kanji_code | ((i == 0) ? 0x00 : 0x80), attr);
98058381Snyan			    ++scp->cursor_pos;
98158381Snyan			    if (++scp->xpos >= scp->xsize) {
98258381Snyan				scp->xpos = 0;
98358381Snyan				scp->ypos++;
98458381Snyan			    }
98558381Snyan			}
98658381Snyan			mark_for_update(scp, scp->cursor_pos - 1);
98758381Snyan			KTYPE_MASK_CTRL(tcp->kanji_type);
98858381Snyan			tcp->kanji_1st_char = 0;
98958381Snyan			goto kanji_end;
99058381Snyan		    } else {
99158381Snyan			tcp->kanji_1st_char = 0;
99258381Snyan		    }
99358381Snyan		}
99458381Snyan		if (IS_KTYPE_KANA(tcp->kanji_type))
99558381Snyan		    c |= 0x80;
99656337Skato		KTYPE_MASK_CTRL(tcp->kanji_type);
99758381Snyan		sc_vtb_putchar(&scp->vtb, p, map[c], attr);
99858381Snyan		mark_for_update(scp, scp->cursor_pos);
99958381Snyan		mark_for_update(scp, scp->cursor_pos);
100058381Snyan		++scp->cursor_pos;
100158381Snyan		++scp->xpos;
100256337Skatokanji_end:
100358381Snyan		++ptr;
100458381Snyan		--len;
100590465Snyanascii_end:
100656337Skato#else /* !KANJI */
100758381Snyan		cnt = imin(len, scp->xsize - scp->xpos);
100858381Snyan		i = cnt;
100958381Snyan		do {
101058381Snyan		    /*
101158381Snyan		     * gcc-2.6.3 generates poor (un)sign extension code.
101258381Snyan		     * Casting the pointers in the following to volatile should
101358381Snyan		     * have no effect, but in fact speeds up this inner loop
101458381Snyan		     * from 26 to 18 cycles (+ cache misses) on i486's.
101558381Snyan		     */
101656337Skato#define	UCVP(ucp)	((u_char volatile *)(ucp))
101758381Snyan		    p = sc_vtb_putchar(&scp->vtb, p, UCVP(map)[*UCVP(ptr)],
101858381Snyan				       attr);
101958381Snyan		    ++ptr;
102058381Snyan		    --i;
102158381Snyan		} while (i > 0 && PRINTABLE(*ptr));
102256337Skato
102358381Snyan		len -= cnt - i;
102458381Snyan		mark_for_update(scp, scp->cursor_pos);
102558381Snyan		scp->cursor_pos += cnt - i;
102658381Snyan		mark_for_update(scp, scp->cursor_pos - 1);
102758381Snyan		scp->xpos += cnt - i;
102856337Skato#endif /* !KANJI */
102956337Skato
103058381Snyan		if (scp->xpos >= scp->xsize) {
103158381Snyan			scp->xpos = 0;
103258381Snyan			scp->ypos++;
103356337Skato		}
103458381Snyan	} else {
103558381Snyan		switch (*ptr) {
103658381Snyan		case 0x07:
103758381Snyan			sc_bell(scp, scp->bell_pitch, scp->bell_duration);
103858381Snyan			break;
103956337Skato
104058381Snyan		case 0x08:	/* non-destructive backspace */
104158381Snyan			if (scp->cursor_pos > 0) {
104258381Snyan				mark_for_update(scp, scp->cursor_pos);
104358381Snyan				scp->cursor_pos--;
104458381Snyan				mark_for_update(scp, scp->cursor_pos);
104558381Snyan				if (scp->xpos > 0)
104658381Snyan					scp->xpos--;
104758381Snyan				else {
104858381Snyan					scp->xpos += scp->xsize - 1;
104958381Snyan					scp->ypos--;
105058381Snyan				}
105158381Snyan			}
105258381Snyan			break;
105356337Skato
105458381Snyan		case 0x09:	/* non-destructive tab */
105558381Snyan			mark_for_update(scp, scp->cursor_pos);
105658381Snyan			scp->cursor_pos += (8 - scp->xpos % 8u);
105758381Snyan			scp->xpos += (8 - scp->xpos % 8u);
105858381Snyan			if (scp->xpos >= scp->xsize) {
105958381Snyan				scp->xpos = 0;
106058381Snyan				scp->ypos++;
106158381Snyan				scp->cursor_pos = scp->xsize * scp->ypos;
106258381Snyan			}
106358381Snyan			mark_for_update(scp, scp->cursor_pos);
106458381Snyan			break;
106556337Skato
106658381Snyan		case 0x0a:	/* newline, same pos */
106758381Snyan			mark_for_update(scp, scp->cursor_pos);
106858381Snyan			scp->cursor_pos += scp->xsize;
106958381Snyan			mark_for_update(scp, scp->cursor_pos);
107058381Snyan			scp->ypos++;
107158381Snyan			break;
107256337Skato
107358381Snyan		case 0x0c:	/* form feed, clears screen */
107458381Snyan			sc_clear_screen(scp);
107558381Snyan			break;
107656337Skato
107758381Snyan		case 0x0d:	/* return, return to pos 0 */
107858381Snyan			mark_for_update(scp, scp->cursor_pos);
107958381Snyan			scp->cursor_pos -= scp->xpos;
108058381Snyan			mark_for_update(scp, scp->cursor_pos);
108158381Snyan			scp->xpos = 0;
108258381Snyan			break;
108358381Snyan
108458381Snyan		case 0x0e:	/* ^N */
108590467Snyan			tcp->kanji_type = KTYPE_JKANA;
108690467Snyan			tcp->esc = 0;
108790467Snyan			tcp->kanji_1st_char = 0;
108890467Snyan			break;
108956337Skato
109058381Snyan		case 0x0f:	/* ^O */
109158381Snyan			tcp->kanji_type = KTYPE_ASCII;
109258381Snyan			tcp->esc = 0;
109358381Snyan			tcp->kanji_1st_char = 0;
109458381Snyan			break;
109556337Skato
109658381Snyan		case 0x1b:	/* start escape sequence */
109758381Snyan			tcp->esc = 1;
109858381Snyan			tcp->num_param = 0;
109958381Snyan			break;
110058381Snyan		}
110158381Snyan		ptr++;
110258381Snyan		len--;
110356337Skato	}
110456337Skato
110558381Snyan	sc_term_gen_scroll(scp, scp->sc->scr_map[0x20], tcp->cur_attr);
110656337Skato
110758381Snyan	scp->sc->write_in_progress--;
110858381Snyan	if (len)
110958381Snyan		goto outloop;
111056337Skato}
111156337Skato
111256337Skatostatic int
111356337Skatoscterm_ioctl(scr_stat *scp, struct tty *tp, u_long cmd, caddr_t data,
1114181905Sed	     struct thread *td)
111556337Skato{
111656337Skato	term_stat *tcp = scp->ts;
111756337Skato	vid_info_t *vi;
111856337Skato
111956337Skato	switch (cmd) {
112056337Skato	case GIO_ATTR:      	/* get current attributes */
112156337Skato		/* FIXME: */
112256337Skato		*(int*)data = (tcp->cur_attr >> 8) & 0xff;
112356337Skato		return 0;
112456337Skato	case CONS_GETINFO:  	/* get current (virtual) console info */
112556337Skato		vi = (vid_info_t *)data;
112656337Skato		if (vi->size != sizeof(struct vid_info))
112756337Skato			return EINVAL;
112856337Skato		vi->mv_norm.fore = tcp->std_color.fg;
112956337Skato		vi->mv_norm.back = tcp->std_color.bg;
113056337Skato		vi->mv_rev.fore = tcp->rev_color.fg;
113156337Skato		vi->mv_rev.back = tcp->rev_color.bg;
113256337Skato		/*
113356337Skato		 * The other fields are filled by the upper routine. XXX
113456337Skato		 */
113556337Skato		return ENOIOCTL;
113656337Skato	}
113756337Skato	return ENOIOCTL;
113856337Skato}
113956337Skato
114056337Skatostatic int
114156337Skatoscterm_reset(scr_stat *scp, int code)
114256337Skato{
114356337Skato	/* FIXME */
114456337Skato	return 0;
114556337Skato}
114656337Skato
114756337Skatostatic void
114856337Skatoscterm_default_attr(scr_stat *scp, int color, int rev_color)
114956337Skato{
115056337Skato	term_stat *tcp = scp->ts;
115156337Skato
115256337Skato	tcp->dflt_std_color.fg = color & 0x0f;
115356337Skato	tcp->dflt_std_color.bg = (color >> 4) & 0x0f;
115456337Skato	tcp->dflt_rev_color.fg = rev_color & 0x0f;
115556337Skato	tcp->dflt_rev_color.bg = (rev_color >> 4) & 0x0f;
115656337Skato	tcp->std_color = tcp->dflt_std_color;
115756337Skato	tcp->rev_color = tcp->dflt_rev_color;
115856337Skato	tcp->cur_color = tcp->std_color;
115956337Skato	tcp->cur_attr = mask2attr(tcp);
116056337Skato}
116156337Skato
116256337Skatostatic void
116356337Skatoscterm_clear(scr_stat *scp)
116456337Skato{
116556337Skato	term_stat *tcp = scp->ts;
116656337Skato
116756337Skato	sc_move_cursor(scp, 0, 0);
116856337Skato	sc_vtb_clear(&scp->vtb, scp->sc->scr_map[0x20], tcp->cur_attr);
116956337Skato	mark_all(scp);
117056337Skato}
117156337Skato
117256337Skatostatic void
117356337Skatoscterm_notify(scr_stat *scp, int event)
117456337Skato{
117556337Skato	switch (event) {
117656337Skato	case SC_TE_NOTIFY_VTSWITCH_IN:
117756337Skato		break;
117856337Skato	case SC_TE_NOTIFY_VTSWITCH_OUT:
117956337Skato		break;
118056337Skato	}
118156337Skato}
118256337Skato
118356337Skatostatic int
118456337Skatoscterm_input(scr_stat *scp, int c, struct tty *tp)
118556337Skato{
118656337Skato	return FALSE;
118756337Skato}
118856337Skato
1189199171Sedstatic const char *
1190199171Sedscterm_fkeystr(scr_stat *scp, int c)
1191199171Sed{
1192199171Sed
1193199171Sed	return (NULL);
1194199171Sed}
1195199171Sed
119656337Skato/*
119756337Skato * Calculate hardware attributes word using logical attributes mask and
119856337Skato * hardware colors
119956337Skato */
120056337Skato
120156337Skato/* FIXME */
120256337Skatostatic int
120356337Skatomask2attr(term_stat *tcp)
120456337Skato{
120556337Skato	int attr, mask = tcp->attr_mask;
120656337Skato
120756337Skato	if (mask & REVERSE_ATTR) {
120856337Skato		attr = ((mask & FG_CHANGED) ?
120956337Skato			tcp->cur_color.bg : tcp->rev_color.fg) |
121056337Skato			(((mask & BG_CHANGED) ?
121156337Skato			tcp->cur_color.fg : tcp->rev_color.bg) << 4);
121256337Skato	} else
121356337Skato		attr = tcp->cur_color.fg | (tcp->cur_color.bg << 4);
121456337Skato
121556337Skato	/* XXX: underline mapping for Hercules adapter can be better */
121656337Skato	if (mask & (BOLD_ATTR | UNDERLINE_ATTR))
121756337Skato		attr ^= 0x08;
121856337Skato	if (mask & BLINK_ATTR)
121956337Skato		attr ^= 0x80;
122056337Skato
122156337Skato	return (attr << 8);
122256337Skato}
1223