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