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