Add a new struct ConfOptions to handle options.
[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 gchar *read_char_option(FILE *f, gchar *option, gchar *label, gchar *value, gchar *text)
118 {
119         if (strcasecmp(option, label) == 0)
120                 {
121                 g_free(text);
122                 text = quoted_value(value, NULL);
123                 }
124         return text;
125 }
126
127 /* Since gdk_color_to_string() is only available since gtk 2.12
128  * here is an equivalent stub function. */
129 static gchar *color_to_string(GdkColor *color)
130 {
131         return g_strdup_printf("#%04X%04X%04X", color->red, color->green, color->blue);
132 }
133
134 static void write_color_option(SecureSaveInfo *ssi, gchar *label, GdkColor *color)
135 {
136         if (color)
137                 {
138                 gchar *colorstring = color_to_string(color);
139
140                 write_char_option(ssi, label, colorstring);
141                 g_free(colorstring);
142                 }
143         else
144                 secure_fprintf(ssi, "%s: \n", label);
145 }
146
147 static GdkColor *read_color_option(FILE *f, gchar *option, gchar *label, gchar *value, GdkColor *color)
148 {
149         if (strcasecmp(option, label) == 0)
150                 {
151                 gchar *colorstr = quoted_value(value, NULL);
152                 if (colorstr) gdk_color_parse(colorstr, color);
153                 g_free(colorstr);
154                 }
155         return color;
156 }
157
158
159 static void write_int_option(SecureSaveInfo *ssi, gchar *label, gint n)
160 {
161         secure_fprintf(ssi, "%s: %d\n", label, n);
162 }
163
164 static gint read_int_option(FILE *f, gchar *option, gchar *label, gchar *value, gint n)
165 {
166         if (strcasecmp(option, label) == 0)
167                 {
168                 n = strtol(value, NULL, 10);
169                 }
170         return n;
171 }
172
173 static void write_int_unit_option(SecureSaveInfo *ssi, gchar *label, gint n, gint subunits)
174 {
175         gint l, r;
176
177         if (subunits > 0)
178                 {
179                 l = n / subunits;
180                 r = n % subunits;
181                 }
182         else
183                 {
184                 l = n;
185                 r = 0;
186                 }
187
188         secure_fprintf(ssi, "%s: %d.%d\n", label, l, r);
189 }
190
191 static gint read_int_unit_option(FILE *f, gchar *option, gchar *label, gchar *value, gint n, gint subunits)
192 {
193         if (strcasecmp(option, label) == 0)
194                 {
195                 gint l, r;
196                 gchar *ptr;
197
198                 ptr = value;
199                 while (*ptr != '\0' && *ptr != '.') ptr++;
200                 if (*ptr == '.')
201                         {
202                         *ptr = '\0';
203                         l = strtol(value, NULL, 10);
204                         *ptr = '.';
205                         ptr++;
206                         r = strtol(ptr, NULL, 10);
207                         }
208                 else
209                         {
210                         l = strtol(value, NULL, 10);
211                         r = 0;
212                         }
213
214                 n = l * subunits + r;
215                 }
216         return n;
217 }
218
219 static void write_bool_option(SecureSaveInfo *ssi, gchar *label, gint n)
220 {
221         secure_fprintf(ssi, "%s: ", label);
222         if (n) secure_fprintf(ssi, "true\n"); else secure_fprintf(ssi, "false\n");
223 }
224
225 static gint read_bool_option(FILE *f, gchar *option, gchar *label, gchar *value, gint n)
226 {
227         if (strcasecmp(option, label) == 0)
228                 {
229                 if (strcasecmp(value, "true") == 0)
230                         n = TRUE;
231                 else
232                         n = FALSE;
233                 }
234         return n;
235 }
236
237 /*
238  *-----------------------------------------------------------------------------
239  * save configuration (public)
240  *-----------------------------------------------------------------------------
241  */ 
242
243 void save_options(void)
244 {
245         SecureSaveInfo *ssi;
246         gchar *rc_path;
247         gchar *rc_pathl;
248         gint i;
249
250         rc_path = g_strconcat(homedir(), "/", GQ_RC_DIR, "/", RC_FILE_NAME, NULL);
251
252         rc_pathl = path_from_utf8(rc_path);
253         ssi = secure_open(rc_pathl);
254         g_free(rc_pathl);
255         if (!ssi)
256                 {
257                 gchar *buf;
258
259                 buf = g_strdup_printf(_("error saving config file: %s\n"), rc_path);
260                 print_term(buf);
261                 g_free(buf);
262
263                 g_free(rc_path);
264                 return;
265                 }
266         
267         secure_fprintf(ssi, "######################################################################\n");
268         secure_fprintf(ssi, "# %30s config file         version %7s #\n", GQ_APPNAME, VERSION);
269         secure_fprintf(ssi, "######################################################################\n");
270         secure_fputc(ssi, '\n');
271
272         secure_fprintf(ssi, "# Note: This file is autogenerated. Options can be changed here,\n");
273         secure_fprintf(ssi, "#       but user comments and formatting will be lost.\n");
274         secure_fputc(ssi, '\n');
275
276         secure_fprintf(ssi, "##### General Options #####\n\n");
277
278         write_int_option(ssi, "layout_style", layout_style);
279         write_char_option(ssi, "layout_order", layout_order);
280         secure_fputc(ssi, '\n');
281
282         write_bool_option(ssi, "layout_view_as_icons", layout_view_icons);
283         write_bool_option(ssi, "layout_view_as_tree", layout_view_tree);
284         write_bool_option(ssi, "show_icon_names", show_icon_names);
285         secure_fputc(ssi, '\n');
286
287         write_bool_option(ssi, "tree_descend_folders", tree_descend_subdirs);
288         write_bool_option(ssi, "lazy_image_sync", lazy_image_sync);
289         write_bool_option(ssi, "update_on_time_change", update_on_time_change);
290         write_bool_option(ssi, "exif_auto_rotate", exif_rotate_enable);
291         secure_fputc(ssi, '\n');
292
293         write_bool_option(ssi, "enable_startup_path", options->startup_path_enable);
294         write_char_option(ssi, "startup_path", options->startup_path);
295         secure_fputc(ssi, '\n');
296
297         secure_fprintf(ssi, "zoom_mode: ");
298         if (options->zoom_mode == ZOOM_RESET_ORIGINAL) secure_fprintf(ssi, "original\n");
299         if (options->zoom_mode == ZOOM_RESET_FIT_WINDOW) secure_fprintf(ssi, "fit\n");
300         if (options->zoom_mode == ZOOM_RESET_NONE) secure_fprintf(ssi, "dont_change\n");
301         write_bool_option(ssi, "two_pass_scaling", options->two_pass_zoom);
302         write_bool_option(ssi, "zoom_to_fit_allow_expand", options->zoom_to_fit_expands);
303         secure_fputc(ssi, '\n');
304
305         write_bool_option(ssi, "fit_window_to_image", options->fit_window);
306         write_bool_option(ssi, "limit_window_size", options->limit_window_size);
307         write_int_option(ssi, "max_window_size", options->max_window_size);
308         write_bool_option(ssi, "limit_autofit_size", options->limit_autofit_size);
309         write_int_option(ssi, "max_autofit_size", options->max_autofit_size);
310         secure_fputc(ssi, '\n');
311
312         write_bool_option(ssi, "progressive_keyboard_scrolling", options->progressive_key_scrolling);
313         write_int_option(ssi, "scroll_reset_method", options->scroll_reset_method);
314         secure_fputc(ssi, '\n');
315
316         write_bool_option(ssi, "enable_thumbnails", options->thumbnails_enabled);
317         write_int_option(ssi, "thumbnail_width", options->thumb_max_width);
318         write_int_option(ssi, "thumbnail_height", options->thumb_max_height);
319         write_bool_option(ssi, "cache_thumbnails", options->enable_thumb_caching);
320         write_bool_option(ssi, "cache_thumbnails_into_dirs", options->enable_thumb_dirs);
321         write_bool_option(ssi, "thumbnail_fast", options->thumbnail_fast);
322         write_bool_option(ssi, "use_xvpics_thumbnails", options->use_xvpics_thumbnails);
323         write_bool_option(ssi, "thumbnail_spec_standard", options->thumbnail_spec_standard);
324         secure_fputc(ssi, '\n');
325
326         write_bool_option(ssi, "local_metadata", options->enable_metadata_dirs);
327         secure_fputc(ssi, '\n');
328
329         write_int_option(ssi, "sort_method", (gint)options->file_sort_method);
330         write_bool_option(ssi, "sort_ascending", options->file_sort_ascending);
331         write_bool_option(ssi, "sort_case_sensitive", file_sort_case_sensitive);
332         secure_fputc(ssi, '\n');
333
334         write_bool_option(ssi, "confirm_delete", options->confirm_delete);
335         write_bool_option(ssi, "enable_delete_key", options->enable_delete_key);
336         write_bool_option(ssi, "safe_delete", options->safe_delete_enable);
337         write_char_option(ssi, "safe_delete_path", options->safe_delete_path);
338         write_int_option(ssi, "safe_delete_size", options->safe_delete_size);
339         secure_fputc(ssi, '\n');
340
341         write_bool_option(ssi, "tools_float", options->tools_float);
342         write_bool_option(ssi, "tools_hidden", options->tools_hidden);
343         write_bool_option(ssi, "restore_tool_state", options->restore_tool);
344         write_bool_option(ssi, "toolbar_hidden", options->toolbar_hidden);
345         secure_fputc(ssi, '\n');
346
347         write_bool_option(ssi, "mouse_wheel_scrolls", options->mousewheel_scrolls);
348         write_bool_option(ssi, "in_place_rename", options->enable_in_place_rename);
349         write_int_option(ssi, "open_recent_max", options->recent_list_max);
350         write_int_option(ssi, "image_cache_size_max", options->tile_cache_max);
351         write_int_option(ssi, "thumbnail_quality", options->thumbnail_quality);
352         write_int_option(ssi, "zoom_quality", options->zoom_quality);
353         write_int_option(ssi, "dither_quality", options->dither_quality);
354         write_int_option(ssi, "zoom_increment", options->zoom_increment);
355         write_bool_option(ssi, "enable_read_ahead", options->enable_read_ahead);
356         write_bool_option(ssi, "display_dialogs_under_mouse", options->place_dialogs_under_mouse);
357         secure_fputc(ssi, '\n');
358
359         write_bool_option(ssi, "user_specified_window_background", options->user_specified_window_background);
360         write_color_option(ssi, "window_background_color", &options->window_background_color);
361         secure_fputc(ssi, '\n');
362
363         write_int_option(ssi, "fullscreen_screen", options->fullscreen_screen);
364         write_bool_option(ssi, "fullscreen_clean_flip", options->fullscreen_clean_flip);
365         write_bool_option(ssi, "fullscreen_disable_saver", options->fullscreen_disable_saver);
366         write_bool_option(ssi, "fullscreen_above", options->fullscreen_above);
367         write_bool_option(ssi, "show_fullscreen_info", options->show_fullscreen_info);
368         write_char_option(ssi, "fullscreen_info", options->fullscreen_info);
369         secure_fputc(ssi, '\n');
370
371         write_int_option(ssi, "custom_similarity_threshold", options->dupe_custom_threshold);
372
373         secure_fprintf(ssi, "\n##### Slideshow Options #####\n\n");
374
375         write_int_unit_option(ssi, "slideshow_delay", options->slideshow_delay, SLIDESHOW_SUBSECOND_PRECISION);
376
377         write_bool_option(ssi, "slideshow_random", options->slideshow_random);
378         write_bool_option(ssi, "slideshow_repeat", options->slideshow_repeat);
379
380         secure_fprintf(ssi, "\n##### Filtering Options #####\n\n");
381
382         write_bool_option(ssi, "show_dotfiles", options->show_dot_files);
383         write_bool_option(ssi, "disable_filtering", options->file_filter_disable);
384         
385         filter_write_list(ssi);
386         
387         sidecar_ext_write(ssi);
388
389         secure_fprintf(ssi, "\n##### Color Profiles #####\n\n");
390
391 #ifndef HAVE_LCMS
392         secure_fprintf(ssi, "# NOTICE: %s was not built with support for color profiles,\n"
393                            "#         color profile options will have no effect.\n\n", GQ_APPNAME);
394 #endif
395
396         write_bool_option(ssi, "color_profile_enabled", color_profile_enabled);
397         write_bool_option(ssi, "color_profile_use_image", color_profile_use_image);
398         write_int_option(ssi, "color_profile_input_type", color_profile_input_type);
399         for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
400                 {
401                 gchar *buf;
402
403                 buf = g_strdup_printf("color_profile_input_file_%d", i + 1);
404                 write_char_option(ssi, buf, color_profile_input_file[i]);
405                 g_free(buf);
406
407                 buf = g_strdup_printf("color_profile_input_name_%d", i + 1);
408                 write_char_option(ssi, buf, color_profile_input_name[i]);
409                 g_free(buf);
410                 }
411         secure_fputc(ssi, '\n');
412         write_int_option(ssi, "color_profile_screen_type", color_profile_screen_type);
413         write_char_option(ssi, "color_profile_screen_file_1", color_profile_screen_file);
414
415         secure_fprintf(ssi, "\n##### External Programs #####\n");
416         secure_fprintf(ssi, "# Maximum of 10 programs (external_1 through external_10)\n");
417         secure_fprintf(ssi, "# format: external_n: \"menu name\" \"command line\"\n\n");
418
419         for (i = 0; i < GQ_EDITOR_SLOTS; i++)
420                 {
421                 gchar *qname = escquote_value(options->editor_name[i]);
422                 gchar *qcommand = escquote_value(options->editor_command[i]);
423                 secure_fprintf(ssi, "external_%d: %s %s\n", i+1, qname, qcommand);
424                 g_free(qname);
425                 g_free(qcommand);
426                 }
427
428         secure_fprintf(ssi, "\n##### Collection Options #####\n\n");
429
430         write_bool_option(ssi, "rectangular_selections", options->collection_rectangular_selection);
431
432         secure_fprintf(ssi, "\n##### Window Positions #####\n\n");
433
434         write_bool_option(ssi, "restore_window_positions", options->save_window_positions);
435         secure_fputc(ssi, '\n');
436         write_int_option(ssi, "main_window_x", options->main_window_x);
437         write_int_option(ssi, "main_window_y", options->main_window_y);
438         write_int_option(ssi, "main_window_width", options->main_window_w);
439         write_int_option(ssi, "main_window_height", options->main_window_h);
440         write_bool_option(ssi, "main_window_maximized", options->main_window_maximized);
441         write_int_option(ssi, "float_window_x", options->float_window_x);
442         write_int_option(ssi, "float_window_y", options->float_window_y);
443         write_int_option(ssi, "float_window_width", options->float_window_w);
444         write_int_option(ssi, "float_window_height", options->float_window_h);
445         write_int_option(ssi, "float_window_divider", options->float_window_divider);
446         write_int_option(ssi, "divider_position_h", options->window_hdivider_pos);
447         write_int_option(ssi, "divider_position_v", options->window_vdivider_pos);
448
449         secure_fprintf(ssi, "\n##### Exif #####\n# 0: never\n# 1: if set\n# 2: always\n\n");
450         for (i = 0; ExifUIList[i].key; i++)
451                 {
452                 secure_fprintf(ssi, "exif_");
453                 write_int_option(ssi, (gchar *)ExifUIList[i].key, ExifUIList[i].current);
454                 }
455
456         secure_fputc(ssi, '\n');
457         secure_fprintf(ssi, "######################################################################\n");
458         secure_fprintf(ssi, "#                         end of config file                         #\n");
459         secure_fprintf(ssi, "######################################################################\n");
460
461         
462         if (secure_close(ssi))
463                 {
464                 gchar *buf;
465
466                 buf = g_strdup_printf(_("error saving config file: %s\nerror: %s\n"), rc_path,
467                                       secsave_strerror(secsave_errno));
468                 print_term(buf);
469                 g_free(buf);
470
471                 g_free(rc_path);
472                 return;
473                 }
474
475         g_free(rc_path);
476 }
477
478 /*
479  *-----------------------------------------------------------------------------
480  * load configuration (public)
481  *-----------------------------------------------------------------------------
482  */ 
483
484 void load_options(void)
485 {
486         FILE *f;
487         gchar *rc_path;
488         gchar *rc_pathl;
489         gchar s_buf[1024];
490         gchar *s_buf_ptr;
491         gchar option[1024];
492         gchar value[1024];
493         gchar value_all[1024];
494         gint c,l,i;
495
496         for (i = 0; ExifUIList[i].key; i++)
497                 ExifUIList[i].current = ExifUIList[i].default_value;
498
499         rc_path = g_strconcat(homedir(), "/", GQ_RC_DIR, "/", RC_FILE_NAME, NULL);
500
501         rc_pathl = path_from_utf8(rc_path);
502         f = fopen(rc_pathl,"r");
503         g_free(rc_pathl);
504         if (!f)
505                 {
506                 g_free(rc_path);
507                 return;
508                 }
509
510         while (fgets(s_buf,1024,f))
511                 {
512                 if (s_buf[0]=='#') continue;
513                 if (s_buf[0]=='\n') continue;
514                 c = 0;
515                 l = strlen(s_buf);
516                 while (s_buf[c] != ':' && c < l) c++;
517                 if (c >= l) continue;
518                 s_buf[c] = '\0';
519                 c++;
520                 while ((s_buf[c] == ' ' || s_buf[c] == 8) && c < l) c++;
521                 s_buf_ptr = s_buf + c;
522                 strncpy(value_all, s_buf_ptr, sizeof(value_all));
523                 while (s_buf[c] != 8 && s_buf[c] != ' ' && s_buf[c] != '\n' && c < l) c++;
524                 s_buf[c] = '\0';
525                 strncpy(option, s_buf, sizeof(option));
526                 strncpy(value, s_buf_ptr, sizeof(value));
527
528                 /* general options */
529
530                 layout_style = read_int_option(f, option,
531                         "layout_style", value, layout_style);
532                 layout_order = read_char_option(f, option,
533                         "layout_order", value, layout_order);
534                 layout_view_icons = read_bool_option(f, option,
535                         "layout_view_as_icons", value, layout_view_icons);
536                 layout_view_tree = read_bool_option(f, option,
537                         "layout_view_as_tree", value, layout_view_tree);
538                 show_icon_names = read_bool_option(f, option,
539                         "show_icon_names", value, show_icon_names);
540
541                 tree_descend_subdirs = read_bool_option(f, option,
542                         "tree_descend_folders", value, tree_descend_subdirs);
543                 lazy_image_sync = read_bool_option(f, option,
544                         "lazy_image_sync", value, lazy_image_sync);
545                 update_on_time_change = read_bool_option(f, option,
546                         "update_on_time_change", value, update_on_time_change);
547                 exif_rotate_enable = read_bool_option(f, option,
548                         "exif_auto_rotate", value, exif_rotate_enable);
549
550                 options->startup_path_enable = read_bool_option(f, option,
551                         "enable_startup_path", value, options->startup_path_enable);
552                 options->startup_path = read_char_option(f, option,
553                         "startup_path", value_all, options->startup_path);
554
555                 if (strcasecmp(option, "zoom_mode") == 0)
556                         {
557                         if (strcasecmp(value, "original") == 0) options->zoom_mode = ZOOM_RESET_ORIGINAL;
558                         if (strcasecmp(value, "fit") == 0) options->zoom_mode = ZOOM_RESET_FIT_WINDOW;
559                         if (strcasecmp(value, "dont_change") == 0) options->zoom_mode = ZOOM_RESET_NONE;
560                         }
561                 options->two_pass_zoom = read_bool_option(f, option,
562                         "two_pass_scaling", value, options->two_pass_zoom);
563                 options->zoom_to_fit_expands = read_bool_option(f, option,
564                         "zoom_to_fit_allow_expand", value, options->zoom_to_fit_expands);
565
566                 options->fit_window = read_bool_option(f, option,
567                         "fit_window_to_image", value, options->fit_window);
568                 options->limit_window_size = read_bool_option(f, option,
569                         "limit_window_size", value, options->limit_window_size);
570                 options->max_window_size = read_int_option(f, option,
571                         "max_window_size", value, options->max_window_size);
572                 options->limit_autofit_size = read_bool_option(f, option,
573                         "limit_autofit_size", value, options->limit_autofit_size);
574                 options->max_autofit_size = read_int_option(f, option,
575                         "max_autofit_size", value, options->max_autofit_size);
576                 options->progressive_key_scrolling = read_bool_option(f, option,
577                         "progressive_keyboard_scrolling", value, options->progressive_key_scrolling);
578                 options->scroll_reset_method = read_int_option(f, option,
579                         "scroll_reset_method", value, options->scroll_reset_method);
580
581                 options->thumbnails_enabled = read_bool_option(f, option,
582                         "enable_thumbnails", value, options->thumbnails_enabled);
583                 options->thumb_max_width = read_int_option(f, option,
584                         "thumbnail_width", value, options->thumb_max_width);
585                 if (options->thumb_max_width < 16) options->thumb_max_width = 16;
586                 options->thumb_max_height = read_int_option(f, option,
587                         "thumbnail_height", value, options->thumb_max_height);
588                 if (options->thumb_max_height < 16) options->thumb_max_height = 16;
589                 options->enable_thumb_caching = read_bool_option(f, option,
590                         "cache_thumbnails", value, options->enable_thumb_caching);
591                 options->enable_thumb_dirs = read_bool_option(f, option,
592                         "cache_thumbnails_into_dirs", value, options->enable_thumb_dirs);
593                 options->thumbnail_fast = read_bool_option(f, option,
594                         "thumbnail_fast", value, options->thumbnail_fast);
595                 options->use_xvpics_thumbnails = read_bool_option(f, option,
596                         "use_xvpics_thumbnails", value, options->use_xvpics_thumbnails);
597                 options->thumbnail_spec_standard = read_bool_option(f, option,
598                         "thumbnail_spec_standard", value, options->thumbnail_spec_standard);
599
600                 options->enable_metadata_dirs = read_bool_option(f, option,
601                         "local_metadata", value, options->enable_metadata_dirs);
602
603                 options->file_sort_method = (SortType)read_int_option(f, option,
604                         "sort_method", value, (gint)options->file_sort_method);
605                 options->file_sort_ascending = read_bool_option(f, option,
606                         "sort_ascending", value, options->file_sort_ascending);
607                 file_sort_case_sensitive = read_bool_option(f, option,
608                         "sort_case_sensitive", value, file_sort_case_sensitive);
609
610                 options->confirm_delete = read_bool_option(f, option,
611                         "confirm_delete", value, options->confirm_delete);
612                 options->enable_delete_key = read_bool_option(f, option,
613                         "enable_delete_key", value, options->enable_delete_key);
614                 options->safe_delete_enable = read_bool_option(f, option,
615                         "safe_delete",  value, options->safe_delete_enable);
616                 options->safe_delete_path = read_char_option(f, option,
617                         "safe_delete_path", value, options->safe_delete_path);
618                 options->safe_delete_size = read_int_option(f, option,
619                         "safe_delete_size", value,options->safe_delete_size);
620
621                 options->tools_float = read_bool_option(f, option,
622                         "tools_float", value, options->tools_float);
623                 options->tools_hidden = read_bool_option(f, option,
624                         "tools_hidden", value, options->tools_hidden);
625                 options->restore_tool = read_bool_option(f, option,
626                         "restore_tool_state", value, options->restore_tool);
627
628                 options->toolbar_hidden = read_bool_option(f, option,
629                         "toolbar_hidden", value, options->toolbar_hidden);
630
631                 options->mousewheel_scrolls = read_bool_option(f, option,
632                         "mouse_wheel_scrolls", value, options->mousewheel_scrolls);
633                 options->enable_in_place_rename = read_bool_option(f, option,
634                         "in_place_rename", value, options->enable_in_place_rename);
635
636                 options->recent_list_max = read_int_option(f, option,
637                         "open_recent_max", value, options->recent_list_max);
638
639                 options->tile_cache_max = read_int_option(f, option,
640                         "image_cache_size_max", value, options->tile_cache_max);
641
642                 options->thumbnail_quality = CLAMP(read_int_option(f, option,
643                         "thumbnail_quality", value, options->thumbnail_quality), GDK_INTERP_NEAREST, GDK_INTERP_HYPER);
644                 options->zoom_quality = CLAMP(read_int_option(f, option,
645                         "zoom_quality", value, options->zoom_quality), GDK_INTERP_NEAREST, GDK_INTERP_HYPER);
646                 options->dither_quality = CLAMP(read_int_option(f, option,
647                         "dither_quality", value, options->dither_quality), GDK_RGB_DITHER_NONE, GDK_RGB_DITHER_MAX);
648
649                 options->zoom_increment = read_int_option(f, option,
650                         "zoom_increment", value, options->zoom_increment);
651
652                 options->enable_read_ahead = read_bool_option(f, option,
653                         "enable_read_ahead", value, options->enable_read_ahead);
654
655                 options->place_dialogs_under_mouse = read_bool_option(f, option,
656                         "display_dialogs_under_mouse", value, options->place_dialogs_under_mouse);
657
658                 options->user_specified_window_background = read_bool_option(f, option,
659                         "user_specified_window_background", value, options->user_specified_window_background);
660                 read_color_option(f, option,
661                         "window_background_color", value, &options->window_background_color);
662
663                 options->fullscreen_screen = read_int_option(f, option,
664                         "fullscreen_screen", value, options->fullscreen_screen);
665                 options->fullscreen_clean_flip = read_bool_option(f, option,
666                         "fullscreen_clean_flip", value, options->fullscreen_clean_flip);
667                 options->fullscreen_disable_saver = read_bool_option(f, option,
668                         "fullscreen_disable_saver", value, options->fullscreen_disable_saver);
669                 options->fullscreen_above = read_bool_option(f, option,
670                         "fullscreen_above", value, options->fullscreen_above);
671                 options->show_fullscreen_info = read_bool_option(f, option,
672                         "show_fullscreen_info", value, options->show_fullscreen_info);
673                 options->fullscreen_info = read_char_option(f, option,
674                         "fullscreen_info", value_all, options->fullscreen_info);
675
676                 options->dupe_custom_threshold = read_int_option(f, option,
677                         "custom_similarity_threshold", value, options->dupe_custom_threshold);
678
679                 /* slideshow options */
680
681                 options->slideshow_delay = read_int_unit_option(f, option,
682                         "slideshow_delay", value, options->slideshow_delay, SLIDESHOW_SUBSECOND_PRECISION);
683                 options->slideshow_random = read_bool_option(f, option,
684                         "slideshow_random", value, options->slideshow_random);
685                 options->slideshow_repeat = read_bool_option(f, option,
686                         "slideshow_repeat", value, options->slideshow_repeat);
687
688                 /* filtering options */
689
690                 options->show_dot_files = read_bool_option(f, option,
691                         "show_dotfiles", value, options->show_dot_files);
692                 options->file_filter_disable = read_bool_option(f, option,
693                         "disable_filtering", value, options->file_filter_disable);
694
695                 if (strcasecmp(option, "filter_ext") == 0)
696                         {
697                         filter_parse(value_all);
698                         }
699
700                 if (strcasecmp(option, "sidecar_ext") == 0)
701                         {
702                         sidecar_ext_parse(value_all, TRUE);
703                         }
704                 
705                 /* Color Profiles */
706
707                 color_profile_enabled = read_bool_option(f, option,
708                         "color_profile_enabled", value, color_profile_enabled);
709                 color_profile_use_image = read_bool_option(f, option,
710                         "color_profile_use_image", value, color_profile_use_image);
711                 color_profile_input_type = read_int_option(f, option,
712                         "color_profile_input_type", value, color_profile_input_type);
713
714                 if (strncasecmp(option, "color_profile_input_file_", 25) == 0)
715                         {
716                         i = strtol(option + 25, NULL, 0) - 1;
717                         if (i >= 0 && i < COLOR_PROFILE_INPUTS)
718                                 {
719                                 color_profile_input_file[i] = read_char_option(f, option,
720                                         option, value, color_profile_input_file[i]);
721                                 }
722                         }
723                 if (strncasecmp(option, "color_profile_input_name_", 25) == 0)
724                         {
725                         i = strtol(option + 25, NULL, 0) - 1;
726                         if (i >= 0 && i < COLOR_PROFILE_INPUTS)
727                                 {
728                                 color_profile_input_name[i] = read_char_option(f, option,
729                                         option, value, color_profile_input_name[i]);
730                                 }
731                         }
732
733                 color_profile_screen_type = read_int_option(f, option,
734                         "color_profile_screen_type", value, color_profile_screen_type);
735                 color_profile_screen_file = read_char_option(f, option,
736                         "color_profile_screen_file_1", value, color_profile_screen_file);
737
738                 /* External Programs */
739
740                 if (strncasecmp(option, "external_", 9) == 0)
741                         {
742                         i = strtol(option + 9, NULL, 0);
743                         if (i > 0 && i <= GQ_EDITOR_SLOTS)
744                                 {
745                                 const gchar *ptr;
746                                 i--;
747                                 g_free(options->editor_name[i]);
748                                 g_free(options->editor_command[i]);
749                                 
750                                 options->editor_name[i] = quoted_value(value_all, &ptr);
751                                 options->editor_command[i] = quoted_value(ptr, NULL);
752                                 }
753                         }
754
755                 /* colection options */
756
757                 options->collection_rectangular_selection = read_bool_option(f, option,
758                         "rectangular_selections", value, options->collection_rectangular_selection);
759
760                 /* window positions */
761
762                 options->save_window_positions = read_bool_option(f, option,
763                         "restore_window_positions", value, options->save_window_positions);
764
765                 options->main_window_x = read_int_option(f, option,
766                         "main_window_x", value, options->main_window_x);
767                 options->main_window_y = read_int_option(f, option,
768                         "main_window_y", value, options->main_window_y);
769                 options->main_window_w = read_int_option(f, option,
770                         "main_window_width", value, options->main_window_w);
771                 options->main_window_h = read_int_option(f, option,
772                         "main_window_height", value, options->main_window_h);
773                 options->main_window_maximized = read_bool_option(f, option,
774                         "main_window_maximized", value, options->main_window_maximized);
775                 options->float_window_x = read_int_option(f, option,
776                         "float_window_x", value, options->float_window_x);
777                 options->float_window_y = read_int_option(f, option,
778                         "float_window_y", value, options->float_window_y);
779                 options->float_window_w = read_int_option(f, option,
780                         "float_window_width", value, options->float_window_w);
781                 options->float_window_h = read_int_option(f, option,
782                         "float_window_height", value, options->float_window_h);
783                 options->float_window_divider = read_int_option(f, option,
784                         "float_window_divider", value, options->float_window_divider);
785                 options->window_hdivider_pos = read_int_option(f, option,
786                         "divider_position_h", value,options-> window_hdivider_pos);
787                 options->window_vdivider_pos = read_int_option(f, option,
788                         "divider_position_v", value, options->window_vdivider_pos);
789
790                 if (0 == strncasecmp(option, "exif_", 5))
791                         {
792                         for (i = 0; ExifUIList[i].key; i++)
793                                 if (0 == strcasecmp(option+5, ExifUIList[i].key))
794                                         ExifUIList[i].current = strtol(value, NULL, 10);
795                         }
796                 }
797
798         fclose(f);
799         g_free(rc_path);
800 }
801