From a42bf7d6cd085fcc310938672242fb996a5d8859 Mon Sep 17 00:00:00 2001 From: ed Date: Mon, 9 May 2011 16:27:39 +0000 Subject: Add proper build infrastructure for teken. I'm not sure whether we should install teken as a library on any stock FreeBSD installation, but I can imagine people want to tinker around with it now and then. Create a /sys/teken/libteken, which holds a Makefile to install a shared library version of the terminal emulator, complete with a manpage. Also add Makefiles for the demo/stress applications, to build it against the shared library. --- sys/teken/Makefile | 13 -- sys/teken/demo/Makefile | 9 + sys/teken/demo/teken_demo.c | 354 ++++++++++++++++++++++++++++++++++++++++ sys/teken/libteken/Makefile | 39 +++++ sys/teken/libteken/Symbol.map | 21 +++ sys/teken/libteken/teken.3 | 220 +++++++++++++++++++++++++ sys/teken/stress/Makefile | 9 + sys/teken/stress/teken_stress.c | 132 +++++++++++++++ sys/teken/teken.c | 16 +- sys/teken/teken.h | 2 + sys/teken/teken_demo.c | 354 ---------------------------------------- sys/teken/teken_stress.c | 132 --------------- 12 files changed, 789 insertions(+), 512 deletions(-) delete mode 100644 sys/teken/Makefile create mode 100644 sys/teken/demo/Makefile create mode 100644 sys/teken/demo/teken_demo.c create mode 100644 sys/teken/libteken/Makefile create mode 100644 sys/teken/libteken/Symbol.map create mode 100644 sys/teken/libteken/teken.3 create mode 100644 sys/teken/stress/Makefile create mode 100644 sys/teken/stress/teken_stress.c delete mode 100644 sys/teken/teken_demo.c delete mode 100644 sys/teken/teken_stress.c (limited to 'sys/teken') diff --git a/sys/teken/Makefile b/sys/teken/Makefile deleted file mode 100644 index cbdd12b..0000000 --- a/sys/teken/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# $FreeBSD$ - -PROG= teken_demo -SRCS= teken_demo.c teken.c teken_state.h -CLEANFILES= teken_state.h teken.log -LDADD= -lncurses -lutil -NO_MAN= -WARNS?= 6 - -teken_state.h: gensequences sequences - awk -f gensequences sequences > ${.TARGET} - -.include diff --git a/sys/teken/demo/Makefile b/sys/teken/demo/Makefile new file mode 100644 index 0000000..ebf40ab --- /dev/null +++ b/sys/teken/demo/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +PROG= teken_demo +LDADD= -lncurses -lteken -lutil +MAN= + +WARNS?= 6 + +.include diff --git a/sys/teken/demo/teken_demo.c b/sys/teken/demo/teken_demo.c new file mode 100644 index 0000000..0700763 --- /dev/null +++ b/sys/teken/demo/teken_demo.c @@ -0,0 +1,354 @@ +/*- + * Copyright (c) 2008-2009 Ed Schouten + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#if defined(__FreeBSD__) +#include +#elif defined(__linux__) +#include +#else +#include +#endif + +#include + +static tf_bell_t test_bell; +static tf_cursor_t test_cursor; +static tf_putchar_t test_putchar; +static tf_fill_t test_fill; +static tf_copy_t test_copy; +static tf_param_t test_param; +static tf_respond_t test_respond; + +static teken_funcs_t tf = { + .tf_bell = test_bell, + .tf_cursor = test_cursor, + .tf_putchar = test_putchar, + .tf_fill = test_fill, + .tf_copy = test_copy, + .tf_param = test_param, + .tf_respond = test_respond, +}; + +struct pixel { + teken_char_t c; + teken_attr_t a; +}; + +#define NCOLS 80 +#define NROWS 24 +struct pixel buffer[NCOLS][NROWS]; + +static int ptfd; + +static void +printchar(const teken_pos_t *p) +{ + int y, x, attr = 0; + struct pixel *px; + char str[5] = { 0 }; + + assert(p->tp_row < NROWS); + assert(p->tp_col < NCOLS); + + getyx(stdscr, y, x); + + px = &buffer[p->tp_col][p->tp_row]; + + /* Convert Unicode to UTF-8. */ + if (px->c < 0x80) { + str[0] = px->c; + } else if (px->c < 0x800) { + str[0] = 0xc0 | (px->c >> 6); + str[1] = 0x80 | (px->c & 0x3f); + } else if (px->c < 0x10000) { + str[0] = 0xe0 | (px->c >> 12); + str[1] = 0x80 | ((px->c >> 6) & 0x3f); + str[2] = 0x80 | (px->c & 0x3f); + } else { + str[0] = 0xf0 | (px->c >> 18); + str[1] = 0x80 | ((px->c >> 12) & 0x3f); + str[2] = 0x80 | ((px->c >> 6) & 0x3f); + str[3] = 0x80 | (px->c & 0x3f); + } + + if (px->a.ta_format & TF_BOLD) + attr |= A_BOLD; + if (px->a.ta_format & TF_UNDERLINE) + attr |= A_UNDERLINE; + if (px->a.ta_format & TF_BLINK) + attr |= A_BLINK; + if (px->a.ta_format & TF_REVERSE) + attr |= A_REVERSE; + + bkgdset(attr | COLOR_PAIR(teken_256to8(px->a.ta_fgcolor) + + 8 * teken_256to8(px->a.ta_bgcolor))); + mvaddstr(p->tp_row, p->tp_col, str); + + move(y, x); +} + +static void +test_bell(void *s __unused) +{ + + beep(); +} + +static void +test_cursor(void *s __unused, const teken_pos_t *p) +{ + + move(p->tp_row, p->tp_col); +} + +static void +test_putchar(void *s __unused, const teken_pos_t *p, teken_char_t c, + const teken_attr_t *a) +{ + + buffer[p->tp_col][p->tp_row].c = c; + buffer[p->tp_col][p->tp_row].a = *a; + printchar(p); +} + +static void +test_fill(void *s, const teken_rect_t *r, teken_char_t c, + const teken_attr_t *a) +{ + teken_pos_t p; + + /* Braindead implementation of fill() - just call putchar(). */ + for (p.tp_row = r->tr_begin.tp_row; p.tp_row < r->tr_end.tp_row; p.tp_row++) + for (p.tp_col = r->tr_begin.tp_col; p.tp_col < r->tr_end.tp_col; p.tp_col++) + test_putchar(s, &p, c, a); +} + +static void +test_copy(void *s __unused, const teken_rect_t *r, const teken_pos_t *p) +{ + int nrow, ncol, x, y; /* Has to be signed - >= 0 comparison */ + teken_pos_t d; + + /* + * Copying is a little tricky. We must make sure we do it in + * correct order, to make sure we don't overwrite our own data. + */ + + nrow = r->tr_end.tp_row - r->tr_begin.tp_row; + ncol = r->tr_end.tp_col - r->tr_begin.tp_col; + + if (p->tp_row < r->tr_begin.tp_row) { + /* Copy from top to bottom. */ + if (p->tp_col < r->tr_begin.tp_col) { + /* Copy from left to right. */ + for (y = 0; y < nrow; y++) { + d.tp_row = p->tp_row + y; + for (x = 0; x < ncol; x++) { + d.tp_col = p->tp_col + x; + buffer[d.tp_col][d.tp_row] = + buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; + printchar(&d); + } + } + } else { + /* Copy from right to left. */ + for (y = 0; y < nrow; y++) { + d.tp_row = p->tp_row + y; + for (x = ncol - 1; x >= 0; x--) { + d.tp_col = p->tp_col + x; + buffer[d.tp_col][d.tp_row] = + buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; + printchar(&d); + } + } + } + } else { + /* Copy from bottom to top. */ + if (p->tp_col < r->tr_begin.tp_col) { + /* Copy from left to right. */ + for (y = nrow - 1; y >= 0; y--) { + d.tp_row = p->tp_row + y; + for (x = 0; x < ncol; x++) { + d.tp_col = p->tp_col + x; + buffer[d.tp_col][d.tp_row] = + buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; + printchar(&d); + } + } + } else { + /* Copy from right to left. */ + for (y = nrow - 1; y >= 0; y--) { + d.tp_row = p->tp_row + y; + for (x = ncol - 1; x >= 0; x--) { + d.tp_col = p->tp_col + x; + buffer[d.tp_col][d.tp_row] = + buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; + printchar(&d); + } + } + } + } +} + +static void +test_param(void *s __unused, int cmd, unsigned int value) +{ + + switch (cmd) { + case TP_SHOWCURSOR: + curs_set(value); + break; + case TP_KEYPADAPP: + keypad(stdscr, value ? TRUE : FALSE); + break; + } +} + +static void +test_respond(void *s __unused, const void *buf, size_t len) +{ + + write(ptfd, buf, len); +} + +static void +redraw_border(void) +{ + unsigned int i; + + for (i = 0; i < NROWS; i++) + mvaddch(i, NCOLS, '|'); + for (i = 0; i < NCOLS; i++) + mvaddch(NROWS, i, '-'); + + mvaddch(NROWS, NCOLS, '+'); +} + +static void +redraw_all(void) +{ + teken_pos_t tp; + + for (tp.tp_row = 0; tp.tp_row < NROWS; tp.tp_row++) + for (tp.tp_col = 0; tp.tp_col < NCOLS; tp.tp_col++) + printchar(&tp); + + redraw_border(); +} + +int +main(int argc __unused, char *argv[] __unused) +{ + struct winsize ws; + teken_t t; + teken_pos_t tp; + fd_set rfds; + char b[256]; + ssize_t bl; + const int ccolors[8] = { + COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, + COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE + }; + int i, j; + + setlocale(LC_CTYPE, "UTF-8"); + + tp.tp_row = ws.ws_row = NROWS; + tp.tp_col = ws.ws_col = NCOLS; + + switch (forkpty(&ptfd, NULL, NULL, &ws)) { + case -1: + perror("forkpty"); + exit(1); + case 0: + setenv("TERM", "xterm", 1); + setenv("LC_CTYPE", "UTF-8", 0); + execlp("zsh", "-zsh", NULL); + execlp("bash", "-bash", NULL); + execlp("sh", "-sh", NULL); + _exit(1); + } + + teken_init(&t, &tf, NULL); + teken_set_winsize(&t, &tp); + + initscr(); + raw(); + start_color(); + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) + init_pair(i + 8 * j, ccolors[i], ccolors[j]); + + redraw_border(); + + FD_ZERO(&rfds); + + for (;;) { + FD_SET(STDIN_FILENO, &rfds); + FD_SET(ptfd, &rfds); + + if (select(ptfd + 1, &rfds, NULL, NULL, NULL) < 0) { + if (errno == EINTR) { + redraw_all(); + refresh(); + continue; + } + break; + } + + if (FD_ISSET(STDIN_FILENO, &rfds)) { + bl = read(STDIN_FILENO, b, sizeof b); + if (bl <= 0) + break; + write(ptfd, b, bl); + } + + if (FD_ISSET(ptfd, &rfds)) { + bl = read(ptfd, b, sizeof b); + if (bl <= 0) + break; + teken_input(&t, b, bl); + refresh(); + } + } + + endwin(); + + return (0); +} diff --git a/sys/teken/libteken/Makefile b/sys/teken/libteken/Makefile new file mode 100644 index 0000000..d1c9d3c --- /dev/null +++ b/sys/teken/libteken/Makefile @@ -0,0 +1,39 @@ +# $FreeBSD$ + +LIB= teken +SHLIB_MAJOR= 0 + +CFLAGS+=-I. +WARNS?= 6 + +SRCDIR= ${.CURDIR}/.. +.PATH: ${SRCDIR} + +SRCS= teken.c teken_state.h +INCS= teken.h +CLEANFILES=teken_state.h + +MAN= teken.3 +MLINKS= teken.3 teken_256to8.3 \ + teken.3 teken_get_curattr.3 \ + teken.3 teken_get_cursor.3 \ + teken.3 teken_get_defattr.3 \ + teken.3 teken_get_defattr_cons25.3 \ + teken.3 teken_get_sequence.3 \ + teken.3 teken_get_winsize.3 \ + teken.3 teken_init.3 \ + teken.3 teken_input.3 \ + teken.3 teken_set_8bit.3 \ + teken.3 teken_set_cons25.3 \ + teken.3 teken_set_curattr.3 \ + teken.3 teken_set_cursor.3 \ + teken.3 teken_set_defattr.3 \ + teken.3 teken_set_winsize.3 + +teken_state.h: ${SRCDIR}/gensequences ${SRCDIR}/sequences + awk -f ${SRCDIR}/gensequences ${SRCDIR}/sequences > ${.TARGET} + +VERSION_DEF= ${.CURDIR}/../../../lib/libc/Versions.def +SYMBOL_MAPS= ${.CURDIR}/Symbol.map + +.include diff --git a/sys/teken/libteken/Symbol.map b/sys/teken/libteken/Symbol.map new file mode 100644 index 0000000..9a10aba --- /dev/null +++ b/sys/teken/libteken/Symbol.map @@ -0,0 +1,21 @@ +/* + * $FreeBSD$ + */ + +FBSD_1.2 { + teken_256to8; + teken_get_curattr; + teken_get_cursor; + teken_get_defattr; + teken_get_defattr_cons25; + teken_get_sequence; + teken_get_winsize; + teken_init; + teken_input; + teken_set_8bit; + teken_set_cons25; + teken_set_curattr; + teken_set_cursor; + teken_set_defattr; + teken_set_winsize; +}; diff --git a/sys/teken/libteken/teken.3 b/sys/teken/libteken/teken.3 new file mode 100644 index 0000000..bcc0db0 --- /dev/null +++ b/sys/teken/libteken/teken.3 @@ -0,0 +1,220 @@ +.\" Copyright (c) 2011 Ed Schouten +.\" 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$ +.\" +.Dd May 9, 2011 +.Dt TEKEN 3 +.Os +.Sh NAME +.Nm teken +.Nd xterm-like terminal emulation interface +.Sh LIBRARY +.Lb libteken +.Sh SYNOPSIS +.In teken.h +.Ft void +.Fn teken_init "teken_t *t" "const teken_funcs_t *funcs" "void *thunk" +.Ft void +.Fn teken_input "teken_t *t" "const void *buf" "size_t nbytes" +.Ft const teken_pos_t * +.Fn teken_get_winsize "teken_t *t" +.Ft void +.Fn teken_set_winsize "teken_t *t" "const teken_pos_t *size" +.Ft const teken_pos_t * +.Fn teken_get_cursor "teken_t *t" +.Ft void +.Fn teken_set_cursor "teken_t *t" "const teken_pos_t *pos" +.Ft const teken_attr_t * +.Fn teken_get_curattr "teken_t *t" +.Ft void +.Fn teken_set_curattr "teken_t *t" "const teken_attr_t *attr" +.Ft const teken_attr_t * +.Fn teken_get_defattr "teken_t *t" +.Ft void +.Fn teken_set_defattr "teken_t *t" "const teken_attr_t *attr" +.Ft const char * +.Fn teken_get_sequence "teken_t *t" "unsigned int id" +.Ft teken_color_t +.Fn teken_256to8 "teken_color_t color" +.Ft void +.Fn teken_get_defattr_cons25 "teken_t *t" "int *fg" "int *bg" +.Ft void +.Fn teken_set_8bit "teken_t *t" +.Ft void +.Fn teken_set_cons25 "teken_t *t" +.Sh DESCRIPTION +The +.Nm +library implements the input parser of a 256-color xterm-like terminal. +It converts a stream of UTF-8 encoded characters into a series of +primitive drawing instructions that can be used by a console driver or +terminal emulator to render a terminal application. +.Pp +The +.Fn teken_init +function is used to initialize terminal state object +.Fa t , +having type +.Vt teken_t . +The supplied +.Vt teken_funcs_t +structure +.Fa funcs +contains a set of callback functions, which are called when supplying +data to +.Fn teken_input . +The +.Fa thunk +argument stores an arbitrary pointer, which is passed to each invocation +of the callback functions. +.Pp +The +.Vt teken_funcs_t +structure stores the following callbacks: +.Bd -literal -offset indent +typedef struct { + tf_bell_t *tf_bell; /* Audible/visible bell. */ + tf_cursor_t *tf_cursor; /* Move cursor to x/y. */ + tf_putchar_t *tf_putchar; /* Put Unicode character at x/y. */ + tf_fill_t *tf_fill; /* Fill rectangle with character. */ + tf_copy_t *tf_copy; /* Copy rectangle to new location. */ + tf_param_t *tf_param; /* Miscellaneous options. */ + tf_respond_t *tf_respond; /* Send response string to user. */ +} teken_funcs_t; +.Ed +.Pp +All callbacks must be provided, though unimplemented callbacks may some +times be sufficient. +The actual types of these callbacks can be found in +.In teken.h . +.Pp +By default, +.Fn teken_init +initializes the +.Vt teken_t +structure to emulate a terminal having 24 rows and 80 columns. +The +.Fn teken_get_winsize +and +.Fn teken_set_winsize +functions can be used to obtain and modify the dimensions of the +terminal. +.Pp +Even though the cursor position is normally controlled by input of data +through +.Fn teken_input +and returned by the +.Fn tf_cursor +callback, it can be obtained and modified manually using the +.Fn teken_get_cursor +and +.Fn teken_set_cursor +functions. +The same holds for +.Fn teken_get_curattr +and +.Fn teken_set_curattr , +which can be used to change the currently selected font attributes and +foreground and background color. +.Pp +By default, +.Nm +emulates a white-on-black terminal, which means the default foreground +color is white, while the background color is black. +These defaults can be modified using +.Fn teken_get_defattr +and +.Fn teken_set_defattr . +.Pp +The +.Fn teken_get_sequence +function is a utility function that can be used to obtain escape +sequences of special keyboard keys, generated by user input. +The +.Fa id +parameter must be one of the +.Dv TKEY_* +parameters listed in +.In teken.h . +.Sh LEGACY FEATURES +This library also provides a set of functions that shouldn't be used in +any modern applications. +.Pp +The +.Fn teken_256to8 +function converts a color code to one of the 8 primary colors, allowing +the terminal to be rendered on graphics hardware that only supports 8 or +16 colors (e.g. VGA). +.Pp +The +.Fn teken_get_defattr_cons25 +function obtains the default terminal attributes as a pair of foreground +and background colors, using ANSI color numbering. +.Pp +The +.Fn teken_set_8bit +function disables UTF-8 processing and switches to 8-bit character mode, +which can be used to support character sets like CP437 and ISO-8859-1. +.Pp +The +.Fn teken_set_cons25 +function switches terminal emulation to +.Dv cons25 , +which is used by versions of +.Fx +prior to 9.0. +.Sh SECURITY CONSIDERATIONS +The +.Fn tf_respond +callback is used to respond to device status requests commands generated +by an application. +In the past, there have been various security issues, where a malicious +application sends a device status request before termination, causing +the generated response to be interpreted by applications such as +.Xr sh 1 . +.Pp +.Nm +only implements a small subset of responses which are unlikely to cause +any harm. +Still, it is advised to leave +.Fn tf_respond +unimplemented. +.Sh SEE ALSO +.Xr ncurses 3 , +.Xr termcap 3 , +.Xr syscons 4 . +.Sh HISTORY +The +.Nm +library appeared in +.Fx 8.0 , +though it was only available and used inside the kernel. +In +.Fx 9.0 , +the +.Nm +library appeared in userspace. +.Sh AUTHORS +.An Ed Schouten Aq ed@FreeBSD.org diff --git a/sys/teken/stress/Makefile b/sys/teken/stress/Makefile new file mode 100644 index 0000000..7216da0 --- /dev/null +++ b/sys/teken/stress/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +PROG= teken_stress +LDADD= -lteken +MAN= + +WARNS?= 6 + +.include diff --git a/sys/teken/stress/teken_stress.c b/sys/teken/stress/teken_stress.c new file mode 100644 index 0000000..203c35b --- /dev/null +++ b/sys/teken/stress/teken_stress.c @@ -0,0 +1,132 @@ +/*- + * Copyright (c) 2008-2009 Ed Schouten + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include + +#include +#include +#include +#include +#include + +#include + +static tf_bell_t stress_bell; +static tf_cursor_t stress_cursor; +static tf_putchar_t stress_putchar; +static tf_fill_t stress_fill; +static tf_copy_t stress_copy; +static tf_param_t stress_param; +static tf_respond_t stress_respond; + +static teken_funcs_t tf = { + .tf_bell = stress_bell, + .tf_cursor = stress_cursor, + .tf_putchar = stress_putchar, + .tf_fill = stress_fill, + .tf_copy = stress_copy, + .tf_param = stress_param, + .tf_respond = stress_respond, +}; + +static void +stress_bell(void *s __unused) +{ +} + +static void +stress_cursor(void *s __unused, const teken_pos_t *p __unused) +{ +} + +static void +stress_putchar(void *s __unused, const teken_pos_t *p __unused, + teken_char_t c __unused, const teken_attr_t *a __unused) +{ +} + +static void +stress_fill(void *s __unused, const teken_rect_t *r __unused, + teken_char_t c __unused, const teken_attr_t *a __unused) +{ +} + +static void +stress_copy(void *s __unused, const teken_rect_t *r __unused, + const teken_pos_t *p __unused) +{ +} + +static void +stress_param(void *s __unused, int cmd __unused, unsigned int value __unused) +{ +} + +static void +stress_respond(void *s __unused, const void *buf __unused, size_t len __unused) +{ +} + +static const char replacement[] = + { 0x1b, '[', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';' }; + +int +main(int argc __unused, char *argv[] __unused) +{ + teken_t t; + int rnd; + unsigned int i, iteration = 0; + unsigned char buf[2048]; + + rnd = open("/dev/urandom", O_RDONLY); + if (rnd < 0) { + perror("/dev/urandom"); + exit(1); + } + + teken_init(&t, &tf, NULL); + + for (;;) { + if (read(rnd, buf, sizeof buf) != sizeof buf) { + perror("read"); + exit(1); + } + + for (i = 0; i < sizeof buf; i++) { + if (buf[i] >= 0x80) + buf[i] = + replacement[buf[i] % sizeof replacement]; + } + + teken_input(&t, buf, sizeof buf); + + iteration++; + if ((iteration % 10000) == 0) + printf("Processed %u frames\n", iteration); + } +} diff --git a/sys/teken/teken.c b/sys/teken/teken.c index 91d706f..cdc2cb3 100644 --- a/sys/teken/teken.c +++ b/sys/teken/teken.c @@ -32,7 +32,6 @@ #include #include #define teken_assert(x) MPASS(x) -#define teken_printf(x,...) #else /* !(__FreeBSD__ && _KERNEL) */ #include #include @@ -40,14 +39,11 @@ #include #include #define teken_assert(x) assert(x) -#define teken_printf(x,...) do { \ - if (df != NULL) \ - fprintf(df, x, ## __VA_ARGS__); \ -} while (0) -/* debug messages */ -static FILE *df; #endif /* __FreeBSD__ && _KERNEL */ +/* 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. */ @@ -153,12 +149,6 @@ teken_init(teken_t *t, const teken_funcs_t *tf, void *softc) { teken_pos_t tp = { .tp_row = 24, .tp_col = 80 }; -#if !(defined(__FreeBSD__) && defined(_KERNEL)) - df = fopen("teken.log", "w"); - if (df != NULL) - setvbuf(df, NULL, _IOLBF, BUFSIZ); -#endif /* !(__FreeBSD__ && _KERNEL) */ - t->t_funcs = tf; t->t_softc = softc; diff --git a/sys/teken/teken.h b/sys/teken/teken.h index 36cb71a..2feef6e 100644 --- a/sys/teken/teken.h +++ b/sys/teken/teken.h @@ -29,6 +29,8 @@ #ifndef _TEKEN_H_ #define _TEKEN_H_ +#include + /* * libteken: terminal emulation library. * diff --git a/sys/teken/teken_demo.c b/sys/teken/teken_demo.c deleted file mode 100644 index 49397a6..0000000 --- a/sys/teken/teken_demo.c +++ /dev/null @@ -1,354 +0,0 @@ -/*- - * Copyright (c) 2008-2009 Ed Schouten - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#if defined(__FreeBSD__) -#include -#elif defined(__linux__) -#include -#else -#include -#endif - -#include "teken.h" - -static tf_bell_t test_bell; -static tf_cursor_t test_cursor; -static tf_putchar_t test_putchar; -static tf_fill_t test_fill; -static tf_copy_t test_copy; -static tf_param_t test_param; -static tf_respond_t test_respond; - -static teken_funcs_t tf = { - .tf_bell = test_bell, - .tf_cursor = test_cursor, - .tf_putchar = test_putchar, - .tf_fill = test_fill, - .tf_copy = test_copy, - .tf_param = test_param, - .tf_respond = test_respond, -}; - -struct pixel { - teken_char_t c; - teken_attr_t a; -}; - -#define NCOLS 80 -#define NROWS 24 -struct pixel buffer[NCOLS][NROWS]; - -static int ptfd; - -static void -printchar(const teken_pos_t *p) -{ - int y, x, attr = 0; - struct pixel *px; - char str[5] = { 0 }; - - assert(p->tp_row < NROWS); - assert(p->tp_col < NCOLS); - - getyx(stdscr, y, x); - - px = &buffer[p->tp_col][p->tp_row]; - - /* Convert Unicode to UTF-8. */ - if (px->c < 0x80) { - str[0] = px->c; - } else if (px->c < 0x800) { - str[0] = 0xc0 | (px->c >> 6); - str[1] = 0x80 | (px->c & 0x3f); - } else if (px->c < 0x10000) { - str[0] = 0xe0 | (px->c >> 12); - str[1] = 0x80 | ((px->c >> 6) & 0x3f); - str[2] = 0x80 | (px->c & 0x3f); - } else { - str[0] = 0xf0 | (px->c >> 18); - str[1] = 0x80 | ((px->c >> 12) & 0x3f); - str[2] = 0x80 | ((px->c >> 6) & 0x3f); - str[3] = 0x80 | (px->c & 0x3f); - } - - if (px->a.ta_format & TF_BOLD) - attr |= A_BOLD; - if (px->a.ta_format & TF_UNDERLINE) - attr |= A_UNDERLINE; - if (px->a.ta_format & TF_BLINK) - attr |= A_BLINK; - if (px->a.ta_format & TF_REVERSE) - attr |= A_REVERSE; - - bkgdset(attr | COLOR_PAIR(teken_256to8(px->a.ta_fgcolor) + - 8 * teken_256to8(px->a.ta_bgcolor))); - mvaddstr(p->tp_row, p->tp_col, str); - - move(y, x); -} - -static void -test_bell(void *s __unused) -{ - - beep(); -} - -static void -test_cursor(void *s __unused, const teken_pos_t *p) -{ - - move(p->tp_row, p->tp_col); -} - -static void -test_putchar(void *s __unused, const teken_pos_t *p, teken_char_t c, - const teken_attr_t *a) -{ - - buffer[p->tp_col][p->tp_row].c = c; - buffer[p->tp_col][p->tp_row].a = *a; - printchar(p); -} - -static void -test_fill(void *s, const teken_rect_t *r, teken_char_t c, - const teken_attr_t *a) -{ - teken_pos_t p; - - /* Braindead implementation of fill() - just call putchar(). */ - for (p.tp_row = r->tr_begin.tp_row; p.tp_row < r->tr_end.tp_row; p.tp_row++) - for (p.tp_col = r->tr_begin.tp_col; p.tp_col < r->tr_end.tp_col; p.tp_col++) - test_putchar(s, &p, c, a); -} - -static void -test_copy(void *s __unused, const teken_rect_t *r, const teken_pos_t *p) -{ - int nrow, ncol, x, y; /* Has to be signed - >= 0 comparison */ - teken_pos_t d; - - /* - * Copying is a little tricky. We must make sure we do it in - * correct order, to make sure we don't overwrite our own data. - */ - - nrow = r->tr_end.tp_row - r->tr_begin.tp_row; - ncol = r->tr_end.tp_col - r->tr_begin.tp_col; - - if (p->tp_row < r->tr_begin.tp_row) { - /* Copy from top to bottom. */ - if (p->tp_col < r->tr_begin.tp_col) { - /* Copy from left to right. */ - for (y = 0; y < nrow; y++) { - d.tp_row = p->tp_row + y; - for (x = 0; x < ncol; x++) { - d.tp_col = p->tp_col + x; - buffer[d.tp_col][d.tp_row] = - buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; - printchar(&d); - } - } - } else { - /* Copy from right to left. */ - for (y = 0; y < nrow; y++) { - d.tp_row = p->tp_row + y; - for (x = ncol - 1; x >= 0; x--) { - d.tp_col = p->tp_col + x; - buffer[d.tp_col][d.tp_row] = - buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; - printchar(&d); - } - } - } - } else { - /* Copy from bottom to top. */ - if (p->tp_col < r->tr_begin.tp_col) { - /* Copy from left to right. */ - for (y = nrow - 1; y >= 0; y--) { - d.tp_row = p->tp_row + y; - for (x = 0; x < ncol; x++) { - d.tp_col = p->tp_col + x; - buffer[d.tp_col][d.tp_row] = - buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; - printchar(&d); - } - } - } else { - /* Copy from right to left. */ - for (y = nrow - 1; y >= 0; y--) { - d.tp_row = p->tp_row + y; - for (x = ncol - 1; x >= 0; x--) { - d.tp_col = p->tp_col + x; - buffer[d.tp_col][d.tp_row] = - buffer[r->tr_begin.tp_col + x][r->tr_begin.tp_row + y]; - printchar(&d); - } - } - } - } -} - -static void -test_param(void *s __unused, int cmd, unsigned int value) -{ - - switch (cmd) { - case TP_SHOWCURSOR: - curs_set(value); - break; - case TP_KEYPADAPP: - keypad(stdscr, value ? TRUE : FALSE); - break; - } -} - -static void -test_respond(void *s __unused, const void *buf, size_t len) -{ - - write(ptfd, buf, len); -} - -static void -redraw_border(void) -{ - unsigned int i; - - for (i = 0; i < NROWS; i++) - mvaddch(i, NCOLS, '|'); - for (i = 0; i < NCOLS; i++) - mvaddch(NROWS, i, '-'); - - mvaddch(NROWS, NCOLS, '+'); -} - -static void -redraw_all(void) -{ - teken_pos_t tp; - - for (tp.tp_row = 0; tp.tp_row < NROWS; tp.tp_row++) - for (tp.tp_col = 0; tp.tp_col < NCOLS; tp.tp_col++) - printchar(&tp); - - redraw_border(); -} - -int -main(int argc __unused, char *argv[] __unused) -{ - struct winsize ws; - teken_t t; - teken_pos_t tp; - fd_set rfds; - char b[256]; - ssize_t bl; - const int ccolors[8] = { - COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, - COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE - }; - int i, j; - - setlocale(LC_CTYPE, "UTF-8"); - - tp.tp_row = ws.ws_row = NROWS; - tp.tp_col = ws.ws_col = NCOLS; - - switch (forkpty(&ptfd, NULL, NULL, &ws)) { - case -1: - perror("forkpty"); - exit(1); - case 0: - setenv("TERM", "xterm", 1); - setenv("LC_CTYPE", "UTF-8", 0); - execlp("zsh", "-zsh", NULL); - execlp("bash", "-bash", NULL); - execlp("sh", "-sh", NULL); - _exit(1); - } - - teken_init(&t, &tf, NULL); - teken_set_winsize(&t, &tp); - - initscr(); - raw(); - start_color(); - for (i = 0; i < 8; i++) - for (j = 0; j < 8; j++) - init_pair(i + 8 * j, ccolors[i], ccolors[j]); - - redraw_border(); - - FD_ZERO(&rfds); - - for (;;) { - FD_SET(STDIN_FILENO, &rfds); - FD_SET(ptfd, &rfds); - - if (select(ptfd + 1, &rfds, NULL, NULL, NULL) < 0) { - if (errno == EINTR) { - redraw_all(); - refresh(); - continue; - } - break; - } - - if (FD_ISSET(STDIN_FILENO, &rfds)) { - bl = read(STDIN_FILENO, b, sizeof b); - if (bl <= 0) - break; - write(ptfd, b, bl); - } - - if (FD_ISSET(ptfd, &rfds)) { - bl = read(ptfd, b, sizeof b); - if (bl <= 0) - break; - teken_input(&t, b, bl); - refresh(); - } - } - - endwin(); - - return (0); -} diff --git a/sys/teken/teken_stress.c b/sys/teken/teken_stress.c deleted file mode 100644 index 1f1c572..0000000 --- a/sys/teken/teken_stress.c +++ /dev/null @@ -1,132 +0,0 @@ -/*- - * Copyright (c) 2008-2009 Ed Schouten - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include - -#include -#include -#include -#include -#include - -#include "teken.h" - -static tf_bell_t stress_bell; -static tf_cursor_t stress_cursor; -static tf_putchar_t stress_putchar; -static tf_fill_t stress_fill; -static tf_copy_t stress_copy; -static tf_param_t stress_param; -static tf_respond_t stress_respond; - -static teken_funcs_t tf = { - .tf_bell = stress_bell, - .tf_cursor = stress_cursor, - .tf_putchar = stress_putchar, - .tf_fill = stress_fill, - .tf_copy = stress_copy, - .tf_param = stress_param, - .tf_respond = stress_respond, -}; - -static void -stress_bell(void *s __unused) -{ -} - -static void -stress_cursor(void *s __unused, const teken_pos_t *p __unused) -{ -} - -static void -stress_putchar(void *s __unused, const teken_pos_t *p __unused, - teken_char_t c __unused, const teken_attr_t *a __unused) -{ -} - -static void -stress_fill(void *s __unused, const teken_rect_t *r __unused, - teken_char_t c __unused, const teken_attr_t *a __unused) -{ -} - -static void -stress_copy(void *s __unused, const teken_rect_t *r __unused, - const teken_pos_t *p __unused) -{ -} - -static void -stress_param(void *s __unused, int cmd __unused, unsigned int value __unused) -{ -} - -static void -stress_respond(void *s __unused, const void *buf __unused, size_t len __unused) -{ -} - -static const char replacement[] = - { 0x1b, '[', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';' }; - -int -main(int argc __unused, char *argv[] __unused) -{ - teken_t t; - int rnd; - unsigned int i, iteration = 0; - unsigned char buf[2048]; - - rnd = open("/dev/urandom", O_RDONLY); - if (rnd < 0) { - perror("/dev/urandom"); - exit(1); - } - - teken_init(&t, &tf, NULL); - - for (;;) { - if (read(rnd, buf, sizeof buf) != sizeof buf) { - perror("read"); - exit(1); - } - - for (i = 0; i < sizeof buf; i++) { - if (buf[i] >= 0x80) - buf[i] = - replacement[buf[i] % sizeof replacement]; - } - - teken_input(&t, buf, sizeof buf); - - iteration++; - if ((iteration % 10000) == 0) - printf("Processed %u frames\n", iteration); - } -} -- cgit v1.1