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