1 /*
2     roxterm - VTE/GTK terminal emulator with tabs
3     Copyright (C) 2004-2015 Tony Houghton <h@realh.co.uk>
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 
20 
21 #include "defns.h"
22 
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "dlg.h"
28 #include "options.h"
29 #include "optsfile.h"
30 
options_reload_keyfile(Options * options)31 void options_reload_keyfile(Options *options)
32 {
33 	if (options->kf)
34 		options_delete_keyfile(options);
35 	options->kf = options_file_open(options->name, options->group_name);
36 	options->kf_dirty = FALSE;
37 }
38 
options_open(const char * leafname,const char * group_name)39 Options *options_open(const char *leafname, const char *group_name)
40 {
41 	Options *options = g_new0(Options, 1);
42 
43 	options->group_name = group_name;
44 	options->name = g_strdup(leafname);
45 	options->ref = 1;
46 	options_reload_keyfile(options);
47 	return options;
48 }
49 
options_copy_keyfile(Options * dest,const Options * src)50 gboolean options_copy_keyfile(Options *dest, const Options *src)
51 {
52 	gsize l = 0;
53 	GError *err = NULL;
54 	char *kf_data = g_key_file_to_data(src->kf, &l, &err);
55 	GKeyFile *old_kf = NULL;
56 	gboolean result = TRUE;
57 
58 	if (dest->kf)
59 	{
60 		old_kf = dest->kf;
61 		dest->kf = NULL;
62 	}
63 	if (err)
64 		goto copy_err;
65 	dest->kf = g_key_file_new();
66 	if (!l || g_key_file_load_from_data(dest->kf, kf_data, l,
67 		G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &err))
68 	{
69 		goto copy_done;
70 	}
71 
72 copy_err:
73 	result = FALSE;
74 	if (err && err->message)
75 		g_critical(_("Unable to copy options keyfile data: %s"), err->message);
76 	if (dest->kf)
77 		g_key_file_free(dest->kf);
78 	dest->kf = old_kf;
79 	old_kf = NULL;
80 
81 copy_done:
82 	if (old_kf)
83 		g_key_file_free(old_kf);
84 	g_free(kf_data);
85 	return result;
86 }
87 
options_copy(const Options * old_opts)88 Options *options_copy(const Options *old_opts)
89 {
90 	Options *new_opts = g_new(Options, 1);
91 
92 	*new_opts = *old_opts;
93 	new_opts->kf = NULL;
94 	new_opts->user_data = NULL;
95 	if (options_copy_keyfile(new_opts, old_opts))
96 	{
97 		new_opts->name = g_strdup(old_opts->name);
98 	}
99 	else
100 	{
101 		g_free(new_opts);
102 		new_opts = NULL;
103 	}
104 	return new_opts;
105 }
106 
options_delete_keyfile(Options * options)107 void options_delete_keyfile(Options * options)
108 {
109 	options_file_delete(options->kf);
110 	options->kf = NULL;
111 }
112 
options_delete(Options * options)113 void options_delete(Options *options)
114 {
115 	if (options->kf)
116 		options_delete_keyfile(options);
117 	g_free(options->name);
118 	g_free(options);
119 }
120 
121 /* Deletes options and returns true if ref reaches zero */
options_unref(Options * options)122 gboolean options_unref(Options * options)
123 {
124 	if (!--options->ref)
125 	{
126 		options_delete(options);
127 		return TRUE;
128 	}
129 	return FALSE;
130 }
131 
options_lookup_string_with_default(Options * options,const char * key,const char * default_value)132 char *options_lookup_string_with_default(Options * options,
133 	const char *key, const char *default_value)
134 {
135 	return options_file_lookup_string_with_default(
136 			options->kf, options->group_name,
137 			key, default_value);
138 }
139 
options_lookup_int_with_default(Options * options,const char * key,int default_value)140 int options_lookup_int_with_default(Options * options,
141 	const char *key, int default_value)
142 {
143 	return options_file_lookup_int_with_default(
144 			options->kf, options->group_name,
145 			key, default_value);
146 }
147 
options_lookup_double_with_default(Options * options,const char * key,double d)148 double options_lookup_double_with_default(Options *options, const char *key,
149         double d)
150 {
151 	char *str_val = options_lookup_string(options, key);
152 	double result = d;
153 
154 	if (str_val)
155 	{
156 		char *endptr;
157 
158 		errno = 0;
159 		result = strtod(str_val, &endptr);
160 		if (endptr == str_val)
161 		{
162 			dlg_warning(NULL,
163 			  _("Unable to convert value '%s' for key '%s' in '%s' to number"),
164 				str_val, key, options->name);
165             result = d;
166 		}
167 		else if (errno)
168 		{
169 			dlg_warning(NULL,
170 				_("Unable to convert value '%s' for key '%s' in '%s' "
171 						"to number: %s"),
172 				str_val, key, options->name, strerror(errno));
173             result = d;
174 		}
175 	}
176 	return result;
177 }
178 
179 
options_set_string(Options * options,const char * key,const char * value)180 void options_set_string(Options * options, const char *key, const char *value)
181 {
182 	if (!options->kf)
183 		options->kf = g_key_file_new();
184 	g_key_file_set_string(options->kf, options->group_name, key,
185 			value ? value : "");
186 }
187 
options_set_int(Options * options,const char * key,int value)188 void options_set_int(Options * options, const char *key, int value)
189 {
190 	if (!options->kf)
191 		options->kf = g_key_file_new();
192 	g_key_file_set_integer(options->kf, options->group_name, key, value);
193 }
194 
options_set_double(Options * options,const char * key,double value)195 void options_set_double(Options * options, const char *key, double value)
196 {
197 	char *str_val = g_strdup_printf("%f", value);
198 
199 	options_set_string(options, key, str_val);
200 	g_free(str_val);
201 }
202 
options_get_leafname(Options * options)203 const char *options_get_leafname(Options *options)
204 {
205 	const char *leafname = strrchr(options->name, G_DIR_SEPARATOR);
206 
207 	return leafname ? leafname + 1 : options->name;
208 }
209 
options_change_leafname(Options * options,const char * new_leaf)210 void options_change_leafname(Options *options, const char *new_leaf)
211 {
212 	char *old_name = options->name;
213 	char *old_leaf = strrchr(options->name, G_DIR_SEPARATOR);
214 
215 	if (old_leaf)
216 	{
217 		*old_leaf = 0;
218 		options->name = g_build_filename(old_name, new_leaf, NULL);
219 	}
220 	else
221 	{
222 		options->name = g_strdup(new_leaf);
223 	}
224 	g_free(old_name);
225 }
226 
227 /* vi:set sw=4 ts=4 noet cindent cino= */
228