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