1 /**
2  * @file    configfile.c
3  * @brief   handle configuration file
4  *
5  * Copyright (C) 2009 Gummi Developers
6  * All Rights reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person
9  * obtaining a copy of this software and associated documentation
10  * files (the "Software"), to deal in the Software without
11  * restriction, including without limitation the rights to use,
12  * copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the
14  * Software is furnished to do so, subject to the following
15  * conditions:
16  *
17  * The above copyright notice and this permission notice shall be
18  * included in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27  * OTHER DEALINGS IN THE SOFTWARE.
28  */
29 
30 #include "configfile.h"
31 
32 #include <glib.h>
33 #include <string.h>
34 #include <sys/stat.h>
35 
36 #include "constants.h"
37 #include "utils.h"
38 
39 
40 const gchar default_config[] =
41 "[General]\n"
42 "config_version = "C_PACKAGE_VERSION"\n"
43 "\n"
44 "[Interface]\n"
45 "mainwindow_x = 0\n"
46 "mainwindow_y = 0\n"
47 "mainwindow_w = 792\n"
48 "mainwindow_h = 558\n"
49 "mainwindow_max = false\n"
50 "toolbar = true\n"
51 "statusbar = true\n"
52 "snippets = true\n"
53 "[Editor]\n"
54 "font = Monospace 14\n"
55 "line_numbers = true\n"
56 "highlighting = true\n"
57 "textwrapping = true\n"
58 "wordwrapping = true\n"
59 "tabwidth = 4\n"
60 "spaces_instof_tabs = false\n"
61 "autoindentation = true\n"
62 "style_scheme = classic\n"
63 "spelling = false\n"
64 "spelling_lang = None\n"
65 "\n"
66 "[Preview]\n"
67 "zoom_mode = Fit Page Width\n"
68 "pagelayout = one_column\n"
69 "autosync = false\n"
70 "animated_scroll = always\n"
71 "cache_size = 150\n"
72 "\n"
73 "[File]\n"
74 "autosaving = false\n"
75 "autosave_timer = 10\n"
76 "autoexport = false\n"
77 "\n"
78 "[Compile]\n"
79 "typesetter = pdflatex\n"
80 "steps = texpdf\n"
81 "pause = false\n"
82 "scheme = on_idle\n"
83 "timer = 1\n"
84 "shellescape = true\n"
85 "synctex = false\n"
86 "\n"
87 "[Misc]\n"
88 "recent1 = __NULL__\n"
89 "recent2 = __NULL__\n"
90 "recent3 = __NULL__\n"
91 "recent4 = __NULL__\n"
92 "recent5 = __NULL__\n";
93 
94 GKeyFile *key_file = NULL;
95 gchar *conf_filepath = 0;
96 
97 
config_init()98 void config_init () {
99     conf_filepath = g_build_filename (C_GUMMI_CONFDIR, "gummi.ini", NULL);
100 
101     // create config & template dirs if not exists:
102     if (!g_file_test (C_GUMMI_TEMPLATEDIR, G_FILE_TEST_IS_DIR)) {
103         slog (L_WARNING, "Template directory does not exist, creating..\n");
104         g_mkdir_with_parents (C_GUMMI_TEMPLATEDIR, DIR_PERMS);
105     }
106 
107     // load config file:
108     g_autoptr(GError) error = NULL;
109     key_file = g_key_file_new ();
110 
111     if (!g_key_file_load_from_file (key_file, conf_filepath, G_KEY_FILE_NONE, &error)) {
112         if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
113             slog (L_WARNING, "Unable to load config, resetting defaults\n");
114         }
115         else {
116             slog (L_ERROR, "%s\n", error->message);
117         }
118         config_load_defaults (key_file);
119     }
120 
121     // replace old welcome texts if still active:
122     gchar* text;
123     if (g_file_get_contents (C_WELCOMETEXT, &text, NULL, NULL)) {
124         guint hash = g_str_hash (text); // thank you mr daniel bernstein
125         if (hash == -676241409 || // 0.6.6
126             hash == 1654921927 || // 0.7.999
127             hash == 66148856) {   // 0.8.0 dev
128             slog (L_WARNING, "Replacing unchanged welcome text with new default\n");
129             utils_copy_file (C_DEFAULTTEXT, C_WELCOMETEXT, NULL);
130         }
131     }
132     g_free (text);
133 
134     slog (L_INFO, "Configuration file: %s\n", conf_filepath);
135 }
136 
config_get_string(const gchar * group,const gchar * key)137 const gchar* config_get_string (const gchar* group, const gchar* key) {
138     g_autoptr(GError) error = NULL;
139     gchar* value;
140 
141     value = g_key_file_get_string (key_file, group, key, &error);
142 
143     if (error) {
144         return config_get_default_string (group, key);
145     }
146     return value;
147 }
148 
config_get_boolean(const gchar * group,const gchar * key)149 const gboolean config_get_boolean (const gchar* group, const gchar* key) {
150     g_autoptr(GError) error = NULL;
151     gboolean value = FALSE;
152 
153     value = g_key_file_get_boolean (key_file, group, key, &error);
154 
155     if (error) {
156         return config_get_default_boolean (group, key);
157     }
158     return value;
159 }
160 
config_get_integer(const gchar * group,const gchar * key)161 const gint config_get_integer (const gchar* group, const gchar* key) {
162     g_autoptr(GError) error = NULL;
163     gint value = FALSE;
164 
165     value = g_key_file_get_integer (key_file, group, key, &error);
166 
167     if (error) {
168         return config_get_default_integer (group, key);
169     }
170     return value;
171 }
172 
config_get_default_string(const gchar * group,const gchar * key)173 const gchar* config_get_default_string (const gchar* group, const gchar* key) {
174     g_autoptr(GKeyFile) default_keys = g_key_file_new ();
175     gchar *default_value;
176 
177     g_key_file_load_from_data (default_keys,
178                                default_config,
179                                strlen (default_config),
180                                G_KEY_FILE_NONE, NULL);
181 
182     slog (L_WARNING, "Config get default value for '%s.%s'\n", group, key);
183 
184     default_value = g_key_file_get_string (default_keys, group, key, NULL);
185     config_set_string (group, key, default_value);
186 
187     return default_value;
188 }
189 
config_get_default_boolean(const gchar * group,const gchar * key)190 const gboolean config_get_default_boolean (const gchar* group, const gchar* key) {
191     g_autoptr(GKeyFile) default_keys = g_key_file_new ();
192     gboolean default_value;
193 
194     g_key_file_load_from_data (default_keys,
195                                default_config,
196                                strlen (default_config),
197                                G_KEY_FILE_NONE, NULL);
198 
199     slog (L_WARNING, "Config get default value for '%s.%s'\n", group, key);
200 
201     default_value = g_key_file_get_boolean (default_keys, group, key, NULL);
202     config_set_boolean (group, key, default_value);
203 
204     return default_value;
205 }
206 
config_get_default_integer(const gchar * group,const gchar * key)207 const gint config_get_default_integer (const gchar* group, const gchar* key) {
208     g_autoptr(GKeyFile) default_keys = g_key_file_new ();
209     gint default_value;
210 
211     g_key_file_load_from_data (default_keys,
212                                default_config,
213                                strlen (default_config),
214                                G_KEY_FILE_NONE, NULL);
215 
216     slog (L_WARNING, "Config get default value for '%s.%s'\n", group, key);
217 
218     default_value = g_key_file_get_integer (default_keys, group, key, NULL);
219     config_set_integer (group, key, default_value);
220 
221     return default_value;
222 }
223 
config_value_as_str_equals(const gchar * group,const gchar * key,gchar * input)224 gboolean config_value_as_str_equals (const gchar* group, const gchar* key, gchar* input) {
225     const gchar* value;
226 
227     value = config_get_string (group, key);
228     if STR_EQU (value, input) {
229         return TRUE;
230     }
231     return FALSE;
232 }
233 
config_set_string(const gchar * group,const gchar * key,gchar * value)234 void config_set_string (const gchar *group, const gchar *key, gchar* value) {
235     g_key_file_set_string (key_file, group, key, value);
236 }
237 
config_set_boolean(const gchar * group,const gchar * key,gboolean value)238 void config_set_boolean (const gchar *group, const gchar *key, gboolean value) {
239     g_key_file_set_boolean (key_file, group, key, value);
240 }
241 
config_set_integer(const gchar * group,const gchar * key,gint value)242 void config_set_integer (const gchar *group, const gchar *key, gint value) {
243     g_key_file_set_integer (key_file, group, key, value);
244 }
245 
config_load_defaults()246 void config_load_defaults () {
247     g_autoptr(GError) error = NULL;
248 
249     g_key_file_load_from_data (key_file, default_config, strlen(default_config),
250                                G_KEY_FILE_NONE, &error);
251 
252     if (error) {
253         slog (L_ERROR, "Error loading default config: %s\n", error->message);
254     }
255     config_save ();
256 }
257 
config_save()258 void config_save () {
259     g_autoptr(GError) error = NULL;
260 
261     if (!g_key_file_save_to_file (key_file, conf_filepath, &error)) {
262         if (error) {
263             slog (L_ERROR, "Error saving config: %s\n", error->message);
264         }
265     }
266 }
267