Manual pages: mcmcdiffmceditmcview

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-2025
   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 <https://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 /*** forward declarations (file scope functions) *************************************************/
  45 
  46 /*** file scope variables ************************************************************************/
  47 
  48 /* --------------------------------------------------------------------------------------------- */
  49 /*** file scope functions ************************************************************************/
  50 /* --------------------------------------------------------------------------------------------- */
  51 
  52 static tty_color_pair_t *
  53 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]  */
  54 {
  55     gchar kname[BUF_TINY];
  56     tty_color_pair_t *mc_skin_color;
  57 
  58     if (group == NULL || key == NULL)
  59         return NULL;
  60 
  61     if (mc_skin == NULL)
  62         mc_skin = &mc_skin__default;
  63 
  64     g_snprintf (kname, sizeof (kname), "%s.%s", group, key);
  65     mc_skin_color = (tty_color_pair_t *) g_hash_table_lookup (mc_skin->colors, (gpointer) kname);
  66 
  67     return mc_skin_color;
  68 }
  69 
  70 /* --------------------------------------------------------------------------------------------- */
  71 
  72 #if 0
  73 static void
  74 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]  */
  75 {
  76     gchar kname[BUF_TINY];
  77     if (group == NULL || key == NULL)
  78         return;
  79 
  80     if (mc_skin == NULL)
  81         mc_skin = &mc_skin__default;
  82 
  83     g_snprintf (kname, sizeof (kname), "%s.%s", group, key);
  84     g_hash_table_remove (mc_skin->colors, (gpointer) kname);
  85 }
  86 #endif
  87 
  88 /* --------------------------------------------------------------------------------------------- */
  89 
  90 static void
  91 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]  */
  92                            tty_color_pair_t *mc_skin_color)
  93 {
  94     gchar *kname;
  95 
  96     kname = g_strdup_printf ("%s.%s", group, key);
  97     if (kname != NULL)
  98     {
  99         if (g_hash_table_lookup (mc_skin->colors, (gpointer) kname) != NULL)
 100             g_hash_table_remove (mc_skin->colors, (gpointer) kname);
 101 
 102         g_hash_table_insert (mc_skin->colors, (gpointer) kname, (gpointer) mc_skin_color);
 103     }
 104 }
 105 
 106 /* --------------------------------------------------------------------------------------------- */
 107 
 108 static tty_color_pair_t *
 109 mc_skin_color_get_with_defaults (const gchar *group, const gchar *name)
     /* [previous][next][first][last][top][bottom][index][help]  */
 110 {
 111     tty_color_pair_t *mc_skin_color;
 112 
 113     mc_skin_color = mc_skin_color_get_from_hash (NULL, group, name);
 114     if (mc_skin_color != NULL)
 115         return mc_skin_color;
 116 
 117     mc_skin_color = mc_skin_color_get_from_hash (NULL, group, "_default_");
 118     if (mc_skin_color != NULL)
 119         return mc_skin_color;
 120 
 121     mc_skin_color = mc_skin_color_get_from_hash (NULL, "core", "_default_");
 122     return mc_skin_color;
 123 }
 124 
 125 /* --------------------------------------------------------------------------------------------- */
 126 
 127 /* If an alias is found, alloc a new string for the resolved value and free the input parameter.
 128    Otherwise it's a no-op returning the original string. */
 129 static gchar *
 130 mc_skin_color_look_up_alias (mc_skin_t *mc_skin, gchar *str)
     /* [previous][next][first][last][top][bottom][index][help]  */
 131 {
 132     gchar *orig, *str2;
 133     int hop = 0;
 134 
 135     orig = g_strdup (str);
 136     str2 = g_strdup (str);
 137 
 138     while (TRUE)
 139     {
 140         gchar **values;
 141         gsize items_count;
 142 
 143         values = mc_config_get_string_list (mc_skin->config, "aliases", str, &items_count);
 144         if (items_count != 1)
 145         {
 146             // No such alias declaration found, that is, we've got the resolved value.
 147             g_strfreev (values);
 148             g_free (str2);
 149             g_free (orig);
 150             return str;
 151         }
 152 
 153         g_free (str);
 154         str = g_strdup (values[0]);
 155         g_strfreev (values);
 156 
 157         // str2 resolves at half speed than str. This is used for loop detection.
 158         if (hop++ % 2 != 0)
 159         {
 160             values = mc_config_get_string_list (mc_skin->config, "aliases", str2, &items_count);
 161             g_assert (items_count == 1);
 162             g_free (str2);
 163             str2 = g_strdup (values[0]);
 164             g_strfreev (values);
 165 
 166             if (strcmp (str, str2) == 0)
 167             {
 168                 // Loop detected.
 169                 fprintf (stderr,
 170                          "Loop detected while trying to resolve alias \"%s\" in skin \"%s\"\n",
 171                          orig, mc_skin->name);
 172                 g_free (str);
 173                 g_free (str2);
 174                 return orig;
 175             }
 176         }
 177     }
 178 }
 179 
 180 /* --------------------------------------------------------------------------------------------- */
 181 
 182 static tty_color_pair_t *
 183 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]  */
 184 {
 185     gsize items_count;
 186     gchar **values;
 187     tty_color_pair_t *mc_skin_color, *tmp;
 188 
 189     values = mc_config_get_string_list (mc_skin->config, group, key, &items_count);
 190     if (values == NULL || values[0] == NULL)
 191     {
 192         g_strfreev (values);
 193         return NULL;
 194     }
 195 
 196     mc_skin_color = g_try_new0 (tty_color_pair_t, 1);
 197     if (mc_skin_color == NULL)
 198     {
 199         g_strfreev (values);
 200         return NULL;
 201     }
 202 
 203     tmp = mc_skin_color_get_with_defaults (group, "_default_");
 204     mc_skin_color->fg = (items_count > 0 && values[0][0])
 205         ? mc_skin_color_look_up_alias (mc_skin, g_strstrip (g_strdup (values[0])))
 206         : (tmp != NULL) ? g_strdup (tmp->fg)
 207                         : NULL;
 208     mc_skin_color->bg = (items_count > 1 && values[1][0])
 209         ? mc_skin_color_look_up_alias (mc_skin, g_strstrip (g_strdup (values[1])))
 210         : (tmp != NULL) ? g_strdup (tmp->bg)
 211                         : NULL;
 212     mc_skin_color->attrs = (items_count > 2 && values[2][0])
 213         ? mc_skin_color_look_up_alias (mc_skin, g_strstrip (g_strdup (values[2])))
 214         : (tmp != NULL) ? g_strdup (tmp->attrs)
 215                         : NULL;
 216 
 217     g_strfreev (values);
 218 
 219     mc_skin_color->pair_index = tty_try_alloc_color_pair (mc_skin_color, FALSE);
 220 
 221     return mc_skin_color;
 222 }
 223 
 224 /* --------------------------------------------------------------------------------------------- */
 225 
 226 static void
 227 mc_skin_color_set_default_for_terminal (mc_skin_t *mc_skin)
     /* [previous][next][first][last][top][bottom][index][help]  */
 228 {
 229     tty_color_pair_t *mc_skin_color;
 230 
 231     mc_skin_color = g_try_new0 (tty_color_pair_t, 1);
 232     if (mc_skin_color != NULL)
 233     {
 234         mc_skin_color->fg = g_strdup ("default");
 235         mc_skin_color->bg = g_strdup ("default");
 236         mc_skin_color->attrs = NULL;
 237         mc_skin_color->pair_index = tty_try_alloc_color_pair (mc_skin_color, FALSE);
 238         mc_skin_color_add_to_hash (mc_skin, "skin", "terminal_default_color", mc_skin_color);
 239     }
 240 }
 241 
 242 /* --------------------------------------------------------------------------------------------- */
 243 
 244 static void
 245 mc_skin_color_cache_init (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 246 {
 247     CORE_DEFAULT_COLOR = mc_skin_color_get ("skin", "terminal_default_color");
 248     CORE_NORMAL_COLOR = mc_skin_color_get ("core", "_default_");
 249     CORE_MARKED_COLOR = mc_skin_color_get ("core", "marked");
 250     CORE_SELECTED_COLOR = mc_skin_color_get ("core", "selected");
 251     CORE_MARKED_SELECTED_COLOR = mc_skin_color_get ("core", "markselect");
 252     CORE_DISABLED_COLOR = mc_skin_color_get ("core", "disabled");
 253     CORE_REVERSE_COLOR = mc_skin_color_get ("core", "reverse");
 254     CORE_HEADER_COLOR = mc_skin_color_get ("core", "header");
 255     CORE_COMMAND_MARK_COLOR = mc_skin_color_get ("core", "commandlinemark");
 256     CORE_SHADOW_COLOR = mc_skin_color_get ("core", "shadow");
 257     CORE_FRAME_COLOR = mc_skin_color_get ("core", "frame");
 258 
 259     DIALOG_NORMAL_COLOR = mc_skin_color_get ("dialog", "_default_");
 260     DIALOG_FOCUS_COLOR = mc_skin_color_get ("dialog", "dfocus");
 261     DIALOG_HOT_NORMAL_COLOR = mc_skin_color_get ("dialog", "dhotnormal");
 262     DIALOG_HOT_FOCUS_COLOR = mc_skin_color_get ("dialog", "dhotfocus");
 263     DIALOG_SELECTED_NORMAL_COLOR = mc_skin_color_get ("dialog", "dselnormal");
 264     DIALOG_SELECTED_FOCUS_COLOR = mc_skin_color_get ("dialog", "dselfocus");
 265     DIALOG_TITLE_COLOR = mc_skin_color_get ("dialog", "dtitle");
 266     DIALOG_FRAME_COLOR = mc_skin_color_get ("dialog", "dframe");
 267 
 268     ERROR_NORMAL_COLOR = mc_skin_color_get ("error", "_default_");
 269     ERROR_FOCUS_COLOR = mc_skin_color_get ("error", "errdfocus");
 270     ERROR_HOT_NORMAL_COLOR = mc_skin_color_get ("error", "errdhotnormal");
 271     ERROR_HOT_FOCUS_COLOR = mc_skin_color_get ("error", "errdhotfocus");
 272     ERROR_TITLE_COLOR = mc_skin_color_get ("error", "errdtitle");
 273     ERROR_FRAME_COLOR = mc_skin_color_get ("error", "errdframe");
 274 
 275     MENU_ENTRY_COLOR = mc_skin_color_get ("menu", "_default_");
 276     MENU_SELECTED_COLOR = mc_skin_color_get ("menu", "menusel");
 277     MENU_HOT_COLOR = mc_skin_color_get ("menu", "menuhot");
 278     MENU_HOTSEL_COLOR = mc_skin_color_get ("menu", "menuhotsel");
 279     MENU_INACTIVE_COLOR = mc_skin_color_get ("menu", "menuinactive");
 280     MENU_FRAME_COLOR = mc_skin_color_get ("menu", "menuframe");
 281 
 282     PMENU_ENTRY_COLOR = mc_skin_color_get ("popupmenu", "_default_");
 283     PMENU_SELECTED_COLOR = mc_skin_color_get ("popupmenu", "menusel");
 284     PMENU_TITLE_COLOR = mc_skin_color_get ("popupmenu", "menutitle");
 285     PMENU_FRAME_COLOR = mc_skin_color_get ("popupmenu", "menuframe");
 286 
 287     BUTTONBAR_HOTKEY_COLOR = mc_skin_color_get ("buttonbar", "hotkey");
 288     BUTTONBAR_BUTTON_COLOR = mc_skin_color_get ("buttonbar", "button");
 289 
 290     STATUSBAR_COLOR = mc_skin_color_get ("statusbar", "_default_");
 291 
 292     CORE_GAUGE_COLOR = mc_skin_color_get ("core", "gauge");
 293     CORE_INPUT_COLOR = mc_skin_color_get ("core", "input");
 294     CORE_INPUT_HISTORY_COLOR = mc_skin_color_get ("core", "inputhistory");
 295     CORE_COMMAND_HISTORY_COLOR = mc_skin_color_get ("core", "commandhistory");
 296     CORE_INPUT_MARK_COLOR = mc_skin_color_get ("core", "inputmark");
 297     CORE_INPUT_UNCHANGED_COLOR = mc_skin_color_get ("core", "inputunchanged");
 298 
 299     HELP_NORMAL_COLOR = mc_skin_color_get ("help", "_default_");
 300     HELP_ITALIC_COLOR = mc_skin_color_get ("help", "helpitalic");
 301     HELP_BOLD_COLOR = mc_skin_color_get ("help", "helpbold");
 302     HELP_LINK_COLOR = mc_skin_color_get ("help", "helplink");
 303     HELP_SLINK_COLOR = mc_skin_color_get ("help", "helpslink");
 304     HELP_TITLE_COLOR = mc_skin_color_get ("help", "helptitle");
 305     HELP_FRAME_COLOR = mc_skin_color_get ("help", "helpframe");
 306 
 307     VIEWER_NORMAL_COLOR = mc_skin_color_get ("viewer", "_default_");
 308     VIEWER_BOLD_COLOR = mc_skin_color_get ("viewer", "viewbold");
 309     VIEWER_UNDERLINED_COLOR = mc_skin_color_get ("viewer", "viewunderline");
 310     VIEWER_SELECTED_COLOR = mc_skin_color_get ("viewer", "viewselected");
 311     VIEWER_FRAME_COLOR = mc_skin_color_get ("viewer", "viewframe");
 312 
 313     EDITOR_NORMAL_COLOR = mc_skin_color_get ("editor", "_default_");
 314     EDITOR_BOLD_COLOR = mc_skin_color_get ("editor", "editbold");
 315     EDITOR_MARKED_COLOR = mc_skin_color_get ("editor", "editmarked");
 316     EDITOR_WHITESPACE_COLOR = mc_skin_color_get ("editor", "editwhitespace");
 317     EDITOR_NONPRINTABLE_COLOR = mc_skin_color_get ("editor", "editnonprintable");
 318     EDITOR_RIGHT_MARGIN_COLOR = mc_skin_color_get ("editor", "editrightmargin");
 319     EDITOR_LINE_STATE_COLOR = mc_skin_color_get ("editor", "editlinestate");
 320     EDITOR_BACKGROUND_COLOR = mc_skin_color_get ("editor", "editbg");
 321     EDITOR_FRAME_COLOR = mc_skin_color_get ("editor", "editframe");
 322     EDITOR_FRAME_ACTIVE_COLOR = mc_skin_color_get ("editor", "editframeactive");
 323     EDITOR_FRAME_DRAG_COLOR = mc_skin_color_get ("editor", "editframedrag");
 324 
 325     EDITOR_BOOKMARK_COLOR = mc_skin_color_get ("editor", "bookmark");
 326     EDITOR_BOOKMARK_FOUND_COLOR = mc_skin_color_get ("editor", "bookmarkfound");
 327 
 328     DIFFVIEWER_ADDED_COLOR = mc_skin_color_get ("diffviewer", "added");
 329     DIFFVIEWER_CHANGEDLINE_COLOR = mc_skin_color_get ("diffviewer", "changedline");
 330     DIFFVIEWER_CHANGEDNEW_COLOR = mc_skin_color_get ("diffviewer", "changednew");
 331     DIFFVIEWER_CHANGED_COLOR = mc_skin_color_get ("diffviewer", "changed");
 332     DIFFVIEWER_REMOVED_COLOR = mc_skin_color_get ("diffviewer", "removed");
 333     DIFFVIEWER_ERROR_COLOR = mc_skin_color_get ("diffviewer", "error");
 334 }
 335 
 336 /* --------------------------------------------------------------------------------------------- */
 337 
 338 static gboolean
 339 mc_skin_color_check_inisection (const gchar *group)
     /* [previous][next][first][last][top][bottom][index][help]  */
 340 {
 341     return !((strcasecmp ("skin", group) == 0) || (strcasecmp ("aliases", group) == 0)
 342              || (strcasecmp ("lines", group) == 0) || (strncasecmp ("widget-", group, 7) == 0));
 343 }
 344 
 345 /* --------------------------------------------------------------------------------------------- */
 346 
 347 static void
 348 mc_skin_color_check_bw_mode (mc_skin_t *mc_skin)
     /* [previous][next][first][last][top][bottom][index][help]  */
 349 {
 350     gchar **groups, **orig_groups;
 351 
 352     if (tty_use_colors () && !mc_global.tty.disable_colors)
 353         return;
 354 
 355     orig_groups = mc_config_get_groups (mc_skin->config, NULL);
 356 
 357     for (groups = orig_groups; *groups != NULL; groups++)
 358         if (mc_skin_color_check_inisection (*groups))
 359             mc_config_del_group (mc_skin->config, *groups);
 360 
 361     g_strfreev (orig_groups);
 362 
 363     mc_skin_hardcoded_blackwhite_colors (mc_skin);
 364 }
 365 
 366 /* --------------------------------------------------------------------------------------------- */
 367 /*** public functions ****************************************************************************/
 368 /* --------------------------------------------------------------------------------------------- */
 369 
 370 gboolean
 371 mc_skin_color_parse_ini_file (mc_skin_t *mc_skin)
     /* [previous][next][first][last][top][bottom][index][help]  */
 372 {
 373     gboolean ret = FALSE;
 374     gsize items_count;
 375     gchar **groups, **orig_groups;
 376     tty_color_pair_t *mc_skin_color;
 377 
 378     mc_skin_color_check_bw_mode (mc_skin);
 379 
 380     orig_groups = mc_config_get_groups (mc_skin->config, &items_count);
 381     if (*orig_groups == NULL)
 382         goto ret;
 383 
 384     // as first, need to set up default colors
 385     mc_skin_color_set_default_for_terminal (mc_skin);
 386     mc_skin_color = mc_skin_color_get_from_ini_file (mc_skin, "core", "_default_");
 387     if (mc_skin_color == NULL)
 388         goto ret;
 389 
 390     tty_color_set_defaults (mc_skin_color);
 391     mc_skin_color_add_to_hash (mc_skin, "core", "_default_", mc_skin_color);
 392 
 393     for (groups = orig_groups; *groups != NULL; groups++)
 394     {
 395         gchar **keys, **orig_keys;
 396 
 397         if (!mc_skin_color_check_inisection (*groups))
 398             continue;
 399 
 400         orig_keys = mc_config_get_keys (mc_skin->config, *groups, NULL);
 401 
 402         for (keys = orig_keys; *keys != NULL; keys++)
 403         {
 404             mc_skin_color = mc_skin_color_get_from_ini_file (mc_skin, *groups, *keys);
 405             if (mc_skin_color != NULL)
 406                 mc_skin_color_add_to_hash (mc_skin, *groups, *keys, mc_skin_color);
 407         }
 408         g_strfreev (orig_keys);
 409     }
 410 
 411     mc_skin_color_cache_init ();
 412 
 413     ret = TRUE;
 414 
 415 ret:
 416     g_strfreev (orig_groups);
 417     return ret;
 418 }
 419 
 420 /* --------------------------------------------------------------------------------------------- */
 421 
 422 int
 423 mc_skin_color_get (const gchar *group, const gchar *name)
     /* [previous][next][first][last][top][bottom][index][help]  */
 424 {
 425     tty_color_pair_t *mc_skin_color;
 426 
 427     mc_skin_color = mc_skin_color_get_with_defaults (group, name);
 428 
 429     return (mc_skin_color != NULL) ? mc_skin_color->pair_index : 0;
 430 }
 431 
 432 /* --------------------------------------------------------------------------------------------- */

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