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