fixed GTKHTML detection
[k8lowj.git] / src / conf_xml.c
blob2d2e8142f535d8c43457163baf963d50c7c5f2d1
1 /* logjam - a GTK client for LiveJournal.
2 * Copyright (C) 2000-2003 Evan Martin <evan@livejournal.com>
4 * vim: tabstop=4 shiftwidth=4 noexpandtab :
5 */
7 #include <libxml/parser.h>
8 #include <libxml/tree.h>
10 #include <string.h>
12 #include "glib-all.h"
14 #include <stdlib.h> /* atoi */
15 #include "conf.h"
16 #include "conf_xml.h"
17 #include "jam_xml.h"
19 /* XXX win32 gross hack. why does the normal xmlFree cause segfaults? */
20 #ifdef G_OS_WIN32
21 #define xmlFree(x) g_free(x)
22 #endif
24 #define xmlGetString jam_xmlGetString
25 #define xmlAddTN(node, name, value) xmlNewTextChild(node, NULL, BAD_CAST name, BAD_CAST value)
27 /*static xmlNodePtr
28 ljxmlAddTxt(xmlNodePtr node, char *name, char *val) {
29 if (val)
30 return xmlNewTextChild(node, NULL, name, val);
31 return NULL;
32 }*/
34 GSList*
35 conf_parsedirlist(const char *base, void* (*fn)(const char*, void*), void *arg) {
36 GSList *list = NULL;
37 GDir *dir;
38 const char *dirname;
39 char *path;
40 void *data;
42 dir = g_dir_open(base, 0, NULL);
43 if (!dir)
44 return NULL;
46 dirname = g_dir_read_name(dir);
47 while (dirname) {
48 path = g_build_filename(base, dirname, NULL);
49 data = fn(path, arg);
50 if (data)
51 list = g_slist_append(list, data);
52 g_free(path);
53 dirname = g_dir_read_name(dir);
55 g_dir_close(dir);
57 return list;
60 void*
61 conf_parsedirxml(const char *dirname, void* (*fn)(xmlDocPtr, xmlNodePtr, void*), void *data) {
62 xmlDocPtr doc;
63 xmlNodePtr node;
64 void *ret;
65 char *path;
67 path = g_build_filename(dirname, "conf.xml", NULL);
69 if (!g_file_test(path, G_FILE_TEST_EXISTS)) {
70 g_free(path);
71 return NULL;
74 doc = xmlParseFile(path);
75 g_free(path);
76 if (doc == NULL) {
77 fprintf(stderr, _("error parsing configuration file.\n"));
78 return NULL;
81 /* we get the root element instead of the doc's first child
82 * because XML allows comments outside of the root element. */
83 node = xmlDocGetRootElement(doc);
84 if (node == NULL) {
85 fprintf(stderr, _("empty document.\n"));
86 xmlFreeDoc(doc);
87 return NULL;
90 ret = fn(doc, node, data);
91 xmlFreeDoc(doc);
93 return ret;
97 /* we use a bunch of macro magic to make this simpler.
98 * (see xml_macros.h)
101 /* this should match the enum in conf.h */
102 static char* geometry_names[] = {
103 "main",
104 "login",
105 "friends",
106 "friendgroups",
107 "console",
108 "manager",
109 "cffloat",
110 "offline",
111 "preview"
114 static void
115 parsegeometry(Geometry *geom, xmlDocPtr doc, xmlNodePtr node) {
116 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
117 XML_GET_INT("x", geom->x)
118 XML_GET_INT("y", geom->y)
119 XML_GET_INT("width", geom->width)
120 XML_GET_INT("height", geom->height)
121 XML_GET_INT("panedpos", geom->panedpos)
122 XML_GET_END("parsegeometry")
126 static void
127 parsegeometries(Configuration *c, xmlDocPtr doc, xmlNodePtr node) {
128 xmlChar *window;
129 int i;
130 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
131 if (xmlStrcmp(node->name, BAD_CAST "geometry") == 0) {
132 window = xmlGetProp(node, BAD_CAST "window");
133 if (!window) continue;
135 for (i = 0; i < GEOM_COUNT; i++) {
136 if (g_ascii_strcasecmp((char*)window, geometry_names[i]) == 0) {
137 parsegeometry(&c->geometries[i], doc, node);
138 break;
141 xmlFree(window);
146 static void*
147 parsehostdir(const char *dirname, void *data) {
148 return conf_parsedirxml(dirname, (conf_parsedirxml_fn)jam_host_from_xml, (void*)dirname);
150 static GSList*
151 parsehostsdir(char *base) {
152 return conf_parsedirlist(base, parsehostdir, NULL);
155 #ifdef HAVE_GTK
156 static void
157 parseshowmeta(Options *options, xmlDocPtr doc, xmlNodePtr node) {
158 JamViewMeta meta;
159 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
160 if (jam_view_meta_from_name((char*)node->name, &meta))
161 options->showmeta[meta] = TRUE;
164 #endif /* HAVE_GTK */
166 static void
167 parseoptions(Configuration *c, xmlDocPtr doc, xmlNodePtr node) {
168 Options *options = &c->options;
170 #define READOPTION(x) XML_GET_BOOL(#x, options->x)
171 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
172 READOPTION(netdump)
173 READOPTION(nofork)
174 READOPTION(useproxy)
175 READOPTION(useproxyauth)
176 #ifdef HAVE_GTK
177 #ifdef HAVE_GTKSPELL
178 READOPTION(usespellcheck)
179 #endif
180 READOPTION(revertusejournal)
181 READOPTION(autosave)
182 READOPTION(cfautostart)
183 READOPTION(cfusemask)
184 READOPTION(docklet)
185 READOPTION(cffloat)
186 READOPTION(cffloatraise)
187 READOPTION(friends_hidestats)
188 READOPTION(allowmultipleinstances)
189 READOPTION(smartquotes)
190 READOPTION(smartquotes_russian)
192 XML_GET_IF("showmeta", parseshowmeta(options, doc, node);)
194 /* backward compatibility. */
195 XML_GET_BOOL("cfautofloat", options->cffloat)
196 XML_GET_BOOL("cfautofloatraise", options->cffloatraise)
197 #endif /* HAVE_GTK */
198 XML_GET_END("parseoptions")
202 static void
203 parsesecurity(Configuration *c, xmlDocPtr doc, xmlNodePtr node) {
204 xmlChar *typestr;
205 typestr = xmlGetProp(node, BAD_CAST "type");
206 if (!typestr) return;
207 lj_security_from_strings(&c->defaultsecurity, (char*)typestr, NULL);
208 xmlFree(typestr);
211 #ifdef HAVE_GTK
212 static GSList*
213 parsequietdlgs(xmlDocPtr doc, xmlNodePtr node) {
214 GSList *quiet_dlgs = NULL;
215 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
216 XML_GET_LIST("quiet_dlg", quiet_dlgs, xmlGetString)
217 XML_GET_END("parsequietdlgs")
219 return quiet_dlgs;
221 #endif /* HAVE_GTK */
223 #ifndef G_OS_WIN32
224 static void
225 parseproxyauth(Configuration *c, xmlDocPtr doc, xmlNodePtr node) {
226 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
227 XML_GET_STR("username", c->proxyuser)
228 XML_GET_STR("password", c->proxypass)
229 XML_GET_END("parseproxyauth")
232 #endif
234 static void*
235 parseconf(xmlDocPtr doc, xmlNodePtr node, void *data) {
236 char *hostname = NULL;
237 char *hostspath;
238 Configuration *c = data;
240 #define XML_GET_CONF(key, func) XML_GET_IF(key, func(c, doc, node);)
241 node = node->xmlChildrenNode;
242 for (; node != NULL; node = node->next) {
243 XML_GET_STR("currentserver", hostname)
244 XML_GET_CONF("geometries", parsegeometries)
245 XML_GET_CONF("options", parseoptions)
246 XML_GET_CONF("defaultsecurity", parsesecurity)
247 XML_GET_STR("uifont", c->uifont)
248 #ifdef HAVE_GTKSPELL
249 XML_GET_STR("spell_language", c->spell_language)
250 #endif /* HAVE_GTKSPELL */
251 #ifndef G_OS_WIN32
252 XML_GET_STR("proxy", c->proxy)
253 XML_GET_CONF("proxyauth", parseproxyauth)
254 XML_GET_STR("spawncommand", c->spawn_command)
255 XML_GET_STR("musiccommand", c->music_command)
256 #endif /* G_OS_WIN32 */
257 XML_GET_INT("cfuserinterval", c->cfuserinterval)
258 XML_GET_INT("cfthreshold", c->cfthreshold)
259 #ifdef HAVE_GTK
260 XML_GET_FUNC("quiet_dlgs", app.quiet_dlgs, parsequietdlgs)
261 #endif
262 XML_GET_END("conf_xml_read")
265 #ifdef HAVE_GTKSPELL
266 if (!c->spell_language || strlen(c->spell_language) < 2) {
267 g_free(c->spell_language);
268 c->spell_language = g_strdup("en");
270 #endif /* HAVE_GTKSPELL */
271 hostspath = g_build_filename(app.conf_dir, "servers", NULL);
272 c->hosts = parsehostsdir(hostspath);
273 g_free(hostspath);
275 if (hostname) {
276 c->lasthost = conf_host_by_name(c, hostname);
277 g_free(hostname);
279 return NULL;
283 conf_read(Configuration *c, char *path) {
284 conf_parsedirxml(path, parseconf, c);
285 return 0;
288 static void
289 writegeometry(Geometry *geometry, char *name, xmlNodePtr node) {
290 node = xmlNewChild(node, NULL, BAD_CAST "geometry", NULL);
291 xmlSetProp(node, BAD_CAST "window", BAD_CAST name);
292 jam_xmlAddInt(node, "x", geometry->x);
293 jam_xmlAddInt(node, "y", geometry->y);
294 jam_xmlAddInt(node, "width", geometry->width);
295 jam_xmlAddInt(node, "height", geometry->height);
296 if (geometry->panedpos > 0)
297 jam_xmlAddInt(node, "panedpos", geometry->panedpos);
300 #ifdef HAVE_GTK
301 static void
302 writeshowmeta(Options *options, xmlNodePtr node) {
303 xmlNodePtr showmeta = xmlNewChild(node, NULL, BAD_CAST "showmeta", NULL);
304 int i;
305 for (i = JAM_VIEW_META_FIRST; i <= JAM_VIEW_META_LAST; i++) {
306 if (options->showmeta[i])
307 xmlNewChild(showmeta, NULL, BAD_CAST jam_view_meta_to_name(i), NULL);
310 #endif /* HAVE_GTK */
312 static void
313 writeoptions(Options *options, xmlNodePtr node) {
314 #define WRITEOPTION(x) if (options->x) xmlNewChild(node, NULL, BAD_CAST #x, NULL);
315 WRITEOPTION(netdump);
316 WRITEOPTION(nofork);
317 WRITEOPTION(useproxy);
318 WRITEOPTION(useproxyauth);
319 #ifdef HAVE_GTK
320 #ifdef HAVE_GTKSPELL
321 WRITEOPTION(usespellcheck);
322 #endif
323 WRITEOPTION(revertusejournal);
324 WRITEOPTION(autosave);
325 WRITEOPTION(cfautostart);
326 WRITEOPTION(cfusemask);
327 WRITEOPTION(docklet);
328 WRITEOPTION(cffloatraise);
329 WRITEOPTION(cffloat);
330 WRITEOPTION(friends_hidestats);
331 WRITEOPTION(allowmultipleinstances);
332 WRITEOPTION(smartquotes);
333 WRITEOPTION(smartquotes_russian);
335 writeshowmeta(options, node);
336 #endif /* HAVE_GTK */
340 conf_write(Configuration *c, char *base) {
341 GError *err = NULL;
342 xmlDocPtr doc;
343 xmlNodePtr root, node;
344 GSList *l;
345 int i;
346 char *path;
348 jam_xmlNewDoc(&doc, &root, "configuration");
349 xmlSetProp(root, BAD_CAST "version", BAD_CAST "1");
351 for (l = c->hosts; l != NULL; l = l->next) {
352 if (!jam_host_write(l->data, &err)) {
353 g_printerr("%s\n", err->message);
354 g_error_free(err);
355 err = NULL;
359 if (c->lasthost)
360 xmlAddTN(root, "currentserver", c->lasthost->name);
362 node = xmlNewChild(root, NULL, BAD_CAST "geometries", NULL);
363 for (i = 0; i < GEOM_COUNT; i++) {
364 if (c->geometries[i].width > 0) {
365 writegeometry(&c->geometries[i], geometry_names[i], node);
369 node = xmlNewChild(root, NULL, BAD_CAST "options", NULL);
370 writeoptions(&c->options, node);
372 if (c->uifont)
373 xmlAddTN(root, "uifont", c->uifont);
375 #ifdef HAVE_GTKSPELL
376 if (c->spell_language)
377 xmlAddTN(root, "spell_language", c->spell_language);
378 #endif
379 #ifndef G_OS_WIN32
380 if (c->proxy)
381 xmlAddTN(root, "proxy", c->proxy);
382 if (c->proxyuser) {
383 node = xmlNewChild(root, NULL, BAD_CAST "proxyauth", NULL);
384 xmlAddTN(node, "username", c->proxyuser);
385 xmlAddTN(node, "password", c->proxypass);
388 if (c->spawn_command)
389 xmlAddTN(root, "spawncommand", c->spawn_command);
391 if (c->music_command)
392 xmlAddTN(root, "musiccommand", c->music_command);
393 #endif
395 if (c->cfuserinterval) {
396 char buf[20];
397 g_snprintf(buf, 20, "%d", c->cfuserinterval);
398 xmlAddTN(root, "cfuserinterval", buf);
401 if (c->cfthreshold) {
402 char buf[20];
403 g_snprintf(buf, 20, "%d", c->cfthreshold);
404 xmlAddTN(root, "cfthreshold", buf);
407 #ifdef HAVE_GTK
408 if (app.quiet_dlgs) {
409 xmlNodePtr xmlList = xmlNewChild(root, NULL, BAD_CAST "quiet_dlgs", NULL);
410 for (l = app.quiet_dlgs; l != NULL; l = l->next) {
411 xmlAddTN(xmlList, "quiet_dlg", (char*)l->data);
414 #endif /* HAVE_GTK */
416 if (c->defaultsecurity.type != LJ_SECURITY_PUBLIC) {
417 char *type = NULL;
418 if (c->defaultsecurity.type == LJ_SECURITY_CUSTOM)
419 c->defaultsecurity.type = LJ_SECURITY_PRIVATE;
420 lj_security_to_strings(&c->defaultsecurity, &type, NULL);
421 if (type) {
422 node = xmlNewChild(root, NULL, BAD_CAST "defaultsecurity", NULL);
423 xmlSetProp(node, BAD_CAST "type", BAD_CAST type);
424 g_free(type);
428 path = g_build_filename(base, "conf.xml", NULL);
429 if (xmlSaveFormatFile(path, doc, TRUE) < 0) {
430 g_printerr("xmlSaveFormatFile error saving to %s.\n", path);
432 xmlFreeDoc(doc);
433 g_free(path);
434 return 0;