Line data Source code
1 : /* $OpenBSD: wsemul_vt100_subr.c,v 1.21 2015/09/05 08:26:43 miod Exp $ */
2 : /* $NetBSD: wsemul_vt100_subr.c,v 1.7 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 : #include <sys/param.h>
31 : #include <sys/systm.h>
32 :
33 : #include <dev/wscons/wsconsio.h>
34 : #include <dev/wscons/wsksymvar.h>
35 : #include <dev/wscons/wsdisplayvar.h>
36 : #include <dev/wscons/wsemulvar.h>
37 : #include <dev/wscons/wsemul_vt100var.h>
38 :
39 : int vt100_selectattribute(struct wsemul_vt100_emuldata *, int, int, int,
40 : long *, long *);
41 : int vt100_ansimode(struct wsemul_vt100_emuldata *, int, int);
42 : int vt100_decmode(struct wsemul_vt100_emuldata *, int, int);
43 : #define VTMODE_SET 33
44 : #define VTMODE_RESET 44
45 : #define VTMODE_REPORT 55
46 :
47 : /*
48 : * scroll up within scrolling region
49 : */
50 : int
51 0 : wsemul_vt100_scrollup(struct wsemul_vt100_emuldata *edp, int n)
52 : {
53 : int help;
54 : int rc;
55 :
56 0 : if (n > edp->scrreg_nrows)
57 0 : n = edp->scrreg_nrows;
58 :
59 0 : help = edp->scrreg_nrows - n;
60 0 : if (help > 0) {
61 0 : WSEMULOP(rc, edp, &edp->abortstate, copyrows,
62 : (edp->emulcookie, edp->scrreg_startrow + n,
63 : edp->scrreg_startrow, help));
64 0 : if (rc != 0)
65 0 : return rc;
66 : }
67 0 : WSEMULOP(rc, edp, &edp->abortstate, eraserows,
68 : (edp->emulcookie, edp->scrreg_startrow + help, n, edp->bkgdattr));
69 0 : if (rc != 0)
70 0 : return rc;
71 0 : if (edp->dblwid) {
72 0 : if (help > 0)
73 0 : memmove(&edp->dblwid[edp->scrreg_startrow],
74 : &edp->dblwid[edp->scrreg_startrow + n], help);
75 0 : memset(&edp->dblwid[edp->scrreg_startrow + help], 0, n);
76 0 : }
77 0 : CHECK_DW;
78 :
79 0 : return 0;
80 0 : }
81 :
82 : /*
83 : * scroll down within scrolling region
84 : */
85 : int
86 0 : wsemul_vt100_scrolldown(struct wsemul_vt100_emuldata *edp, int n)
87 : {
88 : int help;
89 : int rc;
90 :
91 0 : if (n > edp->scrreg_nrows)
92 0 : n = edp->scrreg_nrows;
93 :
94 0 : help = edp->scrreg_nrows - n;
95 0 : if (help > 0) {
96 0 : WSEMULOP(rc, edp, &edp->abortstate, copyrows,
97 : (edp->emulcookie, edp->scrreg_startrow,
98 : edp->scrreg_startrow + n, help));
99 0 : if (rc != 0)
100 0 : return rc;
101 : }
102 0 : WSEMULOP(rc, edp, &edp->abortstate, eraserows,
103 : (edp->emulcookie, edp->scrreg_startrow, n, edp->bkgdattr));
104 0 : if (rc != 0)
105 0 : return rc;
106 0 : if (edp->dblwid) {
107 0 : if (help > 0)
108 0 : memmove(&edp->dblwid[edp->scrreg_startrow + n],
109 : &edp->dblwid[edp->scrreg_startrow], help);
110 0 : memset(&edp->dblwid[edp->scrreg_startrow], 0, n);
111 0 : }
112 0 : CHECK_DW;
113 :
114 0 : return 0;
115 0 : }
116 :
117 : /*
118 : * erase in display
119 : */
120 : int
121 0 : wsemul_vt100_ed(struct wsemul_vt100_emuldata *edp, int arg)
122 : {
123 : int n;
124 : int rc;
125 :
126 0 : switch (arg) {
127 : case 0: /* cursor to end */
128 0 : WSEMULOP(rc, edp, &edp->abortstate, erasecols,
129 : ERASECOLS(edp->ccol, COLS_LEFT + 1, edp->bkgdattr));
130 0 : if (rc != 0)
131 : break;
132 0 : n = edp->nrows - edp->crow - 1;
133 0 : if (n > 0) {
134 0 : WSEMULOP(rc, edp, &edp->abortstate, eraserows,
135 : (edp->emulcookie, edp->crow + 1, n, edp->bkgdattr));
136 0 : if (rc != 0)
137 : break;
138 0 : if (edp->dblwid)
139 0 : memset(&edp->dblwid[edp->crow + 1], 0, n);
140 : }
141 : break;
142 : case 1: /* beginning to cursor */
143 0 : if (edp->crow > 0) {
144 0 : WSEMULOP(rc, edp, &edp->abortstate, eraserows,
145 : (edp->emulcookie, 0, edp->crow, edp->bkgdattr));
146 0 : if (rc != 0)
147 : break;
148 : }
149 0 : WSEMULOP(rc, edp, &edp->abortstate, erasecols,
150 : ERASECOLS(0, edp->ccol + 1, edp->bkgdattr));
151 0 : if (rc != 0)
152 : break;
153 0 : if (edp->dblwid) {
154 0 : if (edp->crow > 0)
155 0 : memset(&edp->dblwid[0], 0, edp->crow);
156 : }
157 : break;
158 : case 2: /* complete display */
159 0 : WSEMULOP(rc, edp, &edp->abortstate, eraserows,
160 : (edp->emulcookie, 0, edp->nrows, edp->bkgdattr));
161 0 : if (rc != 0)
162 : break;
163 0 : if (edp->dblwid)
164 0 : memset(&edp->dblwid[0], 0, edp->nrows);
165 : break;
166 : default:
167 : #ifdef VT100_PRINTUNKNOWN
168 : printf("ed(%d) unknown\n", arg);
169 : #endif
170 : rc = 0;
171 0 : break;
172 : }
173 0 : if (rc != 0)
174 0 : return rc;
175 :
176 0 : CHECK_DW;
177 :
178 0 : return 0;
179 0 : }
180 :
181 : /*
182 : * erase in line
183 : */
184 : int
185 0 : wsemul_vt100_el(struct wsemul_vt100_emuldata *edp, int arg)
186 : {
187 : int rc;
188 :
189 0 : switch (arg) {
190 : case 0: /* cursor to end */
191 0 : WSEMULOP(rc, edp, &edp->abortstate, erasecols,
192 : ERASECOLS(edp->ccol, COLS_LEFT + 1, edp->bkgdattr));
193 : break;
194 : case 1: /* beginning to cursor */
195 0 : WSEMULOP(rc, edp, &edp->abortstate, erasecols,
196 : ERASECOLS(0, edp->ccol + 1, edp->bkgdattr));
197 : break;
198 : case 2: /* complete line */
199 0 : WSEMULOP(rc, edp, &edp->abortstate, erasecols,
200 : (edp->emulcookie, edp->crow, 0, edp->ncols, edp->bkgdattr));
201 : break;
202 : default:
203 : #ifdef VT100_PRINTUNKNOWN
204 : printf("el(%d) unknown\n", arg);
205 : #endif
206 : rc = 0;
207 0 : break;
208 : }
209 :
210 0 : return rc;
211 : }
212 :
213 : /*
214 : * handle commands after CSI (ESC[)
215 : */
216 : int
217 0 : wsemul_vt100_handle_csi(struct wsemul_vt100_emuldata *edp,
218 : struct wsemul_inputstate *instate)
219 : {
220 : int n, help, flags, fgcol, bgcol;
221 0 : long attr, bkgdattr;
222 : u_char c;
223 : int rc = 0;
224 :
225 0 : if (instate->inchar >= 0x100)
226 0 : c = 0x00; /* cause the switch below to end in default: */
227 : else
228 0 : c = (u_char)instate->inchar;
229 :
230 : #define A3(a, b, c) (((a) << 16) | ((b) << 8) | (c))
231 0 : switch (A3(edp->modif1, edp->modif2, c)) {
232 : case A3('>', '\0', 'c'): /* DA secondary */
233 0 : wsdisplay_emulinput(edp->cbcookie, WSEMUL_VT_ID2,
234 : sizeof(WSEMUL_VT_ID2));
235 0 : break;
236 :
237 : case A3('\0', '\0', 'J'): /* ED selective erase in display */
238 : case A3('?', '\0', 'J'): /* DECSED selective erase in display */
239 0 : rc = wsemul_vt100_ed(edp, ARG(0));
240 0 : break;
241 : case A3('\0', '\0', 'K'): /* EL selective erase in line */
242 : case A3('?', '\0', 'K'): /* DECSEL selective erase in line */
243 0 : rc = wsemul_vt100_el(edp, ARG(0));
244 0 : break;
245 : case A3('\0', '\0', 'h'): /* SM */
246 0 : for (n = 0; n < edp->nargs; n++)
247 0 : vt100_ansimode(edp, ARG(n), VTMODE_SET);
248 : break;
249 : case A3('?', '\0', 'h'): /* DECSM */
250 0 : for (n = 0; n < edp->nargs; n++) {
251 0 : rc = vt100_decmode(edp, ARG(n), VTMODE_SET);
252 0 : if (rc != 0)
253 : break;
254 : }
255 : break;
256 : case A3('\0', '\0', 'l'): /* RM */
257 0 : for (n = 0; n < edp->nargs; n++)
258 0 : vt100_ansimode(edp, ARG(n), VTMODE_RESET);
259 : break;
260 : case A3('?', '\0', 'l'): /* DECRM */
261 0 : for (n = 0; n < edp->nargs; n++) {
262 0 : rc = vt100_decmode(edp, ARG(n), VTMODE_RESET);
263 0 : if (rc != 0)
264 : break;
265 : }
266 : break;
267 : case A3('\0', '$', 'p'): /* DECRQM request mode ANSI */
268 0 : vt100_ansimode(edp, ARG(0), VTMODE_REPORT);
269 0 : break;
270 : case A3('?', '$', 'p'): /* DECRQM request mode DEC */
271 0 : rc = vt100_decmode(edp, ARG(0), VTMODE_REPORT);
272 0 : break;
273 : case A3('\0', '\0', 'i'): /* MC printer controller mode */
274 : case A3('?', '\0', 'i'): /* MC printer controller mode */
275 0 : switch (ARG(0)) {
276 : case 0: /* print screen */
277 : case 1: /* print cursor line */
278 : case 4: /* off */
279 : case 5: /* on */
280 : #ifdef VT100_PRINTNOTIMPL
281 : printf("CSI%di ignored\n", ARG(0));
282 : #endif
283 : break;
284 : default:
285 : #ifdef VT100_PRINTUNKNOWN
286 : printf("CSI%di unknown\n", ARG(0));
287 : #endif
288 : break;
289 : }
290 0 : break;
291 :
292 : #define A2(a, b) (((a) << 8) | (b))
293 : case A2('!', 'p'): /* DECSTR soft reset VT300 only */
294 0 : wsemul_vt100_reset(edp);
295 0 : break;
296 :
297 : case A2('"', 'p'): /* DECSCL */
298 0 : switch (ARG(0)) {
299 : case 61: /* VT100 mode (no further arguments!) */
300 : break;
301 : case 62:
302 : case 63: /* VT300 mode */
303 : break;
304 : default:
305 : #ifdef VT100_PRINTUNKNOWN
306 : printf("CSI%d\"p unknown\n", ARG(0));
307 : #endif
308 : break;
309 : }
310 0 : switch (ARG(1)) {
311 : case 0:
312 : case 2: /* 8-bit controls */
313 : #ifdef VT100_PRINTNOTIMPL
314 : printf("CSI%d;%d\"p ignored\n", ARG(0), ARG(1));
315 : #endif
316 : break;
317 : case 1: /* 7-bit controls */
318 : break;
319 : default:
320 : #ifdef VT100_PRINTUNKNOWN
321 : printf("CSI%d;%d\"p unknown\n", ARG(0), ARG(1));
322 : #endif
323 : break;
324 : }
325 0 : break;
326 : case A2('"', 'q'): /* DECSCA select character attribute VT300 */
327 0 : switch (ARG(0)) {
328 : case 0:
329 : case 1: /* erasable */
330 : break;
331 : case 2: /* not erasable */
332 : #ifdef VT100_PRINTNOTIMPL
333 : printf("CSI2\"q ignored\n");
334 : #endif
335 : break;
336 : default:
337 : #ifdef VT100_PRINTUNKNOWN
338 : printf("CSI%d\"q unknown\n", ARG(0));
339 : #endif
340 : break;
341 : }
342 0 : break;
343 :
344 : case A2('$', 'u'): /* DECRQTSR request terminal status report */
345 0 : switch (ARG(0)) {
346 : case 0: /* ignored */
347 : break;
348 : case 1: /* terminal state report */
349 : #ifdef VT100_PRINTNOTIMPL
350 : printf("CSI1$u ignored\n");
351 : #endif
352 : break;
353 : default:
354 : #ifdef VT100_PRINTUNKNOWN
355 : printf("CSI%d$u unknown\n", ARG(0));
356 : #endif
357 : break;
358 : }
359 0 : break;
360 : case A2('$', 'w'): /* DECRQPSR request presentation status report
361 : (VT300 only) */
362 0 : switch (ARG(0)) {
363 : case 0: /* error */
364 : break;
365 : case 1: /* cursor information report */
366 : #ifdef VT100_PRINTNOTIMPL
367 : printf("CSI1$w ignored\n");
368 : #endif
369 : break;
370 : case 2: /* tab stop report */
371 : {
372 : int i, n, ps = 0;
373 0 : char buf[20];
374 :
375 0 : wsdisplay_emulinput(edp->cbcookie, "\033P2$u", 5);
376 0 : if (edp->tabs != NULL)
377 0 : for (i = 0; i < edp->ncols; i++)
378 0 : if (edp->tabs[i]) {
379 0 : n = snprintf(buf, sizeof buf, "%s%d",
380 0 : (ps ? "/" : ""), i + 1);
381 0 : if (n == -1)
382 0 : n = 0;
383 0 : else if (n >= sizeof buf)
384 0 : n = sizeof buf - 1;
385 0 : wsdisplay_emulinput(edp->cbcookie,
386 : buf, n);
387 : ps = 1;
388 0 : }
389 0 : wsdisplay_emulinput(edp->cbcookie, "\033\\", 2);
390 0 : }
391 0 : break;
392 : default:
393 : #ifdef VT100_PRINTUNKNOWN
394 : printf("CSI%d$w unknown\n", ARG(0));
395 : #endif
396 : break;
397 : }
398 : break;
399 : /* gratuitous { for brace matching with the next line */
400 : case A2('$', '}'): /* DECSASD select active status display */
401 : switch (ARG(0)) {
402 : case 0: /* main display */
403 : case 1: /* status line */
404 : #ifdef VT100_PRINTNOTIMPL /* { */
405 : printf("CSI%d$} ignored\n", ARG(0));
406 : #endif
407 : break;
408 : default:
409 : #ifdef VT100_PRINTUNKNOWN /* { */
410 : printf("CSI%d$} unknown\n", ARG(0));
411 : #endif
412 : break;
413 : }
414 : break;
415 : case A2('$', '~'): /* DECSSDD select status line type */
416 : switch (ARG(0)) {
417 : case 0: /* none */
418 : case 1: /* indicator */
419 : case 2: /* host-writable */
420 : #ifdef VT100_PRINTNOTIMPL
421 : printf("CSI%d$~ ignored\n", ARG(0));
422 : #endif
423 : break;
424 : default:
425 : #ifdef VT100_PRINTUNKNOWN
426 : printf("CSI%d$~ unknown\n", ARG(0));
427 : #endif
428 : break;
429 : }
430 : break;
431 :
432 : case A2('&', 'u'): /* DECRQUPSS request user preferred
433 : supplemental set */
434 0 : wsdisplay_emulinput(edp->cbcookie, "\033P0!u%5\033\\", 9);
435 0 : break;
436 :
437 : case '@': /* ICH insert character VT300 only */
438 0 : n = min(DEF1_ARG(0), COLS_LEFT + 1);
439 0 : help = NCOLS - (edp->ccol + n);
440 0 : if (help > 0) {
441 0 : WSEMULOP(rc, edp, &edp->abortstate, copycols,
442 : COPYCOLS(edp->ccol, edp->ccol + n, help));
443 0 : if (rc != 0)
444 : break;
445 : }
446 0 : WSEMULOP(rc, edp, &edp->abortstate, erasecols,
447 : ERASECOLS(edp->ccol, n, edp->bkgdattr));
448 : break;
449 : case 'A': /* CUU */
450 0 : edp->crow -= min(DEF1_ARG(0), ROWS_ABOVE);
451 0 : CHECK_DW;
452 : break;
453 : case 'B': /* CUD */
454 0 : edp->crow += min(DEF1_ARG(0), ROWS_BELOW);
455 0 : CHECK_DW;
456 : break;
457 : case 'C': /* CUF */
458 0 : edp->ccol += min(DEF1_ARG(0), COLS_LEFT);
459 0 : break;
460 : case 'D': /* CUB */
461 0 : edp->ccol -= min(DEF1_ARG(0), edp->ccol);
462 0 : edp->flags &= ~VTFL_LASTCHAR;
463 0 : break;
464 : case 'H': /* CUP */
465 : case 'f': /* HVP */
466 0 : if (edp->flags & VTFL_DECOM)
467 0 : edp->crow = edp->scrreg_startrow +
468 0 : min(DEF1_ARG(0), edp->scrreg_nrows) - 1;
469 : else
470 0 : edp->crow = min(DEF1_ARG(0), edp->nrows) - 1;
471 0 : CHECK_DW;
472 0 : edp->ccol = min(DEF1_ARG(1), NCOLS) - 1;
473 0 : edp->flags &= ~VTFL_LASTCHAR;
474 0 : break;
475 : case 'L': /* IL insert line */
476 : case 'M': /* DL delete line */
477 : {
478 : int savscrstartrow, savscrnrows;
479 :
480 0 : n = min(DEF1_ARG(0), ROWS_BELOW + 1);
481 0 : savscrstartrow = edp->scrreg_startrow;
482 0 : savscrnrows = edp->scrreg_nrows;
483 0 : edp->scrreg_nrows -= ROWS_ABOVE;
484 0 : edp->scrreg_startrow = edp->crow;
485 0 : if (c == 'L')
486 0 : rc = wsemul_vt100_scrolldown(edp, n);
487 : else
488 0 : rc = wsemul_vt100_scrollup(edp, n);
489 0 : edp->scrreg_startrow = savscrstartrow;
490 0 : edp->scrreg_nrows = savscrnrows;
491 : }
492 0 : break;
493 : case 'P': /* DCH delete character */
494 0 : n = min(DEF1_ARG(0), COLS_LEFT + 1);
495 0 : help = NCOLS - (edp->ccol + n);
496 0 : if (help > 0) {
497 0 : WSEMULOP(rc, edp, &edp->abortstate, copycols,
498 : COPYCOLS(edp->ccol + n, edp->ccol, help));
499 0 : if (rc != 0)
500 : break;
501 : }
502 0 : WSEMULOP(rc, edp, &edp->abortstate, erasecols,
503 : ERASECOLS(NCOLS - n, n, edp->bkgdattr));
504 : break;
505 : case 'X': /* ECH erase character */
506 0 : n = min(DEF1_ARG(0), COLS_LEFT + 1);
507 0 : WSEMULOP(rc, edp, &edp->abortstate, erasecols,
508 : ERASECOLS(edp->ccol, n, edp->bkgdattr));
509 : break;
510 : case 'c': /* DA primary */
511 0 : if (ARG(0) == 0)
512 0 : wsdisplay_emulinput(edp->cbcookie, WSEMUL_VT_ID1,
513 : sizeof(WSEMUL_VT_ID1));
514 : break;
515 : case 'g': /* TBC */
516 0 : if (edp->tabs != NULL)
517 0 : switch (ARG(0)) {
518 : case 0:
519 0 : edp->tabs[edp->ccol] = 0;
520 0 : break;
521 : case 3:
522 0 : memset(edp->tabs, 0, edp->ncols);
523 0 : break;
524 : default:
525 : #ifdef VT100_PRINTUNKNOWN
526 : printf("CSI%dg unknown\n", ARG(0));
527 : #endif
528 : break;
529 : }
530 : break;
531 : case 'm': /* SGR select graphic rendition */
532 0 : flags = edp->attrflags;
533 0 : fgcol = edp->fgcol;
534 0 : bgcol = edp->bgcol;
535 0 : for (n = 0; n < edp->nargs; n++) {
536 0 : switch (ARG(n)) {
537 : case 0: /* reset */
538 0 : if (n == edp->nargs - 1) {
539 0 : edp->bkgdattr = edp->curattr = edp->defattr;
540 0 : edp->attrflags = 0;
541 0 : edp->fgcol = WSCOL_WHITE;
542 0 : edp->bgcol = WSCOL_BLACK;
543 0 : return 0;
544 : }
545 : flags = 0;
546 : fgcol = WSCOL_WHITE;
547 : bgcol = WSCOL_BLACK;
548 0 : break;
549 : case 1: /* bold */
550 0 : flags |= WSATTR_HILIT;
551 0 : break;
552 : case 4: /* underline */
553 0 : flags |= WSATTR_UNDERLINE;
554 0 : break;
555 : case 5: /* blink */
556 0 : flags |= WSATTR_BLINK;
557 0 : break;
558 : case 7: /* reverse */
559 0 : flags |= WSATTR_REVERSE;
560 0 : break;
561 : case 22: /* ~bold VT300 only */
562 0 : flags &= ~WSATTR_HILIT;
563 0 : break;
564 : case 24: /* ~underline VT300 only */
565 0 : flags &= ~WSATTR_UNDERLINE;
566 0 : break;
567 : case 25: /* ~blink VT300 only */
568 0 : flags &= ~WSATTR_BLINK;
569 0 : break;
570 : case 27: /* ~reverse VT300 only */
571 0 : flags &= ~WSATTR_REVERSE;
572 0 : break;
573 : case 30: case 31: case 32: case 33:
574 : case 34: case 35: case 36: case 37:
575 : /* fg color */
576 0 : flags |= WSATTR_WSCOLORS;
577 0 : fgcol = ARG(n) - 30;
578 0 : break;
579 : case 39:
580 : /* reset fg color */
581 : fgcol = WSCOL_WHITE;
582 0 : if (bgcol == WSCOL_BLACK)
583 0 : flags &= ~WSATTR_WSCOLORS;
584 : break;
585 : case 40: case 41: case 42: case 43:
586 : case 44: case 45: case 46: case 47:
587 : /* bg color */
588 0 : flags |= WSATTR_WSCOLORS;
589 0 : bgcol = ARG(n) - 40;
590 0 : break;
591 : case 49:
592 : /* reset bg color */
593 : bgcol = WSCOL_BLACK;
594 0 : if (fgcol == WSCOL_WHITE)
595 0 : flags &= ~WSATTR_WSCOLORS;
596 : break;
597 : default:
598 : #ifdef VT100_PRINTUNKNOWN
599 : printf("CSI%dm unknown\n", ARG(n));
600 : #endif
601 : break;
602 : }
603 : }
604 0 : if (vt100_selectattribute(edp, flags, fgcol, bgcol, &attr,
605 : &bkgdattr)) {
606 : #ifdef VT100_DEBUG
607 : printf("error allocating attr %d/%d/%x\n",
608 : fgcol, bgcol, flags);
609 : #endif
610 : } else {
611 0 : edp->curattr = attr;
612 0 : edp->bkgdattr = bkgdattr;
613 0 : edp->attrflags = flags;
614 0 : edp->fgcol = fgcol;
615 0 : edp->bgcol = bgcol;
616 : }
617 : break;
618 : case 'n': /* reports */
619 0 : switch (ARG(0)) {
620 : case 5: /* DSR operating status */
621 : /* 0 = OK, 3 = malfunction */
622 0 : wsdisplay_emulinput(edp->cbcookie, "\033[0n", 4);
623 0 : break;
624 : case 6: /* DSR cursor position report */
625 : {
626 0 : char buf[20];
627 : int row;
628 0 : if (edp->flags & VTFL_DECOM)
629 0 : row = ROWS_ABOVE;
630 : else
631 : row = edp->crow;
632 0 : n = snprintf(buf, sizeof buf, "\033[%d;%dR",
633 0 : row + 1, edp->ccol + 1);
634 0 : if (n == -1)
635 0 : n = 0;
636 0 : else if (n >= sizeof buf)
637 0 : n = sizeof buf - 1;
638 0 : wsdisplay_emulinput(edp->cbcookie, buf, n);
639 0 : }
640 0 : break;
641 : case 15: /* DSR printer status */
642 : /* 13 = no printer, 10 = ready, 11 = not ready */
643 0 : wsdisplay_emulinput(edp->cbcookie, "\033[?13n", 6);
644 0 : break;
645 : case 25: /* UDK status - VT300 only */
646 : /* 20 = locked, 21 = unlocked */
647 0 : wsdisplay_emulinput(edp->cbcookie, "\033[?21n", 6);
648 0 : break;
649 : case 26: /* keyboard dialect */
650 : /* 1 = north american , 7 = german */
651 0 : wsdisplay_emulinput(edp->cbcookie, "\033[?27;1n", 8);
652 0 : break;
653 : default:
654 : #ifdef VT100_PRINTUNKNOWN
655 : printf("CSI%dn unknown\n", ARG(0));
656 : #endif
657 : break;
658 : }
659 : break;
660 : case 'r': /* DECSTBM set top/bottom margins */
661 0 : help = min(DEF1_ARG(0), edp->nrows) - 1;
662 0 : n = min(DEFx_ARG(1, edp->nrows), edp->nrows) - help;
663 0 : if (n < 2) {
664 : /* minimal scrolling region has 2 lines */
665 0 : return 0;
666 : } else {
667 0 : edp->scrreg_startrow = help;
668 0 : edp->scrreg_nrows = n;
669 : }
670 0 : edp->crow = ((edp->flags & VTFL_DECOM) ?
671 0 : edp->scrreg_startrow : 0);
672 0 : edp->ccol = 0;
673 0 : break;
674 : case 'y':
675 0 : switch (ARG(0)) {
676 : case 4: /* DECTST invoke confidence test */
677 : /* ignore */
678 : break;
679 : default:
680 : #ifdef VT100_PRINTUNKNOWN
681 : printf("CSI%dy unknown\n", ARG(0));
682 : #endif
683 : break;
684 : }
685 0 : break;
686 : default:
687 : #ifdef VT100_PRINTUNKNOWN
688 : printf("CSI %x (%d, %d) unknown\n",
689 : instate->inchar, ARG(0), ARG(1));
690 : #endif
691 : break;
692 : }
693 :
694 0 : return rc;
695 0 : }
696 :
697 : /*
698 : * get an attribute from the graphics driver,
699 : * try to find replacements if the desired appearance
700 : * is not supported
701 : */
702 : int
703 0 : vt100_selectattribute(struct wsemul_vt100_emuldata *edp, int flags, int fgcol,
704 : int bgcol, long *attr, long *bkgdattr)
705 : {
706 : int error;
707 :
708 0 : if ((flags & WSATTR_WSCOLORS) &&
709 0 : !(edp->scrcapabilities & WSSCREEN_WSCOLORS)) {
710 0 : flags &= ~WSATTR_WSCOLORS;
711 : #ifdef VT100_DEBUG
712 : printf("colors ignored (impossible)\n");
713 : #endif
714 0 : }
715 0 : error = (*edp->emulops->alloc_attr)(edp->emulcookie, fgcol, bgcol,
716 0 : flags & WSATTR_WSCOLORS, bkgdattr);
717 0 : if (error)
718 0 : return (error);
719 :
720 0 : if ((flags & WSATTR_HILIT) &&
721 0 : !(edp->scrcapabilities & WSSCREEN_HILIT)) {
722 0 : flags &= ~WSATTR_HILIT;
723 0 : if (edp->scrcapabilities & WSSCREEN_WSCOLORS) {
724 : fgcol = WSCOL_RED;
725 0 : flags |= WSATTR_WSCOLORS;
726 0 : } else {
727 : #ifdef VT100_DEBUG
728 : printf("bold ignored (impossible)\n");
729 : #endif
730 : }
731 : }
732 0 : if ((flags & WSATTR_UNDERLINE) &&
733 0 : !(edp->scrcapabilities & WSSCREEN_UNDERLINE)) {
734 0 : flags &= ~WSATTR_UNDERLINE;
735 0 : if (edp->scrcapabilities & WSSCREEN_WSCOLORS) {
736 : fgcol = WSCOL_CYAN;
737 : flags &= ~WSATTR_UNDERLINE;
738 0 : flags |= WSATTR_WSCOLORS;
739 0 : } else {
740 : #ifdef VT100_DEBUG
741 : printf("underline ignored (impossible)\n");
742 : #endif
743 : }
744 : }
745 0 : if ((flags & WSATTR_BLINK) &&
746 0 : !(edp->scrcapabilities & WSSCREEN_BLINK)) {
747 0 : flags &= ~WSATTR_BLINK;
748 : #ifdef VT100_DEBUG
749 : printf("blink ignored (impossible)\n");
750 : #endif
751 0 : }
752 0 : if ((flags & WSATTR_REVERSE) &&
753 0 : !(edp->scrcapabilities & WSSCREEN_REVERSE)) {
754 0 : flags &= ~WSATTR_REVERSE;
755 0 : if (edp->scrcapabilities & WSSCREEN_WSCOLORS) {
756 : int help;
757 : help = bgcol;
758 : bgcol = fgcol;
759 : fgcol = help;
760 0 : flags |= WSATTR_WSCOLORS;
761 0 : } else {
762 : #ifdef VT100_DEBUG
763 : printf("reverse ignored (impossible)\n");
764 : #endif
765 : }
766 : }
767 0 : error = (*edp->emulops->alloc_attr)(edp->emulcookie, fgcol, bgcol,
768 : flags, attr);
769 0 : if (error)
770 0 : return (error);
771 :
772 0 : return (0);
773 0 : }
774 :
775 : /*
776 : * handle device control sequences if the main state machine
777 : * told so by setting edp->dcstype to a nonzero value
778 : */
779 : void
780 0 : wsemul_vt100_handle_dcs(struct wsemul_vt100_emuldata *edp)
781 : {
782 : int i, pos;
783 :
784 0 : switch (edp->dcstype) {
785 : case 0: /* not handled */
786 0 : return;
787 : case DCSTYPE_TABRESTORE:
788 0 : if (edp->tabs != NULL) {
789 0 : memset(edp->tabs, 0, edp->ncols);
790 : pos = 0;
791 0 : for (i = 0; i < edp->dcspos; i++) {
792 0 : char c = edp->dcsarg[i];
793 0 : switch (c) {
794 : case '0': case '1': case '2': case '3':
795 : case '4': case '5': case '6': case '7':
796 : case '8': case '9':
797 0 : pos = pos * 10 + (edp->dcsarg[i] - '0');
798 0 : break;
799 : case '/':
800 0 : if (pos > 0)
801 0 : edp->tabs[pos - 1] = 1;
802 : pos = 0;
803 0 : break;
804 : default:
805 : #ifdef VT100_PRINTUNKNOWN
806 : printf("unknown char %c in DCS\n", c);
807 : #endif
808 : break;
809 : }
810 : }
811 0 : if (pos > 0)
812 0 : edp->tabs[pos - 1] = 1;
813 : }
814 : break;
815 : default:
816 : #ifdef VT100_PRINTUNKNOWN
817 : printf("wsemul_vt100_handle_dcs: bad type %d\n", edp->dcstype);
818 : #endif
819 : break;
820 : }
821 0 : edp->dcstype = 0;
822 0 : }
823 :
824 : int
825 0 : vt100_ansimode(struct wsemul_vt100_emuldata *edp, int nr, int op)
826 : {
827 : int res = 0; /* default: unknown */
828 :
829 0 : switch (nr) {
830 : case 2: /* KAM keyboard locked/unlocked */
831 : break;
832 : case 3: /* CRM control representation */
833 : break;
834 : case 4: /* IRM insert/replace characters */
835 0 : if (op == VTMODE_SET)
836 0 : edp->flags |= VTFL_INSERTMODE;
837 0 : else if (op == VTMODE_RESET)
838 0 : edp->flags &= ~VTFL_INSERTMODE;
839 0 : res = ((edp->flags & VTFL_INSERTMODE) ? 1 : 2);
840 0 : break;
841 : case 10: /* HEM horizontal editing (permanently reset) */
842 : res = 4;
843 0 : break;
844 : case 12: /* SRM local echo off/on */
845 : res = 4; /* permanently reset ??? */
846 0 : break;
847 : case 20: /* LNM newline = newline/linefeed */
848 : break;
849 : default:
850 : #ifdef VT100_PRINTUNKNOWN
851 : printf("ANSI mode %d unknown\n", nr);
852 : #endif
853 : break;
854 : }
855 0 : return (res);
856 : }
857 :
858 : int
859 0 : vt100_decmode(struct wsemul_vt100_emuldata *edp, int nr, int op)
860 : {
861 : #if 0 /* res unused... return it by reference if ever necessary */
862 : int res = 0; /* default: unknown */
863 : #endif
864 0 : int flags = edp->flags;
865 : int rc = 0;
866 :
867 0 : switch (nr) {
868 : case 1: /* DECCKM application/nomal cursor keys */
869 0 : if (op == VTMODE_SET)
870 0 : flags |= VTFL_APPLCURSOR;
871 0 : else if (op == VTMODE_RESET)
872 0 : flags &= ~VTFL_APPLCURSOR;
873 : #if 0
874 : res = ((flags & VTFL_APPLCURSOR) ? 1 : 2);
875 : #endif
876 : break;
877 : case 2: /* DECANM ANSI vt100/vt52 */
878 : #if 0
879 : res = 3; /* permanently set ??? */
880 : #endif
881 : break;
882 : case 3: /* DECCOLM 132/80 cols */
883 : case 4: /* DECSCLM smooth/jump scroll */
884 : case 5: /* DECSCNM light/dark background */
885 : #if 0
886 : res = 4; /* all permanently reset ??? */
887 : #endif
888 : break;
889 : case 6: /* DECOM move within/outside margins */
890 0 : if (op == VTMODE_SET)
891 0 : flags |= VTFL_DECOM;
892 0 : else if (op == VTMODE_RESET)
893 0 : flags &= ~VTFL_DECOM;
894 : #if 0
895 : res = ((flags & VTFL_DECOM) ? 1 : 2);
896 : #endif
897 : break;
898 : case 7: /* DECAWM autowrap */
899 0 : if (op == VTMODE_SET)
900 0 : flags |= VTFL_DECAWM;
901 0 : else if (op == VTMODE_RESET)
902 0 : flags &= ~VTFL_DECAWM;
903 : #if 0
904 : res = ((flags & VTFL_DECAWM) ? 1 : 2);
905 : #endif
906 : break;
907 : case 8: /* DECARM keyboard autorepeat */
908 : break;
909 : case 18: /* DECPFF print form feed */
910 : break;
911 : case 19: /* DECPEX printer extent: screen/scrolling region */
912 : break;
913 : case 25: /* DECTCEM text cursor on/off */
914 0 : if (op == VTMODE_SET)
915 0 : flags |= VTFL_CURSORON;
916 0 : else if (op == VTMODE_RESET)
917 0 : flags &= ~VTFL_CURSORON;
918 0 : if (flags != edp->flags)
919 0 : WSEMULOP(rc, edp, &edp->abortstate, cursor,
920 : (edp->emulcookie, flags & VTFL_CURSORON, edp->crow,
921 : edp->ccol));
922 : #if 0
923 : res = ((flags & VTFL_CURSORON) ? 1 : 2);
924 : #endif
925 : break;
926 : case 42: /* DECNRCM use 7-bit NRC /
927 : 7/8 bit from DEC multilingual or ISO-latin-1*/
928 0 : if (op == VTMODE_SET)
929 0 : flags |= VTFL_NATCHARSET;
930 0 : else if (op == VTMODE_RESET)
931 0 : flags &= ~VTFL_NATCHARSET;
932 : #if 0
933 : res = ((flags & VTFL_NATCHARSET) ? 1 : 2);
934 : #endif
935 : break;
936 : case 66: /* DECNKM numeric keypad */
937 : break;
938 : case 68: /* DECKBUM keyboard usage data processing/typewriter */
939 : break;
940 : default:
941 : #ifdef VT100_PRINTUNKNOWN
942 : printf("DEC mode %d unknown\n", nr);
943 : #endif
944 : break;
945 : }
946 0 : edp->flags = flags;
947 :
948 0 : return rc;
949 : }
|