1 /*-----------------------------------------------------------------------------
2 Copyright (C) Sylvain Fourmanoit <syfou@users.sourceforge.net>
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to
6 deal in the Software without restriction, including without limitation the
7 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 sell copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies of the Software and its documentation and acknowledgment shall be
13 given in the documentation and software packages that this Software was
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 ------------------------------------------------------------------------------*/
24 #include "edesklets.h"
27 #include <string.h> /* memcpy() */
30 /*---------------------------------------------------------------------------*/
31 const Desklet DESKLET_DEFAULTS
= {
32 NULL
, /* gchar * id; */
33 NULL
, /* gchar * uri; */
34 0, 0, 300, 200, /* gint x, y, width, height; */
35 FALSE
, /* gboolean decorate; */
36 5, 1 /* gint timeout, attempts; */
39 /*---------------------------------------------------------------------------*/
41 config_default(Desklet
* desc
) {
42 g_memmove(desc
, &DESKLET_DEFAULTS
, sizeof(Desklet
));
45 /*---------------------------------------------------------------------------*/
47 config_path(gchar
* basename
) {
50 path
= g_build_filename(g_get_user_config_dir(), PACKAGE_NAME
, NULL
);
51 if (!g_file_test(path
, G_FILE_TEST_EXISTS
)) {
52 g_warning(_("trying to create configure dir '%s'"), path
);
53 g_mkdir_with_parents(path
, 0755);
55 ret
= g_build_filename(path
, basename
, NULL
);
60 /*---------------------------------------------------------------------------*/
64 if ((conf
= g_malloc0(sizeof(EConfig
))))
65 if (!(conf
->desklets
= g_array_new(FALSE
, TRUE
, sizeof(Desklet
)))) {
72 /*---------------------------------------------------------------------------*/
74 config_load(gboolean nolock
, gboolean readonly
) {
77 gchar
* fn
, * buf
, ** groups
;
85 conf->crashmode = TRUE;\
86 conf->crashmsg = g_strdup_printf(__VA_ARGS__);\
87 g_warning(conf->crashmsg);\
90 if ((conf
= config_new())) {
91 conf
->kf
= g_key_file_new();
92 fn
= config_path("config");
93 if ((conf
->lf
= fopen_locked(fn
,
94 g_file_test(fn
, G_FILE_TEST_EXISTS
)?"r+":"w+",
95 !nolock
, FALSE
|| readonly
, &err
))) {
96 gio
= g_io_channel_unix_new(fileno(file(conf
->lf
)));
97 g_io_channel_read_to_end(gio
, &buf
, &n
, NULL
);
98 g_io_channel_unref(gio
);
100 if (g_key_file_load_from_data(conf
->kf
, buf
, n
,
101 G_KEY_FILE_KEEP_COMMENTS
,
103 groups
= g_key_file_get_groups(conf
->kf
, &n
);
105 if (g_ascii_strcasecmp("general", groups
[i
])!=0) {
106 #define KEY_GET(param, type) \
108 g_clear_error(&err);\
109 desc.param = g_key_file_get_ ## type(conf->kf, groups[i], #param, &err);\
111 g_clear_error(&err);\
112 g_warning(_("could not retrieve value for %s on %s"), #param, groups[i]);\
113 desc.param = DESKLET_DEFAULTS.param;\
117 KEY_GET(uri
, string
);
120 KEY_GET(width
, integer
);
121 KEY_GET(height
, integer
);
122 KEY_GET(decorate
, boolean
);
123 KEY_GET(timeout
, integer
);
124 KEY_GET(attempts
, integer
);
126 g_array_append_val(conf
->desklets
, desc
);
130 g_warning(err
->message
);
131 crash(_("Loading settings from '%s' skipped entirely "
132 "due to parsing error."), fn
);
136 g_warning(_("config file has zero lenght (first use?)."));
140 if (err
->code
== EERROR_ALREADY_LOCKED
) {
141 g_warning(_("could not get lock on '%s': %s"), fn
, err
->message
);
142 crash(_("Could not lock config file: "
143 "you can only edit one desklet at a time. "
144 "If you are not already editing the config of another desklet, "
145 "this might mean locking is not supported by the local system: "
146 "look at eDesklets online FAQ."));
148 g_warning(err
->message
);
149 crash(_("Could not load config file: "
150 "look at eDesklets online FAQ."));
155 if ((conf
->crashmode
= conf
->crashmode
|| readonly
)) {
156 if (conf
->kf
) g_key_file_free(conf
->kf
); conf
->kf
= NULL
;
157 if (conf
->lf
) fclose_locked(&conf
->lf
, NULL
);
160 g_error(_("Could not allocate configuration"));
166 /*---------------------------------------------------------------------------*/
168 config_merge(EConfig
* conf
, Desklet
* desc
) {
172 for (i
=0; i
<conf
->desklets
->len
; ++i
) {
173 item
= &g_array_index(conf
->desklets
, Desklet
, i
);
174 if (g_ascii_strcasecmp(desc
->id
, item
->id
)==0)
177 if (i
== conf
->desklets
->len
)
178 g_array_append_val(conf
->desklets
, (*desc
));
182 /*---------------------------------------------------------------------------*/
184 config_dump(EConfig
** conf
) {
186 gchar
* out
, *group
, **groups
, *isotime
, *comment
;
192 if (!conf
|| !(*conf
)) return;
193 if ((*conf
)->crashmode
)
196 #define kf ((*conf)->kf)
199 g_get_current_time(&tv
);
200 isotime
= g_time_val_to_iso8601(&tv
);
201 comment
= g_strdup_printf(_("\
202 Edit at your own risk! (last modified: %s)\n"), isotime
);
203 g_key_file_set_comment(kf
, NULL
, NULL
, comment
, NULL
);
207 /* ...existing values */
208 for(i
=0; i
<(*conf
)->desklets
->len
;++i
) {
209 group
= g_strdup_printf("desklet_%d", i
);
210 item
= &g_array_index((*conf
)->desklets
, Desklet
, i
);
212 g_key_file_set_string (kf
, group
, "id" , item
->id
);
214 g_key_file_set_string (kf
, group
, "uri" , item
->uri
);
216 g_key_file_set_integer(kf
, group
, "x" , item
->x
);
218 g_key_file_set_integer(kf
, group
, "y" , item
->y
);
219 g_key_file_set_integer(kf
, group
, "width" , item
->width
);
220 g_key_file_set_integer(kf
, group
, "height" , item
->height
);
221 g_key_file_set_boolean(kf
, group
, "decorate", item
->decorate
);
222 g_key_file_set_integer(kf
, group
, "timeout" , item
->timeout
);
223 g_key_file_set_integer(kf
, group
, "attempts", item
->attempts
);
227 /* ...strip removed values */
228 groups
= g_key_file_get_groups(kf
, &n
);
230 if ((g_ascii_strcasecmp("general", groups
[i
])!=0) &&
231 ((g_strstr_len(groups
[i
], 8, "desklet_")==NULL
) ||
232 (atoi(groups
[i
]+8) >= (*conf
)->desklets
->len
)))
233 g_key_file_remove_group(kf
, groups
[i
], NULL
);
235 /* Dump it to file */
236 out
= g_key_file_to_data(kf
, &n
, NULL
);
237 fseek(file((*conf
)->lf
), 0, SEEK_SET
);
238 fwrite(out
, n
, 1, file((*conf
)->lf
));
239 ftruncate(fileno(file((*conf
)->lf
)), n
);
243 fclose_locked(&(*conf
)->lf
, NULL
);
244 if (kf
) g_key_file_free(kf
);
245 g_array_free((*conf
)->desklets
, TRUE
);
246 if ((*conf
)->crashmsg
) g_free((*conf
)->crashmsg
);
253 /*---------------------------------------------------------------------------*/