Browse Source

Ticket #2169: Add support for 256 colors terminals

Forget the old limit of 8 background and 16 foreground colors.
From now on Midnight Commander can use all the 256 colors,
as your favorite terminal emulator supports them - or not,
in which case it's not going to stay your favorite terminal for long.

Signed-off-by: Slava Zanko <slavazanko@gmail.com>
Egmont Koblinger 14 years ago
parent
commit
e593572bb9
10 changed files with 170 additions and 74 deletions
  1. 3 0
      AUTHORS
  2. 22 10
      doc/man/mc.1.in
  3. 15 3
      doc/man/mcedit.1.in
  4. 1 1
      doc/man/mcview.1.in
  5. 7 4
      lib/skin/colors-old.c
  6. 17 31
      lib/skin/colors.c
  7. 4 2
      lib/skin/common.c
  8. 1 0
      lib/skin/internal.h
  9. 96 19
      lib/tty/color-internal.c
  10. 4 4
      lib/tty/color-internal.h

+ 3 - 0
AUTHORS

@@ -59,6 +59,9 @@ Anton Chumak <nightfast@yahoo.co.uk>
 Antonio Palama, DOS port <palama@posso.dm.unipi.it>
 	DOS port.
 
+Egmont Koblinger <egmont@gmail.com>
+        Support of 256 colors
+
 Erwin van Eijk <wabbit@corner.iaf.nl>
 
 Gerd Knorr <kraxel@cs.tu-berlin.de>

+ 22 - 10
doc/man/mc.1.in

@@ -3417,7 +3417,7 @@ xterm=menu=magenta:marked=,magenta:markselect=,red
 The format for the color definition is:
 .PP
 .nf
-  <keyword>=<foregroundcolor>,<backgroundcolor>:<keyword>= ...
+  <keyword>=<fgcolor>,<bgcolor>,<attributes>:<keyword>=...
 .fi
 .PP
 The colors are optional, and the keywords are: normal, selected, disabled, marked,
@@ -3481,12 +3481,22 @@ The possible colors are: black, gray, red, brightred, green,
 brightgreen, brown, yellow, blue, brightblue, magenta, brightmagenta,
 cyan, brightcyan, lightgray and white. And there is a special keyword
 for transparent background. It is 'default'. The 'default' can only be
-used for background color. Example:
+used for background color. Another special keyword "base" means mc's main
+colors.  When 256 colors are available, they can be specified either as
+color16 to color255, or as rgb000 to rgb555 and gray0 to gray23. Example:
 .PP
 .nf
 [Colors]
 base_color=normal=white,default:marked=magenta,default
 .fi
+.PP
+Attributes can be any of bold, underline, reverse and blink, appended by a
+plus sign if more than one are desired.  The special word "none" means no
+attributes, without attempting to fall back to base_color.  Example:
+.PP
+.nf
+menuhotsel=yellow;black;bold+underline
+.fi
 
 .\"NODE "Skins"
 .SH "Skins"
@@ -3727,11 +3737,12 @@ attribute
 .SH "  Color pair definitions"
 Any parameter in skin\-file contain definition of color pair.
 .PP
-Color pairs described as two colors separated by ';'. First color
-sets the foreground color, second color sets background color.
-One of the colors may be omitted, in this case color will be
-taken from default color pair (global color pair  or
-from default color pair of this section).
+Color pairs described as two colors and the optional attributes
+separated by ';'. First field sets the foreground color, second
+field sets background color, third field sets the attributes.
+Any of the fields may be omitted, in this case value will be
+taken from default color pair (global color pair or from default
+color pair of this section).
 .PP
 Example:
 .br
@@ -3739,14 +3750,15 @@ Example:
 [core]
     # green on black
     _default_=green;black
-    # green (default)  on blue
+    # green (default) on blue
     selected=;blue
     # yellow on black (default)
-    marked=yellow;
+    # underlined yellow on black (default)
+    marked=yellow;;underline
 .fi
 
 .PP
-Possible colors (names) described in
+Possible colors (names) and attributes are described in
 .\"LINK2"
 Colors\&.
 .\"Colors"

+ 15 - 3
doc/man/mcedit.1.in

