tool: support bold headers in Windows

- If virtual terminal processing is enabled in Windows then use ANSI
  escape codes Esc[1m and Esc[22m to turn bold on and off.

Suggested-by: Gisle Vanem

Ref: https://github.com/curl/curl/discussions/11770

Closes https://github.com/curl/curl/pull/12321
This commit is contained in:
Jay Satiro 2023-11-14 04:11:04 -05:00
parent 17162dcb27
commit 8261800f0a
3 changed files with 25 additions and 9 deletions

View File

@ -42,8 +42,8 @@
static char *parse_filename(const char *ptr, size_t len); static char *parse_filename(const char *ptr, size_t len);
#ifdef WIN32 #ifdef WIN32
#define BOLD #define BOLD "\x1b[1m"
#define BOLDOFF #define BOLDOFF "\x1b[22m"
#else #else
#define BOLD "\x1b[1m" #define BOLD "\x1b[1m"
/* Switch off bold by setting "all attributes off" since the explicit /* Switch off bold by setting "all attributes off" since the explicit
@ -212,7 +212,11 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
if(!outs->stream && !tool_create_output_file(outs, per->config)) if(!outs->stream && !tool_create_output_file(outs, per->config))
return CURL_WRITEFUNC_ERROR; return CURL_WRITEFUNC_ERROR;
if(hdrcbdata->global->isatty && hdrcbdata->global->styled_output) if(hdrcbdata->global->isatty &&
#ifdef WIN32
tool_term_has_bold &&
#endif
hdrcbdata->global->styled_output)
value = memchr(ptr, ':', cb); value = memchr(ptr, ':', cb);
if(value) { if(value) {
size_t namelen = value - ptr; size_t namelen = value - ptr;

View File

@ -714,6 +714,8 @@ static struct TerminalSettings {
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#endif #endif
bool tool_term_has_bold;
static void restore_terminal(void) static void restore_terminal(void)
{ {
if(InterlockedExchange(&TerminalSettings.valid, (LONG)FALSE)) if(InterlockedExchange(&TerminalSettings.valid, (LONG)FALSE))
@ -733,16 +735,23 @@ static BOOL WINAPI signal_handler(DWORD type)
static void init_terminal(void) static void init_terminal(void)
{ {
TerminalSettings.hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); TerminalSettings.hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
/* /*
* Enable VT (Virtual Terminal) output. * Enable VT (Virtual Terminal) output.
* Note: VT mode flag can be set on any version of Windows, but VT * Note: VT mode flag can be set on any version of Windows, but VT
* processing only performed on Win10 >= Creators Update) * processing only performed on Win10 >= version 1709 (OS build 16299)
* Creator's Update. Also, ANSI bold on/off supported since then.
*/ */
if((TerminalSettings.hStdOut != INVALID_HANDLE_VALUE) && if(TerminalSettings.hStdOut == INVALID_HANDLE_VALUE ||
GetConsoleMode(TerminalSettings.hStdOut, !GetConsoleMode(TerminalSettings.hStdOut,
&TerminalSettings.dwOutputMode) && &TerminalSettings.dwOutputMode) ||
!(TerminalSettings.dwOutputMode & !curlx_verify_windows_version(10, 0, 16299, PLATFORM_WINNT,
ENABLE_VIRTUAL_TERMINAL_PROCESSING)) { VERSION_GREATER_THAN_EQUAL))
return;
if((TerminalSettings.dwOutputMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING))
tool_term_has_bold = true;
else {
/* The signal handler is set before attempting to change the console mode /* The signal handler is set before attempting to change the console mode
because otherwise a signal would not be caught after the change but because otherwise a signal would not be caught after the change but
before the handler was installed. */ before the handler was installed. */
@ -751,6 +760,7 @@ static void init_terminal(void)
if(SetConsoleMode(TerminalSettings.hStdOut, if(SetConsoleMode(TerminalSettings.hStdOut,
(TerminalSettings.dwOutputMode | (TerminalSettings.dwOutputMode |
ENABLE_VIRTUAL_TERMINAL_PROCESSING))) { ENABLE_VIRTUAL_TERMINAL_PROCESSING))) {
tool_term_has_bold = true;
atexit(restore_terminal); atexit(restore_terminal);
} }
else { else {

View File

@ -70,6 +70,8 @@ extern FILE *tool_stderr;
/* set in win32_init() */ /* set in win32_init() */
extern LARGE_INTEGER tool_freq; extern LARGE_INTEGER tool_freq;
extern bool tool_isVistaOrGreater; extern bool tool_isVistaOrGreater;
/* set in init_terminal() */
extern bool tool_term_has_bold;
#endif #endif
#endif /* HEADER_CURL_TOOL_SETUP_H */ #endif /* HEADER_CURL_TOOL_SETUP_H */