scterm-sck.c revision 57136
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 57136 2000-02-11 08:54:16Z kato $
2756337Skato */
2856337Skato
2956337Skato#include "sc.h"
3056337Skato#include "opt_syscons.h"
3156337Skato
3256337Skato#if NSC > 0
3356337Skato
3456337Skato#include <sys/param.h>
3556337Skato#include <sys/systm.h>
3656337Skato#include <sys/kernel.h>
3756337Skato#include <sys/consio.h>
3856337Skato
3956337Skato#include <machine/pc/display.h>
4056337Skato
4156337Skato#include <dev/syscons/syscons.h>
4256337Skato#include <dev/syscons/sctermvar.h>
4356337Skato
4456337Skato#ifndef SC_DUMB_TERMINAL
4556337Skato
4656337Skato#define MAX_ESC_PAR	5
4756337Skato
4856337Skato#ifdef KANJI
4956337Skato#define IS_KTYPE_ASCII_or_HANKAKU(A)	(!((A) & 0xee))
5056337Skato#define IS_KTYPE_KANA(A)		((A) & 0x11)
5156337Skato#define KTYPE_MASK_CTRL(A)		((A) &= 0xF0)
5256337Skato#endif /* KANJI */
5356337Skato
5456337Skato/* attribute flags */
5556337Skatotypedef struct {
5656337Skato	u_short		fg;			/* foreground color */
5756337Skato	u_short		bg;			/* background color */
5856337Skato} color_t;
5956337Skato
6056337Skatotypedef struct {
6156337Skato	int		flags;
6256337Skato#define SCTERM_BUSY	(1 << 0)
6356337Skato	int		esc;
6456337Skato	int		num_param;
6556337Skato	int		last_param;
6656337Skato	int		param[MAX_ESC_PAR];
6756337Skato	int		saved_xpos;
6856337Skato	int		saved_ypos;
6956337Skato
7056337Skato#ifdef KANJI
7156337Skato	u_char		kanji_1st_char;
7256337Skato	u_char		kanji_type;
7356337Skato#define KTYPE_ASCII	0			/* ASCII */
7456337Skato#define KTYPE_KANA	1			/* HANKAKU */
7556337Skato#define KTYPE_JKANA	0x10			/* JIS HANKAKU */
7656337Skato#define KTYPE_7JIS	0x20			/* JIS */
7756337Skato#define KTYPE_SJIS	2			/* Shift JIS */
7856337Skato#define KTYPE_UJIS	4			/* UJIS */
7956337Skato#define KTYPE_SUKANA	3			/* Shift JIS or UJIS HANKAKU */
8056337Skato#define KTYPE_SUJIS	6			/* SHift JIS or UJIS */
8156337Skato#define KTYPE_KANIN	0x80			/* Kanji Invoke sequence */
8256337Skato#define KTYPE_ASCIN	0x40			/* ASCII Invoke sequence */
8356337Skato#endif /* KANJI */
8456337Skato
8556337Skato	int		attr_mask;		/* current logical attr mask */
8656337Skato#define NORMAL_ATTR	0x00
8756337Skato#define BLINK_ATTR	0x01
8856337Skato#define BOLD_ATTR	0x02
8956337Skato#define UNDERLINE_ATTR	0x04
9056337Skato#define REVERSE_ATTR	0x08
9156337Skato#define FG_CHANGED	0x10
9256337Skato#define BG_CHANGED	0x20
9356337Skato	int		cur_attr;		/* current hardware attr word */
9456337Skato	color_t		cur_color;		/* current hardware color */
9556337Skato	color_t		std_color;		/* normal hardware color */
9656337Skato	color_t		rev_color;		/* reverse hardware color */
9756337Skato	color_t		dflt_std_color;		/* default normal color */
9856337Skato	color_t		dflt_rev_color;		/* default reverse color */
9956337Skato} term_stat;
10056337Skato
10156337Skatostatic sc_term_init_t	scterm_init;
10256337Skatostatic sc_term_term_t	scterm_term;
10356337Skatostatic sc_term_puts_t	scterm_puts;
10456337Skatostatic sc_term_ioctl_t	scterm_ioctl;
10556337Skatostatic sc_term_reset_t	scterm_reset;
10656337Skatostatic sc_term_default_attr_t	scterm_default_attr;
10756337Skatostatic sc_term_clear_t	scterm_clear;
10856337Skatostatic sc_term_notify_t	scterm_notify;
10956337Skatostatic sc_term_input_t	scterm_input;
11056337Skato
11156337Skatostatic sc_term_sw_t sc_term_sc = {
11256337Skato	{ NULL, NULL },
11356337Skato	"sck",				/* emulator name */
11456337Skato	"syscons kanji terminal",	/* description */
11556337Skato	"*",				/* matching renderer, any :-) */
11656337Skato	sizeof(term_stat),		/* softc size */
11756337Skato	0,
11856337Skato	scterm_init,
11956337Skato	scterm_term,
12056337Skato	scterm_puts,
12156337Skato	scterm_ioctl,
12256337Skato	scterm_reset,
12356337Skato	scterm_default_attr,
12456337Skato	scterm_clear,
12556337Skato	scterm_notify,
12656337Skato	scterm_input,
12756337Skato};
12856337Skato
12956337SkatoSCTERM_MODULE(sc, sc_term_sc);
13056337Skato
13156337Skatostatic term_stat	reserved_term_stat;
13256337Skatostatic int		default_kanji = UJIS;
13356337Skatostatic void		scterm_scan_esc(scr_stat *scp, term_stat *tcp,
13456337Skato					u_char c);
13556337Skatostatic int		mask2attr(term_stat *tcp);
13656337Skatostatic u_char		iskanji1(u_char mode, u_char c);
13756337Skatostatic u_char		iskanji2(u_char mode, u_char c);
13856337Skatostatic u_short		kanji_convert(u_char mode, u_char h, u_char l);
13956337Skato
14056337Skatostatic int
14156337Skatoscterm_init(scr_stat *scp, void **softc, int code)
14256337Skato{
14356337Skato	term_stat *tcp;
14456337Skato
14556337Skato	if (*softc == NULL) {
14656337Skato		if (reserved_term_stat.flags & SCTERM_BUSY)
14756337Skato			return EINVAL;
14856337Skato		*softc = &reserved_term_stat;
14956337Skato	}
15056337Skato	tcp = *softc;
15156337Skato
15256337Skato	switch (code) {
15356337Skato	case SC_TE_COLD_INIT:
15456337Skato		bzero(tcp, sizeof(*tcp));
15556337Skato		tcp->flags = SCTERM_BUSY;
15656337Skato		tcp->esc = 0;
15756337Skato		tcp->saved_xpos = -1;
15856337Skato		tcp->saved_ypos = -1;
15956337Skato
16056337Skato#ifdef KANJI
16156337Skato		tcp->kanji_1st_char = 0;
16256337Skato		tcp->kanji_type = KTYPE_ASCII;
16356337Skato#endif
16456337Skato
16556337Skato		tcp->attr_mask = NORMAL_ATTR;
16656337Skato		/* XXX */
16756337Skato		tcp->dflt_std_color.fg = SC_NORM_ATTR & 0x0f;
16856337Skato		tcp->dflt_std_color.bg = (SC_NORM_ATTR >> 4) & 0x0f;
16956337Skato		tcp->dflt_rev_color.fg = SC_NORM_REV_ATTR & 0x0f;
17056337Skato		tcp->dflt_rev_color.bg = (SC_NORM_REV_ATTR >> 4) & 0x0f;
17156337Skato		tcp->std_color = tcp->dflt_std_color;
17256337Skato		tcp->rev_color = tcp->dflt_rev_color;
17356337Skato		tcp->cur_color = tcp->std_color;
17456337Skato		tcp->cur_attr = mask2attr(tcp);
17556337Skato		++sc_term_sc.te_refcount;
17656337Skato		break;
17756337Skato
17856337Skato	case SC_TE_WARM_INIT:
17956337Skato		tcp->esc = 0;
18056337Skato		tcp->saved_xpos = -1;
18156337Skato		tcp->saved_ypos = -1;
18257136Skato#if 0
18356337Skato		tcp->std_color = tcp->dflt_std_color;
18456337Skato		tcp->rev_color = tcp->dflt_rev_color;
18557136Skato#endif
18656337Skato		tcp->cur_color = tcp->std_color;
18756337Skato		tcp->cur_attr = mask2attr(tcp);
18856337Skato		break;
18956337Skato	}
19056337Skato
19156337Skato	return 0;
19256337Skato}
19356337Skato
19456337Skatostatic int
19556337Skatoscterm_term(scr_stat *scp, void **softc)
19656337Skato{
19756337Skato	if (*softc == &reserved_term_stat) {
19856337Skato		*softc = NULL;
19956337Skato		bzero(&reserved_term_stat, sizeof(reserved_term_stat));
20056337Skato	}
20156337Skato	--sc_term_sc.te_refcount;
20256337Skato	return 0;
20356337Skato}
20456337Skato
20556337Skatostatic void
20656337Skatoscterm_scan_esc(scr_stat *scp, term_stat *tcp, u_char c)
20756337Skato{
20856337Skato	static u_char ansi_col[16] = {
20956337Skato		FG_BLACK,     FG_RED,          FG_GREEN,      FG_BROWN,
21056337Skato		FG_BLUE,      FG_MAGENTA,      FG_CYAN,       FG_LIGHTGREY,
21156337Skato		FG_DARKGREY,  FG_LIGHTRED,     FG_LIGHTGREEN, FG_YELLOW,
21256337Skato		FG_LIGHTBLUE, FG_LIGHTMAGENTA, FG_LIGHTCYAN,  FG_WHITE
21356337Skato	    };
21456337Skato	sc_softc_t *sc;
21556337Skato	int i, n;
21656337Skato
21756337Skato    i = n = 0;
21856337Skato    sc = scp->sc;
21956337Skato    if (tcp->esc == 1) {	/* seen ESC */
22056337Skato	switch (c) {
22156337Skato
22256337Skato	case '7':   /* Save cursor position */
22356337Skato	    tcp->saved_xpos = scp->xpos;
22456337Skato	    tcp->saved_ypos = scp->ypos;
22556337Skato	    break;
22656337Skato
22756337Skato	case '8':   /* Restore saved cursor position */
22856337Skato	    if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0)
22956337Skato		sc_move_cursor(scp, tcp->saved_xpos, tcp->saved_ypos);
23056337Skato	    break;
23156337Skato
23256337Skato	case '[':   /* Start ESC [ sequence */
23356337Skato	    tcp->esc = 2;
23456337Skato	    tcp->last_param = -1;
23556337Skato	    for (i = tcp->num_param; i < MAX_ESC_PAR; i++)
23656337Skato		tcp->param[i] = 1;
23756337Skato	    tcp->num_param = 0;
23856337Skato	    return;
23956337Skato
24056337Skato#ifdef KANJI
24156337Skato	case '$':	/* Kanji Invoke sequence */
24256337Skato	    tcp->kanji_type = KTYPE_KANIN;
24356337Skato	    return;
24456337Skato#endif
24556337Skato
24656337Skato	case 'M':   /* Move cursor up 1 line, scroll if at top */
24756337Skato	    sc_term_up_scroll(scp, 1, sc->scr_map[0x20], tcp->cur_attr, 0, 0);
24856337Skato	    break;
24956337Skato#if notyet
25056337Skato	case 'Q':
25156337Skato	    tcp->esc = 4;
25256337Skato	    return;
25356337Skato#endif
25456337Skato	case 'c':   /* Clear screen & home */
25556337Skato	    sc_clear_screen(scp);
25656337Skato	    break;
25756337Skato
25856337Skato	case '(':   /* iso-2022: designate 94 character set to G0 */
25956337Skato#ifdef KANJI
26056337Skato	    tcp->kanji_type = KTYPE_ASCIN;
26156337Skato#else
26256337Skato	    tcp->esc = 5;
26356337Skato#endif
26456337Skato	    return;
26556337Skato	}
26656337Skato    }
26756337Skato    else if (tcp->esc == 2) {	/* seen ESC [ */
26856337Skato	if (c >= '0' && c <= '9') {
26956337Skato	    if (tcp->num_param < MAX_ESC_PAR) {
27056337Skato		if (tcp->last_param != tcp->num_param) {
27156337Skato		    tcp->last_param = tcp->num_param;
27256337Skato		    tcp->param[tcp->num_param] = 0;
27356337Skato		} else {
27456337Skato		    tcp->param[tcp->num_param] *= 10;
27556337Skato		}
27656337Skato		tcp->param[tcp->num_param] += c - '0';
27756337Skato		return;
27856337Skato	    }
27956337Skato	}
28056337Skato	tcp->num_param = tcp->last_param + 1;
28156337Skato	switch (c) {
28256337Skato
28356337Skato	case ';':
28456337Skato	    if (tcp->num_param < MAX_ESC_PAR)
28556337Skato		return;
28656337Skato	    break;
28756337Skato
28856337Skato	case '=':
28956337Skato	    tcp->esc = 3;
29056337Skato	    tcp->last_param = -1;
29156337Skato	    for (i = tcp->num_param; i < MAX_ESC_PAR; i++)
29256337Skato		tcp->param[i] = 1;
29356337Skato	    tcp->num_param = 0;
29456337Skato	    return;
29556337Skato
29656337Skato	case 'A':   /* up n rows */
29756337Skato	    sc_term_up(scp, tcp->param[0], 0);
29856337Skato	    break;
29956337Skato
30056337Skato	case 'B':   /* down n rows */
30156337Skato	    sc_term_down(scp, tcp->param[0], 0);
30256337Skato	    break;
30356337Skato
30456337Skato	case 'C':   /* right n columns */
30556337Skato	    sc_term_right(scp, tcp->param[0]);
30656337Skato	    break;
30756337Skato
30856337Skato	case 'D':   /* left n columns */
30956337Skato	    sc_term_left(scp, tcp->param[0]);
31056337Skato	    break;
31156337Skato
31256337Skato	case 'E':   /* cursor to start of line n lines down */
31356337Skato	    n = tcp->param[0]; if (n < 1) n = 1;
31456337Skato	    sc_move_cursor(scp, 0, scp->ypos + n);
31556337Skato	    break;
31656337Skato
31756337Skato	case 'F':   /* cursor to start of line n lines up */
31856337Skato	    n = tcp->param[0]; if (n < 1) n = 1;
31956337Skato	    sc_move_cursor(scp, 0, scp->ypos - n);
32056337Skato	    break;
32156337Skato
32256337Skato	case 'f':   /* Cursor move */
32356337Skato	case 'H':
32456337Skato	    if (tcp->num_param == 0)
32556337Skato		sc_move_cursor(scp, 0, 0);
32656337Skato	    else if (tcp->num_param == 2)
32756337Skato		sc_move_cursor(scp, tcp->param[1] - 1, tcp->param[0] - 1);
32856337Skato	    break;
32956337Skato
33056337Skato	case 'J':   /* Clear all or part of display */
33156337Skato	    if (tcp->num_param == 0)
33256337Skato		n = 0;
33356337Skato	    else
33456337Skato		n = tcp->param[0];
33556337Skato	    sc_term_clr_eos(scp, n, sc->scr_map[0x20], tcp->cur_attr);
33656337Skato	    break;
33756337Skato
33856337Skato	case 'K':   /* Clear all or part of line */
33956337Skato	    if (tcp->num_param == 0)
34056337Skato		n = 0;
34156337Skato	    else
34256337Skato		n = tcp->param[0];
34356337Skato	    sc_term_clr_eol(scp, n, sc->scr_map[0x20], tcp->cur_attr);
34456337Skato	    break;
34556337Skato
34656337Skato	case 'L':   /* Insert n lines */
34756337Skato	    sc_term_ins_line(scp, scp->ypos, tcp->param[0],
34856337Skato			     sc->scr_map[0x20], tcp->cur_attr, 0);
34956337Skato	    break;
35056337Skato
35156337Skato	case 'M':   /* Delete n lines */
35256337Skato	    sc_term_del_line(scp, scp->ypos, tcp->param[0],
35356337Skato			     sc->scr_map[0x20], tcp->cur_attr, 0);
35456337Skato	    break;
35556337Skato
35656337Skato	case 'P':   /* Delete n chars */
35756337Skato	    sc_term_del_char(scp, tcp->param[0],
35856337Skato			     sc->scr_map[0x20], tcp->cur_attr);
35956337Skato	    break;
36056337Skato
36156337Skato	case '@':   /* Insert n chars */
36256337Skato	    sc_term_ins_char(scp, tcp->param[0],
36356337Skato			     sc->scr_map[0x20], tcp->cur_attr);
36456337Skato	    break;
36556337Skato
36656337Skato	case 'S':   /* scroll up n lines */
36756337Skato	    sc_term_del_line(scp, 0, tcp->param[0],
36856337Skato			     sc->scr_map[0x20], tcp->cur_attr, 0);
36956337Skato	    break;
37056337Skato
37156337Skato	case 'T':   /* scroll down n lines */
37256337Skato	    sc_term_ins_line(scp, 0, tcp->param[0],
37356337Skato			     sc->scr_map[0x20], tcp->cur_attr, 0);
37456337Skato	    break;
37556337Skato
37656337Skato	case 'X':   /* erase n characters in line */
37756337Skato	    n = tcp->param[0]; if (n < 1)  n = 1;
37856337Skato	    if (n > scp->xsize - scp->xpos)
37956337Skato		n = scp->xsize - scp->xpos;
38056337Skato	    sc_vtb_erase(&scp->vtb, scp->cursor_pos, n,
38156337Skato			 sc->scr_map[0x20], tcp->cur_attr);
38256337Skato	    mark_for_update(scp, scp->cursor_pos);
38356337Skato	    mark_for_update(scp, scp->cursor_pos + n - 1);
38456337Skato	    break;
38556337Skato
38656337Skato	case 'Z':   /* move n tabs backwards */
38756337Skato	    sc_term_backtab(scp, tcp->param[0]);
38856337Skato	    break;
38956337Skato
39056337Skato	case '`':   /* move cursor to column n */
39156337Skato	    sc_term_col(scp, tcp->param[0]);
39256337Skato	    break;
39356337Skato
39456337Skato	case 'a':   /* move cursor n columns to the right */
39556337Skato	    sc_term_right(scp, tcp->param[0]);
39656337Skato	    break;
39756337Skato
39856337Skato	case 'd':   /* move cursor to row n */
39956337Skato	    sc_term_row(scp, tcp->param[0]);
40056337Skato	    break;
40156337Skato
40256337Skato	case 'e':   /* move cursor n rows down */
40356337Skato	    sc_term_down(scp, tcp->param[0], 0);
40456337Skato	    break;
40556337Skato
40656337Skato	case 'm':   /* change attribute */
40756337Skato	    if (tcp->num_param == 0) {
40856337Skato		tcp->attr_mask = NORMAL_ATTR;
40956337Skato		tcp->cur_color = tcp->std_color;
41056337Skato		tcp->cur_attr = mask2attr(tcp);
41156337Skato		break;
41256337Skato	    }
41356337Skato	    for (i = 0; i < tcp->num_param; i++) {
41456337Skato		switch (n = tcp->param[i]) {
41556337Skato		case 0: /* back to normal */
41656337Skato		    tcp->attr_mask = NORMAL_ATTR;
41756337Skato		    tcp->cur_color = tcp->std_color;
41856337Skato		    tcp->cur_attr = mask2attr(tcp);
41956337Skato		    break;
42056337Skato		case 1: /* bold */
42156337Skato		    tcp->attr_mask |= BOLD_ATTR;
42256337Skato		    tcp->cur_attr = mask2attr(tcp);
42356337Skato		    break;
42456337Skato		case 4: /* underline */
42556337Skato		    tcp->attr_mask |= UNDERLINE_ATTR;
42656337Skato		    tcp->cur_attr = mask2attr(tcp);
42756337Skato		    break;
42856337Skato		case 5: /* blink */
42956337Skato		    tcp->attr_mask |= BLINK_ATTR;
43056337Skato		    tcp->cur_attr = mask2attr(tcp);
43156337Skato		    break;
43256337Skato		case 7: /* reverse video */
43356337Skato		    tcp->attr_mask |= REVERSE_ATTR;
43456337Skato		    tcp->cur_attr = mask2attr(tcp);
43556337Skato		    break;
43656337Skato		case 30: case 31: /* set fg color */
43756337Skato		case 32: case 33: case 34:
43856337Skato		case 35: case 36: case 37:
43956337Skato		    tcp->attr_mask |= FG_CHANGED;
44056337Skato		    tcp->cur_color.fg = ansi_col[n - 30];
44156337Skato		    tcp->cur_attr = mask2attr(tcp);
44256337Skato		    break;
44356337Skato		case 40: case 41: /* set bg color */
44456337Skato		case 42: case 43: case 44:
44556337Skato		case 45: case 46: case 47:
44656337Skato		    tcp->attr_mask |= BG_CHANGED;
44756337Skato		    tcp->cur_color.bg = ansi_col[n - 40];
44856337Skato		    tcp->cur_attr = mask2attr(tcp);
44956337Skato		    break;
45056337Skato		}
45156337Skato	    }
45256337Skato	    break;
45356337Skato
45456337Skato	case 's':   /* Save cursor position */
45556337Skato	    tcp->saved_xpos = scp->xpos;
45656337Skato	    tcp->saved_ypos = scp->ypos;
45756337Skato	    break;
45856337Skato
45956337Skato	case 'u':   /* Restore saved cursor position */
46056337Skato	    if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0)
46156337Skato		sc_move_cursor(scp, tcp->saved_xpos, tcp->saved_ypos);
46256337Skato	    break;
46356337Skato
46456337Skato	case 'x':
46556337Skato	    if (tcp->num_param == 0)
46656337Skato		n = 0;
46756337Skato	    else
46856337Skato		n = tcp->param[0];
46956337Skato	    switch (n) {
47056337Skato	    case 0:     /* reset attributes */
47156337Skato		tcp->attr_mask = NORMAL_ATTR;
47256337Skato		tcp->cur_color = tcp->std_color = tcp->dflt_std_color;
47356337Skato		tcp->rev_color = tcp->dflt_rev_color;
47456337Skato		tcp->cur_attr = mask2attr(tcp);
47556337Skato		break;
47656337Skato	    case 1:     /* set ansi background */
47756337Skato		tcp->attr_mask &= ~BG_CHANGED;
47856337Skato		tcp->cur_color.bg = tcp->std_color.bg =
47956337Skato		    ansi_col[tcp->param[1] & 0x0f];
48056337Skato		tcp->cur_attr = mask2attr(tcp);
48156337Skato		break;
48256337Skato	    case 2:     /* set ansi foreground */
48356337Skato		tcp->attr_mask &= ~FG_CHANGED;
48456337Skato		tcp->cur_color.fg = tcp->std_color.fg =
48556337Skato		    ansi_col[tcp->param[1] & 0x0f];
48656337Skato		tcp->cur_attr = mask2attr(tcp);
48756337Skato		break;
48856337Skato	    case 3:     /* set ansi attribute directly */
48956337Skato		tcp->attr_mask &= ~(FG_CHANGED | BG_CHANGED);
49056337Skato		tcp->cur_color.fg = tcp->std_color.fg =
49156337Skato		    tcp->param[1] & 0x0f;
49256337Skato		tcp->cur_color.bg = tcp->std_color.bg =
49356337Skato		    (tcp->param[1] >> 4) & 0x0f;
49456337Skato		tcp->cur_attr = mask2attr(tcp);
49556337Skato		break;
49656337Skato	    case 5:     /* set ansi reverse video background */
49756337Skato		tcp->rev_color.bg = ansi_col[tcp->param[1] & 0x0f];
49856337Skato		tcp->cur_attr = mask2attr(tcp);
49956337Skato		break;
50056337Skato	    case 6:     /* set ansi reverse video foreground */
50156337Skato		tcp->rev_color.fg = ansi_col[tcp->param[1] & 0x0f];
50256337Skato		tcp->cur_attr = mask2attr(tcp);
50356337Skato		break;
50456337Skato	    case 7:     /* set ansi reverse video directly */
50556337Skato		tcp->rev_color.fg = tcp->param[1] & 0x0f;
50656337Skato		tcp->rev_color.bg = (tcp->param[1] >> 4) & 0x0f;
50756337Skato		tcp->cur_attr = mask2attr(tcp);
50856337Skato		break;
50956337Skato	    }
51056337Skato	    break;
51156337Skato
51256337Skato	case 'z':   /* switch to (virtual) console n */
51356337Skato	    if (tcp->num_param == 1)
51456337Skato		sc_switch_scr(sc, tcp->param[0]);
51556337Skato	    break;
51656337Skato	}
51756337Skato    }
51856337Skato    else if (tcp->esc == 3) {	/* seen ESC [0-9]+ = */
51956337Skato	if (c >= '0' && c <= '9') {
52056337Skato	    if (tcp->num_param < MAX_ESC_PAR) {
52156337Skato		if (tcp->last_param != tcp->num_param) {
52256337Skato		    tcp->last_param = tcp->num_param;
52356337Skato		    tcp->param[tcp->num_param] = 0;
52456337Skato		} else {
52556337Skato		    tcp->param[tcp->num_param] *= 10;
52656337Skato		}
52756337Skato		tcp->param[tcp->num_param] += c - '0';
52856337Skato		return;
52956337Skato	    }
53056337Skato	}
53156337Skato	tcp->num_param = tcp->last_param + 1;
53256337Skato	switch (c) {
53356337Skato
53456337Skato	case ';':
53556337Skato	    if (tcp->num_param < MAX_ESC_PAR)
53656337Skato		return;
53756337Skato	    break;
53856337Skato
53956337Skato	case 'A':   /* set display border color */
54056337Skato	    if (tcp->num_param == 1) {
54156337Skato		scp->border=tcp->param[0] & 0xff;
54256337Skato		if (scp == sc->cur_scp)
54356337Skato		    sc_set_border(scp, scp->border);
54456337Skato            }
54556337Skato	    break;
54656337Skato
54756337Skato	case 'B':   /* set bell pitch and duration */
54856337Skato	    if (tcp->num_param == 2) {
54956337Skato		scp->bell_pitch = tcp->param[0];
55056337Skato		scp->bell_duration = tcp->param[1];
55156337Skato	    }
55256337Skato	    break;
55356337Skato
55456337Skato	case 'C':   /* set cursor type & shape */
55557136Skato	    i = spltty();
55656337Skato	    if (!ISGRAPHSC(sc->cur_scp))
55756337Skato		sc_remove_cursor_image(sc->cur_scp);
55856337Skato	    if (tcp->num_param == 1) {
55956337Skato		if (tcp->param[0] & 0x01)
56056337Skato		    sc->flags |= SC_BLINK_CURSOR;
56156337Skato		else
56256337Skato		    sc->flags &= ~SC_BLINK_CURSOR;
56356337Skato		if (tcp->param[0] & 0x02)
56456337Skato		    sc->flags |= SC_CHAR_CURSOR;
56556337Skato		else
56656337Skato		    sc->flags &= ~SC_CHAR_CURSOR;
56756337Skato	    } else if (tcp->num_param == 2) {
56856337Skato		sc->cursor_base = scp->font_size
56956337Skato					- (tcp->param[1] & 0x1F) - 1;
57056337Skato		sc->cursor_height = (tcp->param[1] & 0x1F)
57156337Skato					- (tcp->param[0] & 0x1F) + 1;
57256337Skato	    }
57356337Skato	    /*
57456337Skato	     * The cursor shape is global property; all virtual consoles
57556337Skato	     * are affected. Update the cursor in the current console...
57656337Skato	     */
57756337Skato	    if (!ISGRAPHSC(sc->cur_scp)) {
57856337Skato		sc_set_cursor_image(sc->cur_scp);
57956337Skato		sc_draw_cursor_image(sc->cur_scp);
58056337Skato	    }
58157136Skato	    splx(i);
58256337Skato	    break;
58356337Skato
58456337Skato	case 'F':   /* set ansi foreground */
58556337Skato	    if (tcp->num_param == 1) {
58656337Skato		tcp->attr_mask &= ~FG_CHANGED;
58756337Skato		tcp->cur_color.fg = tcp->std_color.fg = tcp->param[0] & 0x0f;
58856337Skato		tcp->cur_attr = mask2attr(tcp);
58956337Skato	    }
59056337Skato	    break;
59156337Skato
59256337Skato	case 'G':   /* set ansi background */
59356337Skato	    if (tcp->num_param == 1) {
59456337Skato		tcp->attr_mask &= ~BG_CHANGED;
59556337Skato		tcp->cur_color.bg = tcp->std_color.bg = tcp->param[0] & 0x0f;
59656337Skato		tcp->cur_attr = mask2attr(tcp);
59756337Skato	    }
59856337Skato	    break;
59956337Skato
60056337Skato	case 'H':   /* set ansi reverse video foreground */
60156337Skato	    if (tcp->num_param == 1) {
60256337Skato		tcp->rev_color.fg = tcp->param[0] & 0x0f;
60356337Skato		tcp->cur_attr = mask2attr(tcp);
60456337Skato	    }
60556337Skato	    break;
60656337Skato
60756337Skato	case 'I':   /* set ansi reverse video background */
60856337Skato	    if (tcp->num_param == 1) {
60956337Skato		tcp->rev_color.bg = tcp->param[0] & 0x0f;
61056337Skato		tcp->cur_attr = mask2attr(tcp);
61156337Skato	    }
61256337Skato	    break;
61356337Skato	}
61456337Skato    }
61556337Skato#if notyet
61656337Skato    else if (tcp->esc == 4) {	/* seen ESC Q */
61756337Skato	/* to be filled */
61856337Skato    }
61956337Skato#endif
62056337Skato    else if (tcp->esc == 5) {	/* seen ESC ( */
62156337Skato	switch (c) {
62256337Skato	case 'B':   /* iso-2022: desginate ASCII into G0 */
62356337Skato	    break;
62456337Skato	/* other items to be filled */
62556337Skato	default:
62656337Skato	    break;
62756337Skato	}
62856337Skato    }
62956337Skato    tcp->esc = 0;
63056337Skato}
63156337Skato
63256337Skatostatic void
63356337Skatoscterm_puts(scr_stat *scp, u_char *buf, int len)
63456337Skato{
63556337Skato	term_stat *tcp = scp->ts;
63656337Skato	u_char *ptr = buf;
63756337Skato#ifdef KANJI
63856337Skato	u_short kanji_code;
63956337Skato#endif
64056337Skato
64156337Skatooutloop:
64256337Skato    scp->sc->write_in_progress++;
64356337Skato
64456337Skato    if (tcp->esc) {
64556337Skato	scterm_scan_esc(scp, tcp, *ptr++);
64656337Skato	len--;
64756337Skato    }
64856337Skato    else if (PRINTABLE(*ptr)) {     /* Print only printables */
64956337Skato	vm_offset_t p;
65056337Skato	u_char *map;
65156337Skato	int attr;
65256337Skato	int i;
65356337Skato#ifdef KANJI
65456337Skato	u_char c;
65556337Skato#else
65656337Skato 	int cnt;
65756337Skato#endif
65856337Skato
65956337Skato	p = sc_vtb_pointer(&scp->vtb, scp->cursor_pos);
66056337Skato	map = scp->sc->scr_map;
66156337Skato	attr = tcp->cur_attr;
66256337Skato
66356337Skato#ifdef KANJI
66456337Skato	c = *ptr;
66556337Skato	if (tcp->kanji_1st_char == 0) {
66656337Skato	    tcp->kanji_type = iskanji1(tcp->kanji_type, c);
66756337Skato	    if (!IS_KTYPE_ASCII_or_HANKAKU(tcp->kanji_type)) {
66856337Skato		/* not Ascii & not HANKAKU */
66956337Skato		tcp->kanji_1st_char = c;
67056337Skato		goto kanji_end;
67156337Skato	    } else {
67256337Skato		tcp->kanji_1st_char = 0;
67356337Skato	    }
67456337Skato	} else {
67556337Skato	    if ((tcp->kanji_type = iskanji2(tcp->kanji_type, c)) & 0xee) {
67656337Skato		/* print kanji on TEXT VRAM */
67756337Skato		kanji_code = kanji_convert(tcp->kanji_type, c, tcp->kanji_1st_char);
67856337Skato		mark_for_update(scp, scp->cursor_pos);
67956337Skato		for (i=0; i<2; i++){
68056337Skato		    /* *cursor_pos = (kanji_code | (i*0x80)); */
68156337Skato		    p = sc_vtb_putchar(&scp->vtb, p,
68256337Skato		   		       kanji_code | ((i == 0) ? 0x00 : 0x80),
68356337Skato				       attr);
68456337Skato		    ++scp->cursor_pos;
68556337Skato		    if (++scp->xpos >= scp->xsize) {
68656337Skato			scp->xpos = 0;
68756337Skato			scp->ypos++;
68856337Skato		    }
68956337Skato		}
69056337Skato		mark_for_update(scp, scp->cursor_pos - 1);
69156337Skato		KTYPE_MASK_CTRL(tcp->kanji_type);
69256337Skato		tcp->kanji_1st_char = 0;
69356337Skato		goto kanji_end;
69456337Skato	    } else {
69556337Skato		tcp->kanji_1st_char = 0;
69656337Skato	    }
69756337Skato	}
69856337Skato	if (IS_KTYPE_KANA(tcp->kanji_type))
69956337Skato		c |= 0x80;
70056337Skato	KTYPE_MASK_CTRL(tcp->kanji_type);
70156337Skato	sc_vtb_putchar(&scp->vtb, p, map[c], attr);
70256337Skato	mark_for_update(scp, scp->cursor_pos);
70356337Skato	mark_for_update(scp, scp->cursor_pos);
70456337Skato	++scp->cursor_pos;
70556337Skato	++scp->xpos;
70656337Skatokanji_end:
70756337Skato	++ptr;
70856337Skato	--len;
70956337Skato#else /* !KANJI */
71056337Skato	cnt = imin(len, scp->xsize - scp->xpos);
71156337Skato	i = cnt;
71256337Skato	do {
71356337Skato	    /*
71456337Skato	     * gcc-2.6.3 generates poor (un)sign extension code.  Casting the
71556337Skato	     * pointers in the following to volatile should have no effect,
71656337Skato	     * but in fact speeds up this inner loop from 26 to 18 cycles
71756337Skato	     * (+ cache misses) on i486's.
71856337Skato	     */
71956337Skato#define	UCVP(ucp)	((u_char volatile *)(ucp))
72056337Skato	    p = sc_vtb_putchar(&scp->vtb, p, UCVP(map)[*UCVP(ptr)], attr);
72156337Skato	    ++ptr;
72256337Skato	    --i;
72356337Skato	} while (i > 0 && PRINTABLE(*ptr));
72456337Skato
72556337Skato	len -= cnt - i;
72656337Skato	mark_for_update(scp, scp->cursor_pos);
72756337Skato	scp->cursor_pos += cnt - i;
72856337Skato	mark_for_update(scp, scp->cursor_pos - 1);
72956337Skato	scp->xpos += cnt - i;
73056337Skato#endif /* !KANJI */
73156337Skato
73256337Skato	if (scp->xpos >= scp->xsize) {
73356337Skato	    scp->xpos = 0;
73456337Skato	    scp->ypos++;
73556337Skato	}
73656337Skato    }
73756337Skato    else  {
73856337Skato	switch (*ptr) {
73956337Skato	case 0x07:
74056337Skato	    sc_bell(scp, scp->bell_pitch, scp->bell_duration);
74156337Skato	    break;
74256337Skato
74356337Skato	case 0x08:      /* non-destructive backspace */
74456337Skato	    if (scp->cursor_pos > 0) {
74556337Skato		mark_for_update(scp, scp->cursor_pos);
74656337Skato		scp->cursor_pos--;
74756337Skato		mark_for_update(scp, scp->cursor_pos);
74856337Skato		if (scp->xpos > 0)
74956337Skato		    scp->xpos--;
75056337Skato		else {
75156337Skato		    scp->xpos += scp->xsize - 1;
75256337Skato		    scp->ypos--;
75356337Skato		}
75456337Skato	    }
75556337Skato	    break;
75656337Skato
75756337Skato	case 0x09:  /* non-destructive tab */
75856337Skato	    mark_for_update(scp, scp->cursor_pos);
75956337Skato	    scp->cursor_pos += (8 - scp->xpos % 8u);
76056337Skato	    scp->xpos += (8 - scp->xpos % 8u);
76156337Skato	    if (scp->xpos >= scp->xsize) {
76256337Skato	        scp->xpos = 0;
76356337Skato	        scp->ypos++;
76456337Skato		scp->cursor_pos = scp->xsize * scp->ypos;
76556337Skato	    }
76656337Skato	    mark_for_update(scp, scp->cursor_pos);
76756337Skato	    break;
76856337Skato
76956337Skato	case 0x0a:  /* newline, same pos */
77056337Skato	    mark_for_update(scp, scp->cursor_pos);
77156337Skato	    scp->cursor_pos += scp->xsize;
77256337Skato	    mark_for_update(scp, scp->cursor_pos);
77356337Skato	    scp->ypos++;
77456337Skato	    break;
77556337Skato
77656337Skato	case 0x0c:  /* form feed, clears screen */
77756337Skato	    sc_clear_screen(scp);
77856337Skato	    break;
77956337Skato
78056337Skato	case 0x0d:  /* return, return to pos 0 */
78156337Skato	    mark_for_update(scp, scp->cursor_pos);
78256337Skato	    scp->cursor_pos -= scp->xpos;
78356337Skato	    mark_for_update(scp, scp->cursor_pos);
78456337Skato	    scp->xpos = 0;
78556337Skato	    break;
78656337Skato
78756337Skato#ifdef PC98
78856337Skato	case 0x0e:		/* ^N */
78956337Skato	    tcp->kanji_type = KTYPE_JKANA;
79056337Skato	    tcp->esc = 0;
79156337Skato	    tcp->kanji_1st_char = 0;
79256337Skato	    break;
79356337Skato
79456337Skato	case 0x0f:		/* ^O */
79556337Skato	    tcp->kanji_type = KTYPE_ASCII;
79656337Skato	    tcp->esc = 0;
79756337Skato	    tcp->kanji_1st_char = 0;
79856337Skato	    break;
79956337Skato#endif /* PC98 */
80056337Skato
80156337Skato	case 0x1b:  /* start escape sequence */
80256337Skato	    tcp->esc = 1;
80356337Skato	    tcp->num_param = 0;
80456337Skato	    break;
80556337Skato	}
80656337Skato	ptr++; len--;
80756337Skato    }
80856337Skato
80956337Skato    sc_term_gen_scroll(scp, scp->sc->scr_map[0x20], tcp->cur_attr);
81056337Skato
81156337Skato    scp->sc->write_in_progress--;
81256337Skato    if (len)
81356337Skato	goto outloop;
81456337Skato}
81556337Skato
81656337Skatostatic int
81756337Skatoscterm_ioctl(scr_stat *scp, struct tty *tp, u_long cmd, caddr_t data,
81856337Skato	     int flag, struct proc *p)
81956337Skato{
82056337Skato	term_stat *tcp = scp->ts;
82156337Skato	vid_info_t *vi;
82256337Skato
82356337Skato	switch (cmd) {
82456337Skato	case GIO_ATTR:      	/* get current attributes */
82556337Skato		/* FIXME: */
82656337Skato		*(int*)data = (tcp->cur_attr >> 8) & 0xff;
82756337Skato		return 0;
82856337Skato	case CONS_GETINFO:  	/* get current (virtual) console info */
82956337Skato		vi = (vid_info_t *)data;
83056337Skato		if (vi->size != sizeof(struct vid_info))
83156337Skato			return EINVAL;
83256337Skato		vi->mv_norm.fore = tcp->std_color.fg;
83356337Skato		vi->mv_norm.back = tcp->std_color.bg;
83456337Skato		vi->mv_rev.fore = tcp->rev_color.fg;
83556337Skato		vi->mv_rev.back = tcp->rev_color.bg;
83656337Skato		/*
83756337Skato		 * The other fields are filled by the upper routine. XXX
83856337Skato		 */
83956337Skato		return ENOIOCTL;
84056337Skato	}
84156337Skato	return ENOIOCTL;
84256337Skato}
84356337Skato
84456337Skatostatic int
84556337Skatoscterm_reset(scr_stat *scp, int code)
84656337Skato{
84756337Skato	/* FIXME */
84856337Skato	return 0;
84956337Skato}
85056337Skato
85156337Skatostatic void
85256337Skatoscterm_default_attr(scr_stat *scp, int color, int rev_color)
85356337Skato{
85456337Skato	term_stat *tcp = scp->ts;
85556337Skato
85656337Skato	tcp->dflt_std_color.fg = color & 0x0f;
85756337Skato	tcp->dflt_std_color.bg = (color >> 4) & 0x0f;
85856337Skato	tcp->dflt_rev_color.fg = rev_color & 0x0f;
85956337Skato	tcp->dflt_rev_color.bg = (rev_color >> 4) & 0x0f;
86056337Skato	tcp->std_color = tcp->dflt_std_color;
86156337Skato	tcp->rev_color = tcp->dflt_rev_color;
86256337Skato	tcp->cur_color = tcp->std_color;
86356337Skato	tcp->cur_attr = mask2attr(tcp);
86456337Skato}
86556337Skato
86656337Skatostatic void
86756337Skatoscterm_clear(scr_stat *scp)
86856337Skato{
86956337Skato	term_stat *tcp = scp->ts;
87056337Skato
87156337Skato	sc_move_cursor(scp, 0, 0);
87256337Skato	sc_vtb_clear(&scp->vtb, scp->sc->scr_map[0x20], tcp->cur_attr);
87356337Skato	mark_all(scp);
87456337Skato}
87556337Skato
87656337Skatostatic void
87756337Skatoscterm_notify(scr_stat *scp, int event)
87856337Skato{
87956337Skato	switch (event) {
88056337Skato	case SC_TE_NOTIFY_VTSWITCH_IN:
88156337Skato		break;
88256337Skato	case SC_TE_NOTIFY_VTSWITCH_OUT:
88356337Skato		break;
88456337Skato	}
88556337Skato}
88656337Skato
88756337Skatostatic int
88856337Skatoscterm_input(scr_stat *scp, int c, struct tty *tp)
88956337Skato{
89056337Skato	return FALSE;
89156337Skato}
89256337Skato
89356337Skato/*
89456337Skato * Calculate hardware attributes word using logical attributes mask and
89556337Skato * hardware colors
89656337Skato */
89756337Skato
89856337Skato/* FIXME */
89956337Skatostatic int
90056337Skatomask2attr(term_stat *tcp)
90156337Skato{
90256337Skato	int attr, mask = tcp->attr_mask;
90356337Skato
90456337Skato	if (mask & REVERSE_ATTR) {
90556337Skato		attr = ((mask & FG_CHANGED) ?
90656337Skato			tcp->cur_color.bg : tcp->rev_color.fg) |
90756337Skato			(((mask & BG_CHANGED) ?
90856337Skato			tcp->cur_color.fg : tcp->rev_color.bg) << 4);
90956337Skato	} else
91056337Skato		attr = tcp->cur_color.fg | (tcp->cur_color.bg << 4);
91156337Skato
91256337Skato	/* XXX: underline mapping for Hercules adapter can be better */
91356337Skato	if (mask & (BOLD_ATTR | UNDERLINE_ATTR))
91456337Skato		attr ^= 0x08;
91556337Skato	if (mask & BLINK_ATTR)
91656337Skato		attr ^= 0x80;
91756337Skato
91856337Skato	return (attr << 8);
91956337Skato}
92056337Skato
92156337Skato#ifdef KANJI
92256337Skatostatic u_char
92356337Skatoiskanji1(u_char mode, u_char c)
92456337Skato{
92556337Skato    if ((mode == KTYPE_7JIS) && (c >= 0x21) && (c <= 0x7e)) {
92656337Skato	/* JIS */
92756337Skato	default_kanji = UJIS;
92856337Skato	return KTYPE_7JIS;
92956337Skato    }
93056337Skato
93156337Skato    if ((mode == KTYPE_JKANA) && (c >= 0x21) && (c <= 0x5f)) {
93256337Skato	/* JIS HANKAKU */
93356337Skato	default_kanji = UJIS;
93456337Skato	return KTYPE_JKANA;
93556337Skato    }
93656337Skato
93756337Skato#if 1
93856337Skato    if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) {
93956337Skato	/* UJIS */
94056337Skato	return KTYPE_UJIS;
94156337Skato    }
94256337Skato#endif
94356337Skato
94456337Skato    if ((c >= 0x81) && (c <= 0x9f) && (c != 0x8e)) {
94556337Skato	/* SJIS */
94656337Skato	default_kanji = SJIS;
94756337Skato	return KTYPE_SJIS;
94856337Skato    }
94956337Skato
95056337Skato    if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == SJIS)) {
95156337Skato	/* SJIS HANKAKU */
95256337Skato	return KTYPE_KANA;
95356337Skato    }
95456337Skato
95556337Skato#if 0
95656337Skato    if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) {
95756337Skato	/* UJIS */
95856337Skato	return KTYPE_UJIS;
95956337Skato    }
96056337Skato#endif
96156337Skato
96256337Skato    if ((c >= 0xf0) && (c <= 0xfe)) {
96356337Skato	/* UJIS */
96456337Skato	default_kanji = UJIS;
96556337Skato	return KTYPE_UJIS;
96656337Skato    }
96756337Skato
96856337Skato    if ((c >= 0xe0) && (c <= 0xef)) {
96956337Skato	/* SJIS or UJIS */
97056337Skato	return KTYPE_SUJIS;
97156337Skato    }
97256337Skato
97356337Skato    if (c == 0x8e) {
97456337Skato	/* SJIS or UJIS HANKAKU */
97556337Skato	return KTYPE_SUKANA;
97656337Skato    }
97756337Skato
97856337Skato    return KTYPE_ASCII;
97956337Skato}
98056337Skato
98156337Skatostatic u_char
98256337Skatoiskanji2(u_char mode, u_char c)
98356337Skato{
98456337Skato    switch (mode) {
98556337Skato    case KTYPE_7JIS:
98656337Skato	if ((c >= 0x21) && (c <= 0x7e)) {
98756337Skato	    /* JIS */
98856337Skato	    return KTYPE_7JIS;
98956337Skato	}
99056337Skato	break;
99156337Skato    case KTYPE_SJIS:
99256337Skato	if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) {
99356337Skato	    /* SJIS */
99456337Skato	    return KTYPE_SJIS;
99556337Skato	}
99656337Skato	break;
99756337Skato    case KTYPE_UJIS:
99856337Skato	if ((c >= 0xa1) && (c <= 0xfe)) {
99956337Skato	    /* UJIS */
100056337Skato	    return KTYPE_UJIS;
100156337Skato	}
100256337Skato	break;
100356337Skato    case KTYPE_SUKANA:
100456337Skato	if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) {
100556337Skato	    /* UJIS HANKAKU */
100656337Skato	    return KTYPE_KANA;
100756337Skato	}
100856337Skato	if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) {
100956337Skato	    /* SJIS */
101056337Skato	    default_kanji = SJIS;
101156337Skato	    return KTYPE_SJIS;
101256337Skato	}
101356337Skato	break;
101456337Skato    case KTYPE_SUJIS:
101556337Skato	if ((c >= 0x40) && (c <= 0xa0) && (c != 0x7f)) {
101656337Skato	    /* SJIS */
101756337Skato	    default_kanji = SJIS;
101856337Skato	    return KTYPE_SJIS;
101956337Skato	}
102056337Skato	if ((c == 0xfd) || (c == 0xfe)) {
102156337Skato	    /* UJIS */
102256337Skato	    default_kanji = UJIS;
102356337Skato	    return KTYPE_UJIS;
102456337Skato	}
102556337Skato	if ((c >= 0xa1) && (c <= 0xfc)) {
102656337Skato	    if (default_kanji == SJIS)
102756337Skato		return KTYPE_SJIS;
102856337Skato	    if (default_kanji == UJIS)
102956337Skato		return KTYPE_UJIS;
103056337Skato	}
103156337Skato	break;
103256337Skato    }
103356337Skato    return KTYPE_ASCII;
103456337Skato}
103556337Skato
103656337Skato/*
103756337Skato * JIS X0208-83 keisen conversion table
103856337Skato */
103956337Skatostatic u_short keiConv[32] = {
104056337Skato	0x240c, 0x260c, 0x300c, 0x340c, 0x3c0c, 0x380c, 0x400c, 0x500c,
104156337Skato	0x480c, 0x580c, 0x600c, 0x250c, 0x270c, 0x330c, 0x370c, 0x3f0c,
104256337Skato	0x3b0c, 0x470c, 0x570c, 0x4f0c, 0x5f0c, 0x6f0c, 0x440c, 0x530c,
104356337Skato	0x4c0c, 0x5b0c, 0x630c, 0x410c, 0x540c, 0x490c, 0x5c0c, 0x660c
104456337Skato};
104556337Skato
104656337Skatostatic u_short
104756337Skatokanji_convert(u_char mode, u_char h, u_char l)
104856337Skato{
104956337Skato    u_short tmp, high, low, c;
105056337Skato    high = (u_short) h;
105156337Skato    low  = (u_short) l;
105256337Skato
105356337Skato    switch (mode) {
105456337Skato    case KTYPE_SJIS: /* SHIFT JIS */
105556337Skato	if (low >= 0xe0) {
105656337Skato	    low -= 0x40;
105756337Skato	}
105856337Skato	low = (low - 0x81) * 2 + 0x21;
105956337Skato	if (high > 0x7f) {
106056337Skato	    high--;
106156337Skato	}
106256337Skato	if (high > 0x9d) {
106356337Skato	    low++;
106456337Skato	    high -= 0x9e - 0x21;
106556337Skato	} else {
106656337Skato	    high -= 0x40 - 0x21;
106756337Skato	}
106856337Skato	high &= 0x7F;
106956337Skato	low  &= 0x7F;
107056337Skato	tmp = ((high << 8) | low) - 0x20;
107156337Skato	break;
107256337Skato    case KTYPE_7JIS: /* JIS */
107356337Skato    case KTYPE_UJIS: /* UJIS */
107456337Skato	high &= 0x7F;
107556337Skato	low &= 0x7F;
107656337Skato	tmp = ((high << 8) | low) - 0x20;
107756337Skato	break;
107856337Skato    default:
107956337Skato	tmp = 0;
108056337Skato	break;
108156337Skato    }
108256337Skato
108356337Skato    /* keisen */
108456337Skato    c = ((tmp & 0xff) << 8) | (tmp >> 8);
108556337Skato    /* 0x2821 .. 0x2840 */
108656337Skato    if (0x0821 <= c && c <= 0x0840)
108756337Skato    tmp = keiConv[c - 0x0821];
108856337Skato
108956337Skato    return (tmp);
109056337Skato}
109156337Skato#endif /* KANJI */
109256337Skato
109356337Skato#endif /* SC_DUMB_TERMINAL */
109456337Skato
109556337Skato#endif /* NSC > 0 */
1096