@@ -33,7 +33,7 @@ Force black and white display.
 Force ANSI color mode on terminals that don't seem to have color
 support.
 .TP
-.I "\-C <keyword>=<FGcolor>,<BGcolor>:<keyword>= ..."
+.I "\-C <keyword>=<fgcolor>,<bgcolor>,<attributes>:<keyword>= ..."
 Specify a different color set.  See the
 .B Colors
 section in mc(1) for more information.
@@ -249,12 +249,14 @@ Each context starts with a line of the form:
 .I delim
 .RI [ foreground ]
 .RI [ background ]
+.RI [ attributes ]
 .PP
 The first context is an exception.  It must start with the command
 .PP
 .B context default
 .RI [ foreground ]
 .RI [ background ]
+.RI [ attributes ]
 .PP
 otherwise
 .B mcedit
@@ -294,6 +296,7 @@ Each rule is a line of the form:
 .RB [ linestart ]
 .I string foreground
 .RI [ background ]
+.RI [ attributes ]
 .PP
 Context or keyword strings are interpreted, so that you can include tabs
 and spaces with the sequences \\t and \\s.  Newlines and backslashes are
@@ -331,8 +334,14 @@ directive to continue across multiple lines.
 .PP
 The possible colors are: black, gray, red, brightred, green,
 brightgreen, brown, yellow, blue, brightblue, magenta, brightmagenta,
-cyan, brightcyan, lightgray and white.  If the syntax file is shared
-with
+cyan, brightcyan, lightgray and white. The special keyword "default" means
+the terminal's default. Another special keyword "base" means mc's main
+colors, it is useful as a placeholder if you want to specify attributes
+without modifying the background color. When 256 colors are available,
+they can be specified either as color16 to color255, or as rgb000 to rgb555
+and gray0 to gray23.
+.PP
+If the syntax file is shared with
 .BR cooledit ,
 it is possible to specify different colors for
 .B mcedit
@@ -349,6 +358,9 @@ uses the color before the slash.  See cooledit(1) for supported
 .B cooledit
 colors.
 .PP
