Preserve last histogram modes.
[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 "filefilter.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 && g_ascii_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 && g_ascii_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 && g_ascii_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 && g_ascii_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 && g_ascii_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 && g_ascii_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 && g_ascii_strcasecmp(option, label) == 0)
249                 {
250                 if (g_ascii_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         WRITE_BOOL(save_metadata_in_image_file);
318
319         WRITE_INT(duplicates_similarity_threshold);
320         WRITE_SEPARATOR();
321
322         WRITE_BOOL(mousewheel_scrolls);
323         WRITE_INT(open_recent_list_maxsize);
324         WRITE_INT(dnd_icon_size);
325         WRITE_BOOL(place_dialogs_under_mouse);
326
327
328         WRITE_SUBTITLE("File operations Options");
329
330         WRITE_BOOL(file_ops.enable_in_place_rename);
331         WRITE_BOOL(file_ops.confirm_delete);
332         WRITE_BOOL(file_ops.enable_delete_key);
333         WRITE_BOOL(file_ops.safe_delete_enable);
334         WRITE_CHAR(file_ops.safe_delete_path);
335         WRITE_INT(file_ops.safe_delete_folder_maxsize);
336
337
338         WRITE_SUBTITLE("Layout Options");
339
340         WRITE_INT(layout.style);
341         WRITE_CHAR(layout.order);
342         WRITE_UINT(layout.dir_view_type);
343         WRITE_UINT(layout.file_view_type);
344         WRITE_BOOL(layout.show_marks);
345         WRITE_BOOL(layout.show_thumbnails);
346         WRITE_SEPARATOR();
347
348         WRITE_BOOL(layout.save_window_positions);
349         WRITE_SEPARATOR();
350
351         WRITE_INT(layout.main_window.x);
352         WRITE_INT(layout.main_window.y);
353         WRITE_INT(layout.main_window.w);
354         WRITE_INT(layout.main_window.h);
355         WRITE_BOOL(layout.main_window.maximized);
356         WRITE_INT(layout.main_window.hdivider_pos);
357         WRITE_INT(layout.main_window.vdivider_pos);
358         WRITE_SEPARATOR();
359
360         WRITE_INT(layout.float_window.x);
361         WRITE_INT(layout.float_window.y);
362         WRITE_INT(layout.float_window.w);
363         WRITE_INT(layout.float_window.h);
364         WRITE_INT(layout.float_window.vdivider_pos);
365         WRITE_SEPARATOR();
366
367         WRITE_BOOL(layout.tools_float);
368         WRITE_BOOL(layout.tools_hidden);
369         WRITE_BOOL(layout.tools_restore_state);
370         WRITE_SEPARATOR();
371
372         WRITE_BOOL(layout.toolbar_hidden);
373
374         WRITE_SUBTITLE("Panels Options");
375
376         WRITE_BOOL(panels.exif.enabled);
377         WRITE_INT(panels.exif.width);
378         WRITE_BOOL(panels.info.enabled);
379         WRITE_INT(panels.info.width);
380         WRITE_BOOL(panels.sort.enabled);
381         WRITE_INT(panels.sort.action_state);
382         WRITE_INT(panels.sort.mode_state);
383         WRITE_INT(panels.sort.selection_state);
384
385         WRITE_SUBTITLE("Image Options");
386
387         secure_fprintf(ssi, "# image.zoom_mode possible values are:\n"
388                             "#   original\n"
389                             "#   fit\n"
390                             "#   dont_change\n");
391         secure_fprintf(ssi, "image.zoom_mode: ");
392         if (options->image.zoom_mode == ZOOM_RESET_ORIGINAL)
393                 secure_fprintf(ssi, "original\n");
394         else if (options->image.zoom_mode == ZOOM_RESET_FIT_WINDOW)
395                 secure_fprintf(ssi, "fit\n");
396         else if (options->image.zoom_mode == ZOOM_RESET_NONE)
397                 secure_fprintf(ssi, "dont_change\n");
398         WRITE_SEPARATOR();
399         WRITE_BOOL(image.zoom_2pass);
400         WRITE_BOOL(image.zoom_to_fit_allow_expand);
401         WRITE_INT(image.zoom_quality);
402         WRITE_INT(image.zoom_increment);
403         WRITE_BOOL(image.fit_window_to_image);
404         WRITE_BOOL(image.limit_window_size);
405         WRITE_INT(image.max_window_size);
406         WRITE_BOOL(image.limit_autofit_size);
407         WRITE_INT(image.max_autofit_size);
408         WRITE_INT(image.scroll_reset_method);
409         WRITE_INT(image.tile_cache_max);
410         WRITE_INT(image.dither_quality);
411         WRITE_BOOL(image.enable_read_ahead);
412         WRITE_BOOL(image.exif_rotate_enable);
413         WRITE_BOOL(image.use_custom_border_color);
414         WRITE_COLOR(image.border_color);
415         WRITE_INT(image.read_buffer_size);
416         WRITE_INT(image.idle_read_loop_count);
417
418         WRITE_SUBTITLE("Thumbnails Options");
419
420         WRITE_INT(thumbnails.max_width);
421         WRITE_INT(thumbnails.max_height);
422         WRITE_BOOL(thumbnails.enable_caching);
423         WRITE_BOOL(thumbnails.cache_into_dirs);
424         WRITE_BOOL(thumbnails.fast);
425         WRITE_BOOL(thumbnails.use_xvpics);
426         WRITE_BOOL(thumbnails.spec_standard);
427         WRITE_INT(thumbnails.quality);
428
429
430         WRITE_SUBTITLE("File sorting Options");
431
432         WRITE_INT(file_sort.method);
433         WRITE_BOOL(file_sort.ascending);
434         WRITE_BOOL(file_sort.case_sensitive);
435
436
437         WRITE_SUBTITLE("Fullscreen Options");
438
439         WRITE_INT(fullscreen.screen);
440         WRITE_BOOL(fullscreen.clean_flip);
441         WRITE_BOOL(fullscreen.disable_saver);
442         WRITE_BOOL(fullscreen.above);
443
444
445         WRITE_SUBTITLE("Histogram Options");
446         WRITE_UINT(histogram.last_channel_mode);
447         WRITE_UINT(histogram.last_log_mode);
448
449
450         WRITE_SUBTITLE("Image Overlay Options");
451         WRITE_BOOL(image_overlay.common.enabled);
452         WRITE_BOOL(image_overlay.common.show_at_startup);
453         WRITE_CHAR(image_overlay.common.template_string);
454
455
456         WRITE_SUBTITLE("Slideshow Options");
457
458         WRITE_INT_UNIT(slideshow.delay, SLIDESHOW_SUBSECOND_PRECISION);
459         WRITE_BOOL(slideshow.random);
460         WRITE_BOOL(slideshow.repeat);
461
462
463         WRITE_SUBTITLE("Collection Options");
464
465         WRITE_BOOL(collections.rectangular_selection);
466
467
468         WRITE_SUBTITLE("Filtering Options");
469
470         WRITE_BOOL(file_filter.show_hidden_files);
471         WRITE_BOOL(file_filter.show_dot_directory);
472         WRITE_BOOL(file_filter.disable);
473         WRITE_SEPARATOR();
474
475         filter_write_list(ssi);
476
477
478         WRITE_SUBTITLE("Sidecars Options");
479
480         sidecar_ext_write(ssi);
481
482
483         WRITE_SUBTITLE("Color Profiles");
484
485 #ifndef HAVE_LCMS
486         secure_fprintf(ssi, "# NOTICE: %s was not built with support for color profiles,\n"
487                             "#         color profile options will have no effect.\n\n", GQ_APPNAME);
488 #endif
489
490         WRITE_BOOL(color_profile.enabled);
491         WRITE_BOOL(color_profile.use_image);
492         WRITE_INT(color_profile.input_type);
493         WRITE_SEPARATOR();
494
495         for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
496                 {
497                 gchar *buf;
498
499                 buf = g_strdup_printf("color_profile.input_file_%d", i + 1);
500                 write_char_option(ssi, buf, options->color_profile.input_file[i]);
501                 g_free(buf);
502
503                 buf = g_strdup_printf("color_profile.input_name_%d", i + 1);
504                 write_char_option(ssi, buf, options->color_profile.input_name[i]);
505                 g_free(buf);
506                 }
507
508         WRITE_SEPARATOR();
509         WRITE_INT(color_profile.screen_type);
510         WRITE_CHAR(color_profile.screen_file);
511
512         WRITE_SUBTITLE("External Programs");
513         secure_fprintf(ssi, "# Maximum of %d programs (external_1 through external_%d)\n", GQ_EDITOR_GENERIC_SLOTS, GQ_EDITOR_GENERIC_SLOTS);
514         secure_fprintf(ssi, "# external_%d through external_%d are used for file ops\n", GQ_EDITOR_GENERIC_SLOTS + 1, GQ_EDITOR_SLOTS);
515         secure_fprintf(ssi, "# format: external_n: \"menu name\" \"command line\"\n\n");
516
517         for (i = 0; i < GQ_EDITOR_SLOTS; i++)
518                 {
519                 if (i == GQ_EDITOR_GENERIC_SLOTS) secure_fputc(ssi, '\n');
520                 gchar *qname = escquote_value(options->editor_name[i]);
521                 gchar *qcommand = escquote_value(options->editor_command[i]);
522                 secure_fprintf(ssi, "external_%d: %s %s\n", i+1, qname, qcommand);
523                 g_free(qname);
524                 g_free(qcommand);
525                 }
526
527
528         WRITE_SUBTITLE("Exif Options");
529         secure_fprintf(ssi, "# Display: 0: never\n"
530                             "#          1: if set\n"
531                             "#          2: always\n\n");
532         for (i = 0; ExifUIList[i].key; i++)
533                 {
534                 secure_fprintf(ssi, "exif.display.");
535                 write_int_option(ssi, (gchar *)ExifUIList[i].key, ExifUIList[i].current);
536                 }
537
538         WRITE_SEPARATOR();
539         WRITE_SEPARATOR();
540
541         secure_fprintf(ssi, "######################################################################\n");
542         secure_fprintf(ssi, "#                         end of config file                         #\n");
543         secure_fprintf(ssi, "######################################################################\n");
544
545
546         if (secure_close(ssi))
547                 printf_term(_("error saving config file: %s\nerror: %s\n"), rc_path,
548                             secsave_strerror(secsave_errno));
549
550         g_free(rc_path);
551 }
552
553 /*
554  *-----------------------------------------------------------------------------
555  * load configuration (public)
556  *-----------------------------------------------------------------------------
557  */
558
559 void load_options(void)
560 {
561         FILE *f;
562         gchar *rc_path;
563         gchar *rc_pathl;
564         gchar s_buf[1024];
565         gchar option[1024];
566         gchar value[1024];
567         gchar value_all[1024];
568         gint i;
569
570         for (i = 0; ExifUIList[i].key; i++)
571                 ExifUIList[i].current = ExifUIList[i].default_value;
572
573         rc_path = g_strconcat(homedir(), "/", GQ_RC_DIR, "/", RC_FILE_NAME, NULL);
574
575         rc_pathl = path_from_utf8(rc_path);
576         f = fopen(rc_pathl,"r");
577         g_free(rc_pathl);
578         if (!f)
579                 {
580                 g_free(rc_path);
581                 return;
582                 }
583
584         while (fgets(s_buf, sizeof(s_buf), f))
585                 {
586                 gchar *option_start, *value_start;
587                 gchar *p = s_buf;
588
589                 while (g_ascii_isspace(*p)) p++;
590                 if (!*p || *p == '\n' || *p == '#') continue;
591                 option_start = p;
592                 while (*p && *p != ':') p++;
593                 if (!*p) continue;
594                 *p = '\0';
595                 p++;
596                 strncpy(option, option_start, sizeof(option));
597                 while (g_ascii_isspace(*p)) p++;
598                 value_start = p;
599                 strncpy(value_all, value_start, sizeof(value_all));
600                 while (*p && !g_ascii_isspace(*p) && *p != '\n') p++;
601                 *p = '\0';
602                 strncpy(value, value_start, sizeof(value));
603
604 #define READ_BOOL(_name_) read_bool_option(f, option, #_name_, value, &options->_name_)
605 #define READ_INT(_name_) read_int_option(f, option, #_name_, value, &options->_name_)
606 #define READ_UINT(_name_) read_uint_option(f, option, #_name_, value, &options->_name_)
607 #define READ_INT_CLAMP(_name_, _min_, _max_) read_int_option_clamp(f, option, #_name_, value, &options->_name_, _min_, _max_)
608 #define READ_INT_UNIT(_name_, _unit_) read_int_unit_option(f, option, #_name_, value, &options->_name_, _unit_)
609 #define READ_CHAR(_name_) read_char_option(f, option, #_name_, value_all, &options->_name_)
610 #define READ_COLOR(_name_) read_color_option(f, option, #_name_, value, &options->_name_)
611
612 #define COMPAT_READ_BOOL(_oldname_, _name_) read_bool_option(f, option, #_oldname_, value, &options->_name_)
613 #define COMPAT_READ_INT(_oldname_, _name_) read_int_option(f, option, #_oldname_, value, &options->_name_)
614 #define COMPAT_READ_UINT(_oldname_, _name_) read_uint_option(f, option, #_oldname_, value, &options->_name_)
615 #define COMPAT_READ_INT_CLAMP(_oldname_, _name_, _min_, _max_) read_int_option_clamp(f, option, #_oldname_, value, &options->_name_, _min_, _max_)
616 #define COMPAT_READ_INT_UNIT(_oldname_, _name_, _unit_) read_int_unit_option(f, option, #_oldname_, value, &options->_name_, _unit_)
617 #define COMPAT_READ_CHAR(_oldname_, _name_) read_char_option(f, option, #_oldname_, value_all, &options->_name_)
618 #define COMPAT_READ_COLOR(_oldname_, _name_) read_color_option(f, option, #_oldname_, value, &options->_name_)
619
620                 /* general options */
621                 READ_BOOL(show_icon_names);
622                 READ_BOOL(show_copy_path);
623
624                 READ_BOOL(tree_descend_subdirs);
625                 READ_BOOL(lazy_image_sync);
626                 READ_BOOL(update_on_time_change);
627
628                 READ_BOOL(startup_path_enable);
629                 READ_CHAR(startup_path);
630
631                 READ_INT(duplicates_similarity_threshold);
632
633                 READ_BOOL(progressive_key_scrolling);
634
635                 READ_BOOL(enable_metadata_dirs);
636                 READ_BOOL(save_metadata_in_image_file);
637
638                 READ_BOOL(mousewheel_scrolls);
639
640                 READ_INT(open_recent_list_maxsize);
641                 READ_INT(dnd_icon_size);
642                 READ_BOOL(place_dialogs_under_mouse);
643
644
645                 /* layout options */
646
647                 READ_INT(layout.style);
648                 READ_CHAR(layout.order);
649                 
650                 COMPAT_READ_UINT(layout.view_as_icons, layout.file_view_type); /* 2008/05/03 */
651
652                 READ_UINT(layout.dir_view_type);
653                 READ_UINT(layout.file_view_type);
654                 READ_BOOL(layout.show_marks);
655                 READ_BOOL(layout.show_thumbnails);
656
657                 /* window positions */
658
659                 READ_BOOL(layout.save_window_positions);
660
661                 READ_INT(layout.main_window.x);
662                 READ_INT(layout.main_window.y);
663                 READ_INT(layout.main_window.w);
664                 READ_INT(layout.main_window.h);
665                 READ_BOOL(layout.main_window.maximized);
666                 READ_INT(layout.float_window.x);
667                 READ_INT(layout.float_window.y);
668                 READ_INT(layout.float_window.w);
669                 READ_INT(layout.float_window.h);
670                 READ_INT(layout.float_window.vdivider_pos);
671                 READ_INT(layout.main_window.hdivider_pos);
672                 READ_INT(layout.main_window.vdivider_pos);
673                 READ_BOOL(layout.tools_float);
674                 READ_BOOL(layout.tools_hidden);
675                 READ_BOOL(layout.tools_restore_state);
676                 READ_BOOL(layout.toolbar_hidden);
677
678                 /* panels */
679                 READ_BOOL(panels.exif.enabled);
680                 READ_INT_CLAMP(panels.exif.width, PANEL_MIN_WIDTH, PANEL_MAX_WIDTH);
681                 READ_BOOL(panels.info.enabled);
682                 READ_INT_CLAMP(panels.info.width, PANEL_MIN_WIDTH, PANEL_MAX_WIDTH);
683                 READ_BOOL(panels.sort.enabled);
684                 READ_INT(panels.sort.action_state);
685                 READ_INT(panels.sort.mode_state);
686                 READ_INT(panels.sort.selection_state);
687
688                 /* image options */
689                 if (g_ascii_strcasecmp(option, "image.zoom_mode") == 0)
690                         {
691                         if (g_ascii_strcasecmp(value, "original") == 0)
692                                 options->image.zoom_mode = ZOOM_RESET_ORIGINAL;
693                         else if (g_ascii_strcasecmp(value, "fit") == 0)
694                                 options->image.zoom_mode = ZOOM_RESET_FIT_WINDOW;
695                         else if (g_ascii_strcasecmp(value, "dont_change") == 0)
696                                 options->image.zoom_mode = ZOOM_RESET_NONE;
697                         }
698                 READ_BOOL(image.zoom_2pass);
699                 READ_BOOL(image.zoom_to_fit_allow_expand);
700                 READ_BOOL(image.fit_window_to_image);
701                 READ_BOOL(image.limit_window_size);
702                 READ_INT(image.max_window_size);
703                 READ_BOOL(image.limit_autofit_size);
704                 READ_INT(image.max_autofit_size);
705                 READ_INT(image.scroll_reset_method);
706                 READ_INT(image.tile_cache_max);
707                 READ_INT_CLAMP(image.zoom_quality, GDK_INTERP_NEAREST, GDK_INTERP_HYPER);
708                 READ_INT_CLAMP(image.dither_quality, GDK_RGB_DITHER_NONE, GDK_RGB_DITHER_MAX);
709                 READ_INT(image.zoom_increment);
710                 READ_BOOL(image.enable_read_ahead);
711                 READ_BOOL(image.exif_rotate_enable);
712                 READ_BOOL(image.use_custom_border_color);
713                 READ_COLOR(image.border_color);
714                 READ_INT_CLAMP(image.read_buffer_size, IMAGE_LOADER_READ_BUFFER_SIZE_MIN, IMAGE_LOADER_READ_BUFFER_SIZE_MAX);
715                 READ_INT_CLAMP(image.idle_read_loop_count, IMAGE_LOADER_IDLE_READ_LOOP_COUNT_MIN, IMAGE_LOADER_IDLE_READ_LOOP_COUNT_MAX);
716
717
718                 /* thumbnails options */
719                 READ_INT_CLAMP(thumbnails.max_width, 16, 512);
720                 READ_INT_CLAMP(thumbnails.max_height, 16, 512);
721
722                 READ_BOOL(thumbnails.enable_caching);
723                 READ_BOOL(thumbnails.cache_into_dirs);
724                 READ_BOOL(thumbnails.fast);
725                 READ_BOOL(thumbnails.use_xvpics);
726                 READ_BOOL(thumbnails.spec_standard);
727                 READ_INT_CLAMP(thumbnails.quality, GDK_INTERP_NEAREST, GDK_INTERP_HYPER);
728
729                 /* file sorting options */
730                 READ_UINT(file_sort.method);
731                 READ_BOOL(file_sort.ascending);
732                 READ_BOOL(file_sort.case_sensitive);
733
734                 /* file operations options */
735                 READ_BOOL(file_ops.enable_in_place_rename);
736                 READ_BOOL(file_ops.confirm_delete);
737                 READ_BOOL(file_ops.enable_delete_key);
738                 READ_BOOL(file_ops.safe_delete_enable);
739                 READ_CHAR(file_ops.safe_delete_path);
740                 READ_INT(file_ops.safe_delete_folder_maxsize);
741
742                 /* fullscreen options */
743                 READ_INT(fullscreen.screen);
744                 READ_BOOL(fullscreen.clean_flip);
745                 READ_BOOL(fullscreen.disable_saver);
746                 READ_BOOL(fullscreen.above);
747
748                 /* histogram */
749                 READ_UINT(histogram.last_channel_mode);
750                 READ_UINT(histogram.last_log_mode);
751
752                 /* image overlay */
753                 COMPAT_READ_BOOL(fullscreen.show_info, image_overlay.common.show_at_startup);
754                 COMPAT_READ_CHAR(fullscreen.info, image_overlay.common.template_string);
755                 READ_BOOL(image_overlay.common.enabled);
756                 READ_BOOL(image_overlay.common.show_at_startup);
757                 READ_CHAR(image_overlay.common.template_string);
758         
759                 /* slideshow options */
760                 READ_INT_UNIT(slideshow.delay, SLIDESHOW_SUBSECOND_PRECISION);
761                 READ_BOOL(slideshow.random);
762                 READ_BOOL(slideshow.repeat);
763
764                 /* collection options */
765
766                 READ_BOOL(collections.rectangular_selection);
767
768                 /* filtering options */
769
770                 READ_BOOL(file_filter.show_hidden_files);
771                 READ_BOOL(file_filter.show_dot_directory);
772                 READ_BOOL(file_filter.disable);
773
774                 if (g_ascii_strcasecmp(option, "file_filter.ext") == 0)
775                         {
776                         filter_parse(value_all);
777                         }
778
779                 if (g_ascii_strcasecmp(option, "sidecar.ext") == 0)
780                         {
781                         sidecar_ext_parse(value_all, TRUE);
782                         }
783
784                 /* Color Profiles */
785
786                 READ_BOOL(color_profile.enabled);
787                 READ_BOOL(color_profile.use_image);
788                 READ_INT(color_profile.input_type);
789
790                 if (g_ascii_strncasecmp(option, "color_profile.input_file_", 25) == 0)
791                         {
792                         i = strtol(option + 25, NULL, 0) - 1;
793                         if (i >= 0 && i < COLOR_PROFILE_INPUTS)
794                                 {
795                                 read_char_option(f, option, option, value, &options->color_profile.input_file[i]);
796                                 }
797                         }
798                 if (g_ascii_strncasecmp(option, "color_profile.input_name_", 25) == 0)
799                         {
800                         i = strtol(option + 25, NULL, 0) - 1;
801                         if (i >= 0 && i < COLOR_PROFILE_INPUTS)
802                                 {
803                                 read_char_option(f, option, option, value, &options->color_profile.input_name[i]);
804                                 }
805                         }
806
807                 READ_INT(color_profile.screen_type);
808                 READ_CHAR(color_profile.screen_file);
809
810                 /* External Programs */
811
812                 if (g_ascii_strncasecmp(option, "external_", 9) == 0)
813                         {
814                         i = strtol(option + 9, NULL, 0);
815                         if (i > 0 && i <= GQ_EDITOR_SLOTS)
816                                 {
817                                 const gchar *ptr;
818                                 i--;
819                                 g_free(options->editor_name[i]);
820                                 g_free(options->editor_command[i]);
821
822                                 options->editor_name[i] = quoted_value(value_all, &ptr);
823                                 options->editor_command[i] = quoted_value(ptr, NULL);
824                                 }
825                         }
826
827                 /* Exif */
828                 if (0 == g_ascii_strncasecmp(option, "exif.display.", 13))
829                         {
830                         for (i = 0; ExifUIList[i].key; i++)
831                                 if (0 == g_ascii_strcasecmp(option + 13, ExifUIList[i].key))
832                                         ExifUIList[i].current = strtol(value, NULL, 10);
833                         }
834                 }
835
836         fclose(f);
837         g_free(rc_path);
838 }