Properly implement the VT100 SCS sequences in xterm-mode.

Even though VT100-like devices can display non-ASCII characters, they do
not use an 8-bit character set. Special escape sequences allow the VT100
to switch character maps. The special graphics character set stores the
box drawing characters, starting at 0x60, ending at 0x7e. This means
we now pass the character map tests in vttest, even the save/restore
cursor test, combined with character maps. dialog(1) also works a lot
better now.

This commit also includes some other minor fixes:

- Default to 24 lines in teken_demo when using xterm emulation.
- Make white foreground and background work in teken_demo.
This commit is contained in:
Ed Schouten 2009-01-20 11:34:28 +00:00
parent b1a4c8e522
commit 4873b07e2a
6 changed files with 201 additions and 31 deletions

View File

@ -71,6 +71,16 @@ 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
@ -81,16 +91,6 @@ NEL Next line ^[ E
RI Reverse index ^[ M
RIS Reset to Initial State ^[ c
RM Reset Mode ^[ [ l r
SCS SCS ^[ ( 0
SCS SCS ^[ ( 1
SCS SCS ^[ ( 2
SCS SCS ^[ ( A
SCS SCS ^[ ( B
SCS SCS ^[ ) 0
SCS SCS ^[ ) 1
SCS SCS ^[ ) 2
SCS SCS ^[ ) A
SCS SCS ^[ ) B
SD Pan Up ^[ [ T n
SGR Set Graphic Rendition ^[ [ m v
SM Set Mode ^[ [ h r

View File

@ -49,21 +49,27 @@ static FILE *df;
#endif /* __FreeBSD__ && _KERNEL */
#include "teken.h"
#ifdef TEKEN_UTF8
#include "teken_wcwidth.h"
#else /* !TEKEN_UTF8 */
static inline int
teken_wcwidth(teken_char_t c __unused)
{
#ifdef TEKEN_XTERM
return (c <= 0x1B) ? -1 : 1;
#define teken_wcwidth(c) ((c <= 0x1B) ? -1 : 1)
#else /* !TEKEN_XTERM */
return (1);
#define teken_wcwidth(c) (1)
#endif /* TEKEN_XTERM */
}
#endif /* TEKEN_UTF8 */
#if defined(TEKEN_XTERM) && defined(TEKEN_UTF8)
#include "teken_scs.h"
#else /* !(TEKEN_XTERM && TEKEN_UTF8) */
#define teken_scs_process(t, c) (c)
#define teken_scs_restore(t)
#define teken_scs_save(t)
#define teken_scs_set(t, g, ts)
#define teken_scs_switch(t, g)
#endif /* TEKEN_XTERM && TEKEN_UTF8 */
/* Private flags for teken_format_t. */
#define TF_REVERSE 0x08
@ -229,6 +235,14 @@ teken_input_char(teken_t *t, teken_char_t c)
case '\x0C':
teken_subr_newpage(t);
break;
#if defined(TEKEN_XTERM) && defined(TEKEN_UTF8)
case '\x0E':
teken_scs_switch(t, 1);
break;
case '\x0F':
teken_scs_switch(t, 0);
break;
#endif /* TEKEN_XTERM && TEKEN_UTF8 */
case '\r':
teken_subr_carriage_return(t);
break;

View File

@ -117,6 +117,10 @@ typedef struct {
tf_respond_t *tf_respond;
} teken_funcs_t;
#if defined(TEKEN_XTERM) && defined(TEKEN_UTF8)
typedef teken_char_t teken_scs_t(teken_char_t);
#endif /* TEKEN_XTERM && TEKEN_UTF8 */
/*
* Terminal state.
*/
@ -146,12 +150,18 @@ struct __teken {
teken_span_t t_originreg;
#define T_NUMCOL 160
unsigned int t_tabstops[T_NUMCOL / (sizeof(unsigned int) * 8)];
unsigned int t_tabstops[T_NUMCOL / (sizeof(unsigned int) * 8)];
#ifdef TEKEN_UTF8
unsigned int t_utf8_left;
teken_char_t t_utf8_partial;
unsigned int t_utf8_left;
teken_char_t t_utf8_partial;
#endif /* TEKEN_UTF8 */
#if defined(TEKEN_XTERM) && defined(TEKEN_UTF8)
unsigned int t_curscs;
teken_scs_t *t_saved_curscs;
teken_scs_t *t_scs[2];
#endif /* TEKEN_XTERM && TEKEN_UTF8 */
};
/* Initialize teken structure. */

View File

@ -70,7 +70,11 @@ struct pixel {
};
#define NCOLS 80
#ifdef TEKEN_XTERM
#define NROWS 24
#else /* !TEKEN_XTERM */
#define NROWS 25
#endif /* TEKEN_XTERM */
struct pixel buffer[NCOLS][NROWS];
static int ptfd;
@ -104,7 +108,7 @@ printchar(const teken_pos_t *p)
if (px->a.ta_format & TF_BLINK)
attr |= A_BLINK;
bkgdset(attr | COLOR_PAIR(px->a.ta_fgcolor + 8 * px->a.ta_bgcolor + 1));
bkgdset(attr | COLOR_PAIR(px->a.ta_fgcolor + 8 * px->a.ta_bgcolor));
mvaddch(p->tp_row, p->tp_col, px->c);
move(y, x);
@ -301,7 +305,7 @@ main(int argc __unused, char *argv[] __unused)
start_color();
for (i = 0; i < 8; i++)
for (j = 0; j < 8; j++)
init_pair(i + 8 * j + 1, ccolors[i], ccolors[j]);
init_pair(i + 8 * j, ccolors[i], ccolors[j]);
redraw_border();

View File

@ -0,0 +1,98 @@
/*-
* 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$
*/
static void
teken_scs_set(teken_t *t, unsigned int g, teken_scs_t *ts)
{
t->t_scs[g] = ts;
}
static void
teken_scs_switch(teken_t *t, unsigned int g)
{
t->t_curscs = g;
}
static void
teken_scs_restore(teken_t *t)
{
t->t_scs[t->t_curscs] = t->t_saved_curscs;
}
static void
teken_scs_save(teken_t *t)
{
t->t_saved_curscs = t->t_scs[t->t_curscs];
}
static teken_char_t
teken_scs_process(teken_t *t, teken_char_t c)
{
return (t->t_scs[t->t_curscs](c));
}
/* Unicode points for VT100 box drawing. */
static const teken_char_t teken_boxdrawing[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
};
static teken_char_t
teken_scs_special_graphics(teken_char_t c)
{
/* Box drawing. */
if (c >= '`' && c <= '~')
return (teken_boxdrawing[c - '`']);
return (c);
}
static teken_char_t
teken_scs_uk_national(teken_char_t c)
{
/* Pound sign. */
if (c == '#')
return (0xa3);
return (c);
}
static teken_char_t
teken_scs_us_ascii(teken_char_t c)
{
/* No processing. */
return (c);
}

View File

@ -30,6 +30,7 @@ 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)
@ -527,6 +528,48 @@ teken_subr_erase_line(teken_t *t, unsigned int mode)
teken_funcs_fill(t, &r, BLANK, &t->t_curattr);
}
static void
teken_subr_g0_scs_special_graphics(teken_t *t __unused)
{
teken_scs_set(t, 0, teken_scs_special_graphics);
}
static void
teken_subr_g0_scs_uk_national(teken_t *t __unused)
{
teken_scs_set(t, 0, teken_scs_uk_national);
}
static void
teken_subr_g0_scs_us_ascii(teken_t *t __unused)
{
teken_scs_set(t, 0, teken_scs_us_ascii);
}
static void
teken_subr_g1_scs_special_graphics(teken_t *t __unused)
{
teken_scs_set(t, 1, teken_scs_special_graphics);
}
static void
teken_subr_g1_scs_uk_national(teken_t *t __unused)
{
teken_scs_set(t, 1, teken_scs_uk_national);
}
static void
teken_subr_g1_scs_us_ascii(teken_t *t __unused)
{
teken_scs_set(t, 1, teken_scs_us_ascii);
}
static void
teken_subr_horizontal_position_absolute(teken_t *t, unsigned int col)
{
@ -740,6 +783,8 @@ static void
teken_subr_regular_character(teken_t *t, teken_char_t c)
{
int width;
c = teken_scs_process(t, c);
/* XXX: Don't process zero-width characters yet. */
width = teken_wcwidth(c);
@ -877,11 +922,15 @@ static void
teken_subr_do_reset(teken_t *t)
{
t->t_curattr = t->t_saved_curattr = t->t_defattr;
t->t_curattr = t->t_defattr;
t->t_cursor.tp_row = t->t_cursor.tp_col = 0;
t->t_saved_cursor = t->t_cursor;
t->t_stateflags = TS_AUTOWRAP;
teken_scs_set(t, 0, teken_scs_us_ascii);
teken_scs_set(t, 1, teken_scs_us_ascii);
teken_scs_switch(t, 0);
teken_subr_save_cursor(t);
teken_tab_default(t);
}
@ -902,6 +951,7 @@ teken_subr_restore_cursor(teken_t *t)
t->t_cursor = t->t_saved_cursor;
t->t_curattr = t->t_saved_curattr;
t->t_stateflags &= ~TS_WRAPPED;
teken_scs_restore(t);
teken_funcs_cursor(t);
}
@ -924,13 +974,7 @@ teken_subr_save_cursor(teken_t *t)
t->t_saved_cursor = t->t_cursor;
t->t_saved_curattr = t->t_curattr;
}
static void
teken_subr_scs(teken_t *t __unused)
{
teken_printf("scs???\n");
teken_scs_save(t);
}
static void