+Attributes can be any of bold, underline, reverse and blink, appended by a
+plus sign if more than one are desired.
+.PP
 Comments may be put on a separate line starting with the hash sign (#).
 .PP
 If you are describing case insensitive language you need to use

+ 1 - 1
doc/man/mcview.1.in

@@ -23,7 +23,7 @@ Force color mode on terminals where
 .B mcview
 defaults to black and white.
 .TP
-.I "\-C <keyword>=<FGcolor>,<BGcolor>:<keyword>= ..."
+.I "\-C <keyword>=<fgcolor>,<bgcolor>,<attributes>:<keyword>= ..."
 Specify a different color set.  See the
 .B Colors
 section in mc(1) for more information.

+ 7 - 4
lib/skin/colors-old.c

@@ -2,10 +2,11 @@
    Skins engine.
    Work with colors - backward compability
 
-   Copyright (C) 2009 The Free Software Foundation, Inc.
+   Copyright (C) 2009, 2010 The Free Software Foundation, Inc.
 
    Written by:
-   Slava Zanko <slavazanko@gmail.com>, 2009.
+   Slava Zanko <slavazanko@gmail.com>, 2009
+   Egmont Koblinger <egmont@gmail.com>, 2010
 
    This file is part of the Midnight Commander.
 
@@ -135,7 +136,7 @@ mc_skin_colors_old_configure_one (mc_skin_t * mc_skin, const char *the_color_str
 
     for (; *colors; colors++)
     {
-        key_val = g_strsplit_set (*colors, "=,", 3);
+        key_val = g_strsplit_set (*colors, "=,", 4);
 
         if (!key_val)
             continue;
@@ -147,7 +148,9 @@ mc_skin_colors_old_configure_one (mc_skin_t * mc_skin, const char *the_color_str
             continue;
         }
 
-        if (key_val[2] != NULL)
+        if (key_val[3] != NULL)
+            skin_val = g_strdup_printf ("%s;%s;%s", key_val[1], key_val[2], key_val[3]);
+        else if (key_val[2] != NULL)
             skin_val = g_strdup_printf ("%s;%s", key_val[1], key_val[2]);
         else
             skin_val = g_strdup_printf ("%s;", key_val[1]);

+ 17 - 31
lib/skin/colors.c

@@ -2,10 +2,11 @@
    Skins engine.
    Work with colors
 
-   Copyright (C) 2009 The Free Software Foundation, Inc.
+   Copyright (C) 2009, 2010 The Free Software Foundation, Inc.
 
    Written by:
-   Slava Zanko <slavazanko@gmail.com>, 2009.
+   Slava Zanko <slavazanko@gmail.com>, 2009
+   Egmont Koblinger <egmont@gmail.com>, 2010
 
    This file is part of the Midnight Commander.
 
@@ -144,36 +145,19 @@ mc_skin_color_get_from_ini_file (mc_skin_t * mc_skin, const gchar * group, const
         return NULL;
     }
 
-    switch (items_count)
-    {
-    case 0:
-        tmp = mc_skin_color_get_with_defaults (group, "_default_");
-        if (tmp != NULL)
-        {
-            mc_skin_color->fgcolor = g_strdup (tmp->fgcolor);
-            mc_skin_color->bgcolor = g_strdup (tmp->bgcolor);
-        }
-        else
-        {
-            g_strfreev (values);
-            g_free (mc_skin_color);
-            return NULL;
-        }
-        break;
-    case 1:
-        mc_skin_color->fgcolor = (values[0]) ? g_strstrip (g_strdup (values[0])) : NULL;
-        tmp = mc_skin_color_get_with_defaults (group, "_default_");
-        mc_skin_color->bgcolor = (tmp != NULL) ? g_strdup (tmp->bgcolor) : NULL;
-        break;
-    case 2:
-        mc_skin_color->fgcolor = (values[0]) ? g_strstrip (g_strdup (values[0])) : NULL;
-        mc_skin_color->bgcolor = (values[1]) ? g_strstrip (g_strdup (values[1])) : NULL;
-        break;
-    }
+    tmp = mc_skin_color_get_with_defaults (group, "_default_");
+    mc_skin_color->fgcolor = (items_count > 0 && values[0][0]) ? g_strstrip (g_strdup (values[0])) :
+        (tmp != NULL) ? g_strdup (tmp->fgcolor) : NULL;
+    mc_skin_color->bgcolor = (items_count > 1 && values[1][0]) ? g_strstrip (g_strdup (values[1])) :
+        (tmp != NULL) ? g_strdup (tmp->bgcolor) : NULL;
+    mc_skin_color->attrs = (items_count > 2 && values[2][0]) ? g_strstrip (g_strdup (values[2])) :
+        (tmp != NULL) ? g_strdup (tmp->attrs) : NULL;
+
     g_strfreev (values);
 
     mc_skin_color->pair_index =
-        tty_try_alloc_color_pair2 (mc_skin_color->fgcolor, mc_skin_color->bgcolor, FALSE);
+        tty_try_alloc_color_pair2 (mc_skin_color->fgcolor, mc_skin_color->bgcolor,
+                                   mc_skin_color->attrs, FALSE);
 
     return mc_skin_color;
 }
@@ -189,8 +173,10 @@ mc_skin_color_set_default_for_terminal (mc_skin_t * mc_skin)
     {
         mc_skin_color->fgcolor = g_strdup ("default");
         mc_skin_color->bgcolor = g_strdup ("default");
+        mc_skin_color->attrs = NULL;
         mc_skin_color->pair_index =
-            tty_try_alloc_color_pair2 (mc_skin_color->fgcolor, mc_skin_color->bgcolor, FALSE);
+            tty_try_alloc_color_pair2 (mc_skin_color->fgcolor, mc_skin_color->bgcolor,
+                                       mc_skin_color->attrs, FALSE);
         mc_skin_color_add_to_hash (mc_skin, "skin", "terminal_default_color", mc_skin_color);
     }
 }
@@ -337,7 +323,7 @@ mc_skin_color_parse_ini_file (mc_skin_t * mc_skin)
     if (mc_skin_color == NULL)
         return FALSE;
 
-    tty_color_set_defaults (mc_skin_color->fgcolor, mc_skin_color->bgcolor);
+    tty_color_set_defaults (mc_skin_color->fgcolor, mc_skin_color->bgcolor, mc_skin_color->attrs);
     mc_skin_color_add_to_hash (mc_skin, "core", "_default_", mc_skin_color);
 
     for (; *groups != NULL; groups++)

+ 4 - 2
lib/skin/common.c

@@ -2,10 +2,11 @@
    Skins engine.
    Interface functions
 
-   Copyright (C) 2009 The Free Software Foundation, Inc.
+   Copyright (C) 2009, 2010 The Free Software Foundation, Inc.
 
    Written by:
-   Slava Zanko <slavazanko@gmail.com>, 2009.
+   Slava Zanko <slavazanko@gmail.com>, 2009
+   Egmont Koblinger <egmont@gmail.com>, 2010
 
    This file is part of the Midnight Commander.
 
@@ -54,6 +55,7 @@ mc_skin_hash_destroy_value (gpointer data)
     mc_skin_color_t *mc_skin_color = (mc_skin_color_t *) data;
     g_free (mc_skin_color->fgcolor);
     g_free (mc_skin_color->bgcolor);
+    g_free (mc_skin_color->attrs);
     g_free (mc_skin_color);
 }
 

