2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3 * Copyright (c) 1992-1998 Søren Schmidt
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer as
11 * the first lines of this file unmodified.
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.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
27 * $FreeBSD: src/sys/dev/syscons/scterm-sc.c,v 1.4.2.10 2001/06/11 09:05:39 phk Exp $
30 #include "opt_syscons.h"
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/consio.h>
36 #include <sys/thread2.h>
38 #include <machine/pc/display.h>
41 #include "sctermvar.h"
43 #ifndef SC_DUMB_TERMINAL
49 u_short fg
; /* foreground color */
50 u_short bg
; /* background color */
55 #define SCTERM_BUSY (1 << 0)
59 int param
[MAX_ESC_PAR
];
62 int attr_mask
; /* current logical attr mask */
63 #define NORMAL_ATTR 0x00
64 #define BLINK_ATTR 0x01
65 #define BOLD_ATTR 0x02
66 #define UNDERLINE_ATTR 0x04
67 #define REVERSE_ATTR 0x08
68 #define FG_CHANGED 0x10
69 #define BG_CHANGED 0x20
70 int cur_attr
; /* current hardware attr word */
71 color_t cur_color
; /* current hardware color */
72 color_t std_color
; /* normal hardware color */
73 color_t rev_color
; /* reverse hardware color */
74 color_t dflt_std_color
; /* default normal color */
75 color_t dflt_rev_color
; /* default reverse color */
78 static sc_term_init_t scterm_init
;
79 static sc_term_term_t scterm_term
;
80 static sc_term_puts_t scterm_puts
;
81 static sc_term_ioctl_t scterm_ioctl
;
82 static sc_term_reset_t scterm_reset
;
83 static sc_term_default_attr_t scterm_default_attr
;
84 static sc_term_clear_t scterm_clear
;
85 static sc_term_notify_t scterm_notify
;
86 static sc_term_input_t scterm_input
;
88 static sc_term_sw_t sc_term_sc
= {
90 "sc", /* emulator name */
91 "syscons terminal", /* description */
92 "*", /* matching renderer, any :-) */
93 sizeof(term_stat
), /* softc size */
106 SCTERM_MODULE(sc
, sc_term_sc
);
108 static term_stat reserved_term_stat
;
109 static void scterm_scan_esc(scr_stat
*scp
, term_stat
*tcp
,
111 static int mask2attr(term_stat
*tcp
);
114 scterm_init(scr_stat
*scp
, void **softc
, int code
)
118 if (*softc
== NULL
) {
119 if (reserved_term_stat
.flags
& SCTERM_BUSY
)
121 *softc
= &reserved_term_stat
;
126 case SC_TE_COLD_INIT
:
127 bzero(tcp
, sizeof(*tcp
));
128 tcp
->flags
= SCTERM_BUSY
;
130 tcp
->saved_xpos
= -1;
131 tcp
->saved_ypos
= -1;
132 tcp
->attr_mask
= NORMAL_ATTR
;
134 tcp
->dflt_std_color
.fg
= SC_NORM_ATTR
& 0x0f;
135 tcp
->dflt_std_color
.bg
= (SC_NORM_ATTR
>> 4) & 0x0f;
136 tcp
->dflt_rev_color
.fg
= SC_NORM_REV_ATTR
& 0x0f;
137 tcp
->dflt_rev_color
.bg
= (SC_NORM_REV_ATTR
>> 4) & 0x0f;
138 tcp
->std_color
= tcp
->dflt_std_color
;
139 tcp
->rev_color
= tcp
->dflt_rev_color
;
140 tcp
->cur_color
= tcp
->std_color
;
141 tcp
->cur_attr
= mask2attr(tcp
);
142 ++sc_term_sc
.te_refcount
;
145 case SC_TE_WARM_INIT
:
147 tcp
->saved_xpos
= -1;
148 tcp
->saved_ypos
= -1;
150 tcp
->std_color
= tcp
->dflt_std_color
;
151 tcp
->rev_color
= tcp
->dflt_rev_color
;
153 tcp
->cur_color
= tcp
->std_color
;
154 tcp
->cur_attr
= mask2attr(tcp
);
162 scterm_term(scr_stat
*scp
, void **softc
)
164 if (*softc
== &reserved_term_stat
) {
166 bzero(&reserved_term_stat
, sizeof(reserved_term_stat
));
168 --sc_term_sc
.te_refcount
;
173 scterm_scan_esc(scr_stat
*scp
, term_stat
*tcp
, u_char c
)
175 static u_char ansi_col
[16] = {
176 FG_BLACK
, FG_RED
, FG_GREEN
, FG_BROWN
,
177 FG_BLUE
, FG_MAGENTA
, FG_CYAN
, FG_LIGHTGREY
,
178 FG_DARKGREY
, FG_LIGHTRED
, FG_LIGHTGREEN
, FG_YELLOW
,
179 FG_LIGHTBLUE
, FG_LIGHTMAGENTA
, FG_LIGHTCYAN
, FG_WHITE
185 if (tcp
->esc
== 1) { /* seen ESC */
188 case '7': /* Save cursor position */
189 tcp
->saved_xpos
= scp
->xpos
;
190 tcp
->saved_ypos
= scp
->ypos
;
193 case '8': /* Restore saved cursor position */
194 if (tcp
->saved_xpos
>= 0 && tcp
->saved_ypos
>= 0)
195 sc_move_cursor(scp
, tcp
->saved_xpos
,
199 case '[': /* Start ESC [ sequence */
201 tcp
->last_param
= -1;
202 for (i
= tcp
->num_param
; i
< MAX_ESC_PAR
; i
++)
207 case 'M': /* Move cursor up 1 line, scroll if at top */
208 sc_term_up_scroll(scp
, 1, sc
->scr_map
[0x20],
209 tcp
->cur_attr
, 0, 0);
216 case 'c': /* reset */
217 tcp
->attr_mask
= NORMAL_ATTR
;
218 tcp
->cur_color
= tcp
->std_color
219 = tcp
->dflt_std_color
;
220 tcp
->rev_color
= tcp
->dflt_rev_color
;
221 tcp
->cur_attr
= mask2attr(tcp
);
222 sc_clear_screen(scp
);
225 case '(': /* iso-2022: designate 94 character set to G0 */
229 } else if (tcp
->esc
== 2) { /* seen ESC [ */
230 if (c
>= '0' && c
<= '9') {
231 if (tcp
->num_param
< MAX_ESC_PAR
) {
232 if (tcp
->last_param
!= tcp
->num_param
) {
233 tcp
->last_param
= tcp
->num_param
;
234 tcp
->param
[tcp
->num_param
] = 0;
236 tcp
->param
[tcp
->num_param
] *= 10;
238 tcp
->param
[tcp
->num_param
] += c
- '0';
242 tcp
->num_param
= tcp
->last_param
+ 1;
246 if (tcp
->num_param
< MAX_ESC_PAR
)
252 tcp
->last_param
= -1;
253 for (i
= tcp
->num_param
; i
< MAX_ESC_PAR
; i
++)
258 case 'A': /* up n rows */
259 sc_term_up(scp
, tcp
->param
[0], 0);
262 case 'B': /* down n rows */
263 sc_term_down(scp
, tcp
->param
[0], 0);
266 case 'C': /* right n columns */
267 sc_term_right(scp
, tcp
->param
[0]);
270 case 'D': /* left n columns */
271 sc_term_left(scp
, tcp
->param
[0]);
274 case 'E': /* cursor to start of line n lines down */
278 sc_move_cursor(scp
, 0, scp
->ypos
+ n
);
281 case 'F': /* cursor to start of line n lines up */
285 sc_move_cursor(scp
, 0, scp
->ypos
- n
);
288 case 'f': /* Cursor move */
290 if (tcp
->num_param
== 0)
291 sc_move_cursor(scp
, 0, 0);
292 else if (tcp
->num_param
== 2)
293 sc_move_cursor(scp
, tcp
->param
[1] - 1,
297 case 'J': /* Clear all or part of display */
298 if (tcp
->num_param
== 0)
302 sc_term_clr_eos(scp
, n
, sc
->scr_map
[0x20],
306 case 'K': /* Clear all or part of line */
307 if (tcp
->num_param
== 0)
311 sc_term_clr_eol(scp
, n
, sc
->scr_map
[0x20],
315 case 'L': /* Insert n lines */
316 sc_term_ins_line(scp
, scp
->ypos
, tcp
->param
[0],
317 sc
->scr_map
[0x20], tcp
->cur_attr
, 0);
320 case 'M': /* Delete n lines */
321 sc_term_del_line(scp
, scp
->ypos
, tcp
->param
[0],
322 sc
->scr_map
[0x20], tcp
->cur_attr
, 0);
325 case 'P': /* Delete n chars */
326 sc_term_del_char(scp
, tcp
->param
[0],
327 sc
->scr_map
[0x20], tcp
->cur_attr
);
330 case '@': /* Insert n chars */
331 sc_term_ins_char(scp
, tcp
->param
[0],
332 sc
->scr_map
[0x20], tcp
->cur_attr
);
335 case 'S': /* scroll up n lines */
336 sc_term_del_line(scp
, 0, tcp
->param
[0],
337 sc
->scr_map
[0x20], tcp
->cur_attr
, 0);
340 case 'T': /* scroll down n lines */
341 sc_term_ins_line(scp
, 0, tcp
->param
[0],
342 sc
->scr_map
[0x20], tcp
->cur_attr
, 0);
345 case 'X': /* erase n characters in line */
349 if (n
> scp
->xsize
- scp
->xpos
)
350 n
= scp
->xsize
- scp
->xpos
;
351 sc_vtb_erase(&scp
->vtb
, scp
->cursor_pos
, n
,
352 sc
->scr_map
[0x20], tcp
->cur_attr
);
353 mark_for_update(scp
, scp
->cursor_pos
);
354 mark_for_update(scp
, scp
->cursor_pos
+ n
- 1);
357 case 'Z': /* move n tabs backwards */
358 sc_term_backtab(scp
, tcp
->param
[0]);
361 case '`': /* move cursor to column n */
362 sc_term_col(scp
, tcp
->param
[0]);
365 case 'a': /* move cursor n columns to the right */
366 sc_term_right(scp
, tcp
->param
[0]);
369 case 'd': /* move cursor to row n */
370 sc_term_row(scp
, tcp
->param
[0]);
373 case 'e': /* move cursor n rows down */
374 sc_term_down(scp
, tcp
->param
[0], 0);
377 case 'm': /* change attribute */
378 if (tcp
->num_param
== 0) {
379 tcp
->attr_mask
= NORMAL_ATTR
;
380 tcp
->cur_color
= tcp
->std_color
;
381 tcp
->cur_attr
= mask2attr(tcp
);
384 for (i
= 0; i
< tcp
->num_param
; i
++) {
385 switch (n
= tcp
->param
[i
]) {
386 case 0: /* back to normal */
387 tcp
->attr_mask
= NORMAL_ATTR
;
388 tcp
->cur_color
= tcp
->std_color
;
389 tcp
->cur_attr
= mask2attr(tcp
);
392 tcp
->attr_mask
|= BOLD_ATTR
;
393 tcp
->cur_attr
= mask2attr(tcp
);
395 case 4: /* underline */
396 tcp
->attr_mask
|= UNDERLINE_ATTR
;
397 tcp
->cur_attr
= mask2attr(tcp
);
400 tcp
->attr_mask
|= BLINK_ATTR
;
401 tcp
->cur_attr
= mask2attr(tcp
);
403 case 7: /* reverse */
404 tcp
->attr_mask
|= REVERSE_ATTR
;
405 tcp
->cur_attr
= mask2attr(tcp
);
407 case 22: /* remove bold (or dim) */
408 tcp
->attr_mask
&= ~BOLD_ATTR
;
409 tcp
->cur_attr
= mask2attr(tcp
);
411 case 24: /* remove underline */
412 tcp
->attr_mask
&= ~UNDERLINE_ATTR
;
413 tcp
->cur_attr
= mask2attr(tcp
);
415 case 25: /* remove blink */
416 tcp
->attr_mask
&= ~BLINK_ATTR
;
417 tcp
->cur_attr
= mask2attr(tcp
);
419 case 27: /* remove reverse */
420 tcp
->attr_mask
&= ~REVERSE_ATTR
;
421 tcp
->cur_attr
= mask2attr(tcp
);
423 case 30: case 31: /* set ansi fg color */
424 case 32: case 33: case 34:
425 case 35: case 36: case 37:
426 tcp
->attr_mask
|= FG_CHANGED
;
427 tcp
->cur_color
.fg
= ansi_col
[n
- 30];
428 tcp
->cur_attr
= mask2attr(tcp
);
430 case 39: /* restore fg color back to normal */
431 tcp
->attr_mask
&= ~(FG_CHANGED
|BOLD_ATTR
);
432 tcp
->cur_color
.fg
= tcp
->std_color
.fg
;
433 tcp
->cur_attr
= mask2attr(tcp
);
435 case 40: case 41: /* set ansi bg color */
436 case 42: case 43: case 44:
437 case 45: case 46: case 47:
438 tcp
->attr_mask
|= BG_CHANGED
;
439 tcp
->cur_color
.bg
= ansi_col
[n
- 40];
440 tcp
->cur_attr
= mask2attr(tcp
);
442 case 49: /* restore bg color back to normal */
443 tcp
->attr_mask
&= ~BG_CHANGED
;
444 tcp
->cur_color
.bg
= tcp
->std_color
.bg
;
445 tcp
->cur_attr
= mask2attr(tcp
);
451 case 's': /* Save cursor position */
452 tcp
->saved_xpos
= scp
->xpos
;
453 tcp
->saved_ypos
= scp
->ypos
;
456 case 'u': /* Restore saved cursor position */
457 if (tcp
->saved_xpos
>= 0 && tcp
->saved_ypos
>= 0)
458 sc_move_cursor(scp
, tcp
->saved_xpos
,
463 if (tcp
->num_param
== 0)
468 case 0: /* reset colors and attributes back to normal */
469 tcp
->attr_mask
= NORMAL_ATTR
;
470 tcp
->cur_color
= tcp
->std_color
471 = tcp
->dflt_std_color
;
472 tcp
->rev_color
= tcp
->dflt_rev_color
;
473 tcp
->cur_attr
= mask2attr(tcp
);
475 case 1: /* set ansi background */
476 tcp
->attr_mask
&= ~BG_CHANGED
;
477 tcp
->cur_color
.bg
= tcp
->std_color
.bg
478 = ansi_col
[tcp
->param
[1] & 0x0f];
479 tcp
->cur_attr
= mask2attr(tcp
);
481 case 2: /* set ansi foreground */
482 tcp
->attr_mask
&= ~FG_CHANGED
;
483 tcp
->cur_color
.fg
= tcp
->std_color
.fg
484 = ansi_col
[tcp
->param
[1] & 0x0f];
485 tcp
->cur_attr
= mask2attr(tcp
);
487 case 3: /* set adapter attribute directly */
488 tcp
->attr_mask
&= ~(FG_CHANGED
| BG_CHANGED
);
489 tcp
->cur_color
.fg
= tcp
->std_color
.fg
490 = tcp
->param
[1] & 0x0f;
491 tcp
->cur_color
.bg
= tcp
->std_color
.bg
492 = (tcp
->param
[1] >> 4) & 0x0f;
493 tcp
->cur_attr
= mask2attr(tcp
);
495 case 5: /* set ansi reverse background */
496 tcp
->rev_color
.bg
= ansi_col
[tcp
->param
[1] & 0x0f];
497 tcp
->cur_attr
= mask2attr(tcp
);
499 case 6: /* set ansi reverse foreground */
500 tcp
->rev_color
.fg
= ansi_col
[tcp
->param
[1] & 0x0f];
501 tcp
->cur_attr
= mask2attr(tcp
);
503 case 7: /* set adapter reverse attribute directly */
504 tcp
->rev_color
.fg
= tcp
->param
[1] & 0x0f;
505 tcp
->rev_color
.bg
= (tcp
->param
[1] >> 4) & 0x0f;
506 tcp
->cur_attr
= mask2attr(tcp
);
511 case 'z': /* switch to (virtual) console n */
512 if (tcp
->num_param
== 1)
513 sc_switch_scr(sc
, tcp
->param
[0]);
516 } else if (tcp
->esc
== 3) { /* seen ESC [0-9]+ = */
517 if (c
>= '0' && c
<= '9') {
518 if (tcp
->num_param
< MAX_ESC_PAR
) {
519 if (tcp
->last_param
!= tcp
->num_param
) {
520 tcp
->last_param
= tcp
->num_param
;
521 tcp
->param
[tcp
->num_param
] = 0;
523 tcp
->param
[tcp
->num_param
] *= 10;
525 tcp
->param
[tcp
->num_param
] += c
- '0';
529 tcp
->num_param
= tcp
->last_param
+ 1;
533 if (tcp
->num_param
< MAX_ESC_PAR
)
537 case 'A': /* set display border color */
538 if (tcp
->num_param
== 1) {
539 scp
->border
=tcp
->param
[0] & 0xff;
540 if (scp
== sc
->cur_scp
)
541 sc_set_border(scp
, scp
->border
);
545 case 'B': /* set bell pitch and duration */
546 if (tcp
->num_param
== 2) {
547 scp
->bell_pitch
= tcp
->param
[0];
549 (tcp
->param
[1] * hz
+ 99) / 100;
553 case 'C': /* set cursor type & shape */
555 if (!ISGRAPHSC(sc
->cur_scp
))
556 sc_remove_cursor_image(sc
->cur_scp
);
557 if (tcp
->num_param
== 1) {
558 if (tcp
->param
[0] & 0x01)
559 sc
->flags
|= SC_BLINK_CURSOR
;
561 sc
->flags
&= ~SC_BLINK_CURSOR
;
562 if (tcp
->param
[0] & 0x02)
563 sc
->flags
|= SC_CHAR_CURSOR
;
565 sc
->flags
&= ~SC_CHAR_CURSOR
;
566 } else if (tcp
->num_param
== 2) {
567 sc
->cursor_base
= scp
->font_height
568 - (tcp
->param
[1] & 0x1F) - 1;
569 sc
->cursor_height
= (tcp
->param
[1] & 0x1F)
570 - (tcp
->param
[0] & 0x1F) + 1;
571 if (sc
->cursor_base
< 0)
574 if (sc
->cursor_height
< 1) {
575 sc
->cursor_height
= 1;
576 } else if (sc
->cursor_height
>
579 sc
->cursor_height
= scp
->font_height
-
584 * The cursor shape is global property;
585 * all virtual consoles are affected.
586 * Update the cursor in the current console...
588 if (!ISGRAPHSC(sc
->cur_scp
)) {
589 sc_set_cursor_image(sc
->cur_scp
);
590 sc_draw_cursor_image(sc
->cur_scp
);
595 case 'F': /* set adapter foreground */
596 if (tcp
->num_param
== 1) {
597 tcp
->attr_mask
&= ~FG_CHANGED
;
598 tcp
->cur_color
.fg
= tcp
->std_color
.fg
599 = tcp
->param
[0] & 0x0f;
600 tcp
->cur_attr
= mask2attr(tcp
);
604 case 'G': /* set adapter background */
605 if (tcp
->num_param
== 1) {
606 tcp
->attr_mask
&= ~BG_CHANGED
;
607 tcp
->cur_color
.bg
= tcp
->std_color
.bg
608 = tcp
->param
[0] & 0x0f;
609 tcp
->cur_attr
= mask2attr(tcp
);
613 case 'H': /* set adapter reverse foreground */
614 if (tcp
->num_param
== 1) {
615 tcp
->rev_color
.fg
= tcp
->param
[0] & 0x0f;
616 tcp
->cur_attr
= mask2attr(tcp
);
620 case 'I': /* set adapter reverse background */
621 if (tcp
->num_param
== 1) {
622 tcp
->rev_color
.bg
= tcp
->param
[0] & 0x0f;
623 tcp
->cur_attr
= mask2attr(tcp
);
628 } else if (tcp
->esc
== 4) { /* seen ESC Q */
631 } else if (tcp
->esc
== 5) { /* seen ESC ( */
633 case 'B': /* iso-2022: desginate ASCII into G0 */
635 /* other items to be filled */
644 scterm_puts(scr_stat
*scp
, u_char
*buf
, int len
)
650 atomic_add_char(&scp
->sc
->write_in_progress
, 1);
653 scterm_scan_esc(scp
, tcp
, *buf
);
665 sc_term_gen_print(scp
, &buf
, &len
, tcp
->cur_attr
);
670 sc_term_gen_scroll(scp
, scp
->sc
->scr_map
[0x20], tcp
->cur_attr
);
672 atomic_add_char(&scp
->sc
->write_in_progress
, -1);
678 scterm_ioctl(scr_stat
*scp
, struct tty
*tp
, u_long cmd
, caddr_t data
,
681 term_stat
*tcp
= scp
->ts
;
685 case GIO_ATTR
: /* get current attributes */
687 *(int*)data
= (tcp
->cur_attr
>> 8) & 0xff;
689 case CONS_GETINFO
: /* get current (virtual) console info */
690 vi
= (vid_info_t
*)data
;
691 if (vi
->size
!= sizeof(struct vid_info
))
693 vi
->mv_norm
.fore
= tcp
->std_color
.fg
;
694 vi
->mv_norm
.back
= tcp
->std_color
.bg
;
695 vi
->mv_rev
.fore
= tcp
->rev_color
.fg
;
696 vi
->mv_rev
.back
= tcp
->rev_color
.bg
;
698 * The other fields are filled by the upper routine. XXX
706 scterm_reset(scr_stat
*scp
, int code
)
713 scterm_default_attr(scr_stat
*scp
, int color
, int rev_color
)
715 term_stat
*tcp
= scp
->ts
;
717 tcp
->dflt_std_color
.fg
= color
& 0x0f;
718 tcp
->dflt_std_color
.bg
= (color
>> 4) & 0x0f;
719 tcp
->dflt_rev_color
.fg
= rev_color
& 0x0f;
720 tcp
->dflt_rev_color
.bg
= (rev_color
>> 4) & 0x0f;
721 tcp
->std_color
= tcp
->dflt_std_color
;
722 tcp
->rev_color
= tcp
->dflt_rev_color
;
723 tcp
->cur_color
= tcp
->std_color
;
724 tcp
->cur_attr
= mask2attr(tcp
);
728 scterm_clear(scr_stat
*scp
)
730 term_stat
*tcp
= scp
->ts
;
732 sc_move_cursor(scp
, 0, 0);
733 sc_vtb_clear(&scp
->vtb
, scp
->sc
->scr_map
[0x20], tcp
->cur_attr
);
738 scterm_notify(scr_stat
*scp
, int event
)
741 case SC_TE_NOTIFY_VTSWITCH_IN
:
743 case SC_TE_NOTIFY_VTSWITCH_OUT
:
749 scterm_input(scr_stat
*scp
, int c
, struct tty
*tp
)
755 * Calculate hardware attributes word using logical attributes mask and
761 mask2attr(term_stat
*tcp
)
763 int attr
, mask
= tcp
->attr_mask
;
765 if (mask
& REVERSE_ATTR
) {
766 attr
= ((mask
& FG_CHANGED
) ?
767 tcp
->cur_color
.bg
: tcp
->rev_color
.fg
) |
768 (((mask
& BG_CHANGED
) ?
769 tcp
->cur_color
.fg
: tcp
->rev_color
.bg
) << 4);
771 attr
= tcp
->cur_color
.fg
| (tcp
->cur_color
.bg
<< 4);
773 /* XXX: underline mapping for Hercules adapter can be better */
774 if (mask
& (BOLD_ATTR
| UNDERLINE_ATTR
))
776 if (mask
& BLINK_ATTR
)
782 #endif /* SC_DUMB_TERMINAL */