diff options
| -rw-r--r-- | st.c | 82 |
1 files changed, 55 insertions, 27 deletions
| @@ -137,6 +137,16 @@ enum term_mode { | |||
| 137 | |MODE_MOUSEMANY, | 137 | |MODE_MOUSEMANY, |
| 138 | }; | 138 | }; |
| 139 | 139 | ||
| 140 | enum charset { | ||
| 141 | CS_GRAPHIC0, | ||
| 142 | CS_GRAPHIC1, | ||
| 143 | CS_UK, | ||
| 144 | CS_USA, | ||
| 145 | CS_MULTI, | ||
| 146 | CS_GER, | ||
| 147 | CS_FIN | ||
| 148 | }; | ||
| 149 | |||
| 140 | enum escape_state { | 150 | enum 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); | |||
| 367 | static void tfulldirt(void); | 380 | static void tfulldirt(void); |
| 368 | static void techo(char *, int); | 381 | static void techo(char *, int); |
| 369 | static long tdefcolor(int *, int *, int); | 382 | static long tdefcolor(int *, int *, int); |
| 383 | static void tselcs(void); | ||
| 384 | static void tdeftran(char); | ||
| 370 | static inline bool match(uint, uint); | 385 | static inline bool match(uint, uint); |
| 371 | static void ttynew(void); | 386 | static void ttynew(void); |
| 372 | static void ttyread(void); | 387 | static 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 | ||
| 2262 | void | 2279 | void |
| 2280 | tdeftran(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 | |||
| 2298 | void | ||
| 2299 | tselcs(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 | |||
| 2306 | void | ||
| 2263 | tputc(char *c, int len) { | 2307 | tputc(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); |