+ 1 - 0
lib/skin/internal.h

@@ -14,6 +14,7 @@ typedef struct mc_skin_color_struct
 {
     gchar *fgcolor;
     gchar *bgcolor;
+    gchar *attrs;
     int pair_index;
 } mc_skin_color_t;
 

+ 96 - 19
lib/tty/color-internal.c

@@ -1,10 +1,11 @@
 /*  Internal stuff of color setup
    Copyright (C) 1994, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-   2007, 2008, 2009 Free Software Foundation, Inc.
+   2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    Written by:
-   Andrew Borodin <aborodin@vmail.ru>, 2009.
-   Slava Zanko <slavazanko@gmail.com>, 2009.
+   Andrew Borodin <aborodin@vmail.ru>, 2009
+   Slava Zanko <slavazanko@gmail.com>, 2009
+   Egmont Koblinger <egmont@gmail.com>, 2010
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -49,21 +50,21 @@ typedef struct mc_tty_color_table_struct
 
 mc_tty_color_table_t const color_table[] = {
     {"black", COLOR_BLACK},
-    {"gray", COLOR_BLACK | A_BOLD},
+    {"gray", COLOR_BLACK + 8},
     {"red", COLOR_RED},
-    {"brightred", COLOR_RED | A_BOLD},
+    {"brightred", COLOR_RED + 8},
     {"green", COLOR_GREEN},
-    {"brightgreen", COLOR_GREEN | A_BOLD},
+    {"brightgreen", COLOR_GREEN + 8},
     {"brown", COLOR_YELLOW},
-    {"yellow", COLOR_YELLOW | A_BOLD},
+    {"yellow", COLOR_YELLOW + 8},
     {"blue", COLOR_BLUE},
-    {"brightblue", COLOR_BLUE | A_BOLD},
+    {"brightblue", COLOR_BLUE + 8},
     {"magenta", COLOR_MAGENTA},
-    {"brightmagenta", COLOR_MAGENTA | A_BOLD},
+    {"brightmagenta", COLOR_MAGENTA + 8},
     {"cyan", COLOR_CYAN},
-    {"brightcyan", COLOR_CYAN | A_BOLD},
+    {"brightcyan", COLOR_CYAN + 8},
     {"lightgray", COLOR_WHITE},
-    {"white", COLOR_WHITE | A_BOLD},
+    {"white", COLOR_WHITE + 8},
     {"default", -1},            /* default color of the terminal */
     /* special colors */
     {"A_REVERSE", SPEC_A_REVERSE},
@@ -74,24 +75,71 @@ mc_tty_color_table_t const color_table[] = {
     {NULL, 0}
 };
 
+mc_tty_color_table_t const attributes_table[] = {
+    {"bold", A_BOLD},
+    {"underline", A_UNDERLINE},
+    {"reverse", A_REVERSE},
+    {"blink", A_BLINK},
+    /* End of list */
+    {NULL, 0}
+};
+
 /*** file scope functions ************************************************************************/
 /* --------------------------------------------------------------------------------------------- */
 
