comparison src/prefs.c @ 10443:b6ca0e1b19d0

[gaim-migrate @ 11703] Shuffle some things around in prefs.c and use xmlnode/the util function for saving prefs. Now all our xml files are written to disk at once, with gobs of error detection. If anyone complains about losing their config file with 2.x, send them to me. Muwha ha ha ha ha. Ha. Heh. Sigh. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Tue, 28 Dec 2004 19:11:15 +0000
parents 3232e1a33899
children fa06fda62868
comparison
equal deleted inserted replaced
10442:937697da5233 10443:b6ca0e1b19d0
45 gpointer data; 45 gpointer data;
46 guint id; 46 guint id;
47 void *handle; 47 void *handle;
48 }; 48 };
49 49
50 /* TODO: This should use GaimValues? */
50 struct gaim_pref { 51 struct gaim_pref {
51 GaimPrefType type; 52 GaimPrefType type;
52 char *name; 53 char *name;
53 union { 54 union {
54 gpointer generic; 55 gpointer generic;
61 struct gaim_pref *parent; 62 struct gaim_pref *parent;
62 struct gaim_pref *sibling; 63 struct gaim_pref *sibling;
63 struct gaim_pref *first_child; 64 struct gaim_pref *first_child;
64 }; 65 };
65 66
67
68 static struct gaim_pref prefs = {
69 GAIM_PREF_NONE,
70 NULL,
71 { NULL },
72 NULL,
73 NULL,
74 NULL,
75 NULL
76 };
77
66 static GHashTable *prefs_hash = NULL; 78 static GHashTable *prefs_hash = NULL;
67 79 static guint save_timer = 0;
68 static struct gaim_pref prefs = { GAIM_PREF_NONE, NULL, {NULL}, NULL, 80 static gboolean prefs_loaded = FALSE;
69 NULL, NULL, NULL }; 81
70 82
71 static guint prefs_save_timer = 0; 83 /*********************************************************************
72 static gboolean prefs_is_loaded = FALSE; 84 * Private utility functions *
73 85 *********************************************************************/
74 86
75 static gboolean prefs_save_callback(gpointer who_cares) { 87 static struct
76 gaim_prefs_sync(); 88 gaim_pref *find_pref(const char *name)
77 prefs_save_timer = 0; 89 {
90 if (!name || name[0] != '/')
91 return NULL;
92 else if (name[1] == '\0')
93 return &prefs;
94 else
95 return g_hash_table_lookup(prefs_hash, name);
96 }
97
98
99 /*********************************************************************
100 * Writing to disk *
101 *********************************************************************/
102
103 /*
104 * This function recursively creates the xmlnode tree from the prefs
105 * tree structure. Yay recursion!
106 */
107 void
108 pref_to_xmlnode(xmlnode *parent, struct gaim_pref *pref)
109 {
110 xmlnode *node, *childnode;
111 struct gaim_pref *child;
112 char buf[20];
113 GList *cur;
114
115 /* Create a new node */
116 node = xmlnode_new_child(parent, "pref");
117 xmlnode_set_attrib(node, "name", pref->name);
118
119 /* Set the type of this node (if type == GAIM_PREF_NONE then do nothing) */
120 if (pref->type == GAIM_PREF_INT) {
121 xmlnode_set_attrib(node, "type", "int");
122 snprintf(buf, sizeof(buf), "%d", pref->value.integer);
123 xmlnode_set_attrib(node, "value", buf);
124 }
125 else if (pref->type == GAIM_PREF_STRING) {
126 xmlnode_set_attrib(node, "type", "string");
127 xmlnode_set_attrib(node, "value", pref->value.string);
128 }
129 else if (pref->type == GAIM_PREF_STRING_LIST) {
130 xmlnode_set_attrib(node, "type", "stringlist");
131 for (cur = pref->value.stringlist; cur != NULL; cur = cur->next)
132 {
133 childnode = xmlnode_new_child(node, "item");
134 xmlnode_set_attrib(childnode, "value", cur->data);
135 }
136 }
137 else if (pref->type == GAIM_PREF_BOOLEAN) {
138 xmlnode_set_attrib(node, "type", "bool");
139 snprintf(buf, sizeof(buf), "%d", pref->value.boolean);
140 xmlnode_set_attrib(node, "value", buf);
141 }
142
143 /* All My Children */
144 for (child = pref->first_child; child != NULL; child = child->sibling)
145 pref_to_xmlnode(node, child);
146 }
147
148 static xmlnode *
149 prefs_to_xmlnode(void)
150 {
151 xmlnode *node;
152 struct gaim_pref *pref, *child;
153
154 pref = &prefs;
155
156 /* Create the root preference node */
157 node = xmlnode_new("pref");
158 xmlnode_set_attrib(node, "version", "1");
159 xmlnode_set_attrib(node, "name", "/");
160
161 /* All My Children */
162 for (child = pref->first_child; child != NULL; child = child->sibling)
163 pref_to_xmlnode(node, child);
164
165 return node;
166 }
167
168 static void
169 sync_prefs(void)
170 {
171 xmlnode *node;
172 char *data;
173
174 if (!prefs_loaded)
175 {
176 /*
177 * TODO: Call schedule_prefs_save()? Ideally we wouldn't need to.
178 * (prefs.xml should be loaded when gaim_prefs_init is called)
179 */
180 gaim_debug_error("prefs", "Attempted to save prefs before "
181 "they were read!\n");
182 return;
183 }
184
185 node = prefs_to_xmlnode();
186 data = xmlnode_to_formatted_str(node, NULL);
187 gaim_util_write_data_to_file("prefs.xml", data, -1);
188 g_free(data);
189 xmlnode_free(node);
190 }
191
192 static gboolean
193 save_cb(gpointer data)
194 {
195 sync_prefs();
196 save_timer = 0;
78 return FALSE; 197 return FALSE;
79 } 198 }
80 199
81 static void schedule_prefs_save() { 200 static void
82 if(!prefs_save_timer) 201 schedule_prefs_save(void)
83 prefs_save_timer = gaim_timeout_add(5000, prefs_save_callback, NULL); 202 {
84 } 203 if (save_timer == 0)
85 204 save_timer = gaim_timeout_add(5000, save_cb, NULL);
86 static void prefs_save_cb(const char *name, GaimPrefType type, gpointer val, 205 }
87 gpointer user_data) { 206
88 207
89 if(!prefs_is_loaded) 208 /*********************************************************************
90 return; 209 * Reading from disk *
91 210 *********************************************************************/
92 gaim_debug(GAIM_DEBUG_MISC, "prefs", "%s changed, scheduling save.\n", name); 211
212 static GList *prefs_stack = NULL;
213
214 static void
215 prefs_start_element_handler (GMarkupParseContext *context,
216 const gchar *element_name,
217 const gchar **attribute_names,
218 const gchar **attribute_values,
219 gpointer user_data,
220 GError **error)
221 {
222 GaimPrefType pref_type = GAIM_PREF_NONE;
223 int i;
224 const char *pref_name = NULL, *pref_value = NULL;
225 GString *pref_name_full;
226 GList *tmp;
227
228 if(strcmp(element_name, "pref") && strcmp(element_name, "item"))
229 return;
230
231 for(i = 0; attribute_names[i]; i++) {
232 if(!strcmp(attribute_names[i], "name")) {
233 pref_name = attribute_values[i];
234 } else if(!strcmp(attribute_names[i], "type")) {
235 if(!strcmp(attribute_values[i], "bool"))
236 pref_type = GAIM_PREF_BOOLEAN;
237 else if(!strcmp(attribute_values[i], "int"))
238 pref_type = GAIM_PREF_INT;
239 else if(!strcmp(attribute_values[i], "string"))
240 pref_type = GAIM_PREF_STRING;
241 else if(!strcmp(attribute_values[i], "stringlist"))
242 pref_type = GAIM_PREF_STRING_LIST;
243 else
244 return;
245 } else if(!strcmp(attribute_names[i], "value")) {
246 pref_value = attribute_values[i];
247 }
248 }
249
250 if(!strcmp(element_name, "item")) {
251 struct gaim_pref *pref;
252
253 pref_name_full = g_string_new("");
254
255 for(tmp = prefs_stack; tmp; tmp = tmp->next) {
256 pref_name_full = g_string_prepend(pref_name_full, tmp->data);
257 pref_name_full = g_string_prepend_c(pref_name_full, '/');
258 }
259
260 pref = find_pref(pref_name_full->str);
261
262 if(pref) {
263 pref->value.stringlist = g_list_append(pref->value.stringlist,
264 g_strdup(pref_value));
265 }
266 } else {
267 if(!pref_name || !strcmp(pref_name, "/"))
268 return;
269
270 pref_name_full = g_string_new(pref_name);
271
272 for(tmp = prefs_stack; tmp; tmp = tmp->next) {
273 pref_name_full = g_string_prepend_c(pref_name_full, '/');
274 pref_name_full = g_string_prepend(pref_name_full, tmp->data);
275 }
276
277 pref_name_full = g_string_prepend_c(pref_name_full, '/');
278
279 switch(pref_type) {
280 case GAIM_PREF_NONE:
281 gaim_prefs_add_none(pref_name_full->str);
282 break;
283 case GAIM_PREF_BOOLEAN:
284 gaim_prefs_set_bool(pref_name_full->str, atoi(pref_value));
285 break;
286 case GAIM_PREF_INT:
287 gaim_prefs_set_int(pref_name_full->str, atoi(pref_value));
288 break;
289 case GAIM_PREF_STRING:
290 gaim_prefs_set_string(pref_name_full->str, pref_value);
291 break;
292 case GAIM_PREF_STRING_LIST:
293 gaim_prefs_set_string_list(pref_name_full->str, NULL);
294 break;
295 }
296 prefs_stack = g_list_prepend(prefs_stack, g_strdup(pref_name));
297 g_string_free(pref_name_full, TRUE);
298 }
299 }
300
301 static void
302 prefs_end_element_handler(GMarkupParseContext *context,
303 const gchar *element_name,
304 gpointer user_data, GError **error)
305 {
306 if(prefs_stack && !strcmp(element_name, "pref")) {
307 g_free(prefs_stack->data);
308 prefs_stack = g_list_delete_link(prefs_stack, prefs_stack);
309 }
310 }
311
312 static GMarkupParser prefs_parser = {
313 prefs_start_element_handler,
314 prefs_end_element_handler,
315 NULL,
316 NULL,
317 NULL
318 };
319
320 gboolean
321 gaim_prefs_load()
322 {
323 gchar *filename = g_build_filename(gaim_user_dir(), "prefs.xml", NULL);
324 gchar *contents = NULL;
325 gsize length;
326 GMarkupParseContext *context;
327 GError *error = NULL;
328
329 if (!filename) {
330 prefs_loaded = TRUE;
331 return FALSE;
332 }
333
334 gaim_debug_info("prefs", "Reading %s\n", filename);
335
336 if(!g_file_get_contents(filename, &contents, &length, &error)) {
337 #ifndef _WIN32
338 g_free(filename);
339 g_error_free(error);
340
341 error = NULL;
342
343 filename = g_build_filename(SYSCONFDIR, "gaim", "prefs.xml", NULL);
344
345 gaim_debug_info("prefs", "Reading %s\n", filename);
346
347 if (!g_file_get_contents(filename, &contents, &length, &error)) {
348 gaim_debug_error("prefs", "Error reading prefs: %s\n",
349 error->message);
350 g_error_free(error);
351 g_free(filename);
352 prefs_loaded = TRUE;
353
354 return FALSE;
355 }
356 #else /* _WIN32 */
357 gaim_debug_error("prefs", "Error reading prefs: %s\n",
358 error->message);
359 g_error_free(error);
360 g_free(filename);
361 prefs_loaded = TRUE;
362
363 return FALSE;
364 #endif /* _WIN32 */
365 }
366
367 context = g_markup_parse_context_new(&prefs_parser, 0, NULL, NULL);
368
369 if(!g_markup_parse_context_parse(context, contents, length, NULL)) {
370 g_markup_parse_context_free(context);
371 g_free(contents);
372 g_free(filename);
373 prefs_loaded = TRUE;
374
375 return FALSE;
376 }
377
378 if(!g_markup_parse_context_end_parse(context, NULL)) {
379 gaim_debug_error("prefs", "Error parsing %s\n", filename);
380 g_markup_parse_context_free(context);
381 g_free(contents);
382 g_free(filename);
383 prefs_loaded = TRUE;
384
385 return FALSE;
386 }
387
388 gaim_debug_info("prefs", "Finished reading %s\n", filename);
389 g_markup_parse_context_free(context);
390 g_free(contents);
391 g_free(filename);
392 prefs_loaded = TRUE;
393
394 return TRUE;
395 }
396
397
398
399 static void
400 prefs_save_cb(const char *name, GaimPrefType type, gpointer val,
401 gpointer user_data)
402 {
403
404 if(!prefs_loaded)
405 return;
406
407 gaim_debug_misc("prefs", "%s changed, scheduling save.\n", name);
93 408
94 schedule_prefs_save(); 409 schedule_prefs_save();
95 }
96
97 void gaim_prefs_init() {
98 prefs_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
99
100 gaim_prefs_connect_callback(NULL, "/", prefs_save_cb, NULL);
101
102 gaim_prefs_add_none("/core");
103 gaim_prefs_add_none("/plugins");
104 gaim_prefs_add_none("/plugins/core");
105 gaim_prefs_add_none("/plugins/lopl");
106 gaim_prefs_add_none("/plugins/prpl");
107
108 /* Away */
109 gaim_prefs_add_none("/core/away");
110 gaim_prefs_add_bool("/core/away/away_when_idle", TRUE);
111 gaim_prefs_add_int("/core/away/mins_before_away", 5);
112 /* XXX: internationalized string in prefs...evil */
113 gaim_prefs_add_string("/core/away/default_message",
114 _("Slightly less boring default"));
115
116 /* Away -> Auto-Reply */
117 if (!gaim_prefs_exists("/core/away/auto_response/enabled") ||
118 !gaim_prefs_exists("/core/away/auto_response/idle_only")) {
119 gaim_prefs_add_string("/core/away/auto_reply", "awayidle");
120 } else {
121 if (!gaim_prefs_get_bool("/core/away/auto_response/enabled")) {
122 gaim_prefs_add_string("/core/away/auto_reply", "never");
123 } else {
124 if (gaim_prefs_get_bool("/core/away/auto_response/idle_only")) {
125 gaim_prefs_add_string("/core/away/auto_reply", "awayidle");
126 } else {
127 gaim_prefs_add_string("/core/away/auto_reply", "away");
128 }
129 }
130 }
131
132 /* Buddies */
133 gaim_prefs_add_none("/core/buddies");
134
135 /* Contact Priority Settings */
136 gaim_prefs_add_none("/core/contact");
137 gaim_prefs_add_bool("/core/contact/last_match", FALSE);
138 gaim_prefs_add_int("/core/contact/offline_score", 4);
139 gaim_prefs_add_int("/core/contact/away_score", 2);
140 gaim_prefs_add_int("/core/contact/idle_score", 1);
141 }
142
143 void
144 gaim_prefs_uninit()
145 {
146 if (prefs_save_timer != 0) {
147 gaim_timeout_remove(prefs_save_timer);
148 prefs_save_timer = 0;
149 gaim_prefs_sync();
150 }
151 } 410 }
152 411
153 static char * 412 static char *
154 get_path_dirname(const char *name) 413 get_path_dirname(const char *name)
155 { 414 {
184 return g_strdup(c + 1); 443 return g_strdup(c + 1);
185 444
186 return g_strdup(name); 445 return g_strdup(name);
187 } 446 }
188 447
189 static char *pref_full_name(struct gaim_pref *pref) { 448 static char *
449 pref_full_name(struct gaim_pref *pref)
450 {
190 GString *name; 451 GString *name;
191 struct gaim_pref *parent; 452 struct gaim_pref *parent;
192 char *ret; 453 char *ret;
193 454
194 if(!pref) 455 if(!pref)
207 ret = name->str; 468 ret = name->str;
208 g_string_free(name, FALSE); 469 g_string_free(name, FALSE);
209 return ret; 470 return ret;
210 } 471 }
211 472
212 static struct gaim_pref *find_pref(const char *name) 473 static struct gaim_pref *
213 { 474 find_pref_parent(const char *name)
214 if(!name || name[0] != '/') {
215 return NULL;
216 } else if(name[1] == '\0') {
217 return &prefs;
218 } else {
219 return g_hash_table_lookup(prefs_hash, name);
220 }
221 }
222
223 static struct gaim_pref *find_pref_parent(const char *name)
224 { 475 {
225 char *parent_name = get_path_dirname(name); 476 char *parent_name = get_path_dirname(name);
226 struct gaim_pref *ret = &prefs; 477 struct gaim_pref *ret = &prefs;
227 478
228 if(strcmp(parent_name, "/")) { 479 if(strcmp(parent_name, "/")) {
231 482
232 g_free(parent_name); 483 g_free(parent_name);
233 return ret; 484 return ret;
234 } 485 }
235 486
236 static void free_pref_value(struct gaim_pref *pref) { 487 static void
488 free_pref_value(struct gaim_pref *pref)
489 {
237 switch(pref->type) { 490 switch(pref->type) {
238 case GAIM_PREF_BOOLEAN: 491 case GAIM_PREF_BOOLEAN:
239 pref->value.boolean = FALSE; 492 pref->value.boolean = FALSE;
240 break; 493 break;
241 case GAIM_PREF_INT: 494 case GAIM_PREF_INT:
256 case GAIM_PREF_NONE: 509 case GAIM_PREF_NONE:
257 break; 510 break;
258 } 511 }
259 } 512 }
260 513
261 static struct gaim_pref *add_pref(GaimPrefType type, const char *name) { 514 static struct gaim_pref *
515 add_pref(GaimPrefType type, const char *name)
516 {
262 struct gaim_pref *parent; 517 struct gaim_pref *parent;
263 struct gaim_pref *me; 518 struct gaim_pref *me;
264 struct gaim_pref *sibling; 519 struct gaim_pref *sibling;
265 char *my_name; 520 char *my_name;
266 521
295 g_hash_table_insert(prefs_hash, g_strdup(name), (gpointer)me); 550 g_hash_table_insert(prefs_hash, g_strdup(name), (gpointer)me);
296 551
297 return me; 552 return me;
298 } 553 }
299 554
300 void gaim_prefs_add_none(const char *name) { 555 void
556 gaim_prefs_add_none(const char *name)
557 {
301 add_pref(GAIM_PREF_NONE, name); 558 add_pref(GAIM_PREF_NONE, name);
302 } 559 }
303 560
304 void gaim_prefs_add_bool(const char *name, gboolean value) { 561 void
562 gaim_prefs_add_bool(const char *name, gboolean value)
563 {
305 struct gaim_pref *pref = add_pref(GAIM_PREF_BOOLEAN, name); 564 struct gaim_pref *pref = add_pref(GAIM_PREF_BOOLEAN, name);
306 565
307 if(!pref) 566 if(!pref)
308 return; 567 return;
309 568
310 pref->value.boolean = value; 569 pref->value.boolean = value;
311 } 570 }
312 571
313 void gaim_prefs_add_int(const char *name, int value) { 572 void
573 gaim_prefs_add_int(const char *name, int value)
574 {
314 struct gaim_pref *pref = add_pref(GAIM_PREF_INT, name); 575 struct gaim_pref *pref = add_pref(GAIM_PREF_INT, name);
315 576
316 if(!pref) 577 if(!pref)
317 return; 578 return;
318 579
319 pref->value.integer = value; 580 pref->value.integer = value;
320 } 581 }
321 582
322 void gaim_prefs_add_string(const char *name, const char *value) { 583 void
584 gaim_prefs_add_string(const char *name, const char *value)
585 {
323 struct gaim_pref *pref = add_pref(GAIM_PREF_STRING, name); 586 struct gaim_pref *pref = add_pref(GAIM_PREF_STRING, name);
324 587
325 if(!pref) 588 if(!pref)
326 return; 589 return;
327 590
328 pref->value.string = g_strdup(value); 591 pref->value.string = g_strdup(value);
329 } 592 }
330 593
331 void gaim_prefs_add_string_list(const char *name, GList *value) { 594 void
595 gaim_prefs_add_string_list(const char *name, GList *value)
596 {
332 struct gaim_pref *pref = add_pref(GAIM_PREF_STRING_LIST, name); 597 struct gaim_pref *pref = add_pref(GAIM_PREF_STRING_LIST, name);
333 GList *tmp; 598 GList *tmp;
334 599
335 if(!pref) 600 if(!pref)
336 return; 601 return;
338 for(tmp = value; tmp; tmp = tmp->next) 603 for(tmp = value; tmp; tmp = tmp->next)
339 pref->value.stringlist = g_list_append(pref->value.stringlist, 604 pref->value.stringlist = g_list_append(pref->value.stringlist,
340 g_strdup(tmp->data)); 605 g_strdup(tmp->data));
341 } 606 }
342 607
343 void remove_pref(struct gaim_pref *pref) { 608 void
609 remove_pref(struct gaim_pref *pref)
610 {
344 char *name; 611 char *name;
345 612
346 if(!pref || pref == &prefs) 613 if(!pref || pref == &prefs)
347 return; 614 return;
348 615
358 sib->sibling = pref->sibling; 625 sib->sibling = pref->sibling;
359 } 626 }
360 627
361 name = pref_full_name(pref); 628 name = pref_full_name(pref);
362 629
363 gaim_debug(GAIM_DEBUG_INFO, "prefs", "removing pref /%s\n", name); 630 gaim_debug_info("prefs", "removing pref /%s\n", name);
364 631
365 g_hash_table_remove(prefs_hash, name); 632 g_hash_table_remove(prefs_hash, name);
366 g_free(name); 633 g_free(name);
367 634
368 free_pref_value(pref); 635 free_pref_value(pref);
370 g_slist_free(pref->callbacks); 637 g_slist_free(pref->callbacks);
371 g_free(pref->name); 638 g_free(pref->name);
372 g_free(pref); 639 g_free(pref);
373 } 640 }
374 641
375 void gaim_prefs_remove(const char *name) { 642 void
643 gaim_prefs_remove(const char *name)
644 {
376 struct gaim_pref *pref = find_pref(name); 645 struct gaim_pref *pref = find_pref(name);
377 646
378 if(!pref) 647 if(!pref)
379 return; 648 return;
380 649
381 remove_pref(pref); 650 remove_pref(pref);
382 } 651 }
383 652
384 void gaim_prefs_destroy() { 653 void
654 gaim_prefs_destroy()
655 {
385 gaim_prefs_remove("/"); 656 gaim_prefs_remove("/");
386 } 657 }
387 658
388 static void do_callbacks(const char* name, struct gaim_pref *pref) { 659 static void
660 do_callbacks(const char* name, struct gaim_pref *pref)
661 {
389 GSList *cbs; 662 GSList *cbs;
390 struct gaim_pref *cb_pref; 663 struct gaim_pref *cb_pref;
391 for(cb_pref = pref; cb_pref; cb_pref = cb_pref->parent) { 664 for(cb_pref = pref; cb_pref; cb_pref = cb_pref->parent) {
392 for(cbs = cb_pref->callbacks; cbs; cbs = cbs->next) { 665 for(cbs = cb_pref->callbacks; cbs; cbs = cbs->next) {
393 struct pref_cb *cb = cbs->data; 666 struct pref_cb *cb = cbs->data;
394 cb->func(name, pref->type, pref->value.generic, cb->data); 667 cb->func(name, pref->type, pref->value.generic, cb->data);
395 } 668 }
396 } 669 }
397 } 670 }
398 671
399 void gaim_prefs_trigger_callback(const char *name) { 672 void
673 gaim_prefs_trigger_callback(const char *name)
674 {
400 struct gaim_pref *pref = find_pref(name); 675 struct gaim_pref *pref = find_pref(name);
401 676
402 if(!pref) { 677 if(!pref) {
403 gaim_debug(GAIM_DEBUG_ERROR, "prefs", 678 gaim_debug_error("prefs",
404 "gaim_prefs_trigger_callback: Unknown pref %s\n", name); 679 "gaim_prefs_trigger_callback: Unknown pref %s\n", name);
405 return; 680 return;
406 } 681 }
407 682
408 do_callbacks(name, pref); 683 do_callbacks(name, pref);
409 } 684 }
410 685
411 void gaim_prefs_set_generic(const char *name, gpointer value) { 686 void
687 gaim_prefs_set_generic(const char *name, gpointer value)
688 {
412 struct gaim_pref *pref = find_pref(name); 689 struct gaim_pref *pref = find_pref(name);
413 690
414 if(!pref) { 691 if(!pref) {
415 gaim_debug(GAIM_DEBUG_ERROR, "prefs", 692 gaim_debug_error("prefs",
416 "gaim_prefs_set_generic: Unknown pref %s\n", name); 693 "gaim_prefs_set_generic: Unknown pref %s\n", name);
417 return; 694 return;
418 } 695 }
419 696
420 pref->value.generic = value; 697 pref->value.generic = value;
421 do_callbacks(name, pref); 698 do_callbacks(name, pref);
422 } 699 }
423 700
424 void gaim_prefs_set_bool(const char *name, gboolean value) { 701 void
702 gaim_prefs_set_bool(const char *name, gboolean value)
703 {
425 struct gaim_pref *pref = find_pref(name); 704 struct gaim_pref *pref = find_pref(name);
426 705
427 if(pref) { 706 if(pref) {
428 if(pref->type != GAIM_PREF_BOOLEAN) { 707 if(pref->type != GAIM_PREF_BOOLEAN) {
429 gaim_debug(GAIM_DEBUG_ERROR, "prefs", 708 gaim_debug_error("prefs",
430 "gaim_prefs_set_bool: %s not a boolean pref\n", name); 709 "gaim_prefs_set_bool: %s not a boolean pref\n", name);
431 return; 710 return;
432 } 711 }
433 712
434 if(pref->value.boolean != value) { 713 if(pref->value.boolean != value) {
438 } else { 717 } else {
439 gaim_prefs_add_bool(name, value); 718 gaim_prefs_add_bool(name, value);
440 } 719 }
441 } 720 }
442 721
443 void gaim_prefs_set_int(const char *name, int value) { 722 void
723 gaim_prefs_set_int(const char *name, int value)
724 {
444 struct gaim_pref *pref = find_pref(name); 725 struct gaim_pref *pref = find_pref(name);
445 726
446 if(pref) { 727 if(pref) {
447 if(pref->type != GAIM_PREF_INT) { 728 if(pref->type != GAIM_PREF_INT) {
448 gaim_debug(GAIM_DEBUG_ERROR, "prefs", 729 gaim_debug_error("prefs",
449 "gaim_prefs_set_int: %s not an integer pref\n", name); 730 "gaim_prefs_set_int: %s not an integer pref\n", name);
450 return; 731 return;
451 } 732 }
452 733
453 if(pref->value.integer != value) { 734 if(pref->value.integer != value) {
457 } else { 738 } else {
458 gaim_prefs_add_int(name, value); 739 gaim_prefs_add_int(name, value);
459 } 740 }
460 } 741 }
461 742
462 void gaim_prefs_set_string(const char *name, const char *value) { 743 void
744 gaim_prefs_set_string(const char *name, const char *value)
745 {
463 struct gaim_pref *pref = find_pref(name); 746 struct gaim_pref *pref = find_pref(name);
464 747
465 if(pref) { 748 if(pref) {
466 if(pref->type != GAIM_PREF_STRING) { 749 if(pref->type != GAIM_PREF_STRING) {
467 gaim_debug(GAIM_DEBUG_ERROR, "prefs", 750 gaim_debug_error("prefs",
468 "gaim_prefs_set_string: %s not a string pref\n", name); 751 "gaim_prefs_set_string: %s not a string pref\n", name);
469 return; 752 return;
470 } 753 }
471 754
472 if((value && !pref->value.string) || 755 if((value && !pref->value.string) ||
479 } else { 762 } else {
480 gaim_prefs_add_string(name, value); 763 gaim_prefs_add_string(name, value);
481 } 764 }
482 } 765 }
483 766
484 void gaim_prefs_set_string_list(const char *name, GList *value) { 767 void
768 gaim_prefs_set_string_list(const char *name, GList *value)
769 {
485 struct gaim_pref *pref = find_pref(name); 770 struct gaim_pref *pref = find_pref(name);
486 if(pref) { 771 if(pref) {
487 GList *tmp; 772 GList *tmp;
488 773
489 if(pref->type != GAIM_PREF_STRING_LIST) { 774 if(pref->type != GAIM_PREF_STRING_LIST) {
490 gaim_debug(GAIM_DEBUG_ERROR, "prefs", 775 gaim_debug_error("prefs",
491 "gaim_prefs_set_string_list: %s not a string list pref\n", 776 "gaim_prefs_set_string_list: %s not a string list pref\n",
492 name); 777 name);
493 return; 778 return;
494 } 779 }
495 780
508 } else { 793 } else {
509 gaim_prefs_add_string_list(name, value); 794 gaim_prefs_add_string_list(name, value);
510 } 795 }
511 } 796 }
512 797
513 gboolean gaim_prefs_exists(const char *name) { 798 gboolean
799 gaim_prefs_exists(const char *name)
800 {
514 struct gaim_pref *pref = find_pref(name); 801 struct gaim_pref *pref = find_pref(name);
515 802
516 if (pref != NULL) 803 if (pref != NULL)
517 return TRUE; 804 return TRUE;
518 805
519 return FALSE; 806 return FALSE;
520 } 807 }
521 808
522 GaimPrefType gaim_prefs_get_type(const char *name) { 809 GaimPrefType
810 gaim_prefs_get_type(const char *name)
811 {
523 struct gaim_pref *pref = find_pref(name); 812 struct gaim_pref *pref = find_pref(name);
524 813
525 if (pref == NULL) 814 if (pref == NULL)
526 return GAIM_PREF_NONE; 815 return GAIM_PREF_NONE;
527 816
528 return (pref->type); 817 return (pref->type);
529 } 818 }
530 819
531 gboolean gaim_prefs_get_bool(const char *name) { 820 gboolean
821 gaim_prefs_get_bool(const char *name)
822 {
532 struct gaim_pref *pref = find_pref(name); 823 struct gaim_pref *pref = find_pref(name);
533 824
534 if(!pref) { 825 if(!pref) {
535 gaim_debug(GAIM_DEBUG_ERROR, "prefs", 826 gaim_debug_error("prefs",
536 "gaim_prefs_get_bool: Unknown pref %s\n", name); 827 "gaim_prefs_get_bool: Unknown pref %s\n", name);
537 return FALSE; 828 return FALSE;
538 } else if(pref->type != GAIM_PREF_BOOLEAN) { 829 } else if(pref->type != GAIM_PREF_BOOLEAN) {
539 gaim_debug(GAIM_DEBUG_ERROR, "prefs", 830 gaim_debug_error("prefs",
540 "gaim_prefs_get_bool: %s not a boolean pref\n", name); 831 "gaim_prefs_get_bool: %s not a boolean pref\n", name);
541 return FALSE; 832 return FALSE;
542 } 833 }
543 834
544 return pref->value.boolean; 835 return pref->value.boolean;
545 } 836 }
546 837
547 int gaim_prefs_get_int(const char *name) { 838 int
839 gaim_prefs_get_int(const char *name)
840 {
548 struct gaim_pref *pref = find_pref(name); 841 struct gaim_pref *pref = find_pref(name);
549 842
550 if(!pref) { 843 if(!pref) {
551 gaim_debug(GAIM_DEBUG_ERROR, "prefs", 844 gaim_debug_error("prefs",
552 "gaim_prefs_get_int: Unknown pref %s\n", name); 845 "gaim_prefs_get_int: Unknown pref %s\n", name);
553 return 0; 846 return 0;
554 } else if(pref->type != GAIM_PREF_INT) { 847 } else if(pref->type != GAIM_PREF_INT) {
555 gaim_debug(GAIM_DEBUG_ERROR, "prefs", 848 gaim_debug_error("prefs",
556 "gaim_prefs_get_int: %s not an integer pref\n", name); 849 "gaim_prefs_get_int: %s not an integer pref\n", name);
557 return 0; 850 return 0;
558 } 851 }
559 852
560 return pref->value.integer; 853 return pref->value.integer;
561 } 854 }
562 855
563 const char *gaim_prefs_get_string(const char *name) { 856 const char *
857 gaim_prefs_get_string(const char *name)
858 {
564 struct gaim_pref *pref = find_pref(name); 859 struct gaim_pref *pref = find_pref(name);
565 860
566 if(!pref) { 861 if(!pref) {
567 gaim_debug(GAIM_DEBUG_ERROR, "prefs", 862 gaim_debug_error("prefs",
568 "gaim_prefs_get_string: Unknown pref %s\n", name); 863 "gaim_prefs_get_string: Unknown pref %s\n", name);
569 return NULL; 864 return NULL;
570 } else if(pref->type != GAIM_PREF_STRING) { 865 } else if(pref->type != GAIM_PREF_STRING) {
571 gaim_debug(GAIM_DEBUG_ERROR, "prefs", 866 gaim_debug_error("prefs",
572 "gaim_prefs_get_string: %s not a string pref\n", name); 867 "gaim_prefs_get_string: %s not a string pref\n", name);
573 return NULL; 868 return NULL;
574 } 869 }
575 870
576 return pref->value.string; 871 return pref->value.string;
577 } 872 }
578 873
579 GList *gaim_prefs_get_string_list(const char *name) { 874 GList *
875 gaim_prefs_get_string_list(const char *name)
876 {
580 struct gaim_pref *pref = find_pref(name); 877 struct gaim_pref *pref = find_pref(name);
581 GList *ret = NULL, *tmp; 878 GList *ret = NULL, *tmp;
582 879
583 if(!pref) { 880 if(!pref) {
584 gaim_debug(GAIM_DEBUG_ERROR, "prefs", 881 gaim_debug_error("prefs",
585 "gaim_prefs_get_string_list: Unknown pref %s\n", name); 882 "gaim_prefs_get_string_list: Unknown pref %s\n", name);
586 return NULL; 883 return NULL;
587 } else if(pref->type != GAIM_PREF_STRING_LIST) { 884 } else if(pref->type != GAIM_PREF_STRING_LIST) {
588 gaim_debug(GAIM_DEBUG_ERROR, "prefs", 885 gaim_debug_error("prefs",
589 "gaim_prefs_get_string_list: %s not a string list pref\n", name); 886 "gaim_prefs_get_string_list: %s not a string list pref\n", name);
590 return NULL; 887 return NULL;
591 } 888 }
592 889
593 for(tmp = pref->value.stringlist; tmp; tmp = tmp->next) 890 for(tmp = pref->value.stringlist; tmp; tmp = tmp->next)
594 ret = g_list_append(ret, g_strdup(tmp->data)); 891 ret = g_list_append(ret, g_strdup(tmp->data));
595 892
596 return ret; 893 return ret;
597 } 894 }
598 895
599 void gaim_prefs_rename(const char *oldname, const char *newname) { 896 void
897 gaim_prefs_rename(const char *oldname, const char *newname)
898 {
600 struct gaim_pref *oldpref, *newpref; 899 struct gaim_pref *oldpref, *newpref;
601 900
602 oldpref = find_pref(oldname); 901 oldpref = find_pref(oldname);
603 newpref = find_pref(newname); 902 newpref = find_pref(newname);
604 903
630 } 929 }
631 930
632 remove_pref(oldpref); 931 remove_pref(oldpref);
633 } 932 }
634 933
635 void gaim_prefs_rename_boolean_toggle(const char *oldname, const char *newname) { 934 void
935 gaim_prefs_rename_boolean_toggle(const char *oldname, const char *newname)
936 {
636 struct gaim_pref *oldpref, *newpref; 937 struct gaim_pref *oldpref, *newpref;
637 938
638 gaim_debug_info("prefs", "Attempting to rename and toggle %s to %s\n", oldname, newname); 939 gaim_debug_info("prefs", "Attempting to rename and toggle %s to %s\n", oldname, newname);
639 940
640 oldpref = find_pref(oldname); 941 oldpref = find_pref(oldname);
653 954
654 remove_pref(oldpref); 955 remove_pref(oldpref);
655 956
656 } 957 }
657 958
658 guint gaim_prefs_connect_callback(void *handle, const char *name, GaimPrefCallback func, gpointer data) 959 guint
960 gaim_prefs_connect_callback(void *handle, const char *name, GaimPrefCallback func, gpointer data)
659 { 961 {
660 struct gaim_pref *pref; 962 struct gaim_pref *pref;
661 struct pref_cb *cb; 963 struct pref_cb *cb;
662 static guint cb_id = 0; 964 static guint cb_id = 0;
663 965
675 pref->callbacks = g_slist_append(pref->callbacks, cb); 977 pref->callbacks = g_slist_append(pref->callbacks, cb);
676 978
677 return cb->id; 979 return cb->id;
678 } 980 }
679 981
680 static gboolean disco_callback_helper(struct gaim_pref *pref, guint callback_id) { 982 static gboolean
983 disco_callback_helper(struct gaim_pref *pref, guint callback_id)
984 {
681 GSList *cbs; 985 GSList *cbs;
682 struct gaim_pref *child; 986 struct gaim_pref *child;
683 987
684 if(!pref) 988 if(!pref)
685 return FALSE; 989 return FALSE;
699 } 1003 }
700 1004
701 return FALSE; 1005 return FALSE;
702 } 1006 }
703 1007
704 void gaim_prefs_disconnect_callback(guint callback_id) { 1008 void
1009 gaim_prefs_disconnect_callback(guint callback_id)
1010 {
705 disco_callback_helper(&prefs, callback_id); 1011 disco_callback_helper(&prefs, callback_id);
706 } 1012 }
707 1013
708 static void disco_callback_helper_handle(struct gaim_pref *pref, void *handle) { 1014 static void
1015 disco_callback_helper_handle(struct gaim_pref *pref, void *handle)
1016 {
709 GSList *cbs; 1017 GSList *cbs;
710 struct gaim_pref *child; 1018 struct gaim_pref *child;
711 1019
712 if(!pref) 1020 if(!pref)
713 return; 1021 return;
725 1033
726 for(child = pref->first_child; child; child = child->sibling) 1034 for(child = pref->first_child; child; child = child->sibling)
727 disco_callback_helper_handle(child, handle); 1035 disco_callback_helper_handle(child, handle);
728 } 1036 }
729 1037
730 void gaim_prefs_disconnect_by_handle(void *handle) { 1038 void
1039 gaim_prefs_disconnect_by_handle(void *handle)
1040 {
731 g_return_if_fail(handle != NULL); 1041 g_return_if_fail(handle != NULL);
1042
732 disco_callback_helper_handle(&prefs, handle); 1043 disco_callback_helper_handle(&prefs, handle);
733 } 1044 }
734 1045
735 static void gaim_prefs_write(FILE *f, struct gaim_pref *pref, int depth) { 1046 void
736 struct gaim_pref *tmp; 1047 gaim_prefs_update_old()
737 char *esc; 1048 {
738 int i;
739
740 if(!pref) {
741 pref = &prefs;
742
743 fprintf(f, "<?xml version='1.0' encoding='UTF-8' ?>\n\n");
744 fprintf(f, "<pref version='1.0' name='/'");
745 } else {
746 for(i=0; i<depth; i++)
747 fprintf(f, "\t");
748 esc = g_markup_escape_text(pref->name, -1);
749 fprintf(f, "<pref name='%s'", esc);
750 g_free(esc);
751 }
752
753 switch(pref->type) {
754 case GAIM_PREF_NONE:
755 break;
756 case GAIM_PREF_BOOLEAN:
757 fprintf(f, " type='bool' value='%d'", pref->value.boolean);
758 break;
759 case GAIM_PREF_INT:
760 fprintf(f, " type='int' value='%d'", pref->value.integer);
761 break;
762 case GAIM_PREF_STRING:
763 esc = g_markup_escape_text(pref->value.string, -1);
764 fprintf(f, " type='string' value='%s'", esc);
765 g_free(esc);
766 break;
767 case GAIM_PREF_STRING_LIST:
768 fprintf(f, " type='stringlist'");
769 break;
770 }
771
772 if(pref->first_child || pref->type == GAIM_PREF_STRING_LIST) {
773 fprintf(f, ">\n");
774
775 for(tmp = pref->first_child; tmp; tmp = tmp->sibling)
776 gaim_prefs_write(f, tmp, depth+1);
777
778 if(pref->type == GAIM_PREF_STRING_LIST) {
779 GList *tmp2;
780 for(tmp2 = pref->value.stringlist; tmp2; tmp2 = tmp2->next) {
781 for(i=0; i<depth+1; i++)
782 fprintf(f, "\t");
783 esc = g_markup_escape_text(tmp2->data, -1);
784 fprintf(f, "<item value='%s' />\n", esc);
785 g_free(esc);
786 }
787 }
788
789 for(i=0; i<depth; i++)
790 fprintf(f, "\t");
791 fprintf(f, "</pref>\n");
792 } else {
793 fprintf(f, " />\n");
794 }
795 }
796
797 void gaim_prefs_sync() {
798 FILE *file;
799 struct stat st;
800 const char *user_dir = gaim_user_dir();
801 char *filename;
802 char *filename_real;
803
804 if(!prefs_is_loaded) {
805 gaim_debug(GAIM_DEBUG_WARNING, "prefs", "prefs saved before loading! scheduling save.\n");
806 schedule_prefs_save(); /* schedule a save for after we read in */
807 return;
808 }
809
810 if(!user_dir)
811 return;
812
813 gaim_debug(GAIM_DEBUG_INFO, "prefs", "writing prefs out to disk.\n");
814
815 file = fopen(user_dir, "r");
816 if(!file)
817 mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR);
818 else
819 fclose(file);
820
821 filename = g_build_filename(user_dir, "prefs.xml.save", NULL);
822
823 if((file = fopen(filename, "w"))) {
824 gaim_prefs_write(file, NULL, 0);
825 fclose(file);
826 chmod(filename, S_IRUSR | S_IWUSR);
827 } else {
828 gaim_debug(GAIM_DEBUG_ERROR, "prefs", "Unable to write %s\n",
829 filename);
830 g_free(filename);
831 return;
832 }
833
834 if (stat(filename, &st) || (st.st_size == 0)) {
835 gaim_debug_error("prefs", "Failed to save prefs\n");
836 unlink(filename);
837 g_free(filename);
838 return;
839 }
840
841 filename_real = g_build_filename(user_dir, "prefs.xml", NULL);
842 if(rename(filename, filename_real) < 0)
843 gaim_debug(GAIM_DEBUG_ERROR, "prefs", "Error renaming %s to %s\n",
844 filename, filename_real);
845
846 g_free(filename);
847 g_free(filename_real);
848 }
849
850 static GList *prefs_stack = NULL;
851
852 static void prefs_start_element_handler (GMarkupParseContext *context,
853 const gchar *element_name,
854 const gchar **attribute_names,
855 const gchar **attribute_values,
856 gpointer user_data,
857 GError **error) {
858 GaimPrefType pref_type = GAIM_PREF_NONE;
859 int i;
860 const char *pref_name = NULL, *pref_value = NULL;
861 GString *pref_name_full;
862 GList *tmp;
863
864 if(strcmp(element_name, "pref") && strcmp(element_name, "item"))
865 return;
866
867 for(i = 0; attribute_names[i]; i++) {
868 if(!strcmp(attribute_names[i], "name")) {
869 pref_name = attribute_values[i];
870 } else if(!strcmp(attribute_names[i], "type")) {
871 if(!strcmp(attribute_values[i], "bool"))
872 pref_type = GAIM_PREF_BOOLEAN;
873 else if(!strcmp(attribute_values[i], "int"))
874 pref_type = GAIM_PREF_INT;
875 else if(!strcmp(attribute_values[i], "string"))
876 pref_type = GAIM_PREF_STRING;
877 else if(!strcmp(attribute_values[i], "stringlist"))
878 pref_type = GAIM_PREF_STRING_LIST;
879 else
880 return;
881 } else if(!strcmp(attribute_names[i], "value")) {
882 pref_value = attribute_values[i];
883 }
884 }
885
886 if(!strcmp(element_name, "item")) {
887 struct gaim_pref *pref;
888
889 pref_name_full = g_string_new("");
890
891 for(tmp = prefs_stack; tmp; tmp = tmp->next) {
892 pref_name_full = g_string_prepend(pref_name_full, tmp->data);
893 pref_name_full = g_string_prepend_c(pref_name_full, '/');
894 }
895
896 pref = find_pref(pref_name_full->str);
897
898 if(pref) {
899 pref->value.stringlist = g_list_append(pref->value.stringlist,
900 g_strdup(pref_value));
901 }
902 } else {
903 if(!pref_name || !strcmp(pref_name, "/"))
904 return;
905
906 pref_name_full = g_string_new(pref_name);
907
908 for(tmp = prefs_stack; tmp; tmp = tmp->next) {
909 pref_name_full = g_string_prepend_c(pref_name_full, '/');
910 pref_name_full = g_string_prepend(pref_name_full, tmp->data);
911 }
912
913 pref_name_full = g_string_prepend_c(pref_name_full, '/');
914
915 switch(pref_type) {
916 case GAIM_PREF_NONE:
917 gaim_prefs_add_none(pref_name_full->str);
918 break;
919 case GAIM_PREF_BOOLEAN:
920 gaim_prefs_set_bool(pref_name_full->str, atoi(pref_value));
921 break;
922 case GAIM_PREF_INT:
923 gaim_prefs_set_int(pref_name_full->str, atoi(pref_value));
924 break;
925 case GAIM_PREF_STRING:
926 gaim_prefs_set_string(pref_name_full->str, pref_value);
927 break;
928 case GAIM_PREF_STRING_LIST:
929 gaim_prefs_set_string_list(pref_name_full->str, NULL);
930 break;
931 }
932 prefs_stack = g_list_prepend(prefs_stack, g_strdup(pref_name));
933 g_string_free(pref_name_full, TRUE);
934 }
935 }
936
937 static void prefs_end_element_handler(GMarkupParseContext *context,
938 const gchar *element_name, gpointer user_data, GError **error) {
939 if(prefs_stack && !strcmp(element_name, "pref")) {
940 g_free(prefs_stack->data);
941 prefs_stack = g_list_delete_link(prefs_stack, prefs_stack);
942 }
943 }
944
945 static GMarkupParser prefs_parser = {
946 prefs_start_element_handler,
947 prefs_end_element_handler,
948 NULL,
949 NULL,
950 NULL
951 };
952
953 gboolean gaim_prefs_load() {
954 gchar *filename = g_build_filename(gaim_user_dir(), "prefs.xml", NULL);
955 gchar *contents = NULL;
956 gsize length;
957 GMarkupParseContext *context;
958 GError *error = NULL;
959
960 if (!filename) {
961 prefs_is_loaded = TRUE;
962 return FALSE;
963 }
964
965 gaim_debug(GAIM_DEBUG_INFO, "prefs", "Reading %s\n", filename);
966
967 if(!g_file_get_contents(filename, &contents, &length, &error)) {
968 #ifndef _WIN32
969 g_free(filename);
970 g_error_free(error);
971
972 error = NULL;
973
974 filename = g_build_filename(SYSCONFDIR, "gaim", "prefs.xml", NULL);
975
976 gaim_debug(GAIM_DEBUG_INFO, "prefs", "Reading %s\n", filename);
977
978 if (!g_file_get_contents(filename, &contents, &length, &error)) {
979 gaim_debug(GAIM_DEBUG_ERROR, "prefs", "Error reading prefs: %s\n",
980 error->message);
981 g_error_free(error);
982 g_free(filename);
983 prefs_is_loaded = TRUE;
984
985 return FALSE;
986 }
987 #else /* _WIN32 */
988 gaim_debug(GAIM_DEBUG_ERROR, "prefs", "Error reading prefs: %s\n",
989 error->message);
990 g_error_free(error);
991 g_free(filename);
992 prefs_is_loaded = TRUE;
993
994 return FALSE;
995 #endif /* _WIN32 */
996 }
997
998 context = g_markup_parse_context_new(&prefs_parser, 0, NULL, NULL);
999
1000 if(!g_markup_parse_context_parse(context, contents, length, NULL)) {
1001 g_markup_parse_context_free(context);
1002 g_free(contents);
1003 g_free(filename);
1004 prefs_is_loaded = TRUE;
1005
1006 return FALSE;
1007 }
1008
1009 if(!g_markup_parse_context_end_parse(context, NULL)) {
1010 gaim_debug(GAIM_DEBUG_ERROR, "prefs", "Error parsing %s\n", filename);
1011 g_markup_parse_context_free(context);
1012 g_free(contents);
1013 g_free(filename);
1014 prefs_is_loaded = TRUE;
1015
1016 return FALSE;
1017 }
1018
1019 gaim_debug(GAIM_DEBUG_INFO, "prefs", "Finished reading %s\n", filename);
1020 g_markup_parse_context_free(context);
1021 g_free(contents);
1022 g_free(filename);
1023 prefs_is_loaded = TRUE;
1024
1025 return TRUE;
1026 }
1027
1028 void gaim_prefs_update_old() {
1029 /* Remove some no-longer-used prefs */ 1049 /* Remove some no-longer-used prefs */
1030 gaim_prefs_remove("/core/away/auto_response/enabled"); 1050 gaim_prefs_remove("/core/away/auto_response/enabled");
1031 gaim_prefs_remove("/core/away/auto_response/idle_only"); 1051 gaim_prefs_remove("/core/away/auto_response/idle_only");
1032 gaim_prefs_remove("/core/away/auto_response/in_active_conv"); 1052 gaim_prefs_remove("/core/away/auto_response/in_active_conv");
1033 gaim_prefs_remove("/core/away/auto_response/sec_before_resend"); 1053 gaim_prefs_remove("/core/away/auto_response/sec_before_resend");
1039 gaim_prefs_remove("/core/conversations/chat/show_join"); 1059 gaim_prefs_remove("/core/conversations/chat/show_join");
1040 gaim_prefs_remove("/core/conversations/chat/show_leave"); 1060 gaim_prefs_remove("/core/conversations/chat/show_leave");
1041 gaim_prefs_remove("/core/conversations/combine_chat_im"); 1061 gaim_prefs_remove("/core/conversations/combine_chat_im");
1042 gaim_prefs_remove("/core/conversations/use_alias_for_title"); 1062 gaim_prefs_remove("/core/conversations/use_alias_for_title");
1043 } 1063 }
1064
1065 void *
1066 gaim_prefs_get_handle(void)
1067 {
1068 static int handle;
1069
1070 return &handle;
1071 }
1072
1073 void
1074 gaim_prefs_init(void)
1075 {
1076 void *handle = gaim_prefs_get_handle();
1077
1078 prefs_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
1079
1080 gaim_prefs_connect_callback(handle, "/", prefs_save_cb, NULL);
1081
1082 gaim_prefs_add_none("/core");
1083 gaim_prefs_add_none("/plugins");
1084 gaim_prefs_add_none("/plugins/core");
1085 gaim_prefs_add_none("/plugins/lopl");
1086 gaim_prefs_add_none("/plugins/prpl");
1087
1088 /* Away */
1089 gaim_prefs_add_none("/core/away");
1090 gaim_prefs_add_bool("/core/away/away_when_idle", TRUE);
1091 gaim_prefs_add_int("/core/away/mins_before_away", 5);
1092 /* XXX: internationalized string in prefs...evil */
1093 gaim_prefs_add_string("/core/away/default_message",
1094 _("Slightly less boring default"));
1095
1096 /* Away -> Auto-Reply */
1097 if (!gaim_prefs_exists("/core/away/auto_response/enabled") ||
1098 !gaim_prefs_exists("/core/away/auto_response/idle_only")) {
1099 gaim_prefs_add_string("/core/away/auto_reply", "awayidle");
1100 } else {
1101 if (!gaim_prefs_get_bool("/core/away/auto_response/enabled")) {
1102 gaim_prefs_add_string("/core/away/auto_reply", "never");
1103 } else {
1104 if (gaim_prefs_get_bool("/core/away/auto_response/idle_only")) {
1105 gaim_prefs_add_string("/core/away/auto_reply", "awayidle");
1106 } else {
1107 gaim_prefs_add_string("/core/away/auto_reply", "away");
1108 }
1109 }
1110 }
1111
1112 /* Buddies */
1113 gaim_prefs_add_none("/core/buddies");
1114
1115 /* Contact Priority Settings */
1116 gaim_prefs_add_none("/core/contact");
1117 gaim_prefs_add_bool("/core/contact/last_match", FALSE);
1118 gaim_prefs_add_int("/core/contact/offline_score", 4);
1119 gaim_prefs_add_int("/core/contact/away_score", 2);
1120 gaim_prefs_add_int("/core/contact/idle_score", 1);
1121 }
1122
1123 void
1124 gaim_prefs_uninit()
1125 {
1126 if (save_timer != 0)
1127 {
1128 gaim_timeout_remove(save_timer);
1129 save_timer = 0;
1130 sync_prefs();
1131 }
1132
1133 gaim_prefs_disconnect_by_handle(gaim_prefs_get_handle());
1134 }