Home | History | Annotate | Line # | Download | only in wscons
wsemul_vt100.c revision 1.35.20.2
      1  1.35.20.1       tls /* $NetBSD: wsemul_vt100.c,v 1.35.20.2 2017/12/03 11:37:37 jdolecek 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.35.20.1       tls __KERNEL_RCSID(0, "$NetBSD: wsemul_vt100.c,v 1.35.20.2 2017/12/03 11:37:37 jdolecek Exp $");
     31       1.26      jmmv 
     32  1.35.20.2  jdolecek #ifdef _KERNEL_OPT
     33       1.26      jmmv #include "opt_wsmsgattrs.h"
     34  1.35.20.2  jdolecek #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.35.20.2  jdolecek 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.35.20.2  jdolecek 	.name = "vt100",
     64  1.35.20.2  jdolecek 	.cnattach = wsemul_vt100_cnattach,
     65  1.35.20.2  jdolecek 	.attach = wsemul_vt100_attach,
     66  1.35.20.2  jdolecek 	.output = wsemul_vt100_output,
     67  1.35.20.2  jdolecek 	.translate = wsemul_vt100_translate,
     68  1.35.20.2  jdolecek 	.detach = wsemul_vt100_detach,
     69  1.35.20.2  jdolecek 	.reset = wsemul_vt100_resetop,
     70       1.26      jmmv #ifdef WSDISPLAY_CUSTOM_OUTPUT
     71  1.35.20.2  jdolecek 	.getmsgattrs = wsemul_vt100_getmsgattrs,
     72  1.35.20.2  jdolecek 	.setmsgattrs = wsemul_vt100_setmsgattrs,
     73       1.26      jmmv #else
     74  1.35.20.2  jdolecek 	.getmsgattrs = NULL,
     75  1.35.20.2  jdolecek 	.setmsgattrs = NULL,
     76       1.26      jmmv #endif
     77  1.35.20.2  jdolecek 	.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 		KASSERT(edp->console == 1);
    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.35.20.2  jdolecek 	vd->tabs = malloc(1024, M_DEVBUF, M_NOWAIT);
    257  1.35.20.2  jdolecek 	vd->dblwid = malloc(1024, 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.35.20.2  jdolecek static void
    291  1.35.20.2  jdolecek wsemul_vt100_resize(void * cookie, const struct wsscreen_descr *type)
    292  1.35.20.2  jdolecek {
    293  1.35.20.2  jdolecek 	struct wsemul_vt100_emuldata *edp = cookie;
    294  1.35.20.2  jdolecek 
    295  1.35.20.2  jdolecek 	edp->bd.nrows = type->nrows;
    296  1.35.20.2  jdolecek 	edp->bd.ncols = type->ncols;
    297  1.35.20.2  jdolecek 	wsemul_vt100_reset(edp);
    298  1.35.20.2  jdolecek 	wsemul_vt100_resetop(cookie, WSEMUL_CLEARSCREEN);
    299  1.35.20.2  jdolecek }
    300  1.35.20.2  jdolecek 
    301        1.9  drochner void
    302       1.15  augustss wsemul_vt100_resetop(void *cookie, enum wsemul_resetops op)
    303        1.9  drochner {
    304        1.9  drochner 	struct wsemul_vt100_emuldata *edp = cookie;
    305       1.32  drochner 	struct vt100base_data *vd = &edp->bd;
    306        1.9  drochner 
    307        1.9  drochner 	switch (op) {
    308        1.9  drochner 	case WSEMUL_RESET:
    309        1.9  drochner 		wsemul_vt100_reset(edp);
    310        1.9  drochner 		break;
    311        1.9  drochner 	case WSEMUL_SYNCFONT:
    312        1.9  drochner 		vt100_initchartables(edp);
    313       1.10  drochner 		break;
    314       1.10  drochner 	case WSEMUL_CLEARSCREEN:
    315       1.32  drochner 		wsemul_vt100_ed(vd, 2);
    316       1.32  drochner 		vd->ccol = vd->crow = 0;
    317       1.32  drochner 		(*vd->emulops->cursor)(vd->emulcookie,
    318       1.32  drochner 					vd->flags & VTFL_CURSORON, 0, 0);
    319       1.10  drochner 		break;
    320       1.10  drochner 	default:
    321        1.9  drochner 		break;
    322        1.9  drochner 	}
    323        1.1  drochner }
    324        1.1  drochner 
    325        1.1  drochner void
    326       1.15  augustss wsemul_vt100_reset(struct wsemul_vt100_emuldata *edp)
    327        1.1  drochner {
    328       1.32  drochner 	struct vt100base_data *vd = &edp->bd;
    329        1.1  drochner 	int i;
    330        1.1  drochner 
    331        1.1  drochner 	edp->state = VT100_EMUL_STATE_NORMAL;
    332       1.32  drochner 	vd->flags = VTFL_DECAWM | VTFL_CURSORON;
    333       1.32  drochner 	vd->bkgdattr = vd->curattr = vd->defattr;
    334       1.32  drochner 	vd->attrflags = vd->msgattrs.default_attrs;
    335       1.32  drochner 	vd->fgcol = vd->msgattrs.default_fg;
    336       1.32  drochner 	vd->bgcol = vd->msgattrs.default_bg;
    337       1.32  drochner 	vd->scrreg_startrow = 0;
    338       1.32  drochner 	vd->scrreg_nrows = vd->nrows;
    339       1.32  drochner 	if (vd->tabs) {
    340       1.32  drochner 		memset(vd->tabs, 0, vd->ncols);
    341       1.32  drochner 		for (i = 8; i < vd->ncols; i += 8)
    342       1.32  drochner 			vd->tabs[i] = 1;
    343        1.1  drochner 	}
    344       1.32  drochner 	vd->dcspos = 0;
    345       1.32  drochner 	vd->dcstype = 0;
    346        1.3  drochner 	edp->chartab_G[0] = 0;
    347        1.3  drochner 	edp->chartab_G[1] = edp->nrctab; /* ??? */
    348        1.3  drochner 	edp->chartab_G[2] = edp->isolatin1tab;
    349        1.3  drochner 	edp->chartab_G[3] = edp->isolatin1tab;
    350        1.3  drochner 	edp->chartab0 = 0;
    351        1.3  drochner 	edp->chartab1 = 2;
    352        1.3  drochner 	edp->sschartab = 0;
    353        1.1  drochner }
    354        1.1  drochner 
    355        1.1  drochner /*
    356        1.1  drochner  * now all the state machine bits
    357        1.1  drochner  */
    358        1.1  drochner 
    359       1.21  sommerfe /*
    360       1.21  sommerfe  * Move the cursor to the next line if possible. If the cursor is at
    361       1.21  sommerfe  * the bottom of the scroll area, then scroll it up. If the cursor is
    362       1.21  sommerfe  * at the bottom of the screen then don't move it down.
    363       1.21  sommerfe  */
    364        1.7  drochner static void
    365       1.21  sommerfe wsemul_vt100_nextline(struct wsemul_vt100_emuldata *edp)
    366       1.21  sommerfe {
    367       1.32  drochner 	struct vt100base_data *vd = &edp->bd;
    368       1.32  drochner 
    369       1.32  drochner 	if (ROWS_BELOW(vd) == 0) {
    370       1.21  sommerfe 		/* Bottom of the scroll region. */
    371       1.32  drochner 	  	wsemul_vt100_scrollup(vd, 1);
    372       1.21  sommerfe 	} else {
    373       1.32  drochner 		if ((vd->crow+1) < vd->nrows)
    374       1.21  sommerfe 			/* Cursor not at the bottom of the screen. */
    375       1.32  drochner 			vd->crow++;
    376       1.32  drochner 		CHECK_DW(vd);
    377       1.21  sommerfe 	}
    378       1.27     perry }
    379       1.21  sommerfe 
    380       1.22  sommerfe static void
    381       1.15  augustss wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *edp, u_char c,
    382       1.15  augustss 	int kernel)
    383        1.1  drochner {
    384       1.32  drochner 	struct vt100base_data *vd = &edp->bd;
    385        1.7  drochner 	u_int *ct, dc;
    386        1.7  drochner 
    387       1.32  drochner 	if ((vd->flags & (VTFL_LASTCHAR | VTFL_DECAWM)) ==
    388        1.7  drochner 	    (VTFL_LASTCHAR | VTFL_DECAWM)) {
    389       1.21  sommerfe 		wsemul_vt100_nextline(edp);
    390       1.32  drochner 		vd->ccol = 0;
    391       1.32  drochner 		vd->flags &= ~VTFL_LASTCHAR;
    392        1.7  drochner 	}
    393        1.7  drochner 
    394        1.7  drochner 	if (c & 0x80) {
    395        1.7  drochner 		c &= 0x7f;
    396        1.7  drochner 		ct = edp->chartab_G[edp->chartab1];
    397        1.7  drochner 	} else {
    398        1.7  drochner 		if (edp->sschartab) {
    399        1.7  drochner 			ct = edp->chartab_G[edp->sschartab];
    400        1.7  drochner 			edp->sschartab = 0;
    401        1.7  drochner 		} else
    402        1.7  drochner 			ct = edp->chartab_G[edp->chartab0];
    403        1.7  drochner 	}
    404        1.7  drochner 	dc = (ct ? ct[c] : c);
    405        1.7  drochner 
    406       1.32  drochner 	if ((vd->flags & VTFL_INSERTMODE) && COLS_LEFT(vd))
    407       1.32  drochner 		COPYCOLS(vd, vd->ccol, vd->ccol + 1, COLS_LEFT(vd));
    408        1.7  drochner 
    409       1.32  drochner 	(*vd->emulops->putchar)(vd->emulcookie, vd->crow,
    410       1.32  drochner 				 vd->ccol << vd->dw, dc,
    411       1.32  drochner 				 kernel ? edp->kernattr : vd->curattr);
    412        1.7  drochner 
    413       1.32  drochner 	if (COLS_LEFT(vd))
    414       1.32  drochner 		vd->ccol++;
    415        1.7  drochner 	else
    416       1.32  drochner 		vd->flags |= VTFL_LASTCHAR;
    417        1.7  drochner }
    418        1.7  drochner 
    419        1.7  drochner static void
    420       1.27     perry wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *edp, u_char c,
    421       1.15  augustss 	int kernel)
    422        1.7  drochner {
    423       1.32  drochner 	struct vt100base_data *vd = &edp->bd;
    424        1.7  drochner 	u_int n;
    425        1.1  drochner 
    426        1.1  drochner 	switch (c) {
    427       1.19  junyoung 	case ASCII_NUL:
    428       1.19  junyoung 	default:
    429        1.1  drochner 		/* ignore */
    430        1.1  drochner 		break;
    431       1.19  junyoung 	case ASCII_BEL:
    432       1.32  drochner 		wsdisplay_emulbell(vd->cbcookie);
    433        1.1  drochner 		break;
    434       1.19  junyoung 	case ASCII_BS:
    435       1.32  drochner 		if (vd->ccol > 0) {
    436       1.32  drochner 			vd->ccol--;
    437       1.32  drochner 			vd->flags &= ~VTFL_LASTCHAR;
    438        1.1  drochner 		}
    439        1.1  drochner 		break;
    440       1.19  junyoung 	case ASCII_CR:
    441       1.32  drochner 		vd->ccol = 0;
    442       1.32  drochner 		vd->flags &= ~VTFL_LASTCHAR;
    443        1.1  drochner 		break;
    444       1.19  junyoung 	case ASCII_HT:
    445       1.32  drochner 		if (vd->tabs) {
    446       1.32  drochner 			if (!COLS_LEFT(vd))
    447        1.1  drochner 				break;
    448       1.32  drochner 			for (n = vd->ccol + 1; n < NCOLS(vd) - 1; n++)
    449       1.32  drochner 				if (vd->tabs[n])
    450        1.1  drochner 					break;
    451        1.1  drochner 		} else {
    452       1.32  drochner 			n = vd->ccol + min(8 - (vd->ccol & 7), COLS_LEFT(vd));
    453        1.1  drochner 		}
    454       1.32  drochner 		vd->ccol = n;
    455        1.1  drochner 		break;
    456       1.19  junyoung 	case ASCII_SO: /* LS1 */
    457        1.3  drochner 		edp->chartab0 = 1;
    458        1.3  drochner 		break;
    459       1.19  junyoung 	case ASCII_SI: /* LS0 */
    460        1.3  drochner 		edp->chartab0 = 0;
    461        1.1  drochner 		break;
    462       1.19  junyoung 	case ASCII_ESC:
    463       1.14  jdolecek 		if (kernel) {
    464       1.14  jdolecek 			printf("wsemul_vt100_output_c0c1: ESC in kernel output ignored\n");
    465       1.14  jdolecek 			break;	/* ignore the ESC */
    466       1.14  jdolecek 		}
    467       1.14  jdolecek 
    468        1.7  drochner 		if (edp->state == VT100_EMUL_STATE_STRING) {
    469        1.7  drochner 			/* might be a string end */
    470        1.7  drochner 			edp->state = VT100_EMUL_STATE_STRING_ESC;
    471        1.7  drochner 		} else {
    472        1.7  drochner 			/* XXX cancel current escape sequence */
    473        1.7  drochner 			edp->state = VT100_EMUL_STATE_ESC;
    474        1.7  drochner 		}
    475        1.1  drochner 		break;
    476        1.1  drochner #if 0
    477       1.19  junyoung 	case CSI: /* 8-bit */
    478        1.7  drochner 		/* XXX cancel current escape sequence */
    479        1.1  drochner 		edp->nargs = 0;
    480        1.8  augustss 		memset(edp->args, 0, sizeof (edp->args));
    481        1.3  drochner 		edp->modif1 = edp->modif2 = '\0';
    482        1.7  drochner 		edp->state = VT100_EMUL_STATE_CSI;
    483        1.1  drochner 		break;
    484       1.19  junyoung 	case DCS: /* 8-bit */
    485        1.7  drochner 		/* XXX cancel current escape sequence */
    486        1.1  drochner 		edp->nargs = 0;
    487        1.8  augustss 		memset(edp->args, 0, sizeof (edp->args));
    488        1.7  drochner 		edp->state = VT100_EMUL_STATE_DCS;
    489        1.1  drochner 		break;
    490       1.19  junyoung 	case ST: /* string end 8-bit */
    491        1.7  drochner 		/* XXX only in VT100_EMUL_STATE_STRING */
    492        1.7  drochner 		wsemul_vt100_handle_dcs(edp);
    493        1.7  drochner 		return (VT100_EMUL_STATE_NORMAL);
    494        1.1  drochner #endif
    495       1.19  junyoung 	case ASCII_LF:
    496       1.19  junyoung 	case ASCII_VT:
    497       1.19  junyoung 	case ASCII_FF:
    498       1.21  sommerfe 		wsemul_vt100_nextline(edp);
    499        1.1  drochner 		break;
    500        1.1  drochner 	}
    501        1.1  drochner }
    502        1.1  drochner 
    503        1.1  drochner static u_int
    504       1.15  augustss wsemul_vt100_output_esc(struct wsemul_vt100_emuldata *edp, u_char c)
    505        1.1  drochner {
    506       1.32  drochner 	struct vt100base_data *vd = &edp->bd;
    507        1.1  drochner 	u_int newstate = VT100_EMUL_STATE_NORMAL;
    508        1.3  drochner 	int i;
    509        1.1  drochner 
    510        1.1  drochner 	switch (c) {
    511       1.19  junyoung 	case '[': /* CSI */
    512       1.32  drochner 		vd->nargs = 0;
    513       1.32  drochner 		memset(vd->args, 0, sizeof (vd->args));
    514       1.32  drochner 		vd->modif1 = vd->modif2 = '\0';
    515        1.1  drochner 		newstate = VT100_EMUL_STATE_CSI;
    516        1.1  drochner 		break;
    517       1.19  junyoung 	case '7': /* DECSC */
    518       1.32  drochner 		vd->flags |= VTFL_SAVEDCURS;
    519       1.32  drochner 		edp->savedcursor_row = vd->crow;
    520       1.32  drochner 		edp->savedcursor_col = vd->ccol;
    521       1.32  drochner 		edp->savedattr = vd->curattr;
    522       1.32  drochner 		edp->savedbkgdattr = vd->bkgdattr;
    523       1.32  drochner 		edp->savedattrflags = vd->attrflags;
    524       1.32  drochner 		edp->savedfgcol = vd->fgcol;
    525       1.32  drochner 		edp->savedbgcol = vd->bgcol;
    526        1.3  drochner 		for (i = 0; i < 4; i++)
    527        1.3  drochner 			edp->savedchartab_G[i] = edp->chartab_G[i];
    528        1.3  drochner 		edp->savedchartab0 = edp->chartab0;
    529        1.3  drochner 		edp->savedchartab1 = edp->chartab1;
    530        1.1  drochner 		break;
    531       1.19  junyoung 	case '8': /* DECRC */
    532       1.32  drochner 		if ((vd->flags & VTFL_SAVEDCURS) == 0)
    533       1.24  christos 			break;
    534       1.32  drochner 		vd->crow = edp->savedcursor_row;
    535       1.32  drochner 		vd->ccol = edp->savedcursor_col;
    536       1.32  drochner 		vd->curattr = edp->savedattr;
    537       1.32  drochner 		vd->bkgdattr = edp->savedbkgdattr;
    538       1.32  drochner 		vd->attrflags = edp->savedattrflags;
    539       1.32  drochner 		vd->fgcol = edp->savedfgcol;
    540       1.32  drochner 		vd->bgcol = edp->savedbgcol;
    541        1.3  drochner 		for (i = 0; i < 4; i++)
    542        1.3  drochner 			edp->chartab_G[i] = edp->savedchartab_G[i];
    543        1.3  drochner 		edp->chartab0 = edp->savedchartab0;
    544        1.3  drochner 		edp->chartab1 = edp->savedchartab1;
    545        1.1  drochner 		break;
    546       1.19  junyoung 	case '=': /* DECKPAM application mode */
    547       1.32  drochner 		vd->flags |= VTFL_APPLKEYPAD;
    548        1.1  drochner 		break;
    549       1.19  junyoung 	case '>': /* DECKPNM numeric mode */
    550       1.32  drochner 		vd->flags &= ~VTFL_APPLKEYPAD;
    551        1.1  drochner 		break;
    552       1.19  junyoung 	case 'E': /* NEL */
    553       1.32  drochner 		vd->ccol = 0;
    554        1.1  drochner 		/* FALLTHRU */
    555       1.19  junyoung 	case 'D': /* IND */
    556       1.21  sommerfe 		wsemul_vt100_nextline(edp);
    557        1.1  drochner 		break;
    558       1.19  junyoung 	case 'H': /* HTS */
    559       1.32  drochner 		KASSERT(vd->tabs != 0);
    560       1.32  drochner 		vd->tabs[vd->ccol] = 1;
    561        1.1  drochner 		break;
    562       1.19  junyoung 	case '~': /* LS1R */
    563        1.3  drochner 		edp->chartab1 = 1;
    564        1.3  drochner 		break;
    565       1.19  junyoung 	case 'n': /* LS2 */
    566        1.3  drochner 		edp->chartab0 = 2;
    567        1.3  drochner 		break;
    568       1.19  junyoung 	case '}': /* LS2R */
    569        1.3  drochner 		edp->chartab1 = 2;
    570        1.3  drochner 		break;
    571       1.19  junyoung 	case 'o': /* LS3 */
    572        1.3  drochner 		edp->chartab0 = 3;
    573        1.3  drochner 		break;
    574       1.19  junyoung 	case '|': /* LS3R */
    575        1.3  drochner 		edp->chartab1 = 3;
    576        1.1  drochner 		break;
    577       1.19  junyoung 	case 'N': /* SS2 */
    578        1.3  drochner 		edp->sschartab = 2;
    579        1.3  drochner 		break;
    580       1.19  junyoung 	case 'O': /* SS3 */
    581        1.3  drochner 		edp->sschartab = 3;
    582        1.1  drochner 		break;
    583       1.19  junyoung 	case 'M': /* RI */
    584       1.32  drochner 		if (ROWS_ABOVE(vd) > 0) {
    585       1.32  drochner 			vd->crow--;
    586       1.32  drochner 			CHECK_DW(vd);
    587        1.1  drochner 			break;
    588        1.1  drochner 		}
    589       1.32  drochner 		wsemul_vt100_scrolldown(vd, 1);
    590        1.1  drochner 		break;
    591       1.19  junyoung 	case 'P': /* DCS */
    592       1.32  drochner 		vd->nargs = 0;
    593       1.32  drochner 		memset(vd->args, 0, sizeof (vd->args));
    594        1.1  drochner 		newstate = VT100_EMUL_STATE_DCS;
    595        1.1  drochner 		break;
    596       1.19  junyoung 	case 'c': /* RIS */
    597        1.1  drochner 		wsemul_vt100_reset(edp);
    598       1.32  drochner 		wsemul_vt100_ed(vd, 2);
    599       1.32  drochner 		vd->ccol = vd->crow = 0;
    600        1.1  drochner 		break;
    601       1.19  junyoung 	case '(': case ')': case '*': case '+': /* SCS */
    602        1.3  drochner 		edp->designating = c - '(';
    603        1.1  drochner 		newstate = VT100_EMUL_STATE_SCS94;
    604        1.1  drochner 		break;
    605       1.19  junyoung 	case '-': case '.': case '/': /* SCS */
    606        1.3  drochner 		edp->designating = c - '-' + 1;
    607        1.1  drochner 		newstate = VT100_EMUL_STATE_SCS96;
    608        1.1  drochner 		break;
    609       1.19  junyoung 	case '#':
    610        1.3  drochner 		newstate = VT100_EMUL_STATE_ESC_HASH;
    611        1.1  drochner 		break;
    612       1.19  junyoung 	case ' ': /* 7/8 bit */
    613        1.1  drochner 		newstate = VT100_EMUL_STATE_ESC_SPC;
    614        1.1  drochner 		break;
    615       1.19  junyoung 	case ']': /* OSC operating system command */
    616       1.19  junyoung 	case '^': /* PM privacy message */
    617       1.19  junyoung 	case '_': /* APC application program command */
    618        1.1  drochner 		/* ignored */
    619        1.1  drochner 		newstate = VT100_EMUL_STATE_STRING;
    620        1.1  drochner 		break;
    621       1.19  junyoung 	case '<': /* exit VT52 mode - ignored */
    622        1.1  drochner 		break;
    623       1.19  junyoung 	default:
    624        1.1  drochner #ifdef VT100_PRINTUNKNOWN
    625        1.1  drochner 		printf("ESC%c unknown\n", c);
    626        1.1  drochner #endif
    627        1.1  drochner 		break;
    628        1.1  drochner 	}
    629        1.1  drochner 
    630        1.1  drochner 	return (newstate);
    631        1.1  drochner }
    632        1.1  drochner 
    633        1.1  drochner static u_int
    634       1.15  augustss wsemul_vt100_output_scs94(struct wsemul_vt100_emuldata *edp, u_char c)
    635        1.1  drochner {
    636        1.1  drochner 	u_int newstate = VT100_EMUL_STATE_NORMAL;
    637        1.1  drochner 
    638        1.1  drochner 	switch (c) {
    639       1.19  junyoung 	case '%': /* probably DEC supplemental graphic */
    640        1.1  drochner 		newstate = VT100_EMUL_STATE_SCS94_PERCENT;
    641        1.1  drochner 		break;
    642       1.19  junyoung 	case 'A': /* british / national */
    643        1.3  drochner 		edp->chartab_G[edp->designating] = edp->nrctab;
    644        1.3  drochner 		break;
    645       1.19  junyoung 	case 'B': /* ASCII */
    646        1.3  drochner 		edp->chartab_G[edp->designating] = 0;
    647        1.3  drochner 		break;
    648       1.19  junyoung 	case '<': /* user preferred supplemental */
    649        1.3  drochner 		/* XXX not really "user" preferred */
    650        1.3  drochner 		edp->chartab_G[edp->designating] = edp->isolatin1tab;
    651        1.3  drochner 		break;
    652       1.19  junyoung 	case '0': /* DEC special graphic */
    653        1.3  drochner 		edp->chartab_G[edp->designating] = edp->decgraphtab;
    654        1.3  drochner 		break;
    655       1.19  junyoung 	case '>': /* DEC tech */
    656        1.3  drochner 		edp->chartab_G[edp->designating] = edp->dectechtab;
    657        1.1  drochner 		break;
    658       1.19  junyoung 	default:
    659        1.1  drochner #ifdef VT100_PRINTUNKNOWN
    660        1.3  drochner 		printf("ESC%c%c unknown\n", edp->designating + '(', c);
    661        1.1  drochner #endif
    662        1.1  drochner 		break;
    663        1.1  drochner 	}
    664        1.1  drochner 	return (newstate);
    665        1.1  drochner }
    666        1.1  drochner 
    667        1.1  drochner static u_int
    668       1.15  augustss wsemul_vt100_output_scs94_percent(struct wsemul_vt100_emuldata *edp, u_char c)
    669        1.1  drochner {
    670        1.1  drochner 	switch (c) {
    671       1.19  junyoung 	case '5': /* DEC supplemental graphic */
    672        1.3  drochner 		/* XXX there are differences */
    673        1.3  drochner 		edp->chartab_G[edp->designating] = edp->isolatin1tab;
    674        1.1  drochner 		break;
    675       1.19  junyoung 	default:
    676        1.1  drochner #ifdef VT100_PRINTUNKNOWN
    677        1.3  drochner 		printf("ESC%c%%%c unknown\n", edp->designating + '(', c);
    678        1.1  drochner #endif
    679        1.1  drochner 		break;
    680        1.1  drochner 	}
    681        1.1  drochner 	return (VT100_EMUL_STATE_NORMAL);
    682        1.1  drochner }
    683        1.1  drochner 
    684        1.1  drochner static u_int
    685       1.15  augustss wsemul_vt100_output_scs96(struct wsemul_vt100_emuldata *edp, u_char c)
    686        1.1  drochner {
    687        1.1  drochner 	u_int newstate = VT100_EMUL_STATE_NORMAL;
    688        1.3  drochner 	int nrc;
    689        1.1  drochner 
    690        1.1  drochner 	switch (c) {
    691       1.31       snj 	case '%': /* probably portuguese */
    692        1.1  drochner 		newstate = VT100_EMUL_STATE_SCS96_PERCENT;
    693        1.1  drochner 		break;
    694       1.19  junyoung 	case 'A': /* ISO-latin-1 supplemental */
    695        1.3  drochner 		edp->chartab_G[edp->designating] = edp->isolatin1tab;
    696        1.3  drochner 		break;
    697       1.19  junyoung 	case '4': /* dutch */
    698        1.3  drochner 		nrc = 1;
    699        1.3  drochner 		goto setnrc;
    700       1.19  junyoung 	case '5': case 'C': /* finnish */
    701        1.3  drochner 		nrc = 2;
    702        1.3  drochner 		goto setnrc;
    703       1.19  junyoung 	case 'R': /* french */
    704        1.3  drochner 		nrc = 3;
    705        1.3  drochner 		goto setnrc;
    706       1.19  junyoung 	case 'Q': /* french canadian */
    707        1.3  drochner 		nrc = 4;
    708        1.3  drochner 		goto setnrc;
    709       1.19  junyoung 	case 'K': /* german */
    710        1.3  drochner 		nrc = 5;
    711        1.3  drochner 		goto setnrc;
    712       1.19  junyoung 	case 'Y': /* italian */
    713        1.3  drochner 		nrc = 6;
    714        1.3  drochner 		goto setnrc;
    715       1.19  junyoung 	case 'E': case '6': /* norwegian / danish */
    716        1.3  drochner 		nrc = 7;
    717        1.3  drochner 		goto setnrc;
    718       1.19  junyoung 	case 'Z': /* spanish */
    719        1.3  drochner 		nrc = 9;
    720        1.3  drochner 		goto setnrc;
    721       1.19  junyoung 	case '7': case 'H': /* swedish */
    722        1.3  drochner 		nrc = 10;
    723        1.3  drochner 		goto setnrc;
    724       1.19  junyoung 	case '=': /* swiss */
    725        1.3  drochner 		nrc = 11;
    726        1.3  drochner setnrc:
    727        1.3  drochner 		vt100_setnrc(edp, nrc); /* what table ??? */
    728        1.1  drochner 		break;
    729       1.19  junyoung 	default:
    730        1.1  drochner #ifdef VT100_PRINTUNKNOWN
    731        1.3  drochner 		printf("ESC%c%c unknown\n", edp->designating + '-' - 1, c);
    732        1.1  drochner #endif
    733        1.1  drochner 		break;
    734        1.1  drochner 	}
    735        1.1  drochner 	return (newstate);
    736        1.1  drochner }
    737        1.1  drochner 
    738        1.1  drochner static u_int
    739       1.15  augustss wsemul_vt100_output_scs96_percent(struct wsemul_vt100_emuldata *edp, u_char c)
    740        1.1  drochner {
    741        1.1  drochner 	switch (c) {
    742       1.31       snj 	case '6': /* portuguese */
    743        1.3  drochner 		vt100_setnrc(edp, 8);
    744        1.1  drochner 		break;
    745       1.19  junyoung 	default:
    746        1.1  drochner #ifdef VT100_PRINTUNKNOWN
    747        1.3  drochner 		printf("ESC%c%%%c unknown\n", edp->designating + '-', c);
    748        1.1  drochner #endif
    749        1.1  drochner 		break;
    750        1.1  drochner 	}
    751        1.1  drochner 	return (VT100_EMUL_STATE_NORMAL);
    752        1.1  drochner }
    753        1.1  drochner 
    754        1.1  drochner static u_int
    755       1.30  christos wsemul_vt100_output_esc_spc(struct wsemul_vt100_emuldata *edp,
    756       1.29  christos     u_char c)
    757        1.1  drochner {
    758        1.1  drochner 	switch (c) {
    759       1.19  junyoung 	case 'F': /* 7-bit controls */
    760       1.19  junyoung 	case 'G': /* 8-bit controls */
    761        1.1  drochner #ifdef VT100_PRINTNOTIMPL
    762        1.1  drochner 		printf("ESC<SPC>%c ignored\n", c);
    763        1.1  drochner #endif
    764        1.1  drochner 		break;
    765       1.19  junyoung 	default:
    766        1.1  drochner #ifdef VT100_PRINTUNKNOWN
    767        1.1  drochner 		printf("ESC<SPC>%c unknown\n", c);
    768        1.1  drochner #endif
    769        1.1  drochner 		break;
    770        1.1  drochner 	}
    771        1.1  drochner 	return (VT100_EMUL_STATE_NORMAL);
    772        1.1  drochner }
    773        1.1  drochner 
    774        1.1  drochner static u_int
    775       1.15  augustss wsemul_vt100_output_string(struct wsemul_vt100_emuldata *edp, u_char c)
    776        1.1  drochner {
    777       1.32  drochner 	struct vt100base_data *vd = &edp->bd;
    778       1.32  drochner 
    779       1.32  drochner 	if (vd->dcstype && vd->dcspos < DCS_MAXLEN)
    780       1.32  drochner 		vd->dcsarg[vd->dcspos++] = c;
    781        1.1  drochner 	return (VT100_EMUL_STATE_STRING);
    782        1.1  drochner }
    783        1.1  drochner 
    784        1.1  drochner static u_int
    785       1.15  augustss wsemul_vt100_output_string_esc(struct wsemul_vt100_emuldata *edp, u_char c)
    786        1.1  drochner {
    787       1.32  drochner 	struct vt100base_data *vd = &edp->bd;
    788       1.32  drochner 
    789        1.1  drochner 	if (c == '\\') { /* ST complete */
    790       1.32  drochner 		wsemul_vt100_handle_dcs(vd);
    791        1.1  drochner 		return (VT100_EMUL_STATE_NORMAL);
    792        1.1  drochner 	} else
    793        1.1  drochner 		return (VT100_EMUL_STATE_STRING);
    794        1.1  drochner }
    795        1.1  drochner 
    796        1.1  drochner static u_int
    797       1.15  augustss wsemul_vt100_output_dcs(struct wsemul_vt100_emuldata *edp, u_char c)
    798        1.1  drochner {
    799       1.32  drochner 	struct vt100base_data *vd = &edp->bd;
    800        1.1  drochner 	u_int newstate = VT100_EMUL_STATE_DCS;
    801        1.1  drochner 
    802        1.1  drochner 	switch (c) {
    803       1.19  junyoung 	case '0': case '1': case '2': case '3': case '4':
    804       1.19  junyoung 	case '5': case '6': case '7': case '8': case '9':
    805        1.1  drochner 		/* argument digit */
    806       1.32  drochner 		if (vd->nargs > VT100_EMUL_NARGS - 1)
    807        1.1  drochner 			break;
    808       1.32  drochner 		vd->args[vd->nargs] = (vd->args[vd->nargs] * 10) +
    809        1.1  drochner 		    (c - '0');
    810        1.1  drochner 		break;
    811       1.19  junyoung 	case ';': /* argument terminator */
    812       1.32  drochner 		vd->nargs++;
    813        1.1  drochner 		break;
    814       1.19  junyoung 	default:
    815       1.32  drochner 		vd->nargs++;
    816       1.32  drochner 		if (vd->nargs > VT100_EMUL_NARGS) {
    817        1.1  drochner #ifdef VT100_DEBUG
    818        1.1  drochner 			printf("vt100: too many arguments\n");
    819        1.1  drochner #endif
    820       1.32  drochner 			vd->nargs = VT100_EMUL_NARGS;
    821        1.1  drochner 		}
    822        1.1  drochner 		newstate = VT100_EMUL_STATE_STRING;
    823        1.1  drochner 		switch (c) {
    824       1.19  junyoung 		case '$':
    825        1.1  drochner 			newstate = VT100_EMUL_STATE_DCS_DOLLAR;
    826        1.1  drochner 			break;
    827       1.19  junyoung 		case '{': /* DECDLD soft charset */
    828       1.19  junyoung 		case '!': /* DECRQUPSS user preferred supplemental set */
    829        1.1  drochner 			/* 'u' must follow - need another state */
    830       1.19  junyoung 		case '|': /* DECUDK program F6..F20 */
    831        1.1  drochner #ifdef VT100_PRINTNOTIMPL
    832        1.1  drochner 			printf("DCS%c ignored\n", c);
    833        1.1  drochner #endif
    834        1.1  drochner 			break;
    835       1.19  junyoung 		default:
    836        1.1  drochner #ifdef VT100_PRINTUNKNOWN
    837       1.32  drochner 			printf("DCS%c (%d, %d) unknown\n", c, ARG(vd, 0), ARG(vd, 1));
    838        1.1  drochner #endif
    839        1.1  drochner 			break;
    840        1.1  drochner 		}
    841        1.1  drochner 	}
    842        1.1  drochner 
    843        1.1  drochner 	return (newstate);
    844        1.1  drochner }
    845        1.1  drochner 
    846        1.1  drochner static u_int
    847       1.15  augustss wsemul_vt100_output_dcs_dollar(struct wsemul_vt100_emuldata *edp, u_char c)
    848        1.1  drochner {
    849       1.32  drochner 	struct vt100base_data *vd = &edp->bd;
    850       1.32  drochner 
    851        1.1  drochner 	switch (c) {
    852       1.19  junyoung 	case 'p': /* DECRSTS terminal state restore */
    853       1.19  junyoung 	case 'q': /* DECRQSS control function request */
    854        1.1  drochner #ifdef VT100_PRINTNOTIMPL
    855        1.1  drochner 		printf("DCS$%c ignored\n", c);
    856        1.1  drochner #endif
    857        1.1  drochner 		break;
    858       1.19  junyoung 	case 't': /* DECRSPS restore presentation state */
    859       1.32  drochner 		switch (ARG(vd, 0)) {
    860       1.19  junyoung 		case 0: /* error */
    861        1.1  drochner 			break;
    862       1.19  junyoung 		case 1: /* cursor information restore */
    863        1.1  drochner #ifdef VT100_PRINTNOTIMPL
    864        1.1  drochner 			printf("DCS1$t ignored\n");
    865        1.1  drochner #endif
    866        1.1  drochner 			break;
    867       1.19  junyoung 		case 2: /* tab stop restore */
    868       1.32  drochner 			vd->dcspos = 0;
    869       1.32  drochner 			vd->dcstype = DCSTYPE_TABRESTORE;
    870        1.1  drochner 			break;
    871       1.19  junyoung 		default:
    872        1.1  drochner #ifdef VT100_PRINTUNKNOWN
    873       1.32  drochner 			printf("DCS%d$t unknown\n", ARG(vd, 0));
    874        1.1  drochner #endif
    875        1.1  drochner 			break;
    876        1.1  drochner 		}
    877        1.1  drochner 		break;
    878       1.19  junyoung 	default:
    879        1.1  drochner #ifdef VT100_PRINTUNKNOWN
    880       1.32  drochner 		printf("DCS$%c (%d, %d) unknown\n", c, ARG(vd, 0), ARG(vd, 1));
    881        1.1  drochner #endif
    882        1.1  drochner 		break;
    883        1.1  drochner 	}
    884        1.1  drochner 	return (VT100_EMUL_STATE_STRING);
    885        1.1  drochner }
    886        1.1  drochner 
    887        1.1  drochner static u_int
    888       1.15  augustss wsemul_vt100_output_esc_hash(struct wsemul_vt100_emuldata *edp, u_char c)
    889        1.1  drochner {
    890       1.32  drochner 	struct vt100base_data *vd = &edp->bd;
    891       1.23  drochner 	int i, j;
    892        1.1  drochner 
    893        1.1  drochner 	switch (c) {
    894       1.19  junyoung 	case '5': /*  DECSWL single width, single height */
    895       1.32  drochner 		if (vd->dw) {
    896       1.32  drochner 			for (i = 0; i < vd->ncols / 2; i++)
    897       1.32  drochner 				(*vd->emulops->copycols)(vd->emulcookie,
    898       1.32  drochner 							  vd->crow,
    899        1.3  drochner 							  2 * i, i, 1);
    900       1.32  drochner 			(*vd->emulops->erasecols)(vd->emulcookie, vd->crow,
    901       1.32  drochner 						   i, vd->ncols - i,
    902       1.32  drochner 						   vd->bkgdattr);
    903       1.32  drochner 			vd->dblwid[vd->crow] = 0;
    904       1.32  drochner 			vd->dw = 0;
    905        1.1  drochner 		}
    906        1.1  drochner 		break;
    907       1.19  junyoung 	case '6': /*  DECDWL double width, single height */
    908       1.19  junyoung 	case '3': /*  DECDHL double width, double height, top half */
    909       1.19  junyoung 	case '4': /*  DECDHL double width, double height, bottom half */
    910       1.32  drochner 		if (!vd->dw) {
    911       1.32  drochner 			for (i = vd->ncols / 2 - 1; i >= 0; i--)
    912       1.32  drochner 				(*vd->emulops->copycols)(vd->emulcookie,
    913       1.32  drochner 							  vd->crow,
    914        1.3  drochner 							  i, 2 * i, 1);
    915       1.32  drochner 			for (i = 0; i < vd->ncols / 2; i++)
    916       1.32  drochner 				(*vd->emulops->erasecols)(vd->emulcookie,
    917       1.32  drochner 							   vd->crow,
    918        1.3  drochner 							   2 * i + 1, 1,
    919       1.32  drochner 							   vd->bkgdattr);
    920       1.32  drochner 			vd->dblwid[vd->crow] = 1;
    921       1.32  drochner 			vd->dw = 1;
    922       1.32  drochner 			if (vd->ccol > (vd->ncols >> 1) - 1)
    923       1.32  drochner 				vd->ccol = (vd->ncols >> 1) - 1;
    924        1.3  drochner 		}
    925        1.1  drochner 		break;
    926       1.23  drochner 	case '8': /* DECALN */
    927       1.32  drochner 		for (i = 0; i < vd->nrows; i++)
    928       1.32  drochner 			for (j = 0; j < vd->ncols; j++)
    929       1.32  drochner 				(*vd->emulops->putchar)(vd->emulcookie, i, j,
    930       1.32  drochner 							 'E', vd->curattr);
    931       1.32  drochner 		vd->ccol = 0;
    932       1.32  drochner 		vd->crow = 0;
    933        1.1  drochner 		break;
    934       1.19  junyoung 	default:
    935        1.1  drochner #ifdef VT100_PRINTUNKNOWN
    936        1.1  drochner 		printf("ESC#%c unknown\n", c);
    937        1.1  drochner #endif
    938        1.1  drochner 		break;
    939        1.1  drochner 	}
    940        1.1  drochner 	return (VT100_EMUL_STATE_NORMAL);
    941        1.1  drochner }
    942        1.1  drochner 
    943        1.1  drochner static u_int
    944       1.15  augustss wsemul_vt100_output_csi(struct wsemul_vt100_emuldata *edp, u_char c)
    945        1.1  drochner {
    946       1.32  drochner 	struct vt100base_data *vd = &edp->bd;
    947        1.1  drochner 	u_int newstate = VT100_EMUL_STATE_CSI;
    948        1.1  drochner 
    949        1.1  drochner 	switch (c) {
    950       1.19  junyoung 	case '0': case '1': case '2': case '3': case '4':
    951       1.19  junyoung 	case '5': case '6': case '7': case '8': case '9':
    952        1.1  drochner 		/* argument digit */
    953       1.32  drochner 		if (vd->nargs > VT100_EMUL_NARGS - 1)
    954        1.1  drochner 			break;
    955       1.32  drochner 		vd->args[vd->nargs] = (vd->args[vd->nargs] * 10) +
    956        1.1  drochner 		    (c - '0');
    957        1.1  drochner 		break;
    958       1.19  junyoung 	case ';': /* argument terminator */
    959       1.32  drochner 		vd->nargs++;
    960        1.1  drochner 		break;
    961       1.19  junyoung 	case '?': /* DEC specific */
    962       1.19  junyoung 	case '>': /* DA query */
    963       1.32  drochner 		vd->modif1 = c;
    964        1.1  drochner 		break;
    965       1.19  junyoung 	case '!':
    966       1.19  junyoung 	case '"':
    967       1.19  junyoung 	case '$':
    968       1.19  junyoung 	case '&':
    969       1.32  drochner 		vd->modif2 = c;
    970        1.1  drochner 		break;
    971       1.19  junyoung 	default: /* end of escape sequence */
    972       1.32  drochner 		vd->nargs++;
    973       1.32  drochner 		if (vd->nargs > VT100_EMUL_NARGS) {
    974        1.1  drochner #ifdef VT100_DEBUG
    975        1.1  drochner 			printf("vt100: too many arguments\n");
    976        1.1  drochner #endif
    977       1.32  drochner 			vd->nargs = VT100_EMUL_NARGS;
    978        1.1  drochner 		}
    979       1.32  drochner 		wsemul_vt100_handle_csi(vd, c);
    980        1.1  drochner 		newstate = VT100_EMUL_STATE_NORMAL;
    981        1.1  drochner 		break;
    982        1.1  drochner 	}
    983        1.1  drochner 	return (newstate);
    984        1.1  drochner }
    985        1.1  drochner 
    986        1.1  drochner void
    987       1.15  augustss wsemul_vt100_output(void *cookie, const u_char *data, u_int count, int kernel)
    988        1.1  drochner {
    989        1.1  drochner 	struct wsemul_vt100_emuldata *edp = cookie;
    990       1.32  drochner 	struct vt100base_data *vd = &edp->bd;
    991        1.1  drochner 
    992        1.1  drochner #ifdef DIAGNOSTIC
    993        1.1  drochner 	if (kernel && !edp->console)
    994        1.1  drochner 		panic("wsemul_vt100_output: kernel output, not console");
    995        1.1  drochner #endif
    996        1.1  drochner 
    997       1.32  drochner 	if (vd->flags & VTFL_CURSORON)
    998       1.32  drochner 		(*vd->emulops->cursor)(vd->emulcookie, 0,
    999       1.32  drochner 					vd->crow, vd->ccol << vd->dw);
   1000        1.1  drochner 	for (; count > 0; data++, count--) {
   1001        1.7  drochner 		if ((*data & 0x7f) < 0x20) {
   1002        1.7  drochner 			wsemul_vt100_output_c0c1(edp, *data, kernel);
   1003        1.7  drochner 			continue;
   1004        1.7  drochner 		}
   1005        1.1  drochner 		if (edp->state == VT100_EMUL_STATE_NORMAL || kernel) {
   1006        1.7  drochner 			wsemul_vt100_output_normal(edp, *data, kernel);
   1007        1.1  drochner 			continue;
   1008        1.1  drochner 		}
   1009  1.35.20.2  jdolecek 		KASSERT(edp->state < __arraycount(vt100_output) - 1);
   1010        1.1  drochner 		edp->state = vt100_output[edp->state - 1](edp, *data);
   1011        1.1  drochner 	}
   1012       1.32  drochner 	if (vd->flags & VTFL_CURSORON)
   1013       1.32  drochner 		(*vd->emulops->cursor)(vd->emulcookie, 1,
   1014       1.32  drochner 					vd->crow, vd->ccol << vd->dw);
   1015        1.1  drochner }
   1016       1.26      jmmv 
   1017       1.26      jmmv #ifdef WSDISPLAY_CUSTOM_OUTPUT
   1018       1.26      jmmv static void
   1019       1.26      jmmv wsemul_vt100_getmsgattrs(void *cookie, struct wsdisplay_msgattrs *ma)
   1020       1.26      jmmv {
   1021       1.26      jmmv 	struct wsemul_vt100_emuldata *edp = cookie;
   1022       1.35  drochner 	struct vt100base_data *vd = &edp->bd;
   1023       1.26      jmmv 
   1024       1.32  drochner 	*ma = vd->msgattrs;
   1025       1.26      jmmv }
   1026       1.26      jmmv 
   1027       1.26      jmmv static void
   1028       1.26      jmmv wsemul_vt100_setmsgattrs(void *cookie, const struct wsscreen_descr *type,
   1029       1.26      jmmv                          const struct wsdisplay_msgattrs *ma)
   1030       1.26      jmmv {
   1031       1.26      jmmv 	int error;
   1032       1.26      jmmv 	long tmp;
   1033       1.26      jmmv 	struct wsemul_vt100_emuldata *edp = cookie;
   1034       1.35  drochner 	struct vt100base_data *vd = &edp->bd;
   1035       1.26      jmmv 
   1036       1.32  drochner 	vd->msgattrs = *ma;
   1037       1.26      jmmv 	if (type->capabilities & WSSCREEN_WSCOLORS) {
   1038       1.32  drochner 		vd->msgattrs.default_attrs |= WSATTR_WSCOLORS;
   1039       1.32  drochner 		vd->msgattrs.kernel_attrs |= WSATTR_WSCOLORS;
   1040       1.26      jmmv 	} else {
   1041       1.32  drochner 		vd->msgattrs.default_bg = vd->msgattrs.kernel_bg = 0;
   1042       1.32  drochner 		vd->msgattrs.default_fg = vd->msgattrs.kernel_fg = 0;
   1043       1.26      jmmv 	}
   1044       1.26      jmmv 
   1045       1.32  drochner 	error = (*vd->emulops->allocattr)(vd->emulcookie,
   1046       1.32  drochner 	                                   vd->msgattrs.default_fg,
   1047       1.32  drochner 					   vd->msgattrs.default_bg,
   1048       1.32  drochner 	                                   vd->msgattrs.default_attrs,
   1049       1.26      jmmv 	                                   &tmp);
   1050  1.35.20.1       tls #ifndef VT100_DEBUG
   1051  1.35.20.1       tls 	__USE(error);
   1052  1.35.20.1       tls #else
   1053       1.26      jmmv 	if (error)
   1054       1.26      jmmv 		printf("vt100: failed to allocate attribute for default "
   1055       1.26      jmmv 		       "messages\n");
   1056       1.26      jmmv 	else
   1057       1.26      jmmv #endif
   1058       1.26      jmmv 	{
   1059       1.32  drochner 		if (vd->curattr == vd->defattr) {
   1060       1.32  drochner 			vd->bkgdattr = vd->curattr = tmp;
   1061       1.32  drochner 			vd->attrflags = vd->msgattrs.default_attrs;
   1062       1.32  drochner 			vd->bgcol = vd->msgattrs.default_bg;
   1063       1.32  drochner 			vd->fgcol = vd->msgattrs.default_fg;
   1064       1.26      jmmv 		} else {
   1065       1.26      jmmv 			edp->savedbkgdattr = edp->savedattr = tmp;
   1066       1.32  drochner 			edp->savedattrflags = vd->msgattrs.default_attrs;
   1067       1.32  drochner 			edp->savedbgcol = vd->msgattrs.default_bg;
   1068       1.32  drochner 			edp->savedfgcol = vd->msgattrs.default_fg;
   1069       1.26      jmmv 		}
   1070       1.32  drochner 		if (vd->emulops->replaceattr != NULL)
   1071       1.32  drochner 			(*vd->emulops->replaceattr)(vd->emulcookie,
   1072       1.32  drochner 			                             vd->defattr, tmp);
   1073       1.32  drochner 		vd->defattr = tmp;
   1074       1.26      jmmv 	}
   1075       1.26      jmmv 
   1076       1.32  drochner 	error = (*vd->emulops->allocattr)(vd->emulcookie,
   1077       1.32  drochner 	                                   vd->msgattrs.kernel_fg,
   1078       1.32  drochner 					   vd->msgattrs.kernel_bg,
   1079       1.32  drochner 	                                   vd->msgattrs.kernel_attrs,
   1080       1.26      jmmv 	                                   &tmp);
   1081       1.26      jmmv #ifdef VT100_DEBUG
   1082       1.26      jmmv 	if (error)
   1083       1.26      jmmv 		printf("vt100: failed to allocate attribute for kernel "
   1084       1.26      jmmv 		       "messages\n");
   1085       1.26      jmmv 	else
   1086       1.26      jmmv #endif
   1087       1.26      jmmv 	{
   1088       1.32  drochner 		if (vd->emulops->replaceattr != NULL)
   1089       1.32  drochner 			(*vd->emulops->replaceattr)(vd->emulcookie,
   1090       1.26      jmmv 			                             edp->kernattr, tmp);
   1091       1.26      jmmv 		edp->kernattr = tmp;
   1092       1.26      jmmv 	}
   1093       1.26      jmmv }
   1094       1.26      jmmv #endif /* WSDISPLAY_CUSTOM_OUTPUT */
   1095