1 /*
2    Skins engine.
3    Interface functions
4 
5    Copyright (C) 2009-2021
6    Free Software Foundation, Inc.
7 
8    Written by:
9    Slava Zanko <slavazanko@gmail.com>, 2009
10    Egmont Koblinger <egmont@gmail.com>, 2010
11 
12    This file is part of the Midnight Commander.
13 
14    The Midnight Commander is free software: you can redistribute it
15    and/or modify it under the terms of the GNU General Public License as
16    published by the Free Software Foundation, either version 3 of the License,
17    or (at your option) any later version.
18 
19    The Midnight Commander is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22    GNU General Public License for more details.
23 
24    You should have received a copy of the GNU General Public License
25    along with this program.  If not, see <http://www.gnu.org/licenses/>.
26  */
27 
28 #include <config.h>
29 #include <stdlib.h>
30 
31 #include "internal.h"
32 #include "lib/util.h"
33 
34 #include "lib/tty/color.h"      /* tty_use_256colors(); */
35 
36 /*** global variables ****************************************************************************/
37 
38 mc_skin_t mc_skin__default;
39 
40 /*** file scope macro definitions ****************************************************************/
41 
42 /*** file scope type declarations ****************************************************************/
43 
44 /*** file scope variables ************************************************************************/
45 
46 static gboolean mc_skin_is_init = FALSE;
47 
48 /* --------------------------------------------------------------------------------------------- */
49 /*** file scope functions ************************************************************************/
50 /* --------------------------------------------------------------------------------------------- */
51 
52 static void
mc_skin_hash_destroy_value(gpointer data)53 mc_skin_hash_destroy_value (gpointer data)
54 {
55     mc_skin_color_t *mc_skin_color = (mc_skin_color_t *) data;
56     g_free (mc_skin_color->fgcolor);
57     g_free (mc_skin_color->bgcolor);
58     g_free (mc_skin_color->attrs);
59     g_free (mc_skin_color);
60 }
61 
62 /* --------------------------------------------------------------------------------------------- */
63 
64 static char *
mc_skin_get_default_name(void)65 mc_skin_get_default_name (void)
66 {
67     char *tmp_str;
68 
69     /* from command line */
70     if (mc_global.tty.skin != NULL)
71         return g_strdup (mc_global.tty.skin);
72 
73     /* from envirovement variable */
74     tmp_str = getenv ("MC_SKIN");
75     if (tmp_str != NULL)
76         return g_strdup (tmp_str);
77 
78     /*  from config. Or 'default' if no present in config */
79     return mc_config_get_string (mc_global.main_config, CONFIG_APP_SECTION, "skin", "default");
80 }
81 
82 /* --------------------------------------------------------------------------------------------- */
83 
84 static void
mc_skin_reinit(void)85 mc_skin_reinit (void)
86 {
87     mc_skin_deinit ();
88     mc_skin__default.name = mc_skin_get_default_name ();
89     mc_skin__default.colors = g_hash_table_new_full (g_str_hash, g_str_equal,
90                                                      g_free, mc_skin_hash_destroy_value);
91 }
92 
93 /* --------------------------------------------------------------------------------------------- */
94 
95 static void
mc_skin_try_to_load_default(void)96 mc_skin_try_to_load_default (void)
97 {
98     mc_skin_reinit ();
99     g_free (mc_skin__default.name);
100     mc_skin__default.name = g_strdup ("default");
101     if (!mc_skin_ini_file_load (&mc_skin__default))
102     {
103         mc_skin_reinit ();
104         mc_skin_set_hardcoded_skin (&mc_skin__default);
105     }
106 
107 }
108 
109 /* --------------------------------------------------------------------------------------------- */
110 /*** public functions ****************************************************************************/
111 /* --------------------------------------------------------------------------------------------- */
112 
113 gboolean
mc_skin_init(const gchar * skin_override,GError ** mcerror)114 mc_skin_init (const gchar * skin_override, GError ** mcerror)
115 {
116     gboolean is_good_init = TRUE;
117     GError *error = NULL;
118 
119     mc_return_val_if_error (mcerror, FALSE);
120 
121     mc_skin__default.have_256_colors = FALSE;
122     mc_skin__default.have_true_colors = FALSE;
123 
124     mc_skin__default.name =
125         skin_override != NULL ? g_strdup (skin_override) : mc_skin_get_default_name ();
126 
127     mc_skin__default.colors = g_hash_table_new_full (g_str_hash, g_str_equal,
128                                                      g_free, mc_skin_hash_destroy_value);
129     if (!mc_skin_ini_file_load (&mc_skin__default))
130     {
131         mc_propagate_error (mcerror, 0,
132                             _("Unable to load '%s' skin.\nDefault skin has been loaded"),
133                             mc_skin__default.name);
134         mc_skin_try_to_load_default ();
135         is_good_init = FALSE;
136     }
137     mc_skin_colors_old_configure (&mc_skin__default);
138 
139     if (!mc_skin_ini_file_parse (&mc_skin__default))
140     {
141         mc_propagate_error (mcerror, 0,
142                             _("Unable to parse '%s' skin.\nDefault skin has been loaded"),
143                             mc_skin__default.name);
144 
145         mc_skin_try_to_load_default ();
146         mc_skin_colors_old_configure (&mc_skin__default);
147         (void) mc_skin_ini_file_parse (&mc_skin__default);
148         is_good_init = FALSE;
149     }
150     if (is_good_init && mc_skin__default.have_true_colors && !tty_use_truecolors (&error))
151     {
152         mc_propagate_error (mcerror, 0,
153                             _
154                             ("Unable to use '%s' skin with true colors support:\n%s\nDefault skin has been loaded"),
155                             mc_skin__default.name, error->message);
156         g_error_free (error);
157         mc_skin_try_to_load_default ();
158         mc_skin_colors_old_configure (&mc_skin__default);
159         (void) mc_skin_ini_file_parse (&mc_skin__default);
160         is_good_init = FALSE;
161     }
162     if (is_good_init && mc_skin__default.have_256_colors && !tty_use_256colors (&error))
163     {
164         mc_propagate_error (mcerror, 0,
165                             _
166                             ("Unable to use '%s' skin with 256 colors support\non non-256 colors terminal.\nDefault skin has been loaded"),
167                             mc_skin__default.name);
168         mc_skin_try_to_load_default ();
169         mc_skin_colors_old_configure (&mc_skin__default);
170         (void) mc_skin_ini_file_parse (&mc_skin__default);
171         is_good_init = FALSE;
172     }
173     mc_skin_is_init = TRUE;
174     return is_good_init;
175 }
176 
177 /* --------------------------------------------------------------------------------------------- */
178 
179 void
mc_skin_deinit(void)180 mc_skin_deinit (void)
181 {
182     tty_color_free_all_tmp ();
183     tty_color_free_all_non_tmp ();
184 
185     MC_PTR_FREE (mc_skin__default.name);
186     g_hash_table_destroy (mc_skin__default.colors);
187     mc_skin__default.colors = NULL;
188 
189     MC_PTR_FREE (mc_skin__default.description);
190 
191     mc_config_deinit (mc_skin__default.config);
192     mc_skin__default.config = NULL;
193 
194     mc_skin_is_init = FALSE;
195 }
196 
197 /* --------------------------------------------------------------------------------------------- */
198 
199 gchar *
mc_skin_get(const gchar * group,const gchar * key,const gchar * default_value)200 mc_skin_get (const gchar * group, const gchar * key, const gchar * default_value)
201 {
202     if (mc_global.tty.ugly_line_drawing)
203     {
204         return g_strdup (default_value);
205     }
206     return mc_config_get_string (mc_skin__default.config, group, key, default_value);
207 }
208 
209 /* --------------------------------------------------------------------------------------------- */
210