Home | History | Annotate | Line # | Download | only in wscons
wsemul_vt100.c revision 1.31.2.1
      1  1.31.2.1  uebayasi /* $NetBSD: wsemul_vt100.c,v 1.31.2.1 2010/04/30 14:43:54 uebayasi Exp $ */
      2       1.1  drochner 
      3       1.1  drochner /*
      4       1.1  drochner  * Copyright (c) 1998
      5       1.1  drochner  *	Matthias Drochner.  All rights reserved.
      6       1.1  drochner  *
      7       1.1  drochner  * Redistribution and use in source and binary forms, with or without
      8       1.1  drochner  * modification, are permitted provided that the following conditions
      9       1.1  drochner  * are met:
     10       1.1  drochner  * 1. Redistributions of source code must retain the above copyright
     11       1.1  drochner  *    notice, this list of conditions and the following disclaimer.
     12       1.1  drochner  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1  drochner  *    notice, this list of conditions and the following disclaimer in the
     14       1.1  drochner  *    documentation and/or other materials provided with the distribution.
     15       1.1  drochner  *
     16       1.1  drochner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17       1.1  drochner  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18       1.1  drochner  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19       1.1  drochner  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20       1.1  drochner  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21       1.1  drochner  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22       1.1  drochner  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23       1.1  drochner  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24       1.1  drochner  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25       1.1  drochner  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26       1.1  drochner  *
     27       1.1  drochner  */
     28      1.16     lukem 
     29      1.16     lukem #include <sys/cdefs.h>
     30  1.31.2.1  uebayasi __KERNEL_RCSID(0, "$NetBSD: wsemul_vt100.c,v 1.31.2.1 2010/04/30 14:43:54 uebayasi Exp $");
     31      1.26      jmmv 
     32      1.26      jmmv #include "opt_wsmsgattrs.h"
     33       1.1  drochner 
     34       1.1  drochner #include <sys/param.h>
     35       1.1  drochner #include <sys/systm.h>
     36       1.1  drochner #include <sys/time.h>
     37       1.1  drochner #include <sys/malloc.h>
     38       1.1  drochner #include <sys/fcntl.h>
     39       1.1  drochner 
     40       1.1  drochner #include <dev/wscons/wsconsio.h>
     41       1.1  drochner #include <dev/wscons/wsdisplayvar.h>
     42       1.1  drochner #include <dev/wscons/wsemulvar.h>
     43       1.1  drochner #include <dev/wscons/wsemul_vt100var.h>
     44       1.1  drochner #include <dev/wscons/ascii.h>
     45       1.1  drochner 
     46      1.15  augustss void	*wsemul_vt100_cnattach(const struct wsscreen_descr *, void *,
     47      1.15  augustss 			       int, int, long);
     48      1.15  augustss void	*wsemul_vt100_attach(int console, const struct wsscreen_descr *,
     49      1.15  augustss 			     void *, int, int, void *, long);
     50      1.15  augustss void	wsemul_vt100_output(void *cookie, const u_char *data, u_int count, int);
     51      1.15  augustss void	wsemul_vt100_detach(void *cookie, u_int *crowp, u_int *ccolp);
     52      1.15  augustss void	wsemul_vt100_resetop(void *, enum wsemul_resetops);
     53      1.26      jmmv #ifdef WSDISPLAY_CUSTOM_OUTPUT
     54      1.26      jmmv static void wsemul_vt100_getmsgattrs(void *, struct wsdisplay_msgattrs *);
     55      1.26      jmmv static void wsemul_vt100_setmsgattrs(void *, const struct wsscreen_descr *,
     56      1.26      jmmv                                      const struct wsdisplay_msgattrs *);
     57      1.26      jmmv #endif /* WSDISPLAY_CUSTOM_OUTPUT */
     58       1.1  drochner 
     59       1.1  drochner const struct wsemul_ops wsemul_vt100_ops = {
     60       1.1  drochner 	"vt100",
     61       1.1  drochner 	wsemul_vt100_cnattach,
     62       1.1  drochner 	wsemul_vt100_attach,
     63       1.1  drochner 	wsemul_vt100_output,
     64       1.1  drochner 	wsemul_vt100_translate,
     65       1.1  drochner 	wsemul_vt100_detach,
     66      1.26      jmmv 	wsemul_vt100_resetop,
     67      1.26      jmmv #ifdef WSDISPLAY_CUSTOM_OUTPUT
     68      1.26      jmmv 	wsemul_vt100_getmsgattrs,
     69      1.26      jmmv 	wsemul_vt100_setmsgattrs,
     70      1.26      jmmv #else
     71      1.26      jmmv 	NULL,
     72      1.26      jmmv 	NULL,
     73      1.26      jmmv #endif
     74       1.1  drochner };
     75       1.1  drochner 
     76       1.1  drochner struct wsemul_vt100_emuldata wsemul_vt100_console_emuldata;
     77       1.1  drochner 
     78      1.15  augustss static void wsemul_vt100_init(struct wsemul_vt100_emuldata *,
     79      1.15  augustss 			      const struct wsscreen_descr *,
     80      1.15  augustss 			      void *, int, int, long);
     81      1.15  augustss 
     82      1.15  augustss static void wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *,
     83      1.15  augustss 				       u_char, int);
     84      1.15  augustss static void wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *,
     85      1.15  augustss 				     u_char, int);
     86      1.21  sommerfe static void wsemul_vt100_nextline(struct wsemul_vt100_emuldata *);
     87      1.15  augustss typedef u_int vt100_handler(struct wsemul_vt100_emuldata *, u_char);
     88      1.21  sommerfe 
     89       1.1  drochner static vt100_handler
     90       1.1  drochner wsemul_vt100_output_esc,
     91       1.1  drochner wsemul_vt100_output_csi,
     92       1.1  drochner wsemul_vt100_output_scs94,
     93       1.1  drochner wsemul_vt100_output_scs94_percent,
     94       1.1  drochner wsemul_vt100_output_scs96,
     95       1.1  drochner wsemul_vt100_output_scs96_percent,
     96       1.3  drochner wsemul_vt100_output_esc_hash,
     97       1.1  drochner wsemul_vt100_output_esc_spc,
     98       1.1  drochner wsemul_vt100_output_string,
     99       1.1  drochner wsemul_vt100_output_string_esc,
    100       1.1  drochner wsemul_vt100_output_dcs,
    101       1.1  drochner wsemul_vt100_output_dcs_dollar;
    102       1.1  drochner 
    103       1.1  drochner #define	VT100_EMUL_STATE_NORMAL		0	/* normal processing */
    104       1.1  drochner #define	VT100_EMUL_STATE_ESC		1	/* got ESC */
    105       1.1  drochner #define	VT100_EMUL_STATE_CSI		2	/* got CSI (ESC[) */
    106       1.3  drochner #define	VT100_EMUL_STATE_SCS94		3	/* got ESC{()*+} */
    107       1.3  drochner #define	VT100_EMUL_STATE_SCS94_PERCENT	4	/* got ESC{()*+}% */
    108       1.3  drochner #define	VT100_EMUL_STATE_SCS96		5	/* got ESC{-./} */
    109       1.3  drochner #define	VT100_EMUL_STATE_SCS96_PERCENT	6	/* got ESC{-./}% */
    110       1.3  drochner #define	VT100_EMUL_STATE_ESC_HASH	7	/* got ESC# */
    111       1.3  drochner #define	VT100_EMUL_STATE_ESC_SPC	8	/* got ESC<SPC> */
    112       1.3  drochner #define	VT100_EMUL_STATE_STRING		9	/* waiting for ST (ESC\) */
    113       1.3  drochner #define	VT100_EMUL_STATE_STRING_ESC	10	/* waiting for ST, got ESC */
    114       1.3  drochner #define	VT100_EMUL_STATE_DCS		11	/* got DCS (ESC P) */
    115       1.3  drochner #define	VT100_EMUL_STATE_DCS_DOLLAR	12	/* got DCS<p>$ */
    116       1.1  drochner 
    117       1.1  drochner vt100_handler *vt100_output[] = {
    118       1.1  drochner 	wsemul_vt100_output_esc,
    119       1.1  drochner 	wsemul_vt100_output_csi,
    120       1.1  drochner 	wsemul_vt100_output_scs94,
    121       1.1  drochner 	wsemul_vt100_output_scs94_percent,
    122       1.1  drochner 	wsemul_vt100_output_scs96,
    123       1.1  drochner 	wsemul_vt100_output_scs96_percent,
    124       1.3  drochner 	wsemul_vt100_output_esc_hash,
    125       1.1  drochner 	wsemul_vt100_output_esc_spc,
    126       1.1  drochner 	wsemul_vt100_output_string,
    127       1.1  drochner 	wsemul_vt100_output_string_esc,
    128       1.1  drochner 	wsemul_vt100_output_dcs,
    129       1.1  drochner 	wsemul_vt100_output_dcs_dollar,
    130       1.1  drochner };
    131       1.1  drochner 
    132       1.1  drochner static void
    133      1.27     perry wsemul_vt100_init(struct wsemul_vt100_emuldata *edp,
    134      1.15  augustss 	const struct wsscreen_descr *type, void *cookie, int ccol, int crow,
    135      1.15  augustss 	long defattr)
    136       1.1  drochner {
    137  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
    138      1.26      jmmv 	int error;
    139      1.26      jmmv 
    140  1.31.2.1  uebayasi 	vd->emulops = type->textops;
    141  1.31.2.1  uebayasi 	vd->emulcookie = cookie;
    142  1.31.2.1  uebayasi 	vd->scrcapabilities = type->capabilities;
    143  1.31.2.1  uebayasi 	vd->nrows = type->nrows;
    144  1.31.2.1  uebayasi 	vd->ncols = type->ncols;
    145  1.31.2.1  uebayasi 	vd->crow = crow;
    146  1.31.2.1  uebayasi 	vd->ccol = ccol;
    147      1.26      jmmv 
    148      1.26      jmmv 	/* The underlying driver has already allocated a default and simple
    149      1.26      jmmv 	 * attribute for us, which is stored in defattr.  We try to set the
    150      1.26      jmmv 	 * values specified by the kernel options below, but in case of
    151      1.26      jmmv 	 * failure we fallback to the value given by the driver. */
    152      1.26      jmmv 
    153      1.26      jmmv 	if (type->capabilities & WSSCREEN_WSCOLORS) {
    154  1.31.2.1  uebayasi 		vd->msgattrs.default_attrs = WS_DEFAULT_COLATTR |
    155      1.26      jmmv 		    WSATTR_WSCOLORS;
    156  1.31.2.1  uebayasi 		vd->msgattrs.default_bg = WS_DEFAULT_BG;
    157  1.31.2.1  uebayasi 		vd->msgattrs.default_fg = WS_DEFAULT_FG;
    158      1.26      jmmv 
    159  1.31.2.1  uebayasi 		vd->msgattrs.kernel_attrs = WS_KERNEL_COLATTR |
    160      1.26      jmmv 		    WSATTR_WSCOLORS;
    161  1.31.2.1  uebayasi 		vd->msgattrs.kernel_bg = WS_KERNEL_BG;
    162  1.31.2.1  uebayasi 		vd->msgattrs.kernel_fg = WS_KERNEL_FG;
    163      1.26      jmmv 	} else {
    164  1.31.2.1  uebayasi 		vd->msgattrs.default_attrs = WS_DEFAULT_MONOATTR;
    165  1.31.2.1  uebayasi 		vd->msgattrs.default_bg = vd->msgattrs.default_fg = 0;
    166      1.26      jmmv 
    167  1.31.2.1  uebayasi 		vd->msgattrs.kernel_attrs = WS_KERNEL_MONOATTR;
    168  1.31.2.1  uebayasi 		vd->msgattrs.kernel_bg = vd->msgattrs.kernel_fg = 0;
    169      1.26      jmmv 	}
    170      1.26      jmmv 
    171  1.31.2.1  uebayasi 	error = (*vd->emulops->allocattr)(cookie,
    172  1.31.2.1  uebayasi 					   vd->msgattrs.default_fg,
    173  1.31.2.1  uebayasi 					   vd->msgattrs.default_bg,
    174  1.31.2.1  uebayasi 					   vd->msgattrs.default_attrs,
    175  1.31.2.1  uebayasi 					   &vd->defattr);
    176      1.26      jmmv 	if (error) {
    177  1.31.2.1  uebayasi 		vd->defattr = defattr;
    178      1.26      jmmv 		/* XXX This assumes the driver has allocated white on black
    179      1.26      jmmv 		 * XXX as the default attribute, which is not always true.
    180      1.26      jmmv 		 * XXX Maybe we need an emulop that, given an attribute,
    181      1.26      jmmv 		 * XXX (defattr) returns its flags and colors? */
    182  1.31.2.1  uebayasi 		vd->msgattrs.default_attrs = 0;
    183  1.31.2.1  uebayasi 		vd->msgattrs.default_bg = WSCOL_BLACK;
    184  1.31.2.1  uebayasi 		vd->msgattrs.default_fg = WSCOL_WHITE;
    185      1.26      jmmv 	} else {
    186  1.31.2.1  uebayasi 		if (vd->emulops->replaceattr != NULL)
    187  1.31.2.1  uebayasi 			(*vd->emulops->replaceattr)(cookie, defattr,
    188  1.31.2.1  uebayasi 			                             vd->defattr);
    189      1.26      jmmv 	}
    190      1.26      jmmv 
    191      1.26      jmmv #if defined(WS_KERNEL_CUSTOMIZED)
    192      1.26      jmmv 	/* Set up kernel colors, in case they were customized by the user;
    193      1.26      jmmv 	 * otherwise default to the colors specified for the console.
    194      1.26      jmmv 	 * In case of failure, we use console colors too; we can assume
    195      1.26      jmmv 	 * they are good as they have been previously allocated and
    196      1.26      jmmv 	 * verified. */
    197  1.31.2.1  uebayasi 	error = (*vd->emulops->allocattr)(cookie,
    198  1.31.2.1  uebayasi 					   vd->msgattrs.kernel_fg,
    199  1.31.2.1  uebayasi 					   vd->msgattrs.kernel_bg,
    200  1.31.2.1  uebayasi 					   vd->msgattrs.kernel_attrs,
    201      1.26      jmmv 					   &edp->kernattr);
    202      1.26      jmmv 	if (error)
    203      1.26      jmmv #endif
    204  1.31.2.1  uebayasi 	edp->kernattr = vd->defattr;
    205       1.1  drochner }
    206       1.1  drochner 
    207       1.1  drochner void *
    208      1.15  augustss wsemul_vt100_cnattach(const struct wsscreen_descr *type, void *cookie,
    209      1.15  augustss 	int ccol, int crow, long defattr)
    210       1.1  drochner {
    211       1.1  drochner 	struct wsemul_vt100_emuldata *edp;
    212  1.31.2.1  uebayasi 	struct vt100base_data *vd;
    213       1.1  drochner 
    214       1.1  drochner 	edp = &wsemul_vt100_console_emuldata;
    215  1.31.2.1  uebayasi 	vd = &edp->bd;
    216       1.1  drochner 	wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr);
    217       1.1  drochner #ifdef DIAGNOSTIC
    218       1.1  drochner 	edp->console = 1;
    219       1.1  drochner #endif
    220  1.31.2.1  uebayasi 	vd->cbcookie = NULL;
    221       1.1  drochner 
    222  1.31.2.1  uebayasi 	vd->tabs = 0;
    223  1.31.2.1  uebayasi 	vd->dblwid = 0;
    224  1.31.2.1  uebayasi 	vd->dw = 0;
    225  1.31.2.1  uebayasi 	vd->dcsarg = 0;
    226       1.3  drochner 	edp->isolatin1tab = edp->decgraphtab = edp->dectechtab = 0;
    227       1.3  drochner 	edp->nrctab = 0;
    228       1.1  drochner 	wsemul_vt100_reset(edp);
    229       1.1  drochner 	return (edp);
    230       1.1  drochner }
    231       1.1  drochner 
    232       1.1  drochner void *
    233      1.15  augustss wsemul_vt100_attach(int console, const struct wsscreen_descr *type,
    234      1.15  augustss 	void *cookie, int ccol, int crow, void *cbcookie, long defattr)
    235       1.1  drochner {
    236       1.1  drochner 	struct wsemul_vt100_emuldata *edp;
    237  1.31.2.1  uebayasi 	struct vt100base_data *vd;
    238       1.1  drochner 
    239       1.1  drochner 	if (console) {
    240       1.1  drochner 		edp = &wsemul_vt100_console_emuldata;
    241       1.1  drochner #ifdef DIAGNOSTIC
    242       1.1  drochner 		KASSERT(edp->console == 1);
    243       1.1  drochner #endif
    244       1.1  drochner 	} else {
    245       1.1  drochner 		edp = malloc(sizeof *edp, M_DEVBUF, M_WAITOK);
    246       1.1  drochner 		wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr);
    247       1.1  drochner #ifdef DIAGNOSTIC
    248       1.1  drochner 		edp->console = 0;
    249       1.1  drochner #endif
    250       1.1  drochner 	}
    251  1.31.2.1  uebayasi 	vd = &edp->bd;
    252  1.31.2.1  uebayasi 	vd->cbcookie = cbcookie;
    253       1.1  drochner 
    254  1.31.2.1  uebayasi 	vd->tabs = malloc(vd->ncols, M_DEVBUF, M_NOWAIT);
    255  1.31.2.1  uebayasi 	vd->dblwid = malloc(vd->nrows, M_DEVBUF, M_NOWAIT|M_ZERO);
    256  1.31.2.1  uebayasi 	vd->dw = 0;
    257  1.31.2.1  uebayasi 	vd->dcsarg = malloc(DCS_MAXLEN, M_DEVBUF, M_NOWAIT);
    258       1.3  drochner 	edp->isolatin1tab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
    259       1.3  drochner 	edp->decgraphtab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
    260       1.3  drochner 	edp->dectechtab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
    261       1.3  drochner 	edp->nrctab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
    262       1.3  drochner 	vt100_initchartables(edp);
    263       1.1  drochner 	wsemul_vt100_reset(edp);
    264       1.1  drochner 	return (edp);
    265       1.1  drochner }
    266       1.1  drochner 
    267       1.1  drochner void
    268      1.15  augustss wsemul_vt100_detach(void *cookie, u_int *crowp, u_int *ccolp)
    269       1.1  drochner {
    270       1.1  drochner 	struct wsemul_vt100_emuldata *edp = cookie;
    271  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
    272       1.1  drochner 
    273  1.31.2.1  uebayasi 	*crowp = vd->crow;
    274  1.31.2.1  uebayasi 	*ccolp = vd->ccol;
    275       1.3  drochner #define f(ptr) if (ptr) {free(ptr, M_DEVBUF); ptr = 0;}
    276  1.31.2.1  uebayasi 	f(vd->tabs)
    277  1.31.2.1  uebayasi 	f(vd->dblwid)
    278  1.31.2.1  uebayasi 	f(vd->dcsarg)
    279       1.3  drochner 	f(edp->isolatin1tab)
    280       1.3  drochner 	f(edp->decgraphtab)
    281       1.3  drochner 	f(edp->dectechtab)
    282       1.3  drochner 	f(edp->nrctab)
    283       1.3  drochner #undef f
    284       1.1  drochner 	if (edp != &wsemul_vt100_console_emuldata)
    285       1.1  drochner 		free(edp, M_DEVBUF);
    286       1.9  drochner }
    287       1.9  drochner 
    288       1.9  drochner void
    289      1.15  augustss wsemul_vt100_resetop(void *cookie, enum wsemul_resetops op)
    290       1.9  drochner {
    291       1.9  drochner 	struct wsemul_vt100_emuldata *edp = cookie;
    292  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
    293       1.9  drochner 
    294       1.9  drochner 	switch (op) {
    295       1.9  drochner 	case WSEMUL_RESET:
    296       1.9  drochner 		wsemul_vt100_reset(edp);
    297       1.9  drochner 		break;
    298       1.9  drochner 	case WSEMUL_SYNCFONT:
    299       1.9  drochner 		vt100_initchartables(edp);
    300      1.10  drochner 		break;
    301      1.10  drochner 	case WSEMUL_CLEARSCREEN:
    302  1.31.2.1  uebayasi 		wsemul_vt100_ed(vd, 2);
    303  1.31.2.1  uebayasi 		vd->ccol = vd->crow = 0;
    304  1.31.2.1  uebayasi 		(*vd->emulops->cursor)(vd->emulcookie,
    305  1.31.2.1  uebayasi 					vd->flags & VTFL_CURSORON, 0, 0);
    306      1.10  drochner 		break;
    307      1.10  drochner 	default:
    308       1.9  drochner 		break;
    309       1.9  drochner 	}
    310       1.1  drochner }
    311       1.1  drochner 
    312       1.1  drochner void
    313      1.15  augustss wsemul_vt100_reset(struct wsemul_vt100_emuldata *edp)
    314       1.1  drochner {
    315  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
    316       1.1  drochner 	int i;
    317       1.1  drochner 
    318       1.1  drochner 	edp->state = VT100_EMUL_STATE_NORMAL;
    319  1.31.2.1  uebayasi 	vd->flags = VTFL_DECAWM | VTFL_CURSORON;
    320  1.31.2.1  uebayasi 	vd->bkgdattr = vd->curattr = vd->defattr;
    321  1.31.2.1  uebayasi 	vd->attrflags = vd->msgattrs.default_attrs;
    322  1.31.2.1  uebayasi 	vd->fgcol = vd->msgattrs.default_fg;
    323  1.31.2.1  uebayasi 	vd->bgcol = vd->msgattrs.default_bg;
    324  1.31.2.1  uebayasi 	vd->scrreg_startrow = 0;
    325  1.31.2.1  uebayasi 	vd->scrreg_nrows = vd->nrows;
    326  1.31.2.1  uebayasi 	if (vd->tabs) {
    327  1.31.2.1  uebayasi 		memset(vd->tabs, 0, vd->ncols);
    328  1.31.2.1  uebayasi 		for (i = 8; i < vd->ncols; i += 8)
    329  1.31.2.1  uebayasi 			vd->tabs[i] = 1;
    330       1.1  drochner 	}
    331  1.31.2.1  uebayasi 	vd->dcspos = 0;
    332  1.31.2.1  uebayasi 	vd->dcstype = 0;
    333       1.3  drochner 	edp->chartab_G[0] = 0;
    334       1.3  drochner 	edp->chartab_G[1] = edp->nrctab; /* ??? */
    335       1.3  drochner 	edp->chartab_G[2] = edp->isolatin1tab;
    336       1.3  drochner 	edp->chartab_G[3] = edp->isolatin1tab;
    337       1.3  drochner 	edp->chartab0 = 0;
    338       1.3  drochner 	edp->chartab1 = 2;
    339       1.3  drochner 	edp->sschartab = 0;
    340       1.1  drochner }
    341       1.1  drochner 
    342       1.1  drochner /*
    343       1.1  drochner  * now all the state machine bits
    344       1.1  drochner  */
    345       1.1  drochner 
    346      1.21  sommerfe /*
    347      1.21  sommerfe  * Move the cursor to the next line if possible. If the cursor is at
    348      1.21  sommerfe  * the bottom of the scroll area, then scroll it up. If the cursor is
    349      1.21  sommerfe  * at the bottom of the screen then don't move it down.
    350      1.21  sommerfe  */
    351       1.7  drochner static void
    352      1.21  sommerfe wsemul_vt100_nextline(struct wsemul_vt100_emuldata *edp)
    353      1.21  sommerfe {
    354  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
    355  1.31.2.1  uebayasi 
    356  1.31.2.1  uebayasi 	if (ROWS_BELOW(vd) == 0) {
    357      1.21  sommerfe 		/* Bottom of the scroll region. */
    358  1.31.2.1  uebayasi 	  	wsemul_vt100_scrollup(vd, 1);
    359      1.21  sommerfe 	} else {
    360  1.31.2.1  uebayasi 		if ((vd->crow+1) < vd->nrows)
    361      1.21  sommerfe 			/* Cursor not at the bottom of the screen. */
    362  1.31.2.1  uebayasi 			vd->crow++;
    363  1.31.2.1  uebayasi 		CHECK_DW(vd);
    364      1.21  sommerfe 	}
    365      1.27     perry }
    366      1.21  sommerfe 
    367      1.22  sommerfe static void
    368      1.15  augustss wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *edp, u_char c,
    369      1.15  augustss 	int kernel)
    370       1.1  drochner {
    371  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
    372       1.7  drochner 	u_int *ct, dc;
    373       1.7  drochner 
    374  1.31.2.1  uebayasi 	if ((vd->flags & (VTFL_LASTCHAR | VTFL_DECAWM)) ==
    375       1.7  drochner 	    (VTFL_LASTCHAR | VTFL_DECAWM)) {
    376      1.21  sommerfe 		wsemul_vt100_nextline(edp);
    377  1.31.2.1  uebayasi 		vd->ccol = 0;
    378  1.31.2.1  uebayasi 		vd->flags &= ~VTFL_LASTCHAR;
    379       1.7  drochner 	}
    380       1.7  drochner 
    381       1.7  drochner 	if (c & 0x80) {
    382       1.7  drochner 		c &= 0x7f;
    383       1.7  drochner 		ct = edp->chartab_G[edp->chartab1];
    384       1.7  drochner 	} else {
    385       1.7  drochner 		if (edp->sschartab) {
    386       1.7  drochner 			ct = edp->chartab_G[edp->sschartab];
    387       1.7  drochner 			edp->sschartab = 0;
    388       1.7  drochner 		} else
    389       1.7  drochner 			ct = edp->chartab_G[edp->chartab0];
    390       1.7  drochner 	}
    391       1.7  drochner 	dc = (ct ? ct[c] : c);
    392       1.7  drochner 
    393  1.31.2.1  uebayasi 	if ((vd->flags & VTFL_INSERTMODE) && COLS_LEFT(vd))
    394  1.31.2.1  uebayasi 		COPYCOLS(vd, vd->ccol, vd->ccol + 1, COLS_LEFT(vd));
    395       1.7  drochner 
    396  1.31.2.1  uebayasi 	(*vd->emulops->putchar)(vd->emulcookie, vd->crow,
    397  1.31.2.1  uebayasi 				 vd->ccol << vd->dw, dc,
    398  1.31.2.1  uebayasi 				 kernel ? edp->kernattr : vd->curattr);
    399       1.7  drochner 
    400  1.31.2.1  uebayasi 	if (COLS_LEFT(vd))
    401  1.31.2.1  uebayasi 		vd->ccol++;
    402       1.7  drochner 	else
    403  1.31.2.1  uebayasi 		vd->flags |= VTFL_LASTCHAR;
    404       1.7  drochner }
    405       1.7  drochner 
    406       1.7  drochner static void
    407      1.27     perry wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *edp, u_char c,
    408      1.15  augustss 	int kernel)
    409       1.7  drochner {
    410  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
    411       1.7  drochner 	u_int n;
    412       1.1  drochner 
    413       1.1  drochner 	switch (c) {
    414      1.19  junyoung 	case ASCII_NUL:
    415      1.19  junyoung 	default:
    416       1.1  drochner 		/* ignore */
    417       1.1  drochner 		break;
    418      1.19  junyoung 	case ASCII_BEL:
    419  1.31.2.1  uebayasi 		wsdisplay_emulbell(vd->cbcookie);
    420       1.1  drochner 		break;
    421      1.19  junyoung 	case ASCII_BS:
    422  1.31.2.1  uebayasi 		if (vd->ccol > 0) {
    423  1.31.2.1  uebayasi 			vd->ccol--;
    424  1.31.2.1  uebayasi 			vd->flags &= ~VTFL_LASTCHAR;
    425       1.1  drochner 		}
    426       1.1  drochner 		break;
    427      1.19  junyoung 	case ASCII_CR:
    428  1.31.2.1  uebayasi 		vd->ccol = 0;
    429  1.31.2.1  uebayasi 		vd->flags &= ~VTFL_LASTCHAR;
    430       1.1  drochner 		break;
    431      1.19  junyoung 	case ASCII_HT:
    432  1.31.2.1  uebayasi 		if (vd->tabs) {
    433  1.31.2.1  uebayasi 			if (!COLS_LEFT(vd))
    434       1.1  drochner 				break;
    435  1.31.2.1  uebayasi 			for (n = vd->ccol + 1; n < NCOLS(vd) - 1; n++)
    436  1.31.2.1  uebayasi 				if (vd->tabs[n])
    437       1.1  drochner 					break;
    438       1.1  drochner 		} else {
    439  1.31.2.1  uebayasi 			n = vd->ccol + min(8 - (vd->ccol & 7), COLS_LEFT(vd));
    440       1.1  drochner 		}
    441  1.31.2.1  uebayasi 		vd->ccol = n;
    442       1.1  drochner 		break;
    443      1.19  junyoung 	case ASCII_SO: /* LS1 */
    444       1.3  drochner 		edp->chartab0 = 1;
    445       1.3  drochner 		break;
    446      1.19  junyoung 	case ASCII_SI: /* LS0 */
    447       1.3  drochner 		edp->chartab0 = 0;
    448       1.1  drochner 		break;
    449      1.19  junyoung 	case ASCII_ESC:
    450      1.14  jdolecek 		if (kernel) {
    451      1.14  jdolecek 			printf("wsemul_vt100_output_c0c1: ESC in kernel output ignored\n");
    452      1.14  jdolecek 			break;	/* ignore the ESC */
    453      1.14  jdolecek 		}
    454      1.14  jdolecek 
    455       1.7  drochner 		if (edp->state == VT100_EMUL_STATE_STRING) {
    456       1.7  drochner 			/* might be a string end */
    457       1.7  drochner 			edp->state = VT100_EMUL_STATE_STRING_ESC;
    458       1.7  drochner 		} else {
    459       1.7  drochner 			/* XXX cancel current escape sequence */
    460       1.7  drochner 			edp->state = VT100_EMUL_STATE_ESC;
    461       1.7  drochner 		}
    462       1.1  drochner 		break;
    463       1.1  drochner #if 0
    464      1.19  junyoung 	case CSI: /* 8-bit */
    465       1.7  drochner 		/* XXX cancel current escape sequence */
    466       1.1  drochner 		edp->nargs = 0;
    467       1.8  augustss 		memset(edp->args, 0, sizeof (edp->args));
    468       1.3  drochner 		edp->modif1 = edp->modif2 = '\0';
    469       1.7  drochner 		edp->state = VT100_EMUL_STATE_CSI;
    470       1.1  drochner 		break;
    471      1.19  junyoung 	case DCS: /* 8-bit */
    472       1.7  drochner 		/* XXX cancel current escape sequence */
    473       1.1  drochner 		edp->nargs = 0;
    474       1.8  augustss 		memset(edp->args, 0, sizeof (edp->args));
    475       1.7  drochner 		edp->state = VT100_EMUL_STATE_DCS;
    476       1.1  drochner 		break;
    477      1.19  junyoung 	case ST: /* string end 8-bit */
    478       1.7  drochner 		/* XXX only in VT100_EMUL_STATE_STRING */
    479       1.7  drochner 		wsemul_vt100_handle_dcs(edp);
    480       1.7  drochner 		return (VT100_EMUL_STATE_NORMAL);
    481       1.1  drochner #endif
    482      1.19  junyoung 	case ASCII_LF:
    483      1.19  junyoung 	case ASCII_VT:
    484      1.19  junyoung 	case ASCII_FF:
    485      1.21  sommerfe 		wsemul_vt100_nextline(edp);
    486       1.1  drochner 		break;
    487       1.1  drochner 	}
    488       1.1  drochner }
    489       1.1  drochner 
    490       1.1  drochner static u_int
    491      1.15  augustss wsemul_vt100_output_esc(struct wsemul_vt100_emuldata *edp, u_char c)
    492       1.1  drochner {
    493  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
    494       1.1  drochner 	u_int newstate = VT100_EMUL_STATE_NORMAL;
    495       1.3  drochner 	int i;
    496       1.1  drochner 
    497       1.1  drochner 	switch (c) {
    498      1.19  junyoung 	case '[': /* CSI */
    499  1.31.2.1  uebayasi 		vd->nargs = 0;
    500  1.31.2.1  uebayasi 		memset(vd->args, 0, sizeof (vd->args));
    501  1.31.2.1  uebayasi 		vd->modif1 = vd->modif2 = '\0';
    502       1.1  drochner 		newstate = VT100_EMUL_STATE_CSI;
    503       1.1  drochner 		break;
    504      1.19  junyoung 	case '7': /* DECSC */
    505  1.31.2.1  uebayasi 		vd->flags |= VTFL_SAVEDCURS;
    506  1.31.2.1  uebayasi 		edp->savedcursor_row = vd->crow;
    507  1.31.2.1  uebayasi 		edp->savedcursor_col = vd->ccol;
    508  1.31.2.1  uebayasi 		edp->savedattr = vd->curattr;
    509  1.31.2.1  uebayasi 		edp->savedbkgdattr = vd->bkgdattr;
    510  1.31.2.1  uebayasi 		edp->savedattrflags = vd->attrflags;
    511  1.31.2.1  uebayasi 		edp->savedfgcol = vd->fgcol;
    512  1.31.2.1  uebayasi 		edp->savedbgcol = vd->bgcol;
    513       1.3  drochner 		for (i = 0; i < 4; i++)
    514       1.3  drochner 			edp->savedchartab_G[i] = edp->chartab_G[i];
    515       1.3  drochner 		edp->savedchartab0 = edp->chartab0;
    516       1.3  drochner 		edp->savedchartab1 = edp->chartab1;
    517       1.1  drochner 		break;
    518      1.19  junyoung 	case '8': /* DECRC */
    519  1.31.2.1  uebayasi 		if ((vd->flags & VTFL_SAVEDCURS) == 0)
    520      1.24  christos 			break;
    521  1.31.2.1  uebayasi 		vd->crow = edp->savedcursor_row;
    522  1.31.2.1  uebayasi 		vd->ccol = edp->savedcursor_col;
    523  1.31.2.1  uebayasi 		vd->curattr = edp->savedattr;
    524  1.31.2.1  uebayasi 		vd->bkgdattr = edp->savedbkgdattr;
    525  1.31.2.1  uebayasi 		vd->attrflags = edp->savedattrflags;
    526  1.31.2.1  uebayasi 		vd->fgcol = edp->savedfgcol;
    527  1.31.2.1  uebayasi 		vd->bgcol = edp->savedbgcol;
    528       1.3  drochner 		for (i = 0; i < 4; i++)
    529       1.3  drochner 			edp->chartab_G[i] = edp->savedchartab_G[i];
    530       1.3  drochner 		edp->chartab0 = edp->savedchartab0;
    531       1.3  drochner 		edp->chartab1 = edp->savedchartab1;
    532       1.1  drochner 		break;
    533      1.19  junyoung 	case '=': /* DECKPAM application mode */
    534  1.31.2.1  uebayasi 		vd->flags |= VTFL_APPLKEYPAD;
    535       1.1  drochner 		break;
    536      1.19  junyoung 	case '>': /* DECKPNM numeric mode */
    537  1.31.2.1  uebayasi 		vd->flags &= ~VTFL_APPLKEYPAD;
    538       1.1  drochner 		break;
    539      1.19  junyoung 	case 'E': /* NEL */
    540  1.31.2.1  uebayasi 		vd->ccol = 0;
    541       1.1  drochner 		/* FALLTHRU */
    542      1.19  junyoung 	case 'D': /* IND */
    543      1.21  sommerfe 		wsemul_vt100_nextline(edp);
    544       1.1  drochner 		break;
    545      1.19  junyoung 	case 'H': /* HTS */
    546  1.31.2.1  uebayasi 		KASSERT(vd->tabs != 0);
    547  1.31.2.1  uebayasi 		vd->tabs[vd->ccol] = 1;
    548       1.1  drochner 		break;
    549      1.19  junyoung 	case '~': /* LS1R */
    550       1.3  drochner 		edp->chartab1 = 1;
    551       1.3  drochner 		break;
    552      1.19  junyoung 	case 'n': /* LS2 */
    553       1.3  drochner 		edp->chartab0 = 2;
    554       1.3  drochner 		break;
    555      1.19  junyoung 	case '}': /* LS2R */
    556       1.3  drochner 		edp->chartab1 = 2;
    557       1.3  drochner 		break;
    558      1.19  junyoung 	case 'o': /* LS3 */
    559       1.3  drochner 		edp->chartab0 = 3;
    560       1.3  drochner 		break;
    561      1.19  junyoung 	case '|': /* LS3R */
    562       1.3  drochner 		edp->chartab1 = 3;
    563       1.1  drochner 		break;
    564      1.19  junyoung 	case 'N': /* SS2 */
    565       1.3  drochner 		edp->sschartab = 2;
    566       1.3  drochner 		break;
    567      1.19  junyoung 	case 'O': /* SS3 */
    568       1.3  drochner 		edp->sschartab = 3;
    569       1.1  drochner 		break;
    570      1.19  junyoung 	case 'M': /* RI */
    571  1.31.2.1  uebayasi 		if (ROWS_ABOVE(vd) > 0) {
    572  1.31.2.1  uebayasi 			vd->crow--;
    573  1.31.2.1  uebayasi 			CHECK_DW(vd);
    574       1.1  drochner 			break;
    575       1.1  drochner 		}
    576  1.31.2.1  uebayasi 		wsemul_vt100_scrolldown(vd, 1);
    577       1.1  drochner 		break;
    578      1.19  junyoung 	case 'P': /* DCS */
    579  1.31.2.1  uebayasi 		vd->nargs = 0;
    580  1.31.2.1  uebayasi 		memset(vd->args, 0, sizeof (vd->args));
    581       1.1  drochner 		newstate = VT100_EMUL_STATE_DCS;
    582       1.1  drochner 		break;
    583      1.19  junyoung 	case 'c': /* RIS */
    584       1.1  drochner 		wsemul_vt100_reset(edp);
    585  1.31.2.1  uebayasi 		wsemul_vt100_ed(vd, 2);
    586  1.31.2.1  uebayasi 		vd->ccol = vd->crow = 0;
    587       1.1  drochner 		break;
    588      1.19  junyoung 	case '(': case ')': case '*': case '+': /* SCS */
    589       1.3  drochner 		edp->designating = c - '(';
    590       1.1  drochner 		newstate = VT100_EMUL_STATE_SCS94;
    591       1.1  drochner 		break;
    592      1.19  junyoung 	case '-': case '.': case '/': /* SCS */
    593       1.3  drochner 		edp->designating = c - '-' + 1;
    594       1.1  drochner 		newstate = VT100_EMUL_STATE_SCS96;
    595       1.1  drochner 		break;
    596      1.19  junyoung 	case '#':
    597       1.3  drochner 		newstate = VT100_EMUL_STATE_ESC_HASH;
    598       1.1  drochner 		break;
    599      1.19  junyoung 	case ' ': /* 7/8 bit */
    600       1.1  drochner 		newstate = VT100_EMUL_STATE_ESC_SPC;
    601       1.1  drochner 		break;
    602      1.19  junyoung 	case ']': /* OSC operating system command */
    603      1.19  junyoung 	case '^': /* PM privacy message */
    604      1.19  junyoung 	case '_': /* APC application program command */
    605       1.1  drochner 		/* ignored */
    606       1.1  drochner 		newstate = VT100_EMUL_STATE_STRING;
    607       1.1  drochner 		break;
    608      1.19  junyoung 	case '<': /* exit VT52 mode - ignored */
    609       1.1  drochner 		break;
    610      1.19  junyoung 	default:
    611       1.1  drochner #ifdef VT100_PRINTUNKNOWN
    612       1.1  drochner 		printf("ESC%c unknown\n", c);
    613       1.1  drochner #endif
    614       1.1  drochner 		break;
    615       1.1  drochner 	}
    616       1.1  drochner 
    617       1.1  drochner 	return (newstate);
    618       1.1  drochner }
    619       1.1  drochner 
    620       1.1  drochner static u_int
    621      1.15  augustss wsemul_vt100_output_scs94(struct wsemul_vt100_emuldata *edp, u_char c)
    622       1.1  drochner {
    623       1.1  drochner 	u_int newstate = VT100_EMUL_STATE_NORMAL;
    624       1.1  drochner 
    625       1.1  drochner 	switch (c) {
    626      1.19  junyoung 	case '%': /* probably DEC supplemental graphic */
    627       1.1  drochner 		newstate = VT100_EMUL_STATE_SCS94_PERCENT;
    628       1.1  drochner 		break;
    629      1.19  junyoung 	case 'A': /* british / national */
    630       1.3  drochner 		edp->chartab_G[edp->designating] = edp->nrctab;
    631       1.3  drochner 		break;
    632      1.19  junyoung 	case 'B': /* ASCII */
    633       1.3  drochner 		edp->chartab_G[edp->designating] = 0;
    634       1.3  drochner 		break;
    635      1.19  junyoung 	case '<': /* user preferred supplemental */
    636       1.3  drochner 		/* XXX not really "user" preferred */
    637       1.3  drochner 		edp->chartab_G[edp->designating] = edp->isolatin1tab;
    638       1.3  drochner 		break;
    639      1.19  junyoung 	case '0': /* DEC special graphic */
    640       1.3  drochner 		edp->chartab_G[edp->designating] = edp->decgraphtab;
    641       1.3  drochner 		break;
    642      1.19  junyoung 	case '>': /* DEC tech */
    643       1.3  drochner 		edp->chartab_G[edp->designating] = edp->dectechtab;
    644       1.1  drochner 		break;
    645      1.19  junyoung 	default:
    646       1.1  drochner #ifdef VT100_PRINTUNKNOWN
    647       1.3  drochner 		printf("ESC%c%c unknown\n", edp->designating + '(', c);
    648       1.1  drochner #endif
    649       1.1  drochner 		break;
    650       1.1  drochner 	}
    651       1.1  drochner 	return (newstate);
    652       1.1  drochner }
    653       1.1  drochner 
    654       1.1  drochner static u_int
    655      1.15  augustss wsemul_vt100_output_scs94_percent(struct wsemul_vt100_emuldata *edp, u_char c)
    656       1.1  drochner {
    657       1.1  drochner 	switch (c) {
    658      1.19  junyoung 	case '5': /* DEC supplemental graphic */
    659       1.3  drochner 		/* XXX there are differences */
    660       1.3  drochner 		edp->chartab_G[edp->designating] = edp->isolatin1tab;
    661       1.1  drochner 		break;
    662      1.19  junyoung 	default:
    663       1.1  drochner #ifdef VT100_PRINTUNKNOWN
    664       1.3  drochner 		printf("ESC%c%%%c unknown\n", edp->designating + '(', c);
    665       1.1  drochner #endif
    666       1.1  drochner 		break;
    667       1.1  drochner 	}
    668       1.1  drochner 	return (VT100_EMUL_STATE_NORMAL);
    669       1.1  drochner }
    670       1.1  drochner 
    671       1.1  drochner static u_int
    672      1.15  augustss wsemul_vt100_output_scs96(struct wsemul_vt100_emuldata *edp, u_char c)
    673       1.1  drochner {
    674       1.1  drochner 	u_int newstate = VT100_EMUL_STATE_NORMAL;
    675       1.3  drochner 	int nrc;
    676       1.1  drochner 
    677       1.1  drochner 	switch (c) {
    678      1.31       snj 	case '%': /* probably portuguese */
    679       1.1  drochner 		newstate = VT100_EMUL_STATE_SCS96_PERCENT;
    680       1.1  drochner 		break;
    681      1.19  junyoung 	case 'A': /* ISO-latin-1 supplemental */
    682       1.3  drochner 		edp->chartab_G[edp->designating] = edp->isolatin1tab;
    683       1.3  drochner 		break;
    684      1.19  junyoung 	case '4': /* dutch */
    685       1.3  drochner 		nrc = 1;
    686       1.3  drochner 		goto setnrc;
    687      1.19  junyoung 	case '5': case 'C': /* finnish */
    688       1.3  drochner 		nrc = 2;
    689       1.3  drochner 		goto setnrc;
    690      1.19  junyoung 	case 'R': /* french */
    691       1.3  drochner 		nrc = 3;
    692       1.3  drochner 		goto setnrc;
    693      1.19  junyoung 	case 'Q': /* french canadian */
    694       1.3  drochner 		nrc = 4;
    695       1.3  drochner 		goto setnrc;
    696      1.19  junyoung 	case 'K': /* german */
    697       1.3  drochner 		nrc = 5;
    698       1.3  drochner 		goto setnrc;
    699      1.19  junyoung 	case 'Y': /* italian */
    700       1.3  drochner 		nrc = 6;
    701       1.3  drochner 		goto setnrc;
    702      1.19  junyoung 	case 'E': case '6': /* norwegian / danish */
    703       1.3  drochner 		nrc = 7;
    704       1.3  drochner 		goto setnrc;
    705      1.19  junyoung 	case 'Z': /* spanish */
    706       1.3  drochner 		nrc = 9;
    707       1.3  drochner 		goto setnrc;
    708      1.19  junyoung 	case '7': case 'H': /* swedish */
    709       1.3  drochner 		nrc = 10;
    710       1.3  drochner 		goto setnrc;
    711      1.19  junyoung 	case '=': /* swiss */
    712       1.3  drochner 		nrc = 11;
    713       1.3  drochner setnrc:
    714       1.3  drochner 		vt100_setnrc(edp, nrc); /* what table ??? */
    715       1.1  drochner 		break;
    716      1.19  junyoung 	default:
    717       1.1  drochner #ifdef VT100_PRINTUNKNOWN
    718       1.3  drochner 		printf("ESC%c%c unknown\n", edp->designating + '-' - 1, c);
    719       1.1  drochner #endif
    720       1.1  drochner 		break;
    721       1.1  drochner 	}
    722       1.1  drochner 	return (newstate);
    723       1.1  drochner }
    724       1.1  drochner 
    725       1.1  drochner static u_int
    726      1.15  augustss wsemul_vt100_output_scs96_percent(struct wsemul_vt100_emuldata *edp, u_char c)
    727       1.1  drochner {
    728       1.1  drochner 	switch (c) {
    729      1.31       snj 	case '6': /* portuguese */
    730       1.3  drochner 		vt100_setnrc(edp, 8);
    731       1.1  drochner 		break;
    732      1.19  junyoung 	default:
    733       1.1  drochner #ifdef VT100_PRINTUNKNOWN
    734       1.3  drochner 		printf("ESC%c%%%c unknown\n", edp->designating + '-', c);
    735       1.1  drochner #endif
    736       1.1  drochner 		break;
    737       1.1  drochner 	}
    738       1.1  drochner 	return (VT100_EMUL_STATE_NORMAL);
    739       1.1  drochner }
    740       1.1  drochner 
    741       1.1  drochner static u_int
    742      1.30  christos wsemul_vt100_output_esc_spc(struct wsemul_vt100_emuldata *edp,
    743      1.29  christos     u_char c)
    744       1.1  drochner {
    745       1.1  drochner 	switch (c) {
    746      1.19  junyoung 	case 'F': /* 7-bit controls */
    747      1.19  junyoung 	case 'G': /* 8-bit controls */
    748       1.1  drochner #ifdef VT100_PRINTNOTIMPL
    749       1.1  drochner 		printf("ESC<SPC>%c ignored\n", c);
    750       1.1  drochner #endif
    751       1.1  drochner 		break;
    752      1.19  junyoung 	default:
    753       1.1  drochner #ifdef VT100_PRINTUNKNOWN
    754       1.1  drochner 		printf("ESC<SPC>%c unknown\n", c);
    755       1.1  drochner #endif
    756       1.1  drochner 		break;
    757       1.1  drochner 	}
    758       1.1  drochner 	return (VT100_EMUL_STATE_NORMAL);
    759       1.1  drochner }
    760       1.1  drochner 
    761       1.1  drochner static u_int
    762      1.15  augustss wsemul_vt100_output_string(struct wsemul_vt100_emuldata *edp, u_char c)
    763       1.1  drochner {
    764  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
    765  1.31.2.1  uebayasi 
    766  1.31.2.1  uebayasi 	if (vd->dcstype && vd->dcspos < DCS_MAXLEN)
    767  1.31.2.1  uebayasi 		vd->dcsarg[vd->dcspos++] = c;
    768       1.1  drochner 	return (VT100_EMUL_STATE_STRING);
    769       1.1  drochner }
    770       1.1  drochner 
    771       1.1  drochner static u_int
    772      1.15  augustss wsemul_vt100_output_string_esc(struct wsemul_vt100_emuldata *edp, u_char c)
    773       1.1  drochner {
    774  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
    775  1.31.2.1  uebayasi 
    776       1.1  drochner 	if (c == '\\') { /* ST complete */
    777  1.31.2.1  uebayasi 		wsemul_vt100_handle_dcs(vd);
    778       1.1  drochner 		return (VT100_EMUL_STATE_NORMAL);
    779       1.1  drochner 	} else
    780       1.1  drochner 		return (VT100_EMUL_STATE_STRING);
    781       1.1  drochner }
    782       1.1  drochner 
    783       1.1  drochner static u_int
    784      1.15  augustss wsemul_vt100_output_dcs(struct wsemul_vt100_emuldata *edp, u_char c)
    785       1.1  drochner {
    786  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
    787       1.1  drochner 	u_int newstate = VT100_EMUL_STATE_DCS;
    788       1.1  drochner 
    789       1.1  drochner 	switch (c) {
    790      1.19  junyoung 	case '0': case '1': case '2': case '3': case '4':
    791      1.19  junyoung 	case '5': case '6': case '7': case '8': case '9':
    792       1.1  drochner 		/* argument digit */
    793  1.31.2.1  uebayasi 		if (vd->nargs > VT100_EMUL_NARGS - 1)
    794       1.1  drochner 			break;
    795  1.31.2.1  uebayasi 		vd->args[vd->nargs] = (vd->args[vd->nargs] * 10) +
    796       1.1  drochner 		    (c - '0');
    797       1.1  drochner 		break;
    798      1.19  junyoung 	case ';': /* argument terminator */
    799  1.31.2.1  uebayasi 		vd->nargs++;
    800       1.1  drochner 		break;
    801      1.19  junyoung 	default:
    802  1.31.2.1  uebayasi 		vd->nargs++;
    803  1.31.2.1  uebayasi 		if (vd->nargs > VT100_EMUL_NARGS) {
    804       1.1  drochner #ifdef VT100_DEBUG
    805       1.1  drochner 			printf("vt100: too many arguments\n");
    806       1.1  drochner #endif
    807  1.31.2.1  uebayasi 			vd->nargs = VT100_EMUL_NARGS;
    808       1.1  drochner 		}
    809       1.1  drochner 		newstate = VT100_EMUL_STATE_STRING;
    810       1.1  drochner 		switch (c) {
    811      1.19  junyoung 		case '$':
    812       1.1  drochner 			newstate = VT100_EMUL_STATE_DCS_DOLLAR;
    813       1.1  drochner 			break;
    814      1.19  junyoung 		case '{': /* DECDLD soft charset */
    815      1.19  junyoung 		case '!': /* DECRQUPSS user preferred supplemental set */
    816       1.1  drochner 			/* 'u' must follow - need another state */
    817      1.19  junyoung 		case '|': /* DECUDK program F6..F20 */
    818       1.1  drochner #ifdef VT100_PRINTNOTIMPL
    819       1.1  drochner 			printf("DCS%c ignored\n", c);
    820       1.1  drochner #endif
    821       1.1  drochner 			break;
    822      1.19  junyoung 		default:
    823       1.1  drochner #ifdef VT100_PRINTUNKNOWN
    824  1.31.2.1  uebayasi 			printf("DCS%c (%d, %d) unknown\n", c, ARG(vd, 0), ARG(vd, 1));
    825       1.1  drochner #endif
    826       1.1  drochner 			break;
    827       1.1  drochner 		}
    828       1.1  drochner 	}
    829       1.1  drochner 
    830       1.1  drochner 	return (newstate);
    831       1.1  drochner }
    832       1.1  drochner 
    833       1.1  drochner static u_int
    834      1.15  augustss wsemul_vt100_output_dcs_dollar(struct wsemul_vt100_emuldata *edp, u_char c)
    835       1.1  drochner {
    836  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
    837  1.31.2.1  uebayasi 
    838       1.1  drochner 	switch (c) {
    839      1.19  junyoung 	case 'p': /* DECRSTS terminal state restore */
    840      1.19  junyoung 	case 'q': /* DECRQSS control function request */
    841       1.1  drochner #ifdef VT100_PRINTNOTIMPL
    842       1.1  drochner 		printf("DCS$%c ignored\n", c);
    843       1.1  drochner #endif
    844       1.1  drochner 		break;
    845      1.19  junyoung 	case 't': /* DECRSPS restore presentation state */
    846  1.31.2.1  uebayasi 		switch (ARG(vd, 0)) {
    847      1.19  junyoung 		case 0: /* error */
    848       1.1  drochner 			break;
    849      1.19  junyoung 		case 1: /* cursor information restore */
    850       1.1  drochner #ifdef VT100_PRINTNOTIMPL
    851       1.1  drochner 			printf("DCS1$t ignored\n");
    852       1.1  drochner #endif
    853       1.1  drochner 			break;
    854      1.19  junyoung 		case 2: /* tab stop restore */
    855  1.31.2.1  uebayasi 			vd->dcspos = 0;
    856  1.31.2.1  uebayasi 			vd->dcstype = DCSTYPE_TABRESTORE;
    857       1.1  drochner 			break;
    858      1.19  junyoung 		default:
    859       1.1  drochner #ifdef VT100_PRINTUNKNOWN
    860  1.31.2.1  uebayasi 			printf("DCS%d$t unknown\n", ARG(vd, 0));
    861       1.1  drochner #endif
    862       1.1  drochner 			break;
    863       1.1  drochner 		}
    864       1.1  drochner 		break;
    865      1.19  junyoung 	default:
    866       1.1  drochner #ifdef VT100_PRINTUNKNOWN
    867  1.31.2.1  uebayasi 		printf("DCS$%c (%d, %d) unknown\n", c, ARG(vd, 0), ARG(vd, 1));
    868       1.1  drochner #endif
    869       1.1  drochner 		break;
    870       1.1  drochner 	}
    871       1.1  drochner 	return (VT100_EMUL_STATE_STRING);
    872       1.1  drochner }
    873       1.1  drochner 
    874       1.1  drochner static u_int
    875      1.15  augustss wsemul_vt100_output_esc_hash(struct wsemul_vt100_emuldata *edp, u_char c)
    876       1.1  drochner {
    877  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
    878      1.23  drochner 	int i, j;
    879       1.1  drochner 
    880       1.1  drochner 	switch (c) {
    881      1.19  junyoung 	case '5': /*  DECSWL single width, single height */
    882  1.31.2.1  uebayasi 		if (vd->dw) {
    883  1.31.2.1  uebayasi 			for (i = 0; i < vd->ncols / 2; i++)
    884  1.31.2.1  uebayasi 				(*vd->emulops->copycols)(vd->emulcookie,
    885  1.31.2.1  uebayasi 							  vd->crow,
    886       1.3  drochner 							  2 * i, i, 1);
    887  1.31.2.1  uebayasi 			(*vd->emulops->erasecols)(vd->emulcookie, vd->crow,
    888  1.31.2.1  uebayasi 						   i, vd->ncols - i,
    889  1.31.2.1  uebayasi 						   vd->bkgdattr);
    890  1.31.2.1  uebayasi 			vd->dblwid[vd->crow] = 0;
    891  1.31.2.1  uebayasi 			vd->dw = 0;
    892       1.1  drochner 		}
    893       1.1  drochner 		break;
    894      1.19  junyoung 	case '6': /*  DECDWL double width, single height */
    895      1.19  junyoung 	case '3': /*  DECDHL double width, double height, top half */
    896      1.19  junyoung 	case '4': /*  DECDHL double width, double height, bottom half */
    897  1.31.2.1  uebayasi 		if (!vd->dw) {
    898  1.31.2.1  uebayasi 			for (i = vd->ncols / 2 - 1; i >= 0; i--)
    899  1.31.2.1  uebayasi 				(*vd->emulops->copycols)(vd->emulcookie,
    900  1.31.2.1  uebayasi 							  vd->crow,
    901       1.3  drochner 							  i, 2 * i, 1);
    902  1.31.2.1  uebayasi 			for (i = 0; i < vd->ncols / 2; i++)
    903  1.31.2.1  uebayasi 				(*vd->emulops->erasecols)(vd->emulcookie,
    904  1.31.2.1  uebayasi 							   vd->crow,
    905       1.3  drochner 							   2 * i + 1, 1,
    906  1.31.2.1  uebayasi 							   vd->bkgdattr);
    907  1.31.2.1  uebayasi 			vd->dblwid[vd->crow] = 1;
    908  1.31.2.1  uebayasi 			vd->dw = 1;
    909  1.31.2.1  uebayasi 			if (vd->ccol > (vd->ncols >> 1) - 1)
    910  1.31.2.1  uebayasi 				vd->ccol = (vd->ncols >> 1) - 1;
    911       1.3  drochner 		}
    912       1.1  drochner 		break;
    913      1.23  drochner 	case '8': /* DECALN */
    914  1.31.2.1  uebayasi 		for (i = 0; i < vd->nrows; i++)
    915  1.31.2.1  uebayasi 			for (j = 0; j < vd->ncols; j++)
    916  1.31.2.1  uebayasi 				(*vd->emulops->putchar)(vd->emulcookie, i, j,
    917  1.31.2.1  uebayasi 							 'E', vd->curattr);
    918  1.31.2.1  uebayasi 		vd->ccol = 0;
    919  1.31.2.1  uebayasi 		vd->crow = 0;
    920       1.1  drochner 		break;
    921      1.19  junyoung 	default:
    922       1.1  drochner #ifdef VT100_PRINTUNKNOWN
    923       1.1  drochner 		printf("ESC#%c unknown\n", c);
    924       1.1  drochner #endif
    925       1.1  drochner 		break;
    926       1.1  drochner 	}
    927       1.1  drochner 	return (VT100_EMUL_STATE_NORMAL);
    928       1.1  drochner }
    929       1.1  drochner 
    930       1.1  drochner static u_int
    931      1.15  augustss wsemul_vt100_output_csi(struct wsemul_vt100_emuldata *edp, u_char c)
    932       1.1  drochner {
    933  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
    934       1.1  drochner 	u_int newstate = VT100_EMUL_STATE_CSI;
    935       1.1  drochner 
    936       1.1  drochner 	switch (c) {
    937      1.19  junyoung 	case '0': case '1': case '2': case '3': case '4':
    938      1.19  junyoung 	case '5': case '6': case '7': case '8': case '9':
    939       1.1  drochner 		/* argument digit */
    940  1.31.2.1  uebayasi 		if (vd->nargs > VT100_EMUL_NARGS - 1)
    941       1.1  drochner 			break;
    942  1.31.2.1  uebayasi 		vd->args[vd->nargs] = (vd->args[vd->nargs] * 10) +
    943       1.1  drochner 		    (c - '0');
    944       1.1  drochner 		break;
    945      1.19  junyoung 	case ';': /* argument terminator */
    946  1.31.2.1  uebayasi 		vd->nargs++;
    947       1.1  drochner 		break;
    948      1.19  junyoung 	case '?': /* DEC specific */
    949      1.19  junyoung 	case '>': /* DA query */
    950  1.31.2.1  uebayasi 		vd->modif1 = c;
    951       1.1  drochner 		break;
    952      1.19  junyoung 	case '!':
    953      1.19  junyoung 	case '"':
    954      1.19  junyoung 	case '$':
    955      1.19  junyoung 	case '&':
    956  1.31.2.1  uebayasi 		vd->modif2 = c;
    957       1.1  drochner 		break;
    958      1.19  junyoung 	default: /* end of escape sequence */
    959  1.31.2.1  uebayasi 		vd->nargs++;
    960  1.31.2.1  uebayasi 		if (vd->nargs > VT100_EMUL_NARGS) {
    961       1.1  drochner #ifdef VT100_DEBUG
    962       1.1  drochner 			printf("vt100: too many arguments\n");
    963       1.1  drochner #endif
    964  1.31.2.1  uebayasi 			vd->nargs = VT100_EMUL_NARGS;
    965       1.1  drochner 		}
    966  1.31.2.1  uebayasi 		wsemul_vt100_handle_csi(vd, c);
    967       1.1  drochner 		newstate = VT100_EMUL_STATE_NORMAL;
    968       1.1  drochner 		break;
    969       1.1  drochner 	}
    970       1.1  drochner 	return (newstate);
    971       1.1  drochner }
    972       1.1  drochner 
    973       1.1  drochner void
    974      1.15  augustss wsemul_vt100_output(void *cookie, const u_char *data, u_int count, int kernel)
    975       1.1  drochner {
    976       1.1  drochner 	struct wsemul_vt100_emuldata *edp = cookie;
    977  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
    978       1.1  drochner 
    979       1.1  drochner #ifdef DIAGNOSTIC
    980       1.1  drochner 	if (kernel && !edp->console)
    981       1.1  drochner 		panic("wsemul_vt100_output: kernel output, not console");
    982       1.1  drochner #endif
    983       1.1  drochner 
    984  1.31.2.1  uebayasi 	if (vd->flags & VTFL_CURSORON)
    985  1.31.2.1  uebayasi 		(*vd->emulops->cursor)(vd->emulcookie, 0,
    986  1.31.2.1  uebayasi 					vd->crow, vd->ccol << vd->dw);
    987       1.1  drochner 	for (; count > 0; data++, count--) {
    988       1.7  drochner 		if ((*data & 0x7f) < 0x20) {
    989       1.7  drochner 			wsemul_vt100_output_c0c1(edp, *data, kernel);
    990       1.7  drochner 			continue;
    991       1.7  drochner 		}
    992       1.1  drochner 		if (edp->state == VT100_EMUL_STATE_NORMAL || kernel) {
    993       1.7  drochner 			wsemul_vt100_output_normal(edp, *data, kernel);
    994       1.1  drochner 			continue;
    995       1.1  drochner 		}
    996       1.1  drochner #ifdef DIAGNOSTIC
    997       1.1  drochner 		if (edp->state > sizeof(vt100_output) / sizeof(vt100_output[0]))
    998      1.20    provos 			panic("wsemul_vt100: invalid state %d", edp->state);
    999       1.1  drochner #endif
   1000       1.1  drochner 		edp->state = vt100_output[edp->state - 1](edp, *data);
   1001       1.1  drochner 	}
   1002  1.31.2.1  uebayasi 	if (vd->flags & VTFL_CURSORON)
   1003  1.31.2.1  uebayasi 		(*vd->emulops->cursor)(vd->emulcookie, 1,
   1004  1.31.2.1  uebayasi 					vd->crow, vd->ccol << vd->dw);
   1005       1.1  drochner }
   1006      1.26      jmmv 
   1007      1.26      jmmv #ifdef WSDISPLAY_CUSTOM_OUTPUT
   1008      1.26      jmmv static void
   1009      1.26      jmmv wsemul_vt100_getmsgattrs(void *cookie, struct wsdisplay_msgattrs *ma)
   1010      1.26      jmmv {
   1011      1.26      jmmv 	struct wsemul_vt100_emuldata *edp = cookie;
   1012  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
   1013      1.26      jmmv 
   1014  1.31.2.1  uebayasi 	*ma = vd->msgattrs;
   1015      1.26      jmmv }
   1016      1.26      jmmv 
   1017      1.26      jmmv static void
   1018      1.26      jmmv wsemul_vt100_setmsgattrs(void *cookie, const struct wsscreen_descr *type,
   1019      1.26      jmmv                          const struct wsdisplay_msgattrs *ma)
   1020      1.26      jmmv {
   1021      1.26      jmmv 	int error;
   1022      1.26      jmmv 	long tmp;
   1023      1.26      jmmv 	struct wsemul_vt100_emuldata *edp = cookie;
   1024  1.31.2.1  uebayasi 	struct vt100base_data *vd = &edp->bd;
   1025      1.26      jmmv 
   1026  1.31.2.1  uebayasi 	vd->msgattrs = *ma;
   1027      1.26      jmmv 	if (type->capabilities & WSSCREEN_WSCOLORS) {
   1028  1.31.2.1  uebayasi 		vd->msgattrs.default_attrs |= WSATTR_WSCOLORS;
   1029  1.31.2.1  uebayasi 		vd->msgattrs.kernel_attrs |= WSATTR_WSCOLORS;
   1030      1.26      jmmv 	} else {
   1031  1.31.2.1  uebayasi 		vd->msgattrs.default_bg = vd->msgattrs.kernel_bg = 0;
   1032  1.31.2.1  uebayasi 		vd->msgattrs.default_fg = vd->msgattrs.kernel_fg = 0;
   1033      1.26      jmmv 	}
   1034      1.26      jmmv 
   1035  1.31.2.1  uebayasi 	error = (*vd->emulops->allocattr)(vd->emulcookie,
   1036  1.31.2.1  uebayasi 	                                   vd->msgattrs.default_fg,
   1037  1.31.2.1  uebayasi 					   vd->msgattrs.default_bg,
   1038  1.31.2.1  uebayasi 	                                   vd->msgattrs.default_attrs,
   1039      1.26      jmmv 	                                   &tmp);
   1040      1.26      jmmv #ifdef VT100_DEBUG
   1041      1.26      jmmv 	if (error)
   1042      1.26      jmmv 		printf("vt100: failed to allocate attribute for default "
   1043      1.26      jmmv 		       "messages\n");
   1044      1.26      jmmv 	else
   1045      1.26      jmmv #endif
   1046      1.26      jmmv 	{
   1047  1.31.2.1  uebayasi 		if (vd->curattr == vd->defattr) {
   1048  1.31.2.1  uebayasi 			vd->bkgdattr = vd->curattr = tmp;
   1049  1.31.2.1  uebayasi 			vd->attrflags = vd->msgattrs.default_attrs;
   1050  1.31.2.1  uebayasi 			vd->bgcol = vd->msgattrs.default_bg;
   1051  1.31.2.1  uebayasi 			vd->fgcol = vd->msgattrs.default_fg;
   1052      1.26      jmmv 		} else {
   1053      1.26      jmmv 			edp->savedbkgdattr = edp->savedattr = tmp;
   1054  1.31.2.1  uebayasi 			edp->savedattrflags = vd->msgattrs.default_attrs;
   1055  1.31.2.1  uebayasi 			edp->savedbgcol = vd->msgattrs.default_bg;
   1056  1.31.2.1  uebayasi 			edp->savedfgcol = vd->msgattrs.default_fg;
   1057      1.26      jmmv 		}
   1058  1.31.2.1  uebayasi 		if (vd->emulops->replaceattr != NULL)
   1059  1.31.2.1  uebayasi 			(*vd->emulops->replaceattr)(vd->emulcookie,
   1060  1.31.2.1  uebayasi 			                             vd->defattr, tmp);
   1061  1.31.2.1  uebayasi 		vd->defattr = tmp;
   1062      1.26      jmmv 	}
   1063      1.26      jmmv 
   1064  1.31.2.1  uebayasi 	error = (*vd->emulops->allocattr)(vd->emulcookie,
   1065  1.31.2.1  uebayasi 	                                   vd->msgattrs.kernel_fg,
   1066  1.31.2.1  uebayasi 					   vd->msgattrs.kernel_bg,
   1067  1.31.2.1  uebayasi 	                                   vd->msgattrs.kernel_attrs,
   1068      1.26      jmmv 	                                   &tmp);
   1069      1.26      jmmv #ifdef VT100_DEBUG
   1070      1.26      jmmv 	if (error)
   1071      1.26      jmmv 		printf("vt100: failed to allocate attribute for kernel "
   1072      1.26      jmmv 		       "messages\n");
   1073      1.26      jmmv 	else
   1074      1.26      jmmv #endif
   1075      1.26      jmmv 	{
   1076  1.31.2.1  uebayasi 		if (vd->emulops->replaceattr != NULL)
   1077  1.31.2.1  uebayasi 			(*vd->emulops->replaceattr)(vd->emulcookie,
   1078      1.26      jmmv 			                             edp->kernattr, tmp);
   1079      1.26      jmmv 		edp->kernattr = tmp;
   1080      1.26      jmmv 	}
   1081      1.26      jmmv }
   1082      1.26      jmmv #endif /* WSDISPLAY_CUSTOM_OUTPUT */
   1083