From d6ecfc0de1610bd146c2028b6b35264522e04f60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Hork=C3=BD?= Date: Sun, 26 Oct 2025 11:51:47 +0100 Subject: [PATCH 1/4] lib/skin/common.c: Fix typo in comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jakub Horký --- lib/skin/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/skin/common.c b/lib/skin/common.c index 34db1db86d..36078cea2e 100644 --- a/lib/skin/common.c +++ b/lib/skin/common.c @@ -73,7 +73,7 @@ mc_skin_get_default_name (void) if (mc_global.tty.skin != NULL) return g_strdup (mc_global.tty.skin); - // from envirovement variable + // from environment variable tmp_str = getenv ("MC_SKIN"); if (tmp_str != NULL) return g_strdup (tmp_str); From b524cc367094580bfc80e493d6dd553f0f23b371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Hork=C3=BD?= Date: Sun, 26 Oct 2025 20:40:51 +0100 Subject: [PATCH 2/4] misc/skins: Differentiate directories and files in true color skins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Display directories in a more prominent color than files, as in most other skins. Signed-off-by: Jakub Horký --- misc/skins/seasons-autumn16M.ini | 6 ++++-- misc/skins/seasons-spring16M.ini | 8 +++++--- misc/skins/seasons-summer16M.ini | 8 +++++--- misc/skins/seasons-winter16M.ini | 8 +++++--- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/misc/skins/seasons-autumn16M.ini b/misc/skins/seasons-autumn16M.ini index 0efcaa1136..00dd95fe49 100644 --- a/misc/skins/seasons-autumn16M.ini +++ b/misc/skins/seasons-autumn16M.ini @@ -56,6 +56,8 @@ MainFg = #ffa MarkedFg = #ff5 HeaderFg = MarkedFg + DirectoryFg = #ffc + SelectedFg = DirectoryFg Selected = #681400 Dialog = #85a918 DialogFocus = #69880c @@ -93,7 +95,7 @@ [core] _default_ = MainFg;Main - selected = ;Selected + selected = SelectedFg;Selected marked = MarkedFg;;bold markselect = MarkedFg;Selected;bold gauge = ;DialogFocus @@ -121,7 +123,7 @@ errdtitle = ;;bold [filehighlight] - directory = + directory = DirectoryFg executable = #84ea84 symlink = #ff58fd hardlink = diff --git a/misc/skins/seasons-spring16M.ini b/misc/skins/seasons-spring16M.ini index 0ec998fca0..5820220227 100644 --- a/misc/skins/seasons-spring16M.ini +++ b/misc/skins/seasons-spring16M.ini @@ -53,9 +53,11 @@ [aliases] Main = #f3ffe7 - MainFg = #000 + MainFg = #303030 MarkedFg = #d14576 HeaderFg = MarkedFg + DirectoryFg = #000 + SelectedFg = DirectoryFg Selected = #d5f1b7 Dialog = Selected DialogFocus = #b3de85 @@ -93,7 +95,7 @@ [core] _default_ = MainFg;Main - selected = ;Selected + selected = SelectedFg;Selected marked = MarkedFg;;bold markselect = MarkedFg;Selected;bold gauge = ;DialogFocus @@ -121,7 +123,7 @@ errdtitle = ;;bold [filehighlight] - directory = + directory = DirectoryFg executable = #00af00 symlink = #870087 hardlink = diff --git a/misc/skins/seasons-summer16M.ini b/misc/skins/seasons-summer16M.ini index b95516ff8e..c817016f5f 100644 --- a/misc/skins/seasons-summer16M.ini +++ b/misc/skins/seasons-summer16M.ini @@ -53,9 +53,11 @@ [aliases] Main = #ffedb3 - MainFg = #000 + MainFg = #303030 MarkedFg = #e311aa HeaderFg = MarkedFg + DirectoryFg = #000 + SelectedFg = DirectoryFg Selected = #d9b64a Dialog = #a7f25a DialogFocus = #f864f6 @@ -93,7 +95,7 @@ [core] _default_ = MainFg;Main - selected = ;Selected + selected = SelectedFg;Selected marked = MarkedFg;;bold markselect = MarkedFg;Selected;bold gauge = ;DialogFocus @@ -121,7 +123,7 @@ errdtitle = ;;bold [filehighlight] - directory = + directory = DirectoryFg executable = #00af00 symlink = #870087 hardlink = diff --git a/misc/skins/seasons-winter16M.ini b/misc/skins/seasons-winter16M.ini index 450cd20c36..8772732829 100644 --- a/misc/skins/seasons-winter16M.ini +++ b/misc/skins/seasons-winter16M.ini @@ -53,9 +53,11 @@ [aliases] Main = #e4e3ed - MainFg = #000 + MainFg = #303030 MarkedFg = #3064a9 HeaderFg = MarkedFg + DirectoryFg = #000 + SelectedFg = DirectoryFg Selected = #cbd1e1 Dialog = Selected DialogFocus = #afbad8 @@ -93,7 +95,7 @@ [core] _default_ = MainFg;Main - selected = ;Selected + selected = SelectedFg;Selected marked = MarkedFg;;bold markselect = MarkedFg;Selected;bold gauge = ;DialogFocus @@ -121,7 +123,7 @@ errdtitle = ;;bold [filehighlight] - directory = + directory = DirectoryFg executable = #00af00 symlink = #870087 hardlink = From cd5fc97a86035c49291cfdafa6f5889c02e64f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Hork=C3=BD?= Date: Sat, 25 Oct 2025 16:14:09 +0200 Subject: [PATCH 3/4] lib/tty: Add true color support with ncurses and improve S-Lang color detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable true color support in ncurses. TERM must be set to a relevant terminfo entry, i.e. *-direct, *-direct16, or *-direct256. When set to *-direct256, both 256-color and true color mode can be used at the same time. Also fix true color detection in S-Lang. S-Lang checks for RGB terminfo capability to enable true color, so we should check for it as well. This means the COLORTERM variable doesn't need to be set when using direct terminfo variants. This also applies to simultaneous 256-color and true color mode. We need to access the RGB extended capability. This is supported in both S-Lang and ncurses, so unify the terminfo access routines to enable it. Now they should be called with both terminfo and termcap capability name. Update FAQ. Resolves: #4137 Resolves: #4821 Signed-off-by: Jakub Horký --- doc/FAQ | 56 +++++++++++++------------ lib/skin/common.c | 7 ++-- lib/tty/color-internal.c | 4 +- lib/tty/color-internal.h | 3 ++ lib/tty/color-ncurses.c | 70 +++++++++++++++++++++++++++++--- lib/tty/color-slang.c | 27 +++++++++--- lib/tty/tty-ncurses.c | 22 ++++++++-- lib/tty/tty-slang.c | 28 ++++++++++++- lib/tty/tty.c | 13 ++---- lib/tty/tty.h | 4 +- misc/skins/sand256.ini | 27 +++++------- misc/skins/seasons-autumn16M.ini | 20 ++------- misc/skins/seasons-spring16M.ini | 20 ++------- misc/skins/seasons-summer16M.ini | 20 ++------- misc/skins/seasons-winter16M.ini | 20 ++------- 15 files changed, 197 insertions(+), 144 deletions(-) diff --git a/doc/FAQ b/doc/FAQ index 1a40f6c541..942d659a70 100644 --- a/doc/FAQ +++ b/doc/FAQ @@ -403,47 +403,51 @@ Frequently Asked Questions If you get colors, be happy. If your terminal stays black and white, your terminal doesn't support - color. You might want to upgrade to a terminal which compatible with + color. You might want to upgrade to a terminal which is compatible with the ANSI color sequences. If your terminal goes completely black, see the next question. More detailed answer: - Check that your terminal supports color. color_xterm, rxvt and Linux - console do support, most other terminals don't. You can test color - support with following simple C program: + Check that your terminal supports color. Most terminals do. You can + test color support with the following command: - #include + printf "\033[32m Hello color world! \033[m\n" - int main (void){ - printf ("\033[32m Hello world! \033[m\n"); - return 0; - } + You can test 256 color support with the following command: - Compile and run it. If you see "Hello world!" text in green your - terminal supports color, otherwise not (however, for color_xterm see - also the next question). + printf "\033[38;5;120m Hello 256-color world! \033[m\n" - Check whether you are using Ncurses or the S-Lang library (type - "mc -V" to find out). + You can test true color support with the following command: - With S-Lang library you can force color support by setting the - environment variable COLORTERM to any value. + printf "\033[38;2;0;200;0m Hello true color world! \033[m\n" - If you use ncurses library, check that your terminfo database - supports color. If not, you should install one of the enhanced - terminfo databases included in GNU Midnight Commander source - distribution. + If you see the text in green, your terminal supports the respective + color mode. - You might want to set the TERM environment variable so that you are - using the correct terminfo database or termcap entry. + Check that you are using the proper TERM variable for your terminal. + If not, set it accordingly. You can use the 'toe -a' command to list + all available terminfo entries. - If you use color_xterm (or rxvt) the correct value might be - xterm-color, xtermc or simply xterm. + If your terminal supports 256 colors, the correct entry name may be + appended with -256color. If your terminal supports true color, it + should be appended with -direct, -direct16, or -direct256. The best + backwards compatibility option is -direct256 variant, which provides + both 256-color and true color support simultaneously. The -direct16 + variant supports bright versions of the basic colors along with true + color support, in contrast to the -direct variant, which supports + only basic 8 colors together with true color when used in a skin. - If you use Linux console the correct value for TERM is linux or - console. + If there is no 256-color or true-color terminfo variant for your + terminal, even though your terminal supports it, send an e-mail to + ncurses/terminfo maintainers (bug-ncurses@gnu.org) and ask them to + add one. + + With the S-Lang library (you can check by 'mc -V'), you can force + color support by setting the environment variable COLORTERM to any + value, and specifically force true color support by setting it to + 'truecolor'. 4.5 My color_xterm goes completely (or partially) black! diff --git a/lib/skin/common.c b/lib/skin/common.c index 36078cea2e..542e1971bd 100644 --- a/lib/skin/common.c +++ b/lib/skin/common.c @@ -164,9 +164,10 @@ mc_skin_init (const gchar *skin_override, GError **mcerror) if (is_good_init && mc_skin__default.have_256_colors && !tty_use_256colors (&error)) { mc_propagate_error (mcerror, 0, - _ ("Unable to use '%s' skin with 256 colors support\non non-256 colors " - "terminal.\nDefault skin has been loaded"), - mc_skin__default.name); + _ ("Unable to use '%s' skin with 256 colors support:\n%s\nDefault " + "skin has been loaded"), + mc_skin__default.name, error->message); + g_error_free (error); mc_skin_try_to_load_default (); mc_skin_colors_old_configure (&mc_skin__default); (void) mc_skin_ini_file_parse (&mc_skin__default); diff --git a/lib/tty/color-internal.c b/lib/tty/color-internal.c index 7a49f55178..dc60ca2059 100644 --- a/lib/tty/color-internal.c +++ b/lib/tty/color-internal.c @@ -155,7 +155,7 @@ parse_256_or_true_color_name (const char *color_name) i = (h[0] << 20) | (h[0] << 16) | (h[1] << 12) | (h[1] << 8) | (h[2] << 4) | h[2]; else i = (h[0] << 20) | (h[1] << 16) | (h[2] << 12) | (h[3] << 8) | (h[4] << 4) | h[5]; - return (1 << 24) | i; + return FLAG_TRUECOLOR | i; } } @@ -178,7 +178,7 @@ tty_color_get_name_by_index (int idx) return color_table[i].name; // Create and return the strings in "colorNNN" or "#rrggbb" format. - if ((idx >= 16 && idx < 256) || (idx & (1 << 24)) != 0) + if ((idx >= 16 && idx < 256) || (idx & FLAG_TRUECOLOR) != 0) { char name[9]; diff --git a/lib/tty/color-internal.h b/lib/tty/color-internal.h index 74e71743ac..e98e968bac 100644 --- a/lib/tty/color-internal.h +++ b/lib/tty/color-internal.h @@ -18,6 +18,9 @@ /*** typedefs(not structures) and defined constants **********************************************/ +#define FLAG_TRUECOLOR (1 << 24) +#define COLORS_TRUECOLOR (1 << 24) + /*** enums ***************************************************************************************/ typedef enum diff --git a/lib/tty/color-ncurses.c b/lib/tty/color-ncurses.c index a28164fde4..dec929041d 100644 --- a/lib/tty/color-ncurses.c +++ b/lib/tty/color-ncurses.c @@ -38,6 +38,7 @@ #include "lib/global.h" +#include "tty.h" #include "tty-ncurses.h" #include "color.h" // variables #include "color-internal.h" @@ -53,6 +54,7 @@ /*** file scope variables ************************************************************************/ static GHashTable *mc_tty_color_color_pair_attrs = NULL; +static int overlay_colors = 0; /* --------------------------------------------------------------------------------------------- */ /*** file scope functions ************************************************************************/ @@ -179,8 +181,9 @@ tty_color_try_alloc_lib_pair (tty_color_lib_pair_t *mc_color_pair) ibg = mc_color_pair->bg; attr = mc_color_pair->attr; - // In legacy color mode, change bright colors into bold - if (!tty_use_256colors (NULL) && !tty_use_truecolors (NULL)) + // If we have 8 indexed colors only, change foreground bright colors into bold and + // background bright colors to basic colors + if (COLORS <= 8 || (tty_use_truecolors (NULL) && overlay_colors <= 8)) { if (ifg >= 8 && ifg < 16) { @@ -191,11 +194,31 @@ tty_color_try_alloc_lib_pair (tty_color_lib_pair_t *mc_color_pair) if (ibg >= 8 && ibg < 16) { ibg &= 0x07; - // attr | = A_BOLD | A_REVERSE ; } } + // Shady trick: if we don't have the exact color, because it is overlaid by backwards + // compatibility indexed values, just borrow one degree of red. The user won't notice :) + if ((ifg & FLAG_TRUECOLOR) != 0) + { + ifg &= ~FLAG_TRUECOLOR; + if (ifg != 0 && ifg <= overlay_colors) + ifg += (1 << 16); + } + + if ((ibg & FLAG_TRUECOLOR) != 0) + { + ibg &= ~FLAG_TRUECOLOR; + if (ibg != 0 && ibg <= overlay_colors) + ibg += (1 << 16); + } + +#if NCURSES_VERSION_PATCH >= 20170401 && defined(NCURSES_EXT_COLORS) && defined(NCURSES_EXT_FUNCS) \ + && defined(HAVE_NCURSES_WIDECHAR) + init_extended_pair (mc_color_pair->pair_index, ifg, ibg); +#else init_pair (mc_color_pair->pair_index, ifg, ibg); +#endif mc_tty_color_save_attr (mc_color_pair->pair_index, attr); } } @@ -231,7 +254,19 @@ tty_use_256colors (GError **error) { (void) error; - return (COLORS == 256); + overlay_colors = tty_tigetnum ("CO", NULL); + + if (COLORS != 256 && !(COLORS > 256 && overlay_colors == 256)) + { + g_set_error (error, MC_ERROR, -1, + _ ("\nIf your terminal supports 256 colors, you need to set your TERM\n" + "environment variable to match your terminal, perhaps using\n" + "a *-256color or *-direct256 variant. Use the 'toe -a'\n" + "command to list all available variants on your system.\n")); + return FALSE; + } + + return TRUE; } /* --------------------------------------------------------------------------------------------- */ @@ -239,9 +274,32 @@ tty_use_256colors (GError **error) gboolean tty_use_truecolors (GError **error) { - // Not yet supported in ncurses - g_set_error (error, MC_ERROR, -1, _ ("True color not supported with ncurses.")); + // Low level true color is supported since ncurses 6.0 patch 20170401 preceding release + // of ncurses 6.1. It needs ABI 6 or higher. +#if !(NCURSES_VERSION_PATCH >= 20170401 && defined(NCURSES_EXT_COLORS) \ + && defined(NCURSES_EXT_FUNCS) && defined(HAVE_NCURSES_WIDECHAR)) + g_set_error (error, MC_ERROR, -1, + _ ("For true color support, you need version 6.1 or later of the ncurses\n" + "library with wide character and ABI 6 or higher support.\n" + "Please upgrade your system.\n")); return FALSE; +#else + // We support only bool RGB cap configuration (8:8:8 bits), but the other variants are so rare + // that we don't need to bother. + if (!(tty_tigetflag ("RGB", NULL) && COLORS == COLORS_TRUECOLOR)) + { + g_set_error ( + error, MC_ERROR, -1, + _ ("\nIf your terminal supports true colors, you need to set your TERM\n" + "environment variable to a *-direct256, *-direct16, or *-direct variant.\n" + "Use the 'toe -a' command to list all available variants on your system.\n")); + return FALSE; + } + + overlay_colors = tty_tigetnum ("CO", NULL); + + return TRUE; +#endif } /* --------------------------------------------------------------------------------------------- */ diff --git a/lib/tty/color-slang.c b/lib/tty/color-slang.c index 78a618299b..b2c6c04b52 100644 --- a/lib/tty/color-slang.c +++ b/lib/tty/color-slang.c @@ -38,6 +38,7 @@ #include "lib/global.h" #include "lib/util.h" // whitespace() +#include "tty.h" #include "tty-slang.h" #include "color.h" // variables #include "color-internal.h" @@ -61,7 +62,10 @@ has_colors (gboolean disable, gboolean force) { mc_tty_color_disable = disable; - if (force || (getenv ("COLORTERM") != NULL)) + // S-Lang enables color if the setaf/setab/setf/setb terminfo capabilities are set or + // the COLORTERM environment variable is set + + if (force) SLtt_Use_Ansi_Colors = 1; if (!mc_tty_color_disable) @@ -215,12 +219,19 @@ gboolean tty_use_256colors (GError **error) { gboolean ret; + int colors, overlay_colors; + + colors = tty_tigetnum ("colors", "Co"); + overlay_colors = tty_tigetnum ("CO", NULL); - ret = (SLtt_Use_Ansi_Colors && SLtt_tgetnum ((char *) "Co") == 256); + ret = (SLtt_Use_Ansi_Colors && (colors == 256 || (colors > 256 && overlay_colors == 256))); if (!ret) g_set_error (error, MC_ERROR, -1, - _ ("Your terminal doesn't even seem to support 256 colors.")); + _ ("\nIf your terminal supports 256 colors, you need to set your TERM\n" + "environment variable to match your terminal, perhaps using\n" + "a *-256color or *-direct256 variant. Use the 'toe -a'\n" + "command to list all available variants on your system.\n")); return ret; } @@ -245,11 +256,15 @@ tty_use_truecolors (GError **error) /* Duplicate slang's check so that we can pop up an error message rather than silently use wrong colors. */ colorterm = getenv ("COLORTERM"); - if (colorterm == NULL - || (strcmp (colorterm, "truecolor") != 0 && strcmp (colorterm, "24bit") != 0)) + if (!((tty_tigetflag ("RGB", NULL) && tty_tigetnum ("colors", "Co") == COLORS_TRUECOLOR) + || (colorterm != NULL + && (strcmp (colorterm, "truecolor") == 0 || strcmp (colorterm, "24bit") == 0)))) { g_set_error (error, MC_ERROR, -1, - _ ("Set COLORTERM=truecolor if your terminal really supports true colors.")); + _ ("\nIf your terminal supports true colors, you need to set your TERM\n" + "environment variable to a *-direct256, *-direct16, or *-direct variant.\n" + "Use the 'toe -a' command to list all available variants on your system.\n" + "Alternatively, you can set COLORTERM=truecolor.\n")); return FALSE; } diff --git a/lib/tty/tty-ncurses.c b/lib/tty/tty-ncurses.c index ff0c4216fd..b3874a1237 100644 --- a/lib/tty/tty-ncurses.c +++ b/lib/tty/tty-ncurses.c @@ -739,12 +739,26 @@ tty_printf (const char *fmt, ...) /* --------------------------------------------------------------------------------------------- */ -char * -tty_tgetstr (const char *cap) +int +tty_tigetflag (const char *terminfo_cap, MC_UNUSED const char *termcap_cap) { - char *unused = NULL; + return tigetflag ((NCURSES_CONST char *) terminfo_cap); +} - return tgetstr ((NCURSES_CONST char *) cap, &unused); +/* --------------------------------------------------------------------------------------------- */ + +int +tty_tigetnum (const char *terminfo_cap, MC_UNUSED const char *termcap_cap) +{ + return tigetnum ((NCURSES_CONST char *) terminfo_cap); +} + +/* --------------------------------------------------------------------------------------------- */ + +char * +tty_tigetstr (const char *terminfo_cap, MC_UNUSED const char *termcap_cap) +{ + return tigetstr ((NCURSES_CONST char *) terminfo_cap); } /* --------------------------------------------------------------------------------------------- */ diff --git a/lib/tty/tty-slang.c b/lib/tty/tty-slang.c index 90b9c9e5ca..570c2c88ec 100644 --- a/lib/tty/tty-slang.c +++ b/lib/tty/tty-slang.c @@ -756,10 +756,34 @@ tty_printf (const char *fmt, ...) /* --------------------------------------------------------------------------------------------- */ +/* Although S-Lang uses the terminfo database by default (through its own parser), it expects + * termcap codes to access standard capabilities. Nevertheless, it can also access extended + * terminfo capabilities (including those that have no termcap equivalent, i.e., whose names + * are longer than two characters). + */ + +/* --------------------------------------------------------------------------------------------- */ + +int +tty_tigetflag (const char *terminfo_cap, const char *termcap_cap) +{ + return SLtt_tgetflag ((SLFUTURE_CONST char *) (termcap_cap ? termcap_cap : terminfo_cap)); +} + +/* --------------------------------------------------------------------------------------------- */ + +int +tty_tigetnum (const char *terminfo_cap, const char *termcap_cap) +{ + return SLtt_tgetnum ((SLFUTURE_CONST char *) (termcap_cap ? termcap_cap : terminfo_cap)); +} + +/* --------------------------------------------------------------------------------------------- */ + char * -tty_tgetstr (const char *cap) +tty_tigetstr (const char *terminfo_cap, const char *termcap_cap) { - return SLtt_tgetstr ((SLFUTURE_CONST char *) cap); + return SLtt_tgetstr ((SLFUTURE_CONST char *) (termcap_cap ? termcap_cap : terminfo_cap)); } /* --------------------------------------------------------------------------------------------- */ diff --git a/lib/tty/tty.c b/lib/tty/tty.c index 28a2148f19..0adc36132a 100644 --- a/lib/tty/tty.c +++ b/lib/tty/tty.c @@ -371,16 +371,9 @@ tty_init_xterm_support (gboolean is_xterm) // Check mouse and ca capabilities /* terminfo/termcap structures have been already initialized, in slang_init() or/and init_curses() */ - // Check terminfo at first, then check termcap - xmouse_seq = tty_tgetstr ("kmous"); - if (xmouse_seq == NULL) - xmouse_seq = tty_tgetstr ("Km"); - smcup = tty_tgetstr ("smcup"); - if (smcup == NULL) - smcup = tty_tgetstr ("ti"); - rmcup = tty_tgetstr ("rmcup"); - if (rmcup == NULL) - rmcup = tty_tgetstr ("te"); + xmouse_seq = tty_tigetstr ("kmous", "Km"); + smcup = tty_tigetstr ("smcup", "ti"); + rmcup = tty_tigetstr ("rmcup", "te"); if (strcmp (termvalue, "cygwin") == 0) { diff --git a/lib/tty/tty.h b/lib/tty/tty.h index 9bd7e87484..86854dec35 100644 --- a/lib/tty/tty.h +++ b/lib/tty/tty.h @@ -63,7 +63,9 @@ typedef enum extern int mc_tty_frm[]; -extern char *tty_tgetstr (const char *name); +extern int tty_tigetflag (const char *terminfo_cap, const char *termcap_cap); +extern int tty_tigetnum (const char *terminfo_cap, const char *termcap_cap); +extern char *tty_tigetstr (const char *terminfo_cap, const char *termcap_cap); /*** declarations of public functions ************************************************************/ diff --git a/misc/skins/sand256.ini b/misc/skins/sand256.ini index 34e7dc25d1..3f521670e6 100644 --- a/misc/skins/sand256.ini +++ b/misc/skins/sand256.ini @@ -1,11 +1,6 @@ # This skin demonstrates how to use 256 colors in mc. # -# As a prerequisite, you will need to: -# 1) Have a terminal emulator that supports 256 colors (a few examples: -# xterm, Gnome terminal and other VTE derivatives, KDE's Konsole; -# iTerm for Mac OS X, PuTTY for Windows). -# 2) Adjust your TERM variable accordingly, e.g.: export TERM=xterm-256color -# Verify by running tput colors +# See the FAQ for instructions on setting up 256 colors. # # Each of the 256 colors has two names, you can use whichever you prefer. # @@ -22,16 +17,16 @@ # magenta brightmagenta # cyan brightcyan # lightgray white -# Note that with 8/16 color terminal settings (such as TERM=xterm), colors -# of the second column can only be used for the foreground, and their actual -# interpretation varies across terminals. Some terminals show the colors -# from the first column instead (that is, you only have 8 colors), but make -# them bold. Others show the brighter version (16 foreground colors). Yet -# others make them bold and bright at the same time. Switching to 256 colors -# should end this ambiguity: you should have 16 separate colors according to -# their names, none of them are bold by default but any of them can be -# switched to bold, and all of them are available for background, too. This -# is the intended behavior, the actual behavior might vary across terminals. +# Note that with 8 color terminal settings (such as TERM=xterm), colors of +# the second column are emulated using the bold attribute (which many +# terminals display as bright colors) for the foreground, and mapped to the +# basic 8 colors for the background. With 16 color terminal settings, the +# actual implementation of bright colors varies across terminals. Most +# terminals show true bright colors for foreground and background. However, +# some terminals show the colors from the first column instead (that is, +# you only have 8 colors), but make them bold. Yet others make them bold +# and bright at the same time. So it is safer to use the rest of the colors +# (color16 to color255). # # Colors of the 6x6x6 cube ("color16" to "color231") can alternatively be # referred to as "rgb000" to "rgb555", all three digits ranging from 0 to 5, diff --git a/misc/skins/seasons-autumn16M.ini b/misc/skins/seasons-autumn16M.ini index 00dd95fe49..6653955080 100644 --- a/misc/skins/seasons-autumn16M.ini +++ b/misc/skins/seasons-autumn16M.ini @@ -1,26 +1,12 @@ # The Four Seasons skins demonstrate how to use direct RGB true colors. # -# As a prerequisite, you will need: -# 1) Midnight Commander version 4.8.19 or newer. -# 2) Midnight Commander being compiled against S-Lang (rather than ncurses). -# 3) S-Lang version 2.3.2 or newer. -# 4) A terminal emulator that supports true colors, such as e.g. -# GNOME Terminal and other VTE derivatives, KDE's Konsole, -# iTerm2 for macOS. See https://github.com/termstandard/colors for a -# more exhaustive and up to date list. -# 5) The TERM environment variable describing 256 color support, e.g.: -# export TERM=xterm-256color -# or inside screen or tmux: -# export TERM=screen-256color -# Verify by running tput colors, it should report 256. -# 6) The COLORTERM env variable set to either "truecolor" or "24bit", e.g.: -# export COLORTERM=truecolor +# See the FAQ for instructions on setting up true colors. # # True colors are referred to by the standard #rrggbb or #rgb notation, the # short form is interpreted by doubling each hex digit. # -# In addition to these the 256 palette colors are still available, and -# obviously so are the attributes. See the sand256.ini skin file for details. +# In addition to these, you can use the basic 8 (non-light) colors and +# the attributes. However, you can't use the 256 indexed colors. [skin] # Falling leaves, beautiful forests, Halloween pumpkins. diff --git a/misc/skins/seasons-spring16M.ini b/misc/skins/seasons-spring16M.ini index 5820220227..883be45eb5 100644 --- a/misc/skins/seasons-spring16M.ini +++ b/misc/skins/seasons-spring16M.ini @@ -1,26 +1,12 @@ # The Four Seasons skins demonstrate how to use direct RGB true colors. # -# As a prerequisite, you will need: -# 1) Midnight Commander version 4.8.19 or newer. -# 2) Midnight Commander being compiled against S-Lang (rather than ncurses). -# 3) S-Lang version 2.3.2 or newer. -# 4) A terminal emulator that supports true colors, such as e.g. -# GNOME Terminal and other VTE derivatives, KDE's Konsole, -# iTerm2 for macOS. See https://github.com/termstandard/colors for a -# more exhaustive and up to date list. -# 5) The TERM environment variable describing 256 color support, e.g.: -# export TERM=xterm-256color -# or inside screen or tmux: -# export TERM=screen-256color -# Verify by running tput colors, it should report 256. -# 6) The COLORTERM env variable set to either "truecolor" or "24bit", e.g.: -# export COLORTERM=truecolor +# See the FAQ for instructions on setting up true colors. # # True colors are referred to by the standard #rrggbb or #rgb notation, the # short form is interpreted by doubling each hex digit. # -# In addition to these the 256 palette colors are still available, and -# obviously so are the attributes. See the sand256.ini skin file for details. +# In addition to these, you can use the basic 8 (non-light) colors and +# the attributes. However, you can't use the 256 indexed colors. [skin] # Blooming. diff --git a/misc/skins/seasons-summer16M.ini b/misc/skins/seasons-summer16M.ini index c817016f5f..fed4543840 100644 --- a/misc/skins/seasons-summer16M.ini +++ b/misc/skins/seasons-summer16M.ini @@ -1,26 +1,12 @@ # The Four Seasons skins demonstrate how to use direct RGB true colors. # -# As a prerequisite, you will need: -# 1) Midnight Commander version 4.8.19 or newer. -# 2) Midnight Commander being compiled against S-Lang (rather than ncurses). -# 3) S-Lang version 2.3.2 or newer. -# 4) A terminal emulator that supports true colors, such as e.g. -# GNOME Terminal and other VTE derivatives, KDE's Konsole, -# iTerm2 for macOS. See https://github.com/termstandard/colors for a -# more exhaustive and up to date list. -# 5) The TERM environment variable describing 256 color support, e.g.: -# export TERM=xterm-256color -# or inside screen or tmux: -# export TERM=screen-256color -# Verify by running tput colors, it should report 256. -# 6) The COLORTERM env variable set to either "truecolor" or "24bit", e.g.: -# export COLORTERM=truecolor +# See the FAQ for instructions on setting up true colors. # # True colors are referred to by the standard #rrggbb or #rgb notation, the # short form is interpreted by doubling each hex digit. # -# In addition to these the 256 palette colors are still available, and -# obviously so are the attributes. See the sand256.ini skin file for details. +# In addition to these, you can use the basic 8 (non-light) colors and +# the attributes. However, you can't use the 256 indexed colors. [skin] # Sunshine, ocean, beach, beachball, sunshades, ice cream. diff --git a/misc/skins/seasons-winter16M.ini b/misc/skins/seasons-winter16M.ini index 8772732829..7d8eafaf41 100644 --- a/misc/skins/seasons-winter16M.ini +++ b/misc/skins/seasons-winter16M.ini @@ -1,26 +1,12 @@ # The Four Seasons skins demonstrate how to use direct RGB true colors. # -# As a prerequisite, you will need: -# 1) Midnight Commander version 4.8.19 or newer. -# 2) Midnight Commander being compiled against S-Lang (rather than ncurses). -# 3) S-Lang version 2.3.2 or newer. -# 4) A terminal emulator that supports true colors, such as e.g. -# GNOME Terminal and other VTE derivatives, KDE's Konsole, -# iTerm2 for macOS. See https://github.com/termstandard/colors for a -# more exhaustive and up to date list. -# 5) The TERM environment variable describing 256 color support, e.g.: -# export TERM=xterm-256color -# or inside screen or tmux: -# export TERM=screen-256color -# Verify by running tput colors, it should report 256. -# 6) The COLORTERM env variable set to either "truecolor" or "24bit", e.g.: -# export COLORTERM=truecolor +# See the FAQ for instructions on setting up true colors. # # True colors are referred to by the standard #rrggbb or #rgb notation, the # short form is interpreted by doubling each hex digit. # -# In addition to these the 256 palette colors are still available, and -# obviously so are the attributes. See the sand256.ini skin file for details. +# In addition to these, you can use the basic 8 (non-light) colors and +# the attributes. However, you can't use the 256 indexed colors. [skin] # The sun is shining and the grass is green, From 5633ffee7e9ba4d5ba8995e72f96d392ac26ebcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Hork=C3=BD?= Date: Mon, 27 Oct 2025 17:09:06 +0100 Subject: [PATCH 4/4] lib/tty: Add compatibility translation from 256 colors to true colors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the terminal does not support 256 colors but does support true color, allow the use of 256-color skins by adding a translation layer that computes direct color values from 256-color palette. Signed-off-by: Jakub Horký --- doc/FAQ | 12 +++++------ lib/tty/color-internal.c | 34 ++++++++++++++++++++++++++++++++ lib/tty/color-internal.h | 2 ++ lib/tty/color-ncurses.c | 24 ++++++++++++++-------- lib/tty/color-slang.c | 27 ++++++++++++++++--------- lib/tty/color.c | 11 +++++++++++ misc/skins/seasons-spring16M.ini | 4 ++-- misc/skins/seasons-summer16M.ini | 4 ++-- misc/skins/seasons-winter16M.ini | 4 ++-- 9 files changed, 93 insertions(+), 29 deletions(-) diff --git a/doc/FAQ b/doc/FAQ index 942d659a70..1670c4c56a 100644 --- a/doc/FAQ +++ b/doc/FAQ @@ -432,12 +432,12 @@ Frequently Asked Questions If your terminal supports 256 colors, the correct entry name may be appended with -256color. If your terminal supports true color, it - should be appended with -direct, -direct16, or -direct256. The best - backwards compatibility option is -direct256 variant, which provides - both 256-color and true color support simultaneously. The -direct16 - variant supports bright versions of the basic colors along with true - color support, in contrast to the -direct variant, which supports - only basic 8 colors together with true color when used in a skin. + should be appended with -direct, -direct16, or -direct256. All three + variants provide both 256-color and true color support simultaneously. + The latter two variants make no difference in mc, and they support + basic colors including their bright versions along with true color + support, in contrast to the -direct variant, which supports only basic + 8 colors together with true color when used in a skin. If there is no 256-color or true-color terminfo variant for your terminal, even though your terminal supports it, send an e-mail to diff --git a/lib/tty/color-internal.c b/lib/tty/color-internal.c index dc60ca2059..9c740ca686 100644 --- a/lib/tty/color-internal.c +++ b/lib/tty/color-internal.c @@ -241,3 +241,37 @@ tty_attr_get_bits (const char *attrs) } /* --------------------------------------------------------------------------------------------- */ + +int +convert_256color_to_truecolor (int color) +{ + int r, g, b; + + // Invalid color + if (color > 255) + return 0; + + if (color >= 232) // Gray scale + r = g = b = (color - 231) * 10 + 8; + else if (color >= 16) // 6x6x6 color cube + { + color -= 16; + + r = (color / (6 * 6) % 6); + r = r > 0 ? r * 40 + 55 : 0; + + g = (color / 6 % 6); + g = g > 0 ? g * 40 + 55 : 0; + + b = (color % 6); + b = b > 0 ? b * 40 + 55 : 0; + } + else // We don't convert basic 16 colors as they are terminal-dependent and user-configurable + return color; + + color = FLAG_TRUECOLOR | (r << 16) | (g << 8) | b; + + return color; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/lib/tty/color-internal.h b/lib/tty/color-internal.h index e98e968bac..76863d4772 100644 --- a/lib/tty/color-internal.h +++ b/lib/tty/color-internal.h @@ -47,12 +47,14 @@ typedef struct extern gboolean use_colors; extern gboolean mc_tty_color_disable; +extern gboolean need_convert_256color; /*** declarations of public functions ************************************************************/ const char *tty_color_get_name_by_index (int idx); int tty_color_get_index_by_name (const char *color_name); int tty_attr_get_bits (const char *attrs); +int convert_256color_to_truecolor (int color); void tty_color_init_lib (gboolean disable, gboolean force); void tty_color_deinit_lib (void); diff --git a/lib/tty/color-ncurses.c b/lib/tty/color-ncurses.c index dec929041d..de4d2b4a41 100644 --- a/lib/tty/color-ncurses.c +++ b/lib/tty/color-ncurses.c @@ -129,6 +129,10 @@ tty_color_init_lib (gboolean disable, gboolean force) use_colors = TRUE; start_color (); use_default_colors (); + + // Extended color mode detection routines must first be called before loading any skin + tty_use_256colors (NULL); + tty_use_truecolors (NULL); } mc_tty_color_color_pair_attrs = g_hash_table_new_full ( @@ -256,17 +260,21 @@ tty_use_256colors (GError **error) overlay_colors = tty_tigetnum ("CO", NULL); - if (COLORS != 256 && !(COLORS > 256 && overlay_colors == 256)) + if (COLORS == 256 || (COLORS > 256 && overlay_colors == 256)) + return TRUE; + + if (tty_use_truecolors (NULL)) { - g_set_error (error, MC_ERROR, -1, - _ ("\nIf your terminal supports 256 colors, you need to set your TERM\n" - "environment variable to match your terminal, perhaps using\n" - "a *-256color or *-direct256 variant. Use the 'toe -a'\n" - "command to list all available variants on your system.\n")); - return FALSE; + need_convert_256color = TRUE; + return TRUE; } - return TRUE; + g_set_error (error, MC_ERROR, -1, + _ ("\nIf your terminal supports 256 colors, you need to set your TERM\n" + "environment variable to match your terminal, perhaps using\n" + "a *-256color or *-direct256 variant. Use the 'toe -a'\n" + "command to list all available variants on your system.\n")); + return FALSE; } /* --------------------------------------------------------------------------------------------- */ diff --git a/lib/tty/color-slang.c b/lib/tty/color-slang.c index b2c6c04b52..f8c177847c 100644 --- a/lib/tty/color-slang.c +++ b/lib/tty/color-slang.c @@ -136,6 +136,10 @@ tty_color_init_lib (gboolean disable, gboolean force) if (has_colors (disable, force) && !disable) { use_colors = TRUE; + + // Extended color mode detection routines must first be called before loading any skin + tty_use_256colors (NULL); + tty_use_truecolors (NULL); } } @@ -218,22 +222,27 @@ tty_set_normal_attrs (void) gboolean tty_use_256colors (GError **error) { - gboolean ret; int colors, overlay_colors; colors = tty_tigetnum ("colors", "Co"); overlay_colors = tty_tigetnum ("CO", NULL); - ret = (SLtt_Use_Ansi_Colors && (colors == 256 || (colors > 256 && overlay_colors == 256))); + if (SLtt_Use_Ansi_Colors && (colors == 256 || (colors > 256 && overlay_colors == 256))) + return TRUE; - if (!ret) - g_set_error (error, MC_ERROR, -1, - _ ("\nIf your terminal supports 256 colors, you need to set your TERM\n" - "environment variable to match your terminal, perhaps using\n" - "a *-256color or *-direct256 variant. Use the 'toe -a'\n" - "command to list all available variants on your system.\n")); + if (tty_use_truecolors (NULL)) + { + need_convert_256color = TRUE; + return TRUE; + } + + g_set_error (error, MC_ERROR, -1, + _ ("\nIf your terminal supports 256 colors, you need to set your TERM\n" + "environment variable to match your terminal, perhaps using\n" + "a *-256color or *-direct256 variant. Use the 'toe -a'\n" + "command to list all available variants on your system.\n")); - return ret; + return FALSE; } /* --------------------------------------------------------------------------------------------- */ diff --git a/lib/tty/color.c b/lib/tty/color.c index 750c0ce505..512659b411 100644 --- a/lib/tty/color.c +++ b/lib/tty/color.c @@ -53,6 +53,8 @@ static tty_color_pair_t tty_color_defaults = { /* Set if we are actually using colors */ gboolean use_colors = FALSE; +gboolean need_convert_256color = FALSE; + /*** file scope macro definitions ****************************************************************/ /*** file scope type declarations ****************************************************************/ @@ -175,6 +177,15 @@ tty_try_alloc_color_pair (const tty_color_pair_t *color, gboolean is_temp) return mc_color_pair->pair_index; } + if (need_convert_256color) + { + if ((ifg & FLAG_TRUECOLOR) == 0) + ifg = convert_256color_to_truecolor (ifg); + + if ((ibg & FLAG_TRUECOLOR) == 0) + ibg = convert_256color_to_truecolor (ibg); + } + mc_color_pair = g_try_new0 (tty_color_lib_pair_t, 1); if (mc_color_pair == NULL) { diff --git a/misc/skins/seasons-spring16M.ini b/misc/skins/seasons-spring16M.ini index 883be45eb5..e3f1abad5b 100644 --- a/misc/skins/seasons-spring16M.ini +++ b/misc/skins/seasons-spring16M.ini @@ -5,8 +5,8 @@ # True colors are referred to by the standard #rrggbb or #rgb notation, the # short form is interpreted by doubling each hex digit. # -# In addition to these, you can use the basic 8 (non-light) colors and -# the attributes. However, you can't use the 256 indexed colors. +# In addition to these the 256 palette colors are still available, and +# obviously so are the attributes. See the sand256.ini skin file for details. [skin] # Blooming. diff --git a/misc/skins/seasons-summer16M.ini b/misc/skins/seasons-summer16M.ini index fed4543840..0cceca1e8f 100644 --- a/misc/skins/seasons-summer16M.ini +++ b/misc/skins/seasons-summer16M.ini @@ -5,8 +5,8 @@ # True colors are referred to by the standard #rrggbb or #rgb notation, the # short form is interpreted by doubling each hex digit. # -# In addition to these, you can use the basic 8 (non-light) colors and -# the attributes. However, you can't use the 256 indexed colors. +# In addition to these the 256 palette colors are still available, and +# obviously so are the attributes. See the sand256.ini skin file for details. [skin] # Sunshine, ocean, beach, beachball, sunshades, ice cream. diff --git a/misc/skins/seasons-winter16M.ini b/misc/skins/seasons-winter16M.ini index 7d8eafaf41..1d0e2e366f 100644 --- a/misc/skins/seasons-winter16M.ini +++ b/misc/skins/seasons-winter16M.ini @@ -5,8 +5,8 @@ # True colors are referred to by the standard #rrggbb or #rgb notation, the # short form is interpreted by doubling each hex digit. # -# In addition to these, you can use the basic 8 (non-light) colors and -# the attributes. However, you can't use the 256 indexed colors. +# In addition to these the 256 palette colors are still available, and +# obviously so are the attributes. See the sand256.ini skin file for details. [skin] # The sun is shining and the grass is green,