root/lib/skin/colors.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. mc_skin_color_get_from_hash
  2. mc_skin_color_remove_from_hash
  3. mc_skin_color_add_to_hash
  4. mc_skin_color_get_with_defaults
  5. mc_skin_color_look_up_alias
  6. mc_skin_color_get_from_ini_file
  7. mc_skin_color_set_default_for_terminal
  8. mc_skin_color_cache_init
  9. mc_skin_color_check_inisection
  10. mc_skin_color_check_bw_mode
  11. mc_skin_color_parse_ini_file
  12. mc_skin_color_get

   1 /*
   2    Skins engine.
   3    Work with colors
   4 
   5    Copyright (C) 2009-2019
   6    Free Software Foundation, Inc.
   7 
   8    Written by:
   9    Slava Zanko <slavazanko@gmail.com>, 2009
  10    Egmont Koblinger <egmont@gmail.com>, 2010
  11    Andrew Borodin <aborodin@vmail.ru>, 2012
  12 
  13    This file is part of the Midnight Commander.
  14 
  15    The Midnight Commander is free software: you can redistribute it
  16    and/or modify it under the terms of the GNU General Public License as
  17    published by the Free Software Foundation, either version 3 of the License,
  18    or (at your option) any later version.
  19 
  20    The Midnight Commander is distributed in the hope that it will be useful,
  21    but WITHOUT ANY WARRANTY; without even the implied warranty of
  22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23    GNU General Public License for more details.
  24 
  25    You should have received a copy of the GNU General Public License
  26    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  27  */
  28 
  29 #include <config.h>
  30 #include <string.h>
  31 
  32 #include "internal.h"
  33 
  34 #include "lib/tty/color.h"
  35 
  36 /*** global variables ****************************************************************************/
  37 
  38 int mc_skin_color__cache[MC_SKIN_COLOR_CACHE_COUNT];
  39 
  40 /*** file scope macro definitions ****************************************************************/
  41 
  42 /*** file scope type declarations ****************************************************************/
  43 
  44 /*** file scope variables ************************************************************************/
  45 
  46 /*** file scope functions ************************************************************************/
  47 
  48 static mc_skin_color_t *
  49 mc_skin_color_get_from_hash (mc_skin_t * mc_skin, const gchar * group, const gchar * key)
     /* [previous][next][first][last][top][bottom][index][help]  */
  50 {
  51     gchar kname[BUF_TINY];
  52     mc_skin_color_t *mc_skin_color;
  53 
  54     if (group == NULL || key == NULL)
  55         return NULL;
  56 
  57     if (mc_skin == NULL)
  58         mc_skin = &mc_skin__default;
  59 
  60     g_snprintf (kname, sizeof (kname), "%s.%s", group, key);
  61     mc_skin_color = (mc_skin_color_t *) g_hash_table_lookup (mc_skin->colors, (gpointer) kname);
  62 
  63     return mc_skin_color;
  64 }
  65 
  66 /* --------------------------------------------------------------------------------------------- */
  67 
  68 #if 0
  69 static void
  70 mc_skin_color_remove_from_hash (mc_skin_t * mc_skin, const gchar * group, const gchar * key)
     /* [previous][next][first][last][top][bottom][index][help]  */
  71 {
  72     gchar kname[BUF_TINY];
  73     if (group == NULL || key == NULL)
  74         return;
  75 
  76     if (mc_skin == NULL)
  77         mc_skin = &mc_skin__default;
  78 
  79     g_snprintf (kname, sizeof (kname), "%s.%s", group, key);
  80     g_hash_table_remove (mc_skin->colors, (gpointer) kname);
  81 }
  82 #endif
  83 
  84 /* --------------------------------------------------------------------------------------------- */
  85 
  86 static void
  87 mc_skin_color_add_to_hash (mc_skin_t * mc_skin, const gchar * group, const gchar * key,
     /* [previous][next][first][last][top][bottom][index][help]  */
  88                            mc_skin_color_t * mc_skin_color)
  89 {
  90     gchar *kname;
  91 
  92     kname = g_strdup_printf ("%s.%s", group, key);
  93     if (kname != NULL)
  94     {
  95         if (g_hash_table_lookup (mc_skin->colors, (gpointer) kname) != NULL)
  96             g_hash_table_remove (mc_skin->colors, (gpointer) kname);
  97 
  98         g_hash_table_insert (mc_skin->colors, (gpointer) kname, (gpointer) mc_skin_color);
  99     }
 100 }
 101 
 102 /* --------------------------------------------------------------------------------------------- */
 103 
 104 static mc_skin_color_t *
 105 mc_skin_color_get_with_defaults (const gchar * group, const gchar * name)
     /* [previous][next][first][last][top][bottom][index][help]  */
 106 {
 107     mc_skin_color_t *mc_skin_color;
 108 
 109     mc_skin_color = mc_skin_color_get_from_hash (NULL, group, name);
 110     if (mc_skin_color != NULL)
 111         return mc_skin_color;
 112 
 113     mc_skin_color = mc_skin_color_get_from_hash (NULL, group, "_default_");
 114     if (mc_skin_color != NULL)
 115         return mc_skin_color;
 116 
 117     mc_skin_color = mc_skin_color_get_from_hash (NULL, "core", "_default_");
 118     return mc_skin_color;
 119 }
 120 
 121 /* --------------------------------------------------------------------------------------------- */
 122 
 123 /* If an alias is found, alloc a new string for the resolved value and free the input parameter.
 124    Otherwise it's a no-op returning the original string. */
 125 static gchar *
 126 mc_skin_color_look_up_alias (mc_skin_t * mc_skin, gchar * str)
     /* [previous][next][first][last][top][bottom][index][help]  */
 127 {
 128     gchar *orig, *str2;
 129     int hop = 0;
 130 
 131     orig = g_strdup (str);
 132     str2 = g_strdup (str);
 133 
 134     while (TRUE)
 135     {
 136         gchar **values;
 137         gsize items_count;
 138 
 139         values = mc_config_get_string_list (mc_skin->config, "aliases", str, &items_count);
 140         if (items_count != 1)
 141         {
 142             /* No such alias declaration found, that is, we've got the resolved value. */
 143             g_strfreev (values);
 144             g_free (str2);
 145             g_free (orig);
 146             return str;
 147         }
 148 
 149         g_free (str);
 150         str = g_strdup (values[0]);
 151         g_strfreev (values);
 152 
 153         /* str2 resolves at half speed than str. This is used for loop detection. */
 154         if (hop++ % 2 != 0)
 155         {
 156             values = mc_config_get_string_list (mc_skin->config, "aliases", str2, &items_count);
 157             g_assert (items_count == 1);
 158             g_free (str2);
 159             str2 = g_strdup (values[0]);
 160             g_strfreev (values);
 161 
 162             if (strcmp (str, str2) == 0)
 163             {
 164                 /* Loop detected. */
 165                 fprintf (stderr,
 166                          "Loop detected while trying to resolve alias \"%s\" in skin \"%s\"\n",
 167                          orig, mc_skin->name);
 168                 g_free (str);
 169                 g_free (str2);
 170                 return orig;
 171             }
 172         }
 173     }
 174 }
 175 
 176 /* --------------------------------------------------------------------------------------------- */
 177 
 178 static mc_skin_color_t *
 179 mc_skin_color_get_from_ini_file (mc_skin_t * mc_skin, const gchar * group, const gchar * key)
     /* [previous][next][first][last][top][bottom][index][help]  */
 180 {
 181     gsize items_count;
 182     gchar **values;
 183     mc_skin_color_t *mc_skin_color, *tmp;
 184 
 185     values = mc_config_get_string_list (mc_skin->config, group, key, &items_count);
 186     if (values == NULL || values[0] == NULL)
 187     {
 188         g_strfreev (values);
 189         return NULL;
 190     }
 191 
 192     mc_skin_color = g_try_new0 (mc_skin_color_t, 1);
 193     if (mc_skin_color == NULL)
 194     {
 195         g_strfreev (values);
 196         return NULL;
 197     }
 198 
 199     tmp = mc_skin_color_get_with_defaults (group, "_default_");
 200     mc_skin_color->fgcolor = (items_count > 0 && values[0][0]) ?
 201         mc_skin_color_look_up_alias (mc_skin, g_strstrip (g_strdup (values[0]))) :
 202         (tmp != NULL) ? g_strdup (tmp->fgcolor) : NULL;
 203     mc_skin_color->bgcolor = (items_count > 1 && values[1][0]) ?
 204         mc_skin_color_look_up_alias (mc_skin, g_strstrip (g_strdup (values[1]))) :
 205         (tmp != NULL) ? g_strdup (tmp->bgcolor) : NULL;
 206     mc_skin_color->attrs = (items_count > 2 && values[2][0]) ?
 207         mc_skin_color_look_up_alias (mc_skin, g_strstrip (g_strdup (values[2]))) :
 208         (tmp != NULL) ? g_strdup (tmp->attrs) : NULL;
 209 
 210     g_strfreev (values);
 211 
 212     mc_skin_color->pair_index =
 213         tty_try_alloc_color_pair2 (mc_skin_color->fgcolor, mc_skin_color->bgcolor,
 214                                    mc_skin_color->attrs, FALSE);
 215 
 216     return mc_skin_color;
 217 }
 218 
 219 /* --------------------------------------------------------------------------------------------- */
 220 
 221 static void
 222 mc_skin_color_set_default_for_terminal (mc_skin_t * mc_skin)
     /* [previous][next][first][last][top][bottom][index][help]  */
 223 {
 224     mc_skin_color_t *mc_skin_color;
 225     mc_skin_color = g_try_new0 (mc_skin_color_t, 1);
 226     if (mc_skin_color != NULL)
 227     {
 228         mc_skin_color->fgcolor = g_strdup ("default");
 229         mc_skin_color->bgcolor = g_strdup ("default");
 230         mc_skin_color->attrs = NULL;
 231         mc_skin_color->pair_index =
 232             tty_try_alloc_color_pair2 (mc_skin_color->fgcolor, mc_skin_color->bgcolor,
 233                                        mc_skin_color->attrs, FALSE);
 234         mc_skin_color_add_to_hash (mc_skin, "skin", "terminal_default_color", mc_skin_color);
 235     }
 236 }
 237 
 238 /* --------------------------------------------------------------------------------------------- */
 239 
 240 static void
 241 mc_skin_color_cache_init (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 242 {
 243     DEFAULT_COLOR = mc_skin_color_get ("skin", "terminal_default_color");
 244     NORMAL_COLOR = mc_skin_color_get ("core", "_default_");
 245     MARKED_COLOR = mc_skin_color_get ("core", "marked");
 246     SELECTED_COLOR = mc_skin_color_get ("core", "selected");
 247     MARKED_SELECTED_COLOR = mc_skin_color_get ("core", "markselect");
 248     DISABLED_COLOR = mc_skin_color_get ("core", "disabled");
 249     REVERSE_COLOR = mc_skin_color_get ("core", "reverse");
 250     HEADER_COLOR = mc_skin_color_get ("core", "header");
 251     COMMAND_MARK_COLOR = mc_skin_color_get ("core", "commandlinemark");
 252 
 253     COLOR_NORMAL = mc_skin_color_get ("dialog", "_default_");
 254     COLOR_FOCUS = mc_skin_color_get ("dialog", "dfocus");
 255     COLOR_HOT_NORMAL = mc_skin_color_get ("dialog", "dhotnormal");
 256     COLOR_HOT_FOCUS = mc_skin_color_get ("dialog", "dhotfocus");
 257     COLOR_TITLE = mc_skin_color_get ("dialog", "dtitle");
 258 
 259     ERROR_COLOR = mc_skin_color_get ("error", "_default_");
 260     ERROR_FOCUS = mc_skin_color_get ("error", "errdfocus");
 261     ERROR_HOT_NORMAL = mc_skin_color_get ("error", "errdhotnormal");
 262     ERROR_HOT_FOCUS = mc_skin_color_get ("error", "errdhotfocus");
 263     ERROR_TITLE = mc_skin_color_get ("error", "errdtitle");
 264 
 265     MENU_ENTRY_COLOR = mc_skin_color_get ("menu", "_default_");
 266     MENU_SELECTED_COLOR = mc_skin_color_get ("menu", "menusel");
 267     MENU_HOT_COLOR = mc_skin_color_get ("menu", "menuhot");
 268     MENU_HOTSEL_COLOR = mc_skin_color_get ("menu", "menuhotsel");
 269     MENU_INACTIVE_COLOR = mc_skin_color_get ("menu", "menuinactive");
 270 
 271     PMENU_ENTRY_COLOR = mc_skin_color_get ("popupmenu", "_default_");
 272     PMENU_SELECTED_COLOR = mc_skin_color_get ("popupmenu", "menusel");
 273     PMENU_TITLE_COLOR = mc_skin_color_get ("popupmenu", "menutitle");
 274 
 275     BUTTONBAR_HOTKEY_COLOR = mc_skin_color_get ("buttonbar", "hotkey");
 276     BUTTONBAR_BUTTON_COLOR = mc_skin_color_get ("buttonbar", "button");
 277 
 278     STATUSBAR_COLOR = mc_skin_color_get ("statusbar", "_default_");
 279 
 280     GAUGE_COLOR = mc_skin_color_get ("core", "gauge");
 281     INPUT_COLOR = mc_skin_color_get ("core", "input");
 282     INPUT_HISTORY_COLOR = mc_skin_color_get ("core", "inputhistory");
 283     COMMAND_HISTORY_COLOR = mc_skin_color_get ("core", "commandhistory");
 284     INPUT_MARK_COLOR = mc_skin_color_get ("core", "inputmark");
 285     INPUT_UNCHANGED_COLOR = mc_skin_color_get ("core", "inputunchanged");
 286 
 287     HELP_NORMAL_COLOR = mc_skin_color_get ("help", "_default_");
 288     HELP_ITALIC_COLOR = mc_skin_color_get ("help", "helpitalic");
 289     HELP_BOLD_COLOR = mc_skin_color_get ("help", "helpbold");
 290     HELP_LINK_COLOR = mc_skin_color_get ("help", "helplink");
 291     HELP_SLINK_COLOR = mc_skin_color_get ("help", "helpslink");
 292     HELP_TITLE_COLOR = mc_skin_color_get ("help", "helptitle");
 293 
 294     VIEW_NORMAL_COLOR = mc_skin_color_get ("viewer", "_default_");
 295     VIEW_BOLD_COLOR = mc_skin_color_get ("viewer", "viewbold");
 296     VIEW_UNDERLINED_COLOR = mc_skin_color_get ("viewer", "viewunderline");
 297     VIEW_SELECTED_COLOR = mc_skin_color_get ("viewer", "viewselected");
 298 
 299     EDITOR_NORMAL_COLOR = mc_skin_color_get ("editor", "_default_");
 300     EDITOR_BOLD_COLOR = mc_skin_color_get ("editor", "editbold");
 301     EDITOR_MARKED_COLOR = mc_skin_color_get ("editor", "editmarked");
 302     EDITOR_WHITESPACE_COLOR = mc_skin_color_get ("editor", "editwhitespace");
 303     EDITOR_RIGHT_MARGIN_COLOR = mc_skin_color_get ("editor", "editrightmargin");
 304     LINE_STATE_COLOR = mc_skin_color_get ("editor", "editlinestate");
 305     EDITOR_BACKGROUND = mc_skin_color_get ("editor", "editbg");
 306     EDITOR_FRAME = mc_skin_color_get ("editor", "editframe");
 307     EDITOR_FRAME_ACTIVE = mc_skin_color_get ("editor", "editframeactive");
 308     EDITOR_FRAME_DRAG = mc_skin_color_get ("editor", "editframedrag");
 309 
 310     BOOK_MARK_COLOR = mc_skin_color_get ("editor", "bookmark");
 311     BOOK_MARK_FOUND_COLOR = mc_skin_color_get ("editor", "bookmarkfound");
 312 
 313     DFF_ADD_COLOR = mc_skin_color_get ("diffviewer", "added");
 314     DFF_CHG_COLOR = mc_skin_color_get ("diffviewer", "changedline");
 315     DFF_CHH_COLOR = mc_skin_color_get ("diffviewer", "changednew");
 316     DFF_CHD_COLOR = mc_skin_color_get ("diffviewer", "changed");
 317     DFF_DEL_COLOR = mc_skin_color_get ("diffviewer", "removed");
 318     DFF_ERROR_COLOR = mc_skin_color_get ("diffviewer", "error");
 319 }
 320 
 321 /* --------------------------------------------------------------------------------------------- */
 322 
 323 static gboolean
 324 mc_skin_color_check_inisection (const gchar * group)
     /* [previous][next][first][last][top][bottom][index][help]  */
 325 {
 326     return !((strcasecmp ("skin", group) == 0) || (strcasecmp ("aliases", group) == 0)
 327              || (strcasecmp ("lines", group) == 0) || (strncasecmp ("widget-", group, 7) == 0));
 328 }
 329 
 330 /* --------------------------------------------------------------------------------------------- */
 331 
 332 static void
 333 mc_skin_color_check_bw_mode (mc_skin_t * mc_skin)
     /* [previous][next][first][last][top][bottom][index][help]  */
 334 {
 335     gchar **groups, **orig_groups;
 336 
 337     if (tty_use_colors () && !mc_global.tty.disable_colors)
 338         return;
 339 
 340     orig_groups = mc_config_get_groups (mc_skin->config, NULL);
 341 
 342     for (groups = orig_groups; *groups != NULL; groups++)
 343         if (mc_skin_color_check_inisection (*groups))
 344             mc_config_del_group (mc_skin->config, *groups);
 345 
 346     g_strfreev (orig_groups);
 347 
 348     mc_skin_hardcoded_blackwhite_colors (mc_skin);
 349 }
 350 
 351 /* --------------------------------------------------------------------------------------------- */
 352 /*** public functions ****************************************************************************/
 353 /* --------------------------------------------------------------------------------------------- */
 354 
 355 gboolean
 356 mc_skin_color_parse_ini_file (mc_skin_t * mc_skin)
     /* [previous][next][first][last][top][bottom][index][help]  */
 357 {
 358     gsize items_count;
 359     gchar **groups, **orig_groups;
 360     mc_skin_color_t *mc_skin_color;
 361 
 362     mc_skin_color_check_bw_mode (mc_skin);
 363 
 364     orig_groups = mc_config_get_groups (mc_skin->config, &items_count);
 365     if (*orig_groups == NULL)
 366     {
 367         g_strfreev (orig_groups);
 368         return FALSE;
 369     }
 370 
 371     /* as first, need to set up default colors */
 372     mc_skin_color_set_default_for_terminal (mc_skin);
 373     mc_skin_color = mc_skin_color_get_from_ini_file (mc_skin, "core", "_default_");
 374     if (mc_skin_color == NULL)
 375         return FALSE;
 376 
 377     tty_color_set_defaults (mc_skin_color->fgcolor, mc_skin_color->bgcolor, mc_skin_color->attrs);
 378     mc_skin_color_add_to_hash (mc_skin, "core", "_default_", mc_skin_color);
 379 
 380     for (groups = orig_groups; *groups != NULL; groups++)
 381     {
 382         gchar **keys, **orig_keys;
 383 
 384         if (!mc_skin_color_check_inisection (*groups))
 385             continue;
 386 
 387         orig_keys = mc_config_get_keys (mc_skin->config, *groups, NULL);
 388 
 389         for (keys = orig_keys; *keys != NULL; keys++)
 390         {
 391             mc_skin_color = mc_skin_color_get_from_ini_file (mc_skin, *groups, *keys);
 392             if (mc_skin_color != NULL)
 393                 mc_skin_color_add_to_hash (mc_skin, *groups, *keys, mc_skin_color);
 394         }
 395         g_strfreev (orig_keys);
 396     }
 397     g_strfreev (orig_groups);
 398 
 399     mc_skin_color_cache_init ();
 400     return TRUE;
 401 }
 402 
 403 /* --------------------------------------------------------------------------------------------- */
 404 
 405 int
 406 mc_skin_color_get (const gchar * group, const gchar * name)
     /* [previous][next][first][last][top][bottom][index][help]  */
 407 {
 408     mc_skin_color_t *mc_skin_color;
 409 
 410     mc_skin_color = mc_skin_color_get_with_defaults (group, name);
 411 
 412     return (mc_skin_color != NULL) ? mc_skin_color->pair_index : 0;
 413 }
 414 
 415 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */