diff options
author | Avi Halachmi (:avih) <avihpit@yahoo.com> | 2020-04-13 08:11:39 +0300 |
---|---|---|
committer | Avi Halachmi (:avih) <avihpit@yahoo.com> | 2020-04-23 17:02:38 +0300 |
commit | 67b7a8adaff99c7e55b7448fe9eca071efeeec49 (patch) | |
tree | d8de0fb1cde32b806c22bd635b3d6ef79997b151 | |
parent | da314d3db2ccd40d734e03aa45aa84c2fafc0530 (diff) | |
download | mpv-67b7a8adaff99c7e55b7448fe9eca071efeeec49.tar.bz2 mpv-67b7a8adaff99c7e55b7448fe9eca071efeeec49.tar.xz |
win32: improve console SGR escape sequence emulation
Previously an SGR sequence was emulated correctly only if:
- It had exactly 1 or 2 numeric values (not 0).
- Only reset, bold, and foreground colors were supported.
- 256/true colors were not skipped correctly with their sub-values.
Now it supports the same as before, plus:
- 0-16 (inclusive) numeric values, e.g. \e[m now resets correctly.
- Supports also codes for background color, reverse, underline* .
- Supports also codes for default intensity/fg/bg/reverse/underline.
- 256/true colors are recognized and skipped gracefully.
* Reverse/underline seem to work only on windows 10.
-rw-r--r-- | osdep/terminal-win.c | 61 |
1 files changed, 50 insertions, 11 deletions
diff --git a/osdep/terminal-win.c b/osdep/terminal-win.c index 3b3a3ea935..3800ea13d6 100644 --- a/osdep/terminal-win.c +++ b/osdep/terminal-win.c @@ -39,8 +39,9 @@ #define hSTDERR GetStdHandle(STD_ERROR_HANDLE) #define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) +#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE) -static short stdoutAttrs = 0; +static short stdoutAttrs = 0; // copied from the screen buffer on init static const unsigned char ansi2win32[8] = { 0, FOREGROUND_RED, @@ -51,6 +52,16 @@ static const unsigned char ansi2win32[8] = { FOREGROUND_BLUE | FOREGROUND_GREEN, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED, }; +static const unsigned char ansi2win32bg[8] = { + 0, + BACKGROUND_RED, + BACKGROUND_GREEN, + BACKGROUND_GREEN | BACKGROUND_RED, + BACKGROUND_BLUE, + BACKGROUND_BLUE | BACKGROUND_RED, + BACKGROUND_BLUE | BACKGROUND_GREEN, + BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED, +}; static bool running; static HANDLE death; @@ -193,9 +204,9 @@ void mp_write_console_ansi(HANDLE wstream, char *buf) // "\033[" [ <i> (';' <i> )* ] <c> // where <i> are integers, and <c> a single char command code. // Also see: http://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes - int params[2] = {-1, -1}; // 'm' might be unlimited; ignore that + int params[16]; // 'm' might be unlimited; ignore that int num_params = 0; - while (num_params < 2) { + while (num_params < MP_ARRAY_SIZE(params)) { char *end = next; long p = strtol(next, &end, 10); if (end == next) @@ -225,20 +236,48 @@ void mp_write_console_ansi(HANDLE wstream, char *buf) break; } case 'm': { // "SGR" + short attr = info.wAttributes; + if (num_params == 0) // reset + params[num_params++] = 0; + + // we don't emulate italic, reverse/underline don't always work for (int n = 0; n < num_params; n++) { int p = params[n]; if (p == 0) { - info.wAttributes = stdoutAttrs; - SetConsoleTextAttribute(wstream, info.wAttributes); + attr = stdoutAttrs; } else if (p == 1) { - info.wAttributes |= FOREGROUND_INTENSITY; - SetConsoleTextAttribute(wstream, info.wAttributes); - } else if (p >= 30 && p < 38) { - info.wAttributes &= ~FOREGROUND_ALL; - info.wAttributes |= ansi2win32[p - 30]; - SetConsoleTextAttribute(wstream, info.wAttributes); + attr |= FOREGROUND_INTENSITY; + } else if (p == 22) { + attr &= ~FOREGROUND_INTENSITY; + } else if (p == 4) { + attr |= COMMON_LVB_UNDERSCORE; + } else if (p == 24) { + attr &= ~COMMON_LVB_UNDERSCORE; + } else if (p == 7) { + attr |= COMMON_LVB_REVERSE_VIDEO; + } else if (p == 27) { + attr &= ~COMMON_LVB_REVERSE_VIDEO; + } else if (p >= 30 && p <= 37) { + attr &= ~FOREGROUND_ALL; + attr |= ansi2win32[p - 30]; + } else if (p == 39) { + attr &= ~FOREGROUND_ALL; + attr |= stdoutAttrs & FOREGROUND_ALL; + } else if (p >= 40 && p <= 47) { + attr &= ~BACKGROUND_ALL; + attr |= ansi2win32bg[p - 40]; + } else if (p == 49) { + attr &= ~BACKGROUND_ALL; + attr |= stdoutAttrs & BACKGROUND_ALL; + } else if (p == 38 || p == 48) { // ignore and skip sub-values + // 256 colors: <38/48>;5;N true colors: <38/48>;2;R;G;B + if (n+1 < num_params) + n += params[n+1] == 5 ? 2 : 2 ? 4 : 0; } } + + if (attr != info.wAttributes) + SetConsoleTextAttribute(wstream, attr); break; } } |