sidecar_ext -> sidecar.ext
[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 gchar *read_char_option(FILE *f, gchar *option, gchar *label, gchar *value, gchar *text)
118 {
119         if (strcasecmp(option, label) == 0)
120                 {
121                 g_free(text);
122                 text = quoted_value(value, NULL);
123                 }
124         return text;
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 GdkColor *read_color_option(FILE *f, gchar *option, gchar *label, gchar *value, GdkColor *color)
148 {
149         if (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         return color;
156 }
157
158
159 static void write_int_option(SecureSaveInfo *ssi, gchar *label, gint n)
160 {
161         secure_fprintf(ssi, "%s: %d\n", label, n);
162 }
163
164 static gint read_int_option(FILE *f, gchar *option, gchar *label, gchar *value, gint n)
165 {
166         if (strcasecmp(option, label) == 0)
167                 {
168                 n = strtol(value, NULL, 10);
169                 }
170         return n;
171 }
172
173 static void write_int_unit_option(SecureSaveInfo *ssi, gchar *label, gint n, gint subunits)
174 {
175         gint l, r;
176
177         if (subunits > 0)
178                 {
179                 l = n / subunits;
180                 r = n % subunits;
181                 }
182         else
183                 {
184                 l = n;
185                 r = 0;
186                 }
187
188         secure_fprintf(ssi, "%s: %d.%d\n", label, l, r);
189 }
190
191 static gint read_int_unit_option(FILE *f, gchar *option, gchar *label, gchar *value, gint n, gint subunits)
192 {
193         if (strcasecmp(option, label) == 0)
194                 {
195                 gint l, r;
196                 gchar *ptr;
197
198                 ptr = value;
199                 while (*ptr != '\0' && *ptr != '.') ptr++;
200                 if (*ptr == '.')
201                         {
202                         *ptr = '\0';
203                         l = strtol(value, NULL, 10);
204                         *ptr = '.';
205                         ptr++;
206                         r = strtol(ptr, NULL, 10);
207                         }
208                 else
209                         {
210                         l = strtol(value, NULL, 10);
211                         r = 0;
212                         }
213
214                 n = l * subunits + r;
215                 }
216         return n;
217 }
218
219 static void write_bool_option(SecureSaveInfo *ssi, gchar *label, gint n)
220 {
221         secure_fprintf(ssi, "%s: ", label);
222         if (n) secure_fprintf(ssi, "true\n"); else secure_fprintf(ssi, "false\n");
223 }
224
225 static gint read_bool_option(FILE *f, gchar *option, gchar *label, gchar *value, gint n)
226 {
227         if (strcasecmp(option, label) == 0)
228                 {
229                 if (strcasecmp(value, "true") == 0)
230                         n = TRUE;
231                 else
232                         n = FALSE;
233                 }
234         return n;
235 }
236
237 /*
238  *-----------------------------------------------------------------------------
239  * save configuration (public)
240  *-----------------------------------------------------------------------------
241  */ 
242
243 void save_options(void)
244 {
245         SecureSaveInfo *ssi;
246         gchar *rc_path;
247         gchar *rc_pathl;
248         gint i;
249
250         rc_path = g_strconcat(homedir(), "/", GQ_RC_DIR, "/", RC_FILE_NAME, NULL);
251
252         rc_pathl = path_from_utf8(rc_path);
253         ssi = secure_open(rc_pathl);
254         g_free(rc_pathl);
255         if (!ssi)
256                 {
257                 gchar *buf;
258
259                 buf = g_strdup_printf(_("error saving config file: %s\n"), rc_path);
260                 print_term(buf);
261                 g_free(buf);
262
263                 g_free(rc_path);
264                 return;
265                 }
266         
267         secure_fprintf(ssi, "######################################################################\n");
268         secure_fprintf(ssi, "# %30s config file         version %7s #\n", GQ_APPNAME, VERSION);
269         secure_fprintf(ssi, "######################################################################\n");
270         secure_fputc(ssi, '\n');
271
272         secure_fprintf(ssi, "# Note: This file is autogenerated. Options can be changed here,\n");
273         secure_fprintf(ssi, "#       but user comments and formatting will be lost.\n");
274         secure_fputc(ssi, '\n');
275
276         secure_fprintf(ssi, "##### General Options #####\n\n");
277
278         write_bool_option(ssi, "show_icon_names", options->show_icon_names);
279         secure_fputc(ssi, '\n');
280
281         write_bool_option(ssi, "tree_descend_subdirs", options->tree_descend_subdirs);
282         write_bool_option(ssi, "lazy_image_sync", options->lazy_image_sync);
283         write_bool_option(ssi, "update_on_time_change", options->update_on_time_change);
284         secure_fputc(ssi, '\n');
285
286         write_bool_option(ssi, "startup_path_enable", options->startup_path_enable);
287         write_char_option(ssi, "startup_path", options->startup_path);
288
289         write_bool_option(ssi, "progressive_key_scrolling", options->progressive_key_scrolling);
290         write_bool_option(ssi, "enable_metadata_dirs", options->enable_metadata_dirs);
291
292         write_int_option(ssi, "duplicates_similarity_threshold", options->duplicates_similarity_threshold);
293         secure_fputc(ssi, '\n');
294
295         write_bool_option(ssi, "mousewheel_scrolls", options->mousewheel_scrolls);
296         write_int_option(ssi, "open_recent_list_maxsize", options->open_recent_list_maxsize);
297         write_bool_option(ssi, "place_dialogs_under_mouse", options->place_dialogs_under_mouse);
298
299
300         secure_fprintf(ssi, "\n##### File operations Options #####\n\n");
301
302         write_bool_option(ssi, "file_ops.enable_in_place_rename", options->file_ops.enable_in_place_rename);
303         write_bool_option(ssi, "file_ops.confirm_delete", options->file_ops.confirm_delete);
304         write_bool_option(ssi, "file_ops.enable_delete_key", options->file_ops.enable_delete_key);
305         write_bool_option(ssi, "file_ops.safe_delete_enable", options->file_ops.safe_delete_enable);
306         write_char_option(ssi, "file_ops.safe_delete_path", options->file_ops.safe_delete_path);
307         write_int_option(ssi, "file_ops.safe_delete_folder_maxsize", options->file_ops.safe_delete_folder_maxsize);
308
309         
310         secure_fprintf(ssi, "\n##### Layout Options #####\n\n");
311
312         write_int_option(ssi, "layout.style", options->layout.style);
313         write_char_option(ssi, "layout.order", options->layout.order);
314         write_bool_option(ssi, "layout.view_as_icons", options->layout.view_as_icons);
315         write_bool_option(ssi, "layout.view_as_tree", options->layout.view_as_tree);
316         write_bool_option(ssi, "layout.show_thumbnails", options->layout.show_thumbnails);
317         secure_fputc(ssi, '\n');
318
319         write_bool_option(ssi, "layout.save_window_positions", options->layout.save_window_positions);
320         secure_fputc(ssi, '\n');
321
322         write_int_option(ssi, "layout.main_window.x", options->layout.main_window.x);
323         write_int_option(ssi, "layout.main_window.y", options->layout.main_window.y);
324         write_int_option(ssi, "layout.main_window.w", options->layout.main_window.w);
325         write_int_option(ssi, "layout.main_window.h", options->layout.main_window.h);
326         write_bool_option(ssi, "layout.main_window.maximized", options->layout.main_window.maximized);
327         write_int_option(ssi, "layout.main_window.hdivider_pos", options->layout.main_window.hdivider_pos);
328         write_int_option(ssi, "layout.main_window.vdivider_pos", options->layout.main_window.vdivider_pos);
329         secure_fputc(ssi, '\n');
330
331         write_int_option(ssi, "layout.float_window.x", options->layout.float_window.x);
332         write_int_option(ssi, "layout.float_window.y", options->layout.float_window.y);
333         write_int_option(ssi, "layout.float_window.w", options->layout.float_window.w);
334         write_int_option(ssi, "layout.float_window.h", options->layout.float_window.h);
335         write_int_option(ssi, "layout.float_window.vdivider_pos", options->layout.float_window.vdivider_pos);
336         secure_fputc(ssi, '\n');
337
338         write_bool_option(ssi, "layout.tools_float", options->layout.tools_float);
339         write_bool_option(ssi, "layout.tools_hidden", options->layout.tools_hidden);
340         write_bool_option(ssi, "layout.tools_restore_state", options->layout.tools_restore_state);
341         secure_fputc(ssi, '\n');
342
343         write_bool_option(ssi, "layout.toolbar_hidden", options->layout.toolbar_hidden);
344
345
346         secure_fprintf(ssi, "\n##### Image Options #####\n\n");
347
348         secure_fprintf(ssi, "image.zoom_mode: ");
349         if (options->image.zoom_mode == ZOOM_RESET_ORIGINAL) secure_fprintf(ssi, "original\n");
350         if (options->image.zoom_mode == ZOOM_RESET_FIT_WINDOW) secure_fprintf(ssi, "fit\n");
351         if (options->image.zoom_mode == ZOOM_RESET_NONE) secure_fprintf(ssi, "dont_change\n");
352         write_bool_option(ssi, "image.zoom_2pass", options->image.zoom_2pass);
353         write_bool_option(ssi, "image.zoom_to_fit_allow_expand", options->image.zoom_to_fit_allow_expand);
354         write_int_option(ssi, "image.zoom_quality", options->image.zoom_quality);
355         write_int_option(ssi, "image.zoom_increment", options->image.zoom_increment);
356         write_bool_option(ssi, "image.fit_window_to_image", options->image.fit_window_to_image);
357         write_bool_option(ssi, "image.limit_window_size", options->image.limit_window_size);
358         write_int_option(ssi, "image.max_window_size", options->image.max_window_size);
359         write_bool_option(ssi, "image.limit_autofit_size", options->image.limit_autofit_size);
360         write_int_option(ssi, "image.max_autofit_size", options->image.max_autofit_size);
361         write_int_option(ssi, "image.scroll_reset_method", options->image.scroll_reset_method);
362         write_int_option(ssi, "image.tile_cache_max", options->image.tile_cache_max);
363         write_int_option(ssi, "image.dither_quality", options->image.dither_quality);
364         write_bool_option(ssi, "image.enable_read_ahead", options->image.enable_read_ahead);
365         write_bool_option(ssi, "image.exif_rotate_enable", options->image.exif_rotate_enable);
366         write_bool_option(ssi, "image.use_custom_border_color", options->image.use_custom_border_color);
367         write_color_option(ssi, "image.border_color", &options->image.border_color);
368
369
370         secure_fprintf(ssi, "\n##### Thumbnails Options #####\n\n");
371
372         write_int_option(ssi, "thumbnails.max_width", options->thumbnails.max_width);
373         write_int_option(ssi, "thumbnails.max_height", options->thumbnails.max_height);
374         write_bool_option(ssi, "thumbnails.enable_caching", options->thumbnails.enable_caching);
375         write_bool_option(ssi, "thumbnails.cache_into_dirs", options->thumbnails.cache_into_dirs);
376         write_bool_option(ssi, "thumbnails.fast", options->thumbnails.fast);
377         write_bool_option(ssi, "thumbnails.use_xvpics", options->thumbnails.use_xvpics);
378         write_bool_option(ssi, "thumbnails.spec_standard", options->thumbnails.spec_standard);
379         write_int_option(ssi, "thumbnails.quality", options->thumbnails.quality);
380
381
382         secure_fprintf(ssi, "\n##### File sorting Options #####\n\n");
383
384         write_int_option(ssi, "file_sort.method", (gint)options->file_sort.method);
385         write_bool_option(ssi, "file_sort.ascending", options->file_sort.ascending);
386         write_bool_option(ssi, "file_sort.case_sensitive", options->file_sort.case_sensitive);
387
388         
389         secure_fprintf(ssi, "\n##### Fullscreen Options #####\n\n");
390
391         write_int_option(ssi, "fullscreen.screen", options->fullscreen.screen);
392         write_bool_option(ssi, "fullscreen.clean_flip", options->fullscreen.clean_flip);
393         write_bool_option(ssi, "fullscreen.disable_saver", options->fullscreen.disable_saver);
394         write_bool_option(ssi, "fullscreen.above", options->fullscreen.above);
395         write_bool_option(ssi, "fullscreen.show_info", options->fullscreen.show_info);
396         write_char_option(ssi, "fullscreen.info", options->fullscreen.info);
397
398         secure_fprintf(ssi, "\n##### Slideshow Options #####\n\n");
399
400         write_int_unit_option(ssi, "slideshow.delay", options->slideshow.delay, SLIDESHOW_SUBSECOND_PRECISION);
401         write_bool_option(ssi, "slideshow.random", options->slideshow.random);
402         write_bool_option(ssi, "slideshow.repeat", options->slideshow.repeat);
403
404
405         secure_fprintf(ssi, "\n##### Collection Options #####\n\n");
406
407         write_bool_option(ssi, "collections.rectangular_selection", options->collections.rectangular_selection);
408
409
410         secure_fprintf(ssi, "\n##### Filtering Options #####\n\n");
411
412         write_bool_option(ssi, "file_filter.show_dot_files", options->file_filter.show_dot_files);
413         write_bool_option(ssi, "file_filter.disable", options->file_filter.disable);
414         secure_fputc(ssi, '\n');
415
416         filter_write_list(ssi);
417         
418
419         secure_fprintf(ssi, "\n##### Sidecars Options #####\n\n");
420
421         sidecar_ext_write(ssi);
422
423
424         secure_fprintf(ssi, "\n##### Color Profiles #####\n\n");
425
426 #ifndef HAVE_LCMS
427         secure_fprintf(ssi, "# NOTICE: %s was not built with support for color profiles,\n"
428                            "#         color profile options will have no effect.\n\n", GQ_APPNAME);
429 #endif
430
431         write_bool_option(ssi, "color_profile.enabled", options->color_profile.enabled);
432         write_bool_option(ssi, "color_profile.use_image", options->color_profile.use_image);
433         write_int_option(ssi, "color_profile.input_type", options->color_profile.input_type);
434         secure_fputc(ssi, '\n');
435
436         for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
437                 {
438                 gchar *buf;
439
440                 buf = g_strdup_printf("color_profile.input_file_%d", i + 1);
441                 write_char_option(ssi, buf, options->color_profile.input_file[i]);
442                 g_free(buf);
443
444                 buf = g_strdup_printf("color_profile.input_name_%d", i + 1);
445                 write_char_option(ssi, buf, options->color_profile.input_name[i]);
446                 g_free(buf);
447                 }
448         secure_fputc(ssi, '\n');
449         write_int_option(ssi, "color_profile.screen_type", options->color_profile.screen_type);
450         write_char_option(ssi, "color_profile.screen_file", options->color_profile.screen_file);
451
452         secure_fprintf(ssi, "\n##### External Programs #####\n");
453         secure_fprintf(ssi, "# Maximum of 10 programs (external_1 through external_10)\n");
454         secure_fprintf(ssi, "# format: external_n: \"menu name\" \"command line\"\n\n");
455
456         for (i = 0; i < GQ_EDITOR_SLOTS; i++)
457                 {
458                 gchar *qname = escquote_value(options->editor_name[i]);
459                 gchar *qcommand = escquote_value(options->editor_command[i]);
460                 secure_fprintf(ssi, "external_%d: %s %s\n", i+1, qname, qcommand);
461                 g_free(qname);
462                 g_free(qcommand);
463                 }
464
465
466         secure_fprintf(ssi, "\n##### Exif #####\n# 0: never\n# 1: if set\n# 2: always\n\n");
467         for (i = 0; ExifUIList[i].key; i++)
468                 {
469                 secure_fprintf(ssi, "exif_");
470                 write_int_option(ssi, (gchar *)ExifUIList[i].key, ExifUIList[i].current);
471                 }
472
473         secure_fputc(ssi, '\n');
474         secure_fprintf(ssi, "######################################################################\n");
475         secure_fprintf(ssi, "#                         end of config file                         #\n");
476         secure_fprintf(ssi, "######################################################################\n");
477
478         
479         if (secure_close(ssi))
480                 {
481                 gchar *buf;
482
483                 buf = g_strdup_printf(_("error saving config file: %s\nerror: %s\n"), rc_path,
484                                       secsave_strerror(secsave_errno));
485                 print_term(buf);
486                 g_free(buf);
487
488                 g_free(rc_path);
489                 return;
490                 }
491
492         g_free(rc_path);
493 }
494
495 /*
496  *-----------------------------------------------------------------------------
497  * load configuration (public)
498  *-----------------------------------------------------------------------------
499  */ 
500
501 void load_options(void)
502 {
503         FILE *f;
504         gchar *rc_path;
505         gchar *rc_pathl;
506         gchar s_buf[1024];
507         gchar *s_buf_ptr;
508         gchar option[1024];
509         gchar value[1024];
510         gchar value_all[1024];
511         gint c,l,i;
512
513         for (i = 0; ExifUIList[i].key; i++)
514                 ExifUIList[i].current = ExifUIList[i].default_value;
515
516         rc_path = g_strconcat(homedir(), "/", GQ_RC_DIR, "/", RC_FILE_NAME, NULL);
517
518         rc_pathl = path_from_utf8(rc_path);
519         f = fopen(rc_pathl,"r");
520         g_free(rc_pathl);
521         if (!f)
522                 {
523                 g_free(rc_path);
524                 return;
525                 }
526
527         while (fgets(s_buf,1024,f))
528                 {
529                 if (s_buf[0]=='#') continue;
530                 if (s_buf[0]=='\n') continue;
531                 c = 0;
532                 l = strlen(s_buf);
533                 while (s_buf[c] != ':' && c < l) c++;
534                 if (c >= l) continue;
535                 s_buf[c] = '\0';
536                 c++;
537                 while ((s_buf[c] == ' ' || s_buf[c] == 8) && c < l) c++;
538                 s_buf_ptr = s_buf + c;
539                 strncpy(value_all, s_buf_ptr, sizeof(value_all));
540                 while (s_buf[c] != 8 && s_buf[c] != ' ' && s_buf[c] != '\n' && c < l) c++;
541                 s_buf[c] = '\0';
542                 strncpy(option, s_buf, sizeof(option));
543                 strncpy(value, s_buf_ptr, sizeof(value));
544
545
546                 /* general options */
547                 options->show_icon_names = read_bool_option(f, option,
548                         "show_icon_names", value, options->show_icon_names);
549
550                 options->tree_descend_subdirs = read_bool_option(f, option,
551                         "tree_descend_subdirs", value, options->tree_descend_subdirs);
552                 options->lazy_image_sync = read_bool_option(f, option,
553                         "lazy_image_sync", value, options->lazy_image_sync);
554                 options->update_on_time_change = read_bool_option(f, option,
555                         "update_on_time_change", value, options->update_on_time_change);
556         
557                 options->startup_path_enable = read_bool_option(f, option,
558                         "startup_path_enable", value, options->startup_path_enable);
559                 options->startup_path = read_char_option(f, option,
560                         "startup_path", value_all, options->startup_path);
561
562                 options->duplicates_similarity_threshold = read_int_option(f, option,
563                         "duplicates_similarity_threshold", value, options->duplicates_similarity_threshold);
564
565                 options->progressive_key_scrolling = read_bool_option(f, option,
566                         "progressive_key_scrolling", value, options->progressive_key_scrolling);
567
568                 options->enable_metadata_dirs = read_bool_option(f, option,
569                         "enable_metadata_dirs", value, options->enable_metadata_dirs);
570
571                 options->mousewheel_scrolls = read_bool_option(f, option,
572                         "mousewheel_scrolls", value, options->mousewheel_scrolls);
573         
574                 options->open_recent_list_maxsize = read_int_option(f, option,
575                         "open_recent_list_maxsize", value, options->open_recent_list_maxsize);
576
577                 options->place_dialogs_under_mouse = read_bool_option(f, option,
578                         "place_dialogs_under_mouse", value, options->place_dialogs_under_mouse);
579
580
581                 /* layout options */
582
583                 options->layout.style = read_int_option(f, option,
584                         "layout.style", value, options->layout.style);
585                 options->layout.order = read_char_option(f, option,
586                         "layout.order", value, options->layout.order);
587                 options->layout.view_as_icons = read_bool_option(f, option,
588                         "layout.view_as_icons", value, options->layout.view_as_icons);
589                 options->layout.view_as_tree = read_bool_option(f, option,
590                         "layout.view_as_tree", value, options->layout.view_as_tree);
591                 options->layout.show_thumbnails = read_bool_option(f, option,
592                         "layout.show_thumbnails", value, options->layout.show_thumbnails);
593
594                 /* window positions */
595
596                 options->layout.save_window_positions = read_bool_option(f, option,
597                         "layout.save_window_positions", value, options->layout.save_window_positions);
598
599                 options->layout.main_window.x = read_int_option(f, option,
600                         "layout.main_window.x", value, options->layout.main_window.x);
601                 options->layout.main_window.y = read_int_option(f, option,
602                         "layout.main_window.y", value, options->layout.main_window.y);
603                 options->layout.main_window.w = read_int_option(f, option,
604                         "layout.main_window.w", value, options->layout.main_window.w);
605                 options->layout.main_window.h = read_int_option(f, option,
606                         "layout.main_window.h", value, options->layout.main_window.h);
607                 options->layout.main_window.maximized = read_bool_option(f, option,
608                         "layout.main_window.maximized", value, options->layout.main_window.maximized);
609                 options->layout.float_window.x = read_int_option(f, option,
610                         "layout.float_window.x", value, options->layout.float_window.x);
611                 options->layout.float_window.y = read_int_option(f, option,
612                         "layout.float_window.y", value, options->layout.float_window.y);
613                 options->layout.float_window.w = read_int_option(f, option,
614                         "layout.float_window.w", value, options->layout.float_window.w);
615                 options->layout.float_window.h = read_int_option(f, option,
616                         "layout.float_window.h", value, options->layout.float_window.h);
617                 options->layout.float_window.vdivider_pos = read_int_option(f, option,
618                         "layout.float_window.vdivider_pos", value, options->layout.float_window.vdivider_pos);
619                 options->layout.main_window.hdivider_pos = read_int_option(f, option,
620                         "layout.main_window.hdivider_pos", value,options->layout.main_window.hdivider_pos);
621                 options->layout.main_window.vdivider_pos = read_int_option(f, option,
622                         "layout.main_window.vdivider_pos", value, options->layout.main_window.vdivider_pos);
623                 options->layout.tools_float = read_bool_option(f, option,
624                         "layout.tools_float", value, options->layout.tools_float);
625                 options->layout.tools_hidden = read_bool_option(f, option,
626                         "layout.tools_hidden", value, options->layout.tools_hidden);
627                 options->layout.tools_restore_state = read_bool_option(f, option,
628                         "layout.tools_restore_state", value, options->layout.tools_restore_state);
629                 options->layout.toolbar_hidden = read_bool_option(f, option,
630                         "layout.toolbar_hidden", value, options->layout.toolbar_hidden);
631
632
633                 /* image options */
634                 if (strcasecmp(option, "image.zoom_mode") == 0)
635                         {
636                         if (strcasecmp(value, "original") == 0) options->image.zoom_mode = ZOOM_RESET_ORIGINAL;
637                         if (strcasecmp(value, "fit") == 0) options->image.zoom_mode = ZOOM_RESET_FIT_WINDOW;
638                         if (strcasecmp(value, "dont_change") == 0) options->image.zoom_mode = ZOOM_RESET_NONE;
639                         }
640                 options->image.zoom_2pass = read_bool_option(f, option,
641                         "image.zoom_2pass", value, options->image.zoom_2pass);
642                 options->image.zoom_to_fit_allow_expand = read_bool_option(f, option,
643                         "image.zoom_to_fit_allow_expand", value, options->image.zoom_to_fit_allow_expand);
644                 options->image.fit_window_to_image = read_bool_option(f, option,
645                         "image.fit_window_to_image", value, options->image.fit_window_to_image);
646                 options->image.limit_window_size = read_bool_option(f, option,
647                         "image.limit_window_size", value, options->image.limit_window_size);
648                 options->image.max_window_size = read_int_option(f, option,
649                         "image.max_window_size", value, options->image.max_window_size);
650                 options->image.limit_autofit_size = read_bool_option(f, option,
651                         "image.limit_autofit_size", value, options->image.limit_autofit_size);
652                 options->image.max_autofit_size = read_int_option(f, option,
653                         "image.max_autofit_size", value, options->image.max_autofit_size);
654                 options->image.scroll_reset_method = read_int_option(f, option,
655                         "image.scroll_reset_method", value, options->image.scroll_reset_method);
656                 options->image.tile_cache_max = read_int_option(f, option,
657                         "image.tile_cache_max", value, options->image.tile_cache_max);
658                 options->image.zoom_quality = CLAMP(read_int_option(f, option,
659                         "image.zoom_quality", value, options->image.zoom_quality), GDK_INTERP_NEAREST, GDK_INTERP_HYPER);
660                 options->image.dither_quality = CLAMP(read_int_option(f, option,
661                         "image.dither_quality", value, options->image.dither_quality), GDK_RGB_DITHER_NONE, GDK_RGB_DITHER_MAX);
662                 options->image.zoom_increment = read_int_option(f, option,
663                         "image.zoom_increment", value, options->image.zoom_increment);
664                 options->image.enable_read_ahead = read_bool_option(f, option,
665                         "image.enable_read_ahead", value, options->image.enable_read_ahead);
666                 options->image.exif_rotate_enable = read_bool_option(f, option,
667                         "image.exif_rotate_enable", value, options->image.exif_rotate_enable);
668                 options->image.use_custom_border_color = read_bool_option(f, option,
669                         "image.use_custom_border_color", value, options->image.use_custom_border_color);
670                 read_color_option(f, option,
671                         "image.border_color", value, &options->image.border_color);
672
673
674                 /* thumbnails options */
675                 options->thumbnails.max_width = read_int_option(f, option,
676                         "thumbnails.max_width", value, options->thumbnails.max_width);
677                 if (options->thumbnails.max_width < 16) options->thumbnails.max_width = 16;
678                 options->thumbnails.max_height = read_int_option(f, option,
679                         "thumbnails.max_height", value, options->thumbnails.max_height);
680                 if (options->thumbnails.max_height < 16) options->thumbnails.max_height = 16;
681                 options->thumbnails.enable_caching = read_bool_option(f, option,
682                         "thumbnails.enable_caching", value, options->thumbnails.enable_caching);
683                 options->thumbnails.cache_into_dirs = read_bool_option(f, option,
684                         "thumbnails.cache_into_dirs", value, options->thumbnails.cache_into_dirs);
685                 options->thumbnails.fast = read_bool_option(f, option,
686                         "thumbnails.fast", value, options->thumbnails.fast);
687                 options->thumbnails.use_xvpics = read_bool_option(f, option,
688                         "thumbnails.use_xvpics", value, options->thumbnails.use_xvpics);
689                 options->thumbnails.spec_standard = read_bool_option(f, option,
690                         "thumbnails.spec_standard", value, options->thumbnails.spec_standard);
691                 options->thumbnails.quality = CLAMP(read_int_option(f, option,
692                         "thumbnails.quality", value, options->thumbnails.quality), GDK_INTERP_NEAREST, GDK_INTERP_HYPER);
693
694                 /* file sorting options */
695                 options->file_sort.method = (SortType)read_int_option(f, option,
696                         "file_sort.method", value, (gint)options->file_sort.method);
697                 options->file_sort.ascending = read_bool_option(f, option,
698                         "file_sort.ascending", value, options->file_sort.ascending);
699                 options->file_sort.case_sensitive = read_bool_option(f, option,
700                         "file_sort.case_sensitive", value, options->file_sort.case_sensitive);
701
702                 /* file operations options */
703                 options->file_ops.enable_in_place_rename = read_bool_option(f, option,
704                         "file_ops.enable_in_place_rename", value, options->file_ops.enable_in_place_rename);
705                 options->file_ops.confirm_delete = read_bool_option(f, option,
706                         "file_ops.confirm_delete", value, options->file_ops.confirm_delete);
707                 options->file_ops.enable_delete_key = read_bool_option(f, option,
708                         "file_ops.enable_delete_key", value, options->file_ops.enable_delete_key);
709                 options->file_ops.safe_delete_enable = read_bool_option(f, option,
710                         "file_ops.safe_delete_enable",  value, options->file_ops.safe_delete_enable);
711                 options->file_ops.safe_delete_path = read_char_option(f, option,
712                         "file_ops.safe_delete_path", value, options->file_ops.safe_delete_path);
713                 options->file_ops.safe_delete_folder_maxsize = read_int_option(f, option,
714                         "file_ops.safe_delete_folder_maxsize", value,options->file_ops.safe_delete_folder_maxsize);
715
716                 /* fullscreen options */
717                 options->fullscreen.screen = read_int_option(f, option,
718                         "fullscreen.screen", value, options->fullscreen.screen);
719                 options->fullscreen.clean_flip = read_bool_option(f, option,
720                         "fullscreen.clean_flip", value, options->fullscreen.clean_flip);
721                 options->fullscreen.disable_saver = read_bool_option(f, option,
722                         "fullscreen.disable_saver", value, options->fullscreen.disable_saver);
723                 options->fullscreen.above = read_bool_option(f, option,
724                         "fullscreen.above", value, options->fullscreen.above);
725                 options->fullscreen.show_info = read_bool_option(f, option,
726                         "fullscreen.show_info", value, options->fullscreen.show_info);
727                 options->fullscreen.info = read_char_option(f, option,
728                         "fullscreen.info", value_all, options->fullscreen.info);
729
730                 /* slideshow options */
731
732                 options->slideshow.delay = read_int_unit_option(f, option,
733                         "slideshow.delay", value, options->slideshow.delay, SLIDESHOW_SUBSECOND_PRECISION);
734                 options->slideshow.random = read_bool_option(f, option,
735                         "slideshow.random", value, options->slideshow.random);
736                 options->slideshow.repeat = read_bool_option(f, option,
737                         "slideshow.repeat", value, options->slideshow.repeat);
738
739                 /* filtering options */
740
741                 options->file_filter.show_dot_files = read_bool_option(f, option,
742                         "file_filter.show_dot_files", value, options->file_filter.show_dot_files);
743                 options->file_filter.disable = read_bool_option(f, option,
744                         "file_filter.disable", value, options->file_filter.disable);
745
746                 if (strcasecmp(option, "file_filter.ext") == 0)
747                         {
748                         filter_parse(value_all);
749                         }
750
751                 if (strcasecmp(option, "sidecar.ext") == 0)
752                         {
753                         sidecar_ext_parse(value_all, TRUE);
754                         }
755                 
756                 /* Color Profiles */
757
758                 options->color_profile.enabled = read_bool_option(f, option,
759                         "color_profile.enabled", value, options->color_profile.enabled);
760                 options->color_profile.use_image = read_bool_option(f, option,
761                         "color_profile.use_image", value, options->color_profile.use_image);
762                 options->color_profile.input_type = read_int_option(f, option,
763                         "color_profile.input_type", value, options->color_profile.input_type);
764
765                 if (strncasecmp(option, "color_profile.input_file_", 25) == 0)
766                         {
767                         i = strtol(option + 25, NULL, 0) - 1;
768                         if (i >= 0 && i < COLOR_PROFILE_INPUTS)
769                                 {
770                                 options->color_profile.input_file[i] = read_char_option(f, option,
771                                         option, value, options->color_profile.input_file[i]);
772                                 }
773                         }
774                 if (strncasecmp(option, "color_profile.input_name_", 25) == 0)
775                         {
776                         i = strtol(option + 25, NULL, 0) - 1;
777                         if (i >= 0 && i < COLOR_PROFILE_INPUTS)
778                                 {
779                                 options->color_profile.input_name[i] = read_char_option(f, option,
780                                         option, value, options->color_profile.input_name[i]);
781                                 }
782                         }
783
784                 options->color_profile.screen_type = read_int_option(f, option,
785                         "color_profile.screen_type", value, options->color_profile.screen_type);
786                 options->color_profile.screen_file = read_char_option(f, option,
787                         "color_profile.screen_file", value, options->color_profile.screen_file);
788
789                 /* External Programs */
790
791                 if (strncasecmp(option, "external_", 9) == 0)
792                         {
793                         i = strtol(option + 9, NULL, 0);
794                         if (i > 0 && i <= GQ_EDITOR_SLOTS)
795                                 {
796                                 const gchar *ptr;
797                                 i--;
798                                 g_free(options->editor_name[i]);
799                                 g_free(options->editor_command[i]);
800                                 
801                                 options->editor_name[i] = quoted_value(value_all, &ptr);
802                                 options->editor_command[i] = quoted_value(ptr, NULL);
803                                 }
804                         }
805
806                 /* collection options */
807
808                 options->collections.rectangular_selection = read_bool_option(f, option,
809                         "collections.rectangular_selection", value, options->collections.rectangular_selection);
810
811                 if (0 == strncasecmp(option, "exif_", 5))
812                         {
813                         for (i = 0; ExifUIList[i].key; i++)
814                                 if (0 == strcasecmp(option+5, ExifUIList[i].key))
815                                         ExifUIList[i].current = strtol(value, NULL, 10);
816                         }
817                 }
818
819         fclose(f);
820         g_free(rc_path);
821 }
822