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