From d375b450b15ef51648a0b39376cd320df724dba3 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Sun, 24 Sep 2023 23:09:27 +0300 Subject: [PATCH 01/28] Initial Legacy Conhost Support (untested) --- chafa/chafa-canvas-config.h | 1 + tools/chafa/chafa.c | 170 ++++++++++++++++++++++++++++++------ 2 files changed, 143 insertions(+), 28 deletions(-) diff --git a/chafa/chafa-canvas-config.h b/chafa/chafa-canvas-config.h index 73b088d9..db179b6e 100644 --- a/chafa/chafa-canvas-config.h +++ b/chafa/chafa-canvas-config.h @@ -87,6 +87,7 @@ typedef enum CHAFA_PIXEL_MODE_SIXELS, CHAFA_PIXEL_MODE_KITTY, CHAFA_PIXEL_MODE_ITERM2, + CHAFA_PIXEL_MODE_CONHOST, CHAFA_PIXEL_MODE_MAX } diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index ef3d4cc3..28a16eac 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -129,6 +129,10 @@ typedef struct gboolean have_parking_row; ChafaTermInfo *term_info; + + gboolean output_utf_16_on_windows; + gchar * output_codepage; + } GlobalOptions; @@ -219,6 +223,45 @@ safe_WriteConsoleA (HANDLE chd, const gchar *data, gsize len) return TRUE; } +//static gboolean has_dom_been_written = FALSE; +static gboolean +safe_WriteConsoleW (HANDLE chd, const wchar_t *data, gsize len) +{ + gsize total_written = 0; + + if (chd == INVALID_HANDLE_VALUE) + return FALSE; + + while (total_written < len) + { + DWORD n_written = 0; + + if (win32_stdout_is_file) + { + /* WriteFile() and fwrite() seem to work equally well despite various + * claims that the former does poorly in a UTF-8 environment. The + * resulting files look good in my tests, but note that catting them + * out with 'type' introduces lots of artefacts. */ +#if 0 + if (!WriteFile (chd, data, (len - total_written)*2, &n_written, NULL)) + return FALSE; +#else + if ((n_written = fwrite (data, 2, len - total_written, stdout)) < 1) + return FALSE; +#endif + } + else + { + if (!WriteConsoleW (chd, data, len - total_written, &n_written, NULL)) + return FALSE; + } + + data += n_written; + total_written += n_written; + } + + return TRUE; +} #endif static gboolean @@ -226,52 +269,97 @@ write_to_stdout (gconstpointer buf, gsize len) { if (len == 0) return TRUE; + gsize converted_len; + gchar * converted_buf = g_convert( + buf, + len, + #ifdef G_OS_WIN32 + options.output_utf_16_on_windows? + "UTF-16LE": + #endif + options.output_codepage, + "UTF-8", + NULL, + &converted_len, + NULL + ); #ifdef G_OS_WIN32 { - const gchar *p0, *p1, *end; + HANDLE chd = GetStdHandle (STD_OUTPUT_HANDLE); gsize total_written = 0; + if (options.output_utf_16_on_windows){ + + /* + **/ + converted_len /= 2; + const wchar_t *p0, *p1, *end; + for (p0 = (const wchar_t *) converted_buf, end = p0 + converted_len; + chd != INVALID_HANDLE_VALUE && total_written < converted_len; + p0 = p1) + { + p1 = wmemchr (p0, L'\n', end - p0); + if (!p1) + p1 = end; - /* In order for UTF-8 to be handled correctly, we need to use WriteConsoleA() - * on MS Windows. We also convert line feeds to DOS-style CRLF as we go. */ + if (!safe_WriteConsoleW (chd, p0, p1 - p0)) + break; - HANDLE chd = GetStdHandle (STD_OUTPUT_HANDLE); + total_written += p1 - p0; - for (p0 = buf, end = p0 + len; - chd != INVALID_HANDLE_VALUE && total_written < len; - p0 = p1) - { - p1 = memchr (p0, '\n', end - p0); - if (!p1) - p1 = end; + if (p1 != end) + { + if (!safe_WriteConsoleW (chd, L"\r\n", 2)) + break; - if (!safe_WriteConsoleA (chd, p0, p1 - p0)) - break; + p1++; + total_written += 1; + } + } + + } else { - total_written += p1 - p0; + /* In order for UTF-8 to be handled correctly, we need to use WriteConsoleA() + * on MS Windows. We also convert line feeds to DOS-style CRLF as we go. */ - if (p1 != end) + const gchar *p0, *p1, *end; + for (p0 = converted_buf, end = p0 + converted_len; + chd != INVALID_HANDLE_VALUE && total_written < converted_len; + p0 = p1) { - if (!safe_WriteConsoleA (chd, "\r\n", 2)) + p1 = memchr (p0, '\n', end - p0); + if (!p1) + p1 = end; + + if (!safe_WriteConsoleA (chd, p0, p1 - p0)) break; - p1++; - total_written += 1; + total_written += p1 - p0; + + if (p1 != end) + { + if (!safe_WriteConsoleA (chd, "\r\n", 2)) + break; + + p1++; + total_written += 1; + } } - } - return total_written == len ? TRUE : FALSE; + } + return total_written == converted_len ? TRUE : FALSE; } #else { gsize total_written; - for (total_written = 0; total_written < len; ) + for (total_written = 0; total_written < converted_len; ) { - gsize n_written = fwrite (((const gchar *) buf) + total_written, 1, - len - total_written, stdout); + + gsize n_written = fwrite (((const gchar *) converted_buf) + total_written, 1, + converted_len - total_written, stdout); total_written += n_written; - if (total_written < len && n_written == 0 && errno != EINTR) + if (total_written < converted_len && n_written == 0 && errno != EINTR) return FALSE; } } @@ -447,6 +535,9 @@ print_summary (void) " --polite=BOOL Polite mode [on, off]. Inhibits escape sequences that may\n" " confuse other programs. Defaults to off.\n" + " --encoding=ENCODING Set Output Encoding to any encoding supported by iconv\n" + " --utf16 Windows only, output using UTF16 functions,\n" + " required for compatibility with older versions of Windows\n" "\nSize and layout:\n" " -C, --center=BOOL Center images horizontally in view [on, off]. Default off.\n" @@ -1408,12 +1499,20 @@ tty_options_init (void) | DISABLE_NEWLINE_AUTO_RETURN)) win32_stdout_is_file = TRUE; } + if (options.output_codepage != NULL){ + /* Set UTF-8 code page output */ + SetConsoleOutputCP (65001); - /* Set UTF-8 code page output */ - SetConsoleOutputCP (65001); + /* Set UTF-8 code page input, for good measure */ + SetConsoleCP (65001); + } + if ( + options.write_utf_16_on_windows && + (options.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS || options.pixel_mode == CHAFA_PIXEL_MODE_CONHOST) - /* Set UTF-8 code page input, for good measure */ - SetConsoleCP (65001); + ) + safe_WriteConsoleW (chd, L"\xfeff", 1); + } #endif @@ -1673,6 +1772,7 @@ parse_options (int *argc, char **argv []) { "dither-intensity", '\0', 0, G_OPTION_ARG_DOUBLE, &options.dither_intensity, "Dither intensity", NULL }, { "dump-glyph-file", '\0', 0, G_OPTION_ARG_CALLBACK, parse_dump_glyph_file_arg, "Dump glyph file", NULL }, { "duration", 'd', 0, G_OPTION_ARG_CALLBACK, parse_duration_arg, "Duration", NULL }, + { "encoding", '\0', 0, G_OPTION_ARG_STRING, &options.output_codepage, "Encoding", NULL }, { "fg", '\0', 0, G_OPTION_ARG_CALLBACK, parse_fg_color_arg, "Foreground color of display", NULL }, { "fg-only", '\0', 0, G_OPTION_ARG_NONE, &options.fg_only, "Foreground only", NULL }, { "fill", '\0', 0, G_OPTION_ARG_CALLBACK, parse_fill_arg, "Fill symbols", NULL }, @@ -1696,6 +1796,7 @@ parse_options (int *argc, char **argv []) { "symbols", '\0', 0, G_OPTION_ARG_CALLBACK, parse_symbols_arg, "Output symbols", NULL }, { "threads", '\0', 0, G_OPTION_ARG_INT, &options.n_threads, "Number of threads", NULL }, { "threshold", 't', 0, G_OPTION_ARG_DOUBLE, &options.transparency_threshold, "Transparency threshold", NULL }, + { "utf16", '\0', 0, G_OPTION_ARG_NONE, &options.output_utf_16_on_windows, "Use WriteConsoleW instead of WriteConsoleA", NULL}, { "view-size", '\0', 0, G_OPTION_ARG_CALLBACK, parse_view_size_arg, "View size", NULL }, { "watch", '\0', 0, G_OPTION_ARG_NONE, &options.watch, "Watch a file's contents", NULL }, /* Deprecated: Equivalent to --scale max */ @@ -1767,6 +1868,9 @@ parse_options (int *argc, char **argv []) options.anim_fps = -1.0; options.anim_speed_multiplier = 1.0; + options.output_codepage = NULL; + options.output_utf_16_on_windows = FALSE; + if (!g_option_context_parse (context, argc, argv, &error)) { g_printerr ("%s: %s\n", options.executable_name, error->message); @@ -2074,6 +2178,16 @@ parse_options (int *argc, char **argv []) chafa_set_n_threads (options.n_threads); + if (options.output_codepage != NULL){ + /* I don't know of a better way of checking for a valid codepage */ + GIConv converter=g_iconv_open(options.output_codepage, "UTF-8"); + if (result == -1) { + g_printerr ("conversion to '%s' not supported by iconv.\n", options.output_codepage); + goto out; + } else + g_iconv_close(converter); + } + result = TRUE; out: From 58c16d4b26d5e9a325e7f439aea81430c4d67f85 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Mon, 25 Sep 2023 01:12:47 +0300 Subject: [PATCH 02/28] typo --- tools/chafa/chafa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index 28a16eac..d2c8e8b0 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -49,6 +49,7 @@ #ifdef G_OS_WIN32 # ifdef HAVE_WINDOWS_H # include +#include # endif # include #endif @@ -1507,7 +1508,7 @@ tty_options_init (void) SetConsoleCP (65001); } if ( - options.write_utf_16_on_windows && + options.output_utf_16_on_windows && (options.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS || options.pixel_mode == CHAFA_PIXEL_MODE_CONHOST) ) From 6b954a9378ffe8ead952892422497091585b5d7c Mon Sep 17 00:00:00 2001 From: oshaboy Date: Mon, 25 Sep 2023 01:24:35 +0300 Subject: [PATCH 03/28] Update chafa.c --- tools/chafa/chafa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index d2c8e8b0..73433686 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -1500,7 +1500,7 @@ tty_options_init (void) | DISABLE_NEWLINE_AUTO_RETURN)) win32_stdout_is_file = TRUE; } - if (options.output_codepage != NULL){ + if (options.output_codepage == NULL){ /* Set UTF-8 code page output */ SetConsoleOutputCP (65001); From 0d1cc7454ad69a05fdab47c1c44ae86392195755 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Mon, 25 Sep 2023 04:22:14 +0300 Subject: [PATCH 04/28] more stuff I can't figure out how to compile --- tools/chafa/chafa.c | 37 ++++++++++++++++++++++++------------- tools/chafa/file-mapping.c | 2 +- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index 73433686..aab46bd9 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -229,7 +229,6 @@ static gboolean safe_WriteConsoleW (HANDLE chd, const wchar_t *data, gsize len) { gsize total_written = 0; - if (chd == INVALID_HANDLE_VALUE) return FALSE; @@ -270,20 +269,29 @@ write_to_stdout (gconstpointer buf, gsize len) { if (len == 0) return TRUE; - gsize converted_len; - gchar * converted_buf = g_convert( - buf, - len, - #ifdef G_OS_WIN32 + //gsize converted_len; + //const gchar * converted_buf; + #ifndef G_OS_WIN32 + /*Make all utf16 checks compile time on non windows platforms*/ + if (options.output_utf_16_on_windows) __builtin_unreachable(); + //options.output_utf_16_on_windows = FALSE; + #endif + gsize tmp; + if (options.output_codepage!=NULL || options.output_utf_16_on_windows ){ + buf = g_convert( + buf, + len, options.output_utf_16_on_windows? "UTF-16LE": - #endif options.output_codepage, - "UTF-8", - NULL, - &converted_len, - NULL - ); + "UTF-8", + NULL, + &tmp, + NULL + ); + len=tmp; + } + //g_printf("%p %p %s %d\n", buf, converted_buf,options.output_codepage, options.output_utf_16_on_windows); #ifdef G_OS_WIN32 { @@ -2188,7 +2196,10 @@ parse_options (int *argc, char **argv []) } else g_iconv_close(converter); } - + #ifndef G_OS_WIN32 + /*Force it to not output UTF16 when not Windows*/ + options.output_utf_16_on_windows = FALSE; + #endif result = TRUE; out: diff --git a/tools/chafa/file-mapping.c b/tools/chafa/file-mapping.c index ee73fc2d..fece81f5 100644 --- a/tools/chafa/file-mapping.c +++ b/tools/chafa/file-mapping.c @@ -26,7 +26,7 @@ #include #include #include - +#include #ifdef G_OS_WIN32 # include # include From 9ff33881d9729acb16abcdec179e912650a6ef55 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Tue, 26 Sep 2023 16:39:48 +0300 Subject: [PATCH 05/28] some optimization stuff --- tools/chafa/chafa.c | 51 ++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index aab46bd9..9a56e728 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -136,6 +136,11 @@ typedef struct } GlobalOptions; +#ifdef G_OS_WIN32 +#define OUTPUT_UTF_16_ON_WINDOWS options.output_utf_16_on_windows +#else +#define OUTPUT_UTF_16_ON_WINDOWS FALSE +#endif typedef struct { @@ -269,19 +274,15 @@ write_to_stdout (gconstpointer buf, gsize len) { if (len == 0) return TRUE; - //gsize converted_len; - //const gchar * converted_buf; - #ifndef G_OS_WIN32 - /*Make all utf16 checks compile time on non windows platforms*/ - if (options.output_utf_16_on_windows) __builtin_unreachable(); - //options.output_utf_16_on_windows = FALSE; - #endif - gsize tmp; - if (options.output_codepage!=NULL || options.output_utf_16_on_windows ){ + + gboolean did_convert = FALSE; + gboolean result = TRUE; + if (options.output_codepage!=NULL || OUTPUT_UTF_16_ON_WINDOWS ){ + gsize tmp; buf = g_convert( buf, len, - options.output_utf_16_on_windows? + OUTPUT_UTF_16_ON_WINDOWS? "UTF-16LE": options.output_codepage, "UTF-8", @@ -290,9 +291,9 @@ write_to_stdout (gconstpointer buf, gsize len) NULL ); len=tmp; + did_convert = TRUE; } - //g_printf("%p %p %s %d\n", buf, converted_buf,options.output_codepage, options.output_utf_16_on_windows); - + #ifdef G_OS_WIN32 { HANDLE chd = GetStdHandle (STD_OUTPUT_HANDLE); @@ -301,10 +302,10 @@ write_to_stdout (gconstpointer buf, gsize len) /* **/ - converted_len /= 2; + len /= 2; const wchar_t *p0, *p1, *end; - for (p0 = (const wchar_t *) converted_buf, end = p0 + converted_len; - chd != INVALID_HANDLE_VALUE && total_written < converted_len; + for (p0 = (const wchar_t *) buf, end = p0 + len; + chd != INVALID_HANDLE_VALUE && total_written < len; p0 = p1) { p1 = wmemchr (p0, L'\n', end - p0); @@ -332,8 +333,8 @@ write_to_stdout (gconstpointer buf, gsize len) * on MS Windows. We also convert line feeds to DOS-style CRLF as we go. */ const gchar *p0, *p1, *end; - for (p0 = converted_buf, end = p0 + converted_len; - chd != INVALID_HANDLE_VALUE && total_written < converted_len; + for (p0 = buf, end = p0 + len; + chd != INVALID_HANDLE_VALUE && total_written < len; p0 = p1) { p1 = memchr (p0, '\n', end - p0); @@ -356,25 +357,27 @@ write_to_stdout (gconstpointer buf, gsize len) } } - return total_written == converted_len ? TRUE : FALSE; + result = total_written == len ? TRUE : FALSE; } #else { gsize total_written; - for (total_written = 0; total_written < converted_len; ) + for (total_written = 0; total_written < len; ) { - gsize n_written = fwrite (((const gchar *) converted_buf) + total_written, 1, - converted_len - total_written, stdout); + gsize n_written = fwrite (((const gchar *) buf) + total_written, 1, + len - total_written, stdout); total_written += n_written; - if (total_written < converted_len && n_written == 0 && errno != EINTR) - return FALSE; + if (total_written < len && n_written == 0 && errno != EINTR) + result = FALSE; } } - return TRUE; + #endif + if (did_convert) g_free((gchar *)buf); + return result; } static guchar From dd8d462bcffebfc2a653317e07dc0f70c35010d3 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Wed, 27 Sep 2023 23:13:48 +0300 Subject: [PATCH 06/28] moar code --- tools/chafa/chafa.c | 94 +++++++++++------------ tools/chafa/character_canvas_to_conhost.c | 65 ++++++++++++++++ tools/chafa/character_canvas_to_conhost.h | 5 ++ 3 files changed, 115 insertions(+), 49 deletions(-) create mode 100644 tools/chafa/character_canvas_to_conhost.c create mode 100644 tools/chafa/character_canvas_to_conhost.h diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index 9a56e728..1efeb9a3 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -49,7 +49,6 @@ #ifdef G_OS_WIN32 # ifdef HAVE_WINDOWS_H # include -#include # endif # include #endif @@ -190,7 +189,7 @@ interruptible_usleep (gdouble us) * different set of I/O functions. */ static gboolean win32_stdout_is_file = FALSE; -static gboolean +gboolean safe_WriteConsoleA (HANDLE chd, const gchar *data, gsize len) { gsize total_written = 0; @@ -229,9 +228,8 @@ safe_WriteConsoleA (HANDLE chd, const gchar *data, gsize len) return TRUE; } -//static gboolean has_dom_been_written = FALSE; -static gboolean -safe_WriteConsoleW (HANDLE chd, const wchar_t *data, gsize len) +gboolean +safe_WriteConsoleW (HANDLE chd, const guintchar2 *data, gsize len) { gsize total_written = 0; if (chd == INVALID_HANDLE_VALUE) @@ -277,7 +275,7 @@ write_to_stdout (gconstpointer buf, gsize len) gboolean did_convert = FALSE; gboolean result = TRUE; - if (options.output_codepage!=NULL || OUTPUT_UTF_16_ON_WINDOWS ){ + if (options.output_codepage!=NULL || OUTPUT_UTF_16_ON_WINDOWS ){ gsize tmp; buf = g_convert( buf, @@ -298,64 +296,49 @@ write_to_stdout (gconstpointer buf, gsize len) { HANDLE chd = GetStdHandle (STD_OUTPUT_HANDLE); gsize total_written = 0; + gboolean (*safe_WriteConsole)(HANDLE, void *, gsize); + gint stride; + void * newline; + /* We need to select whether to use the UTF-8 (Codepage 65001) or UTF-16 semantics */ if (options.output_utf_16_on_windows){ - /* - **/ - len /= 2; - const wchar_t *p0, *p1, *end; - for (p0 = (const wchar_t *) buf, end = p0 + len; - chd != INVALID_HANDLE_VALUE && total_written < len; - p0 = p1) - { - p1 = wmemchr (p0, L'\n', end - p0); - if (!p1) - p1 = end; - - if (!safe_WriteConsoleW (chd, p0, p1 - p0)) - break; - - total_written += p1 - p0; - - if (p1 != end) - { - if (!safe_WriteConsoleW (chd, L"\r\n", 2)) - break; - - p1++; - total_written += 1; - } - } - + stride=2; + safe_WriteConsole=safe_WriteConsoleW; + newline=L"\r\n"; } else { + stride=1; + safe_WriteConsole=safe_WriteConsoleA; + newline="\r\n"; + } + { - /* In order for UTF-8 to be handled correctly, we need to use WriteConsoleA() - * on MS Windows. We also convert line feeds to DOS-style CRLF as we go. */ - + /* on MS Windows. We convert line feeds to DOS-style CRLF as we go. */ const gchar *p0, *p1, *end; for (p0 = buf, end = p0 + len; chd != INVALID_HANDLE_VALUE && total_written < len; p0 = p1) { - p1 = memchr (p0, '\n', end - p0); + if (options.output_utf_16_on_windows) + p1 = wmemchr (p0, L'\n', end - p0); + else + p1 = memchr (p0, '\n', end - p0); if (!p1) p1 = end; - if (!safe_WriteConsoleA (chd, p0, p1 - p0)) + if (!safe_WriteConsole (chd, p0, p1 - p0)) break; - total_written += p1 - p0; + total_written += (p1 - p0)*stride; if (p1 != end) { - if (!safe_WriteConsoleA (chd, "\r\n", 2)) + if (!safe_WriteConsole (chd, newline, 2)) break; - p1++; - total_written += 1; + p1 += stride; + total_written += stride; } } - } result = total_written == len ? TRUE : FALSE; } @@ -890,6 +873,14 @@ parse_format_arg (G_GNUC_UNUSED const gchar *option_name, const gchar *value, G_ { pixel_mode = CHAFA_PIXEL_MODE_ITERM2; } + else if (!strcasecmp (value, "conhost")) + { + #ifdef G_OS_WIN32 + pixel_mode = CHAFA_PIXEL_MODE_CONHOST; + #else + pixel_mode = CHAFA_PIXEL_MODE_SYMBOLS; + #endif + } else { g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, @@ -1503,12 +1494,11 @@ tty_options_init (void) /* Enable ANSI escape sequence parsing etc. on MS Windows command prompt */ if (chd != INVALID_HANDLE_VALUE) - { - if (!SetConsoleMode (chd, - ENABLE_PROCESSED_OUTPUT - | ENABLE_WRAP_AT_EOL_OUTPUT - | ENABLE_VIRTUAL_TERMINAL_PROCESSING - | DISABLE_NEWLINE_AUTO_RETURN)) + { + DWORD bitmask = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; + if (options.pixel_mode != CHAFA_PIXEL_MODE_CONHOST) + bitmask |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN; + if (!SetConsoleMode (chd, bitmask)) win32_stdout_is_file = TRUE; } if (options.output_codepage == NULL){ @@ -2202,7 +2192,13 @@ parse_options (int *argc, char **argv []) #ifndef G_OS_WIN32 /*Force it to not output UTF16 when not Windows*/ options.output_utf_16_on_windows = FALSE; + if (options.pixel_mode == CHAFA_PIXEL_MODE_CONHOST && + (options.mode == CHAFA_CANVAS_MODE_INDEXED_240 || + options.mode == CHAFA_CANVAS_MODE_INDEXED_256 || + options.mode == CHAFA_CANVAS_MODE_TRUECOLOR) + ) options.mode=CHAFA_CANVAS_MODE_INDEXED_16; #endif + result = TRUE; out: diff --git a/tools/chafa/character_canvas_to_conhost.c b/tools/chafa/character_canvas_to_conhost.c new file mode 100644 index 00000000..6e316fc4 --- /dev/null +++ b/tools/chafa/character_canvas_to_conhost.c @@ -0,0 +1,65 @@ +#include "character_canvas_to_conhost.h" + +static gsize unichar_to_utf16(gunichar c, gunichar2 * str){ + if (c>=0x110000 || + (c<0xe000 && c>=0xd800) || + (c%0x10000 >= 0xfffe)) return 0; + if (c<0x10000){ + *str=(gunichar2)c; + return 1; + } else { + const gunichar temp=c-0x10000; + str[0]=(temp>>10)+0xd800; + str[1]=(temp&0x3ff)+0xdc00; + return 2; + } +} + +#define FOREGROUND_ALL FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE +void print_canvas_conhost(const ChafaCanvas * canvas, gbool is_utf16){ + HANDLE outh = GetStdHandle(STD_OUTPUT_HANDLE); + WORD prev_attribute = -1; + const ChafaCanvasConfig * config = chafa_canvas_peek_config(canvas); + const ChafaCanvasMode canvas_mode = chafa_canvas_config_get_canvas_mode(config); + gint width, height; + gchar str[4]; + bool (* safe_WriteConsole)(HANDLE,const void *, DWORD, LPDWORD, LPVOID); + gsize (* unichar_to_utf)(gunichar, void *); + const void * newline; + + if (is_utf16){ + WriteConsoleUTF=safe_WriteConsoleW; + unichar_to_utf=unichar_to_utf16; + newline = L"\r\n"; + } else { + WriteConsoleUTF=safe_WriteConsoleA; + unichar_to_utf=g_unichar_to_utf8; + newline = "\r\n"; + } + chafa_canvas_config_get_geometry(config, &width, &height); + for (int y=0; y +#include +gboolean safe_WriteConsoleA (HANDLE chd, const gchar *data, gsize len); +gboolean safe_WriteConsoleW (HANDLE chd, const guintchar2 *data, gsize len); +void print_canvas_conhost(const ChafaCanvas * canvas, gbool is_utf16); \ No newline at end of file From fcf6e18a386e1bc98fb8a3c07762505d16a861c5 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Tue, 10 Oct 2023 18:09:08 +0300 Subject: [PATCH 07/28] more untested commits. --- tools/chafa/Makefile.am | 3 + tools/chafa/chafa.c | 159 +++++++++++++++++----- tools/chafa/character_canvas_to_conhost.c | 80 ++++++----- tools/chafa/character_canvas_to_conhost.h | 19 ++- 4 files changed, 196 insertions(+), 65 deletions(-) diff --git a/tools/chafa/Makefile.am b/tools/chafa/Makefile.am index 835d999f..6f317135 100644 --- a/tools/chafa/Makefile.am +++ b/tools/chafa/Makefile.am @@ -73,6 +73,9 @@ chafa_LDADD = $(GLIB_LIBS) $(JPEG_LIBS) $(SVG_LIBS) $(TIFF_LIBS) $(WEBP_LIBS) $( if IS_WIN32_BUILD WIN32_LDADD = manifest.o +chafa_SOURCES += \ + character_canvas_to_conhost.c \ + character_canvas_to_conhost.h manifest.o: $(srcdir)/manifest.rc $(WINDRES) -o $@ $(srcdir)/manifest.rc else diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index 1efeb9a3..a3f709b0 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -49,6 +49,8 @@ #ifdef G_OS_WIN32 # ifdef HAVE_WINDOWS_H # include +# include +# include "character_canvas_to_conhost.h" # endif # include #endif @@ -229,7 +231,7 @@ safe_WriteConsoleA (HANDLE chd, const gchar *data, gsize len) } gboolean -safe_WriteConsoleW (HANDLE chd, const guintchar2 *data, gsize len) +safe_WriteConsoleW (HANDLE chd, const gunichar2 *data, gsize len) { gsize total_written = 0; if (chd == INVALID_HANDLE_VALUE) @@ -270,11 +272,11 @@ safe_WriteConsoleW (HANDLE chd, const guintchar2 *data, gsize len) static gboolean write_to_stdout (gconstpointer buf, gsize len) { - if (len == 0) - return TRUE; - gboolean did_convert = FALSE; gboolean result = TRUE; + + if (len == 0) + return TRUE; if (options.output_codepage!=NULL || OUTPUT_UTF_16_ON_WINDOWS ){ gsize tmp; buf = g_convert( @@ -296,12 +298,11 @@ write_to_stdout (gconstpointer buf, gsize len) { HANDLE chd = GetStdHandle (STD_OUTPUT_HANDLE); gsize total_written = 0; - gboolean (*safe_WriteConsole)(HANDLE, void *, gsize); + gboolean (*safe_WriteConsole)(HANDLE, const void *, gsize); gint stride; - void * newline; + const void * newline; /* We need to select whether to use the UTF-8 (Codepage 65001) or UTF-16 semantics */ if (options.output_utf_16_on_windows){ - stride=2; safe_WriteConsole=safe_WriteConsoleW; newline=L"\r\n"; @@ -313,13 +314,13 @@ write_to_stdout (gconstpointer buf, gsize len) { /* on MS Windows. We convert line feeds to DOS-style CRLF as we go. */ - const gchar *p0, *p1, *end; + const gchar * p0, * p1, * end; for (p0 = buf, end = p0 + len; chd != INVALID_HANDLE_VALUE && total_written < len; p0 = p1) { if (options.output_utf_16_on_windows) - p1 = wmemchr (p0, L'\n', end - p0); + p1 = (const gchar *) wmemchr ((const gunichar2 *) p0, L'\n', end - p0); else p1 = memchr (p0, '\n', end - p0); if (!p1) @@ -1513,7 +1514,7 @@ tty_options_init (void) (options.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS || options.pixel_mode == CHAFA_PIXEL_MODE_CONHOST) ) - safe_WriteConsoleW (chd, L"\xfeff", 1); + safe_WriteConsoleW (chd, u"\xfeff", 1); } #endif @@ -2015,7 +2016,8 @@ parse_options (int *argc, char **argv []) /* Now we've established the pixel mode, apply dependent defaults */ - if (options.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS) + if (options.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS || + options.pixel_mode == CHAFA_PIXEL_MODE_CONHOST) { /* Character cell defaults */ @@ -2189,14 +2191,21 @@ parse_options (int *argc, char **argv []) } else g_iconv_close(converter); } - #ifndef G_OS_WIN32 + #ifdef G_OS_WIN32 + if (options.pixel_mode == CHAFA_PIXEL_MODE_CONHOST){ + + options.output_utf_16_on_windows = TRUE; + if (options.mode == CHAFA_CANVAS_MODE_INDEXED_240 || + options.mode == CHAFA_CANVAS_MODE_INDEXED_256 || + options.mode == CHAFA_CANVAS_MODE_TRUECOLOR ) + options.mode=CHAFA_CANVAS_MODE_INDEXED_16; + + } + + #else /*Force it to not output UTF16 when not Windows*/ options.output_utf_16_on_windows = FALSE; - if (options.pixel_mode == CHAFA_PIXEL_MODE_CONHOST && - (options.mode == CHAFA_CANVAS_MODE_INDEXED_240 || - options.mode == CHAFA_CANVAS_MODE_INDEXED_256 || - options.mode == CHAFA_CANVAS_MODE_TRUECOLOR) - ) options.mode=CHAFA_CANVAS_MODE_INDEXED_16; + #endif result = TRUE; @@ -2449,7 +2458,7 @@ write_image (GString **gsa, gint dest_width) out: return result; } - +#if 0 static GString ** build_strings (ChafaPixelType pixel_type, const guint8 *pixels, gint src_width, gint src_height, gint src_rowstride, @@ -2504,7 +2513,6 @@ build_strings (ChafaPixelType pixel_type, const guint8 *pixels, image = chafa_image_new (); chafa_image_set_frame (image, frame); chafa_canvas_set_image (canvas, image, placement_id); - chafa_canvas_print_rows (canvas, options.term_info, &gsa, NULL); chafa_image_unref (image); @@ -2513,7 +2521,74 @@ build_strings (ChafaPixelType pixel_type, const guint8 *pixels, chafa_canvas_config_unref (config); return gsa; } +#endif +static ChafaCanvasConfig * +build_config ( + gint dest_width, gint dest_height, + gboolean is_animation) +{ + ChafaCanvasConfig *config; + config = chafa_canvas_config_new (); + + chafa_canvas_config_set_geometry (config, dest_width, dest_height); + chafa_canvas_config_set_canvas_mode (config, options.mode); + chafa_canvas_config_set_pixel_mode (config, options.pixel_mode); + chafa_canvas_config_set_dither_mode (config, options.dither_mode); + chafa_canvas_config_set_dither_grain_size (config, options.dither_grain_width, options.dither_grain_height); + chafa_canvas_config_set_dither_intensity (config, options.dither_intensity); + chafa_canvas_config_set_color_extractor (config, options.color_extractor); + chafa_canvas_config_set_color_space (config, options.color_space); + chafa_canvas_config_set_fg_color (config, options.fg_color); + chafa_canvas_config_set_bg_color (config, options.bg_color); + chafa_canvas_config_set_preprocessing_enabled (config, options.preprocess); + chafa_canvas_config_set_fg_only_enabled (config, options.fg_only); + chafa_canvas_config_set_passthrough (config, options.passthrough); + if (is_animation + && options.pixel_mode == CHAFA_PIXEL_MODE_KITTY + && !options.transparency_threshold_set) + chafa_canvas_config_set_transparency_threshold (config, 1.0f); + else if (options.transparency_threshold >= 0.0) + chafa_canvas_config_set_transparency_threshold (config, options.transparency_threshold); + + if (options.cell_width > 0 && options.cell_height > 0) + chafa_canvas_config_set_cell_geometry (config, options.cell_width, options.cell_height); + + chafa_canvas_config_set_symbol_map (config, options.symbol_map); + chafa_canvas_config_set_fill_symbol_map (config, options.fill_symbol_map); + + /* Work switch takes values [1..9], we normalize to [0.0..1.0] to + * get the work factor. */ + chafa_canvas_config_set_work_factor (config, (options.work_factor - 1) / 8.0f); + + chafa_canvas_config_set_optimizations (config, options.optimizations); + return config; +} +static ChafaCanvas * +build_canvas (ChafaPixelType pixel_type, const guint8 *pixels, + gint src_width, gint src_height, gint src_rowstride, + const ChafaCanvasConfig * config, + gint placement_id) +{ + ChafaFrame *frame; + ChafaImage *image; + ChafaCanvas *canvas; + canvas = chafa_canvas_new (config); + frame = chafa_frame_new_borrow ((gpointer) pixels, pixel_type, + src_width, src_height, src_rowstride); + image = chafa_image_new (); + chafa_image_set_frame (image, frame); + chafa_canvas_set_image (canvas, image, placement_id); + return canvas; + +} +/* +void destroy_canvas(ChafaCanvas * canvas){ + chafa_frame_unref (canvas->image->frame); + chafa_image_unref (canvas->image); + chafa_canvas_unref (canvas); +} +*/ static void pixel_to_cell_dimensions (gdouble scale, gint cell_width, gint cell_height, @@ -2654,21 +2729,41 @@ run_generic (const gchar *filename, gboolean is_first_file, gboolean is_first_fr options.font_ratio, options.scale >= SCALE_MAX - 0.1 ? TRUE : FALSE, options.stretch); - + ChafaCanvasConfig * cfg = build_config( + dest_width, + dest_height, + is_animation + ); + ChafaCanvas * canvas = build_canvas( + pixel_type, pixels, + src_width, src_height, src_rowstride, cfg, + placement_id >= 0 ? placement_id + ((frame_count++) % 2) : -1 + ); + /* gsa = build_strings (pixel_type, pixels, - src_width, src_height, src_rowstride, - dest_width, dest_height, - is_animation, - placement_id >= 0 ? placement_id + ((frame_count++) % 2) : -1); - - if (!write_image_prologue (is_first_file, is_first_frame, is_animation, dest_height) - || !write_image (gsa, dest_width) - || !write_image_epilogue (dest_width) - || fflush (stdout) != 0) - goto out; - - chafa_free_gstring_array (gsa); + src_width, src_height, src_rowstride, + dest_width, dest_height, + is_animation, + placement_id >= 0 ? placement_id + ((frame_count++) % 2) : -1); + */ + if (options.pixel_mode == CHAFA_PIXEL_MODE_CONHOST){ + CONHOST_LINE * lines; + gsize s; + s=canvas_to_conhost(canvas, &lines); + write_image_conhost(lines, s); + } else { + chafa_canvas_print_rows (canvas, options.term_info, &gsa, NULL); + if (!write_image_prologue (is_first_file, is_first_frame, is_animation, dest_height) + || !write_image (gsa, dest_width) + || !write_image_epilogue (dest_width) + || fflush (stdout) != 0){ + chafa_free_gstring_array (gsa); + goto out; + } + chafa_free_gstring_array (gsa); + } + chafa_canvas_unref(canvas); if (is_animation) { /* Account for time spent converting and printing frame */ diff --git a/tools/chafa/character_canvas_to_conhost.c b/tools/chafa/character_canvas_to_conhost.c index 6e316fc4..75bf7d70 100644 --- a/tools/chafa/character_canvas_to_conhost.c +++ b/tools/chafa/character_canvas_to_conhost.c @@ -15,51 +15,69 @@ static gsize unichar_to_utf16(gunichar c, gunichar2 * str){ } } + #define FOREGROUND_ALL FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE -void print_canvas_conhost(const ChafaCanvas * canvas, gbool is_utf16){ - HANDLE outh = GetStdHandle(STD_OUTPUT_HANDLE); - WORD prev_attribute = -1; - const ChafaCanvasConfig * config = chafa_canvas_peek_config(canvas); - const ChafaCanvasMode canvas_mode = chafa_canvas_config_get_canvas_mode(config); +gsize canvas_to_conhost(ChafaCanvas * canvas, CONHOST_LINE ** lines){ + gint width, height; - gchar str[4]; - bool (* safe_WriteConsole)(HANDLE,const void *, DWORD, LPDWORD, LPVOID); - gsize (* unichar_to_utf)(gunichar, void *); - const void * newline; + ChafaCanvasConfig * config; + ChafaCanvasMode canvas_mode; + - if (is_utf16){ - WriteConsoleUTF=safe_WriteConsoleW; - unichar_to_utf=unichar_to_utf16; - newline = L"\r\n"; - } else { - WriteConsoleUTF=safe_WriteConsoleA; - unichar_to_utf=g_unichar_to_utf8; - newline = "\r\n"; - } + config = chafa_canvas_peek_config(canvas); + canvas_mode = chafa_canvas_config_get_canvas_mode(config); chafa_canvas_config_get_geometry(config, &width, &height); + (*lines)=g_malloc(height*sizeof(CONHOST_LINE)); + for (int y=0; y0) + line->str[line->utf16_string_length++]=*utf16_codes; + if (s==2) + line->str[line->utf16_string_length++]=utf16_codes[1]; if (canvas_mode != CHAFA_CANVAS_MODE_FGBG){ - WORD cur_attribute; gint fg_out, bg_out; chafa_canvas_get_raw_colors_at(canvas,x,y,&fg_out, &bg_out); if (canvas_mode == CHAFA_CANVAS_MODE_FGBG_BGFG) - cur_attribute=bg_out?BACKGROUND_INVERT|FOREGROUND_ALL:FOREGROUND_ALL; + line->attributes[x]=bg_out?COMMON_LVB_REVERSE_VIDEO|FOREGROUND_ALL:FOREGROUND_ALL; else - cur_attribute=(bg_out<<4)|fg_out; - if (cur_attribute==prev_attribute){ - SetConsoleTextAttribute(outh,cur_attribute); - prev_attribute=cur_attribute; - } + line->attributes[x]=(bg_out<<4)|fg_out; } - - gint length=unichar_to_utf(c, str); - WriteConsoleUTF(outh,str,length,NULL, NULL); - } - WriteConsoleUTF(outh, newline,2, NULL, NULL); + line->str=g_realloc(line->str, line->utf16_string_length*sizeof(gunichar2)); + } + return height; +} +void write_image_conhost(const CONHOST_LINE * lines, gsize s){ + HANDLE outh; + COORD curpos; + outh = GetStdHandle(STD_OUTPUT_HANDLE) + { + CONSOLE_SCREEN_BUFFER_INFO bufinfo; + GetConsoleScreenBufferInfo(outh, &bufinfo); + curpos = bufinfo.dwCursorPosition; + } + + for (gsize y=0 ;y #include #include + +typedef WORD attribute; +typedef struct { + gunichar2 * str; + attribute * attributes; + size_t length; + size_t utf16_string_length; +} CONHOST_LINE; gboolean safe_WriteConsoleA (HANDLE chd, const gchar *data, gsize len); -gboolean safe_WriteConsoleW (HANDLE chd, const guintchar2 *data, gsize len); -void print_canvas_conhost(const ChafaCanvas * canvas, gbool is_utf16); \ No newline at end of file +gboolean safe_WriteConsoleW (HANDLE chd, const gunichar2 *data, gsize len); +gsize canvas_to_conhost(ChafaCanvas * canvas, CONHOST_LINE ** lines); +void write_image_conhost(const CONHOST_LINE * lines, gsize s); + +#endif \ No newline at end of file From 4bd65b20b2618b9001f528cf2ee7869cbb0bed12 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Fri, 20 Oct 2023 22:55:10 +0300 Subject: [PATCH 08/28] forgot semicolon --- tools/chafa/character_canvas_to_conhost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/chafa/character_canvas_to_conhost.c b/tools/chafa/character_canvas_to_conhost.c index 75bf7d70..8ba290a8 100644 --- a/tools/chafa/character_canvas_to_conhost.c +++ b/tools/chafa/character_canvas_to_conhost.c @@ -63,7 +63,7 @@ gsize canvas_to_conhost(ChafaCanvas * canvas, CONHOST_LINE ** lines){ void write_image_conhost(const CONHOST_LINE * lines, gsize s){ HANDLE outh; COORD curpos; - outh = GetStdHandle(STD_OUTPUT_HANDLE) + outh = GetStdHandle(STD_OUTPUT_HANDLE); { CONSOLE_SCREEN_BUFFER_INFO bufinfo; GetConsoleScreenBufferInfo(outh, &bufinfo); From ccd0a79f059a8a1f2cc22432090a1dac86135802 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Sat, 4 Nov 2023 21:09:21 +0200 Subject: [PATCH 09/28] I think I solved the conhost and utf16 problems --- chafa/chafa-canvas.c | 4 +- tools/chafa/chafa.c | 48 ++++++++++++----------- tools/chafa/character_canvas_to_conhost.c | 30 ++++++++------ 3 files changed, 46 insertions(+), 36 deletions(-) diff --git a/chafa/chafa-canvas.c b/chafa/chafa-canvas.c index fbb388eb..2fcb045d 100644 --- a/chafa/chafa-canvas.c +++ b/chafa/chafa-canvas.c @@ -1277,7 +1277,7 @@ draw_all_pixels (ChafaCanvas *canvas, ChafaPixelType src_pixel_type, destroy_pixel_canvas (canvas); - if (canvas->config.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS) + if (canvas->config.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS || canvas->config.pixel_mode == CHAFA_PIXEL_MODE_CONHOST) { /* Symbol mode */ @@ -1386,7 +1386,7 @@ chafa_canvas_new (const ChafaCanvasConfig *config) canvas->refs = 1; - if (canvas->config.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS) + if (canvas->config.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS || canvas->config.pixel_mode == CHAFA_PIXEL_MODE_CONHOST) { /* ANSI art */ canvas->width_pixels = canvas->config.width * CHAFA_SYMBOL_WIDTH_PIXELS; diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index 3d383b02..207f4633 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -233,7 +233,6 @@ safe_WriteConsoleA (HANDLE chd, const gchar *data, gsize len) return TRUE; } - gboolean safe_WriteConsoleW (HANDLE chd, const gunichar2 *data, gsize len) { @@ -244,7 +243,6 @@ safe_WriteConsoleW (HANDLE chd, const gunichar2 *data, gsize len) while (total_written < len) { DWORD n_written = 0; - if (win32_stdout_is_file) { /* WriteFile() and fwrite() seem to work equally well despite various @@ -276,14 +274,15 @@ safe_WriteConsoleW (HANDLE chd, const gunichar2 *data, gsize len) static gboolean write_to_stdout (gconstpointer buf, gsize len) { - gboolean did_convert = FALSE; gboolean result = TRUE; - + char * converted_buf=NULL; + const char * chrptr=buf; if (len == 0) return TRUE; if (options.output_codepage!=NULL || OUTPUT_UTF_16_ON_WINDOWS ){ gsize tmp; - buf = g_convert( + + chrptr=buf=converted_buf=g_convert( buf, len, OUTPUT_UTF_16_ON_WINDOWS? @@ -295,7 +294,6 @@ write_to_stdout (gconstpointer buf, gsize len) NULL ); len=tmp; - did_convert = TRUE; } #ifdef G_OS_WIN32 @@ -323,17 +321,17 @@ write_to_stdout (gconstpointer buf, gsize len) chd != INVALID_HANDLE_VALUE && total_written < len; p0 = p1) { - if (options.output_utf_16_on_windows) - p1 = (const gchar *) wmemchr ((const gunichar2 *) p0, L'\n', end - p0); + if (options.output_utf_16_on_windows) + p1 = (const gchar *) wmemchr ((const gunichar2 *) p0, L'\n', (end - p0)/2); else p1 = memchr (p0, '\n', end - p0); if (!p1) p1 = end; - if (!safe_WriteConsole (chd, p0, p1 - p0)) + if (!safe_WriteConsole (chd, p0, (p1 - p0)/stride)) break; - total_written += (p1 - p0)*stride; + total_written += p1 - p0; if (p1 != end) { @@ -364,7 +362,7 @@ write_to_stdout (gconstpointer buf, gsize len) #endif - if (did_convert) g_free((gchar *)buf); + g_free(converted_buf); return result; } @@ -518,7 +516,7 @@ print_summary (void) "\nOutput encoding:\n" - " -f, --format=FORMAT Set output format; one of [iterm, kitty, sixels,\n" + " -f, --format=FORMAT Set output format; one of [conhost,iterm, kitty, sixels,\n" " symbols]. Iterm, kitty and sixels yield much higher\n" " quality but enjoy limited support. Symbols mode yields\n" " beautiful character art.\n" @@ -1622,22 +1620,29 @@ tty_options_init (void) DWORD bitmask = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; if (options.pixel_mode != CHAFA_PIXEL_MODE_CONHOST) bitmask |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN; - if (!SetConsoleMode (chd, bitmask)) - win32_stdout_is_file = TRUE; + if (!SetConsoleMode (chd, bitmask) ){ + if (GetLastError() == ERROR_INVALID_HANDLE) + win32_stdout_is_file = TRUE; + else + /* Compatibility with older Windowses */ + SetConsoleMode (chd,ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT); + + } + } - if (options.output_codepage == NULL){ + if (!options.output_utf_16_on_windows && options.output_codepage == NULL){ /* Set UTF-8 code page output */ SetConsoleOutputCP (65001); /* Set UTF-8 code page input, for good measure */ SetConsoleCP (65001); } - if ( + + if (win32_stdout_is_file && options.output_utf_16_on_windows && (options.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS || options.pixel_mode == CHAFA_PIXEL_MODE_CONHOST) - ) - safe_WriteConsoleW (chd, u"\xfeff", 1); + ) safe_WriteConsoleW (chd, u"\xfeff", 1); } #endif @@ -1659,7 +1664,7 @@ tty_options_init (void) } #endif - if (options.mode != CHAFA_CANVAS_MODE_FGBG) + if (options.mode != CHAFA_CANVAS_MODE_FGBG && options.pixel_mode != CHAFA_PIXEL_MODE_CONHOST) { p0 = chafa_term_info_emit_disable_cursor (options.term_info, buf); write_to_stdout (buf, p0 - buf); @@ -1686,7 +1691,7 @@ tty_options_deinit (void) if (!options.polite) { - if (options.mode != CHAFA_CANVAS_MODE_FGBG) + if (options.mode != CHAFA_CANVAS_MODE_FGBG && options.pixel_mode != CHAFA_PIXEL_MODE_CONHOST) { gchar buf [CHAFA_TERM_SEQ_LENGTH_MAX]; gchar *p0; @@ -2329,13 +2334,11 @@ parse_options (int *argc, char **argv []) options.mode == CHAFA_CANVAS_MODE_INDEXED_256 || options.mode == CHAFA_CANVAS_MODE_TRUECOLOR ) options.mode=CHAFA_CANVAS_MODE_INDEXED_16; - } #else /*Force it to not output UTF16 when not Windows*/ options.output_utf_16_on_windows = FALSE; - #endif result = TRUE; @@ -3054,7 +3057,6 @@ int main (int argc, char *argv []) { int ret; - proc_init (); if (!parse_options (&argc, &argv)) diff --git a/tools/chafa/character_canvas_to_conhost.c b/tools/chafa/character_canvas_to_conhost.c index 8ba290a8..c20d3b57 100644 --- a/tools/chafa/character_canvas_to_conhost.c +++ b/tools/chafa/character_canvas_to_conhost.c @@ -18,17 +18,18 @@ static gsize unichar_to_utf16(gunichar c, gunichar2 * str){ #define FOREGROUND_ALL FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE gsize canvas_to_conhost(ChafaCanvas * canvas, CONHOST_LINE ** lines){ - gint width, height; ChafaCanvasConfig * config; ChafaCanvasMode canvas_mode; - config = chafa_canvas_peek_config(canvas); canvas_mode = chafa_canvas_config_get_canvas_mode(config); chafa_canvas_config_get_geometry(config, &width, &height); (*lines)=g_malloc(height*sizeof(CONHOST_LINE)); - + static const gchar color_lut[16] = { + 0,4,2,6,1,5,3,7, + 8,12,10,14,9,13,11,15 + }; for (int y=0; ystr[line->utf16_string_length++]=*utf16_codes; if (s==2) line->str[line->utf16_string_length++]=utf16_codes[1]; - if (canvas_mode != CHAFA_CANVAS_MODE_FGBG){ + + if (canvas_mode == CHAFA_CANVAS_MODE_FGBG) + line->attributes[x]=FOREGROUND_ALL; + else{ gint fg_out, bg_out; chafa_canvas_get_raw_colors_at(canvas,x,y,&fg_out, &bg_out); if (canvas_mode == CHAFA_CANVAS_MODE_FGBG_BGFG) - line->attributes[x]=bg_out?COMMON_LVB_REVERSE_VIDEO|FOREGROUND_ALL:FOREGROUND_ALL; - else + line->attributes[x]=bg_out?FOREGROUND_ALL:COMMON_LVB_REVERSE_VIDEO|FOREGROUND_ALL; + else { + fg_out=color_lut[fg_out]; + bg_out=color_lut[bg_out]; line->attributes[x]=(bg_out<<4)|fg_out; + } } } @@ -63,6 +70,7 @@ gsize canvas_to_conhost(ChafaCanvas * canvas, CONHOST_LINE ** lines){ void write_image_conhost(const CONHOST_LINE * lines, gsize s){ HANDLE outh; COORD curpos; + DWORD idc; outh = GetStdHandle(STD_OUTPUT_HANDLE); { CONSOLE_SCREEN_BUFFER_INFO bufinfo; @@ -72,12 +80,12 @@ void write_image_conhost(const CONHOST_LINE * lines, gsize s){ for (gsize y=0 ;y Date: Sat, 4 Nov 2023 21:21:57 +0200 Subject: [PATCH 10/28] Build problem on Linux fixed --- tools/chafa/chafa.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index 207f4633..67fe4725 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -276,13 +276,12 @@ write_to_stdout (gconstpointer buf, gsize len) { gboolean result = TRUE; char * converted_buf=NULL; - const char * chrptr=buf; if (len == 0) return TRUE; if (options.output_codepage!=NULL || OUTPUT_UTF_16_ON_WINDOWS ){ gsize tmp; - chrptr=buf=converted_buf=g_convert( + buf=converted_buf=g_convert( buf, len, OUTPUT_UTF_16_ON_WINDOWS? @@ -2877,12 +2876,15 @@ run_generic (const gchar *filename, gboolean is_first_file, gboolean is_first_fr is_animation, placement_id >= 0 ? placement_id + ((frame_count++) % 2) : -1); */ + #ifdef G_OS_WIN32 if (options.pixel_mode == CHAFA_PIXEL_MODE_CONHOST){ CONHOST_LINE * lines; gsize s; s=canvas_to_conhost(canvas, &lines); write_image_conhost(lines, s); - } else { + } else + #endif + { chafa_canvas_print_rows (canvas, options.term_info, &gsa, NULL); if (!write_image_prologue (is_first_file, is_first_frame, is_animation, dest_height) || !write_image (gsa, dest_width) From b38a29a4bbf413a89c3d5c5db03178b65a508160 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Sat, 4 Nov 2023 21:40:43 +0200 Subject: [PATCH 11/28] basic destructor --- tools/chafa/chafa.c | 1 + tools/chafa/character_canvas_to_conhost.c | 8 ++++++++ tools/chafa/character_canvas_to_conhost.h | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index 67fe4725..f0d020e6 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -2882,6 +2882,7 @@ run_generic (const gchar *filename, gboolean is_first_file, gboolean is_first_fr gsize s; s=canvas_to_conhost(canvas, &lines); write_image_conhost(lines, s); + destroy_lines(lines,s); } else #endif { diff --git a/tools/chafa/character_canvas_to_conhost.c b/tools/chafa/character_canvas_to_conhost.c index c20d3b57..f2c1fd34 100644 --- a/tools/chafa/character_canvas_to_conhost.c +++ b/tools/chafa/character_canvas_to_conhost.c @@ -88,4 +88,12 @@ void write_image_conhost(const CONHOST_LINE * lines, gsize s){ curpos.Y++; } +} + +void destroy_lines(const CONHOST_LINE * lines, gsize s){ + for (gsize i=0; i Date: Sat, 4 Nov 2023 21:41:19 +0200 Subject: [PATCH 12/28] const shouldn't be there --- tools/chafa/character_canvas_to_conhost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/chafa/character_canvas_to_conhost.c b/tools/chafa/character_canvas_to_conhost.c index f2c1fd34..3b1b3985 100644 --- a/tools/chafa/character_canvas_to_conhost.c +++ b/tools/chafa/character_canvas_to_conhost.c @@ -90,7 +90,7 @@ void write_image_conhost(const CONHOST_LINE * lines, gsize s){ } } -void destroy_lines(const CONHOST_LINE * lines, gsize s){ +void destroy_lines(CONHOST_LINE * lines, gsize s){ for (gsize i=0; i Date: Sat, 4 Nov 2023 21:51:42 +0200 Subject: [PATCH 13/28] Sanity Check --- tools/chafa/character_canvas_to_conhost.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/chafa/character_canvas_to_conhost.c b/tools/chafa/character_canvas_to_conhost.c index 3b1b3985..0967ff7a 100644 --- a/tools/chafa/character_canvas_to_conhost.c +++ b/tools/chafa/character_canvas_to_conhost.c @@ -22,6 +22,12 @@ gsize canvas_to_conhost(ChafaCanvas * canvas, CONHOST_LINE ** lines){ ChafaCanvasConfig * config; ChafaCanvasMode canvas_mode; + if ( + canvas_mode == CHAFA_CANVAS_MODE_INDEXED_240 || + canvas_mode == CHAFA_CANVAS_MODE_INDEXED_256 || + canvas_mode == CHAFA_CANVAS_MODE_TRUECOLOR + ) return (gsize) -1; + config = chafa_canvas_peek_config(canvas); canvas_mode = chafa_canvas_config_get_canvas_mode(config); chafa_canvas_config_get_geometry(config, &width, &height); From e46fbdd75634a3b3ca42c8655fdec02de8e26035 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Sat, 4 Nov 2023 22:00:35 +0200 Subject: [PATCH 14/28] Does this fix the memory leak? --- tools/chafa/chafa.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index f0d020e6..7009c340 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -2897,7 +2897,10 @@ run_generic (const gchar *filename, gboolean is_first_file, gboolean is_first_fr chafa_free_gstring_array (gsa); } + chafa_frame_unref (canvas->image->frame); + chafa_image_unref (canvas->image); chafa_canvas_unref(canvas); + if (is_animation) { /* Account for time spent converting and printing frame */ From 65b970605b758c2bb0df1111eeb4c2827acfd9ae Mon Sep 17 00:00:00 2001 From: oshaboy Date: Sat, 4 Nov 2023 22:01:08 +0200 Subject: [PATCH 15/28] Revert "Does this fix the memory leak?" This reverts commit e46fbdd75634a3b3ca42c8655fdec02de8e26035. --- tools/chafa/chafa.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index 7009c340..f0d020e6 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -2897,10 +2897,7 @@ run_generic (const gchar *filename, gboolean is_first_file, gboolean is_first_fr chafa_free_gstring_array (gsa); } - chafa_frame_unref (canvas->image->frame); - chafa_image_unref (canvas->image); chafa_canvas_unref(canvas); - if (is_animation) { /* Account for time spent converting and printing frame */ From 5b76a9bee4003b5d4541bc83cbb41ecc1505dc89 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Sat, 4 Nov 2023 22:03:15 +0200 Subject: [PATCH 16/28] Update chafa.c --- tools/chafa/chafa.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index f0d020e6..bd0a4ff4 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -2709,6 +2709,8 @@ build_canvas (ChafaPixelType pixel_type, const guint8 *pixels, image = chafa_image_new (); chafa_image_set_frame (image, frame); chafa_canvas_set_image (canvas, image, placement_id); + chafa_image_unref (image); + chafa_frame_unref (frame); return canvas; } From 7eac28a3a2c939312ba1dfce07ab1cbd5738a080 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Sat, 4 Nov 2023 22:06:49 +0200 Subject: [PATCH 17/28] Update chafa.c --- tools/chafa/chafa.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index bd0a4ff4..a7398dbb 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -2714,13 +2714,7 @@ build_canvas (ChafaPixelType pixel_type, const guint8 *pixels, return canvas; } -/* -void destroy_canvas(ChafaCanvas * canvas){ - chafa_frame_unref (canvas->image->frame); - chafa_image_unref (canvas->image); - chafa_canvas_unref (canvas); -} -*/ + static void pixel_to_cell_dimensions (gdouble scale, gint cell_width, gint cell_height, @@ -2900,6 +2894,7 @@ run_generic (const gchar *filename, gboolean is_first_file, gboolean is_first_fr chafa_free_gstring_array (gsa); } chafa_canvas_unref(canvas); + chafa_canvas_config_unref(cfg); if (is_animation) { /* Account for time spent converting and printing frame */ From 39a261c12a77107a6bff6efa4b4bb8f0abdc5754 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Sat, 4 Nov 2023 22:47:40 +0200 Subject: [PATCH 18/28] few fixes --- tools/chafa/character_canvas_to_conhost.c | 7 ++++--- tools/chafa/character_canvas_to_conhost.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/chafa/character_canvas_to_conhost.c b/tools/chafa/character_canvas_to_conhost.c index 0967ff7a..94d11a7d 100644 --- a/tools/chafa/character_canvas_to_conhost.c +++ b/tools/chafa/character_canvas_to_conhost.c @@ -22,14 +22,15 @@ gsize canvas_to_conhost(ChafaCanvas * canvas, CONHOST_LINE ** lines){ ChafaCanvasConfig * config; ChafaCanvasMode canvas_mode; + + + config = chafa_canvas_peek_config(canvas); + canvas_mode = chafa_canvas_config_get_canvas_mode(config); if ( canvas_mode == CHAFA_CANVAS_MODE_INDEXED_240 || canvas_mode == CHAFA_CANVAS_MODE_INDEXED_256 || canvas_mode == CHAFA_CANVAS_MODE_TRUECOLOR ) return (gsize) -1; - - config = chafa_canvas_peek_config(canvas); - canvas_mode = chafa_canvas_config_get_canvas_mode(config); chafa_canvas_config_get_geometry(config, &width, &height); (*lines)=g_malloc(height*sizeof(CONHOST_LINE)); static const gchar color_lut[16] = { diff --git a/tools/chafa/character_canvas_to_conhost.h b/tools/chafa/character_canvas_to_conhost.h index 0ba69c9c..56695830 100644 --- a/tools/chafa/character_canvas_to_conhost.h +++ b/tools/chafa/character_canvas_to_conhost.h @@ -16,5 +16,5 @@ gboolean safe_WriteConsoleA (HANDLE chd, const gchar *data, gsize len); gboolean safe_WriteConsoleW (HANDLE chd, const gunichar2 *data, gsize len); gsize canvas_to_conhost(ChafaCanvas * canvas, CONHOST_LINE ** lines); void write_image_conhost(const CONHOST_LINE * lines, gsize s); -void destroy_lines(const CONHOST_LINE * lines, gsize s); +void destroy_lines(CONHOST_LINE * lines, gsize s); #endif \ No newline at end of file From 945e322d74e478794e39abd84ceb927a364da904 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Sat, 4 Nov 2023 22:56:13 +0200 Subject: [PATCH 19/28] Windows be like --- tools/chafa/character_canvas_to_conhost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/chafa/character_canvas_to_conhost.c b/tools/chafa/character_canvas_to_conhost.c index 94d11a7d..0aa774f9 100644 --- a/tools/chafa/character_canvas_to_conhost.c +++ b/tools/chafa/character_canvas_to_conhost.c @@ -91,7 +91,7 @@ void write_image_conhost(const CONHOST_LINE * lines, gsize s){ WriteConsoleOutputAttribute(outh, line.attributes, line.length, curpos, &idc); /* WriteConsoleOutput family doesn't scroll the screen * so we have to make another API call to scroll */ - WriteConsoleA(outh,"\n",1, NULL, NULL); + WriteConsoleA(outh,"\r\n",2, NULL, NULL); curpos.Y++; } From 5c135600cdcf98aa9574d5d95603ddc5ceb89d05 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Sun, 5 Nov 2023 06:40:44 +0200 Subject: [PATCH 20/28] Dropping the iconv stuff, it isn't worth it --- tools/chafa/chafa.c | 32 +++++--------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index a7398dbb..922b6fc3 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -137,15 +137,9 @@ typedef struct ChafaTermInfo *term_info; gboolean output_utf_16_on_windows; - gchar * output_codepage; } GlobalOptions; -#ifdef G_OS_WIN32 -#define OUTPUT_UTF_16_ON_WINDOWS options.output_utf_16_on_windows -#else -#define OUTPUT_UTF_16_ON_WINDOWS FALSE -#endif typedef struct { @@ -278,15 +272,13 @@ write_to_stdout (gconstpointer buf, gsize len) char * converted_buf=NULL; if (len == 0) return TRUE; - if (options.output_codepage!=NULL || OUTPUT_UTF_16_ON_WINDOWS ){ - gsize tmp; - +#ifdef G_OS_WIN32 + if (options.output_utf_16_on_windows){ + gsize tmp; buf=converted_buf=g_convert( buf, len, - OUTPUT_UTF_16_ON_WINDOWS? - "UTF-16LE": - options.output_codepage, + "UTF-16LE", "UTF-8", NULL, &tmp, @@ -294,8 +286,6 @@ write_to_stdout (gconstpointer buf, gsize len) ); len=tmp; } - -#ifdef G_OS_WIN32 { HANDLE chd = GetStdHandle (STD_OUTPUT_HANDLE); gsize total_written = 0; @@ -532,7 +522,6 @@ print_summary (void) " --polite=BOOL Polite mode [on, off]. Inhibits escape sequences that may\n" " confuse other programs. Defaults to off.\n" - " --encoding=ENCODING Set Output Encoding to any encoding supported by iconv\n" " --utf16 Windows only, output using UTF16 functions,\n" " required for compatibility with older versions of Windows\n" "\nSize and layout:\n" @@ -1629,7 +1618,7 @@ tty_options_init (void) } } - if (!options.output_utf_16_on_windows && options.output_codepage == NULL){ + if (!options.output_utf_16_on_windows){ /* Set UTF-8 code page output */ SetConsoleOutputCP (65001); @@ -1901,7 +1890,6 @@ parse_options (int *argc, char **argv []) { "dither-intensity", '\0', 0, G_OPTION_ARG_DOUBLE, &options.dither_intensity, "Dither intensity", NULL }, { "dump-glyph-file", '\0', 0, G_OPTION_ARG_CALLBACK, parse_dump_glyph_file_arg, "Dump glyph file", NULL }, { "duration", 'd', 0, G_OPTION_ARG_CALLBACK, parse_duration_arg, "Duration", NULL }, - { "encoding", '\0', 0, G_OPTION_ARG_STRING, &options.output_codepage, "Encoding", NULL }, { "fg", '\0', 0, G_OPTION_ARG_CALLBACK, parse_fg_color_arg, "Foreground color of display", NULL }, { "fg-only", '\0', 0, G_OPTION_ARG_NONE, &options.fg_only, "Foreground only", NULL }, { "fill", '\0', 0, G_OPTION_ARG_CALLBACK, parse_fill_arg, "Fill symbols", NULL }, @@ -1998,7 +1986,6 @@ parse_options (int *argc, char **argv []) options.anim_fps = -1.0; options.anim_speed_multiplier = 1.0; - options.output_codepage = NULL; options.output_utf_16_on_windows = FALSE; if (!g_option_context_parse (context, argc, argv, &error)) @@ -2316,15 +2303,6 @@ parse_options (int *argc, char **argv []) chafa_set_n_threads (options.n_threads); - if (options.output_codepage != NULL){ - /* I don't know of a better way of checking for a valid codepage */ - GIConv converter=g_iconv_open(options.output_codepage, "UTF-8"); - if (result == -1) { - g_printerr ("conversion to '%s' not supported by iconv.\n", options.output_codepage); - goto out; - } else - g_iconv_close(converter); - } #ifdef G_OS_WIN32 if (options.pixel_mode == CHAFA_PIXEL_MODE_CONHOST){ From ece03e5d808a4b9777288f7aa5428c42946fb7ab Mon Sep 17 00:00:00 2001 From: oshaboy Date: Sun, 5 Nov 2023 06:51:07 +0200 Subject: [PATCH 21/28] Reverted API changes --- chafa/chafa-canvas-config.h | 1 - chafa/chafa-canvas.c | 4 +-- tools/chafa/chafa.c | 30 +++++++++---------- ...haracter_canvas_to_conhost.c => conhost.c} | 16 +++++----- ...haracter_canvas_to_conhost.h => conhost.h} | 8 ++--- 5 files changed, 29 insertions(+), 30 deletions(-) rename tools/chafa/{character_canvas_to_conhost.c => conhost.c} (87%) rename tools/chafa/{character_canvas_to_conhost.h => conhost.h} (66%) diff --git a/chafa/chafa-canvas-config.h b/chafa/chafa-canvas-config.h index db179b6e..73b088d9 100644 --- a/chafa/chafa-canvas-config.h +++ b/chafa/chafa-canvas-config.h @@ -87,7 +87,6 @@ typedef enum CHAFA_PIXEL_MODE_SIXELS, CHAFA_PIXEL_MODE_KITTY, CHAFA_PIXEL_MODE_ITERM2, - CHAFA_PIXEL_MODE_CONHOST, CHAFA_PIXEL_MODE_MAX } diff --git a/chafa/chafa-canvas.c b/chafa/chafa-canvas.c index 2fcb045d..fbb388eb 100644 --- a/chafa/chafa-canvas.c +++ b/chafa/chafa-canvas.c @@ -1277,7 +1277,7 @@ draw_all_pixels (ChafaCanvas *canvas, ChafaPixelType src_pixel_type, destroy_pixel_canvas (canvas); - if (canvas->config.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS || canvas->config.pixel_mode == CHAFA_PIXEL_MODE_CONHOST) + if (canvas->config.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS) { /* Symbol mode */ @@ -1386,7 +1386,7 @@ chafa_canvas_new (const ChafaCanvasConfig *config) canvas->refs = 1; - if (canvas->config.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS || canvas->config.pixel_mode == CHAFA_PIXEL_MODE_CONHOST) + if (canvas->config.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS) { /* ANSI art */ canvas->width_pixels = canvas->config.width * CHAFA_SYMBOL_WIDTH_PIXELS; diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index 922b6fc3..a0106ac9 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -50,7 +50,7 @@ # ifdef HAVE_WINDOWS_H # include # include -# include "character_canvas_to_conhost.h" +# include "conhost.h" # endif # include #endif @@ -137,7 +137,7 @@ typedef struct ChafaTermInfo *term_info; gboolean output_utf_16_on_windows; - + gboolean is_conhost_mode; } GlobalOptions; @@ -986,10 +986,10 @@ parse_format_arg (G_GNUC_UNUSED const gchar *option_name, const gchar *value, G_ else if (!strcasecmp (value, "conhost")) { #ifdef G_OS_WIN32 - pixel_mode = CHAFA_PIXEL_MODE_CONHOST; - #else + options.is_conhost_mode=true; + #endif pixel_mode = CHAFA_PIXEL_MODE_SYMBOLS; - #endif + } else { @@ -1606,7 +1606,7 @@ tty_options_init (void) if (chd != INVALID_HANDLE_VALUE) { DWORD bitmask = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; - if (options.pixel_mode != CHAFA_PIXEL_MODE_CONHOST) + if (!options.is_conhost_mode) bitmask |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN; if (!SetConsoleMode (chd, bitmask) ){ if (GetLastError() == ERROR_INVALID_HANDLE) @@ -1628,7 +1628,7 @@ tty_options_init (void) if (win32_stdout_is_file && options.output_utf_16_on_windows && - (options.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS || options.pixel_mode == CHAFA_PIXEL_MODE_CONHOST) + (options.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS) ) safe_WriteConsoleW (chd, u"\xfeff", 1); @@ -1652,7 +1652,7 @@ tty_options_init (void) } #endif - if (options.mode != CHAFA_CANVAS_MODE_FGBG && options.pixel_mode != CHAFA_PIXEL_MODE_CONHOST) + if (options.mode != CHAFA_CANVAS_MODE_FGBG && !options.is_conhost_mode) { p0 = chafa_term_info_emit_disable_cursor (options.term_info, buf); write_to_stdout (buf, p0 - buf); @@ -1679,7 +1679,7 @@ tty_options_deinit (void) if (!options.polite) { - if (options.mode != CHAFA_CANVAS_MODE_FGBG && options.pixel_mode != CHAFA_PIXEL_MODE_CONHOST) + if (options.mode != CHAFA_CANVAS_MODE_FGBG && !options.is_conhost_mode) { gchar buf [CHAFA_TERM_SEQ_LENGTH_MAX]; gchar *p0; @@ -1987,7 +1987,7 @@ parse_options (int *argc, char **argv []) options.anim_speed_multiplier = 1.0; options.output_utf_16_on_windows = FALSE; - + options.is_conhost_mode=FALSE; if (!g_option_context_parse (context, argc, argv, &error)) { g_printerr ("%s: %s\n", options.executable_name, error->message); @@ -2137,8 +2137,7 @@ parse_options (int *argc, char **argv []) /* Now we've established the pixel mode, apply dependent defaults */ - if (options.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS || - options.pixel_mode == CHAFA_PIXEL_MODE_CONHOST) + if (options.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS) { /* Character cell defaults */ @@ -2304,7 +2303,7 @@ parse_options (int *argc, char **argv []) chafa_set_n_threads (options.n_threads); #ifdef G_OS_WIN32 - if (options.pixel_mode == CHAFA_PIXEL_MODE_CONHOST){ + if (options.is_conhost_mode){ options.output_utf_16_on_windows = TRUE; if (options.mode == CHAFA_CANVAS_MODE_INDEXED_240 || @@ -2316,6 +2315,7 @@ parse_options (int *argc, char **argv []) #else /*Force it to not output UTF16 when not Windows*/ options.output_utf_16_on_windows = FALSE; + options.is_conhost_mode = FALSE; #endif result = TRUE; @@ -2851,8 +2851,8 @@ run_generic (const gchar *filename, gboolean is_first_file, gboolean is_first_fr placement_id >= 0 ? placement_id + ((frame_count++) % 2) : -1); */ #ifdef G_OS_WIN32 - if (options.pixel_mode == CHAFA_PIXEL_MODE_CONHOST){ - CONHOST_LINE * lines; + if (options.is_conhost_mode){ + ConhostRow * lines; gsize s; s=canvas_to_conhost(canvas, &lines); write_image_conhost(lines, s); diff --git a/tools/chafa/character_canvas_to_conhost.c b/tools/chafa/conhost.c similarity index 87% rename from tools/chafa/character_canvas_to_conhost.c rename to tools/chafa/conhost.c index 0aa774f9..cab45a19 100644 --- a/tools/chafa/character_canvas_to_conhost.c +++ b/tools/chafa/conhost.c @@ -1,4 +1,4 @@ -#include "character_canvas_to_conhost.h" +#include "conhost.h" static gsize unichar_to_utf16(gunichar c, gunichar2 * str){ if (c>=0x110000 || @@ -17,7 +17,7 @@ static gsize unichar_to_utf16(gunichar c, gunichar2 * str){ #define FOREGROUND_ALL FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE -gsize canvas_to_conhost(ChafaCanvas * canvas, CONHOST_LINE ** lines){ +gsize canvas_to_conhost(ChafaCanvas * canvas, ConhostRow ** lines){ gint width, height; ChafaCanvasConfig * config; ChafaCanvasMode canvas_mode; @@ -32,14 +32,14 @@ gsize canvas_to_conhost(ChafaCanvas * canvas, CONHOST_LINE ** lines){ canvas_mode == CHAFA_CANVAS_MODE_TRUECOLOR ) return (gsize) -1; chafa_canvas_config_get_geometry(config, &width, &height); - (*lines)=g_malloc(height*sizeof(CONHOST_LINE)); + (*lines)=g_malloc(height*sizeof(ConhostRow)); static const gchar color_lut[16] = { 0,4,2,6,1,5,3,7, 8,12,10,14,9,13,11,15 }; for (int y=0; y Date: Sun, 5 Nov 2023 07:03:44 +0200 Subject: [PATCH 22/28] Style Changes Also moved the safe_WriteConsoles to the conhost.c file --- tools/chafa/chafa.c | 178 +++------------------------ tools/chafa/conhost.c | 271 +++++++++++++++++++++++++++--------------- tools/chafa/conhost.h | 14 +-- 3 files changed, 200 insertions(+), 263 deletions(-) diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index a0106ac9..58f769dc 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -189,80 +189,7 @@ interruptible_usleep (gdouble us) * different set of I/O functions. */ static gboolean win32_stdout_is_file = FALSE; -gboolean -safe_WriteConsoleA (HANDLE chd, const gchar *data, gsize len) -{ - gsize total_written = 0; - - if (chd == INVALID_HANDLE_VALUE) - return FALSE; - - while (total_written < len) - { - DWORD n_written = 0; - - if (win32_stdout_is_file) - { - /* WriteFile() and fwrite() seem to work equally well despite various - * claims that the former does poorly in a UTF-8 environment. The - * resulting files look good in my tests, but note that catting them - * out with 'type' introduces lots of artefacts. */ -#if 0 - if (!WriteFile (chd, data, len - total_written, &n_written, NULL)) - return FALSE; -#else - if ((n_written = fwrite (data, 1, len - total_written, stdout)) < 1) - return FALSE; -#endif - } - else - { - if (!WriteConsoleA (chd, data, len - total_written, &n_written, NULL)) - return FALSE; - } - - data += n_written; - total_written += n_written; - } - - return TRUE; -} -gboolean -safe_WriteConsoleW (HANDLE chd, const gunichar2 *data, gsize len) -{ - gsize total_written = 0; - if (chd == INVALID_HANDLE_VALUE) - return FALSE; - - while (total_written < len) - { - DWORD n_written = 0; - if (win32_stdout_is_file) - { - /* WriteFile() and fwrite() seem to work equally well despite various - * claims that the former does poorly in a UTF-8 environment. The - * resulting files look good in my tests, but note that catting them - * out with 'type' introduces lots of artefacts. */ -#if 0 - if (!WriteFile (chd, data, (len - total_written)*2, &n_written, NULL)) - return FALSE; -#else - if ((n_written = fwrite (data, 2, len - total_written, stdout)) < 1) - return FALSE; -#endif - } - else - { - if (!WriteConsoleW (chd, data, len - total_written, &n_written, NULL)) - return FALSE; - } - - data += n_written; - total_written += n_written; - } - return TRUE; -} #endif static gboolean @@ -275,7 +202,7 @@ write_to_stdout (gconstpointer buf, gsize len) #ifdef G_OS_WIN32 if (options.output_utf_16_on_windows){ gsize tmp; - buf=converted_buf=g_convert( + buf=converted_buf=g_convert ( buf, len, "UTF-16LE", @@ -289,7 +216,7 @@ write_to_stdout (gconstpointer buf, gsize len) { HANDLE chd = GetStdHandle (STD_OUTPUT_HANDLE); gsize total_written = 0; - gboolean (*safe_WriteConsole)(HANDLE, const void *, gsize); + gboolean (*safe_WriteConsole) (HANDLE, const void *, gsize); gint stride; const void * newline; /* We need to select whether to use the UTF-8 (Codepage 65001) or UTF-16 semantics */ @@ -351,7 +278,7 @@ write_to_stdout (gconstpointer buf, gsize len) #endif - g_free(converted_buf); + if (converted_buf) g_free (converted_buf); return result; } @@ -985,9 +912,9 @@ parse_format_arg (G_GNUC_UNUSED const gchar *option_name, const gchar *value, G_ } else if (!strcasecmp (value, "conhost")) { - #ifdef G_OS_WIN32 +#ifdef G_OS_WIN32 options.is_conhost_mode=true; - #endif +#endif pixel_mode = CHAFA_PIXEL_MODE_SYMBOLS; } @@ -2302,7 +2229,7 @@ parse_options (int *argc, char **argv []) chafa_set_n_threads (options.n_threads); - #ifdef G_OS_WIN32 +#ifdef G_OS_WIN32 if (options.is_conhost_mode){ options.output_utf_16_on_windows = TRUE; @@ -2312,11 +2239,11 @@ parse_options (int *argc, char **argv []) options.mode=CHAFA_CANVAS_MODE_INDEXED_16; } - #else +#else /*Force it to not output UTF16 when not Windows*/ options.output_utf_16_on_windows = FALSE; options.is_conhost_mode = FALSE; - #endif +#endif result = TRUE; @@ -2566,70 +2493,7 @@ write_image (GString **gsa, gint dest_width) out: return result; } -#if 0 -static GString ** -build_strings (ChafaPixelType pixel_type, const guint8 *pixels, - gint src_width, gint src_height, gint src_rowstride, - gint dest_width, gint dest_height, - gboolean is_animation, - gint placement_id) -{ - ChafaCanvasConfig *config; - ChafaCanvas *canvas; - ChafaFrame *frame; - ChafaImage *image; - GString **gsa; - - config = chafa_canvas_config_new (); - - chafa_canvas_config_set_geometry (config, dest_width, dest_height); - chafa_canvas_config_set_canvas_mode (config, options.mode); - chafa_canvas_config_set_pixel_mode (config, options.pixel_mode); - chafa_canvas_config_set_dither_mode (config, options.dither_mode); - chafa_canvas_config_set_dither_grain_size (config, options.dither_grain_width, options.dither_grain_height); - chafa_canvas_config_set_dither_intensity (config, options.dither_intensity); - chafa_canvas_config_set_color_extractor (config, options.color_extractor); - chafa_canvas_config_set_color_space (config, options.color_space); - chafa_canvas_config_set_fg_color (config, options.fg_color); - chafa_canvas_config_set_bg_color (config, options.bg_color); - chafa_canvas_config_set_preprocessing_enabled (config, options.preprocess); - chafa_canvas_config_set_fg_only_enabled (config, options.fg_only); - chafa_canvas_config_set_passthrough (config, options.passthrough); - - if (is_animation - && options.pixel_mode == CHAFA_PIXEL_MODE_KITTY - && !options.transparency_threshold_set) - chafa_canvas_config_set_transparency_threshold (config, 1.0f); - else if (options.transparency_threshold >= 0.0) - chafa_canvas_config_set_transparency_threshold (config, options.transparency_threshold); - - if (options.cell_width > 0 && options.cell_height > 0) - chafa_canvas_config_set_cell_geometry (config, options.cell_width, options.cell_height); - chafa_canvas_config_set_symbol_map (config, options.symbol_map); - chafa_canvas_config_set_fill_symbol_map (config, options.fill_symbol_map); - - /* Work switch takes values [1..9], we normalize to [0.0..1.0] to - * get the work factor. */ - chafa_canvas_config_set_work_factor (config, (options.work_factor - 1) / 8.0f); - - chafa_canvas_config_set_optimizations (config, options.optimizations); - - canvas = chafa_canvas_new (config); - frame = chafa_frame_new_borrow ((gpointer) pixels, pixel_type, - src_width, src_height, src_rowstride); - image = chafa_image_new (); - chafa_image_set_frame (image, frame); - chafa_canvas_set_image (canvas, image, placement_id); - chafa_canvas_print_rows (canvas, options.term_info, &gsa, NULL); - - chafa_image_unref (image); - chafa_frame_unref (frame); - chafa_canvas_unref (canvas); - chafa_canvas_config_unref (config); - return gsa; -} -#endif static ChafaCanvasConfig * build_config ( gint dest_width, gint dest_height, @@ -2833,32 +2697,26 @@ run_generic (const gchar *filename, gboolean is_first_file, gboolean is_first_fr options.font_ratio, options.scale >= SCALE_MAX - 0.1 ? TRUE : FALSE, options.stretch); - ChafaCanvasConfig * cfg = build_config( + ChafaCanvasConfig * cfg = build_config ( dest_width, dest_height, is_animation ); - ChafaCanvas * canvas = build_canvas( + ChafaCanvas * canvas = build_canvas ( pixel_type, pixels, src_width, src_height, src_rowstride, cfg, placement_id >= 0 ? placement_id + ((frame_count++) % 2) : -1 ); - /* - gsa = build_strings (pixel_type, pixels, - src_width, src_height, src_rowstride, - dest_width, dest_height, - is_animation, - placement_id >= 0 ? placement_id + ((frame_count++) % 2) : -1); - */ - #ifdef G_OS_WIN32 + +#ifdef G_OS_WIN32 if (options.is_conhost_mode){ ConhostRow * lines; gsize s; - s=canvas_to_conhost(canvas, &lines); - write_image_conhost(lines, s); - destroy_lines(lines,s); + s=canvas_to_conhost (canvas, &lines); + write_image_conhost (lines, s); + destroy_lines (lines,s); } else - #endif +#endif { chafa_canvas_print_rows (canvas, options.term_info, &gsa, NULL); if (!write_image_prologue (is_first_file, is_first_frame, is_animation, dest_height) @@ -2871,8 +2729,8 @@ run_generic (const gchar *filename, gboolean is_first_file, gboolean is_first_fr chafa_free_gstring_array (gsa); } - chafa_canvas_unref(canvas); - chafa_canvas_config_unref(cfg); + chafa_canvas_unref (canvas); + chafa_canvas_config_unref (cfg); if (is_animation) { /* Account for time spent converting and printing frame */ diff --git a/tools/chafa/conhost.c b/tools/chafa/conhost.c index cab45a19..29d86c97 100644 --- a/tools/chafa/conhost.c +++ b/tools/chafa/conhost.c @@ -1,106 +1,185 @@ #include "conhost.h" -static gsize unichar_to_utf16(gunichar c, gunichar2 * str){ - if (c>=0x110000 || - (c<0xe000 && c>=0xd800) || - (c%0x10000 >= 0xfffe)) return 0; - if (c<0x10000){ - *str=(gunichar2)c; - return 1; - } else { - const gunichar temp=c-0x10000; - str[0]=(temp>>10)+0xd800; - str[1]=(temp&0x3ff)+0xdc00; - return 2; - } +static gsize +unichar_to_utf16 (gunichar c, gunichar2 * str){ + if (c>=0x110000 || + (c<0xe000 && c>=0xd800) || + (c%0x10000 >= 0xfffe)) return 0; + if (c<0x10000){ + *str=(gunichar2)c; + return 1; + } else { + const gunichar temp=c-0x10000; + str[0]=(temp>>10)+0xd800; + str[1]=(temp&0x3ff)+0xdc00; + return 2; + } } #define FOREGROUND_ALL FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE -gsize canvas_to_conhost(ChafaCanvas * canvas, ConhostRow ** lines){ - gint width, height; - ChafaCanvasConfig * config; - ChafaCanvasMode canvas_mode; - - - - config = chafa_canvas_peek_config(canvas); - canvas_mode = chafa_canvas_config_get_canvas_mode(config); - if ( - canvas_mode == CHAFA_CANVAS_MODE_INDEXED_240 || - canvas_mode == CHAFA_CANVAS_MODE_INDEXED_256 || - canvas_mode == CHAFA_CANVAS_MODE_TRUECOLOR - ) return (gsize) -1; - chafa_canvas_config_get_geometry(config, &width, &height); - (*lines)=g_malloc(height*sizeof(ConhostRow)); - static const gchar color_lut[16] = { - 0,4,2,6,1,5,3,7, - 8,12,10,14,9,13,11,15 - }; - for (int y=0; y0) - line->str[line->utf16_string_length++]=*utf16_codes; - if (s==2) - line->str[line->utf16_string_length++]=utf16_codes[1]; - - if (canvas_mode == CHAFA_CANVAS_MODE_FGBG) - line->attributes[x]=FOREGROUND_ALL; - else{ - gint fg_out, bg_out; - chafa_canvas_get_raw_colors_at(canvas,x,y,&fg_out, &bg_out); - if (canvas_mode == CHAFA_CANVAS_MODE_FGBG_BGFG) - line->attributes[x]=bg_out?FOREGROUND_ALL:COMMON_LVB_REVERSE_VIDEO|FOREGROUND_ALL; - else { - fg_out=color_lut[fg_out]; - bg_out=color_lut[bg_out]; - line->attributes[x]=(bg_out<<4)|fg_out; - } - - } - } - line->str=g_realloc(line->str, line->utf16_string_length*sizeof(gunichar2)); - } - return height; +gsize +canvas_to_conhost (ChafaCanvas * canvas, ConhostRow ** lines){ + gint width, height; + ChafaCanvasConfig * config; + ChafaCanvasMode canvas_mode; + + + + config = chafa_canvas_peek_config (canvas); + canvas_mode = chafa_canvas_config_get_canvas_mode (config); + if ( + canvas_mode == CHAFA_CANVAS_MODE_INDEXED_240 || + canvas_mode == CHAFA_CANVAS_MODE_INDEXED_256 || + canvas_mode == CHAFA_CANVAS_MODE_TRUECOLOR + ) return (gsize) -1; + chafa_canvas_config_get_geometry (config, &width, &height); + (*lines)=g_malloc (height*sizeof(ConhostRow)); + static const gchar color_lut[16] = { + 0,4,2,6,1,5,3,7, + 8,12,10,14,9,13,11,15 + }; + for (int y=0; y0) + line->str[line->utf16_string_length++]=*utf16_codes; + if (s==2) + line->str[line->utf16_string_length++]=utf16_codes[1]; + + if (canvas_mode == CHAFA_CANVAS_MODE_FGBG) + line->attributes[x]=FOREGROUND_ALL; + else{ + gint fg_out, bg_out; + chafa_canvas_get_raw_colors_at (canvas,x,y,&fg_out, &bg_out); + if (canvas_mode == CHAFA_CANVAS_MODE_FGBG_BGFG) + line->attributes[x]=bg_out?FOREGROUND_ALL:COMMON_LVB_REVERSE_VIDEO|FOREGROUND_ALL; + else { + fg_out=color_lut[fg_out]; + bg_out=color_lut[bg_out]; + line->attributes[x]=(bg_out<<4)|fg_out; + } + + } + } + line->str=g_realloc (line->str, line->utf16_string_length*sizeof(gunichar2)); + } + return height; } -void write_image_conhost(const ConhostRow * lines, gsize s){ - HANDLE outh; - COORD curpos; - DWORD idc; - outh = GetStdHandle(STD_OUTPUT_HANDLE); - { - CONSOLE_SCREEN_BUFFER_INFO bufinfo; - GetConsoleScreenBufferInfo(outh, &bufinfo); - curpos = bufinfo.dwCursorPosition; - } - - for (gsize y=0 ;y Date: Sun, 5 Nov 2023 07:16:45 +0200 Subject: [PATCH 23/28] more style --- tools/chafa/Makefile.am | 4 ++-- tools/chafa/chafa.c | 29 +++++++++++------------------ tools/chafa/conhost.c | 34 ++++++++++++++++++---------------- tools/chafa/conhost.h | 5 +++++ 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/tools/chafa/Makefile.am b/tools/chafa/Makefile.am index 6cca0082..ca69601a 100644 --- a/tools/chafa/Makefile.am +++ b/tools/chafa/Makefile.am @@ -75,8 +75,8 @@ chafa_LDADD = $(GLIB_LIBS) $(JPEG_LIBS) $(SVG_LIBS) $(TIFF_LIBS) $(WEBP_LIBS) $( if IS_WIN32_BUILD WIN32_LDADD = manifest.o chafa_SOURCES += \ - character_canvas_to_conhost.c \ - character_canvas_to_conhost.h + conhost.c \ + conhost.h manifest.o: $(srcdir)/manifest.rc $(WINDRES) -o $@ $(srcdir)/manifest.rc else diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index 58f769dc..1329f074 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -183,26 +183,19 @@ interruptible_usleep (gdouble us) } } -#ifdef G_OS_WIN32 - -/* We must determine if stdout is redirected to a file, and if so, use a - * different set of I/O functions. */ -static gboolean win32_stdout_is_file = FALSE; -#endif - static gboolean write_to_stdout (gconstpointer buf, gsize len) { gboolean result = TRUE; - char * converted_buf=NULL; + char * converted_buf = NULL; if (len == 0) return TRUE; #ifdef G_OS_WIN32 if (options.output_utf_16_on_windows){ gsize tmp; - buf=converted_buf=g_convert ( + buf = converted_buf = g_convert ( buf, len, "UTF-16LE", @@ -211,7 +204,7 @@ write_to_stdout (gconstpointer buf, gsize len) &tmp, NULL ); - len=tmp; + len = tmp; } { HANDLE chd = GetStdHandle (STD_OUTPUT_HANDLE); @@ -221,13 +214,13 @@ write_to_stdout (gconstpointer buf, gsize len) const void * newline; /* We need to select whether to use the UTF-8 (Codepage 65001) or UTF-16 semantics */ if (options.output_utf_16_on_windows){ - stride=2; - safe_WriteConsole=safe_WriteConsoleW; - newline=L"\r\n"; + stride = 2; + safe_WriteConsole = safe_WriteConsoleW; + newline = L"\r\n"; } else { - stride=1; - safe_WriteConsole=safe_WriteConsoleA; - newline="\r\n"; + stride = 1; + safe_WriteConsole = safe_WriteConsoleA; + newline = "\r\n"; } { @@ -913,7 +906,7 @@ parse_format_arg (G_GNUC_UNUSED const gchar *option_name, const gchar *value, G_ else if (!strcasecmp (value, "conhost")) { #ifdef G_OS_WIN32 - options.is_conhost_mode=true; + options.is_conhost_mode = TRUE; #endif pixel_mode = CHAFA_PIXEL_MODE_SYMBOLS; @@ -1914,7 +1907,7 @@ parse_options (int *argc, char **argv []) options.anim_speed_multiplier = 1.0; options.output_utf_16_on_windows = FALSE; - options.is_conhost_mode=FALSE; + options.is_conhost_mode = FALSE; if (!g_option_context_parse (context, argc, argv, &error)) { g_printerr ("%s: %s\n", options.executable_name, error->message); diff --git a/tools/chafa/conhost.c b/tools/chafa/conhost.c index 29d86c97..0c02fa01 100644 --- a/tools/chafa/conhost.c +++ b/tools/chafa/conhost.c @@ -6,12 +6,12 @@ unichar_to_utf16 (gunichar c, gunichar2 * str){ (c<0xe000 && c>=0xd800) || (c%0x10000 >= 0xfffe)) return 0; if (c<0x10000){ - *str=(gunichar2)c; + *str = (gunichar2)c; return 1; } else { const gunichar temp=c-0x10000; - str[0]=(temp>>10)+0xd800; - str[1]=(temp&0x3ff)+0xdc00; + str[0] = (temp>>10)+0xd800; + str[1] = (temp&0x3ff)+0xdc00; return 2; } } @@ -21,7 +21,7 @@ unichar_to_utf16 (gunichar c, gunichar2 * str){ gsize canvas_to_conhost (ChafaCanvas * canvas, ConhostRow ** lines){ gint width, height; - ChafaCanvasConfig * config; + const ChafaCanvasConfig * config; ChafaCanvasMode canvas_mode; @@ -34,28 +34,28 @@ canvas_to_conhost (ChafaCanvas * canvas, ConhostRow ** lines){ canvas_mode == CHAFA_CANVAS_MODE_TRUECOLOR ) return (gsize) -1; chafa_canvas_config_get_geometry (config, &width, &height); - (*lines)=g_malloc (height*sizeof(ConhostRow)); + (*lines) = g_malloc (height*sizeof(ConhostRow)); static const gchar color_lut[16] = { 0,4,2,6,1,5,3,7, 8,12,10,14,9,13,11,15 }; - for (int y=0; y0) - line->str[line->utf16_string_length++]=*utf16_codes; + line->str[line->utf16_string_length++] = *utf16_codes; if (s==2) - line->str[line->utf16_string_length++]=utf16_codes[1]; + line->str[line->utf16_string_length++] = utf16_codes[1]; if (canvas_mode == CHAFA_CANVAS_MODE_FGBG) line->attributes[x]=FOREGROUND_ALL; @@ -63,11 +63,11 @@ canvas_to_conhost (ChafaCanvas * canvas, ConhostRow ** lines){ gint fg_out, bg_out; chafa_canvas_get_raw_colors_at (canvas,x,y,&fg_out, &bg_out); if (canvas_mode == CHAFA_CANVAS_MODE_FGBG_BGFG) - line->attributes[x]=bg_out?FOREGROUND_ALL:COMMON_LVB_REVERSE_VIDEO|FOREGROUND_ALL; + line->attributes[x] = bg_out?FOREGROUND_ALL:COMMON_LVB_REVERSE_VIDEO|FOREGROUND_ALL; else { fg_out=color_lut[fg_out]; bg_out=color_lut[bg_out]; - line->attributes[x]=(bg_out<<4)|fg_out; + line->attributes[x] = (bg_out<<4)|fg_out; } } @@ -109,6 +109,8 @@ destroy_lines (ConhostRow * lines, gsize s){ g_free (lines); } +#include +gboolean win32_stdout_is_file = FALSE; gboolean safe_WriteConsoleA (HANDLE chd, const gchar *data, gsize len) { diff --git a/tools/chafa/conhost.h b/tools/chafa/conhost.h index 88b63907..2d866259 100644 --- a/tools/chafa/conhost.h +++ b/tools/chafa/conhost.h @@ -17,4 +17,9 @@ gboolean safe_WriteConsoleW (HANDLE chd, const gunichar2 *data, gsize len); gsize canvas_to_conhost (ChafaCanvas * canvas, ConhostRow ** lines); void write_image_conhost (const ConhostRow * lines, gsize s); void destroy_lines (ConhostRow * lines, gsize s); + +/* We must determine if stdout is redirected to a file, and if so, use a + * different set of I/O functions. */ +extern gboolean win32_stdout_is_file; + #endif \ No newline at end of file From a1d804180d15a500f99a1189c69f4064017140e4 Mon Sep 17 00:00:00 2001 From: oshaboy Date: Sun, 5 Nov 2023 15:34:01 +0200 Subject: [PATCH 24/28] More Formatting + bugfix --- tools/chafa/conhost.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/tools/chafa/conhost.c b/tools/chafa/conhost.c index 0c02fa01..50ab90c2 100644 --- a/tools/chafa/conhost.c +++ b/tools/chafa/conhost.c @@ -1,7 +1,8 @@ #include "conhost.h" static gsize -unichar_to_utf16 (gunichar c, gunichar2 * str){ +unichar_to_utf16 (gunichar c, gunichar2 * str) +{ if (c>=0x110000 || (c<0xe000 && c>=0xd800) || (c%0x10000 >= 0xfffe)) return 0; @@ -19,7 +20,8 @@ unichar_to_utf16 (gunichar c, gunichar2 * str){ #define FOREGROUND_ALL FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE gsize -canvas_to_conhost (ChafaCanvas * canvas, ConhostRow ** lines){ +canvas_to_conhost (ChafaCanvas * canvas, ConhostRow ** lines) +{ gint width, height; const ChafaCanvasConfig * config; ChafaCanvasMode canvas_mode; @@ -77,10 +79,12 @@ canvas_to_conhost (ChafaCanvas * canvas, ConhostRow ** lines){ return height; } void -write_image_conhost (const ConhostRow * lines, gsize s){ +write_image_conhost (const ConhostRow * lines, gsize s) +{ HANDLE outh; COORD curpos; DWORD idc; + outh = GetStdHandle (STD_OUTPUT_HANDLE); { CONSOLE_SCREEN_BUFFER_INFO bufinfo; @@ -92,16 +96,18 @@ write_image_conhost (const ConhostRow * lines, gsize s){ const ConhostRow line = lines[y]; WriteConsoleOutputCharacterW (outh, line.str, line.utf16_string_length, curpos,&idc); WriteConsoleOutputAttribute (outh, line.attributes, line.length, curpos, &idc); - /* WriteConsoleOutput family doesn't scroll the screen - * so we have to make another API call to scroll */ - WriteConsoleA (outh,"\r\n",2, NULL, NULL); curpos.Y++; - } + + /* WriteConsoleOutput family doesn't scroll the screen + * so we have to make another API call to scroll */ + + SetConsoleCursorPosition(outh, curpos); } void -destroy_lines (ConhostRow * lines, gsize s){ +destroy_lines (ConhostRow * lines, gsize s) +{ for (gsize i=0; i Date: Fri, 10 Nov 2023 22:17:43 +0200 Subject: [PATCH 25/28] Style Changes --- tools/chafa/chafa.c | 80 ++++++++++++------------------------------- tools/chafa/conhost.c | 24 ++++++++----- 2 files changed, 37 insertions(+), 67 deletions(-) diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index 1329f074..afeeab29 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -189,39 +189,17 @@ static gboolean write_to_stdout (gconstpointer buf, gsize len) { gboolean result = TRUE; - char * converted_buf = NULL; + if (len == 0) return TRUE; + #ifdef G_OS_WIN32 - if (options.output_utf_16_on_windows){ - gsize tmp; - buf = converted_buf = g_convert ( - buf, - len, - "UTF-16LE", - "UTF-8", - NULL, - &tmp, - NULL - ); - len = tmp; - } + { HANDLE chd = GetStdHandle (STD_OUTPUT_HANDLE); gsize total_written = 0; - gboolean (*safe_WriteConsole) (HANDLE, const void *, gsize); - gint stride; - const void * newline; - /* We need to select whether to use the UTF-8 (Codepage 65001) or UTF-16 semantics */ - if (options.output_utf_16_on_windows){ - stride = 2; - safe_WriteConsole = safe_WriteConsoleW; - newline = L"\r\n"; - } else { - stride = 1; - safe_WriteConsole = safe_WriteConsoleA; - newline = "\r\n"; - } + const void *const newline = "\r\n"; + { /* on MS Windows. We convert line feeds to DOS-style CRLF as we go. */ @@ -230,25 +208,22 @@ write_to_stdout (gconstpointer buf, gsize len) chd != INVALID_HANDLE_VALUE && total_written < len; p0 = p1) { - if (options.output_utf_16_on_windows) - p1 = (const gchar *) wmemchr ((const gunichar2 *) p0, L'\n', (end - p0)/2); - else - p1 = memchr (p0, '\n', end - p0); + p1 = memchr (p0, '\n', end - p0); if (!p1) p1 = end; - if (!safe_WriteConsole (chd, p0, (p1 - p0)/stride)) + if (!safe_WriteConsoleA (chd, p0, p1 - p0)) break; total_written += p1 - p0; if (p1 != end) { - if (!safe_WriteConsole (chd, newline, 2)) + if (!safe_WriteConsoleA (chd, newline, 2)) break; - p1 += stride; - total_written += stride; + p1 += 1; + total_written += 1; } } } @@ -271,7 +246,6 @@ write_to_stdout (gconstpointer buf, gsize len) #endif - if (converted_buf) g_free (converted_buf); return result; } @@ -442,8 +416,8 @@ print_summary (void) " --polite=BOOL Polite mode [on, off]. Inhibits escape sequences that may\n" " confuse other programs. Defaults to off.\n" - " --utf16 Windows only, output using UTF16 functions,\n" - " required for compatibility with older versions of Windows\n" + /*" --utf16 Windows only, output using UTF16 functions,\n" + " required for compatibility with older versions of Windows\n"*/ "\nSize and layout:\n" " -C, --center=BOOL Center images horizontally in view [on, off]. Default off.\n" @@ -1538,19 +1512,6 @@ tty_options_init (void) } } - if (!options.output_utf_16_on_windows){ - /* Set UTF-8 code page output */ - SetConsoleOutputCP (65001); - - /* Set UTF-8 code page input, for good measure */ - SetConsoleCP (65001); - } - - if (win32_stdout_is_file && - options.output_utf_16_on_windows && - (options.pixel_mode == CHAFA_PIXEL_MODE_SYMBOLS) - - ) safe_WriteConsoleW (chd, u"\xfeff", 1); } #endif @@ -1834,7 +1795,7 @@ parse_options (int *argc, char **argv []) { "symbols", '\0', 0, G_OPTION_ARG_CALLBACK, parse_symbols_arg, "Output symbols", NULL }, { "threads", '\0', 0, G_OPTION_ARG_INT, &options.n_threads, "Number of threads", NULL }, { "threshold", 't', 0, G_OPTION_ARG_DOUBLE, &options.transparency_threshold, "Transparency threshold", NULL }, - { "utf16", '\0', 0, G_OPTION_ARG_NONE, &options.output_utf_16_on_windows, "Use WriteConsoleW instead of WriteConsoleA", NULL}, + /*{ "utf16", '\0', 0, G_OPTION_ARG_NONE, &options.output_utf_16_on_windows, "Use WriteConsoleW instead of WriteConsoleA", NULL},*/ { "view-size", '\0', 0, G_OPTION_ARG_CALLBACK, parse_view_size_arg, "View size", NULL }, { "watch", '\0', 0, G_OPTION_ARG_NONE, &options.watch, "Watch a file's contents", NULL }, /* Deprecated: Equivalent to --scale max */ @@ -2547,7 +2508,6 @@ build_canvas (ChafaPixelType pixel_type, const guint8 *pixels, chafa_image_unref (image); chafa_frame_unref (frame); return canvas; - } static void @@ -2702,20 +2662,24 @@ run_generic (const gchar *filename, gboolean is_first_file, gboolean is_first_fr ); #ifdef G_OS_WIN32 - if (options.is_conhost_mode){ - ConhostRow * lines; + if (options.is_conhost_mode) + { + ConhostRow *lines; gsize s; - s=canvas_to_conhost (canvas, &lines); + + s = canvas_to_conhost (canvas, &lines); write_image_conhost (lines, s); destroy_lines (lines,s); - } else + } + else #endif { chafa_canvas_print_rows (canvas, options.term_info, &gsa, NULL); if (!write_image_prologue (is_first_file, is_first_frame, is_animation, dest_height) || !write_image (gsa, dest_width) || !write_image_epilogue (dest_width) - || fflush (stdout) != 0){ + || fflush (stdout) != 0) + { chafa_free_gstring_array (gsa); goto out; } diff --git a/tools/chafa/conhost.c b/tools/chafa/conhost.c index 50ab90c2..41aeb963 100644 --- a/tools/chafa/conhost.c +++ b/tools/chafa/conhost.c @@ -26,8 +26,6 @@ canvas_to_conhost (ChafaCanvas * canvas, ConhostRow ** lines) const ChafaCanvasConfig * config; ChafaCanvasMode canvas_mode; - - config = chafa_canvas_peek_config (canvas); canvas_mode = chafa_canvas_config_get_canvas_mode (config); if ( @@ -41,7 +39,8 @@ canvas_to_conhost (ChafaCanvas * canvas, ConhostRow ** lines) 0,4,2,6,1,5,3,7, 8,12,10,14,9,13,11,15 }; - for (gint y = 0; yattributes[x]=FOREGROUND_ALL; - else{ + else + { gint fg_out, bg_out; chafa_canvas_get_raw_colors_at (canvas,x,y,&fg_out, &bg_out); if (canvas_mode == CHAFA_CANVAS_MODE_FGBG_BGFG) line->attributes[x] = bg_out?FOREGROUND_ALL:COMMON_LVB_REVERSE_VIDEO|FOREGROUND_ALL; - else { + else + { fg_out=color_lut[fg_out]; bg_out=color_lut[bg_out]; line->attributes[x] = (bg_out<<4)|fg_out; @@ -92,7 +94,8 @@ write_image_conhost (const ConhostRow * lines, gsize s) curpos = bufinfo.dwCursorPosition; } - for (gsize y=0 ;y Date: Fri, 10 Nov 2023 22:21:19 +0200 Subject: [PATCH 26/28] Pointers --- tools/chafa/conhost.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/chafa/conhost.c b/tools/chafa/conhost.c index 41aeb963..f0ee4c76 100644 --- a/tools/chafa/conhost.c +++ b/tools/chafa/conhost.c @@ -1,7 +1,7 @@ #include "conhost.h" static gsize -unichar_to_utf16 (gunichar c, gunichar2 * str) +unichar_to_utf16 (gunichar c, gunichar2 *str) { if (c>=0x110000 || (c<0xe000 && c>=0xd800) || @@ -20,10 +20,10 @@ unichar_to_utf16 (gunichar c, gunichar2 * str) #define FOREGROUND_ALL FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE gsize -canvas_to_conhost (ChafaCanvas * canvas, ConhostRow ** lines) +canvas_to_conhost (ChafaCanvas *canvas, ConhostRow **lines) { gint width, height; - const ChafaCanvasConfig * config; + const ChafaCanvasConfig *config; ChafaCanvasMode canvas_mode; config = chafa_canvas_peek_config (canvas); @@ -41,7 +41,7 @@ canvas_to_conhost (ChafaCanvas * canvas, ConhostRow ** lines) }; for (gint y = 0; y Date: Fri, 10 Nov 2023 22:32:22 +0200 Subject: [PATCH 27/28] Now I am hopefully done --- tools/chafa/chafa.c | 31 ++++++++++++++++--------------- tools/chafa/conhost.h | 14 +++++++------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/tools/chafa/chafa.c b/tools/chafa/chafa.c index afeeab29..4bb1e713 100644 --- a/tools/chafa/chafa.c +++ b/tools/chafa/chafa.c @@ -235,7 +235,6 @@ write_to_stdout (gconstpointer buf, gsize len) for (total_written = 0; total_written < len; ) { - gsize n_written = fwrite (((const gchar *) buf) + total_written, 1, len - total_written, stdout); total_written += n_written; @@ -243,8 +242,6 @@ write_to_stdout (gconstpointer buf, gsize len) result = FALSE; } } - - #endif return result; } @@ -883,7 +880,6 @@ parse_format_arg (G_GNUC_UNUSED const gchar *option_name, const gchar *value, G_ options.is_conhost_mode = TRUE; #endif pixel_mode = CHAFA_PIXEL_MODE_SYMBOLS; - } else { @@ -1502,17 +1498,22 @@ tty_options_init (void) DWORD bitmask = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; if (!options.is_conhost_mode) bitmask |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN; - if (!SetConsoleMode (chd, bitmask) ){ + if (!SetConsoleMode (chd, bitmask)) + { if (GetLastError() == ERROR_INVALID_HANDLE) win32_stdout_is_file = TRUE; else /* Compatibility with older Windowses */ SetConsoleMode (chd,ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT); - } - + } } - + + /* Set UTF-8 code page output */ + SetConsoleOutputCP (65001); + + /* Set UTF-8 code page input, for good measure */ + SetConsoleCP (65001); } #endif @@ -1617,7 +1618,6 @@ detect_terminal (ChafaTermInfo **term_info_out, ChafaCanvasMode *mode_out, pixel_mode = CHAFA_PIXEL_MODE_SIXELS; else pixel_mode = CHAFA_PIXEL_MODE_SYMBOLS; - if (chafa_term_info_have_seq (term_info, CHAFA_TERM_SEQ_BEGIN_SCREEN_PASSTHROUGH)) { /* We can do passthrough for sixels and iterm too, but we won't do so @@ -1866,9 +1866,9 @@ parse_options (int *argc, char **argv []) options.file_duration_s = -1.0; /* Unset */ options.anim_fps = -1.0; options.anim_speed_multiplier = 1.0; - options.output_utf_16_on_windows = FALSE; options.is_conhost_mode = FALSE; + if (!g_option_context_parse (context, argc, argv, &error)) { g_printerr ("%s: %s\n", options.executable_name, error->message); @@ -2184,8 +2184,8 @@ parse_options (int *argc, char **argv []) chafa_set_n_threads (options.n_threads); #ifdef G_OS_WIN32 - if (options.is_conhost_mode){ - + if (options.is_conhost_mode) + { options.output_utf_16_on_windows = TRUE; if (options.mode == CHAFA_CANVAS_MODE_INDEXED_240 || options.mode == CHAFA_CANVAS_MODE_INDEXED_256 || @@ -2449,13 +2449,12 @@ write_image (GString **gsa, gint dest_width) } static ChafaCanvasConfig * -build_config ( - gint dest_width, gint dest_height, +build_config (gint dest_width, gint dest_height, gboolean is_animation) { ChafaCanvasConfig *config; - config = chafa_canvas_config_new (); + config = chafa_canvas_config_new (); chafa_canvas_config_set_geometry (config, dest_width, dest_height); chafa_canvas_config_set_canvas_mode (config, options.mode); chafa_canvas_config_set_pixel_mode (config, options.pixel_mode); @@ -2489,6 +2488,7 @@ build_config ( chafa_canvas_config_set_optimizations (config, options.optimizations); return config; } + static ChafaCanvas * build_canvas (ChafaPixelType pixel_type, const guint8 *pixels, gint src_width, gint src_height, gint src_rowstride, @@ -2850,6 +2850,7 @@ int main (int argc, char *argv []) { int ret; + proc_init (); if (!parse_options (&argc, &argv)) diff --git a/tools/chafa/conhost.h b/tools/chafa/conhost.h index 2d866259..2b81989c 100644 --- a/tools/chafa/conhost.h +++ b/tools/chafa/conhost.h @@ -5,18 +5,18 @@ #include #include -typedef WORD attribute; -typedef struct { - gunichar2 * str; - attribute * attributes; +typedef WORD ConhostAttribute; +typedef struct { + gunichar2 *str; + ConhostAttribute *attributes; size_t length; size_t utf16_string_length; } ConhostRow; gboolean safe_WriteConsoleA (HANDLE chd, const gchar *data, gsize len); gboolean safe_WriteConsoleW (HANDLE chd, const gunichar2 *data, gsize len); -gsize canvas_to_conhost (ChafaCanvas * canvas, ConhostRow ** lines); -void write_image_conhost (const ConhostRow * lines, gsize s); -void destroy_lines (ConhostRow * lines, gsize s); +gsize canvas_to_conhost (ChafaCanvas *canvas, ConhostRow **lines); +void write_image_conhost (const ConhostRow *lines, gsize s); +void destroy_lines (ConhostRow *lines, gsize s); /* We must determine if stdout is redirected to a file, and if so, use a * different set of I/O functions. */ From c223c52992797789b4e0a3c03188d459939a4efd Mon Sep 17 00:00:00 2001 From: oshaboy Date: Mon, 13 Nov 2023 21:55:59 +0200 Subject: [PATCH 28/28] Update conhost.c --- tools/chafa/conhost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/chafa/conhost.c b/tools/chafa/conhost.c index f0ee4c76..50ee5dd1 100644 --- a/tools/chafa/conhost.c +++ b/tools/chafa/conhost.c @@ -43,7 +43,7 @@ canvas_to_conhost (ChafaCanvas *canvas, ConhostRow **lines) { ConhostRow *const line = (*lines)+y; *line=(ConhostRow) { - .attributes = g_malloc (width*sizeof(attribute)), + .attributes = g_malloc (width*sizeof(ConhostAttribute)), .str = g_malloc (width*sizeof(gunichar2)*2), .length = width, .utf16_string_length = 0