From 0f85a380c381fa925dd2288a0e2fbe384dcbf0a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Sat, 23 Mar 2024 03:30:43 +0100 Subject: [PATCH] terminal-win: add more control codes support in non-VT mode And skip unsupported private sequences, instead of printing them. --- osdep/terminal-win.c | 82 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 76 insertions(+), 6 deletions(-) diff --git a/osdep/terminal-win.c b/osdep/terminal-win.c index dc8e10407d..238d4b95b7 100644 --- a/osdep/terminal-win.c +++ b/osdep/terminal-win.c @@ -285,6 +285,10 @@ int mp_console_fputs(HANDLE wstream, bstr str) // CSI - Control Sequence Introducer next += 2; + // private sequences + bool priv = next[0] == '?'; + next += priv; + // CSI codes generally follow this syntax: // "\033[" [ (';' )* ] // where are integers, and a single char command code. @@ -308,18 +312,84 @@ int mp_console_fputs(HANDLE wstream, bstr str) CONSOLE_SCREEN_BUFFER_INFO info; GetConsoleScreenBufferInfo(wstream, &info); switch (code) { - case 'K': { // erase to end of line - COORD at = info.dwCursorPosition; - int len = info.dwSize.X - at.X; - FillConsoleOutputCharacterW(wstream, ' ', len, at, &(DWORD){0}); - SetConsoleCursorPosition(wstream, at); + case 'K': { // erase line + COORD cursor_pos = info.dwCursorPosition; + COORD at = cursor_pos; + int len; + switch (num_params ? params[0] : 0) { + case 1: + len = at.X; + at.X = 0; + break; + case 2: + len = info.dwSize.X; + at.X = 0; + break; + case 0: + default: + len = info.dwSize.X - at.X; + } + FillConsoleOutputCharacterW(wstream, L' ', len, at, &(DWORD){0}); + SetConsoleCursorPosition(wstream, cursor_pos); + break; + } + case 'B': { // cursor down + info.dwCursorPosition.Y += !num_params ? 1 : params[0]; + SetConsoleCursorPosition(wstream, info.dwCursorPosition); break; } case 'A': { // cursor up - info.dwCursorPosition.Y -= 1; + info.dwCursorPosition.Y -= !num_params ? 1 : params[0]; SetConsoleCursorPosition(wstream, info.dwCursorPosition); break; } + case 'J': { + // Only full screen clear is supported + if (!num_params || params[0] != 2) + break; + + COORD top_left = {0, 0}; + FillConsoleOutputCharacterW(wstream, L' ', info.dwSize.X * info.dwSize.Y, + top_left, &(DWORD){0}); + SetConsoleCursorPosition(wstream, top_left); + break; + } + case 'f': { + if (num_params != 2) + break; + SetConsoleCursorPosition(wstream, (COORD){params[0], params[1]}); + break; + } + case 'l': { + if (!priv || !num_params) + break; + + switch (params[0]) { + case 25:; // hide the cursor + CONSOLE_CURSOR_INFO cursor_info; + if (!GetConsoleCursorInfo(wstream, &cursor_info)) + break; + cursor_info.bVisible = FALSE; + SetConsoleCursorInfo(wstream, &cursor_info); + break; + } + break; + } + case 'h': { + if (!priv || !num_params) + break; + + switch (params[0]) { + case 25:; // show the cursor + CONSOLE_CURSOR_INFO cursor_info; + if (!GetConsoleCursorInfo(wstream, &cursor_info)) + break; + cursor_info.bVisible = TRUE; + SetConsoleCursorInfo(wstream, &cursor_info); + break; + } + break; + } case 'm': { // "SGR" short attr = info.wAttributes; if (num_params == 0) // reset