2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2009 Hiroyuki Yamamoto and the Claws Mail team
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 3 of the License, or
8 * (at your option) any later version.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include <glib/gi18n.h>
38 #include "prefs_gtk.h"
39 #include "prefs_common.h"
42 #include "passcrypt.h"
46 #define CL(x) (((gulong) (x) >> (gulong) 8) & 0xFFUL)
47 #define RGB_FROM_GDK_COLOR(c) \
48 ((CL(c.red) << (gulong) 16) | \
49 (CL(c.green) << (gulong) 8) | \
52 #ifdef HAVE_FGETS_UNLOCKED
53 #define SC_FGETS fgets_unlocked
55 #define SC_FGETS fgets
63 static GHashTable *whole_cache = NULL;
65 static gboolean prefs_read_config_from_cache(PrefParam *param, const gchar *label,
68 static void prefs_config_parse_one_line(PrefParam *param,
71 void prefs_read_config(PrefParam *param, const gchar *label,
72 const gchar *rcfile, const gchar *encoding)
75 gchar buf[PREFSBUFSIZE];
78 cm_return_if_fail(param != NULL);
79 cm_return_if_fail(label != NULL);
80 cm_return_if_fail(rcfile != NULL);
83 g_warning("Encoding is ignored\n");
85 debug_print("Reading configuration...\n");
87 prefs_set_default(param);
89 if (whole_cache != NULL) {
90 if (prefs_read_config_from_cache(param, label, rcfile) == TRUE)
94 if ((fp = g_fopen(rcfile, "rb")) == NULL) {
95 if (ENOENT != errno) FILE_OP_ERROR(rcfile, "fopen");
99 block_label = g_strdup_printf("[%s]", label);
101 #ifdef HAVE_FGETS_UNLOCKED
105 /* search aiming block */
106 while (SC_FGETS(buf, sizeof(buf), fp) != NULL) {
112 conv_str = conv_codeset_strdup
113 (buf, encoding, CS_INTERNAL);
115 conv_str = g_strdup(buf);
117 (conv_str, block_label, strlen(block_label));
120 val = strncmp(buf, block_label, strlen(block_label));
122 debug_print("Found %s\n", block_label);
128 while (SC_FGETS(buf, sizeof(buf), fp) != NULL) {
130 /* reached next block */
131 if (buf[0] == '[') break;
132 if (buf[0] == '#') continue;
137 conv_str = conv_codeset_strdup
138 (buf, encoding, CS_INTERNAL);
140 conv_str = g_strdup(buf);
141 prefs_config_parse_one_line(param, conv_str);
144 prefs_config_parse_one_line(param, buf);
147 debug_print("Finished reading configuration.\n");
148 #ifdef HAVE_FGETS_UNLOCKED
154 static void prefs_config_parse_one_line(PrefParam *param, const gchar *buf)
161 for (i = 0; param[i].name != NULL; i++) {
162 name_len = strlen(param[i].name);
163 if (g_ascii_strncasecmp(buf, param[i].name, name_len))
165 if (buf[name_len] != '=')
167 value = buf + name_len + 1;
168 /* debug_print("%s = %s\n", param[i].name, value); */
170 switch (param[i].type) {
176 if (g_utf8_validate(value, -1, NULL))
177 tmp = g_strdup(value);
179 tmp = conv_codeset_strdup(value,
180 conv_get_locale_charset_str_no_utf8(),
187 g_warning("Failed to convert character set.");
188 tmp = g_strdup(value);
190 g_free(*((gchar **)param[i].data));
191 *((gchar **)param[i].data) = tmp;
195 *((gint *)param[i].data) =
199 *((gboolean *)param[i].data) =
200 (*value == '0' || *value == '\0')
204 *((DummyEnum *)param[i].data) =
205 (DummyEnum)atoi(value);
208 *((gushort *)param[i].data) =
209 (gushort)atoi(value);
212 if (gdk_color_parse(value, &color)) {
213 *((gulong *)param[i].data) = RGB_FROM_GDK_COLOR(color);
216 /* be compatible and accept ints */
217 *((gulong *)param[i].data) = strtoul(value, 0, 10);
220 g_free(*((gchar **)param[i].data));
221 if (value[0] == '!') {
225 len = base64_decode(tmp, &value[1], strlen(value) - 1);
226 passcrypt_decrypt(tmp, len);
228 *((gchar **)param[i].data) =
229 *tmp ? g_strdup(tmp) : NULL;
231 *((gchar **)param[i].data) =
232 *value ? g_strdup(value) : NULL;
244 g_warning("Failed to write configuration to file\n"); \
245 if (orig_fp) fclose(orig_fp); \
246 prefs_file_close_revert(pfile); \
248 g_free(block_label); \
252 void prefs_write_config(PrefParam *param, const gchar *label,
258 gchar buf[PREFSBUFSIZE];
259 gchar *block_label = NULL;
260 gboolean block_matched = FALSE;
262 cm_return_if_fail(param != NULL);
263 cm_return_if_fail(label != NULL);
264 cm_return_if_fail(rcfile != NULL);
266 rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, rcfile, NULL);
267 if ((orig_fp = g_fopen(rcpath, "rb")) == NULL) {
268 if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
271 if ((pfile = prefs_write_open(rcpath)) == NULL) {
272 g_warning("Failed to write configuration to file\n");
273 if (orig_fp) fclose(orig_fp);
278 block_label = g_strdup_printf("[%s]", label);
280 /* search aiming block */
282 while (fgets(buf, sizeof(buf), orig_fp) != NULL) {
285 val = strncmp(buf, block_label, strlen(block_label));
287 debug_print("Found %s\n", block_label);
288 block_matched = TRUE;
291 TRY(fputs(buf, pfile->fp) != EOF);
295 TRY(fprintf(pfile->fp, "%s\n", block_label) > 0);
297 /* write all param data to file */
298 TRY(prefs_write_param(param, pfile->fp) == 0);
301 gboolean in_dup_block = FALSE;
302 while (fgets(buf, sizeof(buf), orig_fp) != NULL) {
305 TRY(fputc('\n', pfile->fp) != EOF &&
306 fputs(buf, pfile->fp) != EOF);
310 while (fgets(buf, sizeof(buf), orig_fp) != NULL) {
312 if (!strncmp(buf, block_label,
313 strlen(block_label)))
316 in_dup_block = FALSE;
319 TRY(fputs(buf, pfile->fp) != EOF);
326 if (orig_fp) fclose(orig_fp);
327 if (prefs_file_close(pfile) < 0)
328 g_warning("Failed to write configuration to file\n");
331 debug_print("Configuration is saved.\n");
334 gint prefs_write_param(PrefParam *param, FILE *fp)
337 gchar buf[PREFSBUFSIZE];
339 for (i = 0; param[i].name != NULL; i++) {
340 switch (param[i].type) {
345 if (*((gchar **)param[i].data)) {
346 if (g_utf8_validate(*((gchar **)param[i].data), -1, NULL))
347 tmp = g_strdup(*((gchar **)param[i].data));
349 tmp = conv_codeset_strdup(*((gchar **)param[i].data),
350 conv_get_locale_charset_str_no_utf8(),
353 tmp = g_strdup(*((gchar **)param[i].data));
357 g_snprintf(buf, sizeof(buf), "%s=%s\n", param[i].name,
364 g_snprintf(buf, sizeof(buf), "%s=%d\n", param[i].name,
365 *((gint *)param[i].data));
368 g_snprintf(buf, sizeof(buf), "%s=%d\n", param[i].name,
369 *((gboolean *)param[i].data));
372 g_snprintf(buf, sizeof(buf), "%s=%d\n", param[i].name,
373 *((DummyEnum *)param[i].data));
376 g_snprintf(buf, sizeof(buf), "%s=%d\n", param[i].name,
377 *((gushort *)param[i].data));
380 g_snprintf(buf, sizeof buf, "%s=#%6.6lx\n", param[i].name,
381 *((gulong *) param[i].data));
385 gchar *tmp = NULL, tmp2[1024] = {0};
387 tmp = *((gchar **)param[i].data);
393 passcrypt_encrypt(tmp, len);
394 base64_encode(tmp2, tmp, len);
398 g_snprintf(buf, sizeof(buf), "%s=!%s\n", param[i].name,
404 /* unrecognized, fail */
405 debug_print("Unrecognized parameter type\n");
409 if (buf[0] != '\0') {
410 if (fputs(buf, fp) == EOF) {
420 void prefs_set_default(PrefParam *param)
425 cm_return_if_fail(param != NULL);
427 for (i = 0; param[i].name != NULL; i++) {
428 if (!param[i].data) continue;
430 switch (param[i].type) {
432 g_free(*((gchar **)param[i].data));
433 if (param[i].defval != NULL) {
434 if (!strncasecmp(param[i].defval, "ENV_", 4)) {
438 envstr = g_getenv(param[i].defval + 4);
439 tmp = envstr && *envstr ?
440 conv_codeset_strdup(envstr,
441 conv_get_locale_charset_str(),
445 g_warning("Failed to convert character set.");
446 tmp = g_strdup(envstr);
448 *((gchar **)param[i].data) = tmp;
449 } else if (param[i].defval[0] == '~')
450 *((gchar **)param[i].data) =
451 g_strconcat(get_home_dir(),
454 else if (param[i].defval[0] != '\0')
455 *((gchar **)param[i].data) =
456 g_strdup(param[i].defval);
458 *((gchar **)param[i].data) = NULL;
460 *((gchar **)param[i].data) = NULL;
463 g_free(*((gchar **)param[i].data));
464 if (param[i].defval != NULL) {
465 if (param[i].defval[0] != '\0')
466 *((gchar **)param[i].data) =
467 g_strdup(param[i].defval);
469 *((gchar **)param[i].data) = NULL;
471 *((gchar **)param[i].data) = NULL;
474 if (param[i].defval != NULL)
475 *((gint *)param[i].data) =
476 (gint)atoi(param[i].defval);
478 *((gint *)param[i].data) = 0;
481 if (param[i].defval != NULL) {
482 if (!g_ascii_strcasecmp(param[i].defval, "TRUE"))
483 *((gboolean *)param[i].data) = TRUE;
485 *((gboolean *)param[i].data) =
486 atoi(param[i].defval) ? TRUE : FALSE;
488 *((gboolean *)param[i].data) = FALSE;
491 if (param[i].defval != NULL)
492 *((DummyEnum*)param[i].data) =
493 (DummyEnum)atoi(param[i].defval);
495 *((DummyEnum *)param[i].data) = 0;
498 if (param[i].defval != NULL)
499 *((gushort *)param[i].data) =
500 (gushort)atoi(param[i].defval);
502 *((gushort *)param[i].data) = 0;
505 if (param[i].defval != NULL && gdk_color_parse(param[i].defval, &color))
506 *((gulong *)param[i].data) =
507 RGB_FROM_GDK_COLOR(color);
508 else if (param[i].defval)
509 /* be compatible and accept ints */
510 *((gulong *)param[i].data) = strtoul(param[i].defval, 0, 10);
512 *((gulong *)param[i].data) = 0;
520 void prefs_free(PrefParam *param)
524 cm_return_if_fail(param != NULL);
526 for (i = 0; param[i].name != NULL; i++) {
527 if (!param[i].data) continue;
529 switch (param[i].type) {
532 g_free(*((gchar **)param[i].data));
540 void prefs_button_toggled(GtkToggleButton *toggle_btn, GtkWidget *widget)
544 is_active = gtk_toggle_button_get_active(toggle_btn);
545 gtk_widget_set_sensitive(widget, is_active);
548 void prefs_button_toggled_reverse(GtkToggleButton *toggle_btn, GtkWidget *widget)
552 is_active = gtk_toggle_button_get_active(toggle_btn);
553 gtk_widget_set_sensitive(widget, !is_active);
556 void prefs_set_dialog(PrefParam *param)
560 for (i = 0; param[i].name != NULL; i++) {
561 if (param[i].widget_set_func)
562 param[i].widget_set_func(¶m[i]);
566 void prefs_set_data_from_dialog(PrefParam *param)
570 for (i = 0; param[i].name != NULL; i++) {
571 if (param[i].data_set_func)
572 param[i].data_set_func(¶m[i]);
576 void prefs_set_dialog_to_default(PrefParam *param)
580 gchar *str_data = NULL;
586 for (i = 0; param[i].name != NULL; i++) {
587 if (!param[i].widget_set_func) continue;
591 switch (tmpparam.type) {
593 if (tmpparam.defval) {
594 if (!g_ascii_strncasecmp(tmpparam.defval, "ENV_", 4)) {
595 str_data = g_strdup(g_getenv(param[i].defval + 4));
596 tmpparam.data = &str_data;
598 } else if (tmpparam.defval[0] == '~') {
600 g_strconcat(get_home_dir(),
603 tmpparam.data = &str_data;
607 tmpparam.data = &tmpparam.defval;
610 tmpparam.data = &tmpparam.defval;
614 int_data = atoi(tmpparam.defval);
617 tmpparam.data = &int_data;
621 ushort_data = atoi(tmpparam.defval);
624 tmpparam.data = &ushort_data;
627 if (tmpparam.defval) {
628 if (!g_ascii_strcasecmp(tmpparam.defval, "TRUE"))
631 bool_data = atoi(tmpparam.defval)
635 tmpparam.data = &bool_data;
639 enum_data = (DummyEnum)atoi(tmpparam.defval);
642 tmpparam.data = &enum_data;
648 tmpparam.widget_set_func(&tmpparam);
654 void prefs_set_data_from_entry(PrefParam *pparam)
657 const gchar *entry_str;
659 cm_return_if_fail(*pparam->widget != NULL);
661 entry_str = gtk_entry_get_text(GTK_ENTRY(*pparam->widget));
663 switch (pparam->type) {
666 str = (gchar **)pparam->data;
668 *str = entry_str[0] ? g_strdup(entry_str) : NULL;
671 *((gushort *)pparam->data) = atoi(entry_str);
674 *((gint *)pparam->data) = atoi(entry_str);
677 g_warning("Invalid PrefType for GtkEntry widget: %d\n",
682 void prefs_set_escaped_data_from_entry(PrefParam *pparam)
686 cm_return_if_fail(*pparam->widget != NULL);
688 switch (pparam->type) {
690 str = (gchar **)pparam->data;
692 *str = pref_get_pref_from_entry(GTK_ENTRY(*pparam->widget));
695 g_warning("Invalid escaped PrefType for GtkEntry widget: %d\n",
700 void prefs_set_entry(PrefParam *pparam)
704 cm_return_if_fail(*pparam->widget != NULL);
706 switch (pparam->type) {
709 str = (gchar **)pparam->data;
710 gtk_entry_set_text(GTK_ENTRY(*pparam->widget),
714 gtk_entry_set_text(GTK_ENTRY(*pparam->widget),
715 itos(*((gint *)pparam->data)));
718 gtk_entry_set_text(GTK_ENTRY(*pparam->widget),
719 itos(*((gushort *)pparam->data)));
722 g_warning("Invalid PrefType for GtkEntry widget: %d\n",
727 void prefs_set_entry_from_escaped(PrefParam *pparam)
731 cm_return_if_fail(*pparam->widget != NULL);
733 switch (pparam->type) {
735 str = (gchar **)pparam->data;
736 pref_set_entry_from_pref(GTK_ENTRY(*pparam->widget),
740 g_warning("Invalid escaped PrefType for GtkEntry widget: %d\n",
745 void prefs_set_data_from_text(PrefParam *pparam)
748 gchar *text = NULL, *tp = NULL;
751 cm_return_if_fail(*pparam->widget != NULL);
753 switch (pparam->type) {
756 str = (gchar **)pparam->data;
758 if (GTK_IS_EDITABLE(*pparam->widget)) { /* need? */
759 tp = text = gtk_editable_get_chars
760 (GTK_EDITABLE(*pparam->widget), 0, -1);
761 } else if (GTK_IS_TEXT_VIEW(*pparam->widget)) {
762 GtkTextView *textview = GTK_TEXT_VIEW(*pparam->widget);
763 GtkTextBuffer *buffer = gtk_text_view_get_buffer(textview);
764 GtkTextIter start, end;
765 gtk_text_buffer_get_start_iter(buffer, &start);
766 gtk_text_buffer_get_iter_at_offset(buffer, &end, -1);
767 tp = text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
770 cm_return_if_fail (tp && text);
772 if (text[0] == '\0') {
778 Xalloca(tmpp = tmp, strlen(text) * 2 + 1,
779 { *str = NULL; break; });
789 *str = g_strdup(tmp);
793 g_warning("Invalid PrefType for GtkText widget: %d\n",
798 void prefs_set_escaped_data_from_text(PrefParam *pparam)
802 cm_return_if_fail(*pparam->widget != NULL);
804 switch (pparam->type) {
806 str = (gchar **)pparam->data;
808 *str = pref_get_pref_from_textview(GTK_TEXT_VIEW(*pparam->widget));
811 g_warning("Invalid escaped PrefType for GtkText widget: %d\n",
816 void prefs_set_text(PrefParam *pparam)
818 gchar *buf, *sp, *bufp;
821 GtkTextBuffer *buffer;
824 cm_return_if_fail(*pparam->widget != NULL);
826 switch (pparam->type) {
829 str = (gchar **)pparam->data;
831 bufp = buf = alloca(strlen(*str) + 1);
836 if (*sp == '\\' && *(sp + 1) == 'n') {
847 text = GTK_TEXT_VIEW(*pparam->widget);
848 buffer = gtk_text_view_get_buffer(text);
849 gtk_text_buffer_set_text(buffer, "", -1);
850 gtk_text_buffer_get_start_iter(buffer, &iter);
851 gtk_text_buffer_insert(buffer, &iter, buf, -1);
854 g_warning("Invalid PrefType for GtkTextView widget: %d\n",
859 void prefs_set_text_from_escaped(PrefParam *pparam)
863 cm_return_if_fail(*pparam->widget != NULL);
865 switch (pparam->type) {
867 str = (gchar **)pparam->data;
868 pref_set_textview_from_pref(GTK_TEXT_VIEW(*pparam->widget),
872 g_warning("Invalid escaped PrefType for GtkTextView widget: %d\n",
877 void prefs_set_data_from_toggle(PrefParam *pparam)
879 cm_return_if_fail(pparam->type == P_BOOL);
880 cm_return_if_fail(*pparam->widget != NULL);
882 *((gboolean *)pparam->data) =
883 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(*pparam->widget));
886 void prefs_set_toggle(PrefParam *pparam)
888 cm_return_if_fail(pparam->type == P_BOOL);
889 cm_return_if_fail(*pparam->widget != NULL);
891 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(*pparam->widget),
892 *((gboolean *)pparam->data));
895 void prefs_set_data_from_spinbtn(PrefParam *pparam)
897 cm_return_if_fail(*pparam->widget != NULL);
899 switch (pparam->type) {
901 *((gint *)pparam->data) =
902 gtk_spin_button_get_value_as_int
903 (GTK_SPIN_BUTTON(*pparam->widget));
906 *((gushort *)pparam->data) =
907 (gushort)gtk_spin_button_get_value_as_int
908 (GTK_SPIN_BUTTON(*pparam->widget));
911 g_warning("Invalid PrefType for GtkSpinButton widget: %d\n",
916 void prefs_set_spinbtn(PrefParam *pparam)
918 cm_return_if_fail(*pparam->widget != NULL);
920 switch (pparam->type) {
922 gtk_spin_button_set_value(GTK_SPIN_BUTTON(*pparam->widget),
923 (gfloat)*((gint *)pparam->data));
926 gtk_spin_button_set_value(GTK_SPIN_BUTTON(*pparam->widget),
927 (gfloat)*((gushort *)pparam->data));
930 g_warning("Invalid PrefType for GtkSpinButton widget: %d\n",
935 static GSList *prefs_pages = NULL;
937 void prefs_gtk_open(void)
939 prefswindow_open(_("Preferences"), prefs_pages, NULL,
940 &prefs_common.prefswin_width, &prefs_common.prefswin_height,
944 void prefs_gtk_register_page(PrefsPage *page)
946 prefs_pages = g_slist_append(prefs_pages, page);
949 void prefs_gtk_unregister_page(PrefsPage *page)
951 prefs_pages = g_slist_remove(prefs_pages, page);
954 static void prefs_destroy_whole_cache(gpointer to_free)
956 GHashTable *table = (GHashTable *)to_free;
957 g_hash_table_destroy(table);
960 static void prefs_destroy_file_cache(gpointer to_free)
962 GHashTable *table = (GHashTable *)to_free;
963 g_hash_table_destroy(table);
966 static int prefs_cache_sections(GHashTable *file_cache, const gchar *rcfile)
969 gchar buf[PREFSBUFSIZE];
970 GHashTable *section_cache = NULL;
973 fp = g_fopen(rcfile, "rb");
975 debug_print("cache: %s: %s\n", rcfile?rcfile:"(null)", strerror(errno));
979 #ifdef HAVE_FGETS_UNLOCKED
983 while (SC_FGETS(buf, sizeof(buf), fp) != NULL) {
988 continue; /* comment */
989 if (buf[0] == '[') { /* new section */
990 gchar *blockname = g_strdup(buf+1);
992 if (strrchr(blockname, ']'))
993 *strrchr(blockname, ']') = '\0';
995 if ((section_cache = g_hash_table_lookup(file_cache, blockname)) == NULL) {
996 debug_print("new section '%s'\n", blockname);
997 section_cache = g_hash_table_new_full(g_str_hash, g_str_equal,
999 g_hash_table_insert(file_cache,
1000 blockname, section_cache);
1002 debug_print("section '%s' already done\n", blockname);
1004 section_cache = NULL;
1008 if (!section_cache) {
1009 debug_print("skipping stuff %s with no section\n", buf);
1014 if (!strchr(buf, '=')) {
1015 /* plugins do differently */
1018 pref = g_strdup(buf);
1020 //debug_print("new pref '%s'\n", pref);
1021 g_hash_table_insert(section_cache, pref, GINT_TO_POINTER(1));
1025 #ifdef HAVE_FGETS_UNLOCKED
1032 static int prefs_cache(const gchar *rcfile)
1034 GHashTable *file_cache = g_hash_table_new_full(g_str_hash, g_str_equal,
1035 g_free, prefs_destroy_file_cache);
1037 debug_print("new file '%s'\n", rcfile?rcfile:"(null)");
1038 g_hash_table_insert(whole_cache, g_strdup(rcfile), file_cache);
1040 return prefs_cache_sections(file_cache, rcfile);
1043 void prefs_prepare_cache(void)
1045 gchar *clawsrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
1046 gchar *folderitemrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, FOLDERITEM_RC, NULL);
1047 gchar *accountrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, ACCOUNT_RC, NULL);
1049 if (whole_cache == NULL) {
1050 whole_cache = g_hash_table_new_full(g_str_hash, g_str_equal,
1051 g_free, prefs_destroy_whole_cache);
1053 debug_print("already cached\n");
1055 g_free(folderitemrc);
1059 if (prefs_cache(clawsrc) < 0 ||
1060 prefs_cache(folderitemrc) < 0 ||
1061 prefs_cache(accountrc) < 0)
1062 prefs_destroy_cache();
1065 g_free(folderitemrc);
1069 void prefs_destroy_cache(void)
1072 debug_print("no cache\n");
1075 debug_print("destroying cache\n");
1076 g_hash_table_destroy(whole_cache);
1081 static void prefs_parse_cache(gpointer key, gpointer value, gpointer user_data)
1083 gchar *pref = (gchar *)key;
1085 PrefParam *param = (PrefParam *)user_data;
1087 prefs_config_parse_one_line(param, pref);
1090 static gboolean prefs_read_config_from_cache(PrefParam *param, const gchar *label,
1091 const gchar *rcfile)
1093 GHashTable *sections_table = NULL;
1094 GHashTable *values_table = NULL;
1095 sections_table = g_hash_table_lookup(whole_cache, rcfile);
1097 if (sections_table == NULL) {
1098 g_warning("Can't find %s in the whole cache\n", rcfile?rcfile:"(null)");
1101 values_table = g_hash_table_lookup(sections_table, label);
1103 if (values_table == NULL) {
1104 debug_print("no '%s' section in '%s' cache\n", label?label:"(null)", rcfile?rcfile:"(null)");
1107 g_hash_table_foreach(values_table, prefs_parse_cache, param);