scterm-sck.c revision 64021
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 * $FreeBSD: head/sys/pc98/cbus/scterm-sck.c 64021 2000-07-30 08:12:08Z nyan $
2756337Skato */
2856337Skato
2956337Skato#include "opt_syscons.h"
3056337Skato
3156337Skato#include <sys/param.h>
3256337Skato#include <sys/systm.h>
3356337Skato#include <sys/kernel.h>
3456337Skato#include <sys/consio.h>
3556337Skato
3656337Skato#include <machine/pc/display.h>
3756337Skato
3856337Skato#include <dev/syscons/syscons.h>
3956337Skato#include <dev/syscons/sctermvar.h>
4056337Skato
4156337Skato#ifndef SC_DUMB_TERMINAL
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
9856337Skatostatic sc_term_init_t	scterm_init;
9956337Skatostatic sc_term_term_t	scterm_term;
10056337Skatostatic sc_term_puts_t	scterm_puts;
10156337Skatostatic sc_term_ioctl_t	scterm_ioctl;
10256337Skatostatic sc_term_reset_t	scterm_reset;
10356337Skatostatic sc_term_default_attr_t	scterm_default_attr;
10456337Skatostatic sc_term_clear_t	scterm_clear;
10556337Skatostatic sc_term_notify_t	scterm_notify;
10656337Skatostatic sc_term_input_t	scterm_input;
10756337Skato
10856337Skatostatic sc_term_sw_t sc_term_sc = {
10956337Skato	{ NULL, NULL },
11058381Snyan	"sck",					/* emulator name */
11158381Snyan	"syscons kanji terminal",		/* description */
11258381Snyan	"*",					/* matching renderer, any :-) */
11358381Snyan	sizeof(term_stat),			/* softc size */
11456337Skato	0,
11556337Skato	scterm_init,
11656337Skato	scterm_term,
11756337Skato	scterm_puts,
11856337Skato	scterm_ioctl,
11956337Skato	scterm_reset,
12056337Skato	scterm_default_attr,
12156337Skato	scterm_clear,
12256337Skato	scterm_notify,
12356337Skato	scterm_input,
12456337Skato};
12556337Skato
12656337SkatoSCTERM_MODULE(sc, sc_term_sc);
12756337Skato
12856337Skatostatic term_stat	reserved_term_stat;
12956337Skatostatic int		default_kanji = UJIS;
13056337Skatostatic void		scterm_scan_esc(scr_stat *scp, term_stat *tcp,
13156337Skato					u_char c);
13256337Skatostatic int		mask2attr(term_stat *tcp);
13356337Skatostatic u_char		iskanji1(u_char mode, u_char c);
13456337Skatostatic u_char		iskanji2(u_char mode, u_char c);
13556337Skatostatic u_short		kanji_convert(u_char mode, u_char h, u_char l);
13656337Skato
13756337Skatostatic int
13856337Skatoscterm_init(scr_stat *scp, void **softc, int code)
13956337Skato{
14056337Skato	term_stat *tcp;
14156337Skato
14256337Skato	if (*softc == NULL) {
14356337Skato		if (reserved_term_stat.flags & SCTERM_BUSY)
14456337Skato			return EINVAL;
14556337Skato		*softc = &reserved_term_stat;
14656337Skato	}
14756337Skato	tcp = *softc;
14856337Skato
14956337Skato	switch (code) {
15056337Skato	case SC_TE_COLD_INIT:
15156337Skato		bzero(tcp, sizeof(*tcp));
15256337Skato		tcp->flags = SCTERM_BUSY;
15356337Skato		tcp->esc = 0;
15456337Skato		tcp->saved_xpos = -1;
15556337Skato		tcp->saved_ypos = -1;
15656337Skato
15756337Skato#ifdef KANJI
15856337Skato		tcp->kanji_1st_char = 0;
15956337Skato		tcp->kanji_type = KTYPE_ASCII;
16056337Skato#endif
16156337Skato
16256337Skato		tcp->attr_mask = NORMAL_ATTR;
16356337Skato		/* XXX */
16456337Skato		tcp->dflt_std_color.fg = SC_NORM_ATTR & 0x0f;
16556337Skato		tcp->dflt_std_color.bg = (SC_NORM_ATTR >> 4) & 0x0f;
16656337Skato		tcp->dflt_rev_color.fg = SC_NORM_REV_ATTR & 0x0f;
16756337Skato		tcp->dflt_rev_color.bg = (SC_NORM_REV_ATTR >> 4) & 0x0f;
16856337Skato		tcp->std_color = tcp->dflt_std_color;
16956337Skato		tcp->rev_color = tcp->dflt_rev_color;
17056337Skato		tcp->cur_color = tcp->std_color;
17156337Skato		tcp->cur_attr = mask2attr(tcp);
17256337Skato		++sc_term_sc.te_refcount;
17356337Skato		break;
17456337Skato
17556337Skato	case SC_TE_WARM_INIT:
17656337Skato		tcp->esc = 0;
17756337Skato		tcp->saved_xpos = -1;
17856337Skato		tcp->saved_ypos = -1;
17957136Skato#if 0
18056337Skato		tcp->std_color = tcp->dflt_std_color;
18156337Skato		tcp->rev_color = tcp->dflt_rev_color;
18257136Skato#endif
18356337Skato		tcp->cur_color = tcp->std_color;
18456337Skato		tcp->cur_attr = mask2attr(tcp);
18556337Skato		break;
18656337Skato	}
18756337Skato
18856337Skato	return 0;
18956337Skato}
19056337Skato
19156337Skatostatic int
19256337Skatoscterm_term(scr_stat *scp, void **softc)
19356337Skato{
19456337Skato	if (*softc == &reserved_term_stat) {
19556337Skato		*softc = NULL;
19656337Skato		bzero(&reserved_term_stat, sizeof(reserved_term_stat));
19756337Skato	}
19856337Skato	--sc_term_sc.te_refcount;
19956337Skato	return 0;
20056337Skato}
20156337Skato
20256337Skatostatic void
20356337Skatoscterm_scan_esc(scr_stat *scp, term_stat *tcp, u_char c)
20456337Skato{
20556337Skato	static u_char ansi_col[16] = {
20656337Skato		FG_BLACK,     FG_RED,          FG_GREEN,      FG_BROWN,
20756337Skato		FG_BLUE,      FG_MAGENTA,      FG_CYAN,       FG_LIGHTGREY,
20856337Skato		FG_DARKGREY,  FG_LIGHTRED,     FG_LIGHTGREEN, FG_YELLOW,
20956337Skato		FG_LIGHTBLUE, FG_LIGHTMAGENTA, FG_LIGHTCYAN,  FG_WHITE
21058381Snyan	};
21156337Skato	sc_softc_t *sc;
21256337Skato	int i, n;
21356337Skato
21458381Snyan	i = n = 0;
21558381Snyan	sc = scp->sc;
21658381Snyan	if (tcp->esc == 1) {	/* seen ESC */
21759778Snyan#ifdef KANJI
21859778Snyan		switch (tcp->kanji_type) {
21959778Snyan		case KTYPE_KANIN:	/* Kanji Invoke sequence */
22059778Snyan			switch (c) {
22159778Snyan			case 'B':
22259778Snyan			case '@':
22359778Snyan				tcp->kanji_type = KTYPE_7JIS;
22459778Snyan				tcp->esc = 0;
22559778Snyan				tcp->kanji_1st_char = 0;
22659778Snyan				return;
22759778Snyan			default:
22859778Snyan				tcp->kanji_type = KTYPE_ASCII;
22959778Snyan				tcp->esc = 0;
23059778Snyan				break;
23159778Snyan			}
23259778Snyan			break;
23359778Snyan		case KTYPE_ASCIN:	/* Ascii Invoke sequence */
23459778Snyan			switch (c) {
23559778Snyan			case 'J':
23659778Snyan			case 'B':
23759778Snyan			case 'H':
23859778Snyan				tcp->kanji_type = KTYPE_ASCII;
23959778Snyan				tcp->esc = 0;
24059778Snyan				tcp->kanji_1st_char = 0;
24159778Snyan				return;
24259778Snyan			case 'I':
24359778Snyan				tcp->kanji_type = KTYPE_JKANA;
24459778Snyan				tcp->esc = 0;
24559778Snyan				tcp->kanji_1st_char = 0;
24659778Snyan				return;
24759778Snyan			default:
24859778Snyan				tcp->kanji_type = KTYPE_ASCII;
24959778Snyan				tcp->esc = 0;
25059778Snyan				break;
25159778Snyan			}
25259778Snyan			break;
25359778Snyan		default:
25459778Snyan			break;
25559778Snyan		}
25659778Snyan#endif
25758381Snyan		switch (c) {
25856337Skato
25958381Snyan		case '7':	/* Save cursor position */
26058381Snyan			tcp->saved_xpos = scp->xpos;
26158381Snyan			tcp->saved_ypos = scp->ypos;
26258381Snyan			break;
26356337Skato
26458381Snyan		case '8':	/* Restore saved cursor position */
26558381Snyan			if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0)
26658381Snyan				sc_move_cursor(scp, tcp->saved_xpos,
26758381Snyan					       tcp->saved_ypos);
26858381Snyan			break;
26956337Skato
27058381Snyan		case '[':	/* Start ESC [ sequence */
27158381Snyan			tcp->esc = 2;
27258381Snyan			tcp->last_param = -1;
27358381Snyan			for (i = tcp->num_param; i < MAX_ESC_PAR; i++)
27458381Snyan				tcp->param[i] = 1;
27558381Snyan			tcp->num_param = 0;
27658381Snyan			return;
27756337Skato
27856337Skato#ifdef KANJI
27958381Snyan		case '$':	/* Kanji Invoke sequence */
28058381Snyan			tcp->kanji_type = KTYPE_KANIN;
28158381Snyan			return;
28256337Skato#endif
28356337Skato
28458381Snyan		case 'M':	/* Move cursor up 1 line, scroll if at top */
28558381Snyan			sc_term_up_scroll(scp, 1, sc->scr_map[0x20],
28658381Snyan					  tcp->cur_attr, 0, 0);
28758381Snyan			break;
28856337Skato#if notyet
28958381Snyan		case 'Q':
29058381Snyan			tcp->esc = 4;
29158381Snyan			return;
29256337Skato#endif
29364021Snyan		case 'c':       /* reset */
29464021Snyan			tcp->attr_mask = NORMAL_ATTR;
29564021Snyan			tcp->cur_color = tcp->std_color
29664021Snyan				       = tcp->dflt_std_color;
29764021Snyan			tcp->rev_color = tcp->dflt_rev_color;
29864021Snyan			tcp->cur_attr = mask2attr(tcp);
29958381Snyan			sc_clear_screen(scp);
30058381Snyan			break;
30156337Skato
30258381Snyan		case '(':	/* iso-2022: designate 94 character set to G0 */
30356337Skato#ifdef KANJI
30458381Snyan			tcp->kanji_type = KTYPE_ASCIN;
30556337Skato#else
30658381Snyan			tcp->esc = 5;
30756337Skato#endif
30858381Snyan			return;
30956337Skato		}
31058381Snyan	} else if (tcp->esc == 2) {	/* seen ESC [ */
31158381Snyan		if (c >= '0' && c <= '9') {
31258381Snyan			if (tcp->num_param < MAX_ESC_PAR) {
31358381Snyan				if (tcp->last_param != tcp->num_param) {
31458381Snyan					tcp->last_param = tcp->num_param;
31558381Snyan					tcp->param[tcp->num_param] = 0;
31658381Snyan				} else {
31758381Snyan					tcp->param[tcp->num_param] *= 10;
31858381Snyan				}
31958381Snyan				tcp->param[tcp->num_param] += c - '0';
32058381Snyan				return;
32158381Snyan			}
32258381Snyan		}
32358381Snyan		tcp->num_param = tcp->last_param + 1;
32458381Snyan		switch (c) {
32556337Skato
32658381Snyan		case ';':
32758381Snyan			if (tcp->num_param < MAX_ESC_PAR)
32858381Snyan				return;
32958381Snyan			break;
33056337Skato
33158381Snyan		case '=':
33258381Snyan			tcp->esc = 3;
33358381Snyan			tcp->last_param = -1;
33458381Snyan			for (i = tcp->num_param; i < MAX_ESC_PAR; i++)
33558381Snyan				tcp->param[i] = 1;
33658381Snyan			tcp->num_param = 0;
33758381Snyan			return;
33856337Skato
33958381Snyan		case 'A':	/* up n rows */
34058381Snyan			sc_term_up(scp, tcp->param[0], 0);
34158381Snyan			break;
34256337Skato
34358381Snyan		case 'B':	/* down n rows */
34458381Snyan			sc_term_down(scp, tcp->param[0], 0);
34558381Snyan			break;
34656337Skato
34758381Snyan		case 'C':	/* right n columns */
34858381Snyan			sc_term_right(scp, tcp->param[0]);
34958381Snyan			break;
35056337Skato
35158381Snyan		case 'D':	/* left n columns */
35258381Snyan			sc_term_left(scp, tcp->param[0]);
35358381Snyan			break;
35456337Skato
35558381Snyan		case 'E':	/* cursor to start of line n lines down */
35658381Snyan			n = tcp->param[0];
35758381Snyan			if (n < 1)
35858381Snyan				n = 1;
35958381Snyan			sc_move_cursor(scp, 0, scp->ypos + n);
36058381Snyan			break;
36156337Skato
36258381Snyan		case 'F':	/* cursor to start of line n lines up */
36358381Snyan			n = tcp->param[0];
36458381Snyan			if (n < 1)
36558381Snyan				n = 1;
36658381Snyan			sc_move_cursor(scp, 0, scp->ypos - n);
36758381Snyan			break;
36856337Skato
36958381Snyan		case 'f':	/* Cursor move */
37058381Snyan		case 'H':
37158381Snyan			if (tcp->num_param == 0)
37258381Snyan				sc_move_cursor(scp, 0, 0);
37358381Snyan			else if (tcp->num_param == 2)
37458381Snyan				sc_move_cursor(scp, tcp->param[1] - 1,
37558381Snyan					       tcp->param[0] - 1);
37658381Snyan			break;
37756337Skato
37858381Snyan		case 'J':	/* Clear all or part of display */
37958381Snyan			if (tcp->num_param == 0)
38058381Snyan				n = 0;
38158381Snyan			else
38258381Snyan				n = tcp->param[0];
38358381Snyan			sc_term_clr_eos(scp, n, sc->scr_map[0x20],
38458381Snyan					tcp->cur_attr);
38558381Snyan			break;
38656337Skato
38758381Snyan		case 'K':	/* Clear all or part of line */
38858381Snyan			if (tcp->num_param == 0)
38958381Snyan				n = 0;
39058381Snyan			else
39158381Snyan				n = tcp->param[0];
39258381Snyan			sc_term_clr_eol(scp, n, sc->scr_map[0x20],
39358381Snyan					tcp->cur_attr);
39458381Snyan			break;
39556337Skato
39658381Snyan		case 'L':	/* Insert n lines */
39758381Snyan			sc_term_ins_line(scp, scp->ypos, tcp->param[0],
39858381Snyan					 sc->scr_map[0x20], tcp->cur_attr, 0);
39958381Snyan			break;
40056337Skato
40158381Snyan		case 'M':	/* Delete n lines */
40258381Snyan			sc_term_del_line(scp, scp->ypos, tcp->param[0],
40358381Snyan					 sc->scr_map[0x20], tcp->cur_attr, 0);
40458381Snyan			break;
40556337Skato
40658381Snyan		case 'P':	/* Delete n chars */
40758381Snyan			sc_term_del_char(scp, tcp->param[0],
40858381Snyan					 sc->scr_map[0x20], tcp->cur_attr);
40958381Snyan			break;
41056337Skato
41158381Snyan		case '@':	/* Insert n chars */
41258381Snyan			sc_term_ins_char(scp, tcp->param[0],
41358381Snyan					 sc->scr_map[0x20], tcp->cur_attr);
41458381Snyan			break;
41556337Skato
41658381Snyan		case 'S':	/* scroll up n lines */
41758381Snyan			sc_term_del_line(scp, 0, tcp->param[0],
41858381Snyan					 sc->scr_map[0x20], tcp->cur_attr, 0);
41958381Snyan			break;
42056337Skato
42158381Snyan		case 'T':	/* scroll down n lines */
42258381Snyan			sc_term_ins_line(scp, 0, tcp->param[0],
42358381Snyan					 sc->scr_map[0x20], tcp->cur_attr, 0);
42458381Snyan			break;
42556337Skato
42658381Snyan		case 'X':	/* erase n characters in line */
42758381Snyan			n = tcp->param[0];
42858381Snyan			if (n < 1)
42958381Snyan				n = 1;
43058381Snyan			if (n > scp->xsize - scp->xpos)
43158381Snyan				n = scp->xsize - scp->xpos;
43258381Snyan			sc_vtb_erase(&scp->vtb, scp->cursor_pos, n,
43358381Snyan				     sc->scr_map[0x20], tcp->cur_attr);
43458381Snyan			mark_for_update(scp, scp->cursor_pos);
43558381Snyan			mark_for_update(scp, scp->cursor_pos + n - 1);
43658381Snyan			break;
43756337Skato
43858381Snyan		case 'Z':	/* move n tabs backwards */
43958381Snyan			sc_term_backtab(scp, tcp->param[0]);
44058381Snyan			break;
44156337Skato
44258381Snyan		case '`':	/* move cursor to column n */
44358381Snyan			sc_term_col(scp, tcp->param[0]);
44458381Snyan			break;
44556337Skato
44658381Snyan		case 'a':	/* move cursor n columns to the right */
44758381Snyan			sc_term_right(scp, tcp->param[0]);
44858381Snyan			break;
44956337Skato
45058381Snyan		case 'd':	/* move cursor to row n */
45158381Snyan			sc_term_row(scp, tcp->param[0]);
45258381Snyan			break;
45356337Skato
45458381Snyan		case 'e':	/* move cursor n rows down */
45558381Snyan			sc_term_down(scp, tcp->param[0], 0);
45658381Snyan			break;
45756337Skato
45858381Snyan		case 'm':	/* change attribute */
45958381Snyan			if (tcp->num_param == 0) {
46058381Snyan				tcp->attr_mask = NORMAL_ATTR;
46158381Snyan				tcp->cur_color = tcp->std_color;
46258381Snyan				tcp->cur_attr = mask2attr(tcp);
46358381Snyan				break;
46458381Snyan			}
46558381Snyan			for (i = 0; i < tcp->num_param; i++) {
46658381Snyan				switch (n = tcp->param[i]) {
46758381Snyan				case 0:	/* back to normal */
46858381Snyan					tcp->attr_mask = NORMAL_ATTR;
46958381Snyan					tcp->cur_color = tcp->std_color;
47058381Snyan					tcp->cur_attr = mask2attr(tcp);
47158381Snyan					break;
47258381Snyan				case 1:	/* bold */
47358381Snyan					tcp->attr_mask |= BOLD_ATTR;
47458381Snyan					tcp->cur_attr = mask2attr(tcp);
47558381Snyan					break;
47658381Snyan				case 4:	/* underline */
47758381Snyan					tcp->attr_mask |= UNDERLINE_ATTR;
47858381Snyan					tcp->cur_attr = mask2attr(tcp);
47958381Snyan					break;
48058381Snyan				case 5:	/* blink */
48158381Snyan					tcp->attr_mask |= BLINK_ATTR;
48258381Snyan					tcp->cur_attr = mask2attr(tcp);
48358381Snyan					break;
48464021Snyan				case 7: /* reverse */
48558381Snyan					tcp->attr_mask |= REVERSE_ATTR;
48658381Snyan					tcp->cur_attr = mask2attr(tcp);
48758381Snyan					break;
48864021Snyan				case 22: /* remove bold (or dim) */
48964021Snyan					tcp->attr_mask &= ~BOLD_ATTR;
49064021Snyan					tcp->cur_attr = mask2attr(tcp);
49164021Snyan					break;
49264021Snyan				case 24: /* remove underline */
49364021Snyan					tcp->attr_mask &= ~UNDERLINE_ATTR;
49464021Snyan					tcp->cur_attr = mask2attr(tcp);
49564021Snyan					break;
49664021Snyan				case 25: /* remove blink */
49764021Snyan					tcp->attr_mask &= ~BLINK_ATTR;
49864021Snyan					tcp->cur_attr = mask2attr(tcp);
49964021Snyan					break;
50064021Snyan				case 27: /* remove reverse */
50164021Snyan					tcp->attr_mask &= ~REVERSE_ATTR;
50264021Snyan					tcp->cur_attr = mask2attr(tcp);
50364021Snyan					break;
50464021Snyan				case 30: case 31: /* set ansi fg color */
50558381Snyan				case 32: case 33: case 34:
50658381Snyan				case 35: case 36: case 37:
50758381Snyan					tcp->attr_mask |= FG_CHANGED;
50858381Snyan					tcp->cur_color.fg = ansi_col[n - 30];
50958381Snyan					tcp->cur_attr = mask2attr(tcp);
51058381Snyan					break;
51164021Snyan				case 39: /* restore fg color back to normal */
51264021Snyan					tcp->attr_mask &= ~(FG_CHANGED|BOLD_ATTR);
51361950Snyan					tcp->cur_color.fg = tcp->std_color.fg;
51461950Snyan					tcp->cur_attr = mask2attr(tcp);
51561950Snyan					break;
51664021Snyan				case 40: case 41: /* set ansi bg color */
51758381Snyan				case 42: case 43: case 44:
51858381Snyan				case 45: case 46: case 47:
51958381Snyan					tcp->attr_mask |= BG_CHANGED;
52058381Snyan					tcp->cur_color.bg = ansi_col[n - 40];
52158381Snyan					tcp->cur_attr = mask2attr(tcp);
52258381Snyan					break;
52364021Snyan				case 49: /* restore bg color back to normal */
52461950Snyan					tcp->attr_mask &= ~BG_CHANGED;
52561950Snyan					tcp->cur_color.bg = tcp->std_color.bg;
52661950Snyan					tcp->cur_attr = mask2attr(tcp);
52761950Snyan					break;
52858381Snyan				}
52958381Snyan			}
53058381Snyan			break;
53156337Skato
53258381Snyan		case 's':	/* Save cursor position */
53358381Snyan			tcp->saved_xpos = scp->xpos;
53458381Snyan			tcp->saved_ypos = scp->ypos;
53558381Snyan			break;
53656337Skato
53758381Snyan		case 'u':	/* Restore saved cursor position */
53858381Snyan			if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0)
53958381Snyan				sc_move_cursor(scp, tcp->saved_xpos,
54058381Snyan					       tcp->saved_ypos);
54158381Snyan			break;
54256337Skato
54358381Snyan		case 'x':
54458381Snyan			if (tcp->num_param == 0)
54558381Snyan				n = 0;
54658381Snyan			else
54758381Snyan				n = tcp->param[0];
54858381Snyan			switch (n) {
54964021Snyan			case 0: /* reset colors and attributes back to normal */
55058381Snyan				tcp->attr_mask = NORMAL_ATTR;
55158381Snyan				tcp->cur_color = tcp->std_color =
55258381Snyan				    tcp->dflt_std_color;
55358381Snyan				tcp->rev_color = tcp->dflt_rev_color;
55458381Snyan				tcp->cur_attr = mask2attr(tcp);
55558381Snyan				break;
55658381Snyan			case 1:	/* set ansi background */
55758381Snyan				tcp->attr_mask &= ~BG_CHANGED;
55858381Snyan				tcp->cur_color.bg = tcp->std_color.bg =
55958381Snyan				    ansi_col[tcp->param[1] & 0x0f];
56058381Snyan				tcp->cur_attr = mask2attr(tcp);
56158381Snyan				break;
56258381Snyan			case 2:	/* set ansi foreground */
56358381Snyan				tcp->attr_mask &= ~FG_CHANGED;
56458381Snyan				tcp->cur_color.fg = tcp->std_color.fg =
56558381Snyan				    ansi_col[tcp->param[1] & 0x0f];
56658381Snyan				tcp->cur_attr = mask2attr(tcp);
56758381Snyan				break;
56864021Snyan			case 3: /* set adapter attribute directly */
56958381Snyan				tcp->attr_mask &= ~(FG_CHANGED | BG_CHANGED);
57058381Snyan				tcp->cur_color.fg = tcp->std_color.fg =
57158381Snyan				    tcp->param[1] & 0x0f;
57258381Snyan				tcp->cur_color.bg = tcp->std_color.bg =
57358381Snyan				    (tcp->param[1] >> 4) & 0x0f;
57458381Snyan				tcp->cur_attr = mask2attr(tcp);
57558381Snyan				break;
57664021Snyan			case 5: /* set ansi reverse background */
57758381Snyan				tcp->rev_color.bg =
57858381Snyan				    ansi_col[tcp->param[1] & 0x0f];
57958381Snyan				tcp->cur_attr = mask2attr(tcp);
58058381Snyan				break;
58164021Snyan			case 6: /* set ansi reverse foreground */
58258381Snyan				tcp->rev_color.fg =
58358381Snyan				    ansi_col[tcp->param[1] & 0x0f];
58458381Snyan				tcp->cur_attr = mask2attr(tcp);
58558381Snyan				break;
58664021Snyan			case 7: /* set adapter reverse attribute directly */
58758381Snyan				tcp->rev_color.fg = tcp->param[1] & 0x0f;
58858381Snyan				tcp->rev_color.bg = (tcp->param[1] >> 4) & 0x0f;
58958381Snyan				tcp->cur_attr = mask2attr(tcp);
59058381Snyan				break;
59158381Snyan			}
59258381Snyan			break;
59356337Skato
59458381Snyan		case 'z':	/* switch to (virtual) console n */
59558381Snyan			if (tcp->num_param == 1)
59658381Snyan				sc_switch_scr(sc, tcp->param[0]);
59758381Snyan			break;
59856337Skato		}
59958381Snyan	} else if (tcp->esc == 3) {	/* seen ESC [0-9]+ = */
60058381Snyan		if (c >= '0' && c <= '9') {
60158381Snyan			if (tcp->num_param < MAX_ESC_PAR) {
60258381Snyan				if (tcp->last_param != tcp->num_param) {
60358381Snyan					tcp->last_param = tcp->num_param;
60458381Snyan					tcp->param[tcp->num_param] = 0;
60558381Snyan				} else {
60658381Snyan					tcp->param[tcp->num_param] *= 10;
60758381Snyan				}
60858381Snyan				tcp->param[tcp->num_param] += c - '0';
60958381Snyan				return;
61058381Snyan			}
61158381Snyan		}
61258381Snyan		tcp->num_param = tcp->last_param + 1;
61358381Snyan		switch (c) {
61456337Skato
61558381Snyan		case ';':
61658381Snyan			if (tcp->num_param < MAX_ESC_PAR)
61758381Snyan				return;
61858381Snyan			break;
61956337Skato
62058381Snyan		case 'A':   /* set display border color */
62158381Snyan			if (tcp->num_param == 1) {
62258381Snyan				scp->border=tcp->param[0] & 0xff;
62358381Snyan				if (scp == sc->cur_scp)
62458381Snyan					sc_set_border(scp, scp->border);
62558381Snyan			}
62658381Snyan			break;
62756337Skato
62858381Snyan		case 'B':   /* set bell pitch and duration */
62958381Snyan			if (tcp->num_param == 2) {
63058381Snyan				scp->bell_pitch = tcp->param[0];
63158381Snyan				scp->bell_duration = tcp->param[1];
63258381Snyan			}
63358381Snyan			break;
63456337Skato
63558381Snyan		case 'C':   /* set cursor type & shape */
63658381Snyan			i = spltty();
63758381Snyan			if (!ISGRAPHSC(sc->cur_scp))
63858381Snyan				sc_remove_cursor_image(sc->cur_scp);
63958381Snyan			if (tcp->num_param == 1) {
64058381Snyan				if (tcp->param[0] & 0x01)
64158381Snyan					sc->flags |= SC_BLINK_CURSOR;
64258381Snyan				else
64358381Snyan					sc->flags &= ~SC_BLINK_CURSOR;
64458381Snyan				if (tcp->param[0] & 0x02)
64558381Snyan					sc->flags |= SC_CHAR_CURSOR;
64658381Snyan				else
64758381Snyan					sc->flags &= ~SC_CHAR_CURSOR;
64858381Snyan			} else if (tcp->num_param == 2) {
64958381Snyan				sc->cursor_base = scp->font_size
65058381Snyan						- (tcp->param[1] & 0x1F) - 1;
65158381Snyan				sc->cursor_height = (tcp->param[1] & 0x1F)
65258381Snyan						- (tcp->param[0] & 0x1F) + 1;
65358381Snyan			}
65458381Snyan			/*
65558381Snyan			 * The cursor shape is global property;
65658381Snyan			 * all virtual consoles are affected.
65758381Snyan			 * Update the cursor in the current console...
65858381Snyan			 */
65958381Snyan			if (!ISGRAPHSC(sc->cur_scp)) {
66058381Snyan				sc_set_cursor_image(sc->cur_scp);
66158381Snyan				sc_draw_cursor_image(sc->cur_scp);
66258381Snyan			}
66358381Snyan			splx(i);
66458381Snyan			break;
66556337Skato
66664021Snyan		case 'F':   /* set adapter foreground */
66758381Snyan			if (tcp->num_param == 1) {
66858381Snyan				tcp->attr_mask &= ~FG_CHANGED;
66958381Snyan				tcp->cur_color.fg = tcp->std_color.fg =
67058381Snyan				    tcp->param[0] & 0x0f;
67158381Snyan				tcp->cur_attr = mask2attr(tcp);
67258381Snyan			}
67358381Snyan			break;
67456337Skato
67564021Snyan		case 'G':   /* set adapter background */
67658381Snyan			if (tcp->num_param == 1) {
67758381Snyan				tcp->attr_mask &= ~BG_CHANGED;
67858381Snyan				tcp->cur_color.bg = tcp->std_color.bg =
67958381Snyan				    tcp->param[0] & 0x0f;
68058381Snyan				tcp->cur_attr = mask2attr(tcp);
68158381Snyan			}
68258381Snyan			break;
68356337Skato
68464021Snyan		case 'H':   /* set adapter reverse foreground */
68558381Snyan			if (tcp->num_param == 1) {
68658381Snyan				tcp->rev_color.fg = tcp->param[0] & 0x0f;
68758381Snyan				tcp->cur_attr = mask2attr(tcp);
68858381Snyan			}
68958381Snyan			break;
69056337Skato
69164021Snyan		case 'I':   /* set adapter reverse background */
69258381Snyan			if (tcp->num_param == 1) {
69358381Snyan				tcp->rev_color.bg = tcp->param[0] & 0x0f;
69458381Snyan				tcp->cur_attr = mask2attr(tcp);
69558381Snyan			}
69658381Snyan			break;
69758381Snyan		}
69856337Skato#if notyet
69958381Snyan	} else if (tcp->esc == 4) {	/* seen ESC Q */
70058381Snyan		/* to be filled */
70156337Skato#endif
70258381Snyan	} else if (tcp->esc == 5) {	/* seen ESC ( */
70358381Snyan		switch (c) {
70458381Snyan		case 'B':   /* iso-2022: desginate ASCII into G0 */
70558381Snyan			break;
70658381Snyan		/* other items to be filled */
70758381Snyan		default:
70858381Snyan			break;
70958381Snyan		}
71056337Skato	}
71158381Snyan	tcp->esc = 0;
71256337Skato}
71356337Skato
71456337Skatostatic void
71556337Skatoscterm_puts(scr_stat *scp, u_char *buf, int len)
71656337Skato{
71756337Skato	term_stat *tcp = scp->ts;
71856337Skato	u_char *ptr = buf;
71956337Skato#ifdef KANJI
72056337Skato	u_short kanji_code;
72156337Skato#endif
72256337Skato
72356337Skatooutloop:
72458381Snyan	scp->sc->write_in_progress++;
72556337Skato
72658381Snyan	if (tcp->esc) {
72758381Snyan		scterm_scan_esc(scp, tcp, *ptr++);
72858381Snyan		len--;
72958381Snyan	} else if (PRINTABLE(*ptr)) {     /* Print only printables */
73058381Snyan		vm_offset_t p;
73158381Snyan		u_char *map;
73258381Snyan		int attr;
73358381Snyan		int i;
73456337Skato#ifdef KANJI
73558381Snyan		u_char c;
73656337Skato#else
73758381Snyan		int cnt;
73856337Skato#endif
73956337Skato
74058381Snyan		p = sc_vtb_pointer(&scp->vtb, scp->cursor_pos);
74158381Snyan		map = scp->sc->scr_map;
74258381Snyan		attr = tcp->cur_attr;
74356337Skato
74456337Skato#ifdef KANJI
74558381Snyan		c = *ptr;
74658381Snyan		if (tcp->kanji_1st_char == 0) {
74758381Snyan		    tcp->kanji_type = iskanji1(tcp->kanji_type, c);
74858381Snyan		    if (!IS_KTYPE_ASCII_or_HANKAKU(tcp->kanji_type)) {
74958381Snyan			/* not Ascii & not HANKAKU */
75058381Snyan			tcp->kanji_1st_char = c;
75158381Snyan			goto kanji_end;
75258381Snyan		    } else {
75358381Snyan			tcp->kanji_1st_char = 0;
75456337Skato		    }
75558381Snyan		} else {
75658381Snyan		    if ((tcp->kanji_type =
75758381Snyan			 iskanji2(tcp->kanji_type, c)) & 0xee) {
75858381Snyan			/* print kanji on TEXT VRAM */
75958381Snyan			kanji_code = kanji_convert(tcp->kanji_type, c,
76058381Snyan						   tcp->kanji_1st_char);
76158381Snyan			mark_for_update(scp, scp->cursor_pos);
76258381Snyan			for (i = 0; i < 2; i++) {
76358381Snyan			    /* *cursor_pos = (kanji_code | (i*0x80)); */
76458381Snyan			    p = sc_vtb_putchar(&scp->vtb, p,
76558381Snyan			       kanji_code | ((i == 0) ? 0x00 : 0x80), attr);
76658381Snyan			    ++scp->cursor_pos;
76758381Snyan			    if (++scp->xpos >= scp->xsize) {
76858381Snyan				scp->xpos = 0;
76958381Snyan				scp->ypos++;
77058381Snyan			    }
77158381Snyan			}
77258381Snyan			mark_for_update(scp, scp->cursor_pos - 1);
77358381Snyan			KTYPE_MASK_CTRL(tcp->kanji_type);
77458381Snyan			tcp->kanji_1st_char = 0;
77558381Snyan			goto kanji_end;
77658381Snyan		    } else {
77758381Snyan			tcp->kanji_1st_char = 0;
77858381Snyan		    }
77958381Snyan		}
78058381Snyan		if (IS_KTYPE_KANA(tcp->kanji_type))
78158381Snyan		    c |= 0x80;
78256337Skato		KTYPE_MASK_CTRL(tcp->kanji_type);
78358381Snyan		sc_vtb_putchar(&scp->vtb, p, map[c], attr);
78458381Snyan		mark_for_update(scp, scp->cursor_pos);
78558381Snyan		mark_for_update(scp, scp->cursor_pos);
78658381Snyan		++scp->cursor_pos;
78758381Snyan		++scp->xpos;
78856337Skatokanji_end:
78958381Snyan		++ptr;
79058381Snyan		--len;
79156337Skato#else /* !KANJI */
79258381Snyan		cnt = imin(len, scp->xsize - scp->xpos);
79358381Snyan		i = cnt;
79458381Snyan		do {
79558381Snyan		    /*
79658381Snyan		     * gcc-2.6.3 generates poor (un)sign extension code.
79758381Snyan		     * Casting the pointers in the following to volatile should
79858381Snyan		     * have no effect, but in fact speeds up this inner loop
79958381Snyan		     * from 26 to 18 cycles (+ cache misses) on i486's.
80058381Snyan		     */
80156337Skato#define	UCVP(ucp)	((u_char volatile *)(ucp))
80258381Snyan		    p = sc_vtb_putchar(&scp->vtb, p, UCVP(map)[*UCVP(ptr)],
80358381Snyan				       attr);
80458381Snyan		    ++ptr;
80558381Snyan		    --i;
80658381Snyan		} while (i > 0 && PRINTABLE(*ptr));
80756337Skato
80858381Snyan		len -= cnt - i;
80958381Snyan		mark_for_update(scp, scp->cursor_pos);
81058381Snyan		scp->cursor_pos += cnt - i;
81158381Snyan		mark_for_update(scp, scp->cursor_pos - 1);
81258381Snyan		scp->xpos += cnt - i;
81356337Skato#endif /* !KANJI */
81456337Skato
81558381Snyan		if (scp->xpos >= scp->xsize) {
81658381Snyan			scp->xpos = 0;
81758381Snyan			scp->ypos++;
81856337Skato		}
81958381Snyan	} else {
82058381Snyan		switch (*ptr) {
82158381Snyan		case 0x07:
82258381Snyan			sc_bell(scp, scp->bell_pitch, scp->bell_duration);
82358381Snyan			break;
82456337Skato
82558381Snyan		case 0x08:	/* non-destructive backspace */
82658381Snyan			if (scp->cursor_pos > 0) {
82758381Snyan				mark_for_update(scp, scp->cursor_pos);
82858381Snyan				scp->cursor_pos--;
82958381Snyan				mark_for_update(scp, scp->cursor_pos);
83058381Snyan				if (scp->xpos > 0)
83158381Snyan					scp->xpos--;
83258381Snyan				else {
83358381Snyan					scp->xpos += scp->xsize - 1;
83458381Snyan					scp->ypos--;
83558381Snyan				}
83658381Snyan			}
83758381Snyan			break;
83856337Skato
83958381Snyan		case 0x09:	/* non-destructive tab */
84058381Snyan			mark_for_update(scp, scp->cursor_pos);
84158381Snyan			scp->cursor_pos += (8 - scp->xpos % 8u);
84258381Snyan			scp->xpos += (8 - scp->xpos % 8u);
84358381Snyan			if (scp->xpos >= scp->xsize) {
84458381Snyan				scp->xpos = 0;
84558381Snyan				scp->ypos++;
84658381Snyan				scp->cursor_pos = scp->xsize * scp->ypos;
84758381Snyan			}
84858381Snyan			mark_for_update(scp, scp->cursor_pos);
84958381Snyan			break;
85056337Skato
85158381Snyan		case 0x0a:	/* newline, same pos */
85258381Snyan			mark_for_update(scp, scp->cursor_pos);
85358381Snyan			scp->cursor_pos += scp->xsize;
85458381Snyan			mark_for_update(scp, scp->cursor_pos);
85558381Snyan			scp->ypos++;
85658381Snyan			break;
85756337Skato
85858381Snyan		case 0x0c:	/* form feed, clears screen */
85958381Snyan			sc_clear_screen(scp);
86058381Snyan			break;
86156337Skato
86258381Snyan		case 0x0d:	/* return, return to pos 0 */
86358381Snyan			mark_for_update(scp, scp->cursor_pos);
86458381Snyan			scp->cursor_pos -= scp->xpos;
86558381Snyan			mark_for_update(scp, scp->cursor_pos);
86658381Snyan			scp->xpos = 0;
86758381Snyan			break;
86858381Snyan
86956337Skato#ifdef PC98
87058381Snyan		case 0x0e:	/* ^N */
87158381Snyan		tcp->kanji_type = KTYPE_JKANA;
87258381Snyan		tcp->esc = 0;
87358381Snyan		tcp->kanji_1st_char = 0;
87458381Snyan		break;
87556337Skato
87658381Snyan		case 0x0f:	/* ^O */
87758381Snyan			tcp->kanji_type = KTYPE_ASCII;
87858381Snyan			tcp->esc = 0;
87958381Snyan			tcp->kanji_1st_char = 0;
88058381Snyan			break;
88156337Skato#endif /* PC98 */
88256337Skato
88358381Snyan		case 0x1b:	/* start escape sequence */
88458381Snyan			tcp->esc = 1;
88558381Snyan			tcp->num_param = 0;
88658381Snyan			break;
88758381Snyan		}
88858381Snyan		ptr++;
88958381Snyan		len--;
89056337Skato	}
89156337Skato
89258381Snyan	sc_term_gen_scroll(scp, scp->sc->scr_map[0x20], tcp->cur_attr);
89356337Skato
89458381Snyan	scp->sc->write_in_progress--;
89558381Snyan	if (len)
89658381Snyan		goto outloop;
89756337Skato}
89856337Skato
89956337Skatostatic int
90056337Skatoscterm_ioctl(scr_stat *scp, struct tty *tp, u_long cmd, caddr_t data,
90156337Skato	     int flag, struct proc *p)
90256337Skato{
90356337Skato	term_stat *tcp = scp->ts;
90456337Skato	vid_info_t *vi;
90556337Skato
90656337Skato	switch (cmd) {
90756337Skato	case GIO_ATTR:      	/* get current attributes */
90856337Skato		/* FIXME: */
90956337Skato		*(int*)data = (tcp->cur_attr >> 8) & 0xff;
91056337Skato		return 0;
91156337Skato	case CONS_GETINFO:  	/* get current (virtual) console info */
91256337Skato		vi = (vid_info_t *)data;
91356337Skato		if (vi->size != sizeof(struct vid_info))
91456337Skato			return EINVAL;
91556337Skato		vi->mv_norm.fore = tcp->std_color.fg;
91656337Skato		vi->mv_norm.back = tcp->std_color.bg;
91756337Skato		vi->mv_rev.fore = tcp->rev_color.fg;
91856337Skato		vi->mv_rev.back = tcp->rev_color.bg;
91956337Skato		/*
92056337Skato		 * The other fields are filled by the upper routine. XXX
92156337Skato		 */
92256337Skato		return ENOIOCTL;
92356337Skato	}
92456337Skato	return ENOIOCTL;
92556337Skato}
92656337Skato
92756337Skatostatic int
92856337Skatoscterm_reset(scr_stat *scp, int code)
92956337Skato{
93056337Skato	/* FIXME */
93156337Skato	return 0;
93256337Skato}
93356337Skato
93456337Skatostatic void
93556337Skatoscterm_default_attr(scr_stat *scp, int color, int rev_color)
93656337Skato{
93756337Skato	term_stat *tcp = scp->ts;
93856337Skato
93956337Skato	tcp->dflt_std_color.fg = color & 0x0f;
94056337Skato	tcp->dflt_std_color.bg = (color >> 4) & 0x0f;
94156337Skato	tcp->dflt_rev_color.fg = rev_color & 0x0f;
94256337Skato	tcp->dflt_rev_color.bg = (rev_color >> 4) & 0x0f;
94356337Skato	tcp->std_color = tcp->dflt_std_color;
94456337Skato	tcp->rev_color = tcp->dflt_rev_color;
94556337Skato	tcp->cur_color = tcp->std_color;
94656337Skato	tcp->cur_attr = mask2attr(tcp);
94756337Skato}
94856337Skato
94956337Skatostatic void
95056337Skatoscterm_clear(scr_stat *scp)
95156337Skato{
95256337Skato	term_stat *tcp = scp->ts;
95356337Skato
95456337Skato	sc_move_cursor(scp, 0, 0);
95556337Skato	sc_vtb_clear(&scp->vtb, scp->sc->scr_map[0x20], tcp->cur_attr);
95656337Skato	mark_all(scp);
95756337Skato}
95856337Skato
95956337Skatostatic void
96056337Skatoscterm_notify(scr_stat *scp, int event)
96156337Skato{
96256337Skato	switch (event) {
96356337Skato	case SC_TE_NOTIFY_VTSWITCH_IN:
96456337Skato		break;
96556337Skato	case SC_TE_NOTIFY_VTSWITCH_OUT:
96656337Skato		break;
96756337Skato	}
96856337Skato}
96956337Skato
97056337Skatostatic int
97156337Skatoscterm_input(scr_stat *scp, int c, struct tty *tp)
97256337Skato{
97356337Skato	return FALSE;
97456337Skato}
97556337Skato
97656337Skato/*
97756337Skato * Calculate hardware attributes word using logical attributes mask and
97856337Skato * hardware colors
97956337Skato */
98056337Skato
98156337Skato/* FIXME */
98256337Skatostatic int
98356337Skatomask2attr(term_stat *tcp)
98456337Skato{
98556337Skato	int attr, mask = tcp->attr_mask;
98656337Skato
98756337Skato	if (mask & REVERSE_ATTR) {
98856337Skato		attr = ((mask & FG_CHANGED) ?
98956337Skato			tcp->cur_color.bg : tcp->rev_color.fg) |
99056337Skato			(((mask & BG_CHANGED) ?
99156337Skato			tcp->cur_color.fg : tcp->rev_color.bg) << 4);
99256337Skato	} else
99356337Skato		attr = tcp->cur_color.fg | (tcp->cur_color.bg << 4);
99456337Skato
99556337Skato	/* XXX: underline mapping for Hercules adapter can be better */
99656337Skato	if (mask & (BOLD_ATTR | UNDERLINE_ATTR))
99756337Skato		attr ^= 0x08;
99856337Skato	if (mask & BLINK_ATTR)
99956337Skato		attr ^= 0x80;
100056337Skato
100156337Skato	return (attr << 8);
100256337Skato}
100356337Skato
100456337Skato#ifdef KANJI
100556337Skatostatic u_char
100656337Skatoiskanji1(u_char mode, u_char c)
100756337Skato{
100856337Skato    if ((mode == KTYPE_7JIS) && (c >= 0x21) && (c <= 0x7e)) {
100956337Skato	/* JIS */
101056337Skato	default_kanji = UJIS;
101156337Skato	return KTYPE_7JIS;
101256337Skato    }
101356337Skato
101456337Skato    if ((mode == KTYPE_JKANA) && (c >= 0x21) && (c <= 0x5f)) {
101556337Skato	/* JIS HANKAKU */
101656337Skato	default_kanji = UJIS;
101756337Skato	return KTYPE_JKANA;
101856337Skato    }
101956337Skato
102056337Skato#if 1
102156337Skato    if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) {
102256337Skato	/* UJIS */
102356337Skato	return KTYPE_UJIS;
102456337Skato    }
102556337Skato#endif
102656337Skato
102756337Skato    if ((c >= 0x81) && (c <= 0x9f) && (c != 0x8e)) {
102856337Skato	/* SJIS */
102956337Skato	default_kanji = SJIS;
103056337Skato	return KTYPE_SJIS;
103156337Skato    }
103256337Skato
103356337Skato    if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == SJIS)) {
103456337Skato	/* SJIS HANKAKU */
103556337Skato	return KTYPE_KANA;
103656337Skato    }
103756337Skato
103856337Skato#if 0
103956337Skato    if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) {
104056337Skato	/* UJIS */
104156337Skato	return KTYPE_UJIS;
104256337Skato    }
104356337Skato#endif
104456337Skato
104556337Skato    if ((c >= 0xf0) && (c <= 0xfe)) {
104656337Skato	/* UJIS */
104756337Skato	default_kanji = UJIS;
104856337Skato	return KTYPE_UJIS;
104956337Skato    }
105056337Skato
105156337Skato    if ((c >= 0xe0) && (c <= 0xef)) {
105256337Skato	/* SJIS or UJIS */
105356337Skato	return KTYPE_SUJIS;
105456337Skato    }
105556337Skato
105656337Skato    if (c == 0x8e) {
105756337Skato	/* SJIS or UJIS HANKAKU */
105856337Skato	return KTYPE_SUKANA;
105956337Skato    }
106056337Skato
106156337Skato    return KTYPE_ASCII;
106256337Skato}
106356337Skato
106456337Skatostatic u_char
106556337Skatoiskanji2(u_char mode, u_char c)
106656337Skato{
106756337Skato    switch (mode) {
106856337Skato    case KTYPE_7JIS:
106956337Skato	if ((c >= 0x21) && (c <= 0x7e)) {
107056337Skato	    /* JIS */
107156337Skato	    return KTYPE_7JIS;
107256337Skato	}
107356337Skato	break;
107456337Skato    case KTYPE_SJIS:
107556337Skato	if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) {
107656337Skato	    /* SJIS */
107756337Skato	    return KTYPE_SJIS;
107856337Skato	}
107956337Skato	break;
108056337Skato    case KTYPE_UJIS:
108156337Skato	if ((c >= 0xa1) && (c <= 0xfe)) {
108256337Skato	    /* UJIS */
108356337Skato	    return KTYPE_UJIS;
108456337Skato	}
108556337Skato	break;
108656337Skato    case KTYPE_SUKANA:
108756337Skato	if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) {
108856337Skato	    /* UJIS HANKAKU */
108956337Skato	    return KTYPE_KANA;
109056337Skato	}
109156337Skato	if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) {
109256337Skato	    /* SJIS */
109356337Skato	    default_kanji = SJIS;
109456337Skato	    return KTYPE_SJIS;
109556337Skato	}
109656337Skato	break;
109756337Skato    case KTYPE_SUJIS:
109856337Skato	if ((c >= 0x40) && (c <= 0xa0) && (c != 0x7f)) {
109956337Skato	    /* SJIS */
110056337Skato	    default_kanji = SJIS;
110156337Skato	    return KTYPE_SJIS;
110256337Skato	}
110356337Skato	if ((c == 0xfd) || (c == 0xfe)) {
110456337Skato	    /* UJIS */
110556337Skato	    default_kanji = UJIS;
110656337Skato	    return KTYPE_UJIS;
110756337Skato	}
110856337Skato	if ((c >= 0xa1) && (c <= 0xfc)) {
110956337Skato	    if (default_kanji == SJIS)
111056337Skato		return KTYPE_SJIS;
111156337Skato	    if (default_kanji == UJIS)
111256337Skato		return KTYPE_UJIS;
111356337Skato	}
111456337Skato	break;
111556337Skato    }
111656337Skato    return KTYPE_ASCII;
111756337Skato}
111856337Skato
111956337Skato/*
112056337Skato * JIS X0208-83 keisen conversion table
112156337Skato */
112256337Skatostatic u_short keiConv[32] = {
112356337Skato	0x240c, 0x260c, 0x300c, 0x340c, 0x3c0c, 0x380c, 0x400c, 0x500c,
112456337Skato	0x480c, 0x580c, 0x600c, 0x250c, 0x270c, 0x330c, 0x370c, 0x3f0c,
112556337Skato	0x3b0c, 0x470c, 0x570c, 0x4f0c, 0x5f0c, 0x6f0c, 0x440c, 0x530c,
112656337Skato	0x4c0c, 0x5b0c, 0x630c, 0x410c, 0x540c, 0x490c, 0x5c0c, 0x660c
112756337Skato};
112856337Skato
112956337Skatostatic u_short
113056337Skatokanji_convert(u_char mode, u_char h, u_char l)
113156337Skato{
113256337Skato    u_short tmp, high, low, c;
113356337Skato    high = (u_short) h;
113456337Skato    low  = (u_short) l;
113556337Skato
113656337Skato    switch (mode) {
113756337Skato    case KTYPE_SJIS: /* SHIFT JIS */
113856337Skato	if (low >= 0xe0) {
113956337Skato	    low -= 0x40;
114056337Skato	}
114156337Skato	low = (low - 0x81) * 2 + 0x21;
114256337Skato	if (high > 0x7f) {
114356337Skato	    high--;
114456337Skato	}
114556337Skato	if (high > 0x9d) {
114656337Skato	    low++;
114756337Skato	    high -= 0x9e - 0x21;
114856337Skato	} else {
114956337Skato	    high -= 0x40 - 0x21;
115056337Skato	}
115156337Skato	high &= 0x7F;
115256337Skato	low  &= 0x7F;
115356337Skato	tmp = ((high << 8) | low) - 0x20;
115456337Skato	break;
115556337Skato    case KTYPE_7JIS: /* JIS */
115656337Skato    case KTYPE_UJIS: /* UJIS */
115756337Skato	high &= 0x7F;
115856337Skato	low &= 0x7F;
115956337Skato	tmp = ((high << 8) | low) - 0x20;
116056337Skato	break;
116156337Skato    default:
116256337Skato	tmp = 0;
116356337Skato	break;
116456337Skato    }
116556337Skato
116656337Skato    /* keisen */
116756337Skato    c = ((tmp & 0xff) << 8) | (tmp >> 8);
116856337Skato    /* 0x2821 .. 0x2840 */
116956337Skato    if (0x0821 <= c && c <= 0x0840)
117056337Skato    tmp = keiConv[c - 0x0821];
117156337Skato
117256337Skato    return (tmp);
117356337Skato}
117456337Skato#endif /* KANJI */
117556337Skato
117656337Skato#endif /* SC_DUMB_TERMINAL */
1177