diff options
author | Ron Yorston <rmy@pobox.com> | 2021-02-03 14:00:14 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-02-03 14:00:14 +0000 |
commit | b108c7bb2181186a5d95d10a6f187c28b4c753f4 (patch) | |
tree | eb6f5e904d2240eb18d249baf594c35de5aade8a | |
parent | ab7a10870d7347056d86eed03f6aca62aaf4d083 (diff) | |
download | busybox-w32-b108c7bb2181186a5d95d10a6f187c28b4c753f4.tar.gz busybox-w32-b108c7bb2181186a5d95d10a6f187c28b4c753f4.tar.bz2 busybox-w32-b108c7bb2181186a5d95d10a6f187c28b4c753f4.zip |
winansi: extend ANSI emulation
Extend ANSI emulation to include:
ESC[38;2;R;G;Bm 24-bit foreground colour
ESC[48;2;R;G;Bm 24-bit background colour
ESC[38;5;Nm 8-bit foreground colour
ESC[48;5;Nm 8-bit background colour
The colours are selected from the 16 standard console colours.
This is unlikely to be aesthetically pleasing but at least it's
better than raw escape sequences.
Also, add ESC[9m (strike through) as a known but unsupported
sequence.
-rw-r--r-- | win32/winansi.c | 226 |
1 files changed, 177 insertions, 49 deletions
diff --git a/win32/winansi.c b/win32/winansi.c index 59292efc3..eda65e62d 100644 --- a/win32/winansi.c +++ b/win32/winansi.c | |||
@@ -262,12 +262,174 @@ static void move_cursor(int x, int y) | |||
262 | SetConsoleCursorPosition(console, pos); | 262 | SetConsoleCursorPosition(console, pos); |
263 | } | 263 | } |
264 | 264 | ||
265 | /* 24-bit colour */ | ||
266 | static char *process_fg_24bit(char *str, WORD *attr) | ||
267 | { | ||
268 | int count = 0; | ||
269 | int val[3] = {0, 0, 0}; | ||
270 | int dark, bright = 0; | ||
271 | |||
272 | do { | ||
273 | val[count++] = strtol(str, (char **)&str, 10); | ||
274 | ++str; | ||
275 | } while (*(str-1) == ';' && count < 3); | ||
276 | |||
277 | *attr &= ~(FOREGROUND_ALL|FOREGROUND_INTENSITY); | ||
278 | if (val[0] > 127) { | ||
279 | *attr |= FOREGROUND_RED; | ||
280 | ++bright; | ||
281 | } | ||
282 | if (val[1] > 127) { | ||
283 | *attr |= FOREGROUND_GREEN; | ||
284 | ++bright; | ||
285 | } | ||
286 | if (val[2] > 127) { | ||
287 | *attr |= FOREGROUND_BLUE; | ||
288 | ++bright; | ||
289 | } | ||
290 | |||
291 | /* increase intensity if all components are either bright or | ||
292 | * dark and at least one is bright */ | ||
293 | dark = (val[0] <= 63) + (val[1] <= 63) + (val[2] <= 63); | ||
294 | if (bright + dark == 3 && dark != 3) { | ||
295 | *attr |= FOREGROUND_INTENSITY; | ||
296 | } | ||
297 | |||
298 | return str; | ||
299 | } | ||
300 | |||
301 | static char *process_bg_24bit(char *str, WORD *attr) | ||
302 | { | ||
303 | WORD t = 0; | ||
304 | char *s = process_fg_24bit(str, &t); | ||
305 | |||
306 | *attr &= ~(BACKGROUND_ALL|BACKGROUND_INTENSITY); | ||
307 | *attr |= t << 4; | ||
308 | |||
309 | return s; | ||
310 | } | ||
311 | |||
312 | static unsigned char colour_1bit[8] = { | ||
313 | /* Black */ 0, | ||
314 | /* Red */ FOREGROUND_RED, | ||
315 | /* Green */ FOREGROUND_GREEN, | ||
316 | /* Yellow */ FOREGROUND_RED | FOREGROUND_GREEN, | ||
317 | /* Blue */ FOREGROUND_BLUE, | ||
318 | /* Magenta */ FOREGROUND_RED | FOREGROUND_BLUE, | ||
319 | /* Cyan */ FOREGROUND_GREEN | FOREGROUND_BLUE, | ||
320 | /* White */ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | ||
321 | }; | ||
322 | |||
323 | /* 8-bit colour */ | ||
324 | static char *process_fg_8bit(char *str, WORD *attr) | ||
325 | { | ||
326 | int dark, bright = 0; | ||
327 | int val = strtol(str, &str, 10); | ||
328 | int r, g, b; | ||
329 | |||
330 | *attr &= ~(FOREGROUND_ALL|FOREGROUND_INTENSITY); | ||
331 | if (val < 16) { | ||
332 | *attr |= colour_1bit[val % 8]; | ||
333 | if (val > 8) | ||
334 | *attr |= FOREGROUND_INTENSITY; | ||
335 | } | ||
336 | else if (val < 232) { | ||
337 | val -= 16; | ||
338 | r = val / 36 % 6; | ||
339 | g = val / 6 % 6; | ||
340 | b = val % 6; | ||
341 | |||
342 | if (r >= 3) { | ||
343 | *attr |= FOREGROUND_RED; | ||
344 | ++bright; | ||
345 | } | ||
346 | if (g >= 3) { | ||
347 | *attr |= FOREGROUND_GREEN; | ||
348 | ++bright; | ||
349 | } | ||
350 | if (b >= 3) { | ||
351 | *attr |= FOREGROUND_BLUE; | ||
352 | ++bright; | ||
353 | } | ||
354 | |||
355 | /* increase intensity if all components are either bright or | ||
356 | * dark and at least one is bright */ | ||
357 | dark = (r <= 1) + (g <= 1) + (b <= 1); | ||
358 | if (bright + dark == 3 && dark != 3) { | ||
359 | *attr |= FOREGROUND_INTENSITY; | ||
360 | } | ||
361 | } | ||
362 | else if (val < 238) { | ||
363 | /* black */ | ||
364 | } | ||
365 | else if (val < 244) { | ||
366 | /* bright black */ | ||
367 | *attr |= FOREGROUND_INTENSITY; | ||
368 | } | ||
369 | else if (val < 250) { | ||
370 | /* white */ | ||
371 | *attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; | ||
372 | } | ||
373 | else { | ||
374 | /* bright white */ | ||
375 | *attr |= FOREGROUND_INTENSITY; | ||
376 | *attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; | ||
377 | } | ||
378 | |||
379 | return str; | ||
380 | } | ||
381 | |||
382 | static char *process_bg_8bit(char *str, WORD *attr) | ||
383 | { | ||
384 | WORD t = 0; | ||
385 | char *s = process_fg_8bit(str, &t); | ||
386 | |||
387 | *attr &= ~(BACKGROUND_ALL|BACKGROUND_INTENSITY); | ||
388 | *attr |= t << 4; | ||
389 | |||
390 | return s; | ||
391 | } | ||
392 | |||
393 | static char *process_fg(char *str, WORD *attr) | ||
394 | { | ||
395 | long val = strtol(str, (char **)&str, 10); | ||
396 | switch (val) { | ||
397 | case 2: | ||
398 | str = process_fg_24bit(++str, attr); | ||
399 | break; | ||
400 | case 5: | ||
401 | str = process_fg_8bit(++str, attr); | ||
402 | break; | ||
403 | default: | ||
404 | break; | ||
405 | } | ||
406 | |||
407 | return str; | ||
408 | } | ||
409 | |||
410 | static char *process_bg(char *str, WORD *attr) | ||
411 | { | ||
412 | long val = strtol(str, (char **)&str, 10); | ||
413 | switch (val) { | ||
414 | case 2: | ||
415 | str = process_bg_24bit(++str, attr); | ||
416 | break; | ||
417 | case 5: | ||
418 | str = process_bg_8bit(++str, attr); | ||
419 | break; | ||
420 | default: | ||
421 | break; | ||
422 | } | ||
423 | |||
424 | return str; | ||
425 | } | ||
426 | |||
265 | /* On input pos points to the start of a suspected escape sequence. | 427 | /* On input pos points to the start of a suspected escape sequence. |
266 | * If a valid sequence is found return a pointer to the character | 428 | * If a valid sequence is found return a pointer to the character |
267 | * following it, otherwise return the original pointer. */ | 429 | * following it, otherwise return the original pointer. */ |
268 | static char *process_escape(char *pos) | 430 | static char *process_escape(char *pos) |
269 | { | 431 | { |
270 | const char *str, *func; | 432 | char *str, *func; |
271 | char *bel; | 433 | char *bel; |
272 | size_t len; | 434 | size_t len; |
273 | WORD attr = get_console_attr(); | 435 | WORD attr = get_console_attr(); |
@@ -341,85 +503,51 @@ static char *process_escape(char *pos) | |||
341 | inverse = 0; | 503 | inverse = 0; |
342 | break; | 504 | break; |
343 | case 8: /* conceal */ | 505 | case 8: /* conceal */ |
506 | case 9: /* strike through */ | ||
344 | case 28: /* reveal */ | 507 | case 28: /* reveal */ |
345 | /* Unsupported */ | 508 | /* Unsupported */ |
346 | break; | 509 | break; |
510 | |||
511 | /* Foreground colours */ | ||
347 | case 30: /* Black */ | 512 | case 30: /* Black */ |
348 | attr &= ~FOREGROUND_ALL; | ||
349 | break; | ||
350 | case 31: /* Red */ | 513 | case 31: /* Red */ |
351 | attr &= ~FOREGROUND_ALL; | ||
352 | attr |= FOREGROUND_RED; | ||
353 | break; | ||
354 | case 32: /* Green */ | 514 | case 32: /* Green */ |
355 | attr &= ~FOREGROUND_ALL; | ||
356 | attr |= FOREGROUND_GREEN; | ||
357 | break; | ||
358 | case 33: /* Yellow */ | 515 | case 33: /* Yellow */ |
359 | attr &= ~FOREGROUND_ALL; | ||
360 | attr |= FOREGROUND_RED | FOREGROUND_GREEN; | ||
361 | break; | ||
362 | case 34: /* Blue */ | 516 | case 34: /* Blue */ |
363 | attr &= ~FOREGROUND_ALL; | ||
364 | attr |= FOREGROUND_BLUE; | ||
365 | break; | ||
366 | case 35: /* Magenta */ | 517 | case 35: /* Magenta */ |
367 | attr &= ~FOREGROUND_ALL; | ||
368 | attr |= FOREGROUND_RED | FOREGROUND_BLUE; | ||
369 | break; | ||
370 | case 36: /* Cyan */ | 518 | case 36: /* Cyan */ |
371 | attr &= ~FOREGROUND_ALL; | ||
372 | attr |= FOREGROUND_GREEN | FOREGROUND_BLUE; | ||
373 | break; | ||
374 | case 37: /* White */ | 519 | case 37: /* White */ |
375 | attr |= FOREGROUND_RED | | 520 | attr &= ~FOREGROUND_ALL; |
376 | FOREGROUND_GREEN | | 521 | attr |= colour_1bit[val - 30]; |
377 | FOREGROUND_BLUE; | ||
378 | break; | 522 | break; |
379 | case 38: /* Unknown */ | 523 | case 38: /* 8/24 bit */ |
524 | str = process_fg(++str, &attr); | ||
380 | break; | 525 | break; |
381 | case 39: /* reset */ | 526 | case 39: /* reset */ |
382 | attr &= ~FOREGROUND_ALL; | 527 | attr &= ~FOREGROUND_ALL; |
383 | attr |= (plain_attr & FOREGROUND_ALL); | 528 | attr |= (plain_attr & FOREGROUND_ALL); |
384 | break; | 529 | break; |
530 | |||
531 | /* Background colours */ | ||
385 | case 40: /* Black */ | 532 | case 40: /* Black */ |
386 | attr &= ~BACKGROUND_ALL; | ||
387 | break; | ||
388 | case 41: /* Red */ | 533 | case 41: /* Red */ |
389 | attr &= ~BACKGROUND_ALL; | ||
390 | attr |= BACKGROUND_RED; | ||
391 | break; | ||
392 | case 42: /* Green */ | 534 | case 42: /* Green */ |
393 | attr &= ~BACKGROUND_ALL; | ||
394 | attr |= BACKGROUND_GREEN; | ||
395 | break; | ||
396 | case 43: /* Yellow */ | 535 | case 43: /* Yellow */ |
397 | attr &= ~BACKGROUND_ALL; | ||
398 | attr |= BACKGROUND_RED | BACKGROUND_GREEN; | ||
399 | break; | ||
400 | case 44: /* Blue */ | 536 | case 44: /* Blue */ |
401 | attr &= ~BACKGROUND_ALL; | ||
402 | attr |= BACKGROUND_BLUE; | ||
403 | break; | ||
404 | case 45: /* Magenta */ | 537 | case 45: /* Magenta */ |
405 | attr &= ~BACKGROUND_ALL; | ||
406 | attr |= BACKGROUND_RED | BACKGROUND_BLUE; | ||
407 | break; | ||
408 | case 46: /* Cyan */ | 538 | case 46: /* Cyan */ |
409 | attr &= ~BACKGROUND_ALL; | ||
410 | attr |= BACKGROUND_GREEN | BACKGROUND_BLUE; | ||
411 | break; | ||
412 | case 47: /* White */ | 539 | case 47: /* White */ |
413 | attr |= BACKGROUND_RED | | 540 | attr &= ~BACKGROUND_ALL; |
414 | BACKGROUND_GREEN | | 541 | attr |= colour_1bit[val - 40] << 4; |
415 | BACKGROUND_BLUE; | ||
416 | break; | 542 | break; |
417 | case 48: /* Unknown */ | 543 | case 48: /* 8/24 bit */ |
544 | str = process_bg(++str, &attr); | ||
418 | break; | 545 | break; |
419 | case 49: /* reset */ | 546 | case 49: /* reset */ |
420 | attr &= ~BACKGROUND_ALL; | 547 | attr &= ~BACKGROUND_ALL; |
421 | attr |= (plain_attr & BACKGROUND_ALL); | 548 | attr |= (plain_attr & BACKGROUND_ALL); |
422 | break; | 549 | break; |
550 | |||
423 | default: | 551 | default: |
424 | /* Unsupported code */ | 552 | /* Unsupported code */ |
425 | return pos; | 553 | return pos; |