2 * Copyright (c) 1999 FreeBSD(98) Porting Team.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer as
10 * the first lines of this file unmodified.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "opt_syscons.h"
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/module.h>
35 #include <sys/consio.h>
37 #include <machine/pc/display.h>
39 #include <dev/syscons/syscons.h>
40 #include <pc98/cbus/sctermvar.h>
45 #define IS_KTYPE_ASCII_or_HANKAKU(A) (!((A) & 0xee))
46 #define IS_KTYPE_KANA(A) ((A) & 0x11)
47 #define KTYPE_MASK_CTRL(A) ((A) &= 0xF0)
52 u_short fg; /* foreground color */
53 u_short bg; /* background color */
58 #define SCTERM_BUSY (1 << 0)
62 int param[MAX_ESC_PAR];
67 u_char kanji_1st_char;
69 #define KTYPE_ASCII 0 /* ASCII */
70 #define KTYPE_KANA 1 /* HANKAKU */
71 #define KTYPE_JKANA 0x10 /* JIS HANKAKU */
72 #define KTYPE_7JIS 0x20 /* JIS */
73 #define KTYPE_SJIS 2 /* Shift JIS */
74 #define KTYPE_UJIS 4 /* UJIS */
75 #define KTYPE_SUKANA 3 /* Shift JIS or UJIS HANKAKU */
76 #define KTYPE_SUJIS 6 /* SHift JIS or UJIS */
77 #define KTYPE_KANIN 0x80 /* Kanji Invoke sequence */
78 #define KTYPE_ASCIN 0x40 /* ASCII Invoke sequence */
81 int attr_mask; /* current logical attr mask */
82 #define NORMAL_ATTR 0x00
83 #define BLINK_ATTR 0x01
84 #define BOLD_ATTR 0x02
85 #define UNDERLINE_ATTR 0x04
86 #define REVERSE_ATTR 0x08
87 #define FG_CHANGED 0x10
88 #define BG_CHANGED 0x20
89 int cur_attr; /* current hardware attr word */
90 color_t cur_color; /* current hardware color */
91 color_t std_color; /* normal hardware color */
92 color_t rev_color; /* reverse hardware color */
93 color_t dflt_std_color; /* default normal color */
94 color_t dflt_rev_color; /* default reverse color */
97 static sc_term_init_t scterm_init;
98 static sc_term_term_t scterm_term;
99 static sc_term_puts_t scterm_puts;
100 static sc_term_ioctl_t scterm_ioctl;
101 static sc_term_reset_t scterm_reset;
102 static sc_term_default_attr_t scterm_default_attr;
103 static sc_term_clear_t scterm_clear;
104 static sc_term_notify_t scterm_notify;
105 static sc_term_input_t scterm_input;
106 static sc_term_fkeystr_t scterm_fkeystr;
108 static sc_term_sw_t sc_term_sc = {
110 "sck", /* emulator name */
111 "syscons kanji terminal", /* description */
112 "*", /* matching renderer, any :-) */
113 sizeof(term_stat), /* softc size */
127 SCTERM_MODULE(sc, sc_term_sc);
129 static term_stat reserved_term_stat;
130 static int default_kanji = UJIS;
131 static void scterm_scan_esc(scr_stat *scp, term_stat *tcp,
133 static int mask2attr(term_stat *tcp);
136 __inline static u_char
137 iskanji1(u_char mode, u_char c)
140 if ((c >= 0xa1) && (c <= 0xdf)) {
141 if (default_kanji == UJIS) {
145 if (default_kanji == SJIS) {
153 /* SJIS or UJIS HANKAKU */
158 default_kanji = SJIS;
162 if ((c >= 0xe0) && (c <= 0xef)) {
167 if ((c >= 0xf0) && (c <= 0xfe)) {
169 default_kanji = UJIS;
173 if ((mode == KTYPE_7JIS) && (c >= 0x21) && (c <= 0x7e)) {
175 default_kanji = UJIS;
179 if ((mode == KTYPE_JKANA) && (c >= 0x21) && (c <= 0x5f)) {
181 default_kanji = UJIS;
189 __inline static u_char
190 iskanji2(u_char mode, u_char c)
194 if ((c >= 0x21) && (c <= 0x7e)) {
200 if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) {
206 if ((c >= 0xa1) && (c <= 0xfe)) {
212 if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) {
216 if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) {
218 default_kanji = SJIS;
223 if ((c >= 0x40) && (c <= 0xa0) && (c != 0x7f)) {
225 default_kanji = SJIS;
228 if ((c == 0xfd) || (c == 0xfe)) {
230 default_kanji = UJIS;
233 if ((c >= 0xa1) && (c <= 0xfc)) {
234 if (default_kanji == SJIS)
236 if (default_kanji == UJIS)
246 * JIS X0208-83 keisen conversion table
248 static u_short keiConv[32] = {
249 0x240c, 0x260c, 0x300c, 0x340c, 0x3c0c, 0x380c, 0x400c, 0x500c,
250 0x480c, 0x580c, 0x600c, 0x250c, 0x270c, 0x330c, 0x370c, 0x3f0c,
251 0x3b0c, 0x470c, 0x570c, 0x4f0c, 0x5f0c, 0x6f0c, 0x440c, 0x530c,
252 0x4c0c, 0x5b0c, 0x630c, 0x410c, 0x540c, 0x490c, 0x5c0c, 0x660c
256 kanji_convert(u_char mode, u_char h, u_char l)
258 u_short tmp, high, low, c;
264 case KTYPE_SJIS: /* SHIFT JIS */
268 low = (low - 0x81) * 2 + 0x21;
280 tmp = ((high << 8) | low) - 0x20;
282 case KTYPE_7JIS: /* JIS */
283 case KTYPE_UJIS: /* UJIS */
286 tmp = ((high << 8) | low) - 0x20;
294 c = ((tmp & 0xff) << 8) | (tmp >> 8);
295 /* 0x2821 .. 0x2840 */
296 if (0x0821 <= c && c <= 0x0840)
297 tmp = keiConv[c - 0x0821];
304 scterm_init(scr_stat *scp, void **softc, int code)
308 if (*softc == NULL) {
309 if (reserved_term_stat.flags & SCTERM_BUSY)
311 *softc = &reserved_term_stat;
316 case SC_TE_COLD_INIT:
317 bzero(tcp, sizeof(*tcp));
318 tcp->flags = SCTERM_BUSY;
320 tcp->saved_xpos = -1;
321 tcp->saved_ypos = -1;
323 tcp->kanji_1st_char = 0;
324 tcp->kanji_type = KTYPE_ASCII;
326 tcp->attr_mask = NORMAL_ATTR;
328 tcp->dflt_std_color.fg = SC_NORM_ATTR & 0x0f;
329 tcp->dflt_std_color.bg = (SC_NORM_ATTR >> 4) & 0x0f;
330 tcp->dflt_rev_color.fg = SC_NORM_REV_ATTR & 0x0f;
331 tcp->dflt_rev_color.bg = (SC_NORM_REV_ATTR >> 4) & 0x0f;
332 tcp->std_color = tcp->dflt_std_color;
333 tcp->rev_color = tcp->dflt_rev_color;
334 tcp->cur_color = tcp->std_color;
335 tcp->cur_attr = mask2attr(tcp);
336 ++sc_term_sc.te_refcount;
339 case SC_TE_WARM_INIT:
341 tcp->saved_xpos = -1;
342 tcp->saved_ypos = -1;
344 tcp->std_color = tcp->dflt_std_color;
345 tcp->rev_color = tcp->dflt_rev_color;
347 tcp->cur_color = tcp->std_color;
348 tcp->cur_attr = mask2attr(tcp);
356 scterm_term(scr_stat *scp, void **softc)
358 if (*softc == &reserved_term_stat) {
360 bzero(&reserved_term_stat, sizeof(reserved_term_stat));
362 --sc_term_sc.te_refcount;
367 scterm_scan_esc(scr_stat *scp, term_stat *tcp, u_char c)
369 static u_char ansi_col[16] = {
370 FG_BLACK, FG_RED, FG_GREEN, FG_BROWN,
371 FG_BLUE, FG_MAGENTA, FG_CYAN, FG_LIGHTGREY,
372 FG_DARKGREY, FG_LIGHTRED, FG_LIGHTGREEN, FG_YELLOW,
373 FG_LIGHTBLUE, FG_LIGHTMAGENTA, FG_LIGHTCYAN, FG_WHITE
375 static int cattrs[] = {
377 CONS_BLINK_CURSOR, /* blinking block */
378 CONS_CHAR_CURSOR, /* underline */
379 CONS_CHAR_CURSOR | CONS_BLINK_CURSOR, /* blinking underline */
380 CONS_RESET_CURSOR, /* reset to default */
381 CONS_HIDDEN_CURSOR, /* hide cursor */
383 static int tcattrs[] = {
384 CONS_RESET_CURSOR | CONS_LOCAL_CURSOR, /* normal */
385 CONS_HIDDEN_CURSOR | CONS_LOCAL_CURSOR, /* invisible */
386 CONS_BLINK_CURSOR | CONS_LOCAL_CURSOR, /* very visible */
394 if (tcp->esc == 1) { /* seen ESC */
396 switch (tcp->kanji_type) {
397 case KTYPE_KANIN: /* Kanji Invoke sequence */
401 tcp->kanji_type = KTYPE_7JIS;
403 tcp->kanji_1st_char = 0;
406 tcp->kanji_type = KTYPE_ASCII;
411 case KTYPE_ASCIN: /* Ascii Invoke sequence */
416 tcp->kanji_type = KTYPE_ASCII;
418 tcp->kanji_1st_char = 0;
421 tcp->kanji_type = KTYPE_JKANA;
423 tcp->kanji_1st_char = 0;
426 tcp->kanji_type = KTYPE_ASCII;
437 case '7': /* Save cursor position */
438 tcp->saved_xpos = scp->xpos;
439 tcp->saved_ypos = scp->ypos;
442 case '8': /* Restore saved cursor position */
443 if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0)
444 sc_move_cursor(scp, tcp->saved_xpos,
448 case '[': /* Start ESC [ sequence */
450 tcp->last_param = -1;
451 for (i = tcp->num_param; i < MAX_ESC_PAR; i++)
457 case '$': /* Kanji Invoke sequence */
458 tcp->kanji_type = KTYPE_KANIN;
462 case 'M': /* Move cursor up 1 line, scroll if at top */
463 sc_term_up_scroll(scp, 1, sc->scr_map[0x20],
464 tcp->cur_attr, 0, 0);
471 case 'c': /* reset */
472 tcp->attr_mask = NORMAL_ATTR;
473 tcp->cur_color = tcp->std_color
474 = tcp->dflt_std_color;
475 tcp->rev_color = tcp->dflt_rev_color;
476 tcp->cur_attr = mask2attr(tcp);
477 sc_change_cursor_shape(scp,
478 CONS_RESET_CURSOR | CONS_LOCAL_CURSOR, -1, -1);
479 sc_clear_screen(scp);
482 case '(': /* iso-2022: designate 94 character set to G0 */
484 tcp->kanji_type = KTYPE_ASCIN;
490 } else if (tcp->esc == 2) { /* seen ESC [ */
491 if (c >= '0' && c <= '9') {
492 if (tcp->num_param < MAX_ESC_PAR) {
493 if (tcp->last_param != tcp->num_param) {
494 tcp->last_param = tcp->num_param;
495 tcp->param[tcp->num_param] = 0;
497 tcp->param[tcp->num_param] *= 10;
499 tcp->param[tcp->num_param] += c - '0';
503 tcp->num_param = tcp->last_param + 1;
507 if (tcp->num_param < MAX_ESC_PAR)
513 tcp->last_param = -1;
514 for (i = tcp->num_param; i < MAX_ESC_PAR; i++)
519 case 'A': /* up n rows */
520 sc_term_up(scp, tcp->param[0], 0);
523 case 'B': /* down n rows */
524 sc_term_down(scp, tcp->param[0], 0);
527 case 'C': /* right n columns */
528 sc_term_right(scp, tcp->param[0]);
531 case 'D': /* left n columns */
532 sc_term_left(scp, tcp->param[0]);
535 case 'E': /* cursor to start of line n lines down */
539 sc_move_cursor(scp, 0, scp->ypos + n);
542 case 'F': /* cursor to start of line n lines up */
546 sc_move_cursor(scp, 0, scp->ypos - n);
549 case 'f': /* Cursor move */
551 if (tcp->num_param == 0)
552 sc_move_cursor(scp, 0, 0);
553 else if (tcp->num_param == 2)
554 sc_move_cursor(scp, tcp->param[1] - 1,
558 case 'J': /* Clear all or part of display */
559 if (tcp->num_param == 0)
563 sc_term_clr_eos(scp, n, sc->scr_map[0x20],
567 case 'K': /* Clear all or part of line */
568 if (tcp->num_param == 0)
572 sc_term_clr_eol(scp, n, sc->scr_map[0x20],
576 case 'L': /* Insert n lines */
577 sc_term_ins_line(scp, scp->ypos, tcp->param[0],
578 sc->scr_map[0x20], tcp->cur_attr, 0);
581 case 'M': /* Delete n lines */
582 sc_term_del_line(scp, scp->ypos, tcp->param[0],
583 sc->scr_map[0x20], tcp->cur_attr, 0);
586 case 'P': /* Delete n chars */
587 sc_term_del_char(scp, tcp->param[0],
588 sc->scr_map[0x20], tcp->cur_attr);
591 case '@': /* Insert n chars */
592 sc_term_ins_char(scp, tcp->param[0],
593 sc->scr_map[0x20], tcp->cur_attr);
596 case 'S': /* scroll up n lines */
597 sc_term_del_line(scp, 0, tcp->param[0],
598 sc->scr_map[0x20], tcp->cur_attr, 0);
601 case 'T': /* scroll down n lines */
602 sc_term_ins_line(scp, 0, tcp->param[0],
603 sc->scr_map[0x20], tcp->cur_attr, 0);
606 case 'X': /* erase n characters in line */
610 if (n > scp->xsize - scp->xpos)
611 n = scp->xsize - scp->xpos;
612 sc_vtb_erase(&scp->vtb, scp->cursor_pos, n,
613 sc->scr_map[0x20], tcp->cur_attr);
614 mark_for_update(scp, scp->cursor_pos);
615 mark_for_update(scp, scp->cursor_pos + n - 1);
618 case 'Z': /* move n tabs backwards */
619 sc_term_backtab(scp, tcp->param[0]);
622 case '`': /* move cursor to column n */
623 sc_term_col(scp, tcp->param[0]);
626 case 'a': /* move cursor n columns to the right */
627 sc_term_right(scp, tcp->param[0]);
630 case 'd': /* move cursor to row n */
631 sc_term_row(scp, tcp->param[0]);
634 case 'e': /* move cursor n rows down */
635 sc_term_down(scp, tcp->param[0], 0);
638 case 'm': /* change attribute */
639 if (tcp->num_param == 0) {
640 tcp->attr_mask = NORMAL_ATTR;
641 tcp->cur_color = tcp->std_color;
642 tcp->cur_attr = mask2attr(tcp);
645 for (i = 0; i < tcp->num_param; i++) {
646 switch (n = tcp->param[i]) {
647 case 0: /* back to normal */
648 tcp->attr_mask = NORMAL_ATTR;
649 tcp->cur_color = tcp->std_color;
650 tcp->cur_attr = mask2attr(tcp);
653 tcp->attr_mask |= BOLD_ATTR;
654 tcp->cur_attr = mask2attr(tcp);
656 case 4: /* underline */
657 tcp->attr_mask |= UNDERLINE_ATTR;
658 tcp->cur_attr = mask2attr(tcp);
661 tcp->attr_mask |= BLINK_ATTR;
662 tcp->cur_attr = mask2attr(tcp);
664 case 7: /* reverse */
665 tcp->attr_mask |= REVERSE_ATTR;
666 tcp->cur_attr = mask2attr(tcp);
668 case 22: /* remove bold (or dim) */
669 tcp->attr_mask &= ~BOLD_ATTR;
670 tcp->cur_attr = mask2attr(tcp);
672 case 24: /* remove underline */
673 tcp->attr_mask &= ~UNDERLINE_ATTR;
674 tcp->cur_attr = mask2attr(tcp);
676 case 25: /* remove blink */
677 tcp->attr_mask &= ~BLINK_ATTR;
678 tcp->cur_attr = mask2attr(tcp);
680 case 27: /* remove reverse */
681 tcp->attr_mask &= ~REVERSE_ATTR;
682 tcp->cur_attr = mask2attr(tcp);
684 case 30: case 31: /* set ansi fg color */
685 case 32: case 33: case 34:
686 case 35: case 36: case 37:
687 tcp->attr_mask |= FG_CHANGED;
688 tcp->cur_color.fg = ansi_col[n - 30];
689 tcp->cur_attr = mask2attr(tcp);
691 case 39: /* restore fg color back to normal */
692 tcp->attr_mask &= ~(FG_CHANGED|BOLD_ATTR);
693 tcp->cur_color.fg = tcp->std_color.fg;
694 tcp->cur_attr = mask2attr(tcp);
696 case 40: case 41: /* set ansi bg color */
697 case 42: case 43: case 44:
698 case 45: case 46: case 47:
699 tcp->attr_mask |= BG_CHANGED;
700 tcp->cur_color.bg = ansi_col[n - 40];
701 tcp->cur_attr = mask2attr(tcp);
703 case 49: /* restore bg color back to normal */
704 tcp->attr_mask &= ~BG_CHANGED;
705 tcp->cur_color.bg = tcp->std_color.bg;
706 tcp->cur_attr = mask2attr(tcp);
712 case 's': /* Save cursor position */
713 tcp->saved_xpos = scp->xpos;
714 tcp->saved_ypos = scp->ypos;
717 case 'u': /* Restore saved cursor position */
718 if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0)
719 sc_move_cursor(scp, tcp->saved_xpos,
724 if (tcp->num_param == 0)
729 case 0: /* reset colors and attributes back to normal */
730 tcp->attr_mask = NORMAL_ATTR;
731 tcp->cur_color = tcp->std_color
732 = tcp->dflt_std_color;
733 tcp->rev_color = tcp->dflt_rev_color;
734 tcp->cur_attr = mask2attr(tcp);
736 case 1: /* set ansi background */
737 tcp->attr_mask &= ~BG_CHANGED;
738 tcp->cur_color.bg = tcp->std_color.bg
739 = ansi_col[tcp->param[1] & 0x0f];
740 tcp->cur_attr = mask2attr(tcp);
742 case 2: /* set ansi foreground */
743 tcp->attr_mask &= ~FG_CHANGED;
744 tcp->cur_color.fg = tcp->std_color.fg
745 = ansi_col[tcp->param[1] & 0x0f];
746 tcp->cur_attr = mask2attr(tcp);
748 case 3: /* set adapter attribute directly */
749 tcp->attr_mask &= ~(FG_CHANGED | BG_CHANGED);
750 tcp->cur_color.fg = tcp->std_color.fg
751 = tcp->param[1] & 0x0f;
752 tcp->cur_color.bg = tcp->std_color.bg
753 = (tcp->param[1] >> 4) & 0x0f;
754 tcp->cur_attr = mask2attr(tcp);
756 case 5: /* set ansi reverse background */
757 tcp->rev_color.bg = ansi_col[tcp->param[1] & 0x0f];
758 tcp->cur_attr = mask2attr(tcp);
760 case 6: /* set ansi reverse foreground */
761 tcp->rev_color.fg = ansi_col[tcp->param[1] & 0x0f];
762 tcp->cur_attr = mask2attr(tcp);
764 case 7: /* set adapter reverse attribute directly */
765 tcp->rev_color.fg = tcp->param[1] & 0x0f;
766 tcp->rev_color.bg = (tcp->param[1] >> 4) & 0x0f;
767 tcp->cur_attr = mask2attr(tcp);
772 case 'z': /* switch to (virtual) console n */
773 if (tcp->num_param == 1)
774 sc_switch_scr(sc, tcp->param[0]);
777 } else if (tcp->esc == 3) { /* seen ESC [0-9]+ = */
778 if (c >= '0' && c <= '9') {
779 if (tcp->num_param < MAX_ESC_PAR) {
780 if (tcp->last_param != tcp->num_param) {
781 tcp->last_param = tcp->num_param;
782 tcp->param[tcp->num_param] = 0;
784 tcp->param[tcp->num_param] *= 10;
786 tcp->param[tcp->num_param] += c - '0';
790 tcp->num_param = tcp->last_param + 1;
794 if (tcp->num_param < MAX_ESC_PAR)
798 case 'A': /* set display border color */
799 if (tcp->num_param == 1) {
800 scp->border=tcp->param[0] & 0xff;
801 if (scp == sc->cur_scp)
802 sc_set_border(scp, scp->border);
806 case 'B': /* set bell pitch and duration */
807 if (tcp->num_param == 2) {
808 scp->bell_pitch = tcp->param[0];
810 (tcp->param[1] * hz + 99) / 100;
814 case 'C': /* set global/parmanent cursor type & shape */
821 case 1: /* flags only */
822 if (v0 < sizeof(cattrs)/sizeof(cattrs[0]))
824 else /* backward compatibility */
825 v0 = cattrs[v0 & 0x3];
826 sc_change_cursor_shape(scp, v0, -1, -1);
830 v0 &= 0x1f; /* backward compatibility */
833 case 3: /* base and height */
834 if (v2 == 0) /* count from top */
835 sc_change_cursor_shape(scp, -1,
836 scp->font_size - v1 - 1,
838 else if (v2 == 1) /* count from bottom */
839 sc_change_cursor_shape(scp, -1,
846 case 'F': /* set adapter foreground */
847 if (tcp->num_param == 1) {
848 tcp->attr_mask &= ~FG_CHANGED;
849 tcp->cur_color.fg = tcp->std_color.fg
850 = tcp->param[0] & 0x0f;
851 tcp->cur_attr = mask2attr(tcp);
855 case 'G': /* set adapter background */
856 if (tcp->num_param == 1) {
857 tcp->attr_mask &= ~BG_CHANGED;
858 tcp->cur_color.bg = tcp->std_color.bg
859 = tcp->param[0] & 0x0f;
860 tcp->cur_attr = mask2attr(tcp);
864 case 'H': /* set adapter reverse foreground */
865 if (tcp->num_param == 1) {
866 tcp->rev_color.fg = tcp->param[0] & 0x0f;
867 tcp->cur_attr = mask2attr(tcp);
871 case 'I': /* set adapter reverse background */
872 if (tcp->num_param == 1) {
873 tcp->rev_color.bg = tcp->param[0] & 0x0f;
874 tcp->cur_attr = mask2attr(tcp);
878 case 'S': /* set local/temporary cursor type & shape */
887 if (v0 < sizeof(tcattrs)/sizeof(tcattrs[0]))
888 sc_change_cursor_shape(scp,
889 tcattrs[v0], -1, -1);
896 } else if (tcp->esc == 4) { /* seen ESC Q */
899 } else if (tcp->esc == 5) { /* seen ESC ( */
901 case 'B': /* iso-2022: desginate ASCII into G0 */
903 /* other items to be filled */
912 scterm_puts(scr_stat *scp, u_char *buf, int len, int kernel)
924 scp->sc->write_in_progress++;
925 backup = tcp->cur_color;
927 tcp->cur_color.fg = SC_KERNEL_CONS_ATTR & 0x0f;
928 tcp->cur_color.bg = (SC_KERNEL_CONS_ATTR >> 4) & 0x0f;
932 scterm_scan_esc(scp, tcp, *ptr++);
934 } else if (PRINTABLE(*ptr)) { /* Print only printables */
944 p = sc_vtb_pointer(&scp->vtb, scp->cursor_pos);
945 map = scp->sc->scr_map;
946 attr = tcp->cur_attr;
950 if (tcp->kanji_1st_char == 0) {
951 tcp->kanji_type = iskanji1(tcp->kanji_type, c);
952 if (!IS_KTYPE_ASCII_or_HANKAKU(tcp->kanji_type)) {
953 /* not Ascii & not HANKAKU */
954 tcp->kanji_1st_char = c;
956 } else if (tcp->kanji_type == KTYPE_ASCII) {
957 cnt = imin(len, scp->xsize - scp->xpos);
960 p = sc_vtb_putchar(&scp->vtb, p, map[c], attr);
963 } while (i > 0 && PRINTABLE(c) &&
964 iskanji1(tcp->kanji_type, c) == KTYPE_ASCII);
967 mark_for_update(scp, scp->cursor_pos);
968 scp->cursor_pos += cnt - i;
969 mark_for_update(scp, scp->cursor_pos - 1);
970 scp->xpos += cnt - i;
971 KTYPE_MASK_CTRL(tcp->kanji_type);
975 if ((tcp->kanji_type =
976 iskanji2(tcp->kanji_type, c)) & 0xee) {
977 /* print kanji on TEXT VRAM */
978 kanji_code = kanji_convert(tcp->kanji_type, c,
979 tcp->kanji_1st_char);
980 mark_for_update(scp, scp->cursor_pos);
981 for (i = 0; i < 2; i++) {
982 /* *cursor_pos = (kanji_code | (i*0x80)); */
983 p = sc_vtb_putchar(&scp->vtb, p,
984 kanji_code | ((i == 0) ? 0x00 : 0x80), attr);
986 if (++scp->xpos >= scp->xsize) {
991 mark_for_update(scp, scp->cursor_pos - 1);
992 KTYPE_MASK_CTRL(tcp->kanji_type);
993 tcp->kanji_1st_char = 0;
996 tcp->kanji_1st_char = 0;
999 if (IS_KTYPE_KANA(tcp->kanji_type))
1001 KTYPE_MASK_CTRL(tcp->kanji_type);
1002 sc_vtb_putchar(&scp->vtb, p, map[c], attr);
1003 mark_for_update(scp, scp->cursor_pos);
1004 mark_for_update(scp, scp->cursor_pos);
1012 cnt = imin(len, scp->xsize - scp->xpos);
1016 * gcc-2.6.3 generates poor (un)sign extension code.
1017 * Casting the pointers in the following to volatile should
1018 * have no effect, but in fact speeds up this inner loop
1019 * from 26 to 18 cycles (+ cache misses) on i486's.
1021 #define UCVP(ucp) ((u_char volatile *)(ucp))
1022 p = sc_vtb_putchar(&scp->vtb, p, UCVP(map)[*UCVP(ptr)],
1026 } while (i > 0 && PRINTABLE(*ptr));
1029 mark_for_update(scp, scp->cursor_pos);
1030 scp->cursor_pos += cnt - i;
1031 mark_for_update(scp, scp->cursor_pos - 1);
1032 scp->xpos += cnt - i;
1035 if (scp->xpos >= scp->xsize) {
1042 sc_bell(scp, scp->bell_pitch, scp->bell_duration);
1045 case 0x08: /* non-destructive backspace */
1046 if (scp->cursor_pos > 0) {
1047 mark_for_update(scp, scp->cursor_pos);
1049 mark_for_update(scp, scp->cursor_pos);
1053 scp->xpos += scp->xsize - 1;
1059 case 0x09: /* non-destructive tab */
1060 mark_for_update(scp, scp->cursor_pos);
1061 scp->cursor_pos += (8 - scp->xpos % 8u);
1062 scp->xpos += (8 - scp->xpos % 8u);
1063 if (scp->xpos >= scp->xsize) {
1066 scp->cursor_pos = scp->xsize * scp->ypos;
1068 mark_for_update(scp, scp->cursor_pos);
1071 case 0x0a: /* newline, same pos */
1072 mark_for_update(scp, scp->cursor_pos);
1073 scp->cursor_pos += scp->xsize;
1074 mark_for_update(scp, scp->cursor_pos);
1078 case 0x0c: /* form feed, clears screen */
1079 sc_clear_screen(scp);
1082 case 0x0d: /* return, return to pos 0 */
1083 mark_for_update(scp, scp->cursor_pos);
1084 scp->cursor_pos -= scp->xpos;
1085 mark_for_update(scp, scp->cursor_pos);
1090 tcp->kanji_type = KTYPE_JKANA;
1092 tcp->kanji_1st_char = 0;
1096 tcp->kanji_type = KTYPE_ASCII;
1098 tcp->kanji_1st_char = 0;
1101 case 0x1b: /* start escape sequence */
1110 sc_term_gen_scroll(scp, scp->sc->scr_map[0x20], tcp->cur_attr);
1113 tcp->cur_color = backup;
1114 scp->sc->write_in_progress--;
1120 scterm_ioctl(scr_stat *scp, struct tty *tp, u_long cmd, caddr_t data,
1123 term_stat *tcp = scp->ts;
1127 case GIO_ATTR: /* get current attributes */
1129 *(int*)data = (tcp->cur_attr >> 8) & 0xff;
1131 case CONS_GETINFO: /* get current (virtual) console info */
1132 vi = (vid_info_t *)data;
1133 if (vi->size != sizeof(struct vid_info))
1135 vi->mv_norm.fore = tcp->std_color.fg;
1136 vi->mv_norm.back = tcp->std_color.bg;
1137 vi->mv_rev.fore = tcp->rev_color.fg;
1138 vi->mv_rev.back = tcp->rev_color.bg;
1140 * The other fields are filled by the upper routine. XXX
1148 scterm_reset(scr_stat *scp, int code)
1155 scterm_default_attr(scr_stat *scp, int color, int rev_color)
1157 term_stat *tcp = scp->ts;
1159 tcp->dflt_std_color.fg = color & 0x0f;
1160 tcp->dflt_std_color.bg = (color >> 4) & 0x0f;
1161 tcp->dflt_rev_color.fg = rev_color & 0x0f;
1162 tcp->dflt_rev_color.bg = (rev_color >> 4) & 0x0f;
1163 tcp->std_color = tcp->dflt_std_color;
1164 tcp->rev_color = tcp->dflt_rev_color;
1165 tcp->cur_color = tcp->std_color;
1166 tcp->cur_attr = mask2attr(tcp);
1170 scterm_clear(scr_stat *scp)
1172 term_stat *tcp = scp->ts;
1174 sc_move_cursor(scp, 0, 0);
1175 sc_vtb_clear(&scp->vtb, scp->sc->scr_map[0x20], tcp->cur_attr);
1180 scterm_notify(scr_stat *scp, int event)
1183 case SC_TE_NOTIFY_VTSWITCH_IN:
1185 case SC_TE_NOTIFY_VTSWITCH_OUT:
1191 scterm_input(scr_stat *scp, int c, struct tty *tp)
1197 scterm_fkeystr(scr_stat *scp, int c)
1204 * Calculate hardware attributes word using logical attributes mask and
1210 mask2attr(term_stat *tcp)
1212 int attr, mask = tcp->attr_mask;
1214 if (mask & REVERSE_ATTR) {
1215 attr = ((mask & FG_CHANGED) ?
1216 tcp->cur_color.bg : tcp->rev_color.fg) |
1217 (((mask & BG_CHANGED) ?
1218 tcp->cur_color.fg : tcp->rev_color.bg) << 4);
1220 attr = tcp->cur_color.fg | (tcp->cur_color.bg << 4);
1222 /* XXX: underline mapping for Hercules adapter can be better */
1223 if (mask & (BOLD_ATTR | UNDERLINE_ATTR))
1225 if (mask & BLINK_ATTR)