scterm-sck.c revision 59778
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 59778 2000-04-30 08:40:43Z 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
29358381Snyan		case 'c':	/* Clear screen & home */
29458381Snyan			sc_clear_screen(scp);
29558381Snyan			break;
29656337Skato
29758381Snyan		case '(':	/* iso-2022: designate 94 character set to G0 */
29856337Skato#ifdef KANJI
29958381Snyan			tcp->kanji_type = KTYPE_ASCIN;
30056337Skato#else
30158381Snyan			tcp->esc = 5;
30256337Skato#endif
30358381Snyan			return;
30456337Skato		}
30558381Snyan	} else if (tcp->esc == 2) {	/* seen ESC [ */
30658381Snyan		if (c >= '0' && c <= '9') {
30758381Snyan			if (tcp->num_param < MAX_ESC_PAR) {
30858381Snyan				if (tcp->last_param != tcp->num_param) {
30958381Snyan					tcp->last_param = tcp->num_param;
31058381Snyan					tcp->param[tcp->num_param] = 0;
31158381Snyan				} else {
31258381Snyan					tcp->param[tcp->num_param] *= 10;
31358381Snyan				}
31458381Snyan				tcp->param[tcp->num_param] += c - '0';
31558381Snyan				return;
31658381Snyan			}
31758381Snyan		}
31858381Snyan		tcp->num_param = tcp->last_param + 1;
31958381Snyan		switch (c) {
32056337Skato
32158381Snyan		case ';':
32258381Snyan			if (tcp->num_param < MAX_ESC_PAR)
32358381Snyan				return;
32458381Snyan			break;
32556337Skato
32658381Snyan		case '=':
32758381Snyan			tcp->esc = 3;
32858381Snyan			tcp->last_param = -1;
32958381Snyan			for (i = tcp->num_param; i < MAX_ESC_PAR; i++)
33058381Snyan				tcp->param[i] = 1;
33158381Snyan			tcp->num_param = 0;
33258381Snyan			return;
33356337Skato
33458381Snyan		case 'A':	/* up n rows */
33558381Snyan			sc_term_up(scp, tcp->param[0], 0);
33658381Snyan			break;
33756337Skato
33858381Snyan		case 'B':	/* down n rows */
33958381Snyan			sc_term_down(scp, tcp->param[0], 0);
34058381Snyan			break;
34156337Skato
34258381Snyan		case 'C':	/* right n columns */
34358381Snyan			sc_term_right(scp, tcp->param[0]);
34458381Snyan			break;
34556337Skato
34658381Snyan		case 'D':	/* left n columns */
34758381Snyan			sc_term_left(scp, tcp->param[0]);
34858381Snyan			break;
34956337Skato
35058381Snyan		case 'E':	/* cursor to start of line n lines down */
35158381Snyan			n = tcp->param[0];
35258381Snyan			if (n < 1)
35358381Snyan				n = 1;
35458381Snyan			sc_move_cursor(scp, 0, scp->ypos + n);
35558381Snyan			break;
35656337Skato
35758381Snyan		case 'F':	/* cursor to start of line n lines up */
35858381Snyan			n = tcp->param[0];
35958381Snyan			if (n < 1)
36058381Snyan				n = 1;
36158381Snyan			sc_move_cursor(scp, 0, scp->ypos - n);
36258381Snyan			break;
36356337Skato
36458381Snyan		case 'f':	/* Cursor move */
36558381Snyan		case 'H':
36658381Snyan			if (tcp->num_param == 0)
36758381Snyan				sc_move_cursor(scp, 0, 0);
36858381Snyan			else if (tcp->num_param == 2)
36958381Snyan				sc_move_cursor(scp, tcp->param[1] - 1,
37058381Snyan					       tcp->param[0] - 1);
37158381Snyan			break;
37256337Skato
37358381Snyan		case 'J':	/* Clear all or part of display */
37458381Snyan			if (tcp->num_param == 0)
37558381Snyan				n = 0;
37658381Snyan			else
37758381Snyan				n = tcp->param[0];
37858381Snyan			sc_term_clr_eos(scp, n, sc->scr_map[0x20],
37958381Snyan					tcp->cur_attr);
38058381Snyan			break;
38156337Skato
38258381Snyan		case 'K':	/* Clear all or part of line */
38358381Snyan			if (tcp->num_param == 0)
38458381Snyan				n = 0;
38558381Snyan			else
38658381Snyan				n = tcp->param[0];
38758381Snyan			sc_term_clr_eol(scp, n, sc->scr_map[0x20],
38858381Snyan					tcp->cur_attr);
38958381Snyan			break;
39056337Skato
39158381Snyan		case 'L':	/* Insert n lines */
39258381Snyan			sc_term_ins_line(scp, scp->ypos, tcp->param[0],
39358381Snyan					 sc->scr_map[0x20], tcp->cur_attr, 0);
39458381Snyan			break;
39556337Skato
39658381Snyan		case 'M':	/* Delete n lines */
39758381Snyan			sc_term_del_line(scp, scp->ypos, tcp->param[0],
39858381Snyan					 sc->scr_map[0x20], tcp->cur_attr, 0);
39958381Snyan			break;
40056337Skato
40158381Snyan		case 'P':	/* Delete n chars */
40258381Snyan			sc_term_del_char(scp, tcp->param[0],
40358381Snyan					 sc->scr_map[0x20], tcp->cur_attr);
40458381Snyan			break;
40556337Skato
40658381Snyan		case '@':	/* Insert n chars */
40758381Snyan			sc_term_ins_char(scp, tcp->param[0],
40858381Snyan					 sc->scr_map[0x20], tcp->cur_attr);
40958381Snyan			break;
41056337Skato
41158381Snyan		case 'S':	/* scroll up n lines */
41258381Snyan			sc_term_del_line(scp, 0, tcp->param[0],
41358381Snyan					 sc->scr_map[0x20], tcp->cur_attr, 0);
41458381Snyan			break;
41556337Skato
41658381Snyan		case 'T':	/* scroll down n lines */
41758381Snyan			sc_term_ins_line(scp, 0, tcp->param[0],
41858381Snyan					 sc->scr_map[0x20], tcp->cur_attr, 0);
41958381Snyan			break;
42056337Skato
42158381Snyan		case 'X':	/* erase n characters in line */
42258381Snyan			n = tcp->param[0];
42358381Snyan			if (n < 1)
42458381Snyan				n = 1;
42558381Snyan			if (n > scp->xsize - scp->xpos)
42658381Snyan				n = scp->xsize - scp->xpos;
42758381Snyan			sc_vtb_erase(&scp->vtb, scp->cursor_pos, n,
42858381Snyan				     sc->scr_map[0x20], tcp->cur_attr);
42958381Snyan			mark_for_update(scp, scp->cursor_pos);
43058381Snyan			mark_for_update(scp, scp->cursor_pos + n - 1);
43158381Snyan			break;
43256337Skato
43358381Snyan		case 'Z':	/* move n tabs backwards */
43458381Snyan			sc_term_backtab(scp, tcp->param[0]);
43558381Snyan			break;
43656337Skato
43758381Snyan		case '`':	/* move cursor to column n */
43858381Snyan			sc_term_col(scp, tcp->param[0]);
43958381Snyan			break;
44056337Skato
44158381Snyan		case 'a':	/* move cursor n columns to the right */
44258381Snyan			sc_term_right(scp, tcp->param[0]);
44358381Snyan			break;
44456337Skato
44558381Snyan		case 'd':	/* move cursor to row n */
44658381Snyan			sc_term_row(scp, tcp->param[0]);
44758381Snyan			break;
44856337Skato
44958381Snyan		case 'e':	/* move cursor n rows down */
45058381Snyan			sc_term_down(scp, tcp->param[0], 0);
45158381Snyan			break;
45256337Skato
45358381Snyan		case 'm':	/* change attribute */
45458381Snyan			if (tcp->num_param == 0) {
45558381Snyan				tcp->attr_mask = NORMAL_ATTR;
45658381Snyan				tcp->cur_color = tcp->std_color;
45758381Snyan				tcp->cur_attr = mask2attr(tcp);
45858381Snyan				break;
45958381Snyan			}
46058381Snyan			for (i = 0; i < tcp->num_param; i++) {
46158381Snyan				switch (n = tcp->param[i]) {
46258381Snyan				case 0:	/* back to normal */
46358381Snyan					tcp->attr_mask = NORMAL_ATTR;
46458381Snyan					tcp->cur_color = tcp->std_color;
46558381Snyan					tcp->cur_attr = mask2attr(tcp);
46658381Snyan					break;
46758381Snyan				case 1:	/* bold */
46858381Snyan					tcp->attr_mask |= BOLD_ATTR;
46958381Snyan					tcp->cur_attr = mask2attr(tcp);
47058381Snyan					break;
47158381Snyan				case 4:	/* underline */
47258381Snyan					tcp->attr_mask |= UNDERLINE_ATTR;
47358381Snyan					tcp->cur_attr = mask2attr(tcp);
47458381Snyan					break;
47558381Snyan				case 5:	/* blink */
47658381Snyan					tcp->attr_mask |= BLINK_ATTR;
47758381Snyan					tcp->cur_attr = mask2attr(tcp);
47858381Snyan					break;
47958381Snyan				case 7:	/* reverse video */
48058381Snyan					tcp->attr_mask |= REVERSE_ATTR;
48158381Snyan					tcp->cur_attr = mask2attr(tcp);
48258381Snyan					break;
48358381Snyan				case 30: case 31: /* set fg color */
48458381Snyan				case 32: case 33: case 34:
48558381Snyan				case 35: case 36: case 37:
48658381Snyan					tcp->attr_mask |= FG_CHANGED;
48758381Snyan					tcp->cur_color.fg = ansi_col[n - 30];
48858381Snyan					tcp->cur_attr = mask2attr(tcp);
48958381Snyan					break;
49058381Snyan				case 40: case 41: /* set bg color */
49158381Snyan				case 42: case 43: case 44:
49258381Snyan				case 45: case 46: case 47:
49358381Snyan					tcp->attr_mask |= BG_CHANGED;
49458381Snyan					tcp->cur_color.bg = ansi_col[n - 40];
49558381Snyan					tcp->cur_attr = mask2attr(tcp);
49658381Snyan					break;
49758381Snyan				}
49858381Snyan			}
49958381Snyan			break;
50056337Skato
50158381Snyan		case 's':	/* Save cursor position */
50258381Snyan			tcp->saved_xpos = scp->xpos;
50358381Snyan			tcp->saved_ypos = scp->ypos;
50458381Snyan			break;
50556337Skato
50658381Snyan		case 'u':	/* Restore saved cursor position */
50758381Snyan			if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0)
50858381Snyan				sc_move_cursor(scp, tcp->saved_xpos,
50958381Snyan					       tcp->saved_ypos);
51058381Snyan			break;
51156337Skato
51258381Snyan		case 'x':
51358381Snyan			if (tcp->num_param == 0)
51458381Snyan				n = 0;
51558381Snyan			else
51658381Snyan				n = tcp->param[0];
51758381Snyan			switch (n) {
51858381Snyan			case 0:	/* reset attributes */
51958381Snyan				tcp->attr_mask = NORMAL_ATTR;
52058381Snyan				tcp->cur_color = tcp->std_color =
52158381Snyan				    tcp->dflt_std_color;
52258381Snyan				tcp->rev_color = tcp->dflt_rev_color;
52358381Snyan				tcp->cur_attr = mask2attr(tcp);
52458381Snyan				break;
52558381Snyan			case 1:	/* set ansi background */
52658381Snyan				tcp->attr_mask &= ~BG_CHANGED;
52758381Snyan				tcp->cur_color.bg = tcp->std_color.bg =
52858381Snyan				    ansi_col[tcp->param[1] & 0x0f];
52958381Snyan				tcp->cur_attr = mask2attr(tcp);
53058381Snyan				break;
53158381Snyan			case 2:	/* set ansi foreground */
53258381Snyan				tcp->attr_mask &= ~FG_CHANGED;
53358381Snyan				tcp->cur_color.fg = tcp->std_color.fg =
53458381Snyan				    ansi_col[tcp->param[1] & 0x0f];
53558381Snyan				tcp->cur_attr = mask2attr(tcp);
53658381Snyan				break;
53758381Snyan			case 3:	/* set ansi attribute directly */
53858381Snyan				tcp->attr_mask &= ~(FG_CHANGED | BG_CHANGED);
53958381Snyan				tcp->cur_color.fg = tcp->std_color.fg =
54058381Snyan				    tcp->param[1] & 0x0f;
54158381Snyan				tcp->cur_color.bg = tcp->std_color.bg =
54258381Snyan				    (tcp->param[1] >> 4) & 0x0f;
54358381Snyan				tcp->cur_attr = mask2attr(tcp);
54458381Snyan				break;
54558381Snyan			case 5:	/* set ansi reverse video background */
54658381Snyan				tcp->rev_color.bg =
54758381Snyan				    ansi_col[tcp->param[1] & 0x0f];
54858381Snyan				tcp->cur_attr = mask2attr(tcp);
54958381Snyan				break;
55058381Snyan			case 6:	/* set ansi reverse video foreground */
55158381Snyan				tcp->rev_color.fg =
55258381Snyan				    ansi_col[tcp->param[1] & 0x0f];
55358381Snyan				tcp->cur_attr = mask2attr(tcp);
55458381Snyan				break;
55558381Snyan			case 7:	/* set ansi reverse video directly */
55658381Snyan				tcp->rev_color.fg = tcp->param[1] & 0x0f;
55758381Snyan				tcp->rev_color.bg = (tcp->param[1] >> 4) & 0x0f;
55858381Snyan				tcp->cur_attr = mask2attr(tcp);
55958381Snyan				break;
56058381Snyan			}
56158381Snyan			break;
56256337Skato
56358381Snyan		case 'z':	/* switch to (virtual) console n */
56458381Snyan			if (tcp->num_param == 1)
56558381Snyan				sc_switch_scr(sc, tcp->param[0]);
56658381Snyan			break;
56756337Skato		}
56858381Snyan	} else if (tcp->esc == 3) {	/* seen ESC [0-9]+ = */
56958381Snyan		if (c >= '0' && c <= '9') {
57058381Snyan			if (tcp->num_param < MAX_ESC_PAR) {
57158381Snyan				if (tcp->last_param != tcp->num_param) {
57258381Snyan					tcp->last_param = tcp->num_param;
57358381Snyan					tcp->param[tcp->num_param] = 0;
57458381Snyan				} else {
57558381Snyan					tcp->param[tcp->num_param] *= 10;
57658381Snyan				}
57758381Snyan				tcp->param[tcp->num_param] += c - '0';
57858381Snyan				return;
57958381Snyan			}
58058381Snyan		}
58158381Snyan		tcp->num_param = tcp->last_param + 1;
58258381Snyan		switch (c) {
58356337Skato
58458381Snyan		case ';':
58558381Snyan			if (tcp->num_param < MAX_ESC_PAR)
58658381Snyan				return;
58758381Snyan			break;
58856337Skato
58958381Snyan		case 'A':   /* set display border color */
59058381Snyan			if (tcp->num_param == 1) {
59158381Snyan				scp->border=tcp->param[0] & 0xff;
59258381Snyan				if (scp == sc->cur_scp)
59358381Snyan					sc_set_border(scp, scp->border);
59458381Snyan			}
59558381Snyan			break;
59656337Skato
59758381Snyan		case 'B':   /* set bell pitch and duration */
59858381Snyan			if (tcp->num_param == 2) {
59958381Snyan				scp->bell_pitch = tcp->param[0];
60058381Snyan				scp->bell_duration = tcp->param[1];
60158381Snyan			}
60258381Snyan			break;
60356337Skato
60458381Snyan		case 'C':   /* set cursor type & shape */
60558381Snyan			i = spltty();
60658381Snyan			if (!ISGRAPHSC(sc->cur_scp))
60758381Snyan				sc_remove_cursor_image(sc->cur_scp);
60858381Snyan			if (tcp->num_param == 1) {
60958381Snyan				if (tcp->param[0] & 0x01)
61058381Snyan					sc->flags |= SC_BLINK_CURSOR;
61158381Snyan				else
61258381Snyan					sc->flags &= ~SC_BLINK_CURSOR;
61358381Snyan				if (tcp->param[0] & 0x02)
61458381Snyan					sc->flags |= SC_CHAR_CURSOR;
61558381Snyan				else
61658381Snyan					sc->flags &= ~SC_CHAR_CURSOR;
61758381Snyan			} else if (tcp->num_param == 2) {
61858381Snyan				sc->cursor_base = scp->font_size
61958381Snyan						- (tcp->param[1] & 0x1F) - 1;
62058381Snyan				sc->cursor_height = (tcp->param[1] & 0x1F)
62158381Snyan						- (tcp->param[0] & 0x1F) + 1;
62258381Snyan			}
62358381Snyan			/*
62458381Snyan			 * The cursor shape is global property;
62558381Snyan			 * all virtual consoles are affected.
62658381Snyan			 * Update the cursor in the current console...
62758381Snyan			 */
62858381Snyan			if (!ISGRAPHSC(sc->cur_scp)) {
62958381Snyan				sc_set_cursor_image(sc->cur_scp);
63058381Snyan				sc_draw_cursor_image(sc->cur_scp);
63158381Snyan			}
63258381Snyan			splx(i);
63358381Snyan			break;
63456337Skato
63558381Snyan		case 'F':   /* set ansi foreground */
63658381Snyan			if (tcp->num_param == 1) {
63758381Snyan				tcp->attr_mask &= ~FG_CHANGED;
63858381Snyan				tcp->cur_color.fg = tcp->std_color.fg =
63958381Snyan				    tcp->param[0] & 0x0f;
64058381Snyan				tcp->cur_attr = mask2attr(tcp);
64158381Snyan			}
64258381Snyan			break;
64356337Skato
64458381Snyan		case 'G':   /* set ansi background */
64558381Snyan			if (tcp->num_param == 1) {
64658381Snyan				tcp->attr_mask &= ~BG_CHANGED;
64758381Snyan				tcp->cur_color.bg = tcp->std_color.bg =
64858381Snyan				    tcp->param[0] & 0x0f;
64958381Snyan				tcp->cur_attr = mask2attr(tcp);
65058381Snyan			}
65158381Snyan			break;
65256337Skato
65358381Snyan		case 'H':   /* set ansi reverse video foreground */
65458381Snyan			if (tcp->num_param == 1) {
65558381Snyan				tcp->rev_color.fg = tcp->param[0] & 0x0f;
65658381Snyan				tcp->cur_attr = mask2attr(tcp);
65758381Snyan			}
65858381Snyan			break;
65956337Skato
66058381Snyan		case 'I':   /* set ansi reverse video background */
66158381Snyan			if (tcp->num_param == 1) {
66258381Snyan				tcp->rev_color.bg = tcp->param[0] & 0x0f;
66358381Snyan				tcp->cur_attr = mask2attr(tcp);
66458381Snyan			}
66558381Snyan			break;
66658381Snyan		}
66756337Skato#if notyet
66858381Snyan	} else if (tcp->esc == 4) {	/* seen ESC Q */
66958381Snyan		/* to be filled */
67056337Skato#endif
67158381Snyan	} else if (tcp->esc == 5) {	/* seen ESC ( */
67258381Snyan		switch (c) {
67358381Snyan		case 'B':   /* iso-2022: desginate ASCII into G0 */
67458381Snyan			break;
67558381Snyan		/* other items to be filled */
67658381Snyan		default:
67758381Snyan			break;
67858381Snyan		}
67956337Skato	}
68058381Snyan	tcp->esc = 0;
68156337Skato}
68256337Skato
68356337Skatostatic void
68456337Skatoscterm_puts(scr_stat *scp, u_char *buf, int len)
68556337Skato{
68656337Skato	term_stat *tcp = scp->ts;
68756337Skato	u_char *ptr = buf;
68856337Skato#ifdef KANJI
68956337Skato	u_short kanji_code;
69056337Skato#endif
69156337Skato
69256337Skatooutloop:
69358381Snyan	scp->sc->write_in_progress++;
69456337Skato
69558381Snyan	if (tcp->esc) {
69658381Snyan		scterm_scan_esc(scp, tcp, *ptr++);
69758381Snyan		len--;
69858381Snyan	} else if (PRINTABLE(*ptr)) {     /* Print only printables */
69958381Snyan		vm_offset_t p;
70058381Snyan		u_char *map;
70158381Snyan		int attr;
70258381Snyan		int i;
70356337Skato#ifdef KANJI
70458381Snyan		u_char c;
70556337Skato#else
70658381Snyan		int cnt;
70756337Skato#endif
70856337Skato
70958381Snyan		p = sc_vtb_pointer(&scp->vtb, scp->cursor_pos);
71058381Snyan		map = scp->sc->scr_map;
71158381Snyan		attr = tcp->cur_attr;
71256337Skato
71356337Skato#ifdef KANJI
71458381Snyan		c = *ptr;
71558381Snyan		if (tcp->kanji_1st_char == 0) {
71658381Snyan		    tcp->kanji_type = iskanji1(tcp->kanji_type, c);
71758381Snyan		    if (!IS_KTYPE_ASCII_or_HANKAKU(tcp->kanji_type)) {
71858381Snyan			/* not Ascii & not HANKAKU */
71958381Snyan			tcp->kanji_1st_char = c;
72058381Snyan			goto kanji_end;
72158381Snyan		    } else {
72258381Snyan			tcp->kanji_1st_char = 0;
72356337Skato		    }
72458381Snyan		} else {
72558381Snyan		    if ((tcp->kanji_type =
72658381Snyan			 iskanji2(tcp->kanji_type, c)) & 0xee) {
72758381Snyan			/* print kanji on TEXT VRAM */
72858381Snyan			kanji_code = kanji_convert(tcp->kanji_type, c,
72958381Snyan						   tcp->kanji_1st_char);
73058381Snyan			mark_for_update(scp, scp->cursor_pos);
73158381Snyan			for (i = 0; i < 2; i++) {
73258381Snyan			    /* *cursor_pos = (kanji_code | (i*0x80)); */
73358381Snyan			    p = sc_vtb_putchar(&scp->vtb, p,
73458381Snyan			       kanji_code | ((i == 0) ? 0x00 : 0x80), attr);
73558381Snyan			    ++scp->cursor_pos;
73658381Snyan			    if (++scp->xpos >= scp->xsize) {
73758381Snyan				scp->xpos = 0;
73858381Snyan				scp->ypos++;
73958381Snyan			    }
74058381Snyan			}
74158381Snyan			mark_for_update(scp, scp->cursor_pos - 1);
74258381Snyan			KTYPE_MASK_CTRL(tcp->kanji_type);
74358381Snyan			tcp->kanji_1st_char = 0;
74458381Snyan			goto kanji_end;
74558381Snyan		    } else {
74658381Snyan			tcp->kanji_1st_char = 0;
74758381Snyan		    }
74858381Snyan		}
74958381Snyan		if (IS_KTYPE_KANA(tcp->kanji_type))
75058381Snyan		    c |= 0x80;
75156337Skato		KTYPE_MASK_CTRL(tcp->kanji_type);
75258381Snyan		sc_vtb_putchar(&scp->vtb, p, map[c], attr);
75358381Snyan		mark_for_update(scp, scp->cursor_pos);
75458381Snyan		mark_for_update(scp, scp->cursor_pos);
75558381Snyan		++scp->cursor_pos;
75658381Snyan		++scp->xpos;
75756337Skatokanji_end:
75858381Snyan		++ptr;
75958381Snyan		--len;
76056337Skato#else /* !KANJI */
76158381Snyan		cnt = imin(len, scp->xsize - scp->xpos);
76258381Snyan		i = cnt;
76358381Snyan		do {
76458381Snyan		    /*
76558381Snyan		     * gcc-2.6.3 generates poor (un)sign extension code.
76658381Snyan		     * Casting the pointers in the following to volatile should
76758381Snyan		     * have no effect, but in fact speeds up this inner loop
76858381Snyan		     * from 26 to 18 cycles (+ cache misses) on i486's.
76958381Snyan		     */
77056337Skato#define	UCVP(ucp)	((u_char volatile *)(ucp))
77158381Snyan		    p = sc_vtb_putchar(&scp->vtb, p, UCVP(map)[*UCVP(ptr)],
77258381Snyan				       attr);
77358381Snyan		    ++ptr;
77458381Snyan		    --i;
77558381Snyan		} while (i > 0 && PRINTABLE(*ptr));
77656337Skato
77758381Snyan		len -= cnt - i;
77858381Snyan		mark_for_update(scp, scp->cursor_pos);
77958381Snyan		scp->cursor_pos += cnt - i;
78058381Snyan		mark_for_update(scp, scp->cursor_pos - 1);
78158381Snyan		scp->xpos += cnt - i;
78256337Skato#endif /* !KANJI */
78356337Skato
78458381Snyan		if (scp->xpos >= scp->xsize) {
78558381Snyan			scp->xpos = 0;
78658381Snyan			scp->ypos++;
78756337Skato		}
78858381Snyan	} else {
78958381Snyan		switch (*ptr) {
79058381Snyan		case 0x07:
79158381Snyan			sc_bell(scp, scp->bell_pitch, scp->bell_duration);
79258381Snyan			break;
79356337Skato
79458381Snyan		case 0x08:	/* non-destructive backspace */
79558381Snyan			if (scp->cursor_pos > 0) {
79658381Snyan				mark_for_update(scp, scp->cursor_pos);
79758381Snyan				scp->cursor_pos--;
79858381Snyan				mark_for_update(scp, scp->cursor_pos);
79958381Snyan				if (scp->xpos > 0)
80058381Snyan					scp->xpos--;
80158381Snyan				else {
80258381Snyan					scp->xpos += scp->xsize - 1;
80358381Snyan					scp->ypos--;
80458381Snyan				}
80558381Snyan			}
80658381Snyan			break;
80756337Skato
80858381Snyan		case 0x09:	/* non-destructive tab */
80958381Snyan			mark_for_update(scp, scp->cursor_pos);
81058381Snyan			scp->cursor_pos += (8 - scp->xpos % 8u);
81158381Snyan			scp->xpos += (8 - scp->xpos % 8u);
81258381Snyan			if (scp->xpos >= scp->xsize) {
81358381Snyan				scp->xpos = 0;
81458381Snyan				scp->ypos++;
81558381Snyan				scp->cursor_pos = scp->xsize * scp->ypos;
81658381Snyan			}
81758381Snyan			mark_for_update(scp, scp->cursor_pos);
81858381Snyan			break;
81956337Skato
82058381Snyan		case 0x0a:	/* newline, same pos */
82158381Snyan			mark_for_update(scp, scp->cursor_pos);
82258381Snyan			scp->cursor_pos += scp->xsize;
82358381Snyan			mark_for_update(scp, scp->cursor_pos);
82458381Snyan			scp->ypos++;
82558381Snyan			break;
82656337Skato
82758381Snyan		case 0x0c:	/* form feed, clears screen */
82858381Snyan			sc_clear_screen(scp);
82958381Snyan			break;
83056337Skato
83158381Snyan		case 0x0d:	/* return, return to pos 0 */
83258381Snyan			mark_for_update(scp, scp->cursor_pos);
83358381Snyan			scp->cursor_pos -= scp->xpos;
83458381Snyan			mark_for_update(scp, scp->cursor_pos);
83558381Snyan			scp->xpos = 0;
83658381Snyan			break;
83758381Snyan
83856337Skato#ifdef PC98
83958381Snyan		case 0x0e:	/* ^N */
84058381Snyan		tcp->kanji_type = KTYPE_JKANA;
84158381Snyan		tcp->esc = 0;
84258381Snyan		tcp->kanji_1st_char = 0;
84358381Snyan		break;
84456337Skato
84558381Snyan		case 0x0f:	/* ^O */
84658381Snyan			tcp->kanji_type = KTYPE_ASCII;
84758381Snyan			tcp->esc = 0;
84858381Snyan			tcp->kanji_1st_char = 0;
84958381Snyan			break;
85056337Skato#endif /* PC98 */
85156337Skato
85258381Snyan		case 0x1b:	/* start escape sequence */
85358381Snyan			tcp->esc = 1;
85458381Snyan			tcp->num_param = 0;
85558381Snyan			break;
85658381Snyan		}
85758381Snyan		ptr++;
85858381Snyan		len--;
85956337Skato	}
86056337Skato
86158381Snyan	sc_term_gen_scroll(scp, scp->sc->scr_map[0x20], tcp->cur_attr);
86256337Skato
86358381Snyan	scp->sc->write_in_progress--;
86458381Snyan	if (len)
86558381Snyan		goto outloop;
86656337Skato}
86756337Skato
86856337Skatostatic int
86956337Skatoscterm_ioctl(scr_stat *scp, struct tty *tp, u_long cmd, caddr_t data,
87056337Skato	     int flag, struct proc *p)
87156337Skato{
87256337Skato	term_stat *tcp = scp->ts;
87356337Skato	vid_info_t *vi;
87456337Skato
87556337Skato	switch (cmd) {
87656337Skato	case GIO_ATTR:      	/* get current attributes */
87756337Skato		/* FIXME: */
87856337Skato		*(int*)data = (tcp->cur_attr >> 8) & 0xff;
87956337Skato		return 0;
88056337Skato	case CONS_GETINFO:  	/* get current (virtual) console info */
88156337Skato		vi = (vid_info_t *)data;
88256337Skato		if (vi->size != sizeof(struct vid_info))
88356337Skato			return EINVAL;
88456337Skato		vi->mv_norm.fore = tcp->std_color.fg;
88556337Skato		vi->mv_norm.back = tcp->std_color.bg;
88656337Skato		vi->mv_rev.fore = tcp->rev_color.fg;
88756337Skato		vi->mv_rev.back = tcp->rev_color.bg;
88856337Skato		/*
88956337Skato		 * The other fields are filled by the upper routine. XXX
89056337Skato		 */
89156337Skato		return ENOIOCTL;
89256337Skato	}
89356337Skato	return ENOIOCTL;
89456337Skato}
89556337Skato
89656337Skatostatic int
89756337Skatoscterm_reset(scr_stat *scp, int code)
89856337Skato{
89956337Skato	/* FIXME */
90056337Skato	return 0;
90156337Skato}
90256337Skato
90356337Skatostatic void
90456337Skatoscterm_default_attr(scr_stat *scp, int color, int rev_color)
90556337Skato{
90656337Skato	term_stat *tcp = scp->ts;
90756337Skato
90856337Skato	tcp->dflt_std_color.fg = color & 0x0f;
90956337Skato	tcp->dflt_std_color.bg = (color >> 4) & 0x0f;
91056337Skato	tcp->dflt_rev_color.fg = rev_color & 0x0f;
91156337Skato	tcp->dflt_rev_color.bg = (rev_color >> 4) & 0x0f;
91256337Skato	tcp->std_color = tcp->dflt_std_color;
91356337Skato	tcp->rev_color = tcp->dflt_rev_color;
91456337Skato	tcp->cur_color = tcp->std_color;
91556337Skato	tcp->cur_attr = mask2attr(tcp);
91656337Skato}
91756337Skato
91856337Skatostatic void
91956337Skatoscterm_clear(scr_stat *scp)
92056337Skato{
92156337Skato	term_stat *tcp = scp->ts;
92256337Skato
92356337Skato	sc_move_cursor(scp, 0, 0);
92456337Skato	sc_vtb_clear(&scp->vtb, scp->sc->scr_map[0x20], tcp->cur_attr);
92556337Skato	mark_all(scp);
92656337Skato}
92756337Skato
92856337Skatostatic void
92956337Skatoscterm_notify(scr_stat *scp, int event)
93056337Skato{
93156337Skato	switch (event) {
93256337Skato	case SC_TE_NOTIFY_VTSWITCH_IN:
93356337Skato		break;
93456337Skato	case SC_TE_NOTIFY_VTSWITCH_OUT:
93556337Skato		break;
93656337Skato	}
93756337Skato}
93856337Skato
93956337Skatostatic int
94056337Skatoscterm_input(scr_stat *scp, int c, struct tty *tp)
94156337Skato{
94256337Skato	return FALSE;
94356337Skato}
94456337Skato
94556337Skato/*
94656337Skato * Calculate hardware attributes word using logical attributes mask and
94756337Skato * hardware colors
94856337Skato */
94956337Skato
95056337Skato/* FIXME */
95156337Skatostatic int
95256337Skatomask2attr(term_stat *tcp)
95356337Skato{
95456337Skato	int attr, mask = tcp->attr_mask;
95556337Skato
95656337Skato	if (mask & REVERSE_ATTR) {
95756337Skato		attr = ((mask & FG_CHANGED) ?
95856337Skato			tcp->cur_color.bg : tcp->rev_color.fg) |
95956337Skato			(((mask & BG_CHANGED) ?
96056337Skato			tcp->cur_color.fg : tcp->rev_color.bg) << 4);
96156337Skato	} else
96256337Skato		attr = tcp->cur_color.fg | (tcp->cur_color.bg << 4);
96356337Skato
96456337Skato	/* XXX: underline mapping for Hercules adapter can be better */
96556337Skato	if (mask & (BOLD_ATTR | UNDERLINE_ATTR))
96656337Skato		attr ^= 0x08;
96756337Skato	if (mask & BLINK_ATTR)
96856337Skato		attr ^= 0x80;
96956337Skato
97056337Skato	return (attr << 8);
97156337Skato}
97256337Skato
97356337Skato#ifdef KANJI
97456337Skatostatic u_char
97556337Skatoiskanji1(u_char mode, u_char c)
97656337Skato{
97756337Skato    if ((mode == KTYPE_7JIS) && (c >= 0x21) && (c <= 0x7e)) {
97856337Skato	/* JIS */
97956337Skato	default_kanji = UJIS;
98056337Skato	return KTYPE_7JIS;
98156337Skato    }
98256337Skato
98356337Skato    if ((mode == KTYPE_JKANA) && (c >= 0x21) && (c <= 0x5f)) {
98456337Skato	/* JIS HANKAKU */
98556337Skato	default_kanji = UJIS;
98656337Skato	return KTYPE_JKANA;
98756337Skato    }
98856337Skato
98956337Skato#if 1
99056337Skato    if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) {
99156337Skato	/* UJIS */
99256337Skato	return KTYPE_UJIS;
99356337Skato    }
99456337Skato#endif
99556337Skato
99656337Skato    if ((c >= 0x81) && (c <= 0x9f) && (c != 0x8e)) {
99756337Skato	/* SJIS */
99856337Skato	default_kanji = SJIS;
99956337Skato	return KTYPE_SJIS;
100056337Skato    }
100156337Skato
100256337Skato    if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == SJIS)) {
100356337Skato	/* SJIS HANKAKU */
100456337Skato	return KTYPE_KANA;
100556337Skato    }
100656337Skato
100756337Skato#if 0
100856337Skato    if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) {
100956337Skato	/* UJIS */
101056337Skato	return KTYPE_UJIS;
101156337Skato    }
101256337Skato#endif
101356337Skato
101456337Skato    if ((c >= 0xf0) && (c <= 0xfe)) {
101556337Skato	/* UJIS */
101656337Skato	default_kanji = UJIS;
101756337Skato	return KTYPE_UJIS;
101856337Skato    }
101956337Skato
102056337Skato    if ((c >= 0xe0) && (c <= 0xef)) {
102156337Skato	/* SJIS or UJIS */
102256337Skato	return KTYPE_SUJIS;
102356337Skato    }
102456337Skato
102556337Skato    if (c == 0x8e) {
102656337Skato	/* SJIS or UJIS HANKAKU */
102756337Skato	return KTYPE_SUKANA;
102856337Skato    }
102956337Skato
103056337Skato    return KTYPE_ASCII;
103156337Skato}
103256337Skato
103356337Skatostatic u_char
103456337Skatoiskanji2(u_char mode, u_char c)
103556337Skato{
103656337Skato    switch (mode) {
103756337Skato    case KTYPE_7JIS:
103856337Skato	if ((c >= 0x21) && (c <= 0x7e)) {
103956337Skato	    /* JIS */
104056337Skato	    return KTYPE_7JIS;
104156337Skato	}
104256337Skato	break;
104356337Skato    case KTYPE_SJIS:
104456337Skato	if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) {
104556337Skato	    /* SJIS */
104656337Skato	    return KTYPE_SJIS;
104756337Skato	}
104856337Skato	break;
104956337Skato    case KTYPE_UJIS:
105056337Skato	if ((c >= 0xa1) && (c <= 0xfe)) {
105156337Skato	    /* UJIS */
105256337Skato	    return KTYPE_UJIS;
105356337Skato	}
105456337Skato	break;
105556337Skato    case KTYPE_SUKANA:
105656337Skato	if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) {
105756337Skato	    /* UJIS HANKAKU */
105856337Skato	    return KTYPE_KANA;
105956337Skato	}
106056337Skato	if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) {
106156337Skato	    /* SJIS */
106256337Skato	    default_kanji = SJIS;
106356337Skato	    return KTYPE_SJIS;
106456337Skato	}
106556337Skato	break;
106656337Skato    case KTYPE_SUJIS:
106756337Skato	if ((c >= 0x40) && (c <= 0xa0) && (c != 0x7f)) {
106856337Skato	    /* SJIS */
106956337Skato	    default_kanji = SJIS;
107056337Skato	    return KTYPE_SJIS;
107156337Skato	}
107256337Skato	if ((c == 0xfd) || (c == 0xfe)) {
107356337Skato	    /* UJIS */
107456337Skato	    default_kanji = UJIS;
107556337Skato	    return KTYPE_UJIS;
107656337Skato	}
107756337Skato	if ((c >= 0xa1) && (c <= 0xfc)) {
107856337Skato	    if (default_kanji == SJIS)
107956337Skato		return KTYPE_SJIS;
108056337Skato	    if (default_kanji == UJIS)
108156337Skato		return KTYPE_UJIS;
108256337Skato	}
108356337Skato	break;
108456337Skato    }
108556337Skato    return KTYPE_ASCII;
108656337Skato}
108756337Skato
108856337Skato/*
108956337Skato * JIS X0208-83 keisen conversion table
109056337Skato */
109156337Skatostatic u_short keiConv[32] = {
109256337Skato	0x240c, 0x260c, 0x300c, 0x340c, 0x3c0c, 0x380c, 0x400c, 0x500c,
109356337Skato	0x480c, 0x580c, 0x600c, 0x250c, 0x270c, 0x330c, 0x370c, 0x3f0c,
109456337Skato	0x3b0c, 0x470c, 0x570c, 0x4f0c, 0x5f0c, 0x6f0c, 0x440c, 0x530c,
109556337Skato	0x4c0c, 0x5b0c, 0x630c, 0x410c, 0x540c, 0x490c, 0x5c0c, 0x660c
109656337Skato};
109756337Skato
109856337Skatostatic u_short
109956337Skatokanji_convert(u_char mode, u_char h, u_char l)
110056337Skato{
110156337Skato    u_short tmp, high, low, c;
110256337Skato    high = (u_short) h;
110356337Skato    low  = (u_short) l;
110456337Skato
110556337Skato    switch (mode) {
110656337Skato    case KTYPE_SJIS: /* SHIFT JIS */
110756337Skato	if (low >= 0xe0) {
110856337Skato	    low -= 0x40;
110956337Skato	}
111056337Skato	low = (low - 0x81) * 2 + 0x21;
111156337Skato	if (high > 0x7f) {
111256337Skato	    high--;
111356337Skato	}
111456337Skato	if (high > 0x9d) {
111556337Skato	    low++;
111656337Skato	    high -= 0x9e - 0x21;
111756337Skato	} else {
111856337Skato	    high -= 0x40 - 0x21;
111956337Skato	}
112056337Skato	high &= 0x7F;
112156337Skato	low  &= 0x7F;
112256337Skato	tmp = ((high << 8) | low) - 0x20;
112356337Skato	break;
112456337Skato    case KTYPE_7JIS: /* JIS */
112556337Skato    case KTYPE_UJIS: /* UJIS */
112656337Skato	high &= 0x7F;
112756337Skato	low &= 0x7F;
112856337Skato	tmp = ((high << 8) | low) - 0x20;
112956337Skato	break;
113056337Skato    default:
113156337Skato	tmp = 0;
113256337Skato	break;
113356337Skato    }
113456337Skato
113556337Skato    /* keisen */
113656337Skato    c = ((tmp & 0xff) << 8) | (tmp >> 8);
113756337Skato    /* 0x2821 .. 0x2840 */
113856337Skato    if (0x0821 <= c && c <= 0x0840)
113956337Skato    tmp = keiConv[c - 0x0821];
114056337Skato
114156337Skato    return (tmp);
114256337Skato}
114356337Skato#endif /* KANJI */
114456337Skato
114556337Skato#endif /* SC_DUMB_TERMINAL */
1146