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