+static int
+parse_256_color_name (const char *color_name)
+{
+    int i;
+    char dummy;
+    if (sscanf (color_name, "color%d%c", &i, &dummy) == 1 && i >= 0 && i < 256)
+    {
+        return i;
+    }
+    if (sscanf (color_name, "gray%d%c", &i, &dummy) == 1 && i >= 0 && i < 24)
+    {
+        return 232 + i;
+    }
+    if (strncmp (color_name, "rgb", 3) == 0 &&
+        color_name[3] >= '0' && color_name[3] < '6' &&
+        color_name[4] >= '0' && color_name[4] < '6' &&
+        color_name[5] >= '0' && color_name[5] < '6' && color_name[6] == '\0')
+    {
+        return 16 + 36 * (color_name[3] - '0') + 6 * (color_name[4] - '0') + (color_name[5] - '0');
+    }
+    return -1;
+}
+
+/* --------------------------------------------------------------------------------------------- */
 /*** public functions ****************************************************************************/
 /* --------------------------------------------------------------------------------------------- */
 
 const char *
-tty_color_get_valid_name (const char *color_name)
+tty_color_get_name_by_index (int idx)
 {
-
-    if (color_name != NULL)
+    static char **color_N_names = NULL;
+    int i;
+
+    /* Find the real English name of the first 16 colors, */
+    /* as well as the A_* special values. */
+    for (i = 0; color_table[i].name != NULL; i++)
+        if (idx == color_table[i].value)
+            return color_table[i].name;
+    /* Create and return the strings "color16" to "color255". */
+    if (idx >= 16 && idx < 256)
     {
-        size_t i;
-        for (i = 0; color_table[i].name != NULL; i++)
-            if (strcmp (color_name, color_table[i].name) == 0)
-                return color_table[i].name;
+        if (color_N_names == NULL)
+        {
+            color_N_names = g_try_malloc0 (240 * sizeof (char *));
+        }
+        if (color_N_names[idx - 16] == NULL)
+        {
+            color_N_names[idx - 16] = g_try_malloc (9);
+            sprintf (color_N_names[idx - 16], "color%d", idx);
+        }
+        return color_N_names[idx - 16];
     }
-    return NULL;
+    return "default";
 }
 
 /* --------------------------------------------------------------------------------------------- */
@@ -106,8 +154,37 @@ tty_color_get_index_by_name (const char *color_name)
         for (i = 0; color_table[i].name != NULL; i++)
             if (strcmp (color_name, color_table[i].name) == 0)
                 return color_table[i].value;
+        return parse_256_color_name (color_name);
     }
     return -1;
 }
 
 /* --------------------------------------------------------------------------------------------- */
+
+int
+tty_attr_get_bits (const char *attrs)
+{
+    int attr_bits = 0;
+    gchar **attr_list;
+    int i, j;
+
+    if (attrs != NULL)
+    {
+        attr_list = g_strsplit (attrs, "+", -1);
+        for (i = 0; attr_list[i] != NULL; i++)
+        {
+            for (j = 0; attributes_table[j].name != NULL; j++)
+            {
+                if (strcmp (attr_list[i], attributes_table[j].name) == 0)
+                {
+                    attr_bits |= attributes_table[j].value;
+                    break;
+                }
+            }
+        }
+        g_strfreev (attr_list);
+    }
+    return attr_bits;
+}
+
+/* --------------------------------------------------------------------------------------------- */

+ 4 - 4
lib/tty/color-internal.h

@@ -33,11 +33,10 @@ typedef enum {
 
 typedef struct mc_color_pair_struct
 {
-    const char *cfg;
-    const char *cbg;
     int ifg;
     int ibg;
-    int pair_index;
+    int attr;
+    size_t pair_index;
     gboolean is_temp;
 } tty_color_pair_t;
 
@@ -48,8 +47,9 @@ extern gboolean mc_tty_color_disable;
 
 /*** declarations of public functions ************************************************************/
 
-const char *tty_color_get_valid_name (const char *);
+const char *tty_color_get_name_by_index (int);
 int tty_color_get_index_by_name (const char *);
+int tty_attr_get_bits (const char *);
 
 void tty_color_init_lib (gboolean, gboolean);
 void tty_color_deinit_lib (void);

Some files were not shown because too many files changed in this diff