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