summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/conf/files6
-rw-r--r--sys/conf/files.amd643
-rw-r--r--sys/conf/files.i3863
-rw-r--r--sys/conf/files.ia643
-rw-r--r--sys/conf/files.powerpc3
-rw-r--r--sys/conf/files.sparc643
-rw-r--r--sys/dev/syscons/scterm-dumb.c155
-rw-r--r--sys/dev/syscons/scterm-sc.c811
-rw-r--r--sys/dev/syscons/scterm-teken.c504
-rw-r--r--sys/dev/syscons/scterm.c1
-rw-r--r--sys/dev/syscons/syscons.c37
-rw-r--r--sys/dev/syscons/syscons.h3
-rw-r--r--sys/dev/syscons/teken/Makefile13
-rw-r--r--sys/dev/syscons/teken/gensequences157
-rw-r--r--sys/dev/syscons/teken/sequences107
-rw-r--r--sys/dev/syscons/teken/teken.c386
-rw-r--r--sys/dev/syscons/teken/teken.h168
-rw-r--r--sys/dev/syscons/teken/teken_demo.c336
-rw-r--r--sys/dev/syscons/teken/teken_stress.c123
-rw-r--r--sys/dev/syscons/teken/teken_subr.h1107
-rw-r--r--sys/dev/syscons/teken/teken_subr_compat.h51
-rw-r--r--sys/dev/syscons/teken/teken_wcwidth.h120
-rw-r--r--sys/pc98/cbus/scterm-sck.c6
-rw-r--r--sys/pc98/cbus/sctermvar.h (renamed from sys/dev/syscons/sctermvar.h)0
24 files changed, 3117 insertions, 989 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 08639e9..dc38a54 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -75,6 +75,11 @@ pccarddevs.h standard \
compile-with "${AWK} -f $S/tools/pccarddevs2h.awk $S/dev/pccard/pccarddevs" \
no-obj no-implicit-rule before-depend \
clean "pccarddevs.h"
+teken_state.h optional sc \
+ dependency "$S/dev/syscons/teken/gensequences $S/dev/syscons/teken/sequences" \
+ compile-with "${AWK} -f $S/dev/syscons/teken/gensequences $S/dev/syscons/teken/sequences > teken_state.h" \
+ no-obj no-implicit-rule before-depend \
+ clean "teken_state.h"
usbdevs.h optional usb \
dependency "$S/tools/usbdevs2h.awk $S/dev/usb/usbdevs" \
compile-with "${AWK} -f $S/tools/usbdevs2h.awk $S/dev/usb/usbdevs -h" \
@@ -1424,7 +1429,6 @@ dev/syscons/logo/logo_saver.c optional logo_saver
dev/syscons/rain/rain_saver.c optional rain_saver
dev/syscons/schistory.c optional sc
dev/syscons/scmouse.c optional sc
-dev/syscons/scterm-dumb.c optional sc
dev/syscons/scterm.c optional sc
dev/syscons/scvidctl.c optional sc
dev/syscons/snake/snake_saver.c optional snake_saver
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 82ec801..c6c403f 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -196,9 +196,10 @@ dev/sio/sio_pci.c optional sio pci
dev/sio/sio_puc.c optional sio puc
dev/speaker/spkr.c optional speaker
dev/syscons/apm/apm_saver.c optional apm_saver apm
-dev/syscons/scterm-sc.c optional sc
+dev/syscons/scterm-teken.c optional sc
dev/syscons/scvgarndr.c optional sc vga
dev/syscons/scvtb.c optional sc
+dev/syscons/teken/teken.c optional sc
dev/uart/uart_cpu_amd64.c optional uart
dev/wpi/if_wpi.c optional wpi
isa/atrtc.c standard
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 17076db..72c1269 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -220,10 +220,11 @@ dev/sio/sio_puc.c optional sio puc
dev/speaker/spkr.c optional speaker
dev/sr/if_sr_isa.c optional sr isa
dev/syscons/apm/apm_saver.c optional apm_saver apm
-dev/syscons/scterm-sc.c optional sc
+dev/syscons/scterm-teken.c optional sc
dev/syscons/scvesactl.c optional sc vga vesa
dev/syscons/scvgarndr.c optional sc vga
dev/syscons/scvtb.c optional sc
+dev/syscons/teken/teken.c optional sc
dev/uart/uart_cpu_i386.c optional uart
dev/acpica/acpi_if.m standard
dev/wpi/if_wpi.c optional wpi
diff --git a/sys/conf/files.ia64 b/sys/conf/files.ia64
index 6556fbb..c17acb2 100644
--- a/sys/conf/files.ia64
+++ b/sys/conf/files.ia64
@@ -57,9 +57,10 @@ dev/fb/fb.c optional fb | vga
dev/fb/vga.c optional vga
dev/hwpmc/hwpmc_ia64.c optional hwpmc
dev/kbd/kbd.c optional atkbd | sc | ukbd
-dev/syscons/scterm-sc.c optional sc
+dev/syscons/scterm-teken.c optional sc
dev/syscons/scvgarndr.c optional sc vga
dev/syscons/scvtb.c optional sc
+dev/syscons/teken/teken.c optional sc
dev/uart/uart_cpu_ia64.c optional uart
dev/acpica/acpi_if.m standard
ia64/acpica/OsdEnvironment.c optional acpi
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index 901e36d..f42f81b 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -39,8 +39,9 @@ dev/powermac_nvram/powermac_nvram.c optional powermac_nvram powermac
dev/quicc/quicc_bfe_ocp.c optional quicc mpc85xx
dev/scc/scc_bfe_macio.c optional scc powermac
dev/syscons/scgfbrndr.c optional sc
-dev/syscons/scterm-sc.c optional sc
+dev/syscons/scterm-teken.c optional sc
dev/syscons/scvtb.c optional sc
+dev/syscons/teken/teken.c optional sc
dev/tsec/if_tsec.c optional tsec
dev/tsec/if_tsec_ocp.c optional tsec mpc85xx
dev/uart/uart_bus_ocp.c optional uart mpc85xx
diff --git a/sys/conf/files.sparc64 b/sys/conf/files.sparc64
index 311027c..90c37a9 100644
--- a/sys/conf/files.sparc64
+++ b/sys/conf/files.sparc64
@@ -55,8 +55,9 @@ dev/pcf/pcf_ebus.c optional pcf ebus
dev/sound/sbus/cs4231.c optional snd_audiocs ebus | \
snd_audiocs sbus
dev/syscons/scgfbrndr.c optional sc
-dev/syscons/scterm-sc.c optional sc
+dev/syscons/scterm-teken.c optional sc
dev/syscons/scvtb.c optional sc
+dev/syscons/teken/teken.c optional sc
dev/uart/uart_cpu_sparc64.c optional uart
dev/uart/uart_kbd_sun.c optional uart sc
kern/syscalls.c optional ktr
diff --git a/sys/dev/syscons/scterm-dumb.c b/sys/dev/syscons/scterm-dumb.c
deleted file mode 100644
index 1c130b6..0000000
--- a/sys/dev/syscons/scterm-dumb.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*-
- * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer as
- * the first lines of this file unmodified.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_syscons.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/consio.h>
-
-#if defined(__sparc64__) || defined(__powerpc__)
-#include <machine/sc_machdep.h>
-#else
-#include <machine/pc/display.h>
-#endif
-
-#include <dev/syscons/syscons.h>
-#include <dev/syscons/sctermvar.h>
-
-#ifdef SC_DUMB_TERMINAL
-
-/* dumb terminal emulator */
-
-static sc_term_init_t dumb_init;
-static sc_term_term_t dumb_term;
-static sc_term_puts_t dumb_puts;
-static sc_term_ioctl_t dumb_ioctl;
-static sc_term_clear_t dumb_clear;
-static sc_term_input_t dumb_input;
-static void dumb_nop(void);
-
-static sc_term_sw_t sc_term_dumb = {
- { NULL, NULL },
- "dumb", /* emulator name */
- "dumb terminal", /* description */
- "*", /* matching renderer */
- 0, /* softc size */
- 0,
- dumb_init,
- dumb_term,
- dumb_puts,
- dumb_ioctl,
- (sc_term_reset_t *)dumb_nop,
- (sc_term_default_attr_t *)dumb_nop,
- dumb_clear,
- (sc_term_notify_t *)dumb_nop,
- dumb_input,
-};
-
-SCTERM_MODULE(dumb, sc_term_dumb);
-
-static int
-dumb_init(scr_stat *scp, void **softc, int code)
-{
- switch (code) {
- case SC_TE_COLD_INIT:
- ++sc_term_dumb.te_refcount;
- break;
- case SC_TE_WARM_INIT:
- break;
- }
- return 0;
-}
-
-static int
-dumb_term(scr_stat *scp, void **softc)
-{
- --sc_term_dumb.te_refcount;
- return 0;
-}
-
-static void
-dumb_puts(scr_stat *scp, u_char *buf, int len)
-{
- while (len > 0) {
- ++scp->sc->write_in_progress;
- sc_term_gen_print(scp, &buf, &len, SC_NORM_ATTR << 8);
- sc_term_gen_scroll(scp, scp->sc->scr_map[0x20],
- SC_NORM_ATTR << 8);
- --scp->sc->write_in_progress;
- }
-}
-
-static int
-dumb_ioctl(scr_stat *scp, struct tty *tp, u_long cmd, caddr_t data,
- int flag, struct proc *p)
-{
- vid_info_t *vi;
-
- switch (cmd) {
- case GIO_ATTR: /* get current attributes */
- *(int*)data = SC_NORM_ATTR;
- return 0;
- case CONS_GETINFO: /* get current (virtual) console info */
- vi = (vid_info_t *)data;
- if (vi->size != sizeof(struct vid_info))
- return EINVAL;
- vi->mv_norm.fore = SC_NORM_ATTR & 0x0f;
- vi->mv_norm.back = (SC_NORM_ATTR >> 4) & 0x0f;
- vi->mv_rev.fore = SC_NORM_ATTR & 0x0f;
- vi->mv_rev.back = (SC_NORM_ATTR >> 4) & 0x0f;
- /*
- * The other fields are filled by the upper routine. XXX
- */
- return ENOIOCTL;
- }
- return ENOIOCTL;
-}
-
-static void
-dumb_clear(scr_stat *scp)
-{
- sc_move_cursor(scp, 0, 0);
- sc_vtb_clear(&scp->vtb, scp->sc->scr_map[0x20], SC_NORM_ATTR << 8);
- mark_all(scp);
-}
-
-static int
-dumb_input(scr_stat *scp, int c, struct tty *tp)
-{
- return FALSE;
-}
-
-static void
-dumb_nop(void)
-{
- /* nothing */
-}
-
-#endif /* SC_DUMB_TERMINAL */
diff --git a/sys/dev/syscons/scterm-sc.c b/sys/dev/syscons/scterm-sc.c
deleted file mode 100644
index b52bea8..0000000
--- a/sys/dev/syscons/scterm-sc.c
+++ /dev/null
@@ -1,811 +0,0 @@
-/*-
- * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
- * Copyright (c) 1992-1998 Søren Schmidt
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer as
- * the first lines of this file unmodified.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_syscons.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/consio.h>
-
-#if defined(__sparc64__) || defined(__powerpc__)
-#include <machine/sc_machdep.h>
-#else
-#include <machine/pc/display.h>
-#endif
-
-#include <dev/syscons/syscons.h>
-#include <dev/syscons/sctermvar.h>
-
-#ifndef SC_DUMB_TERMINAL
-
-#define MAX_ESC_PAR 5
-
-/* attribute flags */
-typedef struct {
- u_short fg; /* foreground color */
- u_short bg; /* background color */
-} color_t;
-
-typedef struct {
- int flags;
-#define SCTERM_BUSY (1 << 0)
- int esc;
- int num_param;
- int last_param;
- int param[MAX_ESC_PAR];
- int saved_xpos;
- int saved_ypos;
- int attr_mask; /* current logical attr mask */
-#define NORMAL_ATTR 0x00
-#define BLINK_ATTR 0x01
-#define BOLD_ATTR 0x02
-#define UNDERLINE_ATTR 0x04
-#define REVERSE_ATTR 0x08
-#define FG_CHANGED 0x10
-#define BG_CHANGED 0x20
- int cur_attr; /* current hardware attr word */
- color_t cur_color; /* current hardware color */
- color_t std_color; /* normal hardware color */
- color_t rev_color; /* reverse hardware color */
- color_t dflt_std_color; /* default normal color */
- color_t dflt_rev_color; /* default reverse color */
-} term_stat;
-
-static sc_term_init_t scterm_init;
-static sc_term_term_t scterm_term;
-static sc_term_puts_t scterm_puts;
-static sc_term_ioctl_t scterm_ioctl;
-static sc_term_reset_t scterm_reset;
-static sc_term_default_attr_t scterm_default_attr;
-static sc_term_clear_t scterm_clear;
-static sc_term_notify_t scterm_notify;
-static sc_term_input_t scterm_input;
-
-static sc_term_sw_t sc_term_sc = {
- { NULL, NULL },
- "sc", /* emulator name */
- "syscons terminal", /* description */
- "*", /* matching renderer, any :-) */
- sizeof(term_stat), /* softc size */
- 0,
- scterm_init,
- scterm_term,
- scterm_puts,
- scterm_ioctl,
- scterm_reset,
- scterm_default_attr,
- scterm_clear,
- scterm_notify,
- scterm_input,
-};
-
-SCTERM_MODULE(sc, sc_term_sc);
-
-static term_stat reserved_term_stat;
-static void scterm_scan_esc(scr_stat *scp, term_stat *tcp,
- u_char c);
-static int mask2attr(term_stat *tcp);
-
-static int
-scterm_init(scr_stat *scp, void **softc, int code)
-{
- term_stat *tcp;
-
- if (*softc == NULL) {
- if (reserved_term_stat.flags & SCTERM_BUSY)
- return EINVAL;
- *softc = &reserved_term_stat;
- }
- tcp = *softc;
-
- switch (code) {
- case SC_TE_COLD_INIT:
- bzero(tcp, sizeof(*tcp));
- tcp->flags = SCTERM_BUSY;
- tcp->esc = 0;
- tcp->saved_xpos = -1;
- tcp->saved_ypos = -1;
- tcp->attr_mask = NORMAL_ATTR;
- /* XXX */
- tcp->dflt_std_color.fg = SC_NORM_ATTR & 0x0f;
- tcp->dflt_std_color.bg = (SC_NORM_ATTR >> 4) & 0x0f;
- tcp->dflt_rev_color.fg = SC_NORM_REV_ATTR & 0x0f;
- tcp->dflt_rev_color.bg = (SC_NORM_REV_ATTR >> 4) & 0x0f;
- tcp->std_color = tcp->dflt_std_color;
- tcp->rev_color = tcp->dflt_rev_color;
- tcp->cur_color = tcp->std_color;
- tcp->cur_attr = mask2attr(tcp);
- ++sc_term_sc.te_refcount;
- break;
-
- case SC_TE_WARM_INIT:
- tcp->esc = 0;
- tcp->saved_xpos = -1;
- tcp->saved_ypos = -1;
-#if 0
- tcp->std_color = tcp->dflt_std_color;
- tcp->rev_color = tcp->dflt_rev_color;
-#endif
- tcp->cur_color = tcp->std_color;
- tcp->cur_attr = mask2attr(tcp);
- break;
- }
-
- return 0;
-}
-
-static int
-scterm_term(scr_stat *scp, void **softc)
-{
- if (*softc == &reserved_term_stat) {
- *softc = NULL;
- bzero(&reserved_term_stat, sizeof(reserved_term_stat));
- }
- --sc_term_sc.te_refcount;
- return 0;
-}
-
-static void
-scterm_scan_esc(scr_stat *scp, term_stat *tcp, u_char c)
-{
- static u_char ansi_col[16] = {
- FG_BLACK, FG_RED, FG_GREEN, FG_BROWN,
- FG_BLUE, FG_MAGENTA, FG_CYAN, FG_LIGHTGREY,
- FG_DARKGREY, FG_LIGHTRED, FG_LIGHTGREEN, FG_YELLOW,
- FG_LIGHTBLUE, FG_LIGHTMAGENTA, FG_LIGHTCYAN, FG_WHITE
- };
- static int cattrs[] = {
- 0, /* block */
- CONS_BLINK_CURSOR, /* blinking block */
- CONS_CHAR_CURSOR, /* underline */
- CONS_CHAR_CURSOR | CONS_BLINK_CURSOR, /* blinking underline */
- CONS_RESET_CURSOR, /* reset to default */
- CONS_HIDDEN_CURSOR, /* hide cursor */
- };
- static int tcattrs[] = {
- CONS_RESET_CURSOR | CONS_LOCAL_CURSOR, /* normal */
- CONS_HIDDEN_CURSOR | CONS_LOCAL_CURSOR, /* invisible */
- CONS_BLINK_CURSOR | CONS_LOCAL_CURSOR, /* very visible */
- };
- sc_softc_t *sc;
- int v0, v1, v2;
- int i, n;
-
- i = n = 0;
- sc = scp->sc;
- if (tcp->esc == 1) { /* seen ESC */
- switch (c) {
-
- case '7': /* Save cursor position */
- tcp->saved_xpos = scp->xpos;
- tcp->saved_ypos = scp->ypos;
- break;
-
- case '8': /* Restore saved cursor position */
- if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0)
- sc_move_cursor(scp, tcp->saved_xpos,
- tcp->saved_ypos);
- break;
-
- case '[': /* Start ESC [ sequence */
- tcp->esc = 2;
- tcp->last_param = -1;
- for (i = tcp->num_param; i < MAX_ESC_PAR; i++)
- tcp->param[i] = 1;
- tcp->num_param = 0;
- return;
-
- case 'M': /* Move cursor up 1 line, scroll if at top */
- sc_term_up_scroll(scp, 1, sc->scr_map[0x20],
- tcp->cur_attr, 0, 0);
- break;
-#ifdef notyet
- case 'Q':
- tcp->esc = 4;
- return;
-#endif
- case 'c': /* reset */
- tcp->attr_mask = NORMAL_ATTR;
- tcp->cur_color = tcp->std_color
- = tcp->dflt_std_color;
- tcp->rev_color = tcp->dflt_rev_color;
- tcp->cur_attr = mask2attr(tcp);
- sc_change_cursor_shape(scp,
- CONS_RESET_CURSOR | CONS_LOCAL_CURSOR, -1, -1);
- sc_clear_screen(scp);
- break;
-
- case '(': /* iso-2022: designate 94 character set to G0 */
- tcp->esc = 5;
- return;
- }
- } else if (tcp->esc == 2) { /* seen ESC [ */
- if (c >= '0' && c <= '9') {
- if (tcp->num_param < MAX_ESC_PAR) {
- if (tcp->last_param != tcp->num_param) {
- tcp->last_param = tcp->num_param;
- tcp->param[tcp->num_param] = 0;
- } else {
- tcp->param[tcp->num_param] *= 10;
- }
- tcp->param[tcp->num_param] += c - '0';
- return;
- }
- }
- tcp->num_param = tcp->last_param + 1;
- switch (c) {
-
- case ';':
- if (tcp->num_param < MAX_ESC_PAR)
- return;
- break;
-
- case '=':
- tcp->esc = 3;
- tcp->last_param = -1;
- for (i = tcp->num_param; i < MAX_ESC_PAR; i++)
- tcp->param[i] = 1;
- tcp->num_param = 0;
- return;
-
- case 'A': /* up n rows */
- sc_term_up(scp, tcp->param[0], 0);
- break;
-
- case 'B': /* down n rows */
- sc_term_down(scp, tcp->param[0], 0);
- break;
-
- case 'C': /* right n columns */
- sc_term_right(scp, tcp->param[0]);
- break;
-
- case 'D': /* left n columns */
- sc_term_left(scp, tcp->param[0]);
- break;
-
- case 'E': /* cursor to start of line n lines down */
- n = tcp->param[0];
- if (n < 1)
- n = 1;
- sc_move_cursor(scp, 0, scp->ypos + n);
- break;
-
- case 'F': /* cursor to start of line n lines up */
- n = tcp->param[0];
- if (n < 1)
- n = 1;
- sc_move_cursor(scp, 0, scp->ypos - n);
- break;
-
- case 'f': /* Cursor move */
- case 'H':
- if (tcp->num_param == 0)
- sc_move_cursor(scp, 0, 0);
- else if (tcp->num_param == 2)
- sc_move_cursor(scp, tcp->param[1] - 1,
- tcp->param[0] - 1);
- break;
-
- case 'J': /* Clear all or part of display */
- if (tcp->num_param == 0)
- n = 0;
- else
- n = tcp->param[0];
- sc_term_clr_eos(scp, n, sc->scr_map[0x20],
- tcp->cur_attr);
- break;
-
- case 'K': /* Clear all or part of line */
- if (tcp->num_param == 0)
- n = 0;
- else
- n = tcp->param[0];
- sc_term_clr_eol(scp, n, sc->scr_map[0x20],
- tcp->cur_attr);
- break;
-
- case 'L': /* Insert n lines */
- sc_term_ins_line(scp, scp->ypos, tcp->param[0],
- sc->scr_map[0x20], tcp->cur_attr, 0);
- break;
-
- case 'M': /* Delete n lines */
- sc_term_del_line(scp, scp->ypos, tcp->param[0],
- sc->scr_map[0x20], tcp->cur_attr, 0);
- break;
-
- case 'P': /* Delete n chars */
- sc_term_del_char(scp, tcp->param[0],
- sc->scr_map[0x20], tcp->cur_attr);
- break;
-
- case '@': /* Insert n chars */
- sc_term_ins_char(scp, tcp->param[0],
- sc->scr_map[0x20], tcp->cur_attr);
- break;
-
- case 'S': /* scroll up n lines */
- sc_term_del_line(scp, 0, tcp->param[0],
- sc->scr_map[0x20], tcp->cur_attr, 0);
- break;
-
- case 'T': /* scroll down n lines */
- sc_term_ins_line(scp, 0, tcp->param[0],
- sc->scr_map[0x20], tcp->cur_attr, 0);
- break;
-
- case 'X': /* erase n characters in line */
- n = tcp->param[0];
- if (n < 1)
- n = 1;
- if (n > scp->xsize - scp->xpos)
- n = scp->xsize - scp->xpos;
- sc_vtb_erase(&scp->vtb, scp->cursor_pos, n,
- sc->scr_map[0x20], tcp->cur_attr);
- mark_for_update(scp, scp->cursor_pos);
- mark_for_update(scp, scp->cursor_pos + n - 1);
- break;
-
- case 'Z': /* move n tabs backwards */
- sc_term_backtab(scp, tcp->param[0]);
- break;
-
- case '`': /* move cursor to column n */
- sc_term_col(scp, tcp->param[0]);
- break;
-
- case 'a': /* move cursor n columns to the right */
- sc_term_right(scp, tcp->param[0]);
- break;
-
- case 'd': /* move cursor to row n */
- sc_term_row(scp, tcp->param[0]);
- break;
-
- case 'e': /* move cursor n rows down */
- sc_term_down(scp, tcp->param[0], 0);
- break;
-
- case 'm': /* change attribute */
- if (tcp->num_param == 0) {
- tcp->attr_mask = NORMAL_ATTR;
- tcp->cur_color = tcp->std_color;
- tcp->cur_attr = mask2attr(tcp);
- break;
- }
- for (i = 0; i < tcp->num_param; i++) {
- switch (n = tcp->param[i]) {
- case 0: /* back to normal */
- tcp->attr_mask = NORMAL_ATTR;
- tcp->cur_color = tcp->std_color;
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 1: /* bold */
- tcp->attr_mask |= BOLD_ATTR;
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 4: /* underline */
- tcp->attr_mask |= UNDERLINE_ATTR;
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 5: /* blink */
- tcp->attr_mask |= BLINK_ATTR;
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 7: /* reverse */
- tcp->attr_mask |= REVERSE_ATTR;
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 22: /* remove bold (or dim) */
- tcp->attr_mask &= ~BOLD_ATTR;
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 24: /* remove underline */
- tcp->attr_mask &= ~UNDERLINE_ATTR;
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 25: /* remove blink */
- tcp->attr_mask &= ~BLINK_ATTR;
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 27: /* remove reverse */
- tcp->attr_mask &= ~REVERSE_ATTR;
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 30: case 31: /* set ansi fg color */
- case 32: case 33: case 34:
- case 35: case 36: case 37:
- tcp->attr_mask |= FG_CHANGED;
- tcp->cur_color.fg = ansi_col[n - 30];
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 39: /* restore fg color back to normal */
- tcp->attr_mask &= ~(FG_CHANGED|BOLD_ATTR);
- tcp->cur_color.fg = tcp->std_color.fg;
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 40: case 41: /* set ansi bg color */
- case 42: case 43: case 44:
- case 45: case 46: case 47:
- tcp->attr_mask |= BG_CHANGED;
- tcp->cur_color.bg = ansi_col[n - 40];
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 49: /* restore bg color back to normal */
- tcp->attr_mask &= ~BG_CHANGED;
- tcp->cur_color.bg = tcp->std_color.bg;
- tcp->cur_attr = mask2attr(tcp);
- break;
- }
- }
- break;
-
- case 's': /* Save cursor position */
- tcp->saved_xpos = scp->xpos;
- tcp->saved_ypos = scp->ypos;
- break;
-
- case 'u': /* Restore saved cursor position */
- if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0)
- sc_move_cursor(scp, tcp->saved_xpos,
- tcp->saved_ypos);
- break;
-
- case 'x':
- if (tcp->num_param == 0)
- n = 0;
- else
- n = tcp->param[0];
- switch (n) {
- case 0: /* reset colors and attributes back to normal */
- tcp->attr_mask = NORMAL_ATTR;
- tcp->cur_color = tcp->std_color
- = tcp->dflt_std_color;
- tcp->rev_color = tcp->dflt_rev_color;
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 1: /* set ansi background */
- tcp->attr_mask &= ~BG_CHANGED;
- tcp->cur_color.bg = tcp->std_color.bg
- = ansi_col[tcp->param[1] & 0x0f];
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 2: /* set ansi foreground */
- tcp->attr_mask &= ~FG_CHANGED;
- tcp->cur_color.fg = tcp->std_color.fg
- = ansi_col[tcp->param[1] & 0x0f];
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 3: /* set adapter attribute directly */
- tcp->attr_mask &= ~(FG_CHANGED | BG_CHANGED);
- tcp->cur_color.fg = tcp->std_color.fg
- = tcp->param[1] & 0x0f;
- tcp->cur_color.bg = tcp->std_color.bg
- = (tcp->param[1] >> 4) & 0x0f;
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 5: /* set ansi reverse background */
- tcp->rev_color.bg = ansi_col[tcp->param[1] & 0x0f];
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 6: /* set ansi reverse foreground */
- tcp->rev_color.fg = ansi_col[tcp->param[1] & 0x0f];
- tcp->cur_attr = mask2attr(tcp);
- break;
- case 7: /* set adapter reverse attribute directly */
- tcp->rev_color.fg = tcp->param[1] & 0x0f;
- tcp->rev_color.bg = (tcp->param[1] >> 4) & 0x0f;
- tcp->cur_attr = mask2attr(tcp);
- break;
- }
- break;
-
- case 'z': /* switch to (virtual) console n */
- if (tcp->num_param == 1)
- sc_switch_scr(sc, tcp->param[0]);
- break;
- }
- } else if (tcp->esc == 3) { /* seen ESC [0-9]+ = */
- if (c >= '0' && c <= '9') {
- if (tcp->num_param < MAX_ESC_PAR) {
- if (tcp->last_param != tcp->num_param) {
- tcp->last_param = tcp->num_param;
- tcp->param[tcp->num_param] = 0;
- } else {
- tcp->param[tcp->num_param] *= 10;
- }
- tcp->param[tcp->num_param] += c - '0';
- return;
- }
- }
- tcp->num_param = tcp->last_param + 1;
- switch (c) {
-
- case ';':
- if (tcp->num_param < MAX_ESC_PAR)
- return;
- break;
-
- case 'A': /* set display border color */
- if (tcp->num_param == 1) {
- scp->border=tcp->param[0] & 0xff;
- if (scp == sc->cur_scp)
- sc_set_border(scp, scp->border);
- }
- break;
-
- case 'B': /* set bell pitch and duration */
- if (tcp->num_param == 2) {
- scp->bell_pitch = tcp->param[0];
- scp->bell_duration =
- (tcp->param[1] * hz + 99) / 100;
- }
- break;
-
- case 'C': /* set global/parmanent cursor type & shape */
- i = spltty();
- n = tcp->num_param;
- v0 = tcp->param[0];
- v1 = tcp->param[1];
- v2 = tcp->param[2];
- switch (n) {
- case 1: /* flags only */
- if (v0 < sizeof(cattrs)/sizeof(cattrs[0]))
- v0 = cattrs[v0];
- else /* backward compatibility */
- v0 = cattrs[v0 & 0x3];
- sc_change_cursor_shape(scp, v0, -1, -1);
- break;
- case 2:
- v2 = 0;
- v0 &= 0x1f; /* backward compatibility */
- v1 &= 0x1f;
- /* FALL THROUGH */
- case 3: /* base and height */
- if (v2 == 0) /* count from top */
- sc_change_cursor_shape(scp, -1,
- scp->font_size - v1 - 1,
- v1 - v0 + 1);
- else if (v2 == 1) /* count from bottom */
- sc_change_cursor_shape(scp, -1,
- v0, v1 - v0 + 1);
- break;
- }
- splx(i);
- break;
-
- case 'F': /* set adapter foreground */
- if (tcp->num_param == 1) {
- tcp->attr_mask &= ~FG_CHANGED;
- tcp->cur_color.fg = tcp->std_color.fg
- = tcp->param[0] & 0x0f;
- tcp->cur_attr = mask2attr(tcp);
- }
- break;
-
- case 'G': /* set adapter background */
- if (tcp->num_param == 1) {
- tcp->attr_mask &= ~BG_CHANGED;
- tcp->cur_color.bg = tcp->std_color.bg
- = tcp->param[0] & 0x0f;
- tcp->cur_attr = mask2attr(tcp);
- }
- break;
-
- case 'H': /* set adapter reverse foreground */
- if (tcp->num_param == 1) {
- tcp->rev_color.fg = tcp->param[0] & 0x0f;
- tcp->cur_attr = mask2attr(tcp);
- }
- break;
-
- case 'I': /* set adapter reverse background */
- if (tcp->num_param == 1) {
- tcp->rev_color.bg = tcp->param[0] & 0x0f;
- tcp->cur_attr = mask2attr(tcp);
- }
- break;
-
- case 'S': /* set local/temporary cursor type & shape */
- i = spltty();
- n = tcp->num_param;
- v0 = tcp->param[0];
- switch (n) {
- case 0:
- v0 = 0;
- /* FALL THROUGH */
- case 1:
- if (v0 < sizeof(tcattrs)/sizeof(tcattrs[0]))
- sc_change_cursor_shape(scp,
- tcattrs[v0], -1, -1);
- break;
- }
- splx(i);
- break;
- }
-#ifdef notyet
- } else if (tcp->esc == 4) { /* seen ESC Q */
- /* to be filled */
-#endif
- } else if (tcp->esc == 5) { /* seen ESC ( */
- switch (c) {
- case 'B': /* iso-2022: desginate ASCII into G0 */
- break;
- /* other items to be filled */
- default:
- break;
- }
- }
- tcp->esc = 0;
-}
-
-static void
-scterm_puts(scr_stat *scp, u_char *buf, int len)
-{
- term_stat *tcp;
-
- tcp = scp->ts;
-outloop:
- scp->sc->write_in_progress++;
-
- if (tcp->esc) {
- scterm_scan_esc(scp, tcp, *buf);
- buf++;
- len--;
- } else {
- switch (*buf) {
- case 0x1b:
- tcp->esc = 1;
- tcp->num_param = 0;
- buf++;
- len--;
- break;
- default:
- sc_term_gen_print(scp, &buf, &len, tcp->cur_attr);
- break;
- }
- }
-
- sc_term_gen_scroll(scp, scp->sc->scr_map[0x20], tcp->cur_attr);
-
- scp->sc->write_in_progress--;
- if (len)
- goto outloop;
-}
-
-static int
-scterm_ioctl(scr_stat *scp, struct tty *tp, u_long cmd, caddr_t data,
- struct thread *td)
-{
- term_stat *tcp = scp->ts;
- vid_info_t *vi;
-
- switch (cmd) {
- case GIO_ATTR: /* get current attributes */
- /* FIXME: */
- *(int*)data = (tcp->cur_attr >> 8) & 0xff;
- return 0;
- case CONS_GETINFO: /* get current (virtual) console info */
- vi = (vid_info_t *)data;
- if (vi->size != sizeof(struct vid_info))
- return EINVAL;
- vi->mv_norm.fore = tcp->std_color.fg;
- vi->mv_norm.back = tcp->std_color.bg;
- vi->mv_rev.fore = tcp->rev_color.fg;
- vi->mv_rev.back = tcp->rev_color.bg;
- /*
- * The other fields are filled by the upper routine. XXX
- */
- return ENOIOCTL;
- }
- return ENOIOCTL;
-}
-
-static int
-scterm_reset(scr_stat *scp, int code)
-{
- /* FIXME */
- return 0;
-}
-
-static void
-scterm_default_attr(scr_stat *scp, int color, int rev_color)
-{
- term_stat *tcp = scp->ts;
-
- tcp->dflt_std_color.fg = color & 0x0f;
- tcp->dflt_std_color.bg = (color >> 4) & 0x0f;
- tcp->dflt_rev_color.fg = rev_color & 0x0f;
- tcp->dflt_rev_color.bg = (rev_color >> 4) & 0x0f;
- tcp->std_color = tcp->dflt_std_color;
- tcp->rev_color = tcp->dflt_rev_color;
- tcp->cur_color = tcp->std_color;
- tcp->cur_attr = mask2attr(tcp);
-}
-
-static void
-scterm_clear(scr_stat *scp)
-{
- term_stat *tcp = scp->ts;
-
- sc_move_cursor(scp, 0, 0);
- sc_vtb_clear(&scp->vtb, scp->sc->scr_map[0x20], tcp->cur_attr);
- mark_all(scp);
-}
-
-static void
-scterm_notify(scr_stat *scp, int event)
-{
- switch (event) {
- case SC_TE_NOTIFY_VTSWITCH_IN:
- break;
- case SC_TE_NOTIFY_VTSWITCH_OUT:
- break;
- }
-}
-
-static int
-scterm_input(scr_stat *scp, int c, struct tty *tp)
-{
- return FALSE;
-}
-
-/*
- * Calculate hardware attributes word using logical attributes mask and
- * hardware colors
- */
-
-/* FIXME */
-static int
-mask2attr(term_stat *tcp)
-{
- int attr, mask = tcp->attr_mask;
-
- if (mask & REVERSE_ATTR) {
- attr = ((mask & FG_CHANGED) ?
- tcp->cur_color.bg : tcp->rev_color.fg) |
- (((mask & BG_CHANGED) ?
- tcp->cur_color.fg : tcp->rev_color.bg) << 4);
- } else
- attr = tcp->cur_color.fg | (tcp->cur_color.bg << 4);
-
- /* XXX: underline mapping for Hercules adapter can be better */
- if (mask & (BOLD_ATTR | UNDERLINE_ATTR))
- attr ^= 0x08;
- if (mask & BLINK_ATTR)
- attr ^= 0x80;
-
- return (attr << 8);
-}
-
-#endif /* SC_DUMB_TERMINAL */
diff --git a/sys/dev/syscons/scterm-teken.c b/sys/dev/syscons/scterm-teken.c
new file mode 100644
index 0000000..798a2cd
--- /dev/null
+++ b/sys/dev/syscons/scterm-teken.c
@@ -0,0 +1,504 @@
+/*-
+ * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
+ * All rights reserved.
+ *
+ * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer as
+ * the first lines of this file unmodified.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_syscons.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/consio.h>
+
+#if defined(__sparc64__) || defined(__powerpc__)
+#include <machine/sc_machdep.h>
+#else
+#include <machine/pc/display.h>
+#endif
+
+#include <dev/syscons/syscons.h>
+
+#include <dev/syscons/teken/teken.h>
+
+static void scteken_revattr(unsigned char, teken_attr_t *);
+
+static sc_term_init_t scteken_init;
+static sc_term_term_t scteken_term;
+static sc_term_puts_t scteken_puts;
+static sc_term_ioctl_t scteken_ioctl;
+static sc_term_default_attr_t scteken_default_attr;
+static sc_term_clear_t scteken_clear;
+static sc_term_input_t scteken_input;
+static void scteken_nop(void);
+
+typedef struct {
+ teken_t ts_teken;
+ int ts_busy;
+} teken_stat;
+
+static teken_stat reserved_teken_stat;
+
+static sc_term_sw_t sc_term_scteken = {
+ { NULL, NULL },
+ "scteken", /* emulator name */
+ "teken terminal", /* description */
+ "*", /* matching renderer */
+ sizeof(teken_stat), /* softc size */
+ 0,
+ scteken_init,
+ scteken_term,
+ scteken_puts,
+ scteken_ioctl,
+ (sc_term_reset_t *)scteken_nop,
+ scteken_default_attr,
+ scteken_clear,
+ (sc_term_notify_t *)scteken_nop,
+ scteken_input,
+};
+
+SCTERM_MODULE(scteken, sc_term_scteken);
+
+static tf_bell_t scteken_bell;
+static tf_cursor_t scteken_cursor;
+static tf_putchar_t scteken_putchar;
+static tf_fill_t scteken_fill;
+static tf_copy_t scteken_copy;
+static tf_param_t scteken_param;
+static tf_respond_t scteken_respond;
+
+static const teken_funcs_t scteken_funcs = {
+ .tf_bell = scteken_bell,
+ .tf_cursor = scteken_cursor,
+ .tf_putchar = scteken_putchar,
+ .tf_fill = scteken_fill,
+ .tf_copy = scteken_copy,
+ .tf_param = scteken_param,
+ .tf_respond = scteken_respond,
+};
+
+static int
+scteken_init(scr_stat *scp, void **softc, int code)
+{
+ teken_stat *ts = scp->ts;
+ teken_pos_t tp;
+
+ if (*softc == NULL) {
+ if (reserved_teken_stat.ts_busy)
+ return (EINVAL);
+ *softc = &reserved_teken_stat;
+ }
+ ts = *softc;
+
+ switch (code) {
+ case SC_TE_COLD_INIT:
+ ++sc_term_scteken.te_refcount;
+ ts->ts_busy = 1;
+ /* FALLTHROUGH */
+ case SC_TE_WARM_INIT:
+ teken_init(&ts->ts_teken, &scteken_funcs, scp);
+
+ tp.tp_row = scp->ysize;
+ tp.tp_col = scp->xsize;
+ teken_set_winsize(&ts->ts_teken, &tp);
+
+ tp.tp_row = scp->cursor_pos / scp->xsize;
+ tp.tp_col = scp->cursor_pos % scp->xsize;
+ teken_set_cursor(&ts->ts_teken, &tp);
+ break;
+ }
+
+ return (0);
+}
+
+static int
+scteken_term(scr_stat *scp, void **softc)
+{
+
+ if (*softc == &reserved_teken_stat) {
+ *softc = NULL;
+ reserved_teken_stat.ts_busy = 0;
+ }
+ --sc_term_scteken.te_refcount;
+
+ return (0);
+}
+
+static void
+scteken_puts(scr_stat *scp, u_char *buf, int len)
+{
+ teken_stat *ts = scp->ts;
+
+ scp->sc->write_in_progress++;
+ teken_input(&ts->ts_teken, buf, len);
+ scp->sc->write_in_progress--;
+}
+
+static int
+scteken_ioctl(scr_stat *scp, struct tty *tp, u_long cmd, caddr_t data,
+ struct thread *td)
+{
+ vid_info_t *vi;
+
+ switch (cmd) {
+ case GIO_ATTR: /* get current attributes */
+ *(int*)data = SC_NORM_ATTR;
+ return (0);
+ case CONS_GETINFO: /* get current (virtual) console info */
+ /* XXX: INCORRECT! */
+ vi = (vid_info_t *)data;
+ if (vi->size != sizeof(struct vid_info))
+ return EINVAL;
+ vi->mv_norm.fore = SC_NORM_ATTR & 0x0f;
+ vi->mv_norm.back = (SC_NORM_ATTR >> 4) & 0x0f;
+ vi->mv_rev.fore = SC_NORM_ATTR & 0x0f;
+ vi->mv_rev.back = (SC_NORM_ATTR >> 4) & 0x0f;
+ /*
+ * The other fields are filled by the upper routine. XXX
+ */
+ return (ENOIOCTL);
+ }
+
+ return (ENOIOCTL);
+}
+
+static void
+scteken_default_attr(scr_stat *scp, int color, int rev_color)
+{
+ teken_stat *ts = scp->ts;
+ teken_attr_t ta;
+
+ scteken_revattr(color, &ta);
+ teken_set_defattr(&ts->ts_teken, &ta);
+}
+
+static void
+scteken_clear(scr_stat *scp)
+{
+
+ sc_move_cursor(scp, 0, 0);
+ sc_vtb_clear(&scp->vtb, scp->sc->scr_map[0x20], SC_NORM_ATTR << 8);
+ mark_all(scp);
+}
+
+static int
+scteken_input(scr_stat *scp, int c, struct tty *tp)
+{
+
+ return FALSE;
+}
+
+static void
+scteken_nop(void)
+{
+
+}
+
+/*
+ * libteken routines.
+ */
+
+static const unsigned char fgcolors_normal[TC_NCOLORS] = {
+ FG_BLACK, FG_RED, FG_GREEN, FG_BROWN,
+ FG_BLUE, FG_MAGENTA, FG_CYAN, FG_LIGHTGREY,
+};
+
+static const unsigned char fgcolors_bold[TC_NCOLORS] = {
+ FG_DARKGREY, FG_LIGHTRED, FG_LIGHTGREEN, FG_YELLOW,
+ FG_LIGHTBLUE, FG_LIGHTMAGENTA, FG_LIGHTCYAN, FG_WHITE,
+};
+
+static const unsigned char bgcolors[TC_NCOLORS] = {
+ BG_BLACK, BG_RED, BG_GREEN, BG_BROWN,
+ BG_BLUE, BG_MAGENTA, BG_CYAN, BG_LIGHTGREY,
+};
+
+static void
+scteken_revattr(unsigned char color, teken_attr_t *a)
+{
+ teken_color_t fg, bg;
+
+ /*
+ * XXX: Reverse conversion of syscons to teken attributes. Not
+ * realiable. Maybe we should turn it into a 1:1 mapping one of
+ * these days?
+ */
+
+ a->ta_format = 0;
+ a->ta_fgcolor = TC_WHITE;
+ a->ta_bgcolor = TC_BLACK;
+
+#ifdef FG_BLINK
+ if (color & FG_BLINK) {
+ a->ta_format |= TF_BLINK;
+ color &= ~FG_BLINK;
+ }
+#endif /* FG_BLINK */
+
+ for (fg = 0; fg < TC_NCOLORS; fg++) {
+ for (bg = 0; bg < TC_NCOLORS; bg++) {
+ if ((fgcolors_normal[fg] | bgcolors[bg]) == color) {
+ a->ta_fgcolor = fg;
+ a->ta_bgcolor = bg;
+ return;
+ }
+
+ if ((fgcolors_bold[fg] | bgcolors[bg]) == color) {
+ a->ta_fgcolor = fg;
+ a->ta_bgcolor = bg;
+ a->ta_format |= TF_BOLD;
+ return;
+ }
+ }
+ }
+}
+
+static inline unsigned int
+scteken_attr(const teken_attr_t *a)
+{
+ unsigned int attr = 0;
+
+ if (a->ta_format & TF_BOLD)
+ attr |= fgcolors_bold[a->ta_fgcolor];
+ else
+ attr |= fgcolors_normal[a->ta_fgcolor];
+ attr |= bgcolors[a->ta_bgcolor];
+
+#ifdef FG_UNDERLINE
+ if (a->ta_format & TF_UNDERLINE)
+ attr |= FG_UNDERLINE;
+#endif /* FG_UNDERLINE */
+#ifdef FG_BLINK
+ if (a->ta_format & TF_BLINK)
+ attr |= FG_BLINK;
+#endif /* FG_BLINK */
+
+ return (attr << 8);
+}
+
+static void
+scteken_bell(void *arg)
+{
+ scr_stat *scp = arg;
+
+ sc_bell(scp, scp->bell_pitch, scp->bell_duration);
+}
+
+static void
+scteken_cursor(void *arg, const teken_pos_t *p)
+{
+ scr_stat *scp = arg;
+
+ sc_move_cursor(scp, p->tp_col, p->tp_row);
+}
+
+static void
+scteken_putchar(void *arg, const teken_pos_t *tp, teken_char_t c,
+ const teken_attr_t *a)
+{
+ scr_stat *scp = arg;
+ u_char *map;
+ u_char ch;
+ vm_offset_t p;
+ int cursor, attr;
+
+#ifdef TEKEN_UTF8
+ if (c >= 0x80) {
+ /* XXX: Don't display UTF-8 yet. */
+ attr = (FG_YELLOW|BG_RED) << 8;
+ ch = '?';
+ } else
+#endif /* TEKEN_UTF8 */
+ {
+ attr = scteken_attr(a);
+ ch = c;
+ }
+
+ map = scp->sc->scr_map;
+
+ cursor = tp->tp_row * scp->xsize + tp->tp_col;
+ p = sc_vtb_pointer(&scp->vtb, cursor);
+ sc_vtb_putchar(&scp->vtb, p, map[ch], attr);
+
+ mark_for_update(scp, cursor);
+ /*
+ * XXX: Why do we need this? Only marking `cursor' should be
+ * enough. Without this line, we get artifacts.
+ */
+ mark_for_update(scp, imin(cursor + 1, scp->xsize * scp->ysize - 1));
+}
+
+static void
+scteken_fill(void *arg, const teken_rect_t *r, teken_char_t c,
+ const teken_attr_t *a)
+{
+ scr_stat *scp = arg;
+ u_char *map;
+ u_char ch;
+ unsigned int width;
+ int attr, row;
+
+#ifdef TEKEN_UTF8
+ if (c >= 0x80) {
+ /* XXX: Don't display UTF-8 yet. */
+ attr = (FG_YELLOW|BG_RED) << 8;
+ ch = '?';
+ } else
+#endif /* TEKEN_UTF8 */
+ {
+ attr = scteken_attr(a);
+ ch = c;
+ }
+
+ map = scp->sc->scr_map;
+
+ if (r->tr_begin.tp_col == 0 && r->tr_end.tp_col == scp->xsize) {
+ /* Single contiguous region to fill. */
+ sc_vtb_erase(&scp->vtb, r->tr_begin.tp_row * scp->xsize,
+ (r->tr_end.tp_row - r->tr_begin.tp_row) * scp->xsize,
+ map[ch], attr);
+ } else {
+ /* Fill display line by line. */
+ width = r->tr_end.tp_col - r->tr_begin.tp_col;
+
+ for (row = r->tr_begin.tp_row; row < r->tr_end.tp_row; row++) {
+ sc_vtb_erase(&scp->vtb, r->tr_begin.tp_row *
+ scp->xsize + r->tr_begin.tp_col,
+ width, map[ch], attr);
+ }
+ }
+
+ /* Mark begin and end positions to be refreshed. */
+ mark_for_update(scp,
+ r->tr_begin.tp_row * scp->xsize + r->tr_begin.tp_col);
+ mark_for_update(scp,
+ (r->tr_end.tp_row - 1) * scp->xsize + (r->tr_end.tp_col - 1));
+ sc_remove_cutmarking(scp);
+}
+
+static void
+scteken_copy(void *arg, const teken_rect_t *r, const teken_pos_t *p)
+{
+ scr_stat *scp = arg;
+ unsigned int width;
+ int src, dst, end;
+
+#ifndef SC_NO_HISTORY
+ /*
+ * We count a line of input as history if we perform a copy of
+ * one whole line upward. In other words: if a line of text gets
+ * overwritten by a rectangle that's right below it.
+ */
+ if (scp->history != NULL &&
+ r->tr_begin.tp_col == 0 && r->tr_end.tp_col == scp->xsize &&
+ r->tr_begin.tp_row == p->tp_row + 1) {
+ sc_hist_save_one_line(scp, p->tp_row);
+ }
+#endif
+
+ if (r->tr_begin.tp_col == 0 && r->tr_end.tp_col == scp->xsize) {
+ /* Single contiguous region to copy. */
+ sc_vtb_move(&scp->vtb, r->tr_begin.tp_row * scp->xsize,
+ p->tp_row * scp->xsize,
+ (r->tr_end.tp_row - r->tr_begin.tp_row) * scp->xsize);
+ } else {
+ /* Copy line by line. */
+ width = r->tr_end.tp_col - r->tr_begin.tp_col;
+
+ if (p->tp_row < r->tr_begin.tp_row) {
+ /* Copy from top to bottom. */
+ src = r->tr_begin.tp_row * scp->xsize +
+ r->tr_begin.tp_col;
+ end = r->tr_end.tp_row * scp->xsize +
+ r->tr_end.tp_col;
+ dst = p->tp_row * scp->xsize + p->tp_col;
+
+ while (src < end) {
+ sc_vtb_move(&scp->vtb, src, dst, width);
+
+ src += scp->xsize;
+ dst += scp->xsize;
+ }
+ } else {
+ /* Copy from bottom to top. */
+ src = (r->tr_end.tp_row - 1) * scp->xsize +
+ r->tr_begin.tp_col;
+ end = r->tr_begin.tp_row * scp->xsize +
+ r->tr_begin.tp_col;
+ dst = (p->tp_row + r->tr_end.tp_row -
+ r->tr_begin.tp_row - 1) * scp->xsize + p->tp_col;
+
+ while (src >= end) {
+ sc_vtb_move(&scp->vtb, src, dst, width);
+
+ src -= scp->xsize;
+ dst -= scp->xsize;
+ }
+ }
+ }
+
+ /* Mark begin and end positions to be refreshed. */
+ mark_for_update(scp,
+ p->tp_row * scp->xsize + p->tp_col);
+ mark_for_update(scp,
+ (p->tp_row + r->tr_end.tp_row - r->tr_begin.tp_row - 1) *
+ scp->xsize +
+ (p->tp_col + r->tr_end.tp_col - r->tr_begin.tp_col - 1));
+ sc_remove_cutmarking(scp);
+}
+
+static void
+scteken_param(void *arg, int cmd, int value)
+{
+ scr_stat *scp = arg;
+
+ switch (cmd) {
+ case TP_SHOWCURSOR:
+ if (value) {
+ sc_change_cursor_shape(scp,
+ CONS_RESET_CURSOR|CONS_LOCAL_CURSOR, -1, -1);
+ } else {
+ sc_change_cursor_shape(scp,
+ CONS_HIDDEN_CURSOR|CONS_LOCAL_CURSOR, -1, -1);
+ }
+ break;
+ case TP_SWITCHVT:
+ sc_switch_scr(scp->sc, value);
+ break;
+ }
+}
+
+static void
+scteken_respond(void *arg, const void *buf, size_t len)
+{
+ scr_stat *scp = arg;
+
+ sc_respond(scp, buf, len);
+}
diff --git a/sys/dev/syscons/scterm.c b/sys/dev/syscons/scterm.c
index 0b9135a..f0f56b5 100644
--- a/sys/dev/syscons/scterm.c
+++ b/sys/dev/syscons/scterm.c
@@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
#include <sys/consio.h>
#include <dev/syscons/syscons.h>
-#include <dev/syscons/sctermvar.h>
SET_DECLARE(scterm_set, sc_term_sw_t);
diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c
index 37b08b6..a9b8e40 100644
--- a/sys/dev/syscons/syscons.c
+++ b/sys/dev/syscons/syscons.c
@@ -2741,6 +2741,16 @@ scinit(int unit, int flags)
init_scp(sc, sc->first_vty, scp);
sc_vtb_init(&scp->vtb, VTB_MEMORY, scp->xsize, scp->ysize,
(void *)sc_buffer, FALSE);
+
+ /* move cursors to the initial positions */
+ if (col >= scp->xsize)
+ col = 0;
+ if (row >= scp->ysize)
+ row = scp->ysize - 1;
+ scp->xpos = col;
+ scp->ypos = row;
+ scp->cursor_pos = scp->cursor_oldpos = row*scp->xsize + col;
+
if (sc_init_emulator(scp, SC_DFLT_TERM))
sc_init_emulator(scp, "*");
(*scp->tsw->te_default_attr)(scp,
@@ -2764,15 +2774,6 @@ scinit(int unit, int flags)
sc_vtb_copy(&scp->scr, 0, &scp->vtb, 0, scp->xsize*scp->ysize);
#endif
- /* move cursors to the initial positions */
- if (col >= scp->xsize)
- col = 0;
- if (row >= scp->ysize)
- row = scp->ysize - 1;
- scp->xpos = col;
- scp->ypos = row;
- scp->cursor_pos = scp->cursor_oldpos = row*scp->xsize + col;
-
if (bios_value.cursor_end < scp->font_size)
sc->dflt_curs_attr.base = scp->font_size -
bios_value.cursor_end - 1;
@@ -3569,7 +3570,7 @@ sc_show_font(scr_stat *scp, int page)
#endif /* !SC_NO_FONT_LOADING */
void
-sc_paste(scr_stat *scp, u_char *p, int count)
+sc_paste(scr_stat *scp, const u_char *p, int count)
{
struct tty *tp;
u_char *rmap;
@@ -3584,6 +3585,22 @@ sc_paste(scr_stat *scp, u_char *p, int count)
}
void
+sc_respond(scr_stat *scp, const u_char *p, int count)
+{
+ struct tty *tp;
+
+ tp = SC_DEV(scp->sc, scp->sc->cur_scp->index);
+ if (!tty_opened(tp))
+ return;
+ for (; count > 0; --count)
+ ttydisc_rint(tp, *p++, 0);
+#if 0
+ /* XXX: we can't call ttydisc_rint_done() here! */
+ ttydisc_rint_done(tp);
+#endif
+}
+
+void
sc_bell(scr_stat *scp, int pitch, int duration)
{
if (cold || shutdown_in_progress || !enable_bell)
diff --git a/sys/dev/syscons/syscons.h b/sys/dev/syscons/syscons.h
index 548cec6..56b30d3 100644
--- a/sys/dev/syscons/syscons.h
+++ b/sys/dev/syscons/syscons.h
@@ -563,7 +563,8 @@ int sc_clean_up(scr_stat *scp);
int sc_switch_scr(sc_softc_t *sc, u_int next_scr);
void sc_alloc_scr_buffer(scr_stat *scp, int wait, int discard);
int sc_init_emulator(scr_stat *scp, char *name);
-void sc_paste(scr_stat *scp, u_char *p, int count);
+void sc_paste(scr_stat *scp, const u_char *p, int count);
+void sc_respond(scr_stat *scp, const u_char *p, int count);
void sc_bell(scr_stat *scp, int pitch, int duration);
/* schistory.c */
diff --git a/sys/dev/syscons/teken/Makefile b/sys/dev/syscons/teken/Makefile
new file mode 100644
index 0000000..cbdd12b
--- /dev/null
+++ b/sys/dev/syscons/teken/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+PROG= teken_demo
+SRCS= teken_demo.c teken.c teken_state.h
+CLEANFILES= teken_state.h teken.log
+LDADD= -lncurses -lutil
+NO_MAN=
+WARNS?= 6
+
+teken_state.h: gensequences sequences
+ awk -f gensequences sequences > ${.TARGET}
+
+.include <bsd.prog.mk>
diff --git a/sys/dev/syscons/teken/gensequences b/sys/dev/syscons/teken/gensequences
new file mode 100644
index 0000000..86c7979
--- /dev/null
+++ b/sys/dev/syscons/teken/gensequences
@@ -0,0 +1,157 @@
+#!/usr/bin/awk -f
+
+#-
+# Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+function die(msg) {
+ print msg;
+ exit 1;
+}
+
+function cchar(str) {
+ if (str == "^[")
+ return "\\x1B";
+
+ return str;
+}
+
+BEGIN {
+FS = "\t+"
+
+while (getline > 0) {
+ if (NF == 0 || $1 ~ /^#/)
+ continue;
+
+ if (NF != 3 && NF != 4)
+ die("Invalid line layout: " NF " columns");
+
+ split($3, sequence, " +");
+ nsequences = 0;
+ for (s in sequence)
+ nsequences++;
+
+ prefix = "";
+ l_prefix_name[""] = "teken_state_init";
+ for (i = 1; i < nsequences; i++) {
+ n = prefix sequence[i];
+ l_prefix_parent[n] = prefix;
+ l_prefix_suffix[n] = sequence[i];
+ if (!l_prefix_name[n])
+ l_prefix_name[n] = "teken_state_" ++npr;
+ prefix = n;
+ }
+
+ suffix = sequence[nsequences];
+ cmd = prefix suffix;
+
+ # Fill lists
+ if (l_cmd_name[cmd] != "")
+ die(cmd " already exists");
+ l_cmd_prefix[cmd] = prefix;
+ l_cmd_suffix[cmd] = suffix;
+ l_cmd_args[cmd] = $4;
+ l_cmd_abbr[cmd] = $1;
+ l_cmd_name[cmd] = $2;
+ l_cmd_c_name[cmd] = "teken_subr_" tolower($2);
+ gsub(" ", "_", l_cmd_c_name[cmd]);
+
+ if ($4 != "")
+ l_prefix_numbercmds[prefix]++;
+}
+
+print "/* Generated file. Do not edit. */";
+print "";
+
+for (p in l_prefix_name) {
+ if (l_prefix_name[p] != "teken_state_init")
+ print "static teken_state_t " l_prefix_name[p] ";";
+}
+
+for (p in l_prefix_name) {
+ print "";
+ print "/* '" p "' */";
+ print "static void";
+ print l_prefix_name[p] "(teken_t *t, teken_char_t c)";
+ print "{";
+
+ if (l_prefix_numbercmds[p] > 0) {
+ print "";
+ print "\tif (teken_state_numbers(t, c))";
+ print "\t\treturn;";
+ }
+
+ print "";
+ print "\tswitch (c) {";
+ for (c in l_cmd_prefix) {
+ if (l_cmd_prefix[c] != p)
+ continue;
+
+ print "\tcase '" cchar(l_cmd_suffix[c]) "': /* " l_cmd_abbr[c] ": " l_cmd_name[c] " */";
+
+ if (l_cmd_args[c] == "v") {
+ print "\t\t" l_cmd_c_name[c] "(t, t->t_curnum, t->t_nums);";
+ } else {
+ printf "\t\t%s(t", l_cmd_c_name[c];
+ split(l_cmd_args[c], args, " ");
+ for (a = 1; args[a] != ""; a++) {
+ if (args[a] == "n")
+ printf ", (t->t_curnum < %d || t->t_nums[%d] == 0) ? 1 : t->t_nums[%d]", a, (a - 1), (a - 1);
+ else if (args[a] == "r")
+ printf ", t->t_curnum < %d ? 0 : t->t_nums[%d]", a, (a - 1);
+ else
+ die("Invalid argument type: " args[a]);
+ }
+ print ");";
+ }
+ print "\t\tbreak;";
+ }
+ for (pc in l_prefix_parent) {
+ if (l_prefix_parent[pc] != p)
+ continue;
+ print "\tcase '" cchar(l_prefix_suffix[pc]) "':";
+ print "\t\tteken_state_switch(t, " l_prefix_name[pc] ");";
+ print "\t\treturn;";
+ }
+
+ print "\tdefault:";
+ if (l_prefix_name[p] == "teken_state_init") {
+ print "\t\tteken_subr_regular_character(t, c);";
+ } else {
+ print "\t\tteken_printf(\"Unsupported sequence in " l_prefix_name[p] ": %u\\n\", (unsigned int)c);";
+ }
+ print "\t\tbreak;";
+
+ print "\t}";
+
+ if (l_prefix_name[p] != "teken_state_init") {
+ print "";
+ print "\tteken_state_switch(t, teken_state_init);";
+ }
+ print "}";
+}
+
+}
diff --git a/sys/dev/syscons/teken/sequences b/sys/dev/syscons/teken/sequences
new file mode 100644
index 0000000..eb5a9fe
--- /dev/null
+++ b/sys/dev/syscons/teken/sequences
@@ -0,0 +1,107 @@
+#-
+# Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+# File format is as follows:
+# Abbr Abbreviation of sequence name
+# Name Sequence name (will be converted to C function name)
+# Sequence Bytes that form the sequence
+# Arguments Standard value of arguments passed to this sequence
+# - `n' non-zero number (0 gets converted to 1)
+# - `r' regular numeric argument
+# - `v' means a variable number of arguments
+
+# Abbr Name Sequence Arguments
+CBT Cursor Backward Tabulation ^[ [ Z n
+CHT Cursor Forward Tabulation ^[ [ I n
+CNL Cursor Next Line ^[ [ E n
+CPL Cursor Previous Line ^[ [ F n
+CPR Cursor Position Report ^[ [ n r
+CUB Cursor Backward ^[ [ D n
+CUD Cursor Down ^[ [ B n
+CUD Cursor Down ^[ [ e n
+CUF Cursor Forward ^[ [ C n
+CUF Cursor Forward ^[ [ a n
+CUP Cursor Position ^[ [ H n n
+CUP Cursor Position ^[ [ f n n
+CUU Cursor Up ^[ [ A n
+DA1 Primary Device Attributes ^[ [ c r
+DA2 Secondary Device Attributes ^[ [ > c r
+DC Delete character ^[ [ P n
+DCS Device Control String ^[ P
+DECALN Alignment test ^[ # 8
+DECDHL Double Height Double Width Line Top ^[ # 3
+DECDHL Double Height Double Width Line Bottom ^[ # 4
+DECDWL Single Height Double Width Line ^[ # 6
+DECKPAM Keypad application mode ^[ =
+DECKPNM Keypad numeric mode ^[ >
+DECRC Restore cursor ^[ 8
+DECRC Restore cursor ^[ [ u
+DECRM Reset DEC mode ^[ [ ? l r
+DECSC Save cursor ^[ 7
+DECSC Save cursor ^[ [ s
+DECSM Set DEC mode ^[ [ ? h r
+DECSTBM Set top and bottom margins ^[ [ r r r
+DECSWL Single Height Single Width Line ^[ # 5
+DL Delete line ^[ [ M n
+DSR Device Status Report ^[ [ ? n r
+ECH Erase character ^[ [ X n
+ED Erase display ^[ [ J r
+EL Erase line ^[ [ K r
+HPA Horizontal Position Absolute ^[ [ G n
+HPA Horizontal Position Absolute ^[ [ ` n
+HTS Horizontal Tab Set ^[ H
+ICH Insert character ^[ [ @ n
+IL Insert line ^[ [ L n
+IND Index ^[ D
+NEL Next line ^[ E
+RI Reverse index ^[ M
+RIS Reset to Initial State ^[ c
+RM Reset Mode ^[ [ l r
+SCS SCS ^[ ( 0
+SCS SCS ^[ ( 1
+SCS SCS ^[ ( 2
+SCS SCS ^[ ( A
+SCS SCS ^[ ( B
+SCS SCS ^[ ) 0
+SCS SCS ^[ ) 1
+SCS SCS ^[ ) 2
+SCS SCS ^[ ) A
+SCS SCS ^[ ) B
+SD Pan Up ^[ [ T n
+SGR Set Graphic Rendition ^[ [ m v
+SM Set Mode ^[ [ h r
+ST String Terminator ^[ \\
+SU Pan Down ^[ [ S n
+TBC Tab Clear ^[ [ g r
+VPA Vertical Position Absolute ^[ [ d n
+
+# Cons25 compatibility sequences
+C25CURS Cons25 set cursor type ^[ [ = S r
+C25VTSW Cons25 switch virtual terminal ^[ [ z r
+
+# VT52 compatibility
+#DECID VT52 DECID ^[ Z
diff --git a/sys/dev/syscons/teken/teken.c b/sys/dev/syscons/teken/teken.c
new file mode 100644
index 0000000..e1efcf7
--- /dev/null
+++ b/sys/dev/syscons/teken/teken.c
@@ -0,0 +1,386 @@
+/*-
+ * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+#if defined(__FreeBSD__) && defined(_KERNEL)
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/systm.h>
+#define teken_assert(x) MPASS(x)
+#define teken_printf(x,...)
+#else /* !(__FreeBSD__ && _KERNEL) */
+#include <sys/types.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#define teken_assert(x) assert(x)
+#define teken_printf(x,...) do { \
+ if (df != NULL) \
+ fprintf(df, x, ## __VA_ARGS__); \
+} while (0)
+/* debug messages */
+static FILE *df;
+#endif /* __FreeBSD__ && _KERNEL */
+
+#include "teken.h"
+#ifdef TEKEN_UTF8
+#include "teken_wcwidth.h"
+#else /* !TEKEN_UTF8 */
+static inline int
+teken_wcwidth(teken_char_t c)
+{
+
+ return (c <= 0x1B) ? -1 : 1;
+}
+#endif /* TEKEN_UTF8 */
+
+/* Private flags for teken_format_t. */
+#define TF_REVERSE 0x08
+
+/* Private flags for t_stateflags. */
+#define TS_FIRSTDIGIT 0x01 /* First numeric digit in escape sequence. */
+#define TS_INSERT 0x02 /* Insert mode. */
+#define TS_AUTOWRAP 0x04 /* Autowrap. */
+#define TS_ORIGIN 0x08 /* Origin mode. */
+#define TS_WRAPPED 0x10 /* Next character should be printed on col 0. */
+
+/* Character that blanks a cell. */
+#define BLANK ' '
+
+static teken_state_t teken_state_init;
+
+/*
+ * Wrappers for hooks.
+ */
+
+static inline void
+teken_funcs_bell(teken_t *t)
+{
+
+ t->t_funcs->tf_bell(t->t_softc);
+}
+
+static inline void
+teken_funcs_cursor(teken_t *t)
+{
+
+ teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
+ teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
+
+ t->t_funcs->tf_cursor(t->t_softc, &t->t_cursor);
+}
+
+static inline void
+teken_funcs_putchar(teken_t *t, const teken_pos_t *p, teken_char_t c,
+ const teken_attr_t *a)
+{
+ teken_attr_t ta;
+
+ teken_assert(p->tp_row < t->t_winsize.tp_row);
+ teken_assert(p->tp_col < t->t_winsize.tp_col);
+
+ /* Apply inversion. */
+ if (a->ta_format & TF_REVERSE) {
+ ta.ta_format = a->ta_format;
+ ta.ta_fgcolor = a->ta_bgcolor;
+ ta.ta_bgcolor = a->ta_fgcolor;
+ a = &ta;
+ }
+
+ t->t_funcs->tf_putchar(t->t_softc, p, c, a);
+}
+
+static inline void
+teken_funcs_fill(teken_t *t, const teken_rect_t *r,
+ const teken_char_t c, const teken_attr_t *a)
+{
+ teken_attr_t ta;
+
+ teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
+ teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
+ teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
+ teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
+
+ /* Apply inversion. */
+ if (a->ta_format & TF_REVERSE) {
+ ta.ta_format = a->ta_format;
+ ta.ta_fgcolor = a->ta_bgcolor;
+ ta.ta_bgcolor = a->ta_fgcolor;
+ a = &ta;
+ }
+
+ t->t_funcs->tf_fill(t->t_softc, r, c, a);
+}
+
+static inline void
+teken_funcs_copy(teken_t *t, const teken_rect_t *r, const teken_pos_t *p)
+{
+
+ teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
+ teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
+ teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
+ teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
+ teken_assert(p->tp_row + (r->tr_end.tp_row - r->tr_begin.tp_row) <= t->t_winsize.tp_row);
+ teken_assert(p->tp_col + (r->tr_end.tp_col - r->tr_begin.tp_col) <= t->t_winsize.tp_col);
+
+ t->t_funcs->tf_copy(t->t_softc, r, p);
+}
+
+static inline void
+teken_funcs_param(teken_t *t, int cmd, int value)
+{
+
+ t->t_funcs->tf_param(t->t_softc, cmd, value);
+}
+
+static inline void
+teken_funcs_respond(teken_t *t, const void *buf, size_t len)
+{
+
+ t->t_funcs->tf_respond(t->t_softc, buf, len);
+}
+
+#include "teken_subr.h"
+#include "teken_subr_compat.h"
+
+/*
+ * Programming interface.
+ */
+
+void
+teken_init(teken_t *t, const teken_funcs_t *tf, void *softc)
+{
+ teken_pos_t tp = { .tp_row = 24, .tp_col = 80 };
+
+#if !(defined(__FreeBSD__) && defined(_KERNEL))
+ df = fopen("teken.log", "w");
+ if (df != NULL)
+ setvbuf(df, NULL, _IOLBF, BUFSIZ);
+#endif /* !(__FreeBSD__ && _KERNEL) */
+
+ t->t_funcs = tf;
+ t->t_softc = softc;
+
+ t->t_nextstate = teken_state_init;
+
+ t->t_defattr.ta_format = 0;
+ t->t_defattr.ta_fgcolor = TC_WHITE;
+ t->t_defattr.ta_bgcolor = TC_BLACK;
+ teken_subr_do_reset(t);
+
+#ifdef TEKEN_UTF8
+ t->t_utf8_left = 0;
+#endif /* TEKEN_UTF8 */
+
+ teken_set_winsize(t, &tp);
+}
+
+static void
+teken_input_char(teken_t *t, teken_char_t c)
+{
+
+ switch (c) {
+ case '\0':
+ break;
+ case '\a':
+ teken_subr_bell(t);
+ break;
+ case '\b':
+ teken_subr_backspace(t);
+ break;
+ case '\n':
+ case '\x0B':
+ teken_subr_newline(t);
+ break;
+ case '\r':
+ teken_subr_carriage_return(t);
+ break;
+ case '\t':
+ teken_subr_horizontal_tab(t);
+ break;
+ default:
+ t->t_nextstate(t, c);
+ break;
+ }
+
+ /* Post-processing assertions. */
+ teken_assert(t->t_cursor.tp_row >= t->t_originreg.ts_begin);
+ teken_assert(t->t_cursor.tp_row < t->t_originreg.ts_end);
+ teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
+ teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
+ teken_assert(t->t_saved_cursor.tp_row < t->t_winsize.tp_row);
+ teken_assert(t->t_saved_cursor.tp_col < t->t_winsize.tp_col);
+ teken_assert(t->t_scrollreg.ts_end <= t->t_winsize.tp_row);
+ teken_assert(t->t_scrollreg.ts_begin < t->t_scrollreg.ts_end);
+ /* Origin region has to be window size or the same as scrollreg. */
+ teken_assert((t->t_originreg.ts_begin == t->t_scrollreg.ts_begin &&
+ t->t_originreg.ts_end == t->t_scrollreg.ts_end) ||
+ (t->t_originreg.ts_begin == 0 &&
+ t->t_originreg.ts_end == t->t_winsize.tp_row));
+}
+
+static void
+teken_input_byte(teken_t *t, unsigned char c)
+{
+
+#ifdef TEKEN_UTF8
+ /*
+ * UTF-8 handling.
+ */
+ if ((c & 0x80) == 0x00) {
+ /* One-byte sequence. */
+ t->t_utf8_left = 0;
+ teken_input_char(t, c);
+ } else if ((c & 0xe0) == 0xc0) {
+ /* Two-byte sequence. */
+ t->t_utf8_left = 1;
+ t->t_utf8_partial = c & 0x1f;
+ } else if ((c & 0xf0) == 0xe0) {
+ /* Three-byte sequence. */
+ t->t_utf8_left = 2;
+ t->t_utf8_partial = c & 0x0f;
+ } else if ((c & 0xf8) == 0xf0) {
+ /* Four-byte sequence. */
+ t->t_utf8_left = 3;
+ t->t_utf8_partial = c & 0x07;
+ } else if ((c & 0xc0) == 0x80) {
+ if (t->t_utf8_left == 0)
+ return;
+ t->t_utf8_left--;
+ t->t_utf8_partial = (t->t_utf8_partial << 6) | (c & 0x3f);
+ if (t->t_utf8_left == 0) {
+ teken_printf("Got UTF-8 char %u\n", t->t_utf8_partial);
+ teken_input_char(t, t->t_utf8_partial);
+ }
+ }
+#else /* !TEKEN_UTF8 */
+ teken_input_char(t, c);
+#endif /* TEKEN_UTF8 */
+}
+
+void
+teken_input(teken_t *t, const void *buf, size_t len)
+{
+ const char *c = buf;
+
+ while (len-- > 0)
+ teken_input_byte(t, *c++);
+}
+
+void
+teken_set_cursor(teken_t *t, const teken_pos_t *p)
+{
+
+ /* XXX: bounds checking with originreg! */
+ teken_assert(p->tp_row < t->t_winsize.tp_row);
+ teken_assert(p->tp_col < t->t_winsize.tp_col);
+
+ t->t_cursor = *p;
+}
+
+void
+teken_set_defattr(teken_t *t, const teken_attr_t *a)
+{
+
+ t->t_curattr = t->t_saved_curattr = t->t_defattr = *a;
+}
+
+void
+teken_set_winsize(teken_t *t, const teken_pos_t *p)
+{
+
+ teken_assert(p->tp_col <= T_NUMCOL);
+
+ t->t_winsize = *p;
+ /* XXX: bounds checking with cursor/etc! */
+ t->t_scrollreg.ts_begin = 0;
+ t->t_scrollreg.ts_end = t->t_winsize.tp_row;
+ t->t_originreg = t->t_scrollreg;
+}
+
+/*
+ * State machine.
+ */
+
+static void
+teken_state_switch(teken_t *t, teken_state_t *s)
+{
+
+ t->t_nextstate = s;
+ t->t_curnum = 0;
+ t->t_stateflags |= TS_FIRSTDIGIT;
+}
+
+static int
+teken_state_numbers(teken_t *t, teken_char_t c)
+{
+
+ teken_assert(t->t_curnum < T_NUMSIZE);
+
+ if (c >= '0' && c <= '9') {
+ /*
+ * Don't do math with the default value of 1 when a
+ * custom number is inserted.
+ */
+ if (t->t_stateflags & TS_FIRSTDIGIT) {
+ t->t_stateflags &= ~TS_FIRSTDIGIT;
+ t->t_nums[t->t_curnum] = 0;
+ } else {
+ t->t_nums[t->t_curnum] *= 10;
+ }
+
+ t->t_nums[t->t_curnum] += c - '0';
+ return (1);
+ } else if (c == ';') {
+ if (t->t_stateflags & TS_FIRSTDIGIT)
+ t->t_nums[t->t_curnum] = 0;
+
+ /* Only allow a limited set of arguments. */
+ if (++t->t_curnum == T_NUMSIZE) {
+ teken_state_switch(t, teken_state_init);
+ return (1);
+ }
+
+ t->t_stateflags |= TS_FIRSTDIGIT;
+ return (1);
+ } else {
+ if (t->t_stateflags & TS_FIRSTDIGIT && t->t_curnum > 0) {
+ /* Finish off the last empty argument. */
+ t->t_nums[t->t_curnum] = 0;
+ t->t_curnum++;
+ } else if ((t->t_stateflags & TS_FIRSTDIGIT) == 0) {
+ /* Also count the last argument. */
+ t->t_curnum++;
+ }
+ }
+
+ return (0);
+}
+
+#include "teken_state.h"
diff --git a/sys/dev/syscons/teken/teken.h b/sys/dev/syscons/teken/teken.h
new file mode 100644
index 0000000..ef107ca
--- /dev/null
+++ b/sys/dev/syscons/teken/teken.h
@@ -0,0 +1,168 @@
+/*-
+ * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _TEKEN_H_
+#define _TEKEN_H_
+
+/*
+ * libteken: terminal emulation library.
+ *
+ * This library converts an UTF-8 stream of bytes to terminal drawing
+ * commands. It implements commands similar to xterm-color.
+ */
+
+#if 0
+/*
+ * XXX: Disable UTF-8 support for now. It requires UTF-8 keyboard input
+ * and rendering, which we do not yet support.
+ */
+#define TEKEN_UTF8
+#endif
+
+#ifdef TEKEN_UTF8
+typedef uint32_t teken_char_t;
+#else /* !TEKEN_UTF8 */
+typedef unsigned char teken_char_t;
+#endif /* TEKEN_UTF8 */
+typedef unsigned short teken_unit_t;
+typedef unsigned char teken_format_t;
+#define TF_BOLD 0x01
+#define TF_UNDERLINE 0x02
+#define TF_BLINK 0x04
+typedef unsigned char teken_color_t;
+#define TC_BLACK 0
+#define TC_RED 1
+#define TC_GREEN 2
+#define TC_BROWN 3
+#define TC_BLUE 4
+#define TC_MAGENTA 5
+#define TC_CYAN 6
+#define TC_WHITE 7
+#define TC_NCOLORS 8
+
+typedef struct {
+ teken_unit_t tp_row;
+ teken_unit_t tp_col;
+} teken_pos_t;
+typedef struct {
+ teken_pos_t tr_begin;
+ teken_pos_t tr_end;
+} teken_rect_t;
+typedef struct {
+ teken_format_t ta_format;
+ teken_color_t ta_fgcolor;
+ teken_color_t ta_bgcolor;
+} teken_attr_t;
+typedef struct {
+ teken_unit_t ts_begin;
+ teken_unit_t ts_end;
+} teken_span_t;
+
+typedef struct __teken teken_t;
+
+typedef void teken_state_t(teken_t *, teken_char_t);
+
+/*
+ * Drawing routines supplied by the user.
+ */
+
+typedef void tf_bell_t(void *);
+typedef void tf_cursor_t(void *, const teken_pos_t *);
+typedef void tf_putchar_t(void *, const teken_pos_t *, teken_char_t,
+ const teken_attr_t *);
+typedef void tf_fill_t(void *, const teken_rect_t *, teken_char_t,
+ const teken_attr_t *);
+typedef void tf_copy_t(void *, const teken_rect_t *, const teken_pos_t *);
+typedef void tf_param_t(void *, int, int);
+#define TP_SHOWCURSOR 0
+#define TP_CURSORKEYS 1
+#define TP_KEYPADAPP 2
+#define TP_AUTOREPEAT 3
+#define TP_SWITCHVT 4
+#define TP_132COLS 5
+typedef void tf_respond_t(void *, const void *, size_t);
+
+typedef struct {
+ tf_bell_t *tf_bell;
+ tf_cursor_t *tf_cursor;
+ tf_putchar_t *tf_putchar;
+ tf_fill_t *tf_fill;
+ tf_copy_t *tf_copy;
+ tf_param_t *tf_param;
+ tf_respond_t *tf_respond;
+} teken_funcs_t;
+
+/*
+ * Terminal state.
+ */
+
+struct __teken {
+ const teken_funcs_t *t_funcs;
+ void *t_softc;
+
+ teken_state_t *t_nextstate;
+ unsigned int t_stateflags;
+
+#define T_NUMSIZE 8
+ unsigned int t_nums[T_NUMSIZE];
+ unsigned int t_curnum;
+
+ teken_pos_t t_cursor;
+ teken_attr_t t_curattr;
+ teken_pos_t t_saved_cursor;
+ teken_attr_t t_saved_curattr;
+
+ teken_attr_t t_defattr;
+ teken_pos_t t_winsize;
+
+ /* For DECSTBM. */
+ teken_span_t t_scrollreg;
+ /* For DECOM. */
+ teken_span_t t_originreg;
+
+#define T_NUMCOL 160
+ unsigned int t_tabstops[T_NUMCOL / (sizeof(unsigned int) * 8)];
+
+#ifdef TEKEN_UTF8
+ unsigned int t_utf8_left;
+ teken_char_t t_utf8_partial;
+#endif /* TEKEN_UTF8 */
+};
+
+/* Initialize teken structure. */
+void teken_init(teken_t *, const teken_funcs_t *, void *);
+
+/* Deliver character input. */
+void teken_input(teken_t *, const void *, size_t);
+
+/* Set teken attributes. */
+void teken_set_cursor(teken_t *, const teken_pos_t *);
+void teken_set_defattr(teken_t *, const teken_attr_t *);
+void teken_set_winsize(teken_t *, const teken_pos_t *);
+
+#endif /* !_TEKEN_H_ */
diff --git a/sys/dev/syscons/teken/teken_demo.c b/sys/dev/syscons/teken/teken_demo.c
new file mode 100644
index 0000000..7d01f9b
--- /dev/null
+++ b/sys/dev/syscons/teken/teken_demo.c
@@ -0,0 +1,336 @@
+/*-
+ * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/ioctl.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <ncurses.h>
+#if defined(__FreeBSD__)
+#include <libutil.h>
+#elif defined(__linux__)
+#include <pty.h>
+#else
+#include <util.h>
+#endif
+
+#include "teken.h"
+
+static tf_bell_t test_bell;
+static tf_cursor_t test_cursor;
+static tf_putchar_t test_putchar;
+static tf_fill_t test_fill;
+static tf_copy_t test_copy;
+static tf_param_t test_param;
+static tf_respond_t test_respond;
+
+static teken_funcs_t tf = {
+ .tf_bell = test_bell,
+ .tf_cursor = test_cursor,
+ .tf_putchar = test_putchar,
+ .tf_fill = test_fill,
+ .tf_copy = test_copy,
+ .tf_param = test_param,
+ .tf_respond = test_respond,
+};
+
+struct pixel {
+ teken_char_t c;
+ teken_attr_t a;
+};
+
+#define NCOLS 80
+#define NROWS 24
+struct pixel buffer[NCOLS][NROWS];
+
+static int ptfd;
+
+static void
+printchar(const teken_pos_t *p)
+{
+ int y, x, attr = 0;
+ struct pixel *px, pt;
+
+ assert(p->tp_row < NROWS);
+ assert(p->tp_col < NCOLS);
+
+ getyx(stdscr, y, x);
+
+ px = &buffer[p->tp_col][p->tp_row];
+
+ if (px->c >= 0x80) {
+ /* Mark UTF-8 chars (we don't support it). */
+ px = &pt;
+ px->c = '?';
+ px->a.ta_format = TF_BOLD;
+ px->a.ta_fgcolor = TC_BROWN;
+ px->a.ta_bgcolor = TC_RED;
+ }
+
+ if (px->a.ta_format & TF_BOLD)
+ attr |= A_BOLD;
+ if (px->a.ta_format & TF_UNDERLINE)
+ attr |= A_UNDERLINE;
+ if (px->a.ta_format & TF_BLINK)
+ attr |= A_BLINK;
+
+ bkgdset(attr | COLOR_PAIR(px->a.ta_fgcolor + 8 * px->a.ta_bgcolor + 1));
+ mvaddch(p->tp_row, p->tp_col, px->c);
+
+ move(y, x);
+}
+
+static void
+test_bell(void *s __unused)
+{
+
+ beep();
+}
+
+static void
+test_cursor(void *s __unused, const teken_pos_t *p)
+{
+
+ move(p->tp_row, p->tp_col);
+}
+
+static void
+test_putchar(void *s __unused, const teken_pos_t *p, teken_char_t c,
+ const teken_attr_t *a)
+{
+
+ buffer[p->tp_col][p->tp_row].c = c;
+ buffer[p->tp_col][p->tp_row].a = *a;
+ printchar(p);
+}
+
+static void
+test_fill(void *s, const teken_rect_t *r, teken_char_t c,
+ const teken_attr_t *a)
+{
+ teken_pos_t p;
+
+ /* Braindead implementation of fill() - just call putchar(). */
+ for (p.tp_row = r->tr_begin.tp_row; p.tp_row < r->tr_end.tp_row; p.tp_row++)
+ for (p.tp_col = r->tr_begin.tp_col; p.tp_col < r->tr_end.tp_col; p.tp_col++)
+ test_putchar(s, &p, c, a);
+}
+
+static void
+test_copy(void *s __unused, const teken_rect_t *r, const teken_pos_t *p)
+{
+ int nrow, ncol, x, y; /* Has to be signed - >= 0 comparison */
+ teken_pos_t d;
+
+ /*
+ * Copying is a little tricky. We must make sure we do it in
+ * correct order, to make sure we don't overwrite our own data.
+ */
+
+ nrow = r->tr_end.tp_row - r->tr_begin.tp_row;
+ ncol = r->tr_end.tp_col - r->tr_begin.tp_col;
+
+ if (p->tp_row < r->tr_begin.tp_row) {
+ /* Copy from top to bottom. */
+ if (p->tp_col < r->tr_begin.tp_col) {
+ /* Copy from left to right. */
+ for (y = 0; y < nrow; y++) {
+ d.tp_row = p->tp_row + y;
+ for (x = 0; x < ncol; x++) {
+ d.tp_col = p->tp_col + x;
+ buffer[d.tp_col][d.tp_row] =
+ buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y];
+ printchar(&d);
+ }
+ }
+ } else {
+ /* Copy from right to left. */
+ for (y = 0; y < nrow; y++) {
+ d.tp_row = p->tp_row + y;
+ for (x = ncol - 1; x >= 0; x--) {
+ d.tp_col = p->tp_col + x;
+ buffer[d.tp_col][d.tp_row] =
+ buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y];
+ printchar(&d);
+ }
+ }
+ }
+ } else {
+ /* Copy from bottom to top. */
+ if (p->tp_col < r->tr_begin.tp_col) {
+ /* Copy from left to right. */
+ for (y = nrow - 1; y >= 0; y--) {
+ d.tp_row = p->tp_row + y;
+ for (x = 0; x < ncol; x++) {
+ d.tp_col = p->tp_col + x;
+ buffer[d.tp_col][d.tp_row] =
+ buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y];
+ printchar(&d);
+ }
+ }
+ } else {
+ /* Copy from right to left. */
+ for (y = nrow - 1; y >= 0; y--) {
+ d.tp_row = p->tp_row + y;
+ for (x = ncol - 1; x >= 0; x--) {
+ d.tp_col = p->tp_col + x;
+ buffer[d.tp_col][d.tp_row] =
+ buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y];
+ printchar(&d);
+ }
+ }
+ }
+ }
+}
+
+static void
+test_param(void *s __unused, int cmd, int value)
+{
+
+ switch (cmd) {
+ case TP_SHOWCURSOR:
+ curs_set(value);
+ break;
+ case TP_KEYPADAPP:
+ keypad(stdscr, value ? TRUE : FALSE);
+ break;
+ }
+}
+
+static void
+test_respond(void *s __unused, const void *buf, size_t len)
+{
+
+ write(ptfd, buf, len);
+}
+
+static void
+redraw_border(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < NROWS; i++)
+ mvaddch(i, NCOLS, '|');
+ for (i = 0; i < NCOLS; i++)
+ mvaddch(NROWS, i, '-');
+
+ mvaddch(NROWS, NCOLS, '+');
+}
+
+static void
+redraw_all(void)
+{
+ teken_pos_t tp;
+
+ for (tp.tp_row = 0; tp.tp_row < NROWS; tp.tp_row++)
+ for (tp.tp_col = 0; tp.tp_col < NCOLS; tp.tp_col++)
+ printchar(&tp);
+
+ redraw_border();
+}
+
+int
+main(int argc __unused, char *argv[] __unused)
+{
+ struct winsize ws;
+ teken_t t;
+ teken_pos_t tp;
+ fd_set rfds;
+ char b[256];
+ ssize_t bl;
+ const int ccolors[8] = { COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE };
+ int i, j;
+
+ tp.tp_row = ws.ws_row = NROWS;
+ tp.tp_col = ws.ws_col = NCOLS;
+
+ switch (forkpty(&ptfd, NULL, NULL, &ws)) {
+ case -1:
+ perror("forkpty");
+ exit(1);
+ case 0:
+ setenv("TERM", "xterm-color", 1);
+ setenv("LC_CTYPE", "UTF-8", 0);
+ execlp("zsh", "-zsh", NULL);
+ execlp("bash", "-bash", NULL);
+ execlp("sh", "-sh", NULL);
+ _exit(1);
+ }
+
+ teken_init(&t, &tf, NULL);
+ teken_set_winsize(&t, &tp);
+
+ initscr();
+ raw();
+ start_color();
+ for (i = 0; i < 8; i++)
+ for (j = 0; j < 8; j++)
+ init_pair(i + 8 * j + 1, ccolors[i], ccolors[j]);
+
+ redraw_border();
+
+ FD_ZERO(&rfds);
+
+ for (;;) {
+ FD_SET(STDIN_FILENO, &rfds);
+ FD_SET(ptfd, &rfds);
+
+ if (select(ptfd + 1, &rfds, NULL, NULL, NULL) < 0) {
+ if (errno == EINTR) {
+ redraw_all();
+ refresh();
+ continue;
+ }
+ break;
+ }
+
+ if (FD_ISSET(STDIN_FILENO, &rfds)) {
+ bl = read(STDIN_FILENO, b, sizeof b);
+ if (bl <= 0)
+ break;
+ write(ptfd, b, bl);
+ }
+
+ if (FD_ISSET(ptfd, &rfds)) {
+ bl = read(ptfd, b, sizeof b);
+ if (bl <= 0)
+ break;
+ teken_input(&t, b, bl);
+ refresh();
+ }
+ }
+
+ endwin();
+
+ return (0);
+}
diff --git a/sys/dev/syscons/teken/teken_stress.c b/sys/dev/syscons/teken/teken_stress.c
new file mode 100644
index 0000000..1b71647
--- /dev/null
+++ b/sys/dev/syscons/teken/teken_stress.c
@@ -0,0 +1,123 @@
+/*-
+ * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "teken.h"
+
+static tf_bell_t stress_bell;
+static tf_cursor_t stress_cursor;
+static tf_putchar_t stress_putchar;
+static tf_fill_t stress_fill;
+static tf_copy_t stress_copy;
+static tf_param_t stress_param;
+static tf_respond_t stress_respond;
+
+static teken_funcs_t tf = {
+ .tf_bell = stress_bell,
+ .tf_cursor = stress_cursor,
+ .tf_putchar = stress_putchar,
+ .tf_fill = stress_fill,
+ .tf_copy = stress_copy,
+ .tf_param = stress_param,
+ .tf_respond = stress_respond,
+};
+
+static void
+stress_bell(void *s __unused)
+{
+}
+
+static void
+stress_cursor(void *s __unused, const teken_pos_t *p __unused)
+{
+}
+
+static void
+stress_putchar(void *s __unused, const teken_pos_t *p __unused,
+ teken_char_t c __unused, const teken_attr_t *a __unused)
+{
+}
+
+static void
+stress_fill(void *s __unused, const teken_rect_t *r __unused,
+ teken_char_t c __unused, const teken_attr_t *a __unused)
+{
+}
+
+static void
+stress_copy(void *s __unused, const teken_rect_t *r __unused,
+ const teken_pos_t *p __unused)
+{
+}
+
+static void
+stress_param(void *s __unused, int cmd __unused, int value __unused)
+{
+}
+
+static void
+stress_respond(void *s __unused, const void *buf __unused, size_t len __unused)
+{
+}
+
+int
+main(int argc __unused, char *argv[] __unused)
+{
+ teken_t t;
+ int rnd;
+ unsigned int iteration = 0;
+ char buf[2048];
+
+ rnd = open("/dev/urandom", O_RDONLY);
+ if (rnd < 0) {
+ perror("/dev/urandom");
+ exit(1);
+ }
+
+ teken_init(&t, &tf, NULL);
+
+ for (;;) {
+ if (read(rnd, buf, sizeof buf) != sizeof buf) {
+ perror("read");
+ exit(1);
+ }
+
+ teken_input(&t, buf, sizeof buf);
+
+ iteration++;
+ if ((iteration % 10000) == 0)
+ printf("Processed %u frames\n", iteration);
+ }
+}
diff --git a/sys/dev/syscons/teken/teken_subr.h b/sys/dev/syscons/teken/teken_subr.h
new file mode 100644
index 0000000..de79cfa
--- /dev/null
+++ b/sys/dev/syscons/teken/teken_subr.h
@@ -0,0 +1,1107 @@
+/*-
+ * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+static void teken_subr_cursor_up(teken_t *, unsigned int);
+static void teken_subr_erase_line(teken_t *, unsigned int);
+static void teken_subr_regular_character(teken_t *, teken_char_t);
+static void teken_subr_reset_to_initial_state(teken_t *);
+
+static inline int
+teken_tab_isset(teken_t *t, unsigned int col)
+{
+ unsigned int b, o;
+
+ teken_assert(col <= T_NUMCOL);
+
+ b = col / (sizeof(unsigned int) * 8);
+ o = col % (sizeof(unsigned int) * 8);
+
+ return (t->t_tabstops[b] & (1 << o));
+}
+
+static inline void
+teken_tab_clear(teken_t *t, unsigned int col)
+{
+ unsigned int b, o;
+
+ teken_assert(col <= T_NUMCOL);
+
+ b = col / (sizeof(unsigned int) * 8);
+ o = col % (sizeof(unsigned int) * 8);
+
+ t->t_tabstops[b] &= ~(1 << o);
+}
+
+static inline void
+teken_tab_set(teken_t *t, unsigned int col)
+{
+ unsigned int b, o;
+
+ teken_assert(col <= T_NUMCOL);
+
+ b = col / (sizeof(unsigned int) * 8);
+ o = col % (sizeof(unsigned int) * 8);
+
+ t->t_tabstops[b] |= 1 << o;
+}
+
+static void
+teken_tab_default(teken_t *t)
+{
+ unsigned int i;
+
+ memset(&t->t_tabstops, 0, T_NUMCOL / 8);
+
+ for (i = 8; i < T_NUMCOL; i += 8)
+ teken_tab_set(t, i);
+}
+
+static void
+teken_subr_do_scroll(teken_t *t, int amount)
+{
+ teken_rect_t tr;
+ teken_pos_t tp;
+
+ teken_assert(t->t_cursor.tp_row <= t->t_winsize.tp_row);
+ teken_assert(t->t_scrollreg.ts_end <= t->t_winsize.tp_row);
+ teken_assert(amount != 0);
+
+ /* Copy existing data 1 line up. */
+ if (amount > 0) {
+ /* Scroll down. */
+
+ /* Copy existing data up. */
+ if (t->t_scrollreg.ts_begin + amount < t->t_scrollreg.ts_end) {
+ tr.tr_begin.tp_row = t->t_scrollreg.ts_begin + amount;
+ tr.tr_begin.tp_col = 0;
+ tr.tr_end.tp_row = t->t_scrollreg.ts_end;
+ tr.tr_end.tp_col = t->t_winsize.tp_col;
+ tp.tp_row = t->t_scrollreg.ts_begin;
+ tp.tp_col = 0;
+ teken_funcs_copy(t, &tr, &tp);
+
+ tr.tr_begin.tp_row = t->t_scrollreg.ts_end - amount;
+ } else {
+ tr.tr_begin.tp_row = t->t_scrollreg.ts_begin;
+ }
+
+ /* Clear the last lines. */
+ tr.tr_begin.tp_col = 0;
+ tr.tr_end.tp_row = t->t_scrollreg.ts_end;
+ tr.tr_end.tp_col = t->t_winsize.tp_col;
+ teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
+ } else {
+ /* Scroll up. */
+ amount = -amount;
+
+ /* Copy existing data down. */
+ if (t->t_scrollreg.ts_begin + amount < t->t_scrollreg.ts_end) {
+ tr.tr_begin.tp_row = t->t_scrollreg.ts_begin;
+ tr.tr_begin.tp_col = 0;
+ tr.tr_end.tp_row = t->t_scrollreg.ts_end - amount;
+ tr.tr_end.tp_col = t->t_winsize.tp_col;
+ tp.tp_row = t->t_scrollreg.ts_begin + amount;
+ tp.tp_col = 0;
+ teken_funcs_copy(t, &tr, &tp);
+
+ tr.tr_end.tp_row = t->t_scrollreg.ts_begin + amount;
+ } else {
+ tr.tr_end.tp_row = t->t_scrollreg.ts_end;
+ }
+
+ /* Clear the first lines. */
+ tr.tr_begin.tp_row = t->t_scrollreg.ts_begin;
+ tr.tr_begin.tp_col = 0;
+ tr.tr_end.tp_col = t->t_winsize.tp_col;
+ teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
+ }
+}
+
+static ssize_t
+teken_subr_do_cpr(teken_t *t, unsigned int cmd, char response[16])
+{
+
+ switch (cmd) {
+ case 5: /* Operating status. */
+ strcpy(response, "0n");
+ return (2);
+ case 6: { /* Cursor position. */
+ int len;
+
+ len = snprintf(response, 16, "%u;%uR",
+ (t->t_cursor.tp_row - t->t_originreg.ts_begin) + 1,
+ t->t_cursor.tp_col + 1);
+
+ if (len >= 16)
+ return (-1);
+ return (len);
+ }
+ case 15: /* Printer status. */
+ strcpy(response, "13n");
+ return (3);
+ case 25: /* UDK status. */
+ strcpy(response, "20n");
+ return (3);
+ case 26: /* Keyboard status. */
+ strcpy(response, "27;1n");
+ return (5);
+ default:
+ teken_printf("Unknown DSR\n");
+ return (-1);
+ }
+}
+
+static void
+teken_subr_alignment_test(teken_t *t)
+{
+ teken_rect_t tr;
+
+ t->t_scrollreg.ts_begin = 0;
+ t->t_scrollreg.ts_end = t->t_winsize.tp_row;
+
+ t->t_cursor.tp_row = t->t_cursor.tp_col = 0;
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+
+ tr.tr_begin.tp_row = 0;
+ tr.tr_begin.tp_col = 0;
+ tr.tr_end = t->t_winsize;
+ teken_funcs_fill(t, &tr, 'E', &t->t_defattr);
+}
+
+static void
+teken_subr_backspace(teken_t *t)
+{
+
+ if (t->t_cursor.tp_col == 0)
+ return;
+
+ t->t_cursor.tp_col--;
+ t->t_stateflags &= ~TS_WRAPPED;
+
+ teken_funcs_cursor(t);
+}
+
+static void
+teken_subr_bell(teken_t *t)
+{
+
+ teken_funcs_bell(t);
+}
+
+static void
+teken_subr_carriage_return(teken_t *t)
+{
+
+ t->t_cursor.tp_col = 0;
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+}
+
+static void
+teken_subr_cursor_backward(teken_t *t, unsigned int ncols)
+{
+
+ if (ncols > t->t_cursor.tp_col)
+ t->t_cursor.tp_col = 0;
+ else
+ t->t_cursor.tp_col -= ncols;
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+}
+
+static void
+teken_subr_cursor_backward_tabulation(teken_t *t, unsigned int ntabs)
+{
+
+ do {
+ /* Stop when we've reached the beginning of the line. */
+ if (t->t_cursor.tp_col == 0)
+ break;
+
+ t->t_cursor.tp_col--;
+
+ /* Tab marker set. */
+ if (teken_tab_isset(t, t->t_cursor.tp_col))
+ ntabs--;
+ } while (ntabs > 0);
+}
+
+static void
+teken_subr_cursor_down(teken_t *t, unsigned int nrows)
+{
+
+ teken_assert(t->t_cursor.tp_row < t->t_scrollreg.ts_end);
+ if (t->t_cursor.tp_row + nrows >= t->t_scrollreg.ts_end)
+ t->t_cursor.tp_row = t->t_scrollreg.ts_end - 1;
+ else
+ t->t_cursor.tp_row += nrows;
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+}
+
+static void
+teken_subr_cursor_forward(teken_t *t, unsigned int ncols)
+{
+
+ if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col)
+ t->t_cursor.tp_col = t->t_winsize.tp_col - 1;
+ else
+ t->t_cursor.tp_col += ncols;
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+}
+
+static void
+teken_subr_cursor_forward_tabulation(teken_t *t, unsigned int ntabs)
+{
+
+ do {
+ /* Stop when we've reached the end of the line. */
+ if (t->t_cursor.tp_col == t->t_winsize.tp_col - 1)
+ break;
+
+ t->t_cursor.tp_col++;
+
+ /* Tab marker set. */
+ if (teken_tab_isset(t, t->t_cursor.tp_col))
+ ntabs--;
+ } while (ntabs > 0);
+}
+
+static void
+teken_subr_cursor_next_line(teken_t *t, unsigned int ncols)
+{
+
+ t->t_cursor.tp_col = 0;
+ teken_subr_cursor_down(t, ncols);
+}
+
+static void
+teken_subr_cursor_position(teken_t *t, unsigned int row, unsigned int col)
+{
+
+ t->t_cursor.tp_row = t->t_originreg.ts_begin + row - 1;
+ if (row >= t->t_originreg.ts_end)
+ t->t_cursor.tp_row = t->t_originreg.ts_end - 1;
+
+ t->t_cursor.tp_col = col - 1;
+ if (t->t_cursor.tp_col >= t->t_winsize.tp_col)
+ t->t_cursor.tp_col = t->t_winsize.tp_col - 1;
+
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+}
+
+static void
+teken_subr_cursor_position_report(teken_t *t, unsigned int cmd)
+{
+ char response[18] = "\x1B[";
+ ssize_t len;
+
+ len = teken_subr_do_cpr(t, cmd, response + 2);
+ if (len < 0)
+ return;
+
+ teken_funcs_respond(t, response, len + 2);
+}
+
+static void
+teken_subr_cursor_previous_line(teken_t *t, unsigned int ncols)
+{
+
+ t->t_cursor.tp_col = 0;
+ teken_subr_cursor_up(t, ncols);
+}
+
+static void
+teken_subr_cursor_up(teken_t *t, unsigned int nrows)
+{
+
+ if (t->t_scrollreg.ts_begin + nrows >= t->t_cursor.tp_row)
+ t->t_cursor.tp_row = t->t_scrollreg.ts_begin;
+ else
+ t->t_cursor.tp_row -= nrows;
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+}
+
+static void
+teken_subr_delete_character(teken_t *t, unsigned int ncols)
+{
+ teken_rect_t tr;
+
+ tr.tr_begin.tp_row = t->t_cursor.tp_row;
+ tr.tr_end.tp_row = t->t_cursor.tp_row + 1;
+ tr.tr_end.tp_col = t->t_winsize.tp_col;
+
+ if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col) {
+ tr.tr_begin.tp_col = t->t_cursor.tp_col;
+ } else {
+ /* Copy characters to the left. */
+ tr.tr_begin.tp_col = t->t_cursor.tp_col + ncols;
+ teken_funcs_copy(t, &tr, &t->t_cursor);
+
+ tr.tr_begin.tp_col = t->t_winsize.tp_col - ncols;
+ }
+
+ /* Blank trailing columns. */
+ teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
+}
+
+static void
+teken_subr_delete_line(teken_t *t, unsigned int nrows)
+{
+ teken_rect_t tr;
+
+ tr.tr_begin.tp_col = 0;
+ tr.tr_end.tp_row = t->t_scrollreg.ts_end;
+ tr.tr_end.tp_col = t->t_winsize.tp_col;
+
+ if (t->t_cursor.tp_row + nrows >= t->t_scrollreg.ts_end) {
+ tr.tr_begin.tp_row = t->t_cursor.tp_row;
+ } else {
+ teken_pos_t tp;
+
+ /* Copy rows up. */
+ tr.tr_begin.tp_row = t->t_cursor.tp_row + nrows;
+ tp.tp_row = t->t_cursor.tp_row;
+ tp.tp_col = 0;
+ teken_funcs_copy(t, &tr, &tp);
+
+ tr.tr_begin.tp_row = t->t_scrollreg.ts_end - nrows;
+ }
+
+ /* Blank trailing rows. */
+ teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
+}
+
+static void
+teken_subr_device_control_string(teken_t *t __unused)
+{
+
+ teken_printf("device control string???\n");
+}
+
+static void
+teken_subr_device_status_report(teken_t *t, unsigned int cmd)
+{
+ char response[19] = "\x1B[?";
+ ssize_t len;
+
+ len = teken_subr_do_cpr(t, cmd, response + 3);
+ if (len < 0)
+ return;
+
+ teken_funcs_respond(t, response, len + 3);
+}
+
+static void
+teken_subr_double_height_double_width_line_top(teken_t *t __unused)
+{
+
+ teken_printf("double height double width top\n");
+}
+
+static void
+teken_subr_double_height_double_width_line_bottom(teken_t *t __unused)
+{
+
+ teken_printf("double height double width bottom\n");
+}
+
+static void
+teken_subr_erase_character(teken_t *t, unsigned int ncols)
+{
+ teken_rect_t tr;
+
+ tr.tr_begin = t->t_cursor;
+ tr.tr_end.tp_row = t->t_cursor.tp_row + 1;
+
+ if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col)
+ tr.tr_end.tp_col = t->t_winsize.tp_col;
+ else
+ tr.tr_end.tp_col = t->t_cursor.tp_col + ncols;
+
+ teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
+}
+
+static void
+teken_subr_erase_display(teken_t *t, unsigned int mode)
+{
+ teken_rect_t r;
+
+ r.tr_begin.tp_col = 0;
+ r.tr_end.tp_col = t->t_winsize.tp_col;
+
+ switch (mode) {
+ case 1: /* Erase from the top to the cursor. */
+ teken_subr_erase_line(t, 1);
+
+ /* Erase lines above. */
+ if (t->t_cursor.tp_row == 0)
+ return;
+ r.tr_begin.tp_row = 0;
+ r.tr_end.tp_row = t->t_cursor.tp_row;
+ break;
+ case 2: /* Erase entire display. */
+ r.tr_begin.tp_row = 0;
+ r.tr_end.tp_row = t->t_winsize.tp_row;
+ break;
+ default: /* Erase from cursor to the bottom. */
+ teken_subr_erase_line(t, 0);
+
+ /* Erase lines below. */
+ if (t->t_cursor.tp_row == t->t_winsize.tp_row - 1)
+ return;
+ r.tr_begin.tp_row = t->t_cursor.tp_row + 1;
+ r.tr_end.tp_row = t->t_winsize.tp_row;
+ break;
+ }
+
+ teken_funcs_fill(t, &r, BLANK, &t->t_curattr);
+}
+
+static void
+teken_subr_erase_line(teken_t *t, unsigned int mode)
+{
+ teken_rect_t r;
+
+ r.tr_begin.tp_row = t->t_cursor.tp_row;
+ r.tr_end.tp_row = t->t_cursor.tp_row + 1;
+
+ switch (mode) {
+ case 1: /* Erase from the beginning of the line to the cursor. */
+ r.tr_begin.tp_col = 0;
+ r.tr_end.tp_col = t->t_cursor.tp_col + 1;
+ break;
+ case 2: /* Erase entire line. */
+ r.tr_begin.tp_col = 0;
+ r.tr_end.tp_col = t->t_winsize.tp_col;
+ break;
+ default: /* Erase from cursor to the end of the line. */
+ r.tr_begin.tp_col = t->t_cursor.tp_col;
+ r.tr_end.tp_col = t->t_winsize.tp_col;
+ break;
+ }
+
+ teken_funcs_fill(t, &r, BLANK, &t->t_curattr);
+}
+
+static void
+teken_subr_horizontal_position_absolute(teken_t *t, unsigned int col)
+{
+
+ t->t_cursor.tp_col = col - 1;
+ if (t->t_cursor.tp_col >= t->t_winsize.tp_col)
+ t->t_cursor.tp_col = t->t_winsize.tp_col - 1;
+
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+}
+
+static void
+teken_subr_horizontal_tab(teken_t *t)
+{
+ teken_rect_t tr;
+
+ tr.tr_begin = t->t_cursor;
+ teken_subr_cursor_forward_tabulation(t, 1);
+ tr.tr_end.tp_row = tr.tr_begin.tp_row + 1;
+ tr.tr_end.tp_col = t->t_cursor.tp_col;
+
+ /* Blank region that we skipped. */
+ if (tr.tr_end.tp_col > tr.tr_begin.tp_col)
+ teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
+}
+
+static void
+teken_subr_horizontal_tab_set(teken_t *t)
+{
+
+ teken_tab_set(t, t->t_cursor.tp_col);
+}
+
+static void
+teken_subr_index(teken_t *t)
+{
+
+ if (t->t_cursor.tp_row < t->t_scrollreg.ts_end - 1) {
+ t->t_cursor.tp_row++;
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+ } else {
+ teken_subr_do_scroll(t, 1);
+ }
+}
+
+static void
+teken_subr_insert_character(teken_t *t, unsigned int ncols)
+{
+ teken_rect_t tr;
+
+ tr.tr_begin = t->t_cursor;
+ tr.tr_end.tp_row = t->t_cursor.tp_row + 1;
+
+ if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col) {
+ tr.tr_end.tp_col = t->t_winsize.tp_col;
+ } else {
+ teken_pos_t tp;
+
+ /* Copy characters to the right. */
+ tr.tr_end.tp_col = t->t_winsize.tp_col - ncols;
+ tp.tp_row = t->t_cursor.tp_row;
+ tp.tp_col = t->t_cursor.tp_col + ncols;
+ teken_funcs_copy(t, &tr, &tp);
+
+ tr.tr_end.tp_col = t->t_cursor.tp_col + ncols;
+ }
+
+ /* Blank current location. */
+ teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
+}
+
+static void
+teken_subr_insert_line(teken_t *t, unsigned int nrows)
+{
+ teken_rect_t tr;
+
+ tr.tr_begin.tp_row = t->t_cursor.tp_row;
+ tr.tr_begin.tp_col = 0;
+ tr.tr_end.tp_col = t->t_winsize.tp_col;
+
+ if (t->t_cursor.tp_row + nrows >= t->t_scrollreg.ts_end) {
+ tr.tr_end.tp_row = t->t_scrollreg.ts_end;
+ } else {
+ teken_pos_t tp;
+
+ /* Copy lines down. */
+ tr.tr_end.tp_row = t->t_scrollreg.ts_end - nrows;
+ tp.tp_row = t->t_cursor.tp_row + nrows;
+ tp.tp_col = 0;
+ teken_funcs_copy(t, &tr, &tp);
+
+ tr.tr_end.tp_row = t->t_cursor.tp_row + nrows;
+ }
+
+ /* Blank current location. */
+ teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
+}
+
+static void
+teken_subr_keypad_application_mode(teken_t *t)
+{
+
+ teken_funcs_param(t, TP_KEYPADAPP, 1);
+}
+
+static void
+teken_subr_keypad_numeric_mode(teken_t *t)
+{
+
+ teken_funcs_param(t, TP_KEYPADAPP, 0);
+}
+
+static void
+teken_subr_newline(teken_t *t)
+{
+
+ t->t_cursor.tp_row++;
+
+ if (t->t_cursor.tp_row >= t->t_scrollreg.ts_end) {
+ teken_subr_do_scroll(t, 1);
+ t->t_cursor.tp_row = t->t_scrollreg.ts_end - 1;
+ }
+
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+}
+
+static void
+teken_subr_next_line(teken_t *t)
+{
+
+ t->t_cursor.tp_col = 0;
+ teken_subr_newline(t);
+}
+
+static void
+teken_subr_pan_down(teken_t *t, unsigned int nrows)
+{
+
+ teken_subr_do_scroll(t, (int)nrows);
+}
+
+static void
+teken_subr_pan_up(teken_t *t, unsigned int nrows)
+{
+
+ teken_subr_do_scroll(t, -(int)nrows);
+}
+
+static void
+teken_subr_primary_device_attributes(teken_t *t, unsigned int request)
+{
+
+ if (request == 0) {
+ const char response[] = "\x1B[?1;2c";
+
+ teken_funcs_respond(t, response, sizeof response - 1);
+ } else {
+ teken_printf("Unknown DA1\n");
+ }
+}
+
+static void
+teken_subr_do_putchar(teken_t *t, const teken_pos_t *tp, teken_char_t c,
+ int width)
+{
+
+ if (t->t_stateflags & TS_INSERT &&
+ tp->tp_col < t->t_winsize.tp_col - width) {
+ teken_rect_t ctr;
+ teken_pos_t ctp;
+
+ /* Insert mode. Move existing characters to the right. */
+ ctr.tr_begin = *tp;
+ ctr.tr_end.tp_row = tp->tp_row + 1;
+ ctr.tr_end.tp_col = t->t_winsize.tp_col - width;
+ ctp.tp_row = tp->tp_row;
+ ctp.tp_col = tp->tp_col + width;
+ teken_funcs_copy(t, &ctr, &ctp);
+ }
+
+ teken_funcs_putchar(t, tp, c, &t->t_curattr);
+}
+
+static void
+teken_subr_regular_character(teken_t *t, teken_char_t c)
+{
+ int width;
+
+ /* XXX: Don't process zero-width characters yet. */
+ width = teken_wcwidth(c);
+ if (width <= 0)
+ return;
+
+ if (t->t_cursor.tp_col == t->t_winsize.tp_col - 1 &&
+ (t->t_stateflags & (TS_WRAPPED|TS_AUTOWRAP)) ==
+ (TS_WRAPPED|TS_AUTOWRAP)) {
+ teken_pos_t tp;
+
+ /* Perform line wrapping. */
+
+ if (t->t_cursor.tp_row == t->t_scrollreg.ts_end - 1) {
+ /* Perform scrolling. */
+ teken_subr_do_scroll(t, 1);
+ tp.tp_row = t->t_scrollreg.ts_end - 1;
+ } else {
+ /* No scrolling needed. */
+ tp.tp_row = t->t_cursor.tp_row + 1;
+ if (tp.tp_row == t->t_winsize.tp_row) {
+ /*
+ * Corner case: regular character
+ * outside scrolling region, but at the
+ * bottom of the screen.
+ */
+ teken_subr_do_putchar(t, &t->t_cursor,
+ c, width);
+ return;
+ }
+ }
+
+ tp.tp_col = 0;
+ teken_subr_do_putchar(t, &tp, c, width);
+
+ t->t_cursor.tp_row = tp.tp_row;
+ t->t_cursor.tp_col = width;
+ t->t_stateflags &= ~TS_WRAPPED;
+ } else {
+ /* No line wrapping needed. */
+ teken_subr_do_putchar(t, &t->t_cursor, c, width);
+ t->t_cursor.tp_col += width;
+
+ if (t->t_cursor.tp_col >= t->t_winsize.tp_col) {
+ t->t_stateflags |= TS_WRAPPED;
+ t->t_cursor.tp_col = t->t_winsize.tp_col - 1;
+ } else {
+ t->t_stateflags &= ~TS_WRAPPED;
+ }
+ }
+
+ teken_funcs_cursor(t);
+}
+
+static void
+teken_subr_reset_dec_mode(teken_t *t, unsigned int cmd)
+{
+
+ switch (cmd) {
+ case 1: /* Cursor keys mode. */
+ teken_funcs_param(t, TP_CURSORKEYS, 0);
+ break;
+ case 2: /* DECANM: ANSI/VT52 mode. */
+ teken_printf("DECRST VT52\n");
+ break;
+ case 3: /* 132 column mode. */
+ teken_funcs_param(t, TP_132COLS, 0);
+ teken_subr_reset_to_initial_state(t);
+ break;
+ case 5: /* Inverse video. */
+ teken_printf("DECRST inverse video\n");
+ break;
+ case 6: /* Origin mode. */
+ t->t_stateflags &= ~TS_ORIGIN;
+ t->t_originreg.ts_begin = 0;
+ t->t_originreg.ts_end = t->t_winsize.tp_row;
+ t->t_cursor.tp_row = t->t_cursor.tp_col = 0;
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+ break;
+ case 7: /* Autowrap mode. */
+ t->t_stateflags &= ~TS_AUTOWRAP;
+ break;
+ case 8: /* Autorepeat mode. */
+ teken_funcs_param(t, TP_AUTOREPEAT, 0);
+ break;
+ case 25: /* Hide cursor. */
+ teken_funcs_param(t, TP_SHOWCURSOR, 0);
+ break;
+ case 40: /* Disallow 132 columns. */
+ teken_printf("DECRST allow 132\n");
+ break;
+ case 45: /* Disable reverse wraparound. */
+ teken_printf("DECRST reverse wraparound\n");
+ break;
+ case 47: /* Switch to alternate buffer. */
+ teken_printf("Switch to alternate buffer\n");
+ break;
+ default:
+ teken_printf("Unknown DECRST: %u\n", cmd);
+ }
+}
+
+static void
+teken_subr_reset_mode(teken_t *t, unsigned int cmd)
+{
+
+ switch (cmd) {
+ case 4:
+ t->t_stateflags &= ~TS_INSERT;
+ break;
+ default:
+ teken_printf("Unknown reset mode: %u\n", cmd);
+ }
+}
+
+static void
+teken_subr_do_reset(teken_t *t)
+{
+
+ t->t_curattr = t->t_saved_curattr = t->t_defattr;
+ t->t_cursor.tp_row = t->t_cursor.tp_col = 0;
+ t->t_saved_cursor = t->t_cursor;
+ t->t_stateflags = TS_AUTOWRAP;
+
+ teken_tab_default(t);
+}
+
+static void
+teken_subr_reset_to_initial_state(teken_t *t)
+{
+
+ teken_subr_do_reset(t);
+ teken_subr_erase_display(t, 2);
+ teken_funcs_cursor(t);
+}
+
+static void
+teken_subr_restore_cursor(teken_t *t)
+{
+
+ t->t_cursor = t->t_saved_cursor;
+ t->t_curattr = t->t_saved_curattr;
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+}
+
+static void
+teken_subr_reverse_index(teken_t *t)
+{
+
+ if (t->t_cursor.tp_row > t->t_scrollreg.ts_begin) {
+ t->t_cursor.tp_row--;
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+ } else {
+ teken_subr_do_scroll(t, -1);
+ }
+}
+
+static void
+teken_subr_save_cursor(teken_t *t)
+{
+
+ t->t_saved_cursor = t->t_cursor;
+ t->t_saved_curattr = t->t_curattr;
+}
+
+static void
+teken_subr_scs(teken_t *t __unused)
+{
+
+ teken_printf("scs???\n");
+}
+
+static void
+teken_subr_secondary_device_attributes(teken_t *t, unsigned int request)
+{
+
+ if (request == 0) {
+ const char response[] = "\x1B[>0;10;0c";
+ teken_funcs_respond(t, response, sizeof response - 1);
+ } else {
+ teken_printf("Unknown DA2\n");
+ }
+}
+
+static void
+teken_subr_set_dec_mode(teken_t *t, unsigned int cmd)
+{
+
+ switch (cmd) {
+ case 1: /* Cursor keys mode. */
+ teken_funcs_param(t, TP_CURSORKEYS, 1);
+ break;
+ case 2: /* DECANM: ANSI/VT52 mode. */
+ teken_printf("DECSET VT52\n");
+ break;
+ case 3: /* 132 column mode. */
+ teken_funcs_param(t, TP_132COLS, 1);
+ teken_subr_reset_to_initial_state(t);
+ break;
+ case 5: /* Inverse video. */
+ teken_printf("DECSET inverse video\n");
+ break;
+ case 6: /* Origin mode. */
+ t->t_stateflags |= TS_ORIGIN;
+ t->t_originreg = t->t_scrollreg;
+ t->t_cursor.tp_row = t->t_scrollreg.ts_begin;
+ t->t_cursor.tp_col = 0;
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+ break;
+ case 7: /* Autowrap mode. */
+ t->t_stateflags |= TS_AUTOWRAP;
+ break;
+ case 8: /* Autorepeat mode. */
+ teken_funcs_param(t, TP_AUTOREPEAT, 1);
+ break;
+ case 25: /* Display cursor. */
+ teken_funcs_param(t, TP_SHOWCURSOR, 1);
+ break;
+ case 40: /* Allow 132 columns. */
+ teken_printf("DECSET allow 132\n");
+ break;
+ case 45: /* Enable reverse wraparound. */
+ teken_printf("DECSET reverse wraparound\n");
+ break;
+ case 47: /* Switch to alternate buffer. */
+ teken_printf("Switch away from alternate buffer\n");
+ break;
+ default:
+ teken_printf("Unknown DECSET: %u\n", cmd);
+ }
+}
+
+static void
+teken_subr_set_mode(teken_t *t, unsigned int cmd)
+{
+
+ switch (cmd) {
+ case 4:
+ teken_printf("Insert mode\n");
+ t->t_stateflags |= TS_INSERT;
+ break;
+ default:
+ teken_printf("Unknown set mode: %u\n", cmd);
+ }
+}
+
+static void
+teken_subr_set_graphic_rendition(teken_t *t, unsigned int ncmds,
+ unsigned int cmds[])
+{
+ unsigned int i, n;
+
+ /* No attributes means reset. */
+ if (ncmds == 0) {
+ t->t_curattr = t->t_defattr;
+ return;
+ }
+
+ for (i = 0; i < ncmds; i++) {
+ n = cmds[i];
+
+ switch (n) {
+ case 0: /* Reset. */
+ t->t_curattr = t->t_defattr;
+ break;
+ case 1: /* Bold. */
+ t->t_curattr.ta_format |= TF_BOLD;
+ break;
+ case 4: /* Underline. */
+ t->t_curattr.ta_format |= TF_UNDERLINE;
+ break;
+ case 5: /* Blink. */
+ t->t_curattr.ta_format |= TF_BLINK;
+ break;
+ case 7: /* Reverse. */
+ t->t_curattr.ta_format |= TF_REVERSE;
+ break;
+ case 22: /* Remove bold. */
+ t->t_curattr.ta_format &= ~TF_BOLD;
+ break;
+ case 24: /* Remove underline. */
+ t->t_curattr.ta_format &= ~TF_UNDERLINE;
+ break;
+ case 25: /* Remove blink. */
+ t->t_curattr.ta_format &= ~TF_BLINK;
+ break;
+ case 27: /* Remove reverse. */
+ t->t_curattr.ta_format &= ~TF_REVERSE;
+ break;
+ case 30: /* Set foreground color: black */
+ case 31: /* Set foreground color: red */
+ case 32: /* Set foreground color: green */
+ case 33: /* Set foreground color: brown */
+ case 34: /* Set foreground color: blue */
+ case 35: /* Set foreground color: magenta */
+ case 36: /* Set foreground color: cyan */
+ case 37: /* Set foreground color: white */
+ t->t_curattr.ta_fgcolor = n - 30;
+ break;
+ case 39: /* Set default foreground color. */
+ t->t_curattr.ta_fgcolor = t->t_defattr.ta_fgcolor;
+ break;
+ case 40: /* Set background color: black */
+ case 41: /* Set background color: red */
+ case 42: /* Set background color: green */
+ case 43: /* Set background color: brown */
+ case 44: /* Set background color: blue */
+ case 45: /* Set background color: magenta */
+ case 46: /* Set background color: cyan */
+ case 47: /* Set background color: white */
+ t->t_curattr.ta_bgcolor = n - 40;
+ break;
+ case 49: /* Set default background color. */
+ t->t_curattr.ta_bgcolor = t->t_defattr.ta_bgcolor;
+ break;
+ default:
+ teken_printf("unsupported attribute %u\n", n);
+ }
+ }
+}
+
+static void
+teken_subr_set_top_and_bottom_margins(teken_t *t, unsigned int top,
+ unsigned int bottom)
+{
+
+ /* Adjust top row number. */
+ if (top > 0)
+ top--;
+ /* Adjust bottom row number. */
+ if (bottom == 0 || bottom > t->t_winsize.tp_row)
+ bottom = t->t_winsize.tp_row;
+
+ /* Invalid arguments. */
+ if (top >= bottom - 1) {
+ top = 0;
+ bottom = t->t_winsize.tp_row;
+ }
+
+ t->t_scrollreg.ts_begin = top;
+ t->t_scrollreg.ts_end = bottom;
+ if (t->t_stateflags & TS_ORIGIN) {
+ /* XXX: home cursor? */
+ t->t_originreg = t->t_scrollreg;
+ t->t_cursor.tp_row = t->t_originreg.ts_begin;
+ t->t_cursor.tp_col = 0;
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+ }
+}
+
+static void
+teken_subr_single_height_double_width_line(teken_t *t __unused)
+{
+
+ teken_printf("single height double width???\n");
+}
+
+static void
+teken_subr_single_height_single_width_line(teken_t *t __unused)
+{
+
+ teken_printf("single height single width???\n");
+}
+
+static void
+teken_subr_string_terminator(teken_t *t __unused)
+{
+
+ teken_printf("string terminator???\n");
+}
+
+static void
+teken_subr_tab_clear(teken_t *t, unsigned int cmd)
+{
+
+ switch (cmd) {
+ case 0:
+ teken_tab_clear(t, t->t_cursor.tp_col);
+ break;
+ case 3:
+ memset(&t->t_tabstops, 0, T_NUMCOL / 8);
+ break;
+ }
+}
+
+static void
+teken_subr_vertical_position_absolute(teken_t *t, unsigned int row)
+{
+
+ t->t_cursor.tp_row = t->t_originreg.ts_begin + row - 1;
+ if (row >= t->t_originreg.ts_end)
+ t->t_cursor.tp_row = t->t_originreg.ts_end - 1;
+
+
+ t->t_stateflags &= ~TS_WRAPPED;
+ teken_funcs_cursor(t);
+}
diff --git a/sys/dev/syscons/teken/teken_subr_compat.h b/sys/dev/syscons/teken/teken_subr_compat.h
new file mode 100644
index 0000000..5378bb0
--- /dev/null
+++ b/sys/dev/syscons/teken/teken_subr_compat.h
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+static void
+teken_subr_cons25_set_cursor_type(teken_t *t, unsigned int type)
+{
+
+ teken_funcs_param(t, TP_SHOWCURSOR, type != 1);
+}
+
+static void
+teken_subr_cons25_switch_virtual_terminal(teken_t *t, unsigned int vt)
+{
+
+ teken_funcs_param(t, TP_SWITCHVT, vt);
+}
+
+#if 0
+static void
+teken_subr_vt52_decid(teken_t *t)
+{
+ const char response[] = "\x1B/Z";
+
+ teken_funcs_respond(t, response, sizeof response - 1);
+}
+#endif
diff --git a/sys/dev/syscons/teken/teken_wcwidth.h b/sys/dev/syscons/teken/teken_wcwidth.h
new file mode 100644
index 0000000..838fb3d
--- /dev/null
+++ b/sys/dev/syscons/teken/teken_wcwidth.h
@@ -0,0 +1,120 @@
+/*
+ * Markus Kuhn -- 2007-05-26 (Unicode 5.0)
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted. The author
+ * disclaims all warranties with regard to this software.
+ *
+ * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
+ *
+ * $FreeBSD$
+ */
+
+struct interval {
+ teken_char_t first;
+ teken_char_t last;
+};
+
+/* auxiliary function for binary search in interval table */
+static int bisearch(teken_char_t ucs, const struct interval *table, int max) {
+ int min = 0;
+ int mid;
+
+ if (ucs < table[0].first || ucs > table[max].last)
+ return 0;
+ while (max >= min) {
+ mid = (min + max) / 2;
+ if (ucs > table[mid].last)
+ min = mid + 1;
+ else if (ucs < table[mid].first)
+ max = mid - 1;
+ else
+ return 1;
+ }
+
+ return 0;
+}
+
+static int teken_wcwidth(teken_char_t ucs)
+{
+ /* sorted list of non-overlapping intervals of non-spacing characters */
+ /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
+ static const struct interval combining[] = {
+ { 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 },
+ { 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
+ { 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 },
+ { 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 },
+ { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
+ { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
+ { 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 },
+ { 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D },
+ { 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 },
+ { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD },
+ { 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C },
+ { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D },
+ { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC },
+ { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD },
+ { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C },
+ { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D },
+ { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 },
+ { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 },
+ { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC },
+ { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
+ { 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D },
+ { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 },
+ { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E },
+ { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC },
+ { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 },
+ { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E },
+ { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 },
+ { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 },
+ { 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 },
+ { 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F },
+ { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 },
+ { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD },
+ { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD },
+ { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 },
+ { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B },
+ { 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 },
+ { 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 },
+ { 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF },
+ { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 },
+ { 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F },
+ { 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B },
+ { 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F },
+ { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB },
+ { 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F },
+ { 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 },
+ { 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD },
+ { 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F },
+ { 0xE0100, 0xE01EF }
+ };
+
+ /* test for 8-bit control characters */
+ if (ucs == 0)
+ return 0;
+ if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
+ return -1;
+
+ /* binary search in table of non-spacing characters */
+ if (bisearch(ucs, combining,
+ sizeof(combining) / sizeof(struct interval) - 1))
+ return 0;
+
+ /* if we arrive here, ucs is not a combining or C0/C1 control character */
+
+ return 1 +
+ (ucs >= 0x1100 &&
+ (ucs <= 0x115f || /* Hangul Jamo init. consonants */
+ ucs == 0x2329 || ucs == 0x232a ||
+ (ucs >= 0x2e80 && ucs <= 0xa4cf &&
+ ucs != 0x303f) || /* CJK ... Yi */
+ (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
+ (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
+ (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
+ (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
+ (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
+ (ucs >= 0xffe0 && ucs <= 0xffe6) ||
+ (ucs >= 0x20000 && ucs <= 0x2fffd) ||
+ (ucs >= 0x30000 && ucs <= 0x3fffd)));
+}
diff --git a/sys/pc98/cbus/scterm-sck.c b/sys/pc98/cbus/scterm-sck.c
index ced4a92..2577f66 100644
--- a/sys/pc98/cbus/scterm-sck.c
+++ b/sys/pc98/cbus/scterm-sck.c
@@ -37,9 +37,7 @@
#include <machine/pc/display.h>
#include <dev/syscons/syscons.h>
-#include <dev/syscons/sctermvar.h>
-
-#ifndef SC_DUMB_TERMINAL
+#include <pc98/cbus/sctermvar.h>
#define MAX_ESC_PAR 5
@@ -1212,5 +1210,3 @@ mask2attr(term_stat *tcp)
return (attr << 8);
}
-
-#endif /* SC_DUMB_TERMINAL */
diff --git a/sys/dev/syscons/sctermvar.h b/sys/pc98/cbus/sctermvar.h
index b1c01af..b1c01af 100644
--- a/sys/dev/syscons/sctermvar.h
+++ b/sys/pc98/cbus/sctermvar.h
OpenPOWER on IntegriCloud