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