[libteken] Initial import. This is a fork of libteken, which originally lived in domokit/third_party Change-Id: I04420463a526d8f789bbeef4c8d91a7a06894b7f
diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index c2a4eac..0000000 --- a/AUTHORS +++ /dev/null
@@ -1,8 +0,0 @@ -# This is the list of Fuchsia Authors. - -# Names should be added to this file as one of -# Organization's name -# Individual's name <submission email address> -# Individual's name <submission email address> <email2> <emailN> - -Google Inc.
diff --git a/BUILD.gn b/BUILD.gn new file mode 100644 index 0000000..0d46c90 --- /dev/null +++ b/BUILD.gn
@@ -0,0 +1,17 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("libteken") { + sources = [ + "teken/teken.c", + "teken/teken.h", + "teken/teken_scs.h", + "teken/teken_state.h", + "teken/teken_subr.h", + "teken/teken_subr_compat.h", + "teken/teken_wcwidth.h", + ] + + defines = [ "__unused=__attribute__((unused))" ] +}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 81e2938..0000000 --- a/CONTRIBUTING.md +++ /dev/null
@@ -1,9 +0,0 @@ -This repository accepts contributions using Gerrit. - -Instructions for using Gerrit: - - * https://gerrit-review.googlesource.com/Documentation/ - -Before we can land your change, you need to sign the Google CLA: - - * https://cla.developers.google.com/
diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..8f274b3 --- /dev/null +++ b/COPYRIGHT
@@ -0,0 +1,126 @@ +# $FreeBSD: head/COPYRIGHT 260125 2013-12-31 12:18:10Z gjb $ +# @(#)COPYRIGHT 8.2 (Berkeley) 3/21/94 + +The compilation of software known as FreeBSD is distributed under the +following terms: + +Copyright (c) 1992-2014 The FreeBSD Project. 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. + +The 4.4BSD and 4.4BSD-Lite software is distributed under the following +terms: + +All of the documentation and software included in the 4.4BSD and 4.4BSD-Lite +Releases is copyrighted by The Regents of the University of California. + +Copyright 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 + The Regents of the University of California. 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. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: +This product includes software developed by the University of +California, Berkeley and its contributors. +4. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + +The Institute of Electrical and Electronics Engineers and the American +National Standards Committee X3, on Information Processing Systems have +given us permission to reprint portions of their documentation. + +In the following statement, the phrase ``this text'' refers to portions +of the system documentation. + +Portions of this text are reprinted and reproduced in electronic form in +the second BSD Networking Software Release, from IEEE Std 1003.1-1988, IEEE +Standard Portable Operating System Interface for Computer Environments +(POSIX), copyright C 1988 by the Institute of Electrical and Electronics +Engineers, Inc. In the event of any discrepancy between these versions +and the original IEEE Standard, the original IEEE Standard is the referee +document. + +In the following statement, the phrase ``This material'' refers to portions +of the system documentation. + +This material is reproduced with permission from American National +Standards Committee X3, on Information Processing Systems. Computer and +Business Equipment Manufacturers Association (CBEMA), 311 First St., NW, +Suite 500, Washington, DC 20001-2178. The developmental work of +Programming Language C was completed by the X3J11 Technical Committee. + +The views and conclusions contained in the software and documentation are +those of the authors and should not be interpreted as representing official +policies, either expressed or implied, of the Regents of the University +of California. + + +NOTE: The copyright of UC Berkeley's Berkeley Software Distribution ("BSD") +source has been updated. The copyright addendum may be found at +ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change and is +included below. + +July 22, 1999 + +To All Licensees, Distributors of Any Version of BSD: + +As you know, certain of the Berkeley Software Distribution ("BSD") source +code files require that further distributions of products containing all or +portions of the software, acknowledge within their advertising materials +that such products contain software developed by UC Berkeley and its +contributors. + +Specifically, the provision reads: + +" * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors." + +Effective immediately, licensees and distributors are no longer required to +include the acknowledgement within advertising materials. Accordingly, the +foregoing paragraph of those BSD Unix files containing it is hereby deleted +in its entirety. + +William Hoskins +Director, Office of Technology Licensing +University of California, Berkeley
diff --git a/LICENSE b/LICENSE deleted file mode 100644 index ac6402f..0000000 --- a/LICENSE +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2016 The Fuchsia Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * 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. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT -// OWNER 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.
diff --git a/README.md b/README.md index 8b90b74..93cbbc1 100644 --- a/README.md +++ b/README.md
@@ -1,5 +1,24 @@ -Fuchsia Open Source Template Repository -======================================= +Name: libteken +URL: svn://svn.FreeBSD.org/base/head/sys/teken/ +Version: r276292 +License: BSD +License File: COPYRIGHT +Security Critical: no -This repository is a template that we will use when creating new open source -repositories for Fuchsia. +Description: +This is libteken from FreeBSD, a VT100-ish terminal emulator library. + +It was obtained as follows (from this directory): + + svn export svn://svn.FreeBSD.org/base/head/sys/teken/@276292 + svn export svn://svn.FreeBSD.org/base/head/COPYRIGHT@276292 + +Local modifications: +* teken/teken_state.h: manually generated (from the teken subdirectory) using: + |awk -f gensequences sequences > teken_state.h|. +* teken/teken.h: |#include <stdint.h>|. +* teken/teken.h: |extern "C"| guards added for C++. +* teken/gensequences: made executable, to placate checkperms.py. +* teken/{demo, libteken, stress}: removed. +* teken.c: remove sys/cdefs.h to fix fnl/musl build + (http://wiki.musl-libc.org/wiki/FAQ#Q:_I.27m_trying_to_compile_something_against_musl_and_I_get_error_messages_about_sys.2Fcdefs.h)
diff --git a/teken/gensequences b/teken/gensequences new file mode 100755 index 0000000..83a3d10 --- /dev/null +++ b/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: head/sys/teken/gensequences 223574 2011-06-26 18:25:10Z ed $ + +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/teken/sequences b/teken/sequences new file mode 100644 index 0000000..080657a --- /dev/null +++ b/teken/sequences
@@ -0,0 +1,113 @@ +#- +# 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: head/sys/teken/sequences 214817 2010-11-05 00:56:21Z ed $ + +# 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 +G0SCS0 G0 SCS Special Graphics ^[ ( 0 +G0SCS1 G0 SCS US ASCII ^[ ( 1 +G0SCS2 G0 SCS Special Graphics ^[ ( 2 +G0SCSA G0 SCS UK National ^[ ( A +G0SCSB G0 SCS US ASCII ^[ ( B +G1SCS0 G1 SCS Special Graphics ^[ ) 0 +G1SCS1 G1 SCS US ASCII ^[ ) 1 +G1SCS2 G1 SCS Special Graphics ^[ ) 2 +G1SCSA G1 SCS UK National ^[ ) A +G1SCSB G1 SCS US ASCII ^[ ) B +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 +OSC Operating System Command ^[ ] +RI Reverse index ^[ M +RIS Reset to Initial State ^[ c +RM Reset Mode ^[ [ l r +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 +C25ADBG Cons25 set adapter background ^[ [ = G r +C25ADFG Cons25 set adapter foreground ^[ [ = F r +C25BLPD Cons25 set bell pitch duration ^[ [ = B r r +C25CURS Cons25 set cursor type ^[ [ = S r +C25MODE Cons25 set terminal mode ^[ [ = T r +C25SGR Cons25 set graphic rendition ^[ [ x r r +C25VTSW Cons25 switch virtual terminal ^[ [ z r + +# VT52 compatibility +#DECID VT52 DECID ^[ Z
diff --git a/teken/teken.c b/teken/teken.c new file mode 100644 index 0000000..b1c9d15 --- /dev/null +++ b/teken/teken.c
@@ -0,0 +1,557 @@ +/*- + * 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: head/sys/teken/teken.c 261551 2014-02-06 13:28:06Z ray $ + */ + +#if defined(__FreeBSD__) && defined(_KERNEL) +#include <sys/param.h> +#include <sys/lock.h> +#include <sys/systm.h> +#define teken_assert(x) MPASS(x) +#else /* !(__FreeBSD__ && _KERNEL) */ +#include <sys/types.h> +#include <assert.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#define teken_assert(x) assert(x) +#endif /* __FreeBSD__ && _KERNEL */ + +/* debug messages */ +#define teken_printf(x,...) + +/* Private flags for t_stateflags. */ +#define TS_FIRSTDIGIT 0x0001 /* First numeric digit in escape sequence. */ +#define TS_INSERT 0x0002 /* Insert mode. */ +#define TS_AUTOWRAP 0x0004 /* Autowrap. */ +#define TS_ORIGIN 0x0008 /* Origin mode. */ +#define TS_WRAPPED 0x0010 /* Next character should be printed on col 0. */ +#define TS_8BIT 0x0020 /* UTF-8 disabled. */ +#define TS_CONS25 0x0040 /* cons25 emulation. */ +#define TS_INSTRING 0x0080 /* Inside string. */ +#define TS_CURSORKEYS 0x0100 /* Cursor keys mode. */ + +/* Character that blanks a cell. */ +#define BLANK ' ' + +#include "teken.h" +#include "teken_wcwidth.h" +#include "teken_scs.h" + +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_assert(p->tp_row < t->t_winsize.tp_row); + teken_assert(p->tp_col < t->t_winsize.tp_col); + + 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_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); + + 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, unsigned 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 }; + + t->t_funcs = tf; + t->t_softc = softc; + + t->t_nextstate = teken_state_init; + t->t_stateflags = 0; + t->t_utf8_left = 0; + + 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); + + teken_set_winsize(t, &tp); +} + +static void +teken_input_char(teken_t *t, teken_char_t c) +{ + + /* + * There is no support for DCS and OSC. Just discard strings + * until we receive characters that may indicate string + * termination. + */ + if (t->t_stateflags & TS_INSTRING) { + switch (c) { + case '\x1B': + t->t_stateflags &= ~TS_INSTRING; + break; + case '\a': + t->t_stateflags &= ~TS_INSTRING; + return; + default: + return; + } + } + + 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 '\x0C': + teken_subr_newpage(t); + break; + case '\x0E': + if (t->t_stateflags & TS_CONS25) + t->t_nextstate(t, c); + else + t->t_curscs = 1; + break; + case '\x0F': + if (t->t_stateflags & TS_CONS25) + t->t_nextstate(t, c); + else + t->t_curscs = 0; + 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) +{ + + /* + * UTF-8 handling. + */ + if ((c & 0x80) == 0x00 || t->t_stateflags & TS_8BIT) { + /* 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 %x\n", t->t_utf8_partial); + teken_input_char(t, t->t_utf8_partial); + } + } +} + +void +teken_input(teken_t *t, const void *buf, size_t len) +{ + const char *c = buf; + + while (len-- > 0) + teken_input_byte(t, *c++); +} + +const teken_pos_t * +teken_get_cursor(teken_t *t) +{ + + return (&t->t_cursor); +} + +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; +} + +const teken_attr_t * +teken_get_curattr(teken_t *t) +{ + + return (&t->t_curattr); +} + +void +teken_set_curattr(teken_t *t, const teken_attr_t *a) +{ + + t->t_curattr = *a; +} + +const teken_attr_t * +teken_get_defattr(teken_t *t) +{ + + return (&t->t_defattr); +} + +void +teken_set_defattr(teken_t *t, const teken_attr_t *a) +{ + + t->t_curattr = t->t_saved_curattr = t->t_defattr = *a; +} + +const teken_pos_t * +teken_get_winsize(teken_t *t) +{ + + return (&t->t_winsize); +} + +static void +teken_trim_cursor_pos(teken_t *t, const teken_pos_t *new) +{ + const teken_pos_t *cur; + + cur = &t->t_winsize; + + if (cur->tp_row < new->tp_row || cur->tp_col < new->tp_col) + return; + if (t->t_cursor.tp_row >= new->tp_row) + t->t_cursor.tp_row = new->tp_row - 1; + if (t->t_cursor.tp_col >= new->tp_col) + t->t_cursor.tp_col = new->tp_col - 1; +} + +void +teken_set_winsize(teken_t *t, const teken_pos_t *p) +{ + + teken_trim_cursor_pos(t, p); + t->t_winsize = *p; + teken_subr_do_reset(t); +} + +void +teken_set_winsize_noreset(teken_t *t, const teken_pos_t *p) +{ + + teken_trim_cursor_pos(t, p); + t->t_winsize = *p; + teken_subr_do_resize(t); +} + +void +teken_set_8bit(teken_t *t) +{ + + t->t_stateflags |= TS_8BIT; +} + +void +teken_set_cons25(teken_t *t) +{ + + t->t_stateflags |= TS_CONS25; +} + +/* + * 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); +} + +teken_color_t +teken_256to8(teken_color_t c) +{ + unsigned int r, g, b; + + if (c < 16) { + /* Traditional color indices. */ + return (c % 8); + } else if (c >= 244) { + /* Upper grayscale colors. */ + return (TC_WHITE); + } else if (c >= 232) { + /* Lower grayscale colors. */ + return (TC_BLACK); + } + + /* Convert to RGB. */ + c -= 16; + b = c % 6; + g = (c / 6) % 6; + r = c / 36; + + if (r < g) { + /* Possibly green. */ + if (g < b) + return (TC_BLUE); + else if (g > b) + return (TC_GREEN); + else + return (TC_CYAN); + } else if (r > g) { + /* Possibly red. */ + if (r < b) + return (TC_BLUE); + else if (r > b) + return (TC_RED); + else + return (TC_MAGENTA); + } else { + /* Possibly brown. */ + if (g < b) + return (TC_BLUE); + else if (g > b) + return (TC_BROWN); + else if (r < 3) + return (TC_BLACK); + else + return (TC_WHITE); + } +} + +static const char * const special_strings_cons25[] = { + [TKEY_UP] = "\x1B[A", [TKEY_DOWN] = "\x1B[B", + [TKEY_LEFT] = "\x1B[D", [TKEY_RIGHT] = "\x1B[C", + + [TKEY_HOME] = "\x1B[H", [TKEY_END] = "\x1B[F", + [TKEY_INSERT] = "\x1B[L", [TKEY_DELETE] = "\x7F", + [TKEY_PAGE_UP] = "\x1B[I", [TKEY_PAGE_DOWN] = "\x1B[G", + + [TKEY_F1] = "\x1B[M", [TKEY_F2] = "\x1B[N", + [TKEY_F3] = "\x1B[O", [TKEY_F4] = "\x1B[P", + [TKEY_F5] = "\x1B[Q", [TKEY_F6] = "\x1B[R", + [TKEY_F7] = "\x1B[S", [TKEY_F8] = "\x1B[T", + [TKEY_F9] = "\x1B[U", [TKEY_F10] = "\x1B[V", + [TKEY_F11] = "\x1B[W", [TKEY_F12] = "\x1B[X", +}; + +static const char * const special_strings_ckeys[] = { + [TKEY_UP] = "\x1BOA", [TKEY_DOWN] = "\x1BOB", + [TKEY_LEFT] = "\x1BOD", [TKEY_RIGHT] = "\x1BOC", + + [TKEY_HOME] = "\x1BOH", [TKEY_END] = "\x1BOF", +}; + +static const char * const special_strings_normal[] = { + [TKEY_UP] = "\x1B[A", [TKEY_DOWN] = "\x1B[B", + [TKEY_LEFT] = "\x1B[D", [TKEY_RIGHT] = "\x1B[C", + + [TKEY_HOME] = "\x1B[H", [TKEY_END] = "\x1B[F", + [TKEY_INSERT] = "\x1B[2~", [TKEY_DELETE] = "\x1B[3~", + [TKEY_PAGE_UP] = "\x1B[5~", [TKEY_PAGE_DOWN] = "\x1B[6~", + + [TKEY_F1] = "\x1BOP", [TKEY_F2] = "\x1BOQ", + [TKEY_F3] = "\x1BOR", [TKEY_F4] = "\x1BOS", + [TKEY_F5] = "\x1B[15~", [TKEY_F6] = "\x1B[17~", + [TKEY_F7] = "\x1B[18~", [TKEY_F8] = "\x1B[19~", + [TKEY_F9] = "\x1B[20~", [TKEY_F10] = "\x1B[21~", + [TKEY_F11] = "\x1B[23~", [TKEY_F12] = "\x1B[24~", +}; + +const char * +teken_get_sequence(teken_t *t, unsigned int k) +{ + + /* Cons25 mode. */ + if (t->t_stateflags & TS_CONS25 && + k < sizeof special_strings_cons25 / sizeof(char *)) + return (special_strings_cons25[k]); + + /* Cursor keys mode. */ + if (t->t_stateflags & TS_CURSORKEYS && + k < sizeof special_strings_ckeys / sizeof(char *)) + return (special_strings_ckeys[k]); + + /* Default xterm sequences. */ + if (k < sizeof special_strings_normal / sizeof(char *)) + return (special_strings_normal[k]); + + return (NULL); +} + +#include "teken_state.h"
diff --git a/teken/teken.h b/teken/teken.h new file mode 100644 index 0000000..e5c252b --- /dev/null +++ b/teken/teken.h
@@ -0,0 +1,223 @@ +/*- + * 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: head/sys/teken/teken.h 259667 2013-12-20 21:31:50Z ed $ + */ + +#ifndef _TEKEN_H_ +#define _TEKEN_H_ + +// !!! Start of Mojo addition. +#include <stdint.h> +// !!! End of Mojo addition. +#include <sys/types.h> + +/* + * libteken: terminal emulation library. + * + * This library converts an UTF-8 stream of bytes to terminal drawing + * commands. + */ + +// !!! Start of Mojo addition. +#ifdef __cplusplus +extern "C" { +#endif +// !!! End of Mojo addition. + +typedef uint32_t teken_char_t; +typedef unsigned short teken_unit_t; +typedef unsigned char teken_format_t; +#define TF_BOLD 0x01 /* Bold character. */ +#define TF_UNDERLINE 0x02 /* Underline character. */ +#define TF_BLINK 0x04 /* Blinking character. */ +#define TF_REVERSE 0x08 /* Reverse rendered character. */ +#define TF_CJK_RIGHT 0x10 /* Right-hand side of CJK character. */ +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, unsigned int); +#define TP_SHOWCURSOR 0 +#define TP_KEYPADAPP 1 +#define TP_AUTOREPEAT 2 +#define TP_SWITCHVT 3 +#define TP_132COLS 4 +#define TP_SETBELLPD 5 +#define TP_SETBELLPD_PITCH(pd) ((pd) >> 16) +#define TP_SETBELLPD_DURATION(pd) ((pd) & 0xffff) +#define TP_MOUSE 6 +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; + +typedef teken_char_t teken_scs_t(teken_t *, teken_char_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)]; + + unsigned int t_utf8_left; + teken_char_t t_utf8_partial; + + unsigned int t_curscs; + teken_scs_t *t_saved_curscs; + teken_scs_t *t_scs[2]; +}; + +/* 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); + +/* Get/set teken attributes. */ +const teken_pos_t *teken_get_cursor(teken_t *); +const teken_attr_t *teken_get_curattr(teken_t *); +const teken_attr_t *teken_get_defattr(teken_t *); +void teken_get_defattr_cons25(teken_t *, int *, int *); +const teken_pos_t *teken_get_winsize(teken_t *); +void teken_set_cursor(teken_t *, const teken_pos_t *); +void teken_set_curattr(teken_t *, const teken_attr_t *); +void teken_set_defattr(teken_t *, const teken_attr_t *); +void teken_set_winsize(teken_t *, const teken_pos_t *); +void teken_set_winsize_noreset(teken_t *, const teken_pos_t *); + +/* Key input escape sequences. */ +#define TKEY_UP 0x00 +#define TKEY_DOWN 0x01 +#define TKEY_LEFT 0x02 +#define TKEY_RIGHT 0x03 + +#define TKEY_HOME 0x04 +#define TKEY_END 0x05 +#define TKEY_INSERT 0x06 +#define TKEY_DELETE 0x07 +#define TKEY_PAGE_UP 0x08 +#define TKEY_PAGE_DOWN 0x09 + +#define TKEY_F1 0x0a +#define TKEY_F2 0x0b +#define TKEY_F3 0x0c +#define TKEY_F4 0x0d +#define TKEY_F5 0x0e +#define TKEY_F6 0x0f +#define TKEY_F7 0x10 +#define TKEY_F8 0x11 +#define TKEY_F9 0x12 +#define TKEY_F10 0x13 +#define TKEY_F11 0x14 +#define TKEY_F12 0x15 +const char *teken_get_sequence(teken_t *, unsigned int); + +/* Legacy features. */ +void teken_set_8bit(teken_t *); +void teken_set_cons25(teken_t *); + +/* Color conversion. */ +teken_color_t teken_256to8(teken_color_t); + +// !!! Start of Mojo addition. +#ifdef __cplusplus +} // extern "C" +#endif +// !!! End of Mojo addition. + +#endif /* !_TEKEN_H_ */
diff --git a/teken/teken_scs.h b/teken/teken_scs.h new file mode 100644 index 0000000..c055894 --- /dev/null +++ b/teken/teken_scs.h
@@ -0,0 +1,80 @@ +/*- + * Copyright (c) 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: head/sys/teken/teken_scs.h 203659 2010-02-08 09:16:59Z ed $ + */ + +static inline teken_char_t +teken_scs_process(teken_t *t, teken_char_t c) +{ + + return (t->t_scs[t->t_curscs](t, c)); +} + +/* Unicode points for VT100 box drawing. */ +static const uint16_t teken_boxdrawing_unicode[31] = { + 0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1, + 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba, + 0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c, + 0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7 +}; + +/* ASCII points for VT100 box drawing. */ +static const uint8_t teken_boxdrawing_8bit[31] = { + '?', '?', 'H', 'F', 'C', 'L', '?', '?', + 'N', 'V', '+', '+', '+', '+', '+', '-', + '-', '-', '-', '-', '+', '+', '+', '+', + '|', '?', '?', '?', '?', '?', '?', +}; + +static teken_char_t +teken_scs_special_graphics(teken_t *t, teken_char_t c) +{ + + /* Box drawing. */ + if (c >= '`' && c <= '~') + return (t->t_stateflags & TS_8BIT ? + teken_boxdrawing_8bit[c - '`'] : + teken_boxdrawing_unicode[c - '`']); + return (c); +} + +static teken_char_t +teken_scs_uk_national(teken_t *t, teken_char_t c) +{ + + /* Pound sign. */ + if (c == '#') + return (t->t_stateflags & TS_8BIT ? 0x9c : 0xa3); + return (c); +} + +static teken_char_t +teken_scs_us_ascii(teken_t *t __unused, teken_char_t c) +{ + + /* No processing. */ + return (c); +}
diff --git a/teken/teken_state.h b/teken/teken_state.h new file mode 100644 index 0000000..65b0b44 --- /dev/null +++ b/teken/teken_state.h
@@ -0,0 +1,383 @@ +/* Generated file. Do not edit. */ + +static teken_state_t teken_state_2; +static teken_state_t teken_state_6; +static teken_state_t teken_state_1; +static teken_state_t teken_state_7; +static teken_state_t teken_state_8; +static teken_state_t teken_state_3; +static teken_state_t teken_state_5; +static teken_state_t teken_state_4; + +/* '' */ +static void +teken_state_init(teken_t *t, teken_char_t c) +{ + + switch (c) { + case '\x1B': + teken_state_switch(t, teken_state_1); + return; + default: + teken_subr_regular_character(t, c); + break; + } +} + +/* '^[[' */ +static void +teken_state_2(teken_t *t, teken_char_t c) +{ + + if (teken_state_numbers(t, c)) + return; + + switch (c) { + case 'X': /* ECH: Erase character */ + teken_subr_erase_character(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'Z': /* CBT: Cursor Backward Tabulation */ + teken_subr_cursor_backward_tabulation(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case '`': /* HPA: Horizontal Position Absolute */ + teken_subr_horizontal_position_absolute(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'a': /* CUF: Cursor Forward */ + teken_subr_cursor_forward(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'c': /* DA1: Primary Device Attributes */ + teken_subr_primary_device_attributes(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + case 'd': /* VPA: Vertical Position Absolute */ + teken_subr_vertical_position_absolute(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'e': /* CUD: Cursor Down */ + teken_subr_cursor_down(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'f': /* CUP: Cursor Position */ + teken_subr_cursor_position(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0], (t->t_curnum < 2 || t->t_nums[1] == 0) ? 1 : t->t_nums[1]); + break; + case 'g': /* TBC: Tab Clear */ + teken_subr_tab_clear(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + case 'h': /* SM: Set Mode */ + teken_subr_set_mode(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + case 'l': /* RM: Reset Mode */ + teken_subr_reset_mode(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + case 'm': /* SGR: Set Graphic Rendition */ + teken_subr_set_graphic_rendition(t, t->t_curnum, t->t_nums); + break; + case 'n': /* CPR: Cursor Position Report */ + teken_subr_cursor_position_report(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + case 'r': /* DECSTBM: Set top and bottom margins */ + teken_subr_set_top_and_bottom_margins(t, t->t_curnum < 1 ? 0 : t->t_nums[0], t->t_curnum < 2 ? 0 : t->t_nums[1]); + break; + case 's': /* DECSC: Save cursor */ + teken_subr_save_cursor(t); + break; + case 'u': /* DECRC: Restore cursor */ + teken_subr_restore_cursor(t); + break; + case 'x': /* C25SGR: Cons25 set graphic rendition */ + teken_subr_cons25_set_graphic_rendition(t, t->t_curnum < 1 ? 0 : t->t_nums[0], t->t_curnum < 2 ? 0 : t->t_nums[1]); + break; + case 'z': /* C25VTSW: Cons25 switch virtual terminal */ + teken_subr_cons25_switch_virtual_terminal(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + case '@': /* ICH: Insert character */ + teken_subr_insert_character(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'A': /* CUU: Cursor Up */ + teken_subr_cursor_up(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'B': /* CUD: Cursor Down */ + teken_subr_cursor_down(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'C': /* CUF: Cursor Forward */ + teken_subr_cursor_forward(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'D': /* CUB: Cursor Backward */ + teken_subr_cursor_backward(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'E': /* CNL: Cursor Next Line */ + teken_subr_cursor_next_line(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'F': /* CPL: Cursor Previous Line */ + teken_subr_cursor_previous_line(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'G': /* HPA: Horizontal Position Absolute */ + teken_subr_horizontal_position_absolute(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'H': /* CUP: Cursor Position */ + teken_subr_cursor_position(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0], (t->t_curnum < 2 || t->t_nums[1] == 0) ? 1 : t->t_nums[1]); + break; + case 'I': /* CHT: Cursor Forward Tabulation */ + teken_subr_cursor_forward_tabulation(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'J': /* ED: Erase display */ + teken_subr_erase_display(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + case 'K': /* EL: Erase line */ + teken_subr_erase_line(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + case 'L': /* IL: Insert line */ + teken_subr_insert_line(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'M': /* DL: Delete line */ + teken_subr_delete_line(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'P': /* DC: Delete character */ + teken_subr_delete_character(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'S': /* SU: Pan Down */ + teken_subr_pan_down(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case 'T': /* SD: Pan Up */ + teken_subr_pan_up(t, (t->t_curnum < 1 || t->t_nums[0] == 0) ? 1 : t->t_nums[0]); + break; + case '=': + teken_state_switch(t, teken_state_8); + return; + case '>': + teken_state_switch(t, teken_state_3); + return; + case '?': + teken_state_switch(t, teken_state_5); + return; + default: + teken_printf("Unsupported sequence in teken_state_2: %u\n", (unsigned int)c); + break; + } + + teken_state_switch(t, teken_state_init); +} + +/* '^[(' */ +static void +teken_state_6(teken_t *t, teken_char_t c) +{ + + switch (c) { + case '0': /* G0SCS0: G0 SCS Special Graphics */ + teken_subr_g0_scs_special_graphics(t); + break; + case '1': /* G0SCS1: G0 SCS US ASCII */ + teken_subr_g0_scs_us_ascii(t); + break; + case '2': /* G0SCS2: G0 SCS Special Graphics */ + teken_subr_g0_scs_special_graphics(t); + break; + case 'A': /* G0SCSA: G0 SCS UK National */ + teken_subr_g0_scs_uk_national(t); + break; + case 'B': /* G0SCSB: G0 SCS US ASCII */ + teken_subr_g0_scs_us_ascii(t); + break; + default: + teken_printf("Unsupported sequence in teken_state_6: %u\n", (unsigned int)c); + break; + } + + teken_state_switch(t, teken_state_init); +} + +/* '^[' */ +static void +teken_state_1(teken_t *t, teken_char_t c) +{ + + switch (c) { + case '7': /* DECSC: Save cursor */ + teken_subr_save_cursor(t); + break; + case '8': /* DECRC: Restore cursor */ + teken_subr_restore_cursor(t); + break; + case '=': /* DECKPAM: Keypad application mode */ + teken_subr_keypad_application_mode(t); + break; + case '>': /* DECKPNM: Keypad numeric mode */ + teken_subr_keypad_numeric_mode(t); + break; + case 'D': /* IND: Index */ + teken_subr_index(t); + break; + case 'E': /* NEL: Next line */ + teken_subr_next_line(t); + break; + case 'H': /* HTS: Horizontal Tab Set */ + teken_subr_horizontal_tab_set(t); + break; + case 'M': /* RI: Reverse index */ + teken_subr_reverse_index(t); + break; + case 'P': /* DCS: Device Control String */ + teken_subr_device_control_string(t); + break; + case ']': /* OSC: Operating System Command */ + teken_subr_operating_system_command(t); + break; + case 'c': /* RIS: Reset to Initial State */ + teken_subr_reset_to_initial_state(t); + break; + case '\\': /* ST: String Terminator */ + teken_subr_string_terminator(t); + break; + case '[': + teken_state_switch(t, teken_state_2); + return; + case '(': + teken_state_switch(t, teken_state_6); + return; + case ')': + teken_state_switch(t, teken_state_7); + return; + case '#': + teken_state_switch(t, teken_state_4); + return; + default: + teken_printf("Unsupported sequence in teken_state_1: %u\n", (unsigned int)c); + break; + } + + teken_state_switch(t, teken_state_init); +} + +/* '^[)' */ +static void +teken_state_7(teken_t *t, teken_char_t c) +{ + + switch (c) { + case '0': /* G1SCS0: G1 SCS Special Graphics */ + teken_subr_g1_scs_special_graphics(t); + break; + case '1': /* G1SCS1: G1 SCS US ASCII */ + teken_subr_g1_scs_us_ascii(t); + break; + case '2': /* G1SCS2: G1 SCS Special Graphics */ + teken_subr_g1_scs_special_graphics(t); + break; + case 'A': /* G1SCSA: G1 SCS UK National */ + teken_subr_g1_scs_uk_national(t); + break; + case 'B': /* G1SCSB: G1 SCS US ASCII */ + teken_subr_g1_scs_us_ascii(t); + break; + default: + teken_printf("Unsupported sequence in teken_state_7: %u\n", (unsigned int)c); + break; + } + + teken_state_switch(t, teken_state_init); +} + +/* '^[[=' */ +static void +teken_state_8(teken_t *t, teken_char_t c) +{ + + if (teken_state_numbers(t, c)) + return; + + switch (c) { + case 'B': /* C25BLPD: Cons25 set bell pitch duration */ + teken_subr_cons25_set_bell_pitch_duration(t, t->t_curnum < 1 ? 0 : t->t_nums[0], t->t_curnum < 2 ? 0 : t->t_nums[1]); + break; + case 'F': /* C25ADFG: Cons25 set adapter foreground */ + teken_subr_cons25_set_adapter_foreground(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + case 'G': /* C25ADBG: Cons25 set adapter background */ + teken_subr_cons25_set_adapter_background(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + case 'S': /* C25CURS: Cons25 set cursor type */ + teken_subr_cons25_set_cursor_type(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + case 'T': /* C25MODE: Cons25 set terminal mode */ + teken_subr_cons25_set_terminal_mode(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + default: + teken_printf("Unsupported sequence in teken_state_8: %u\n", (unsigned int)c); + break; + } + + teken_state_switch(t, teken_state_init); +} + +/* '^[[>' */ +static void +teken_state_3(teken_t *t, teken_char_t c) +{ + + if (teken_state_numbers(t, c)) + return; + + switch (c) { + case 'c': /* DA2: Secondary Device Attributes */ + teken_subr_secondary_device_attributes(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + default: + teken_printf("Unsupported sequence in teken_state_3: %u\n", (unsigned int)c); + break; + } + + teken_state_switch(t, teken_state_init); +} + +/* '^[[?' */ +static void +teken_state_5(teken_t *t, teken_char_t c) +{ + + if (teken_state_numbers(t, c)) + return; + + switch (c) { + case 'h': /* DECSM: Set DEC mode */ + teken_subr_set_dec_mode(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + case 'l': /* DECRM: Reset DEC mode */ + teken_subr_reset_dec_mode(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + case 'n': /* DSR: Device Status Report */ + teken_subr_device_status_report(t, t->t_curnum < 1 ? 0 : t->t_nums[0]); + break; + default: + teken_printf("Unsupported sequence in teken_state_5: %u\n", (unsigned int)c); + break; + } + + teken_state_switch(t, teken_state_init); +} + +/* '^[#' */ +static void +teken_state_4(teken_t *t, teken_char_t c) +{ + + switch (c) { + case '3': /* DECDHL: Double Height Double Width Line Top */ + teken_subr_double_height_double_width_line_top(t); + break; + case '4': /* DECDHL: Double Height Double Width Line Bottom */ + teken_subr_double_height_double_width_line_bottom(t); + break; + case '5': /* DECSWL: Single Height Single Width Line */ + teken_subr_single_height_single_width_line(t); + break; + case '6': /* DECDWL: Single Height Double Width Line */ + teken_subr_single_height_double_width_line(t); + break; + case '8': /* DECALN: Alignment test */ + teken_subr_alignment_test(t); + break; + default: + teken_printf("Unsupported sequence in teken_state_4: %u\n", (unsigned int)c); + break; + } + + teken_state_switch(t, teken_state_init); +}
diff --git a/teken/teken_subr.h b/teken/teken_subr.h new file mode 100644 index 0000000..5dea10b --- /dev/null +++ b/teken/teken_subr.h
@@ -0,0 +1,1306 @@ +/*- + * 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: head/sys/teken/teken_subr.h 259761 2013-12-23 05:47:27Z ed $ + */ + +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 void teken_subr_save_cursor(teken_t *); + +static inline int +teken_tab_isset(teken_t *t, unsigned int col) +{ + unsigned int b, o; + + if (col >= T_NUMCOL) + return ((col % 8) == 0); + + 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; + + if (col >= T_NUMCOL) + return; + + 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; + + if (col >= T_NUMCOL) + return; + + 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_cursor.tp_row = t->t_cursor.tp_col = 0; + t->t_scrollreg.ts_begin = 0; + t->t_scrollreg.ts_end = t->t_winsize.tp_row; + t->t_originreg = t->t_scrollreg; + t->t_stateflags &= ~(TS_WRAPPED|TS_ORIGIN); + 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_stateflags & TS_CONS25) { + if (t->t_cursor.tp_col == 0) { + if (t->t_cursor.tp_row == t->t_originreg.ts_begin) + return; + t->t_cursor.tp_row--; + t->t_cursor.tp_col = t->t_winsize.tp_col - 1; + } else { + t->t_cursor.tp_col--; + } + } else { + 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); + + teken_funcs_cursor(t); +} + +static void +teken_subr_cursor_down(teken_t *t, unsigned int nrows) +{ + + 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); + + teken_funcs_cursor(t); +} + +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 (t->t_cursor.tp_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; + + /* Ignore if outside scrolling region. */ + if (t->t_cursor.tp_row < t->t_scrollreg.ts_begin || + t->t_cursor.tp_row >= t->t_scrollreg.ts_end) + return; + + 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) +{ + + teken_printf("Unsupported device control string\n"); + t->t_stateflags |= TS_INSTRING; +} + +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_g0_scs_special_graphics(teken_t *t __unused) +{ + + t->t_scs[0] = teken_scs_special_graphics; +} + +static void +teken_subr_g0_scs_uk_national(teken_t *t __unused) +{ + + t->t_scs[0] = teken_scs_uk_national; +} + +static void +teken_subr_g0_scs_us_ascii(teken_t *t __unused) +{ + + t->t_scs[0] = teken_scs_us_ascii; +} + +static void +teken_subr_g1_scs_special_graphics(teken_t *t __unused) +{ + + t->t_scs[1] = teken_scs_special_graphics; +} + +static void +teken_subr_g1_scs_uk_national(teken_t *t __unused) +{ + + t->t_scs[1] = teken_scs_uk_national; +} + +static void +teken_subr_g1_scs_us_ascii(teken_t *t __unused) +{ + + t->t_scs[1] = teken_scs_us_ascii; +} + +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_subr_cursor_forward_tabulation(t, 1); +} + +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; + + /* Ignore if outside scrolling region. */ + if (t->t_cursor.tp_row < t->t_scrollreg.ts_begin || + t->t_cursor.tp_row >= t->t_scrollreg.ts_end) + return; + + 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_newpage(teken_t *t) +{ + + if (t->t_stateflags & TS_CONS25) { + teken_rect_t tr; + + /* Clear screen. */ + tr.tr_begin.tp_row = t->t_originreg.ts_begin; + tr.tr_begin.tp_col = 0; + tr.tr_end.tp_row = t->t_originreg.ts_end; + tr.tr_end.tp_col = t->t_winsize.tp_col; + teken_funcs_fill(t, &tr, BLANK, &t->t_curattr); + + /* Cursor at top left. */ + 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); + } else { + teken_subr_newline(t); + } +} + +static void +teken_subr_next_line(teken_t *t) +{ + + t->t_cursor.tp_col = 0; + teken_subr_newline(t); +} + +static void +teken_subr_operating_system_command(teken_t *t) +{ + + teken_printf("Unsupported operating system command\n"); + t->t_stateflags |= TS_INSTRING; +} + +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); + + if (width == 2 && tp->tp_col + 1 < t->t_winsize.tp_col) { + teken_pos_t tp2; + teken_attr_t attr; + + /* Print second half of CJK fullwidth character. */ + tp2.tp_row = tp->tp_row; + tp2.tp_col = tp->tp_col + 1; + attr = t->t_curattr; + attr.ta_format |= TF_CJK_RIGHT; + teken_funcs_putchar(t, &tp2, c, &attr); + } +} + +static void +teken_subr_regular_character(teken_t *t, teken_char_t c) +{ + int width; + + if (t->t_stateflags & TS_8BIT) { + if (!(t->t_stateflags & TS_CONS25) && (c <= 0x1b || c == 0x7f)) + return; + c = teken_scs_process(t, c); + width = 1; + } else { + c = teken_scs_process(t, c); + width = teken_wcwidth(c); + /* XXX: Don't process zero-width characters yet. */ + if (width <= 0) + return; + } + + if (t->t_stateflags & TS_CONS25) { + 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) { + if (t->t_cursor.tp_row == t->t_scrollreg.ts_end - 1) { + /* Perform scrolling. */ + teken_subr_do_scroll(t, 1); + } else { + /* No scrolling needed. */ + if (t->t_cursor.tp_row < + t->t_winsize.tp_row - 1) + t->t_cursor.tp_row++; + } + t->t_cursor.tp_col = 0; + } + } else if (t->t_stateflags & TS_AUTOWRAP && + ((t->t_stateflags & TS_WRAPPED && + t->t_cursor.tp_col + 1 == t->t_winsize.tp_col) || + t->t_cursor.tp_col + width > t->t_winsize.tp_col)) { + teken_pos_t tp; + + /* + * Perform line wrapping, if: + * - Autowrapping is enabled, and + * - We're in the wrapped state at the last column, or + * - The character to be printed does not fit anymore. + */ + 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. */ + t->t_stateflags &= ~TS_CURSORKEYS; + 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; + case 1000: /* Mouse input. */ + teken_funcs_param(t, TP_MOUSE, 0); + 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_resize(teken_t *t) +{ + + t->t_scrollreg.ts_begin = 0; + t->t_scrollreg.ts_end = t->t_winsize.tp_row; + t->t_originreg = t->t_scrollreg; +} + +static void +teken_subr_do_reset(teken_t *t) +{ + + t->t_curattr = t->t_defattr; + t->t_cursor.tp_row = t->t_cursor.tp_col = 0; + t->t_scrollreg.ts_begin = 0; + t->t_scrollreg.ts_end = t->t_winsize.tp_row; + t->t_originreg = t->t_scrollreg; + t->t_stateflags &= TS_8BIT|TS_CONS25; + t->t_stateflags |= TS_AUTOWRAP; + + t->t_scs[0] = teken_scs_us_ascii; + t->t_scs[1] = teken_scs_us_ascii; + t->t_curscs = 0; + + teken_subr_save_cursor(t); + 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_param(t, TP_SHOWCURSOR, 1); + 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_scs[t->t_curscs] = t->t_saved_curscs; + t->t_stateflags &= ~TS_WRAPPED; + + /* Get out of origin mode when the cursor is moved outside. */ + if (t->t_cursor.tp_row < t->t_originreg.ts_begin || + t->t_cursor.tp_row >= t->t_originreg.ts_end) { + t->t_stateflags &= ~TS_ORIGIN; + t->t_originreg.ts_begin = 0; + t->t_originreg.ts_end = t->t_winsize.tp_row; + } + + 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; + t->t_saved_curscs = t->t_scs[t->t_curscs]; +} + +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. */ + t->t_stateflags |= TS_CURSORKEYS; + 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; + case 1000: /* Mouse input. */ + teken_funcs_param(t, TP_MOUSE, 1); + 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 38: /* Set foreground color: 256 color mode */ + if (i + 2 >= ncmds || cmds[i + 1] != 5) + continue; + t->t_curattr.ta_fgcolor = cmds[i + 2]; + i += 2; + 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 48: /* Set background color: 256 color mode */ + if (i + 2 >= ncmds || cmds[i + 1] != 5) + continue; + t->t_curattr.ta_bgcolor = cmds[i + 2]; + i += 2; + break; + case 49: /* Set default background color. */ + t->t_curattr.ta_bgcolor = t->t_defattr.ta_bgcolor; + break; + case 90: /* Set bright foreground color: black */ + case 91: /* Set bright foreground color: red */ + case 92: /* Set bright foreground color: green */ + case 93: /* Set bright foreground color: brown */ + case 94: /* Set bright foreground color: blue */ + case 95: /* Set bright foreground color: magenta */ + case 96: /* Set bright foreground color: cyan */ + case 97: /* Set bright foreground color: white */ + t->t_curattr.ta_fgcolor = n - 90 + 8; + break; + case 100: /* Set bright background color: black */ + case 101: /* Set bright background color: red */ + case 102: /* Set bright background color: green */ + case 103: /* Set bright background color: brown */ + case 104: /* Set bright background color: blue */ + case 105: /* Set bright background color: magenta */ + case 106: /* Set bright background color: cyan */ + case 107: /* Set bright background color: white */ + t->t_curattr.ta_bgcolor = n - 100 + 8; + 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; + } + + /* Apply scrolling region. */ + t->t_scrollreg.ts_begin = top; + t->t_scrollreg.ts_end = bottom; + if (t->t_stateflags & TS_ORIGIN) + t->t_originreg = t->t_scrollreg; + + /* Home cursor to the top left of the scrolling region. */ + 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) +{ + + /* + * Strings are already terminated in teken_input_char() when ^[ + * is inserted. + */ +} + +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 (t->t_cursor.tp_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/teken/teken_subr_compat.h b/teken/teken_subr_compat.h new file mode 100644 index 0000000..826a854 --- /dev/null +++ b/teken/teken_subr_compat.h
@@ -0,0 +1,126 @@ +/*- + * 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: head/sys/teken/teken_subr_compat.h 214817 2010-11-05 00:56:21Z ed $ + */ + +static void +teken_subr_cons25_set_cursor_type(teken_t *t, unsigned int type) +{ + + teken_funcs_param(t, TP_SHOWCURSOR, type != 1); +} + +static const teken_color_t cons25_colors[8] = { TC_BLACK, TC_BLUE, + TC_GREEN, TC_CYAN, TC_RED, TC_MAGENTA, TC_BROWN, TC_WHITE }; + +static void +teken_subr_cons25_set_adapter_background(teken_t *t, unsigned int c) +{ + + t->t_defattr.ta_bgcolor = cons25_colors[c % 8]; + t->t_curattr.ta_bgcolor = cons25_colors[c % 8]; +} + +static void +teken_subr_cons25_set_adapter_foreground(teken_t *t, unsigned int c) +{ + + t->t_defattr.ta_fgcolor = cons25_colors[c % 8]; + t->t_curattr.ta_fgcolor = cons25_colors[c % 8]; + if (c >= 8) { + t->t_defattr.ta_format |= TF_BOLD; + t->t_curattr.ta_format |= TF_BOLD; + } else { + t->t_defattr.ta_format &= ~TF_BOLD; + t->t_curattr.ta_format &= ~TF_BOLD; + } +} + +static const teken_color_t cons25_revcolors[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + +void +teken_get_defattr_cons25(teken_t *t, int *fg, int *bg) +{ + + *fg = cons25_revcolors[teken_256to8(t->t_defattr.ta_fgcolor)]; + if (t->t_defattr.ta_format & TF_BOLD) + *fg += 8; + *bg = cons25_revcolors[teken_256to8(t->t_defattr.ta_bgcolor)]; +} + +static void +teken_subr_cons25_switch_virtual_terminal(teken_t *t, unsigned int vt) +{ + + teken_funcs_param(t, TP_SWITCHVT, vt); +} + +static void +teken_subr_cons25_set_bell_pitch_duration(teken_t *t, unsigned int pitch, + unsigned int duration) +{ + + teken_funcs_param(t, TP_SETBELLPD, (pitch << 16) | + (duration & 0xffff)); +} + +static void +teken_subr_cons25_set_graphic_rendition(teken_t *t, unsigned int cmd, + unsigned int param __unused) +{ + + switch (cmd) { + case 0: /* Reset. */ + t->t_curattr = t->t_defattr; + break; + default: + teken_printf("unsupported attribute %u\n", cmd); + } +} + +static void +teken_subr_cons25_set_terminal_mode(teken_t *t, unsigned int mode) +{ + + switch (mode) { + case 0: /* Switch terminal to xterm. */ + t->t_stateflags &= ~TS_CONS25; + break; + case 1: /* Switch terminal to cons25. */ + t->t_stateflags |= TS_CONS25; + break; + } +} + +#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/teken/teken_wcwidth.h b/teken/teken_wcwidth.h new file mode 100644 index 0000000..ef6da10 --- /dev/null +++ b/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: head/sys/teken/teken_wcwidth.h 186681 2009-01-01 13:26:53Z ed $ + */ + +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))); +}