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