mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-03 09:01:42 -05:00
terminal: Implement character set switching
Includes the 3 vt100 character sets. Some of the graphic symbols don't display because they are not included in the default font. Apparantly the cairo toy font API doesn't do font substitution. Signed-off-by: Callum Lowcay <callum@callumscode.com>
This commit is contained in:
parent
69e9658da0
commit
256e72f0e2
1 changed files with 117 additions and 0 deletions
|
|
@ -166,6 +166,69 @@ utf8_next_char(struct utf8_state_machine *machine, char c)
|
||||||
return machine->state;
|
return machine->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct char_sub {
|
||||||
|
union utf8_char match;
|
||||||
|
union utf8_char replace;
|
||||||
|
};
|
||||||
|
/* Set last char_sub match to NULL char */
|
||||||
|
typedef struct char_sub *character_set;
|
||||||
|
|
||||||
|
struct char_sub CS_US[] = {
|
||||||
|
{{{0, }}, {{0, }}}
|
||||||
|
};
|
||||||
|
static struct char_sub CS_UK[] = {
|
||||||
|
{{{'#', 0, }}, {{0xC2, 0xA3, 0, }}},
|
||||||
|
{{{0, }}, {{0, }}}
|
||||||
|
};
|
||||||
|
static struct char_sub CS_SPECIAL[] = {
|
||||||
|
{{{'`', 0, }}, {{0xE2, 0x99, 0xA6, 0}}}, /* diamond */
|
||||||
|
{{{'a', 0, }}, {{0xE2, 0x96, 0x92, 0}}}, /* 50% cell */
|
||||||
|
{{{'b', 0, }}, {{0xE2, 0x90, 0x89, 0}}}, /* HT */
|
||||||
|
{{{'c', 0, }}, {{0xE2, 0x90, 0x8C, 0}}}, /* FF */
|
||||||
|
{{{'d', 0, }}, {{0xE2, 0x90, 0x8D, 0}}}, /* CR */
|
||||||
|
{{{'e', 0, }}, {{0xE2, 0x90, 0x8A, 0}}}, /* LF */
|
||||||
|
{{{'f', 0, }}, {{0xC2, 0xB0, 0, }}}, /* Degree */
|
||||||
|
{{{'g', 0, }}, {{0xC2, 0xB1, 0, }}}, /* Plus/Minus */
|
||||||
|
{{{'h', 0, }}, {{0xE2, 0x90, 0xA4, 0}}}, /* NL */
|
||||||
|
{{{'i', 0, }}, {{0xE2, 0x90, 0x8B, 0}}}, /* VT */
|
||||||
|
{{{'j', 0, }}, {{0xE2, 0x94, 0x98, 0}}}, /* CN_RB */
|
||||||
|
{{{'k', 0, }}, {{0xE2, 0x94, 0x90, 0}}}, /* CN_RT */
|
||||||
|
{{{'l', 0, }}, {{0xE2, 0x94, 0x8C, 0}}}, /* CN_LT */
|
||||||
|
{{{'m', 0, }}, {{0xE2, 0x94, 0x94, 0}}}, /* CN_RB */
|
||||||
|
{{{'n', 0, }}, {{0xE2, 0x94, 0xBC, 0}}}, /* CROSS */
|
||||||
|
{{{'o', 0, }}, {{0xE2, 0x94, 0x80, 0}}}, /* H */
|
||||||
|
{{{'p', 0, }}, {{0xE2, 0x94, 0x80, 0}}}, /* H */
|
||||||
|
{{{'q', 0, }}, {{0xE2, 0x94, 0x80, 0}}}, /* H */
|
||||||
|
{{{'r', 0, }}, {{0xE2, 0x94, 0x80, 0}}}, /* H */
|
||||||
|
{{{'s', 0, }}, {{0xE2, 0x94, 0x80, 0}}}, /* H */
|
||||||
|
{{{'t', 0, }}, {{0xE2, 0x94, 0x9C, 0}}}, /* TR */
|
||||||
|
{{{'u', 0, }}, {{0xE2, 0x94, 0xA4, 0}}}, /* TL */
|
||||||
|
{{{'v', 0, }}, {{0xE2, 0x94, 0xB4, 0}}}, /* TU */
|
||||||
|
{{{'w', 0, }}, {{0xE2, 0x94, 0xAC, 0}}}, /* TD */
|
||||||
|
{{{'x', 0, }}, {{0xE2, 0x94, 0x82, 0}}}, /* V */
|
||||||
|
{{{'y', 0, }}, {{0xE2, 0x89, 0xA4, 0}}}, /* LE */
|
||||||
|
{{{'z', 0, }}, {{0xE2, 0x89, 0xA5, 0}}}, /* GE */
|
||||||
|
{{{'{', 0, }}, {{0xCF, 0x80, 0, }}}, /* PI */
|
||||||
|
{{{'|', 0, }}, {{0xE2, 0x89, 0xA0, 0}}}, /* NEQ */
|
||||||
|
{{{'}', 0, }}, {{0xC2, 0xA3, 0, }}}, /* POUND */
|
||||||
|
{{{'~', 0, }}, {{0xE2, 0x8B, 0x85, 0}}}, /* DOT */
|
||||||
|
{{{0, }}, {{0, }}}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
apply_char_set(character_set cs, union utf8_char *utf8)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (cs[i].match.byte[0]) {
|
||||||
|
if ((*utf8).ch == cs[i].match.ch) {
|
||||||
|
*utf8 = cs[i].replace;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct terminal_color { double r, g, b, a; };
|
struct terminal_color { double r, g, b, a; };
|
||||||
struct attr {
|
struct attr {
|
||||||
unsigned char fg, bg;
|
unsigned char fg, bg;
|
||||||
|
|
@ -202,6 +265,8 @@ struct terminal {
|
||||||
struct attr saved_attr;
|
struct attr saved_attr;
|
||||||
union utf8_char last_char;
|
union utf8_char last_char;
|
||||||
int margin_top, margin_bottom;
|
int margin_top, margin_bottom;
|
||||||
|
character_set cs, g0, g1;
|
||||||
|
character_set saved_cs, saved_g0, saved_g1;
|
||||||
int data_pitch, attr_pitch; /* The width in bytes of a line */
|
int data_pitch, attr_pitch; /* The width in bytes of a line */
|
||||||
int width, height, start, row, column;
|
int width, height, start, row, column;
|
||||||
int saved_row, saved_column;
|
int saved_row, saved_column;
|
||||||
|
|
@ -249,6 +314,14 @@ terminal_init(struct terminal *terminal)
|
||||||
terminal->row = 0;
|
terminal->row = 0;
|
||||||
terminal->column = 0;
|
terminal->column = 0;
|
||||||
|
|
||||||
|
terminal->g0 = CS_US;
|
||||||
|
terminal->g1 = CS_US;
|
||||||
|
terminal->cs = terminal->g0;
|
||||||
|
|
||||||
|
terminal->saved_g0 = terminal->g0;
|
||||||
|
terminal->saved_g1 = terminal->g1;
|
||||||
|
terminal->saved_cs = terminal->cs;
|
||||||
|
|
||||||
terminal->saved_attr = terminal->curr_attr;
|
terminal->saved_attr = terminal->curr_attr;
|
||||||
terminal->saved_origin_mode = terminal->origin_mode;
|
terminal->saved_origin_mode = terminal->origin_mode;
|
||||||
terminal->saved_row = terminal->row;
|
terminal->saved_row = terminal->row;
|
||||||
|
|
@ -714,6 +787,12 @@ handle_term_parameter(struct terminal *terminal, int code, int sr)
|
||||||
|
|
||||||
if (terminal->qmark_flag) {
|
if (terminal->qmark_flag) {
|
||||||
switch(code) {
|
switch(code) {
|
||||||
|
case 2: /* DECANM */
|
||||||
|
/* No VT52 support yet */
|
||||||
|
terminal->g0 = CS_US;
|
||||||
|
terminal->g1 = CS_US;
|
||||||
|
terminal->cs = terminal->g0;
|
||||||
|
break;
|
||||||
case 3: /* DECCOLM */
|
case 3: /* DECCOLM */
|
||||||
if (sr)
|
if (sr)
|
||||||
terminal_resize(terminal, 132, 24);
|
terminal_resize(terminal, 132, 24);
|
||||||
|
|
@ -1147,12 +1226,18 @@ handle_non_csi_escape(struct terminal *terminal, char code)
|
||||||
terminal->saved_column = terminal->column;
|
terminal->saved_column = terminal->column;
|
||||||
terminal->saved_attr = terminal->curr_attr;
|
terminal->saved_attr = terminal->curr_attr;
|
||||||
terminal->saved_origin_mode = terminal->origin_mode;
|
terminal->saved_origin_mode = terminal->origin_mode;
|
||||||
|
terminal->saved_cs = terminal->cs;
|
||||||
|
terminal->saved_g0 = terminal->g0;
|
||||||
|
terminal->saved_g1 = terminal->g1;
|
||||||
break;
|
break;
|
||||||
case '8': /* DECRC */
|
case '8': /* DECRC */
|
||||||
terminal->row = terminal->saved_row;
|
terminal->row = terminal->saved_row;
|
||||||
terminal->column = terminal->saved_column;
|
terminal->column = terminal->saved_column;
|
||||||
terminal->curr_attr = terminal->saved_attr;
|
terminal->curr_attr = terminal->saved_attr;
|
||||||
terminal->origin_mode = terminal->saved_origin_mode;
|
terminal->origin_mode = terminal->saved_origin_mode;
|
||||||
|
terminal->cs = terminal->saved_cs;
|
||||||
|
terminal->g0 = terminal->saved_g0;
|
||||||
|
terminal->g1 = terminal->saved_g1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unknown escape code: %c\n", code);
|
fprintf(stderr, "Unknown escape code: %c\n", code);
|
||||||
|
|
@ -1179,6 +1264,30 @@ handle_special_escape(struct terminal *terminal, char special, char code)
|
||||||
fprintf(stderr, "Unknown HASH escape #%c\n", code);
|
fprintf(stderr, "Unknown HASH escape #%c\n", code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (special == '(' || special == ')') {
|
||||||
|
switch(code) {
|
||||||
|
case '0':
|
||||||
|
if (special == '(')
|
||||||
|
terminal->g0 = CS_SPECIAL;
|
||||||
|
else
|
||||||
|
terminal->g1 = CS_SPECIAL;
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
if (special == '(')
|
||||||
|
terminal->g0 = CS_UK;
|
||||||
|
else
|
||||||
|
terminal->g1 = CS_UK;
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
if (special == '(')
|
||||||
|
terminal->g0 = CS_US;
|
||||||
|
else
|
||||||
|
terminal->g1 = CS_US;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unknown character set %c\n", code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unknown special escape %c%c\n", special, code);
|
fprintf(stderr, "Unknown special escape %c%c\n", special, code);
|
||||||
}
|
}
|
||||||
|
|
@ -1307,6 +1416,12 @@ handle_special_char(struct terminal *terminal, char c)
|
||||||
case '\a':
|
case '\a':
|
||||||
/* Bell */
|
/* Bell */
|
||||||
break;
|
break;
|
||||||
|
case '\x0E': /* SO */
|
||||||
|
terminal->cs = terminal->g1;
|
||||||
|
break;
|
||||||
|
case '\x0F': /* SI */
|
||||||
|
terminal->cs = terminal->g0;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1321,6 +1436,8 @@ handle_char(struct terminal *terminal, union utf8_char utf8)
|
||||||
struct attr *attr_row;
|
struct attr *attr_row;
|
||||||
|
|
||||||
if (handle_special_char(terminal, utf8.byte[0])) return;
|
if (handle_special_char(terminal, utf8.byte[0])) return;
|
||||||
|
|
||||||
|
apply_char_set(terminal->cs, &utf8);
|
||||||
|
|
||||||
/* There are a whole lot of non-characters, control codes,
|
/* There are a whole lot of non-characters, control codes,
|
||||||
* and formatting codes that should probably be ignored,
|
* and formatting codes that should probably be ignored,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue