Line data Source code
1 : /* $OpenBSD: wsemul_vt100.c,v 1.36 2017/08/10 09:12:32 fcambus Exp $ */
2 : /* $NetBSD: wsemul_vt100.c,v 1.13 2000/04/28 21:56:16 mycroft Exp $ */
3 :
4 : /*
5 : * Copyright (c) 2007, 2013 Miodrag Vallat.
6 : *
7 : * Permission to use, copy, modify, and distribute this software for any
8 : * purpose with or without fee is hereby granted, provided that the above
9 : * copyright notice, this permission notice, and the disclaimer below
10 : * appear in all copies.
11 : *
12 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 : */
20 : /*
21 : * Copyright (c) 1998
22 : * Matthias Drochner. All rights reserved.
23 : *
24 : * Redistribution and use in source and binary forms, with or without
25 : * modification, are permitted provided that the following conditions
26 : * are met:
27 : * 1. Redistributions of source code must retain the above copyright
28 : * notice, this list of conditions and the following disclaimer.
29 : * 2. Redistributions in binary form must reproduce the above copyright
30 : * notice, this list of conditions and the following disclaimer in the
31 : * documentation and/or other materials provided with the distribution.
32 : *
33 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
34 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
36 : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
37 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
38 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
39 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
40 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
41 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
42 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 : *
44 : */
45 :
46 : #include <sys/param.h>
47 : #include <sys/systm.h>
48 : #include <sys/time.h>
49 : #include <sys/malloc.h>
50 : #include <sys/fcntl.h>
51 :
52 : #include <dev/wscons/wscons_features.h>
53 : #include <dev/wscons/wsconsio.h>
54 : #include <dev/wscons/wsdisplayvar.h>
55 : #include <dev/wscons/wsemulvar.h>
56 : #include <dev/wscons/wsemul_vt100var.h>
57 : #include <dev/wscons/ascii.h>
58 :
59 : void *wsemul_vt100_cnattach(const struct wsscreen_descr *, void *,
60 : int, int, long);
61 : void *wsemul_vt100_attach(int, const struct wsscreen_descr *,
62 : void *, int, int, void *, long);
63 : u_int wsemul_vt100_output(void *, const u_char *, u_int, int);
64 : void wsemul_vt100_detach(void *, u_int *, u_int *);
65 : void wsemul_vt100_resetop(void *, enum wsemul_resetops);
66 :
67 : const struct wsemul_ops wsemul_vt100_ops = {
68 : "vt100",
69 : wsemul_vt100_cnattach,
70 : wsemul_vt100_attach,
71 : wsemul_vt100_output,
72 : wsemul_vt100_translate,
73 : wsemul_vt100_detach,
74 : wsemul_vt100_resetop
75 : };
76 :
77 : struct wsemul_vt100_emuldata wsemul_vt100_console_emuldata;
78 :
79 : void wsemul_vt100_init(struct wsemul_vt100_emuldata *,
80 : const struct wsscreen_descr *, void *, int, int, long);
81 : int wsemul_vt100_jump_scroll(struct wsemul_vt100_emuldata *,
82 : const u_char *, u_int, int);
83 : int wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *,
84 : struct wsemul_inputstate *, int);
85 : int wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *,
86 : struct wsemul_inputstate *, int);
87 : int wsemul_vt100_nextline(struct wsemul_vt100_emuldata *);
88 :
89 : typedef int vt100_handler(struct wsemul_vt100_emuldata *, struct
90 : wsemul_inputstate *);
91 : vt100_handler
92 : wsemul_vt100_output_esc,
93 : wsemul_vt100_output_csi,
94 : wsemul_vt100_output_scs94,
95 : wsemul_vt100_output_scs94_percent,
96 : wsemul_vt100_output_scs96,
97 : wsemul_vt100_output_scs96_percent,
98 : wsemul_vt100_output_esc_hash,
99 : wsemul_vt100_output_esc_spc,
100 : wsemul_vt100_output_string,
101 : wsemul_vt100_output_string_esc,
102 : wsemul_vt100_output_dcs,
103 : wsemul_vt100_output_dcs_dollar,
104 : wsemul_vt100_output_esc_percent;
105 :
106 : #define VT100_EMUL_STATE_NORMAL 0 /* normal processing */
107 : #define VT100_EMUL_STATE_ESC 1 /* got ESC */
108 : #define VT100_EMUL_STATE_CSI 2 /* got CSI (ESC[) */
109 : #define VT100_EMUL_STATE_SCS94 3 /* got ESC{()*+} */
110 : #define VT100_EMUL_STATE_SCS94_PERCENT 4 /* got ESC{()*+}% */
111 : #define VT100_EMUL_STATE_SCS96 5 /* got ESC{-./} */
112 : #define VT100_EMUL_STATE_SCS96_PERCENT 6 /* got ESC{-./}% */
113 : #define VT100_EMUL_STATE_ESC_HASH 7 /* got ESC# */
114 : #define VT100_EMUL_STATE_ESC_SPC 8 /* got ESC<SPC> */
115 : #define VT100_EMUL_STATE_STRING 9 /* waiting for ST (ESC\) */
116 : #define VT100_EMUL_STATE_STRING_ESC 10 /* waiting for ST, got ESC */
117 : #define VT100_EMUL_STATE_DCS 11 /* got DCS (ESC P) */
118 : #define VT100_EMUL_STATE_DCS_DOLLAR 12 /* got DCS<p>$ */
119 : #define VT100_EMUL_STATE_ESC_PERCENT 13 /* got ESC% */
120 :
121 : vt100_handler *vt100_output[] = {
122 : wsemul_vt100_output_esc,
123 : wsemul_vt100_output_csi,
124 : wsemul_vt100_output_scs94,
125 : wsemul_vt100_output_scs94_percent,
126 : wsemul_vt100_output_scs96,
127 : wsemul_vt100_output_scs96_percent,
128 : wsemul_vt100_output_esc_hash,
129 : wsemul_vt100_output_esc_spc,
130 : wsemul_vt100_output_string,
131 : wsemul_vt100_output_string_esc,
132 : wsemul_vt100_output_dcs,
133 : wsemul_vt100_output_dcs_dollar,
134 : wsemul_vt100_output_esc_percent,
135 : };
136 :
137 : void
138 0 : wsemul_vt100_init(struct wsemul_vt100_emuldata *edp,
139 : const struct wsscreen_descr *type, void *cookie, int ccol, int crow,
140 : long defattr)
141 : {
142 0 : edp->emulops = type->textops;
143 0 : edp->emulcookie = cookie;
144 0 : edp->scrcapabilities = type->capabilities;
145 0 : edp->nrows = type->nrows;
146 0 : edp->ncols = type->ncols;
147 0 : edp->crow = crow;
148 0 : edp->ccol = ccol;
149 0 : edp->defattr = defattr;
150 0 : wsemul_reset_abortstate(&edp->abortstate);
151 0 : }
152 :
153 : void *
154 0 : wsemul_vt100_cnattach(const struct wsscreen_descr *type, void *cookie, int ccol,
155 : int crow, long defattr)
156 : {
157 : struct wsemul_vt100_emuldata *edp;
158 : int res;
159 :
160 : edp = &wsemul_vt100_console_emuldata;
161 0 : wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr);
162 : #ifdef DIAGNOSTIC
163 0 : edp->console = 1;
164 : #endif
165 0 : edp->cbcookie = NULL;
166 :
167 : #ifndef WS_KERNEL_FG
168 : #define WS_KERNEL_FG WSCOL_WHITE
169 : #endif
170 : #ifndef WS_KERNEL_BG
171 : #define WS_KERNEL_BG WSCOL_BLUE
172 : #endif
173 : #ifndef WS_KERNEL_COLATTR
174 : #define WS_KERNEL_COLATTR 0
175 : #endif
176 : #ifndef WS_KERNEL_MONOATTR
177 : #define WS_KERNEL_MONOATTR 0
178 : #endif
179 0 : if (type->capabilities & WSSCREEN_WSCOLORS)
180 0 : res = (*edp->emulops->alloc_attr)(cookie,
181 : WS_KERNEL_FG, WS_KERNEL_BG,
182 : WS_KERNEL_COLATTR | WSATTR_WSCOLORS, &edp->kernattr);
183 : else
184 0 : res = (*edp->emulops->alloc_attr)(cookie, 0, 0,
185 : WS_KERNEL_MONOATTR, &edp->kernattr);
186 0 : if (res)
187 0 : edp->kernattr = defattr;
188 :
189 0 : edp->tabs = NULL;
190 0 : edp->dblwid = NULL;
191 0 : edp->dw = 0;
192 0 : edp->dcsarg = 0;
193 0 : edp->isolatin1tab = edp->decgraphtab = edp->dectechtab = NULL;
194 0 : edp->nrctab = NULL;
195 0 : wsemul_vt100_reset(edp);
196 0 : return (edp);
197 : }
198 :
199 : void *
200 0 : wsemul_vt100_attach(int console, const struct wsscreen_descr *type,
201 : void *cookie, int ccol, int crow, void *cbcookie, long defattr)
202 : {
203 : struct wsemul_vt100_emuldata *edp;
204 :
205 0 : if (console) {
206 : edp = &wsemul_vt100_console_emuldata;
207 : #ifdef DIAGNOSTIC
208 0 : KASSERT(edp->console == 1);
209 : #endif
210 : } else {
211 0 : edp = malloc(sizeof *edp, M_DEVBUF, M_NOWAIT);
212 0 : if (edp == NULL)
213 0 : return (NULL);
214 0 : wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr);
215 : #ifdef DIAGNOSTIC
216 0 : edp->console = 0;
217 : #endif
218 : }
219 0 : edp->cbcookie = cbcookie;
220 :
221 0 : edp->tabs = malloc(edp->ncols, M_DEVBUF, M_NOWAIT);
222 0 : edp->dblwid = malloc(edp->nrows, M_DEVBUF, M_NOWAIT | M_ZERO);
223 0 : edp->dw = 0;
224 0 : edp->dcsarg = malloc(DCS_MAXLEN, M_DEVBUF, M_NOWAIT);
225 0 : edp->isolatin1tab = malloc(128 * sizeof(u_int), M_DEVBUF, M_NOWAIT);
226 0 : edp->decgraphtab = malloc(128 * sizeof(u_int), M_DEVBUF, M_NOWAIT);
227 0 : edp->dectechtab = malloc(128 * sizeof(u_int), M_DEVBUF, M_NOWAIT);
228 0 : edp->nrctab = malloc(128 * sizeof(u_int), M_DEVBUF, M_NOWAIT);
229 0 : vt100_initchartables(edp);
230 0 : wsemul_vt100_reset(edp);
231 0 : return (edp);
232 0 : }
233 :
234 : void
235 0 : wsemul_vt100_detach(void *cookie, u_int *crowp, u_int *ccolp)
236 : {
237 0 : struct wsemul_vt100_emuldata *edp = cookie;
238 :
239 0 : *crowp = edp->crow;
240 0 : *ccolp = edp->ccol;
241 : #define f(ptr) if (ptr) {free(ptr, M_DEVBUF, 0); ptr = NULL;}
242 0 : f(edp->tabs)
243 0 : f(edp->dblwid)
244 0 : f(edp->dcsarg)
245 0 : f(edp->isolatin1tab)
246 0 : f(edp->decgraphtab)
247 0 : f(edp->dectechtab)
248 0 : f(edp->nrctab)
249 : #undef f
250 0 : if (edp != &wsemul_vt100_console_emuldata)
251 0 : free(edp, M_DEVBUF, sizeof *edp);
252 0 : }
253 :
254 : void
255 0 : wsemul_vt100_resetop(void *cookie, enum wsemul_resetops op)
256 : {
257 0 : struct wsemul_vt100_emuldata *edp = cookie;
258 :
259 0 : switch (op) {
260 : case WSEMUL_RESET:
261 0 : wsemul_vt100_reset(edp);
262 0 : break;
263 : case WSEMUL_SYNCFONT:
264 0 : vt100_initchartables(edp);
265 0 : break;
266 : case WSEMUL_CLEARSCREEN:
267 0 : (void)wsemul_vt100_ed(edp, 2);
268 0 : edp->ccol = edp->crow = 0;
269 0 : (*edp->emulops->cursor)(edp->emulcookie,
270 0 : edp->flags & VTFL_CURSORON, 0, 0);
271 0 : break;
272 : case WSEMUL_CLEARCURSOR:
273 0 : (*edp->emulops->cursor)(edp->emulcookie, 0, edp->crow,
274 0 : edp->ccol);
275 0 : break;
276 : default:
277 : break;
278 : }
279 0 : }
280 :
281 : void
282 0 : wsemul_vt100_reset(struct wsemul_vt100_emuldata *edp)
283 : {
284 : int i;
285 :
286 0 : edp->state = VT100_EMUL_STATE_NORMAL;
287 0 : edp->flags = VTFL_DECAWM | VTFL_CURSORON;
288 0 : edp->bkgdattr = edp->curattr = edp->defattr;
289 0 : edp->attrflags = 0;
290 0 : edp->fgcol = WSCOL_WHITE;
291 0 : edp->bgcol = WSCOL_BLACK;
292 0 : edp->scrreg_startrow = 0;
293 0 : edp->scrreg_nrows = edp->nrows;
294 0 : if (edp->tabs) {
295 0 : memset(edp->tabs, 0, edp->ncols);
296 0 : for (i = 8; i < edp->ncols; i += 8)
297 0 : edp->tabs[i] = 1;
298 : }
299 0 : edp->dcspos = 0;
300 0 : edp->dcstype = 0;
301 0 : edp->chartab_G[0] = NULL;
302 0 : edp->chartab_G[1] = edp->nrctab; /* ??? */
303 0 : edp->chartab_G[2] = edp->isolatin1tab;
304 0 : edp->chartab_G[3] = edp->isolatin1tab;
305 0 : edp->chartab0 = 0;
306 0 : edp->chartab1 = 2;
307 0 : edp->sschartab = 0;
308 0 : }
309 :
310 : /*
311 : * Move the cursor to the next line if possible. If the cursor is at
312 : * the bottom of the scroll area, then scroll it up. If the cursor is
313 : * at the bottom of the screen then don't move it down.
314 : */
315 : int
316 0 : wsemul_vt100_nextline(struct wsemul_vt100_emuldata *edp)
317 : {
318 : int rc;
319 :
320 0 : if (ROWS_BELOW == 0) {
321 : /* Bottom of the scroll region. */
322 0 : rc = wsemul_vt100_scrollup(edp, 1);
323 0 : } else {
324 0 : if ((edp->crow+1) < edp->nrows)
325 : /* Cursor not at the bottom of the screen. */
326 0 : edp->crow++;
327 0 : CHECK_DW;
328 : rc = 0;
329 : }
330 :
331 0 : return rc;
332 : }
333 :
334 : /*
335 : * now all the state machine bits
336 : */
337 :
338 : int
339 0 : wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *edp,
340 : struct wsemul_inputstate *instate, int kernel)
341 : {
342 0 : u_int *ct, dc;
343 : u_char c;
344 0 : int oldsschartab = edp->sschartab;
345 : int rc = 0;
346 :
347 0 : if ((edp->flags & (VTFL_LASTCHAR | VTFL_DECAWM)) ==
348 : (VTFL_LASTCHAR | VTFL_DECAWM)) {
349 0 : rc = wsemul_vt100_nextline(edp);
350 0 : if (rc != 0)
351 0 : return rc;
352 0 : edp->ccol = 0;
353 0 : edp->flags &= ~VTFL_LASTCHAR;
354 0 : }
355 :
356 : #ifdef HAVE_UTF8_SUPPORT
357 0 : if (edp->flags & VTFL_UTF8) {
358 0 : (*edp->emulops->mapchar)(edp->emulcookie, instate->inchar, &dc);
359 0 : } else
360 : #endif
361 : {
362 0 : c = instate->inchar & 0xff;
363 0 : if (c & 0x80) {
364 0 : c &= 0x7f;
365 0 : ct = edp->chartab_G[edp->chartab1];
366 0 : } else {
367 0 : if (edp->sschartab) {
368 0 : ct = edp->chartab_G[edp->sschartab];
369 0 : edp->sschartab = 0;
370 0 : } else
371 0 : ct = edp->chartab_G[edp->chartab0];
372 : }
373 0 : dc = ct ? ct[c] : c;
374 : }
375 :
376 0 : if ((edp->flags & VTFL_INSERTMODE) && COLS_LEFT) {
377 0 : WSEMULOP(rc, edp, &edp->abortstate, copycols,
378 : COPYCOLS(edp->ccol, edp->ccol + 1, COLS_LEFT));
379 0 : if (rc != 0) {
380 : /* undo potential sschartab update */
381 0 : edp->sschartab = oldsschartab;
382 :
383 0 : return rc;
384 : }
385 : }
386 :
387 0 : WSEMULOP(rc, edp, &edp->abortstate, putchar,
388 : (edp->emulcookie, edp->crow, edp->ccol << edp->dw, dc,
389 : kernel ? edp->kernattr : edp->curattr));
390 0 : if (rc != 0) {
391 : /* undo potential sschartab update */
392 0 : edp->sschartab = oldsschartab;
393 :
394 0 : return rc;
395 : }
396 :
397 0 : if (COLS_LEFT)
398 0 : edp->ccol++;
399 : else
400 0 : edp->flags |= VTFL_LASTCHAR;
401 :
402 0 : return 0;
403 0 : }
404 :
405 : int
406 0 : wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *edp,
407 : struct wsemul_inputstate *instate, int kernel)
408 : {
409 : u_int n;
410 : int rc = 0;
411 :
412 0 : switch (instate->inchar) {
413 : case ASCII_NUL:
414 : default:
415 : /* ignore */
416 : break;
417 : case ASCII_BEL:
418 0 : if (edp->state == VT100_EMUL_STATE_STRING) {
419 : /* acts as an equivalent to the ``ESC \'' string end */
420 0 : wsemul_vt100_handle_dcs(edp);
421 0 : edp->state = VT100_EMUL_STATE_NORMAL;
422 0 : } else {
423 0 : wsdisplay_emulbell(edp->cbcookie);
424 : }
425 : break;
426 : case ASCII_BS:
427 0 : if (edp->ccol > 0) {
428 0 : edp->ccol--;
429 0 : edp->flags &= ~VTFL_LASTCHAR;
430 0 : }
431 : break;
432 : case ASCII_CR:
433 0 : edp->ccol = 0;
434 0 : break;
435 : case ASCII_HT:
436 0 : if (edp->tabs) {
437 0 : if (!COLS_LEFT)
438 : break;
439 0 : for (n = edp->ccol + 1; n < NCOLS - 1; n++)
440 0 : if (edp->tabs[n])
441 : break;
442 : } else {
443 0 : n = edp->ccol + min(8 - (edp->ccol & 7), COLS_LEFT);
444 : }
445 0 : edp->ccol = n;
446 0 : break;
447 : case ASCII_SO: /* LS1 */
448 0 : edp->flags &= ~VTFL_UTF8;
449 0 : edp->chartab0 = 1;
450 0 : break;
451 : case ASCII_SI: /* LS0 */
452 0 : edp->flags &= ~VTFL_UTF8;
453 0 : edp->chartab0 = 0;
454 0 : break;
455 : case ASCII_ESC:
456 0 : if (kernel) {
457 0 : printf("wsemul_vt100_output_c0c1: ESC in kernel "
458 : "output ignored\n");
459 0 : break; /* ignore the ESC */
460 : }
461 :
462 0 : if (edp->state == VT100_EMUL_STATE_STRING) {
463 : /* might be a string end */
464 0 : edp->state = VT100_EMUL_STATE_STRING_ESC;
465 0 : } else {
466 : /* XXX cancel current escape sequence */
467 0 : edp->state = VT100_EMUL_STATE_ESC;
468 : }
469 : break;
470 : case ASCII_CAN:
471 : case ASCII_SUB:
472 : /* cancel current escape sequence */
473 0 : edp->state = VT100_EMUL_STATE_NORMAL;
474 0 : break;
475 : case ASCII_LF:
476 : case ASCII_VT:
477 : case ASCII_FF:
478 0 : rc = wsemul_vt100_nextline(edp);
479 0 : break;
480 : }
481 :
482 0 : if (COLS_LEFT != 0)
483 0 : edp->flags &= ~VTFL_LASTCHAR;
484 :
485 0 : return rc;
486 : }
487 :
488 : int
489 0 : wsemul_vt100_output_esc(struct wsemul_vt100_emuldata *edp,
490 : struct wsemul_inputstate *instate)
491 : {
492 : u_int newstate = VT100_EMUL_STATE_NORMAL;
493 : int rc = 0;
494 : int i;
495 :
496 0 : switch (instate->inchar) {
497 : case '[': /* CSI */
498 0 : edp->nargs = 0;
499 0 : memset(edp->args, 0, sizeof (edp->args));
500 0 : edp->modif1 = edp->modif2 = '\0';
501 : newstate = VT100_EMUL_STATE_CSI;
502 0 : break;
503 : case '7': /* DECSC */
504 0 : edp->flags |= VTFL_SAVEDCURS;
505 0 : edp->savedcursor_row = edp->crow;
506 0 : edp->savedcursor_col = edp->ccol;
507 0 : edp->savedattr = edp->curattr;
508 0 : edp->savedbkgdattr = edp->bkgdattr;
509 0 : edp->savedattrflags = edp->attrflags;
510 0 : edp->savedfgcol = edp->fgcol;
511 0 : edp->savedbgcol = edp->bgcol;
512 0 : for (i = 0; i < 4; i++)
513 0 : edp->savedchartab_G[i] = edp->chartab_G[i];
514 0 : edp->savedchartab0 = edp->chartab0;
515 0 : edp->savedchartab1 = edp->chartab1;
516 0 : break;
517 : case '8': /* DECRC */
518 0 : if ((edp->flags & VTFL_SAVEDCURS) == 0)
519 : break;
520 0 : edp->crow = edp->savedcursor_row;
521 0 : edp->ccol = edp->savedcursor_col;
522 0 : edp->curattr = edp->savedattr;
523 0 : edp->bkgdattr = edp->savedbkgdattr;
524 0 : edp->attrflags = edp->savedattrflags;
525 0 : edp->fgcol = edp->savedfgcol;
526 0 : edp->bgcol = edp->savedbgcol;
527 0 : for (i = 0; i < 4; i++)
528 0 : edp->chartab_G[i] = edp->savedchartab_G[i];
529 0 : edp->chartab0 = edp->savedchartab0;
530 0 : edp->chartab1 = edp->savedchartab1;
531 0 : break;
532 : case '=': /* DECKPAM application mode */
533 0 : edp->flags |= VTFL_APPLKEYPAD;
534 0 : break;
535 : case '>': /* DECKPNM numeric mode */
536 0 : edp->flags &= ~VTFL_APPLKEYPAD;
537 0 : break;
538 : case 'E': /* NEL */
539 0 : edp->ccol = 0;
540 : /* FALLTHROUGH */
541 : case 'D': /* IND */
542 0 : rc = wsemul_vt100_nextline(edp);
543 0 : break;
544 : case 'H': /* HTS */
545 0 : if (edp->tabs != NULL)
546 0 : edp->tabs[edp->ccol] = 1;
547 : break;
548 : case '~': /* LS1R */
549 0 : edp->flags &= ~VTFL_UTF8;
550 0 : edp->chartab1 = 1;
551 0 : break;
552 : case 'n': /* LS2 */
553 0 : edp->flags &= ~VTFL_UTF8;
554 0 : edp->chartab0 = 2;
555 0 : break;
556 : case '}': /* LS2R */
557 0 : edp->flags &= ~VTFL_UTF8;
558 0 : edp->chartab1 = 2;
559 0 : break;
560 : case 'o': /* LS3 */
561 0 : edp->flags &= ~VTFL_UTF8;
562 0 : edp->chartab0 = 3;
563 0 : break;
564 : case '|': /* LS3R */
565 0 : edp->flags &= ~VTFL_UTF8;
566 0 : edp->chartab1 = 3;
567 0 : break;
568 : case 'N': /* SS2 */
569 0 : edp->flags &= ~VTFL_UTF8;
570 0 : edp->sschartab = 2;
571 0 : break;
572 : case 'O': /* SS3 */
573 0 : edp->flags &= ~VTFL_UTF8;
574 0 : edp->sschartab = 3;
575 0 : break;
576 : case 'M': /* RI */
577 0 : if (ROWS_ABOVE > 0) {
578 0 : edp->crow--;
579 0 : CHECK_DW;
580 : break;
581 : }
582 0 : rc = wsemul_vt100_scrolldown(edp, 1);
583 0 : break;
584 : case 'P': /* DCS */
585 0 : edp->nargs = 0;
586 0 : memset(edp->args, 0, sizeof (edp->args));
587 : newstate = VT100_EMUL_STATE_DCS;
588 0 : break;
589 : case 'c': /* RIS */
590 0 : wsemul_vt100_reset(edp);
591 0 : rc = wsemul_vt100_ed(edp, 2);
592 0 : if (rc != 0)
593 : break;
594 0 : edp->ccol = edp->crow = 0;
595 0 : break;
596 : case '(': case ')': case '*': case '+': /* SCS */
597 0 : edp->designating = instate->inchar - '(';
598 : newstate = VT100_EMUL_STATE_SCS94;
599 0 : break;
600 : case '-': case '.': case '/': /* SCS */
601 0 : edp->designating = instate->inchar - '-' + 1;
602 : newstate = VT100_EMUL_STATE_SCS96;
603 0 : break;
604 : case '#':
605 : newstate = VT100_EMUL_STATE_ESC_HASH;
606 0 : break;
607 : case ' ': /* 7/8 bit */
608 : newstate = VT100_EMUL_STATE_ESC_SPC;
609 0 : break;
610 : case ']': /* OSC operating system command */
611 : case '^': /* PM privacy message */
612 : case '_': /* APC application program command */
613 : /* ignored */
614 : newstate = VT100_EMUL_STATE_STRING;
615 0 : break;
616 : case '<': /* exit VT52 mode - ignored */
617 : break;
618 : case '%': /* UTF-8 encoding sequences */
619 : newstate = VT100_EMUL_STATE_ESC_PERCENT;
620 0 : break;
621 : default:
622 : #ifdef VT100_PRINTUNKNOWN
623 : printf("ESC %x unknown\n", instate->inchar);
624 : #endif
625 : break;
626 : }
627 :
628 0 : if (COLS_LEFT != 0)
629 0 : edp->flags &= ~VTFL_LASTCHAR;
630 :
631 0 : if (rc != 0)
632 0 : return rc;
633 :
634 0 : edp->state = newstate;
635 0 : return 0;
636 0 : }
637 :
638 : int
639 0 : wsemul_vt100_output_scs94(struct wsemul_vt100_emuldata *edp,
640 : struct wsemul_inputstate *instate)
641 : {
642 : u_int newstate = VT100_EMUL_STATE_NORMAL;
643 :
644 0 : switch (instate->inchar) {
645 : case '%': /* probably DEC supplemental graphic */
646 : newstate = VT100_EMUL_STATE_SCS94_PERCENT;
647 0 : break;
648 : case 'A': /* british / national */
649 0 : edp->flags &= ~VTFL_UTF8;
650 0 : edp->chartab_G[edp->designating] = edp->nrctab;
651 0 : break;
652 : case 'B': /* ASCII */
653 0 : edp->flags &= ~VTFL_UTF8;
654 0 : edp->chartab_G[edp->designating] = 0;
655 0 : break;
656 : case '<': /* user preferred supplemental */
657 : /* XXX not really "user" preferred */
658 0 : edp->flags &= ~VTFL_UTF8;
659 0 : edp->chartab_G[edp->designating] = edp->isolatin1tab;
660 0 : break;
661 : case '0': /* DEC special graphic */
662 0 : edp->flags &= ~VTFL_UTF8;
663 0 : edp->chartab_G[edp->designating] = edp->decgraphtab;
664 0 : break;
665 : case '>': /* DEC tech */
666 0 : edp->flags &= ~VTFL_UTF8;
667 0 : edp->chartab_G[edp->designating] = edp->dectechtab;
668 0 : break;
669 : default:
670 : #ifdef VT100_PRINTUNKNOWN
671 : printf("ESC%c %x unknown\n", edp->designating + '(',
672 : instate->inchar);
673 : #endif
674 : break;
675 : }
676 :
677 0 : edp->state = newstate;
678 0 : return 0;
679 : }
680 :
681 : int
682 0 : wsemul_vt100_output_scs94_percent(struct wsemul_vt100_emuldata *edp,
683 : struct wsemul_inputstate *instate)
684 : {
685 0 : switch (instate->inchar) {
686 : case '5': /* DEC supplemental graphic */
687 : /* XXX there are differences */
688 0 : edp->flags &= ~VTFL_UTF8;
689 0 : edp->chartab_G[edp->designating] = edp->isolatin1tab;
690 0 : break;
691 : default:
692 : #ifdef VT100_PRINTUNKNOWN
693 : printf("ESC%c%% %x unknown\n", edp->designating + '(',
694 : instate->inchar);
695 : #endif
696 : break;
697 : }
698 :
699 0 : edp->state = VT100_EMUL_STATE_NORMAL;
700 0 : return 0;
701 : }
702 :
703 : int
704 0 : wsemul_vt100_output_scs96(struct wsemul_vt100_emuldata *edp,
705 : struct wsemul_inputstate *instate)
706 : {
707 : u_int newstate = VT100_EMUL_STATE_NORMAL;
708 : int nrc;
709 :
710 0 : switch (instate->inchar) {
711 : case '%': /* probably portuguese */
712 : newstate = VT100_EMUL_STATE_SCS96_PERCENT;
713 0 : break;
714 : case 'A': /* ISO-latin-1 supplemental */
715 0 : edp->flags &= ~VTFL_UTF8;
716 0 : edp->chartab_G[edp->designating] = edp->isolatin1tab;
717 0 : break;
718 : case '4': /* dutch */
719 : nrc = 1;
720 0 : goto setnrc;
721 : case '5': case 'C': /* finnish */
722 : nrc = 2;
723 0 : goto setnrc;
724 : case 'R': /* french */
725 : nrc = 3;
726 0 : goto setnrc;
727 : case 'Q': /* french canadian */
728 : nrc = 4;
729 0 : goto setnrc;
730 : case 'K': /* german */
731 : nrc = 5;
732 0 : goto setnrc;
733 : case 'Y': /* italian */
734 : nrc = 6;
735 0 : goto setnrc;
736 : case 'E': case '6': /* norwegian / danish */
737 : nrc = 7;
738 0 : goto setnrc;
739 : case 'Z': /* spanish */
740 : nrc = 9;
741 0 : goto setnrc;
742 : case '7': case 'H': /* swedish */
743 : nrc = 10;
744 0 : goto setnrc;
745 : case '=': /* swiss */
746 0 : nrc = 11;
747 : setnrc:
748 0 : if (vt100_setnrc(edp, nrc) == 0) /* what table ??? */
749 : break;
750 : /* else FALLTHROUGH */
751 : default:
752 : #ifdef VT100_PRINTUNKNOWN
753 : printf("ESC%c %x unknown\n", edp->designating + '-' - 1,
754 : instate->inchar);
755 : #endif
756 : break;
757 : }
758 :
759 0 : edp->state = newstate;
760 0 : return 0;
761 : }
762 :
763 : int
764 0 : wsemul_vt100_output_scs96_percent(struct wsemul_vt100_emuldata *edp,
765 : struct wsemul_inputstate *instate)
766 : {
767 0 : switch (instate->inchar) {
768 : case '6': /* portuguese */
769 0 : if (vt100_setnrc(edp, 8) == 0)
770 : break;
771 : /* else FALLTHROUGH */
772 : default:
773 : #ifdef VT100_PRINTUNKNOWN
774 : printf("ESC%c%% %x unknown\n", edp->designating + '-' - 1,
775 : instate->inchar);
776 : #endif
777 : break;
778 : }
779 :
780 0 : edp->state = VT100_EMUL_STATE_NORMAL;
781 0 : return 0;
782 : }
783 :
784 : int
785 0 : wsemul_vt100_output_esc_spc(struct wsemul_vt100_emuldata *edp,
786 : struct wsemul_inputstate *instate)
787 : {
788 : switch (instate->inchar) {
789 : case 'F': /* 7-bit controls */
790 : case 'G': /* 8-bit controls */
791 : #ifdef VT100_PRINTNOTIMPL
792 : printf("ESC<SPC> %x ignored\n", instate->inchar);
793 : #endif
794 : break;
795 : default:
796 : #ifdef VT100_PRINTUNKNOWN
797 : printf("ESC<SPC> %x unknown\n", instate->inchar);
798 : #endif
799 : break;
800 : }
801 :
802 0 : edp->state = VT100_EMUL_STATE_NORMAL;
803 0 : return 0;
804 : }
805 :
806 : int
807 0 : wsemul_vt100_output_string(struct wsemul_vt100_emuldata *edp,
808 : struct wsemul_inputstate *instate)
809 : {
810 0 : if (edp->dcstype && edp->dcspos < DCS_MAXLEN) {
811 0 : if (instate->inchar & ~0xff) {
812 : #ifdef VT100_PRINTUNKNOWN
813 : printf("unknown char %x in DCS\n", instate->inchar);
814 : #endif
815 : } else
816 0 : edp->dcsarg[edp->dcspos++] = (char)instate->inchar;
817 : }
818 :
819 0 : edp->state = VT100_EMUL_STATE_STRING;
820 0 : return 0;
821 : }
822 :
823 : int
824 0 : wsemul_vt100_output_string_esc(struct wsemul_vt100_emuldata *edp,
825 : struct wsemul_inputstate *instate)
826 : {
827 0 : if (instate->inchar == '\\') { /* ST complete */
828 0 : wsemul_vt100_handle_dcs(edp);
829 0 : edp->state = VT100_EMUL_STATE_NORMAL;
830 0 : } else
831 0 : edp->state = VT100_EMUL_STATE_STRING;
832 :
833 0 : return 0;
834 : }
835 :
836 : int
837 0 : wsemul_vt100_output_dcs(struct wsemul_vt100_emuldata *edp,
838 : struct wsemul_inputstate *instate)
839 : {
840 : u_int newstate = VT100_EMUL_STATE_DCS;
841 :
842 0 : switch (instate->inchar) {
843 : case '0': case '1': case '2': case '3': case '4':
844 : case '5': case '6': case '7': case '8': case '9':
845 : /* argument digit */
846 0 : if (edp->nargs > VT100_EMUL_NARGS - 1)
847 : break;
848 0 : edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
849 0 : (instate->inchar - '0');
850 0 : break;
851 : case ';': /* argument terminator */
852 0 : edp->nargs++;
853 0 : break;
854 : default:
855 0 : edp->nargs++;
856 0 : if (edp->nargs > VT100_EMUL_NARGS) {
857 : #ifdef VT100_DEBUG
858 : printf("vt100: too many arguments\n");
859 : #endif
860 0 : edp->nargs = VT100_EMUL_NARGS;
861 0 : }
862 : newstate = VT100_EMUL_STATE_STRING;
863 0 : switch (instate->inchar) {
864 : case '$':
865 : newstate = VT100_EMUL_STATE_DCS_DOLLAR;
866 : break;
867 : case '{': /* DECDLD soft charset */ /* } */
868 : case '!': /* DECRQUPSS user preferred supplemental set */
869 : /* 'u' must follow - need another state */
870 : case '|': /* DECUDK program F6..F20 */
871 : #ifdef VT100_PRINTNOTIMPL
872 : printf("DCS%c ignored\n", (char)instate->inchar);
873 : #endif
874 : break;
875 : default:
876 : #ifdef VT100_PRINTUNKNOWN
877 : printf("DCS %x (%d, %d) unknown\n", instate->inchar,
878 : ARG(0), ARG(1));
879 : #endif
880 : break;
881 : }
882 : }
883 :
884 0 : edp->state = newstate;
885 0 : return 0;
886 : }
887 :
888 : int
889 0 : wsemul_vt100_output_dcs_dollar(struct wsemul_vt100_emuldata *edp,
890 : struct wsemul_inputstate *instate)
891 : {
892 0 : switch (instate->inchar) {
893 : case 'p': /* DECRSTS terminal state restore */
894 : case 'q': /* DECRQSS control function request */
895 : #ifdef VT100_PRINTNOTIMPL
896 : printf("DCS$%c ignored\n", (char)instate->inchar);
897 : #endif
898 : break;
899 : case 't': /* DECRSPS restore presentation state */
900 0 : switch (ARG(0)) {
901 : case 0: /* error */
902 : break;
903 : case 1: /* cursor information restore */
904 : #ifdef VT100_PRINTNOTIMPL
905 : printf("DCS1$t ignored\n");
906 : #endif
907 : break;
908 : case 2: /* tab stop restore */
909 0 : edp->dcspos = 0;
910 0 : edp->dcstype = DCSTYPE_TABRESTORE;
911 0 : break;
912 : default:
913 : #ifdef VT100_PRINTUNKNOWN
914 : printf("DCS%d$t unknown\n", ARG(0));
915 : #endif
916 : break;
917 : }
918 : break;
919 : default:
920 : #ifdef VT100_PRINTUNKNOWN
921 : printf("DCS$ %x (%d, %d) unknown\n",
922 : instate->inchar, ARG(0), ARG(1));
923 : #endif
924 : break;
925 : }
926 :
927 0 : edp->state = VT100_EMUL_STATE_STRING;
928 0 : return 0;
929 : }
930 :
931 : int
932 0 : wsemul_vt100_output_esc_percent(struct wsemul_vt100_emuldata *edp,
933 : struct wsemul_inputstate *instate)
934 : {
935 0 : switch (instate->inchar) {
936 : #ifdef HAVE_UTF8_SUPPORT
937 : case 'G':
938 0 : edp->flags |= VTFL_UTF8;
939 0 : edp->kstate.mbleft = edp->instate.mbleft = 0;
940 0 : break;
941 : case '@':
942 0 : edp->flags &= ~VTFL_UTF8;
943 0 : break;
944 : #endif
945 : default:
946 : #ifdef VT100_PRINTUNKNOWN
947 : printf("ESC% %x unknown\n", instate->inchar);
948 : #endif
949 : break;
950 : }
951 0 : edp->state = VT100_EMUL_STATE_NORMAL;
952 0 : return 0;
953 : }
954 :
955 : int
956 0 : wsemul_vt100_output_esc_hash(struct wsemul_vt100_emuldata *edp,
957 : struct wsemul_inputstate *instate)
958 : {
959 : int i;
960 : int rc = 0;
961 :
962 0 : switch (instate->inchar) {
963 : case '5': /* DECSWL single width, single height */
964 0 : if (edp->dblwid != NULL && edp->dw != 0) {
965 0 : for (i = 0; i < edp->ncols / 2; i++) {
966 0 : WSEMULOP(rc, edp, &edp->abortstate, copycols,
967 : (edp->emulcookie, edp->crow, 2 * i, i, 1));
968 0 : if (rc != 0)
969 0 : return rc;
970 : }
971 0 : WSEMULOP(rc, edp, &edp->abortstate, erasecols,
972 : (edp->emulcookie, edp->crow, i, edp->ncols - i,
973 : edp->bkgdattr));
974 0 : if (rc != 0)
975 0 : return rc;
976 0 : edp->dblwid[edp->crow] = 0;
977 0 : edp->dw = 0;
978 0 : }
979 : break;
980 : case '6': /* DECDWL double width, single height */
981 : case '3': /* DECDHL double width, double height, top half */
982 : case '4': /* DECDHL double width, double height, bottom half */
983 0 : if (edp->dblwid != NULL && edp->dw == 0) {
984 0 : for (i = edp->ncols / 2 - 1; i >= 0; i--) {
985 0 : WSEMULOP(rc, edp, &edp->abortstate, copycols,
986 : (edp->emulcookie, edp->crow, i, 2 * i, 1));
987 0 : if (rc != 0)
988 0 : return rc;
989 : }
990 0 : for (i = 0; i < edp->ncols / 2; i++) {
991 0 : WSEMULOP(rc, edp, &edp->abortstate, erasecols,
992 : (edp->emulcookie, edp->crow, 2 * i + 1, 1,
993 : edp->bkgdattr));
994 0 : if (rc != 0)
995 0 : return rc;
996 : }
997 0 : edp->dblwid[edp->crow] = 1;
998 0 : edp->dw = 1;
999 0 : if (edp->ccol > (edp->ncols >> 1) - 1)
1000 0 : edp->ccol = (edp->ncols >> 1) - 1;
1001 : }
1002 : break;
1003 : case '8': { /* DECALN */
1004 : int i, j;
1005 0 : for (i = 0; i < edp->nrows; i++)
1006 0 : for (j = 0; j < edp->ncols; j++) {
1007 0 : WSEMULOP(rc, edp, &edp->abortstate, putchar,
1008 : (edp->emulcookie, i, j, 'E', edp->curattr));
1009 0 : if (rc != 0)
1010 0 : return rc;
1011 : }
1012 0 : }
1013 0 : edp->ccol = 0;
1014 0 : edp->crow = 0;
1015 0 : break;
1016 : default:
1017 : #ifdef VT100_PRINTUNKNOWN
1018 : printf("ESC# %x unknown\n", instate->inchar);
1019 : #endif
1020 : break;
1021 : }
1022 :
1023 0 : if (COLS_LEFT != 0)
1024 0 : edp->flags &= ~VTFL_LASTCHAR;
1025 :
1026 0 : edp->state = VT100_EMUL_STATE_NORMAL;
1027 0 : return 0;
1028 0 : }
1029 :
1030 : int
1031 0 : wsemul_vt100_output_csi(struct wsemul_vt100_emuldata *edp,
1032 : struct wsemul_inputstate *instate)
1033 : {
1034 : u_int newstate = VT100_EMUL_STATE_CSI;
1035 : int oargs;
1036 : int rc = 0;
1037 :
1038 0 : switch (instate->inchar) {
1039 : case '0': case '1': case '2': case '3': case '4':
1040 : case '5': case '6': case '7': case '8': case '9':
1041 : /* argument digit */
1042 0 : if (edp->nargs > VT100_EMUL_NARGS - 1)
1043 : break;
1044 0 : edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
1045 0 : (instate->inchar - '0');
1046 0 : break;
1047 : case ';': /* argument terminator */
1048 0 : edp->nargs++;
1049 0 : break;
1050 : case '?': /* DEC specific */
1051 : case '>': /* DA query */
1052 0 : edp->modif1 = (char)instate->inchar;
1053 0 : break;
1054 : case '!':
1055 : case '"':
1056 : case '$':
1057 : case '&':
1058 0 : edp->modif2 = (char)instate->inchar;
1059 0 : break;
1060 : default: /* end of escape sequence */
1061 0 : oargs = edp->nargs++;
1062 0 : if (edp->nargs > VT100_EMUL_NARGS) {
1063 : #ifdef VT100_DEBUG
1064 : printf("vt100: too many arguments\n");
1065 : #endif
1066 0 : edp->nargs = VT100_EMUL_NARGS;
1067 0 : }
1068 0 : rc = wsemul_vt100_handle_csi(edp, instate);
1069 0 : if (rc != 0) {
1070 0 : edp->nargs = oargs;
1071 0 : return rc;
1072 : }
1073 : newstate = VT100_EMUL_STATE_NORMAL;
1074 0 : break;
1075 : }
1076 :
1077 0 : if (COLS_LEFT != 0)
1078 0 : edp->flags &= ~VTFL_LASTCHAR;
1079 :
1080 0 : edp->state = newstate;
1081 0 : return 0;
1082 0 : }
1083 :
1084 : u_int
1085 0 : wsemul_vt100_output(void *cookie, const u_char *data, u_int count, int kernel)
1086 : {
1087 0 : struct wsemul_vt100_emuldata *edp = cookie;
1088 : struct wsemul_inputstate *instate;
1089 : u_int processed = 0;
1090 : #ifdef HAVE_JUMP_SCROLL
1091 : int lines;
1092 : #endif
1093 : int rc = 0;
1094 :
1095 : #ifdef DIAGNOSTIC
1096 0 : if (kernel && !edp->console)
1097 0 : panic("wsemul_vt100_output: kernel output, not console");
1098 : #endif
1099 :
1100 0 : instate = kernel ? &edp->kstate : &edp->instate;
1101 :
1102 0 : switch (edp->abortstate.state) {
1103 : case ABORT_FAILED_CURSOR:
1104 : /*
1105 : * If we could not display the cursor back, we pretended not
1106 : * having been able to display the last character. But this
1107 : * is a lie, so compensate here.
1108 : */
1109 0 : data++, count--;
1110 : processed++;
1111 0 : wsemul_reset_abortstate(&edp->abortstate);
1112 0 : break;
1113 : case ABORT_OK:
1114 : /* remove cursor image if visible */
1115 0 : if (edp->flags & VTFL_CURSORON) {
1116 0 : rc = (*edp->emulops->cursor)
1117 0 : (edp->emulcookie, 0, edp->crow,
1118 0 : edp->ccol << edp->dw);
1119 0 : if (rc != 0)
1120 0 : return 0;
1121 : }
1122 : break;
1123 : default:
1124 : break;
1125 : }
1126 :
1127 0 : for (;;) {
1128 : #ifdef HAVE_JUMP_SCROLL
1129 0 : switch (edp->abortstate.state) {
1130 : case ABORT_FAILED_JUMP_SCROLL:
1131 : /*
1132 : * If we failed a previous jump scroll attempt, we
1133 : * need to try to resume it with the same distance.
1134 : * We can not recompute it since there might be more
1135 : * bytes in the tty ring, causing a different result.
1136 : */
1137 0 : lines = edp->abortstate.lines;
1138 0 : break;
1139 : case ABORT_OK:
1140 : /*
1141 : * If we are at the bottom of the scrolling area, count
1142 : * newlines until an escape sequence appears.
1143 : */
1144 0 : if ((edp->state == VT100_EMUL_STATE_NORMAL || kernel) &&
1145 0 : ROWS_BELOW == 0)
1146 0 : lines = wsemul_vt100_jump_scroll(edp, data,
1147 0 : count, kernel);
1148 : else
1149 : lines = 0;
1150 : break;
1151 : default:
1152 : /*
1153 : * If we are recovering a non-scrolling failure,
1154 : * do not try to scroll yet.
1155 : */
1156 : lines = 0;
1157 0 : break;
1158 : }
1159 :
1160 0 : if (lines > 1) {
1161 0 : wsemul_resume_abort(&edp->abortstate);
1162 0 : rc = wsemul_vt100_scrollup(edp, lines);
1163 0 : if (rc != 0) {
1164 0 : wsemul_abort_jump_scroll(&edp->abortstate,
1165 : lines);
1166 0 : return processed;
1167 : }
1168 0 : wsemul_reset_abortstate(&edp->abortstate);
1169 0 : edp->crow -= lines;
1170 0 : }
1171 : #endif
1172 :
1173 0 : wsemul_resume_abort(&edp->abortstate);
1174 :
1175 0 : if (wsemul_getchar(&data, &count, instate,
1176 : #ifdef HAVE_UTF8_SUPPORT
1177 0 : (edp->state == VT100_EMUL_STATE_NORMAL && !kernel) ?
1178 0 : edp->flags & VTFL_UTF8 : 0
1179 : #else
1180 : 0
1181 : #endif
1182 0 : ) != 0)
1183 : break;
1184 :
1185 0 : if (!(instate->inchar & ~0xff) &&
1186 0 : (instate->inchar & 0x7f) < 0x20) {
1187 0 : rc = wsemul_vt100_output_c0c1(edp, instate, kernel);
1188 0 : if (rc != 0)
1189 : break;
1190 0 : processed++;
1191 0 : continue;
1192 : }
1193 :
1194 0 : if (edp->state == VT100_EMUL_STATE_NORMAL || kernel) {
1195 0 : rc = wsemul_vt100_output_normal(edp, instate, kernel);
1196 0 : if (rc != 0)
1197 : break;
1198 0 : processed++;
1199 0 : continue;
1200 : }
1201 : #ifdef DIAGNOSTIC
1202 0 : if (edp->state > nitems(vt100_output))
1203 0 : panic("wsemul_vt100: invalid state %d", edp->state);
1204 : #endif
1205 0 : rc = vt100_output[edp->state - 1](edp, instate);
1206 0 : if (rc != 0)
1207 : break;
1208 0 : processed++;
1209 : }
1210 :
1211 0 : if (rc != 0)
1212 0 : wsemul_abort_other(&edp->abortstate);
1213 : else {
1214 : /* put cursor image back if visible */
1215 0 : if (edp->flags & VTFL_CURSORON) {
1216 0 : rc = (*edp->emulops->cursor)
1217 0 : (edp->emulcookie, 1, edp->crow,
1218 0 : edp->ccol << edp->dw);
1219 0 : if (rc != 0) {
1220 : /*
1221 : * Fail the last character output, remembering
1222 : * that only the cursor operation really needs
1223 : * to be done.
1224 : */
1225 0 : wsemul_abort_cursor(&edp->abortstate);
1226 0 : processed--;
1227 0 : }
1228 : }
1229 : }
1230 :
1231 0 : if (rc == 0)
1232 0 : wsemul_reset_abortstate(&edp->abortstate);
1233 :
1234 0 : return processed;
1235 0 : }
1236 :
1237 : #ifdef HAVE_JUMP_SCROLL
1238 : int
1239 0 : wsemul_vt100_jump_scroll(struct wsemul_vt100_emuldata *edp, const u_char *data,
1240 : u_int count, int kernel)
1241 : {
1242 0 : struct wsemul_inputstate tmpstate;
1243 : u_int pos, lines;
1244 :
1245 : lines = 0;
1246 0 : pos = edp->ccol;
1247 0 : tmpstate = kernel ? edp->kstate : edp->instate; /* structure copy */
1248 :
1249 0 : while (wsemul_getchar(&data, &count, &tmpstate,
1250 : #ifdef HAVE_UTF8_SUPPORT
1251 0 : kernel ? 0 : edp->flags & VTFL_UTF8
1252 : #else
1253 : 0
1254 : #endif
1255 0 : ) == 0) {
1256 : /*
1257 : * Only char causing a transition from
1258 : * VT100_EMUL_STATE_NORMAL to another state, for now.
1259 : * Revisit this if this changes...
1260 : */
1261 0 : if (tmpstate.inchar == ASCII_ESC)
1262 : break;
1263 :
1264 0 : if (ISSET(edp->flags, VTFL_DECAWM))
1265 0 : switch (tmpstate.inchar) {
1266 : case ASCII_BS:
1267 0 : if (pos > 0)
1268 0 : pos--;
1269 : break;
1270 : case ASCII_CR:
1271 : pos = 0;
1272 0 : break;
1273 : case ASCII_HT:
1274 0 : if (edp->tabs) {
1275 0 : pos++;
1276 0 : while (pos < NCOLS - 1 &&
1277 0 : edp->tabs[pos] == 0)
1278 0 : pos++;
1279 : } else {
1280 0 : pos = (pos + 7) & ~7;
1281 0 : if (pos >= NCOLS)
1282 0 : pos = NCOLS - 1;
1283 : }
1284 : break;
1285 : default:
1286 0 : if (!(tmpstate.inchar & ~0xff) &&
1287 0 : (tmpstate.inchar & 0x7f) < 0x20)
1288 : break;
1289 0 : if (pos++ >= NCOLS) {
1290 : pos = 0;
1291 0 : tmpstate.inchar = ASCII_LF;
1292 0 : }
1293 : break;
1294 : }
1295 :
1296 0 : if (tmpstate.inchar == ASCII_LF ||
1297 0 : tmpstate.inchar == ASCII_VT ||
1298 0 : tmpstate.inchar == ASCII_FF) {
1299 0 : if (++lines >= edp->scrreg_nrows - 1)
1300 : break;
1301 : }
1302 : }
1303 :
1304 0 : return lines;
1305 0 : }
1306 : #endif
|