aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto E. Vargas Caballero <k0ga@shike2.com>2013-10-01 21:23:11 +0200
committerRoberto E. Vargas Caballero <k0ga@shike2.com>2013-10-02 21:22:15 +0200
commit7a4eefe87cb7661c8a77286d05b6c3afb467f806 (patch)
tree9ecce302d1acd95238e312a315c211cce5bec4a3
parentc5c2365ab7c7ac2671b6e7d31cc9b0d41636393c (diff)
downloadst-patched-7a4eefe87cb7661c8a77286d05b6c3afb467f806.tar.bz2
st-patched-7a4eefe87cb7661c8a77286d05b6c3afb467f806.tar.xz
st-patched-7a4eefe87cb7661c8a77286d05b6c3afb467f806.zip
Add support for multiple charset definitions
vt100 has support for two defined charset, G0 and G1. Each charset can be defined, but in each moment is selected only one of both charset. This is usually used selecting a national charset in G0 and graphic charset in G1, so you can switch between graphic charset and text charset without losing the national charset already defined. st hasn't support for national charsets, because it is an utf8 based terminal emulator, but it has support for graphic charset because it is heavily used, but it only supports G0, without understanding G1 selection sequences, which causes some programs in some moments can print some garbage in the screen. This patch adds a fake support for multiple charset definitions, where we only support graphic charset and us-ascii charset, but we allow more of one charset definition. This patch allow define G0 until G3 charsets, but only accepts select G0 or G1, and it accepts some national charset definitions but all of them are mapped to us-ascii.
-rw-r--r--st.c82
1 files changed, 55 insertions, 27 deletions
diff --git a/st.c b/st.c
index 84f9abb..77ea0c8 100644
--- a/st.c
+++ b/st.c
@@ -137,6 +137,16 @@ enum term_mode {
137 |MODE_MOUSEMANY, 137 |MODE_MOUSEMANY,
138}; 138};
139 139
140enum charset {
141 CS_GRAPHIC0,
142 CS_GRAPHIC1,
143 CS_UK,
144 CS_USA,
145 CS_MULTI,
146 CS_GER,
147 CS_FIN
148};
149
140enum escape_state { 150enum escape_state {
141 ESC_START = 1, 151 ESC_START = 1,
142 ESC_CSI = 2, 152 ESC_CSI = 2,
@@ -216,6 +226,9 @@ typedef struct {
216 int bot; /* bottom scroll limit */ 226 int bot; /* bottom scroll limit */
217 int mode; /* terminal mode flags */ 227 int mode; /* terminal mode flags */
218 int esc; /* escape state flags */ 228 int esc; /* escape state flags */
229 char trantbl[4]; /* charset table translation */
230 int charset; /* current charset */
231 int icharset; /* selected charset for sequence */
219 bool numlock; /* lock numbers in keyboard */ 232 bool numlock; /* lock numbers in keyboard */
220 bool *tabs; 233 bool *tabs;
221} Term; 234} Term;
@@ -367,6 +380,8 @@ static void tsetmode(bool, bool, int *, int);
367static void tfulldirt(void); 380static void tfulldirt(void);
368static void techo(char *, int); 381static void techo(char *, int);
369static long tdefcolor(int *, int *, int); 382static long tdefcolor(int *, int *, int);
383static void tselcs(void);
384static void tdeftran(char);
370static inline bool match(uint, uint); 385static inline bool match(uint, uint);
371static void ttynew(void); 386static void ttynew(void);
372static void ttyread(void); 387static void ttyread(void);
@@ -1369,6 +1384,8 @@ treset(void) {
1369 term.top = 0; 1384 term.top = 0;
1370 term.bot = term.row - 1; 1385 term.bot = term.row - 1;
1371 term.mode = MODE_WRAP; 1386 term.mode = MODE_WRAP;
1387 memset(term.trantbl, sizeof(term.trantbl), CS_USA);
1388 term.charset = 0;
1372 1389
1373 tclearregion(0, 0, term.col-1, term.row-1); 1390 tclearregion(0, 0, term.col-1, term.row-1);
1374 tmoveto(0, 0); 1391 tmoveto(0, 0);
@@ -2260,6 +2277,33 @@ techo(char *buf, int len) {
2260} 2277}
2261 2278
2262void 2279void
2280tdeftran(char ascii) {
2281 char c, (*bp)[2];
2282 static char tbl[][2] = {
2283 {'0', CS_GRAPHIC0}, {'1', CS_GRAPHIC1}, {'A', CS_UK},
2284 {'B', CS_USA}, {'<', CS_MULTI}, {'K', CS_GER},
2285 {'5', CS_FIN}, {'C', CS_FIN},
2286 {0, 0}
2287 };
2288
2289 for (bp = &tbl[0]; (c = (*bp)[0]) && c != ascii; ++bp)
2290 /* nothing */;
2291
2292 if (c == 0)
2293 fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii);
2294 else
2295 term.trantbl[term.icharset] = (*bp)[1];
2296}
2297
2298void
2299tselcs(void) {
2300 if (term.trantbl[term.charset] == CS_GRAPHIC0)
2301 term.c.attr.mode |= ATTR_GFX;
2302 else
2303 term.c.attr.mode &= ~ATTR_GFX;
2304}
2305
2306void
2263tputc(char *c, int len) { 2307tputc(char *c, int len) {
2264 uchar ascii = *c; 2308 uchar ascii = *c;
2265 bool control = ascii < '\x20' || ascii == 0177; 2309 bool control = ascii < '\x20' || ascii == 0177;
@@ -2351,13 +2395,12 @@ tputc(char *c, int len) {
2351 term.esc = ESC_START; 2395 term.esc = ESC_START;
2352 return; 2396 return;
2353 case '\016': /* SO */ 2397 case '\016': /* SO */
2398 term.charset = 0;
2399 tselcs();
2400 return;
2354 case '\017': /* SI */ 2401 case '\017': /* SI */
2355 /* 2402 term.charset = 1;
2356 * Different charsets are hard to handle. Applications 2403 tselcs();
2357 * should use the right alt charset escapes for the
2358 * only reason they still exist: line drawing. The
2359 * rest is incompatible history st should not support.
2360 */
2361 return; 2404 return;
2362 case '\032': /* SUB */ 2405 case '\032': /* SUB */
2363 case '\030': /* CAN */ 2406 case '\030': /* CAN */
@@ -2385,22 +2428,8 @@ tputc(char *c, int len) {
2385 if(ascii == '\\') 2428 if(ascii == '\\')
2386 strhandle(); 2429 strhandle();
2387 } else if(term.esc & ESC_ALTCHARSET) { 2430 } else if(term.esc & ESC_ALTCHARSET) {
2388 switch(ascii) { 2431 tdeftran(ascii);
2389 case '0': /* Line drawing set */ 2432 tselcs();
2390 term.c.attr.mode |= ATTR_GFX;
2391 break;
2392 case 'B': /* USASCII */
2393 term.c.attr.mode &= ~ATTR_GFX;
2394 break;
2395 case 'A': /* UK (IGNORED) */
2396 case '<': /* multinational charset (IGNORED) */
2397 case '5': /* Finnish (IGNORED) */
2398 case 'C': /* Finnish (IGNORED) */
2399 case 'K': /* German (IGNORED) */
2400 break;
2401 default:
2402 fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii);
2403 }
2404 term.esc = 0; 2433 term.esc = 0;
2405 } else if(term.esc & ESC_TEST) { 2434 } else if(term.esc & ESC_TEST) {
2406 if(ascii == '8') { /* DEC screen alignment test. */ 2435 if(ascii == '8') { /* DEC screen alignment test. */
@@ -2431,13 +2460,12 @@ tputc(char *c, int len) {
2431 term.esc |= ESC_STR; 2460 term.esc |= ESC_STR;
2432 break; 2461 break;
2433 case '(': /* set primary charset G0 */ 2462 case '(': /* set primary charset G0 */
2463 case ')': /* set secondary charset G1 */
2464 case '*': /* set tertiary charset G2 */
2465 case '+': /* set quaternary charset G3 */
2466 term.icharset = ascii - '(';
2434 term.esc |= ESC_ALTCHARSET; 2467 term.esc |= ESC_ALTCHARSET;
2435 break; 2468 break;
2436 case ')': /* set secondary charset G1 (IGNORED) */
2437 case '*': /* set tertiary charset G2 (IGNORED) */
2438 case '+': /* set quaternary charset G3 (IGNORED) */
2439 term.esc = 0;
2440 break;
2441 case 'D': /* IND -- Linefeed */ 2469 case 'D': /* IND -- Linefeed */
2442 if(term.c.y == term.bot) { 2470 if(term.c.y == term.bot) {
2443 tscrollup(term.top, 1); 2471 tscrollup(term.top, 1);