1
// vim: set ts=8 sts=8 sw=8 noexpandtab textwidth=112:
3
#include <tilda-config.h>
9
#include <stdlib.h> /* atoi */
10
#include <unistd.h> /* fsync */
12
#include <configsys.h>
13
#include <translation.h>
14
#include <key_converter.h>
19
/* CONFIGURATION OPTIONS */
20
static cfg_opt_t config_opts[] = {
23
CFG_STR("tilda_config_version", PACKAGE_VERSION, CFGF_NONE),
24
CFG_STR("image", NULL, CFGF_NONE),
25
CFG_STR("command", "", CFGF_NONE),
26
CFG_STR("font", "Monospace 13", CFGF_NONE),
27
CFG_STR("key", NULL, CFGF_NONE),
28
CFG_STR("title", "Tilda", CFGF_NONE),
29
CFG_STR("background_color", "white", CFGF_NONE),
30
CFG_STR("working_dir", NULL, CFGF_NONE),
31
CFG_STR("web_browser", "firefox", CFGF_NONE),
34
CFG_INT("lines", 100, CFGF_NONE),
35
CFG_INT("max_width", 600, CFGF_NONE),
36
CFG_INT("max_height", 150, CFGF_NONE),
37
CFG_INT("min_width", 1, CFGF_NONE),
38
CFG_INT("min_height", 1, CFGF_NONE),
39
CFG_INT("transparency", 0, CFGF_NONE),
40
CFG_INT("x_pos", 0, CFGF_NONE),
41
CFG_INT("y_pos", 0, CFGF_NONE),
42
CFG_INT("tab_pos", 0, CFGF_NONE),
43
CFG_INT("backspace_key", 0, CFGF_NONE),
44
CFG_INT("delete_key", 1, CFGF_NONE),
45
CFG_INT("d_set_title", 3, CFGF_NONE),
46
CFG_INT("command_exit", 0, CFGF_NONE),
47
CFG_INT("scheme", 3, CFGF_NONE),
48
CFG_INT("slide_sleep_usec", 15000, CFGF_NONE),
49
CFG_INT("animation_orientation", 0, CFGF_NONE),
52
CFG_INT("scrollbar_pos", 1, CFGF_NONE),
53
CFG_INT("back_red", 0x0000, CFGF_NONE),
54
CFG_INT("back_green", 0x0000, CFGF_NONE),
55
CFG_INT("back_blue", 0x0000, CFGF_NONE),
56
CFG_INT("text_red", 0xffff, CFGF_NONE),
57
CFG_INT("text_green", 0xffff, CFGF_NONE),
58
CFG_INT("text_blue", 0xffff, CFGF_NONE),
61
CFG_BOOL("scroll_background", TRUE, CFGF_NONE),
62
CFG_BOOL("scroll_on_output", FALSE, CFGF_NONE),
63
CFG_BOOL("notebook_border", FALSE, CFGF_NONE),
64
CFG_BOOL("antialias", TRUE, CFGF_NONE),
65
CFG_BOOL("scrollbar", FALSE, CFGF_NONE),
66
CFG_BOOL("use_image", FALSE, CFGF_NONE),
67
CFG_BOOL("grab_focus", TRUE, CFGF_NONE),
68
CFG_BOOL("above", TRUE, CFGF_NONE),
69
CFG_BOOL("notaskbar", TRUE, CFGF_NONE),
70
CFG_BOOL("bold", TRUE, CFGF_NONE),
71
CFG_BOOL("blinks", TRUE, CFGF_NONE),
72
CFG_BOOL("scroll_on_key", TRUE, CFGF_NONE),
73
CFG_BOOL("bell", FALSE, CFGF_NONE),
74
CFG_BOOL("run_command", FALSE, CFGF_NONE),
75
CFG_BOOL("pinned", TRUE, CFGF_NONE),
76
CFG_BOOL("animation", TRUE, CFGF_NONE),
77
CFG_BOOL("hidden", FALSE, CFGF_NONE),
78
CFG_BOOL("centered_horizontally", FALSE, CFGF_NONE),
79
CFG_BOOL("centered_vertically", FALSE, CFGF_NONE),
80
CFG_BOOL("enable_transparency", FALSE, CFGF_NONE),
81
CFG_BOOL("double_buffer", FALSE, CFGF_NONE),
85
static gboolean config_writing_disabled = FALSE;
87
/* Define these here, so that we can enable a non-threadsafe version
88
* without changing the code below. */
90
static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
91
#define config_mutex_lock() g_static_mutex_lock (&mutex)
92
#define config_mutex_unlock() g_static_mutex_unlock (&mutex)
94
#define config_mutex_lock()
95
#define config_mutex_unlock()
98
#define CONFIG1_OLDER -1
99
#define CONFIGS_SAME 0
100
#define CONFIG1_NEWER 1
102
static void try_to_update_config_file (const gchar *config_file);
103
static gboolean compare_config_versions (const gchar *config1, const gchar *config2);
108
* Start up the configuration system, using the configuration file given
109
* to get the current values. If the configuration file given does not exist,
110
* go ahead and write out the default config to the file.
112
gint config_init (const gchar *config_file)
116
tc = cfg_init (config_opts, 0);
118
/* I know that this is racy, but I can't think of a good
119
* way to fix it ... */
120
if (g_file_test (config_file, G_FILE_TEST_IS_REGULAR)) {
121
/* Read the file, and try to upgrade it */
122
ret = cfg_parse (tc, config_file);
124
if (ret == CFG_SUCCESS)
125
try_to_update_config_file (config_file);
127
DEBUG_ERROR ("Problem parsing config");
128
g_printerr (_("Problem parsing config file\n"));
132
/* This is commented out because we don't want to do this. Basically, there
133
* is no need to write the config until we have shown the wizard, which is
134
* automatically shown on the first run. */
137
/* Write out the defaults */
138
config_write (config_file);
145
/* Note: set config_file to NULL to just free the
146
* data structures, and not write out the state to
148
gint config_free (const gchar *config_file)
152
if (config_file != NULL)
153
ret = config_write (config_file);
160
gint config_setint (const gchar *key, const gint val)
162
config_mutex_lock ();
163
cfg_setint (tc, key, val);
164
config_mutex_unlock ();
169
gint config_setstr (const gchar *key, const gchar *val)
171
config_mutex_lock ();
172
cfg_setstr (tc, key, val);
173
config_mutex_unlock ();
178
gint config_setbool(const gchar *key, const gboolean val)
180
config_mutex_lock ();
181
cfg_setbool (tc, key, val);
182
config_mutex_unlock ();
187
gint config_getint (const gchar *key)
191
config_mutex_lock ();
192
temp = cfg_getint (tc, key);
193
config_mutex_unlock ();
198
gchar* config_getstr (const gchar *key)
202
config_mutex_lock ();
203
temp = cfg_getstr (tc, key);
204
config_mutex_unlock ();
209
gboolean config_getbool(const gchar *key)
213
config_mutex_lock ();
214
temp = cfg_getbool (tc, key);
215
config_mutex_unlock ();
220
/* This will write out the current state of the config file to the disk.
221
* It's use is generally discouraged, since config_free() will also write
222
* out the configuration to disk. */
223
gint config_write (const gchar *config_file)
225
DEBUG_FUNCTION ("config_write");
226
DEBUG_ASSERT (config_file != NULL);
231
/* Check to see if writing is disabled. Leave early if it is. */
232
if (config_writing_disabled)
235
fp = fopen(config_file, "w");
239
config_mutex_lock ();
241
config_mutex_unlock ();
243
if (fsync (fileno(fp)))
245
// Error occurred during sync
247
DEBUG_ERROR ("Unable to sync file");
249
g_printerr (_("Unable to sync the config file to disk\n"));
257
DEBUG_ERROR ("Unable to close config file");
259
g_printerr (_("Unable to close the config file\n"));
266
DEBUG_ERROR ("Unable to write config file");
268
g_printerr (_("Unable to write the config file to %s\n"), config_file);
276
* Compares two config versions together.
278
* Returns -1 if config1 is older than config2 (UPDATE REQUIRED)
279
* Returns 0 if config1 is equal to config2 (NORMAL USAGE)
280
* Returns 1 if config1 is newer than config2 (DISABLE WRITE)
282
static gboolean compare_config_versions (const gchar *config1, const gchar *config2)
284
DEBUG_FUNCTION ("compare_config_versions");
285
DEBUG_ASSERT (config1 != NULL);
286
DEBUG_ASSERT (config2 != NULL);
289
* 1) Split apart both strings using the .'s
290
* 2) Compare the major-major version
291
* 3) Compare the major version
292
* 4) Compare the minor version
295
gchar **config1_tokens;
296
gchar **config2_tokens;
297
gint config1_version[3];
298
gint config2_version[3];
301
config1_tokens = g_strsplit (config1, ".", 3);
302
config2_tokens = g_strsplit (config2, ".", 3);
306
config1_version[i] = atoi (config1_tokens[i]);
307
config2_version[i] = atoi (config2_tokens[i]);
310
g_strfreev (config1_tokens);
311
g_strfreev (config2_tokens);
313
/* We're done splitting things, so compare now */
316
if (config1_version[i] > config2_version[i])
317
return CONFIG1_NEWER;
319
if (config1_version[i] < config2_version[i])
320
return CONFIG1_OLDER;
327
* Compare config file versions and see if we know about a new version.
329
* If we have a version newer than what we know about, we need to stop
330
* anything from writing to the config file.
332
* If we are at the same config version, we're done, so exit early.
334
* If the config is older than we are now, update it and then write
337
static void try_to_update_config_file (const gchar *config_file)
339
DEBUG_FUNCTION ("try_to_update_config_file");
340
DEBUG_ASSERT (config_file != NULL);
342
gboolean changed = FALSE;
343
gchar *current_config = config_getstr ("tilda_config_version");
345
if (compare_config_versions (current_config, PACKAGE_VERSION) == CONFIGS_SAME)
346
return; // Same version as ourselves, we're done!
348
if (compare_config_versions (current_config, PACKAGE_VERSION) == CONFIG1_NEWER)
350
// We have a version newer than ourselves!
351
// Disable writing to the config for safety.
352
config_writing_disabled = TRUE;
353
return; // Out early, since we won't be able to update anyway!
356
/* NOTE: Start with the oldest config version first, and work our way up to the
357
* NOTE: newest that we support, updating our current version each time.
359
* NOTE: You may need to re-read the config each time! Probably not though,
360
* NOTE: since you should be updating VALUES not names directly in the config.
361
* NOTE: Try to rely on libconfuse to generate the configs :) */
363
/* Below is a template for creating new entries in the updater. If you ever
364
* change anything between versions, copy this, replacing YOUR_VERSION
365
* with the new version that you are making. */
367
if (compare_config_versions (current_config, YOUR_VERSION) == CONFIG1_OLDER)
369
// TODO: Add things here to migrate from whatever we are to YOUR_VERSION
370
current_config = YOUR_VERSION;
375
if (compare_config_versions (current_config, "0.09.4") == CONFIG1_OLDER)
377
/* Nothing to update here. All we did was add an option, there is no
378
* need to rewrite the config file here, since the writer at the end
379
* will automatically add the default value of the new option. */
380
current_config = "0.09.4";
384
if (compare_config_versions (current_config, "0.9.5") == CONFIG1_OLDER)
389
old_key = config_getstr ("key");
390
new_key = upgrade_key_to_095 (old_key);
392
config_setstr ("key", new_key);
395
current_config = "0.9.5";
399
/* We've run through all the updates, so set our config file version to the
400
* version we're at now, then write out the config file.
402
* NOTE: this only happens if we upgraded the config, due to some early-exit
408
config_setstr ("tilda_config_version", current_config);
409
config_write (config_file);