Read show_icon_names only once.
[geeqie.git] / src / rcfile.c
1 /*
2  * Geeqie
3  * (C) 2006 John Ellis
4  *
5  * Author: John Ellis
6  *
7  * This software is released under the GNU General Public License (GNU GPL).
8  * Please read the included file COPYING for more information.
9  * This software comes with no warranty of any kind, use at your own risk!
10  */
11
12 #include <glib/gstdio.h>
13 #include <errno.h>
14
15 #include "main.h"
16 #include "rcfile.h"
17
18 #include "bar_exif.h"
19 #include "filelist.h"
20 #include "secure_save.h"
21 #include "slideshow.h"
22 #include "ui_fileops.h"
23
24
25 /*
26  *-----------------------------------------------------------------------------
27  * line write/parse routines (private)
28  *-----------------------------------------------------------------------------
29  */ 
30  
31 /* 
32    returns text without quotes or NULL for empty or broken string
33    any text up to first '"' is skipped
34    tail is set to point at the char after the second '"'
35    or at the ending \0 
36    
37 */
38
39 gchar *quoted_value(const gchar *text, const gchar **tail)
40 {
41         const gchar *ptr;
42         gint c = 0;
43         gint l = strlen(text);
44         gchar *retval = NULL;
45         
46         if (tail) *tail = text;
47         
48         if (l == 0) return retval;
49
50         while (c < l && text[c] !='"') c++;
51         if (text[c] == '"')
52                 {
53                 gint e;
54                 c++;
55                 ptr = text + c;
56                 e = c;
57                 while (e < l)
58                         {
59                         if (text[e-1] != '\\' && text[e] == '"') break;
60                         e++;
61                         }
62                 if (text[e] == '"')
63                         {
64                         if (e - c > 0)
65                                 {
66                                 gchar *substring = g_strndup(ptr, e - c);
67                                 
68                                 if (substring)
69                                         {
70                                         retval = g_strcompress(substring);
71                                         g_free(substring);
72                                         }
73                                 }
74                         }
75                 if (tail) *tail = text + e + 1;
76                 }
77         else
78                 /* for compatibility with older formats (<0.3.7)
79                  * read a line without quotes too */
80                 {
81                 c = 0;
82                 while (c < l && text[c] !=' ' && text[c] !=8 && text[c] != '\n') c++;
83                 if (c != 0)
84                         {
85                         retval = g_strndup(text, c);
86                         }
87                 if (tail) *tail = text + c;
88                 }
89
90         return retval;
91 }
92
93 gchar *escquote_value(const gchar *text)
94 {
95         gchar *e;
96         
97         if (!text) return g_strdup("\"\"");
98
99         e = g_strescape(text, "");
100         if (e)
101                 {
102                 gchar *retval = g_strdup_printf("\"%s\"", e);
103                 g_free(e);
104                 return retval;
105                 }
106         return g_strdup("\"\"");
107 }
108
109 static void write_char_option(SecureSaveInfo *ssi, gchar *label, gchar *text)
110 {
111         gchar *escval = escquote_value(text);
112
113         secure_fprintf(ssi, "%s: %s\n", label, escval);
114         g_free(escval);
115 }
116
117 static void read_char_option(FILE *f, gchar *option, gchar *label, gchar *value, gchar **text)
118 {
119         if (text && strcasecmp(option, label) == 0)
120                 {
121                 g_free(*text);
122                 *text = quoted_value(value, NULL);
123                 }
124 }
125
126 /* Since gdk_color_to_string() is only available since gtk 2.12
127  * here is an equivalent stub function. */
128 static gchar *color_to_string(GdkColor *color)
129 {
130         return g_strdup_printf("#%04X%04X%04X", color->red, color->green, color->blue);
131 }
132
133 static void write_color_option(SecureSaveInfo *ssi, gchar *label, GdkColor *color)
134 {
135         if (color)
136                 {
137                 gchar *colorstring = color_to_string(color);
138
139                 write_char_option(ssi, label, colorstring);
140                 g_free(colorstring);
141                 }
142         else
143                 secure_fprintf(ssi, "%s: \n", label);
144 }
145
146 static void read_color_option(FILE *f, gchar *option, gchar *label, gchar *value, GdkColor *color)
147 {
148         if (color && strcasecmp(option, label) == 0)
149                 {
150                 gchar *colorstr = quoted_value(value, NULL);
151                 if (colorstr) gdk_color_parse(colorstr, color);
152                 g_free(colorstr);
153                 }
154 }
155
156
157 static void write_int_option(SecureSaveInfo *ssi, gchar *label, gint n)
158 {
159         secure_fprintf(ssi, "%s: %d\n", label, n);
160 }
161
162 static void read_int_option(FILE *f, gchar *option, gchar *label, gchar *value, gint *n)
163 {
164         if (n && strcasecmp(option, label) == 0)
165                 {
166                 *n = strtol(value, NULL, 10);
167                 }
168 }
169
170 static void read_uint_option(FILE *f, gchar *option, gchar *label, gchar *value, guint *n)
171 {
172         if (n && strcasecmp(option, label) == 0)
173                 {
174                 *n = strtoul(value, NULL, 10);
175                 }
176 }
177
178
179
180 static void read_int_option_clamp(FILE *f, gchar *option, gchar *label, gchar *value, gint *n, gint min, gint max)
181 {
182         if (n && strcasecmp(option, label) == 0)
183                 {
184                 *n = CLAMP(strtol(value, NULL, 10), min, max);
185                 }
186 }
187
188
189 static void write_int_unit_option(SecureSaveInfo *ssi, gchar *label, gint n, gint subunits)
190 {
191         gint l, r;
192
193         if (subunits > 0)
194                 {
195                 l = n / subunits;
196                 r = n % subunits;
197                 }
198         else
199                 {
200                 l = n;
201                 r = 0;
202                 }
203
204         secure_fprintf(ssi, "%s: %d.%d\n", label, l, r);
205 }
206
207 static void read_int_unit_option(FILE *f, gchar *option, gchar *label, gchar *value, gint *n, gint subunits)
208 {
209         if (n && strcasecmp(option, label) == 0)
210                 {
211                 gint l, r;
212                 gchar *ptr;
213
214                 ptr = value;
215                 while (*ptr != '\0' && *ptr != '.') ptr++;
216                 if (*ptr == '.')
217                         {
218                         *ptr = '\0';
219                         l = strtol(value, NULL, 10);
220                         *ptr = '.';
221                         ptr++;
222                         r = strtol(ptr, NULL, 10);
223                         }
224                 else
225                         {
226                         l = strtol(value, NULL, 10);
227                         r = 0;
228                         }
229
230                 *n = l * subunits + r;
231                 }
232 }
233
234 static void write_bool_option(SecureSaveInfo *ssi, gchar *label, gint n)
235 {
236         secure_fprintf(ssi, "%s: ", label);
237         if (n) secure_fprintf(ssi, "true\n"); else secure_fprintf(ssi, "false\n");
238 }
239
240 static void read_bool_option(FILE *f, gchar *option, gchar *label, gchar *value, gint *n)
241 {
242         if (n && strcasecmp(option, label) == 0)
243                 {
244                 if (strcasecmp(value, "true") == 0 || strcmp(value, "1") == 0)
245                         *n = TRUE;
246                 else
247                         *n = FALSE;
248                 }
249 }
250
251 /*
252  *-----------------------------------------------------------------------------
253  * save configuration (public)
254  *-----------------------------------------------------------------------------
255  */ 
256
257 void save_options(void)
258 {
259         SecureSaveInfo *ssi;
260         gchar *rc_path;
261         gchar *rc_pathl;
262         gint i;
263
264         rc_path = g_strconcat(homedir(), "/", GQ_RC_DIR, "/", RC_FILE_NAME, NULL);
265
266         rc_pathl = path_from_utf8(rc_path);
267         ssi = secure_open(rc_pathl);
268         g_free(rc_pathl);
269         if (!ssi)
270                 {
271                 gchar *buf;
272
273                 buf = g_strdup_printf(_("error saving config file: %s\n"), rc_path);
274                 print_term(buf);
275                 g_free(buf);
276
277                 g_free(rc_path);
278                 return;
279                 }
280         
281 #define WRITE_BOOL(_name_) write_bool_option(ssi, #_name_, options->_name_)
282 #define WRITE_INT(_name_) write_int_option(ssi, #_name_, options->_name_)
283 #define WRITE_INT_UNIT(_name_, _unit_) write_int_unit_option(ssi, #_name_, options->_name_, _unit_)
284 #define WRITE_CHAR(_name_) write_char_option(ssi, #_name_, options->_name_)
285 #define WRITE_COLOR(_name_) write_color_option(ssi, #_name_, &options->_name_)
286
287 #define WRITE_SEPARATOR() secure_fputc(ssi, '\n')
288 #define WRITE_SUBTITLE(_title_) secure_fprintf(ssi, "\n\n##### "_title_" #####\n\n")
289
290         secure_fprintf(ssi, "######################################################################\n");
291         secure_fprintf(ssi, "# %30s config file         version %7s #\n", GQ_APPNAME, VERSION);
292         secure_fprintf(ssi, "######################################################################\n");
293         WRITE_SEPARATOR();
294
295         secure_fprintf(ssi, "# Note: This file is autogenerated. Options can be changed here,\n");
296         secure_fprintf(ssi, "#       but user comments and formatting will be lost.\n");
297         WRITE_SEPARATOR();
298
299         WRITE_SUBTITLE("General Options");
300
301         WRITE_BOOL(show_icon_names);
302         WRITE_SEPARATOR();
303
304         WRITE_BOOL(tree_descend_subdirs);
305         WRITE_BOOL(lazy_image_sync);
306         WRITE_BOOL(update_on_time_change);
307         WRITE_SEPARATOR();
308
309         WRITE_BOOL(startup_path_enable);
310         WRITE_CHAR(startup_path);
311
312         WRITE_BOOL(progressive_key_scrolling);
313         WRITE_BOOL(enable_metadata_dirs);
314
315         WRITE_INT(duplicates_similarity_threshold);
316         WRITE_SEPARATOR();
317
318         WRITE_BOOL(mousewheel_scrolls);
319         WRITE_INT(open_recent_list_maxsize);
320         WRITE_BOOL(place_dialogs_under_mouse);
321
322
323         WRITE_SUBTITLE("File operations Options");
324
325         WRITE_BOOL(file_ops.enable_in_place_rename);
326         WRITE_BOOL(file_ops.confirm_delete);
327         WRITE_BOOL(file_ops.enable_delete_key);
328         WRITE_BOOL(file_ops.safe_delete_enable);
329         WRITE_CHAR(file_ops.safe_delete_path);
330         WRITE_INT(file_ops.safe_delete_folder_maxsize);
331
332         
333         WRITE_SUBTITLE("Layout Options");
334
335         WRITE_INT(layout.style);
336         WRITE_CHAR(layout.order);
337         WRITE_BOOL(layout.view_as_icons);
338         WRITE_BOOL(layout.view_as_tree);
339         WRITE_BOOL(layout.show_thumbnails);
340         WRITE_SEPARATOR();
341
342         WRITE_BOOL(layout.save_window_positions);
343         WRITE_SEPARATOR();
344
345         WRITE_INT(layout.main_window.x);
346         WRITE_INT(layout.main_window.y);
347         WRITE_INT(layout.main_window.w);
348         WRITE_INT(layout.main_window.h);
349         WRITE_BOOL(layout.main_window.maximized);
350         WRITE_INT(layout.main_window.hdivider_pos);
351         WRITE_INT(layout.main_window.vdivider_pos);
352         WRITE_SEPARATOR();
353
354         WRITE_INT(layout.float_window.x);
355         WRITE_INT(layout.float_window.y);
356         WRITE_INT(layout.float_window.w);
357         WRITE_INT(layout.float_window.h);
358         WRITE_INT(layout.float_window.vdivider_pos);
359         WRITE_SEPARATOR();
360
361         WRITE_BOOL(layout.tools_float);
362         WRITE_BOOL(layout.tools_hidden);
363         WRITE_BOOL(layout.tools_restore_state);
364         WRITE_SEPARATOR();
365
366         WRITE_BOOL(layout.toolbar_hidden);
367
368
369         WRITE_SUBTITLE("Image Options");
370
371         secure_fprintf(ssi, "image.zoom_mode: ");
372         if (options->image.zoom_mode == ZOOM_RESET_ORIGINAL) secure_fprintf(ssi, "original\n");
373         if (options->image.zoom_mode == ZOOM_RESET_FIT_WINDOW) secure_fprintf(ssi, "fit\n");
374         if (options->image.zoom_mode == ZOOM_RESET_NONE) secure_fprintf(ssi, "dont_change\n");
375         WRITE_BOOL(image.zoom_2pass);
376         WRITE_BOOL(image.zoom_to_fit_allow_expand);
377         WRITE_INT(image.zoom_quality);
378         WRITE_INT(image.zoom_increment);
379         WRITE_BOOL(image.fit_window_to_image);
380         WRITE_BOOL(image.limit_window_size);
381         WRITE_INT(image.max_window_size);
382         WRITE_BOOL(image.limit_autofit_size);
383         WRITE_INT(image.max_autofit_size);
384         WRITE_INT(image.scroll_reset_method);
385         WRITE_INT(image.tile_cache_max);
386         WRITE_INT(image.dither_quality);
387         WRITE_BOOL(image.enable_read_ahead);
388         WRITE_BOOL(image.exif_rotate_enable);
389         WRITE_BOOL(image.use_custom_border_color);
390         WRITE_COLOR(image.border_color);
391
392
393         WRITE_SUBTITLE("Thumbnails Options");
394
395         WRITE_INT(thumbnails.max_width);
396         WRITE_INT(thumbnails.max_height);
397         WRITE_BOOL(thumbnails.enable_caching);
398         WRITE_BOOL(thumbnails.cache_into_dirs);
399         WRITE_BOOL(thumbnails.fast);
400         WRITE_BOOL(thumbnails.use_xvpics);
401         WRITE_BOOL(thumbnails.spec_standard);
402         WRITE_INT(thumbnails.quality);
403
404
405         WRITE_SUBTITLE("File sorting Options");
406
407         WRITE_INT(file_sort.method);
408         WRITE_BOOL(file_sort.ascending);
409         WRITE_BOOL(file_sort.case_sensitive);
410
411         
412         WRITE_SUBTITLE("Fullscreen Options");
413
414         WRITE_INT(fullscreen.screen);
415         WRITE_BOOL(fullscreen.clean_flip);
416         WRITE_BOOL(fullscreen.disable_saver);
417         WRITE_BOOL(fullscreen.above);
418         WRITE_BOOL(fullscreen.show_info);
419         WRITE_CHAR(fullscreen.info);
420
421         WRITE_SUBTITLE("Slideshow Options");
422
423         WRITE_INT_UNIT(slideshow.delay, SLIDESHOW_SUBSECOND_PRECISION);
424         WRITE_BOOL(slideshow.random);
425         WRITE_BOOL(slideshow.repeat);
426
427
428         WRITE_SUBTITLE("Collection Options");
429
430         WRITE_BOOL(collections.rectangular_selection);
431
432
433         WRITE_SUBTITLE("Filtering Options");
434
435         WRITE_BOOL(file_filter.show_hidden_files);
436         WRITE_BOOL(file_filter.show_dot_directory);
437         WRITE_BOOL(file_filter.disable);
438         WRITE_SEPARATOR();
439
440         filter_write_list(ssi);
441         
442
443         WRITE_SUBTITLE("Sidecars Options");
444
445         sidecar_ext_write(ssi);
446
447
448         WRITE_SUBTITLE("Color Profiles");
449
450 #ifndef HAVE_LCMS
451         secure_fprintf(ssi, "# NOTICE: %s was not built with support for color profiles,\n"
452                             "#         color profile options will have no effect.\n\n", GQ_APPNAME);
453 #endif
454
455         WRITE_BOOL(color_profile.enabled);
456         WRITE_BOOL(color_profile.use_image);
457         WRITE_INT(color_profile.input_type);
458         WRITE_SEPARATOR();
459
460         for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
461                 {
462                 gchar *buf;
463
464                 buf = g_strdup_printf("color_profile.input_file_%d", i + 1);
465                 write_char_option(ssi, buf, options->color_profile.input_file[i]);
466                 g_free(buf);
467
468                 buf = g_strdup_printf("color_profile.input_name_%d", i + 1);
469                 write_char_option(ssi, buf, options->color_profile.input_name[i]);
470                 g_free(buf);
471                 }
472
473         WRITE_SEPARATOR();
474         WRITE_INT(color_profile.screen_type);
475         WRITE_CHAR(color_profile.screen_file);
476
477         WRITE_SUBTITLE("External Programs");
478         secure_fprintf(ssi, "# Maximum of %d programs (external_1 through external_%d)\n", GQ_EDITOR_GENERIC_SLOTS, GQ_EDITOR_GENERIC_SLOTS);
479         secure_fprintf(ssi, "# external_%d through external_%d are used for file ops\n", GQ_EDITOR_GENERIC_SLOTS + 1, GQ_EDITOR_SLOTS);
480         secure_fprintf(ssi, "# format: external_n: \"menu name\" \"command line\"\n\n");
481
482         for (i = 0; i < GQ_EDITOR_SLOTS; i++)
483                 {
484                 if (i == GQ_EDITOR_GENERIC_SLOTS) secure_fputc(ssi, '\n');
485                 gchar *qname = escquote_value(options->editor_name[i]);
486                 gchar *qcommand = escquote_value(options->editor_command[i]);
487                 secure_fprintf(ssi, "external_%d: %s %s\n", i+1, qname, qcommand);
488                 g_free(qname);
489                 g_free(qcommand);
490                 }
491
492
493         WRITE_SUBTITLE("Exif Options");
494         secure_fprintf(ssi, "# Display: 0: never\n"
495                             "#          1: if set\n"
496                             "#          2: always\n\n");
497         for (i = 0; ExifUIList[i].key; i++)
498                 {
499                 secure_fprintf(ssi, "exif.display.");
500                 write_int_option(ssi, (gchar *)ExifUIList[i].key, ExifUIList[i].current);
501                 }
502
503         WRITE_SEPARATOR();
504         WRITE_SEPARATOR();
505
506         secure_fprintf(ssi, "######################################################################\n");
507         secure_fprintf(ssi, "#                         end of config file                         #\n");
508         secure_fprintf(ssi, "######################################################################\n");
509
510         
511         if (secure_close(ssi))
512                 {
513                 gchar *buf;
514
515                 buf = g_strdup_printf(_("error saving config file: %s\nerror: %s\n"), rc_path,
516                                       secsave_strerror(secsave_errno));
517                 print_term(buf);
518                 g_free(buf);
519
520                 g_free(rc_path);
521                 return;
522                 }
523
524         g_free(rc_path);
525 }
526
527 /*
528  *-----------------------------------------------------------------------------
529  * load configuration (public)
530  *-----------------------------------------------------------------------------
531  */ 
532
533 void load_options(void)
534 {
535         FILE *f;
536         gchar *rc_path;
537         gchar *rc_pathl;
538         gchar s_buf[1024];
539         gchar option[1024];
540         gchar value[1024];
541         gchar value_all[1024];
542         gint i;
543
544         for (i = 0; ExifUIList[i].key; i++)
545                 ExifUIList[i].current = ExifUIList[i].default_value;
546
547         rc_path = g_strconcat(homedir(), "/", GQ_RC_DIR, "/", RC_FILE_NAME, NULL);
548
549         rc_pathl = path_from_utf8(rc_path);
550         f = fopen(rc_pathl,"r");
551         g_free(rc_pathl);
552         if (!f)
553                 {
554                 g_free(rc_path);
555                 return;
556                 }
557
558         while (fgets(s_buf, sizeof(s_buf), f))
559                 {
560                 gchar *option_start, *value_start;
561                 gchar *p = s_buf;
562
563                 while(g_ascii_isspace(*p)) p++;
564                 if (!*p || *p == '\n' || *p == '#') continue;
565                 option_start = p;
566                 while(*p && *p != ':') p++;
567                 if (!*p) continue;
568                 *p = '\0';
569                 p++;
570                 strncpy(option, option_start, sizeof(option));
571                 while(g_ascii_isspace(*p)) p++;
572                 value_start = p;
573                 strncpy(value_all, value_start, sizeof(value_all));
574                 while(*p && !g_ascii_isspace(*p) && *p != '\n') p++;
575                 *p = '\0';
576                 strncpy(value, value_start, sizeof(value));
577
578 #define READ_BOOL(_name_) read_bool_option(f, option, #_name_, value, &options->_name_)
579 #define READ_INT(_name_) read_int_option(f, option, #_name_, value, &options->_name_)
580 #define READ_UINT(_name_) read_uint_option(f, option, #_name_, value, &options->_name_)
581 #define READ_INT_CLAMP(_name_, _min_, _max_) read_int_option_clamp(f, option, #_name_, value, &options->_name_, _min_, _max_)
582 #define READ_INT_UNIT(_name_, _unit_) read_int_unit_option(f, option, #_name_, value, &options->_name_, _unit_)
583 #define READ_CHAR(_name_) read_char_option(f, option, #_name_, value_all, &options->_name_)
584 #define READ_COLOR(_name_) read_color_option(f, option, #_name_, value, &options->_name_)
585
586                 /* general options */
587                 READ_BOOL(show_icon_names);
588
589                 READ_BOOL(tree_descend_subdirs);
590                 READ_BOOL(lazy_image_sync);
591                 READ_BOOL(update_on_time_change);
592         
593                 READ_BOOL(startup_path_enable);
594                 READ_CHAR(startup_path);
595
596                 READ_INT(duplicates_similarity_threshold);
597
598                 READ_BOOL(progressive_key_scrolling);
599
600                 READ_BOOL(enable_metadata_dirs);
601
602                 READ_BOOL(mousewheel_scrolls);
603         
604                 READ_INT(open_recent_list_maxsize);
605
606                 READ_BOOL(place_dialogs_under_mouse);
607
608
609                 /* layout options */
610
611                 READ_INT(layout.style);
612                 READ_CHAR(layout.order);
613                 READ_BOOL(layout.view_as_icons);
614                 READ_BOOL(layout.view_as_tree);
615                 READ_BOOL(layout.show_thumbnails);
616
617                 /* window positions */
618
619                 READ_BOOL(layout.save_window_positions);
620
621                 READ_INT(layout.main_window.x);
622                 READ_INT(layout.main_window.y);
623                 READ_INT(layout.main_window.w);
624                 READ_INT(layout.main_window.h);
625                 READ_BOOL(layout.main_window.maximized);
626                 READ_INT(layout.float_window.x);
627                 READ_INT(layout.float_window.y);
628                 READ_INT(layout.float_window.w);
629                 READ_INT(layout.float_window.h);
630                 READ_INT(layout.float_window.vdivider_pos);
631                 READ_INT(layout.main_window.hdivider_pos);
632                 READ_INT(layout.main_window.vdivider_pos);
633                 READ_BOOL(layout.tools_float);
634                 READ_BOOL(layout.tools_hidden);
635                 READ_BOOL(layout.tools_restore_state);
636                 READ_BOOL(layout.toolbar_hidden);
637
638
639                 /* image options */
640                 if (strcasecmp(option, "image.zoom_mode") == 0)
641                         {
642                         if (strcasecmp(value, "original") == 0) options->image.zoom_mode = ZOOM_RESET_ORIGINAL;
643                         if (strcasecmp(value, "fit") == 0) options->image.zoom_mode = ZOOM_RESET_FIT_WINDOW;
644                         if (strcasecmp(value, "dont_change") == 0) options->image.zoom_mode = ZOOM_RESET_NONE;
645                         }
646                 READ_BOOL(image.zoom_2pass);
647                 READ_BOOL(image.zoom_to_fit_allow_expand);
648                 READ_BOOL(image.fit_window_to_image);
649                 READ_BOOL(image.limit_window_size);
650                 READ_INT(image.max_window_size);
651                 READ_BOOL(image.limit_autofit_size);
652                 READ_INT(image.max_autofit_size);
653                 READ_INT(image.scroll_reset_method);
654                 READ_INT(image.tile_cache_max);
655                 READ_INT_CLAMP(image.zoom_quality, GDK_INTERP_NEAREST, GDK_INTERP_HYPER);
656                 READ_INT_CLAMP(image.dither_quality, GDK_RGB_DITHER_NONE, GDK_RGB_DITHER_MAX);
657                 READ_INT(image.zoom_increment);
658                 READ_BOOL(image.enable_read_ahead);
659                 READ_BOOL(image.exif_rotate_enable);
660                 READ_BOOL(image.use_custom_border_color);
661                 READ_COLOR(image.border_color);
662
663
664                 /* thumbnails options */
665                 READ_INT_CLAMP(thumbnails.max_width, 16, 512);
666                 READ_INT_CLAMP(thumbnails.max_height, 16, 512);
667
668                 READ_BOOL(thumbnails.enable_caching);
669                 READ_BOOL(thumbnails.cache_into_dirs);
670                 READ_BOOL(thumbnails.fast);
671                 READ_BOOL(thumbnails.use_xvpics);
672                 READ_BOOL(thumbnails.spec_standard);
673                 READ_INT_CLAMP(thumbnails.quality, GDK_INTERP_NEAREST, GDK_INTERP_HYPER);
674
675                 /* file sorting options */
676                 READ_UINT(file_sort.method);
677                 READ_BOOL(file_sort.ascending);
678                 READ_BOOL(file_sort.case_sensitive);
679
680                 /* file operations options */
681                 READ_BOOL(file_ops.enable_in_place_rename);
682                 READ_BOOL(file_ops.confirm_delete);
683                 READ_BOOL(file_ops.enable_delete_key);
684                 READ_BOOL(file_ops.safe_delete_enable);
685                 READ_CHAR(file_ops.safe_delete_path);
686                 READ_INT(file_ops.safe_delete_folder_maxsize);
687
688                 /* fullscreen options */
689                 READ_INT(fullscreen.screen);
690                 READ_BOOL(fullscreen.clean_flip);
691                 READ_BOOL(fullscreen.disable_saver);
692                 READ_BOOL(fullscreen.above);
693                 READ_BOOL(fullscreen.show_info);
694                 READ_CHAR(fullscreen.info);
695
696                 /* slideshow options */
697
698                 READ_INT_UNIT(slideshow.delay, SLIDESHOW_SUBSECOND_PRECISION);
699                 READ_BOOL(slideshow.random);
700                 READ_BOOL(slideshow.repeat);
701
702                 /* collection options */
703
704                 READ_BOOL(collections.rectangular_selection);
705
706                 /* filtering options */
707
708                 READ_BOOL(file_filter.show_hidden_files);
709                 READ_BOOL(file_filter.show_dot_directory);
710                 READ_BOOL(file_filter.disable);
711
712                 if (strcasecmp(option, "file_filter.ext") == 0)
713                         {
714                         filter_parse(value_all);
715                         }
716
717                 if (strcasecmp(option, "sidecar.ext") == 0)
718                         {
719                         sidecar_ext_parse(value_all, TRUE);
720                         }
721                 
722                 /* Color Profiles */
723
724                 READ_BOOL(color_profile.enabled);
725                 READ_BOOL(color_profile.use_image);
726                 READ_INT(color_profile.input_type);
727
728                 if (strncasecmp(option, "color_profile.input_file_", 25) == 0)
729                         {
730                         i = strtol(option + 25, NULL, 0) - 1;
731                         if (i >= 0 && i < COLOR_PROFILE_INPUTS)
732                                 {
733                                 read_char_option(f, option, option, value, &options->color_profile.input_file[i]);
734                                 }
735                         }
736                 if (strncasecmp(option, "color_profile.input_name_", 25) == 0)
737                         {
738                         i = strtol(option + 25, NULL, 0) - 1;
739                         if (i >= 0 && i < COLOR_PROFILE_INPUTS)
740                                 {
741                                 read_char_option(f, option, option, value, &options->color_profile.input_name[i]);
742                                 }
743                         }
744
745                 READ_INT(color_profile.screen_type);
746                 READ_CHAR(color_profile.screen_file);
747
748                 /* External Programs */
749
750                 if (strncasecmp(option, "external_", 9) == 0)
751                         {
752                         i = strtol(option + 9, NULL, 0);
753                         if (i > 0 && i <= GQ_EDITOR_SLOTS)
754                                 {
755                                 const gchar *ptr;
756                                 i--;
757                                 g_free(options->editor_name[i]);
758                                 g_free(options->editor_command[i]);
759                                 
760                                 options->editor_name[i] = quoted_value(value_all, &ptr);
761                                 options->editor_command[i] = quoted_value(ptr, NULL);
762                                 }
763                         }
764
765                 /* Exif */
766                 if (0 == strncasecmp(option, "exif.display.", 13))
767                         {
768                         for (i = 0; ExifUIList[i].key; i++)
769                                 if (0 == strcasecmp(option + 13, ExifUIList[i].key))
770                                         ExifUIList[i].current = strtol(value, NULL, 10);
771                         }
772                 }
773
774         fclose(f);
775         g_free(rc_path);
776 }
777