Rename window options (moved to layout) and re-order rc file.
[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_bool_option(ssi, "show_icon_names", options->show_icon_names);
279         secure_fputc(ssi, '\n');
280
281         write_bool_option(ssi, "tree_descend_folders", options->tree_descend_subdirs);
282         write_bool_option(ssi, "lazy_image_sync", options->lazy_image_sync);
283         write_bool_option(ssi, "update_on_time_change", options->update_on_time_change);
284         secure_fputc(ssi, '\n');
285
286         write_bool_option(ssi, "enable_startup_path", options->startup_path_enable);
287         write_char_option(ssi, "startup_path", options->startup_path);
288
289         write_bool_option(ssi, "progressive_keyboard_scrolling", options->progressive_key_scrolling);
290         write_bool_option(ssi, "local_metadata", options->enable_metadata_dirs);
291
292         write_bool_option(ssi, "confirm_delete", options->confirm_delete);
293         write_bool_option(ssi, "enable_delete_key", options->enable_delete_key);
294         write_bool_option(ssi, "safe_delete", options->safe_delete_enable);
295         write_char_option(ssi, "safe_delete_path", options->safe_delete_path);
296         write_int_option(ssi, "safe_delete_size", options->safe_delete_size);
297         secure_fputc(ssi, '\n');
298         
299         write_int_option(ssi, "custom_similarity_threshold", options->dupe_custom_threshold);
300         secure_fputc(ssi, '\n');
301
302         write_bool_option(ssi, "mouse_wheel_scrolls", options->mousewheel_scrolls);
303         write_bool_option(ssi, "in_place_rename", options->enable_in_place_rename);
304         write_int_option(ssi, "open_recent_max", options->recent_list_max);
305         write_bool_option(ssi, "display_dialogs_under_mouse", options->place_dialogs_under_mouse);
306         secure_fputc(ssi, '\n');
307
308         write_bool_option(ssi, "user_specified_window_background", options->user_specified_window_background);
309         write_color_option(ssi, "window_background_color", &options->window_background_color);
310
311
312         secure_fprintf(ssi, "\n##### Layout Options #####\n\n");
313
314         write_int_option(ssi, "layout.style", options->layout.style);
315         write_char_option(ssi, "layout.order", options->layout.order);
316         write_bool_option(ssi, "layout.view_as_icons", options->layout.view_as_icons);
317         write_bool_option(ssi, "layout.view_as_tree", options->layout.view_as_tree);
318         secure_fputc(ssi, '\n');
319
320         write_bool_option(ssi, "layout.save_window_positions", options->layout.save_window_positions);
321         secure_fputc(ssi, '\n');
322
323         write_int_option(ssi, "layout.main_window.x", options->layout.main_window.x);
324         write_int_option(ssi, "layout.main_window.y", options->layout.main_window.y);
325         write_int_option(ssi, "layout.main_window.w", options->layout.main_window.w);
326         write_int_option(ssi, "layout.main_window.h", options->layout.main_window.h);
327         write_bool_option(ssi, "layout.main_window.maximized", options->layout.main_window.maximized);
328         write_int_option(ssi, "layout.main_window.hdivider_pos", options->layout.main_window.hdivider_pos);
329         write_int_option(ssi, "layout.main_window.vdivider_pos", options->layout.main_window.vdivider_pos);
330         secure_fputc(ssi, '\n');
331
332         write_int_option(ssi, "layout.float_window.x", options->layout.float_window.x);
333         write_int_option(ssi, "layout.float_window.y", options->layout.float_window.y);
334         write_int_option(ssi, "layout.float_window.w", options->layout.float_window.w);
335         write_int_option(ssi, "layout.float_window.h", options->layout.float_window.h);
336         write_int_option(ssi, "layout.float_window.vdivider_pos", options->layout.float_window.vdivider_pos);
337         secure_fputc(ssi, '\n');
338
339         write_bool_option(ssi, "layout.tools_float", options->layout.tools_float);
340         write_bool_option(ssi, "layout.tools_hidden", options->layout.tools_hidden);
341         write_bool_option(ssi, "layout.tools_restore_state", options->layout.tools_restore_state);
342         secure_fputc(ssi, '\n');
343
344         write_bool_option(ssi, "layout.toolbar_hidden", options->layout.toolbar_hidden);
345
346
347         secure_fprintf(ssi, "\n##### Image Options #####\n\n");
348
349         secure_fprintf(ssi, "image.zoom_mode: ");
350         if (options->image.zoom_mode == ZOOM_RESET_ORIGINAL) secure_fprintf(ssi, "original\n");
351         if (options->image.zoom_mode == ZOOM_RESET_FIT_WINDOW) secure_fprintf(ssi, "fit\n");
352         if (options->image.zoom_mode == ZOOM_RESET_NONE) secure_fprintf(ssi, "dont_change\n");
353         write_bool_option(ssi, "image.zoom_2pass", options->image.zoom_2pass);
354         write_bool_option(ssi, "image.zoom_to_fit_allow_expand", options->image.zoom_to_fit_allow_expand);
355         write_int_option(ssi, "image.zoom_quality", options->image.zoom_quality);
356         write_int_option(ssi, "image.zoom_increment", options->image.zoom_increment);
357         write_bool_option(ssi, "image.fit_window_to_image", options->image.fit_window_to_image);
358         write_bool_option(ssi, "image.limit_window_size", options->image.limit_window_size);
359         write_int_option(ssi, "image.max_window_size", options->image.max_window_size);
360         write_bool_option(ssi, "image.limit_autofit_size", options->image.limit_autofit_size);
361         write_int_option(ssi, "image.max_autofit_size", options->image.max_autofit_size);
362         write_int_option(ssi, "image.scroll_reset_method", options->image.scroll_reset_method);
363         write_int_option(ssi, "image.tile_cache_max", options->image.tile_cache_max);
364         write_int_option(ssi, "image.dither_quality", options->image.dither_quality);
365         write_bool_option(ssi, "image.enable_read_ahead", options->image.enable_read_ahead);
366         write_bool_option(ssi, "image.exif_rotate_enable", options->image.exif_rotate_enable);
367
368
369         secure_fprintf(ssi, "\n##### Thumbnails Options #####\n\n");
370
371         write_bool_option(ssi, "thumbnails.enabled", options->thumbnails.enabled);
372         write_int_option(ssi, "thumbnails.max_width", options->thumbnails.max_width);
373         write_int_option(ssi, "thumbnails.max_height", options->thumbnails.max_height);
374         write_bool_option(ssi, "thumbnails.enable_caching", options->thumbnails.enable_caching);
375         write_bool_option(ssi, "thumbnails.cache_into_dirs", options->thumbnails.cache_into_dirs);
376         write_bool_option(ssi, "thumbnails.fast", options->thumbnails.fast);
377         write_bool_option(ssi, "thumbnails.use_xvpics", options->thumbnails.use_xvpics);
378         write_bool_option(ssi, "thumbnails.spec_standard", options->thumbnails.spec_standard);
379         write_int_option(ssi, "thumbnails.quality", options->thumbnails.quality);
380
381
382         secure_fprintf(ssi, "\n##### File sorting Options #####\n\n");
383
384         write_int_option(ssi, "file_sort.method", (gint)options->file_sort.method);
385         write_bool_option(ssi, "file_sort.ascending", options->file_sort.ascending);
386         write_bool_option(ssi, "file_sort.case_sensitive", options->file_sort.case_sensitive);
387
388         
389         secure_fprintf(ssi, "\n##### Fullscreen Options #####\n\n");
390
391         write_int_option(ssi, "fullscreen.screen", options->fullscreen.screen);
392         write_bool_option(ssi, "fullscreen.clean_flip", options->fullscreen.clean_flip);
393         write_bool_option(ssi, "fullscreen.disable_saver", options->fullscreen.disable_saver);
394         write_bool_option(ssi, "fullscreen.above", options->fullscreen.above);
395         write_bool_option(ssi, "fullscreen.show_info", options->fullscreen.show_info);
396         write_char_option(ssi, "fullscreen.info", options->fullscreen.info);
397
398         secure_fprintf(ssi, "\n##### Slideshow Options #####\n\n");
399
400         write_int_unit_option(ssi, "slideshow.delay", options->slideshow.delay, SLIDESHOW_SUBSECOND_PRECISION);
401         write_bool_option(ssi, "slideshow.random", options->slideshow.random);
402         write_bool_option(ssi, "slideshow.repeat", options->slideshow.repeat);
403
404
405         secure_fprintf(ssi, "\n##### Collection Options #####\n\n");
406
407         write_bool_option(ssi, "collections.rectangular_selection", options->collections.rectangular_selection);
408
409
410         secure_fprintf(ssi, "\n##### Filtering Options #####\n\n");
411
412         write_bool_option(ssi, "file_filter.show_dot_files", options->file_filter.show_dot_files);
413         write_bool_option(ssi, "file_filter.disable", options->file_filter.disable);
414         secure_fputc(ssi, '\n');
415
416         filter_write_list(ssi);
417         
418
419         secure_fprintf(ssi, "\n##### Sidecars Options #####\n\n");
420
421         sidecar_ext_write(ssi);
422
423
424         secure_fprintf(ssi, "\n##### Color Profiles #####\n\n");
425
426 #ifndef HAVE_LCMS
427         secure_fprintf(ssi, "# NOTICE: %s was not built with support for color profiles,\n"
428                            "#         color profile options will have no effect.\n\n", GQ_APPNAME);
429 #endif
430
431         write_bool_option(ssi, "color_profile.enabled", options->color_profile.enabled);
432         write_bool_option(ssi, "color_profile.use_image", options->color_profile.use_image);
433         write_int_option(ssi, "color_profile.input_type", options->color_profile.input_type);
434         secure_fputc(ssi, '\n');
435
436         for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
437                 {
438                 gchar *buf;
439
440                 buf = g_strdup_printf("color_profile.input_file_%d", i + 1);
441                 write_char_option(ssi, buf, options->color_profile.input_file[i]);
442                 g_free(buf);
443
444                 buf = g_strdup_printf("color_profile.input_name_%d", i + 1);
445                 write_char_option(ssi, buf, options->color_profile.input_name[i]);
446                 g_free(buf);
447                 }
448         secure_fputc(ssi, '\n');
449         write_int_option(ssi, "color_profile.screen_type", options->color_profile.screen_type);
450         write_char_option(ssi, "color_profile.screen_file", options->color_profile.screen_file);
451
452         secure_fprintf(ssi, "\n##### External Programs #####\n");
453         secure_fprintf(ssi, "# Maximum of 10 programs (external_1 through external_10)\n");
454         secure_fprintf(ssi, "# format: external_n: \"menu name\" \"command line\"\n\n");
455
456         for (i = 0; i < GQ_EDITOR_SLOTS; i++)
457                 {
458                 gchar *qname = escquote_value(options->editor_name[i]);
459                 gchar *qcommand = escquote_value(options->editor_command[i]);
460                 secure_fprintf(ssi, "external_%d: %s %s\n", i+1, qname, qcommand);
461                 g_free(qname);
462                 g_free(qcommand);
463                 }
464
465
466         secure_fprintf(ssi, "\n##### Exif #####\n# 0: never\n# 1: if set\n# 2: always\n\n");
467         for (i = 0; ExifUIList[i].key; i++)
468                 {
469                 secure_fprintf(ssi, "exif_");
470                 write_int_option(ssi, (gchar *)ExifUIList[i].key, ExifUIList[i].current);
471                 }
472
473         secure_fputc(ssi, '\n');
474         secure_fprintf(ssi, "######################################################################\n");
475         secure_fprintf(ssi, "#                         end of config file                         #\n");
476         secure_fprintf(ssi, "######################################################################\n");
477
478         
479         if (secure_close(ssi))
480                 {
481                 gchar *buf;
482
483                 buf = g_strdup_printf(_("error saving config file: %s\nerror: %s\n"), rc_path,
484                                       secsave_strerror(secsave_errno));
485                 print_term(buf);
486                 g_free(buf);
487
488                 g_free(rc_path);
489                 return;
490                 }
491
492         g_free(rc_path);
493 }
494
495 /*
496  *-----------------------------------------------------------------------------
497  * load configuration (public)
498  *-----------------------------------------------------------------------------
499  */ 
500
501 void load_options(void)
502 {
503         FILE *f;
504         gchar *rc_path;
505         gchar *rc_pathl;
506         gchar s_buf[1024];
507         gchar *s_buf_ptr;
508         gchar option[1024];
509         gchar value[1024];
510         gchar value_all[1024];
511         gint c,l,i;
512
513         for (i = 0; ExifUIList[i].key; i++)
514                 ExifUIList[i].current = ExifUIList[i].default_value;
515
516         rc_path = g_strconcat(homedir(), "/", GQ_RC_DIR, "/", RC_FILE_NAME, NULL);
517
518         rc_pathl = path_from_utf8(rc_path);
519         f = fopen(rc_pathl,"r");
520         g_free(rc_pathl);
521         if (!f)
522                 {
523                 g_free(rc_path);
524                 return;
525                 }
526
527         while (fgets(s_buf,1024,f))
528                 {
529                 if (s_buf[0]=='#') continue;
530                 if (s_buf[0]=='\n') continue;
531                 c = 0;
532                 l = strlen(s_buf);
533                 while (s_buf[c] != ':' && c < l) c++;
534                 if (c >= l) continue;
535                 s_buf[c] = '\0';
536                 c++;
537                 while ((s_buf[c] == ' ' || s_buf[c] == 8) && c < l) c++;
538                 s_buf_ptr = s_buf + c;
539                 strncpy(value_all, s_buf_ptr, sizeof(value_all));
540                 while (s_buf[c] != 8 && s_buf[c] != ' ' && s_buf[c] != '\n' && c < l) c++;
541                 s_buf[c] = '\0';
542                 strncpy(option, s_buf, sizeof(option));
543                 strncpy(value, s_buf_ptr, sizeof(value));
544
545                 /* layout options */
546
547                 options->layout.style = read_int_option(f, option,
548                         "layout.style", value, options->layout.style);
549                 options->layout.order = read_char_option(f, option,
550                         "layout.order", value, options->layout.order);
551                 options->layout.view_as_icons = read_bool_option(f, option,
552                         "layout.view_as_icons", value, options->layout.view_as_icons);
553                 options->layout.view_as_tree = read_bool_option(f, option,
554                         "layout.view_as_tree", value, options->layout.view_as_tree);
555                 /* window positions */
556
557                 options->layout.save_window_positions = read_bool_option(f, option,
558                         "layout.save_window_positions", value, options->layout.save_window_positions);
559
560                 options->layout.main_window.x = read_int_option(f, option,
561                         "layout.main_window.x", value, options->layout.main_window.x);
562                 options->layout.main_window.y = read_int_option(f, option,
563                         "layout.main_window.y", value, options->layout.main_window.y);
564                 options->layout.main_window.w = read_int_option(f, option,
565                         "layout.main_window.w", value, options->layout.main_window.w);
566                 options->layout.main_window.h = read_int_option(f, option,
567                         "layout.main_window.h", value, options->layout.main_window.h);
568                 options->layout.main_window.maximized = read_bool_option(f, option,
569                         "layout.main_window.maximized", value, options->layout.main_window.maximized);
570                 options->layout.float_window.x = read_int_option(f, option,
571                         "layout.float_window.x", value, options->layout.float_window.x);
572                 options->layout.float_window.y = read_int_option(f, option,
573                         "layout.float_window.y", value, options->layout.float_window.y);
574                 options->layout.float_window.w = read_int_option(f, option,
575                         "layout.float_window.w", value, options->layout.float_window.w);
576                 options->layout.float_window.h = read_int_option(f, option,
577                         "layout.float_window.h", value, options->layout.float_window.h);
578                 options->layout.float_window.vdivider_pos = read_int_option(f, option,
579                         "layout.float_window.vdivider_pos", value, options->layout.float_window.vdivider_pos);
580                 options->layout.main_window.hdivider_pos = read_int_option(f, option,
581                         "layout.main_window.hdivider_pos", value,options->layout.main_window.hdivider_pos);
582                 options->layout.main_window.vdivider_pos = read_int_option(f, option,
583                         "layout.main_window.vdivider_pos", value, options->layout.main_window.vdivider_pos);
584                 options->layout.tools_float = read_bool_option(f, option,
585                         "layout.tools_float", value, options->layout.tools_float);
586                 options->layout.tools_hidden = read_bool_option(f, option,
587                         "layout.tools_hidden", value, options->layout.tools_hidden);
588                 options->layout.tools_restore_state = read_bool_option(f, option,
589                         "layout.tools_restore_state", value, options->layout.tools_restore_state);
590                 options->layout.toolbar_hidden = read_bool_option(f, option,
591                         "layout.toolbar_hidden", value, options->layout.toolbar_hidden);
592
593
594                 /* general options */
595                 options->show_icon_names = read_bool_option(f, option,
596                         "show_icon_names", value, options->show_icon_names);
597
598                 options->tree_descend_subdirs = read_bool_option(f, option,
599                         "tree_descend_folders", value, options->tree_descend_subdirs);
600                 options->lazy_image_sync = read_bool_option(f, option,
601                         "lazy_image_sync", value, options->lazy_image_sync);
602                 options->update_on_time_change = read_bool_option(f, option,
603                         "update_on_time_change", value, options->update_on_time_change);
604         
605                 options->startup_path_enable = read_bool_option(f, option,
606                         "enable_startup_path", value, options->startup_path_enable);
607                 options->startup_path = read_char_option(f, option,
608                         "startup_path", value_all, options->startup_path);
609
610                 /* image options */
611                 if (strcasecmp(option, "image.zoom_mode") == 0)
612                         {
613                         if (strcasecmp(value, "original") == 0) options->image.zoom_mode = ZOOM_RESET_ORIGINAL;
614                         if (strcasecmp(value, "fit") == 0) options->image.zoom_mode = ZOOM_RESET_FIT_WINDOW;
615                         if (strcasecmp(value, "dont_change") == 0) options->image.zoom_mode = ZOOM_RESET_NONE;
616                         }
617                 options->image.zoom_2pass = read_bool_option(f, option,
618                         "image.zoom_2pass", value, options->image.zoom_2pass);
619                 options->image.zoom_to_fit_allow_expand = read_bool_option(f, option,
620                         "image.zoom_to_fit_allow_expand", value, options->image.zoom_to_fit_allow_expand);
621                 options->image.fit_window_to_image = read_bool_option(f, option,
622                         "image.fit_window_to_image", value, options->image.fit_window_to_image);
623                 options->image.limit_window_size = read_bool_option(f, option,
624                         "image.limit_window_size", value, options->image.limit_window_size);
625                 options->image.max_window_size = read_int_option(f, option,
626                         "image.max_window_size", value, options->image.max_window_size);
627                 options->image.limit_autofit_size = read_bool_option(f, option,
628                         "image.limit_autofit_size", value, options->image.limit_autofit_size);
629                 options->image.max_autofit_size = read_int_option(f, option,
630                         "image.max_autofit_size", value, options->image.max_autofit_size);
631                 options->image.scroll_reset_method = read_int_option(f, option,
632                         "image.scroll_reset_method", value, options->image.scroll_reset_method);
633                 options->image.tile_cache_max = read_int_option(f, option,
634                         "image.tile_cache_max", value, options->image.tile_cache_max);
635                 options->image.zoom_quality = CLAMP(read_int_option(f, option,
636                         "image.zoom_quality", value, options->image.zoom_quality), GDK_INTERP_NEAREST, GDK_INTERP_HYPER);
637                 options->image.dither_quality = CLAMP(read_int_option(f, option,
638                         "image.dither_quality", value, options->image.dither_quality), GDK_RGB_DITHER_NONE, GDK_RGB_DITHER_MAX);
639                 options->image.zoom_increment = read_int_option(f, option,
640                         "image.zoom_increment", value, options->image.zoom_increment);
641                 options->image.enable_read_ahead = read_bool_option(f, option,
642                         "image.enable_read_ahead", value, options->image.enable_read_ahead);
643                 options->image.exif_rotate_enable = read_bool_option(f, option,
644                         "image.exif_rotate_enable", value, options->image.exif_rotate_enable);
645
646                 options->progressive_key_scrolling = read_bool_option(f, option,
647                         "progressive_keyboard_scrolling", value, options->progressive_key_scrolling);
648
649
650                 /* thumbnails options */
651                 options->thumbnails.enabled = read_bool_option(f, option,
652                         "thumbnails.enabled", value, options->thumbnails.enabled);
653                 options->thumbnails.max_width = read_int_option(f, option,
654                         "thumbnails.max_width", value, options->thumbnails.max_width);
655                 if (options->thumbnails.max_width < 16) options->thumbnails.max_width = 16;
656                 options->thumbnails.max_height = read_int_option(f, option,
657                         "thumbnails.max_height", value, options->thumbnails.max_height);
658                 if (options->thumbnails.max_height < 16) options->thumbnails.max_height = 16;
659                 options->thumbnails.enable_caching = read_bool_option(f, option,
660                         "thumbnails.enable_caching", value, options->thumbnails.enable_caching);
661                 options->thumbnails.cache_into_dirs = read_bool_option(f, option,
662                         "thumbnails.cache_into_dirs", value, options->thumbnails.cache_into_dirs);
663                 options->thumbnails.fast = read_bool_option(f, option,
664                         "thumbnails.fast", value, options->thumbnails.fast);
665                 options->thumbnails.use_xvpics = read_bool_option(f, option,
666                         "thumbnails.use_xvpics", value, options->thumbnails.use_xvpics);
667                 options->thumbnails.spec_standard = read_bool_option(f, option,
668                         "thumbnails.spec_standard", value, options->thumbnails.spec_standard);
669                 options->thumbnails.quality = CLAMP(read_int_option(f, option,
670                         "thumbnails.quality", value, options->thumbnails.quality), GDK_INTERP_NEAREST, GDK_INTERP_HYPER);
671
672                 options->enable_metadata_dirs = read_bool_option(f, option,
673                         "local_metadata", value, options->enable_metadata_dirs);
674
675                 /* file sorting options */
676                 options->file_sort.method = (SortType)read_int_option(f, option,
677                         "file_sort.method", value, (gint)options->file_sort.method);
678                 options->file_sort.ascending = read_bool_option(f, option,
679                         "file_sort.ascending", value, options->file_sort.ascending);
680                 options->file_sort.case_sensitive = read_bool_option(f, option,
681                         "file_sort.case_sensitive", value, options->file_sort.case_sensitive);
682
683                 options->confirm_delete = read_bool_option(f, option,
684                         "confirm_delete", value, options->confirm_delete);
685                 options->enable_delete_key = read_bool_option(f, option,
686                         "enable_delete_key", value, options->enable_delete_key);
687                 options->safe_delete_enable = read_bool_option(f, option,
688                         "safe_delete",  value, options->safe_delete_enable);
689                 options->safe_delete_path = read_char_option(f, option,
690                         "safe_delete_path", value, options->safe_delete_path);
691                 options->safe_delete_size = read_int_option(f, option,
692                         "safe_delete_size", value,options->safe_delete_size);
693
694                 options->mousewheel_scrolls = read_bool_option(f, option,
695                         "mouse_wheel_scrolls", value, options->mousewheel_scrolls);
696                 options->enable_in_place_rename = read_bool_option(f, option,
697                         "in_place_rename", value, options->enable_in_place_rename);
698
699                 options->recent_list_max = read_int_option(f, option,
700                         "open_recent_max", value, options->recent_list_max);
701
702                 options->place_dialogs_under_mouse = read_bool_option(f, option,
703                         "display_dialogs_under_mouse", value, options->place_dialogs_under_mouse);
704
705                 options->user_specified_window_background = read_bool_option(f, option,
706                         "user_specified_window_background", value, options->user_specified_window_background);
707                 read_color_option(f, option,
708                         "window_background_color", value, &options->window_background_color);
709
710                 options->fullscreen.screen = read_int_option(f, option,
711                         "fullscreen.screen", value, options->fullscreen.screen);
712                 options->fullscreen.clean_flip = read_bool_option(f, option,
713                         "fullscreen.clean_flip", value, options->fullscreen.clean_flip);
714                 options->fullscreen.disable_saver = read_bool_option(f, option,
715                         "fullscreen.disable_saver", value, options->fullscreen.disable_saver);
716                 options->fullscreen.above = read_bool_option(f, option,
717                         "fullscreen.above", value, options->fullscreen.above);
718                 options->fullscreen.show_info = read_bool_option(f, option,
719                         "fullscreen.show_info", value, options->fullscreen.show_info);
720                 options->fullscreen.info = read_char_option(f, option,
721                         "fullscreen.info", value_all, options->fullscreen.info);
722
723                 options->dupe_custom_threshold = read_int_option(f, option,
724                         "custom_similarity_threshold", value, options->dupe_custom_threshold);
725
726                 /* slideshow options */
727
728                 options->slideshow.delay = read_int_unit_option(f, option,
729                         "slideshow.delay", value, options->slideshow.delay, SLIDESHOW_SUBSECOND_PRECISION);
730                 options->slideshow.random = read_bool_option(f, option,
731                         "slideshow.random", value, options->slideshow.random);
732                 options->slideshow.repeat = read_bool_option(f, option,
733                         "slideshow.repeat", value, options->slideshow.repeat);
734
735                 /* filtering options */
736
737                 options->file_filter.show_dot_files = read_bool_option(f, option,
738                         "file_filter.show_dot_files", value, options->file_filter.show_dot_files);
739                 options->file_filter.disable = read_bool_option(f, option,
740                         "file_filter.disable", value, options->file_filter.disable);
741
742                 if (strcasecmp(option, "file_filter.ext") == 0)
743                         {
744                         filter_parse(value_all);
745                         }
746
747                 if (strcasecmp(option, "sidecar_ext") == 0)
748                         {
749                         sidecar_ext_parse(value_all, TRUE);
750                         }
751                 
752                 /* Color Profiles */
753
754                 options->color_profile.enabled = read_bool_option(f, option,
755                         "color_profile.enabled", value, options->color_profile.enabled);
756                 options->color_profile.use_image = read_bool_option(f, option,
757                         "color_profile.use_image", value, options->color_profile.use_image);
758                 options->color_profile.input_type = read_int_option(f, option,
759                         "color_profile.input_type", value, options->color_profile.input_type);
760
761                 if (strncasecmp(option, "color_profile.input_file_", 25) == 0)
762                         {
763                         i = strtol(option + 25, NULL, 0) - 1;
764                         if (i >= 0 && i < COLOR_PROFILE_INPUTS)
765                                 {
766                                 options->color_profile.input_file[i] = read_char_option(f, option,
767                                         option, value, options->color_profile.input_file[i]);
768                                 }
769                         }
770                 if (strncasecmp(option, "color_profile.input_name_", 25) == 0)
771                         {
772                         i = strtol(option + 25, NULL, 0) - 1;
773                         if (i >= 0 && i < COLOR_PROFILE_INPUTS)
774                                 {
775                                 options->color_profile.input_name[i] = read_char_option(f, option,
776                                         option, value, options->color_profile.input_name[i]);
777                                 }
778                         }
779
780                 options->color_profile.screen_type = read_int_option(f, option,
781                         "color_profile.screen_type", value, options->color_profile.screen_type);
782                 options->color_profile.screen_file = read_char_option(f, option,
783                         "color_profile.screen_file", value, options->color_profile.screen_file);
784
785                 /* External Programs */
786
787                 if (strncasecmp(option, "external_", 9) == 0)
788                         {
789                         i = strtol(option + 9, NULL, 0);
790                         if (i > 0 && i <= GQ_EDITOR_SLOTS)
791                                 {
792                                 const gchar *ptr;
793                                 i--;
794                                 g_free(options->editor_name[i]);
795                                 g_free(options->editor_command[i]);
796                                 
797                                 options->editor_name[i] = quoted_value(value_all, &ptr);
798                                 options->editor_command[i] = quoted_value(ptr, NULL);
799                                 }
800                         }
801
802                 /* collection options */
803
804                 options->collections.rectangular_selection = read_bool_option(f, option,
805                         "collections.rectangular_selection", value, options->collections.rectangular_selection);
806
807                 if (0 == strncasecmp(option, "exif_", 5))
808                         {
809                         for (i = 0; ExifUIList[i].key; i++)
810                                 if (0 == strcasecmp(option+5, ExifUIList[i].key))
811                                         ExifUIList[i].current = strtol(value, NULL, 10);
812                         }
813                 }
814
815         fclose(f);
816         g_free(rc_path);
817 }
818