4 * Copyright (C) 2008 The Geeqie Team
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!
13 #include <glib/gstdio.h>
21 #include "secure_save.h"
22 #include "slideshow.h"
23 #include "ui_fileops.h"
27 *-----------------------------------------------------------------------------
28 * line write/parse routines (private)
29 *-----------------------------------------------------------------------------
33 returns text without quotes or NULL for empty or broken string
34 any text up to first '"' is skipped
35 tail is set to point at the char after the second '"'
40 gchar *quoted_value(const gchar *text, const gchar **tail)
44 gint l = strlen(text);
47 if (tail) *tail = text;
49 if (l == 0) return retval;
51 while (c < l && text[c] !='"') c++;
60 if (text[e-1] != '\\' && text[e] == '"') break;
67 gchar *substring = g_strndup(ptr, e - c);
71 retval = g_strcompress(substring);
76 if (tail) *tail = text + e + 1;
79 /* for compatibility with older formats (<0.3.7)
80 * read a line without quotes too */
83 while (c < l && text[c] !=' ' && text[c] !=8 && text[c] != '\n') c++;
86 retval = g_strndup(text, c);
88 if (tail) *tail = text + c;
94 gchar *escquote_value(const gchar *text)
98 if (!text) return g_strdup("\"\"");
100 e = g_strescape(text, "");
103 gchar *retval = g_strdup_printf("\"%s\"", e);
107 return g_strdup("\"\"");
110 static void write_char_option(SecureSaveInfo *ssi, gchar *label, gchar *text)
112 gchar *escval = escquote_value(text);
114 secure_fprintf(ssi, "%s: %s\n", label, escval);
118 static void read_char_option(FILE *f, gchar *option, gchar *label, gchar *value, gchar **text)
120 if (text && strcasecmp(option, label) == 0)
123 *text = quoted_value(value, NULL);
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)
131 return g_strdup_printf("#%04X%04X%04X", color->red, color->green, color->blue);
134 static void write_color_option(SecureSaveInfo *ssi, gchar *label, GdkColor *color)
138 gchar *colorstring = color_to_string(color);
140 write_char_option(ssi, label, colorstring);
144 secure_fprintf(ssi, "%s: \n", label);
147 static void read_color_option(FILE *f, gchar *option, gchar *label, gchar *value, GdkColor *color)
149 if (color && strcasecmp(option, label) == 0)
151 gchar *colorstr = quoted_value(value, NULL);
152 if (colorstr) gdk_color_parse(colorstr, color);
158 static void write_int_option(SecureSaveInfo *ssi, gchar *label, gint n)
160 secure_fprintf(ssi, "%s: %d\n", label, n);
163 static void read_int_option(FILE *f, gchar *option, gchar *label, gchar *value, gint *n)
165 if (n && strcasecmp(option, label) == 0)
167 *n = strtol(value, NULL, 10);
171 static void write_uint_option(SecureSaveInfo *ssi, gchar *label, guint n)
173 secure_fprintf(ssi, "%s: %u\n", label, n);
176 static void read_uint_option(FILE *f, gchar *option, gchar *label, gchar *value, guint *n)
178 if (n && strcasecmp(option, label) == 0)
180 *n = strtoul(value, NULL, 10);
186 static void read_int_option_clamp(FILE *f, gchar *option, gchar *label, gchar *value, gint *n, gint min, gint max)
188 if (n && strcasecmp(option, label) == 0)
190 *n = CLAMP(strtol(value, NULL, 10), min, max);
195 static void write_int_unit_option(SecureSaveInfo *ssi, gchar *label, gint n, gint subunits)
210 secure_fprintf(ssi, "%s: %d.%d\n", label, l, r);
213 static void read_int_unit_option(FILE *f, gchar *option, gchar *label, gchar *value, gint *n, gint subunits)
215 if (n && strcasecmp(option, label) == 0)
221 while (*ptr != '\0' && *ptr != '.') ptr++;
225 l = strtol(value, NULL, 10);
228 r = strtol(ptr, NULL, 10);
232 l = strtol(value, NULL, 10);
236 *n = l * subunits + r;
240 static void write_bool_option(SecureSaveInfo *ssi, gchar *label, gint n)
242 secure_fprintf(ssi, "%s: ", label);
243 if (n) secure_fprintf(ssi, "true\n"); else secure_fprintf(ssi, "false\n");
246 static void read_bool_option(FILE *f, gchar *option, gchar *label, gchar *value, gint *n)
248 if (n && strcasecmp(option, label) == 0)
250 if (strcasecmp(value, "true") == 0 || strcmp(value, "1") == 0)
258 *-----------------------------------------------------------------------------
259 * save configuration (public)
260 *-----------------------------------------------------------------------------
263 void save_options(void)
270 rc_path = g_strconcat(homedir(), "/", GQ_RC_DIR, "/", RC_FILE_NAME, NULL);
272 rc_pathl = path_from_utf8(rc_path);
273 ssi = secure_open(rc_pathl);
277 printf_term(_("error saving config file: %s\n"), rc_path);
282 #define WRITE_BOOL(_name_) write_bool_option(ssi, #_name_, options->_name_)
283 #define WRITE_INT(_name_) write_int_option(ssi, #_name_, options->_name_)
284 #define WRITE_UINT(_name_) write_uint_option(ssi, #_name_, options->_name_)
285 #define WRITE_INT_UNIT(_name_, _unit_) write_int_unit_option(ssi, #_name_, options->_name_, _unit_)
286 #define WRITE_CHAR(_name_) write_char_option(ssi, #_name_, options->_name_)
287 #define WRITE_COLOR(_name_) write_color_option(ssi, #_name_, &options->_name_)
289 #define WRITE_SEPARATOR() secure_fputc(ssi, '\n')
290 #define WRITE_SUBTITLE(_title_) secure_fprintf(ssi, "\n\n##### "_title_" #####\n\n")
292 secure_fprintf(ssi, "######################################################################\n");
293 secure_fprintf(ssi, "# %30s config file version %7s #\n", GQ_APPNAME, VERSION);
294 secure_fprintf(ssi, "######################################################################\n");
297 secure_fprintf(ssi, "# Note: This file is autogenerated. Options can be changed here,\n");
298 secure_fprintf(ssi, "# but user comments and formatting will be lost.\n");
301 WRITE_SUBTITLE("General Options");
303 WRITE_BOOL(show_icon_names);
306 WRITE_BOOL(tree_descend_subdirs);
307 WRITE_BOOL(lazy_image_sync);
308 WRITE_BOOL(update_on_time_change);
311 WRITE_BOOL(startup_path_enable);
312 WRITE_CHAR(startup_path);
314 WRITE_BOOL(progressive_key_scrolling);
315 WRITE_BOOL(enable_metadata_dirs);
317 WRITE_INT(duplicates_similarity_threshold);
320 WRITE_BOOL(mousewheel_scrolls);
321 WRITE_INT(open_recent_list_maxsize);
322 WRITE_INT(dnd_icon_size);
323 WRITE_BOOL(place_dialogs_under_mouse);
326 WRITE_SUBTITLE("File operations Options");
328 WRITE_BOOL(file_ops.enable_in_place_rename);
329 WRITE_BOOL(file_ops.confirm_delete);
330 WRITE_BOOL(file_ops.enable_delete_key);
331 WRITE_BOOL(file_ops.safe_delete_enable);
332 WRITE_CHAR(file_ops.safe_delete_path);
333 WRITE_INT(file_ops.safe_delete_folder_maxsize);
336 WRITE_SUBTITLE("Layout Options");
338 WRITE_INT(layout.style);
339 WRITE_CHAR(layout.order);
340 WRITE_BOOL(layout.view_as_icons);
341 WRITE_UINT(layout.dir_view_type);
342 WRITE_BOOL(layout.show_marks);
343 WRITE_BOOL(layout.show_thumbnails);
346 WRITE_BOOL(layout.save_window_positions);
349 WRITE_INT(layout.main_window.x);
350 WRITE_INT(layout.main_window.y);
351 WRITE_INT(layout.main_window.w);
352 WRITE_INT(layout.main_window.h);
353 WRITE_BOOL(layout.main_window.maximized);
354 WRITE_INT(layout.main_window.hdivider_pos);
355 WRITE_INT(layout.main_window.vdivider_pos);
358 WRITE_INT(layout.float_window.x);
359 WRITE_INT(layout.float_window.y);
360 WRITE_INT(layout.float_window.w);
361 WRITE_INT(layout.float_window.h);
362 WRITE_INT(layout.float_window.vdivider_pos);
365 WRITE_BOOL(layout.tools_float);
366 WRITE_BOOL(layout.tools_hidden);
367 WRITE_BOOL(layout.tools_restore_state);
370 WRITE_BOOL(layout.toolbar_hidden);
373 WRITE_SUBTITLE("Image Options");
375 secure_fprintf(ssi, "# image.zoom_mode possible values are:\n"
379 secure_fprintf(ssi, "image.zoom_mode: ");
380 if (options->image.zoom_mode == ZOOM_RESET_ORIGINAL)
381 secure_fprintf(ssi, "original\n");
382 else if (options->image.zoom_mode == ZOOM_RESET_FIT_WINDOW)
383 secure_fprintf(ssi, "fit\n");
384 else if (options->image.zoom_mode == ZOOM_RESET_NONE)
385 secure_fprintf(ssi, "dont_change\n");
387 WRITE_BOOL(image.zoom_2pass);
388 WRITE_BOOL(image.zoom_to_fit_allow_expand);
389 WRITE_INT(image.zoom_quality);
390 WRITE_INT(image.zoom_increment);
391 WRITE_BOOL(image.fit_window_to_image);
392 WRITE_BOOL(image.limit_window_size);
393 WRITE_INT(image.max_window_size);
394 WRITE_BOOL(image.limit_autofit_size);
395 WRITE_INT(image.max_autofit_size);
396 WRITE_INT(image.scroll_reset_method);
397 WRITE_INT(image.tile_cache_max);
398 WRITE_INT(image.dither_quality);
399 WRITE_BOOL(image.enable_read_ahead);
400 WRITE_BOOL(image.exif_rotate_enable);
401 WRITE_BOOL(image.use_custom_border_color);
402 WRITE_COLOR(image.border_color);
403 WRITE_INT(image.read_buffer_size);
404 WRITE_INT(image.idle_read_loop_count);
406 WRITE_SUBTITLE("Thumbnails Options");
408 WRITE_INT(thumbnails.max_width);
409 WRITE_INT(thumbnails.max_height);
410 WRITE_BOOL(thumbnails.enable_caching);
411 WRITE_BOOL(thumbnails.cache_into_dirs);
412 WRITE_BOOL(thumbnails.fast);
413 WRITE_BOOL(thumbnails.use_xvpics);
414 WRITE_BOOL(thumbnails.spec_standard);
415 WRITE_INT(thumbnails.quality);
418 WRITE_SUBTITLE("File sorting Options");
420 WRITE_INT(file_sort.method);
421 WRITE_BOOL(file_sort.ascending);
422 WRITE_BOOL(file_sort.case_sensitive);
425 WRITE_SUBTITLE("Fullscreen Options");
427 WRITE_INT(fullscreen.screen);
428 WRITE_BOOL(fullscreen.clean_flip);
429 WRITE_BOOL(fullscreen.disable_saver);
430 WRITE_BOOL(fullscreen.above);
432 WRITE_SUBTITLE("Image Overlay Options");
433 WRITE_BOOL(image_overlay.common.enabled);
434 WRITE_BOOL(image_overlay.common.show_at_startup);
435 WRITE_CHAR(image_overlay.common.template_string);
437 WRITE_SUBTITLE("Slideshow Options");
439 WRITE_INT_UNIT(slideshow.delay, SLIDESHOW_SUBSECOND_PRECISION);
440 WRITE_BOOL(slideshow.random);
441 WRITE_BOOL(slideshow.repeat);
444 WRITE_SUBTITLE("Collection Options");
446 WRITE_BOOL(collections.rectangular_selection);
449 WRITE_SUBTITLE("Filtering Options");
451 WRITE_BOOL(file_filter.show_hidden_files);
452 WRITE_BOOL(file_filter.show_dot_directory);
453 WRITE_BOOL(file_filter.disable);
456 filter_write_list(ssi);
459 WRITE_SUBTITLE("Sidecars Options");
461 sidecar_ext_write(ssi);
464 WRITE_SUBTITLE("Color Profiles");
467 secure_fprintf(ssi, "# NOTICE: %s was not built with support for color profiles,\n"
468 "# color profile options will have no effect.\n\n", GQ_APPNAME);
471 WRITE_BOOL(color_profile.enabled);
472 WRITE_BOOL(color_profile.use_image);
473 WRITE_INT(color_profile.input_type);
476 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
480 buf = g_strdup_printf("color_profile.input_file_%d", i + 1);
481 write_char_option(ssi, buf, options->color_profile.input_file[i]);
484 buf = g_strdup_printf("color_profile.input_name_%d", i + 1);
485 write_char_option(ssi, buf, options->color_profile.input_name[i]);
490 WRITE_INT(color_profile.screen_type);
491 WRITE_CHAR(color_profile.screen_file);
493 WRITE_SUBTITLE("External Programs");
494 secure_fprintf(ssi, "# Maximum of %d programs (external_1 through external_%d)\n", GQ_EDITOR_GENERIC_SLOTS, GQ_EDITOR_GENERIC_SLOTS);
495 secure_fprintf(ssi, "# external_%d through external_%d are used for file ops\n", GQ_EDITOR_GENERIC_SLOTS + 1, GQ_EDITOR_SLOTS);
496 secure_fprintf(ssi, "# format: external_n: \"menu name\" \"command line\"\n\n");
498 for (i = 0; i < GQ_EDITOR_SLOTS; i++)
500 if (i == GQ_EDITOR_GENERIC_SLOTS) secure_fputc(ssi, '\n');
501 gchar *qname = escquote_value(options->editor_name[i]);
502 gchar *qcommand = escquote_value(options->editor_command[i]);
503 secure_fprintf(ssi, "external_%d: %s %s\n", i+1, qname, qcommand);
509 WRITE_SUBTITLE("Exif Options");
510 secure_fprintf(ssi, "# Display: 0: never\n"
513 for (i = 0; ExifUIList[i].key; i++)
515 secure_fprintf(ssi, "exif.display.");
516 write_int_option(ssi, (gchar *)ExifUIList[i].key, ExifUIList[i].current);
522 secure_fprintf(ssi, "######################################################################\n");
523 secure_fprintf(ssi, "# end of config file #\n");
524 secure_fprintf(ssi, "######################################################################\n");
527 if (secure_close(ssi))
529 printf_term(_("error saving config file: %s\nerror: %s\n"), rc_path,
530 secsave_strerror(secsave_errno));
539 *-----------------------------------------------------------------------------
540 * load configuration (public)
541 *-----------------------------------------------------------------------------
544 void load_options(void)
552 gchar value_all[1024];
555 for (i = 0; ExifUIList[i].key; i++)
556 ExifUIList[i].current = ExifUIList[i].default_value;
558 rc_path = g_strconcat(homedir(), "/", GQ_RC_DIR, "/", RC_FILE_NAME, NULL);
560 rc_pathl = path_from_utf8(rc_path);
561 f = fopen(rc_pathl,"r");
569 while (fgets(s_buf, sizeof(s_buf), f))
571 gchar *option_start, *value_start;
574 while(g_ascii_isspace(*p)) p++;
575 if (!*p || *p == '\n' || *p == '#') continue;
577 while(*p && *p != ':') p++;
581 strncpy(option, option_start, sizeof(option));
582 while(g_ascii_isspace(*p)) p++;
584 strncpy(value_all, value_start, sizeof(value_all));
585 while(*p && !g_ascii_isspace(*p) && *p != '\n') p++;
587 strncpy(value, value_start, sizeof(value));
589 #define READ_BOOL(_name_) read_bool_option(f, option, #_name_, value, &options->_name_)
590 #define READ_INT(_name_) read_int_option(f, option, #_name_, value, &options->_name_)
591 #define READ_UINT(_name_) read_uint_option(f, option, #_name_, value, &options->_name_)
592 #define READ_INT_CLAMP(_name_, _min_, _max_) read_int_option_clamp(f, option, #_name_, value, &options->_name_, _min_, _max_)
593 #define READ_INT_UNIT(_name_, _unit_) read_int_unit_option(f, option, #_name_, value, &options->_name_, _unit_)
594 #define READ_CHAR(_name_) read_char_option(f, option, #_name_, value_all, &options->_name_)
595 #define READ_COLOR(_name_) read_color_option(f, option, #_name_, value, &options->_name_)
597 #define COMPAT_READ_BOOL(_oldname_, _name_) read_bool_option(f, option, #_oldname_, value, &options->_name_)
598 #define COMPAT_READ_INT(_oldname_, _name_) read_int_option(f, option, #_oldname_, value, &options->_name_)
599 #define COMPAT_READ_UINT(_oldname_, _name_) read_uint_option(f, option, #_oldname_, value, &options->_name_)
600 #define COMPAT_READ_INT_CLAMP(_oldname_, _name_, _min_, _max_) read_int_option_clamp(f, option, #_oldname_, value, &options->_name_, _min_, _max_)
601 #define COMPAT_READ_INT_UNIT(_oldname_, _name_, _unit_) read_int_unit_option(f, option, #_oldname_, value, &options->_name_, _unit_)
602 #define COMPAT_READ_CHAR(_oldname_, _name_) read_char_option(f, option, #_oldname_, value_all, &options->_name_)
603 #define COMPAT_READ_COLOR(_oldname_, _name_) read_color_option(f, option, #_oldname_, value, &options->_name_)
605 /* general options */
606 READ_BOOL(show_icon_names);
608 READ_BOOL(tree_descend_subdirs);
609 READ_BOOL(lazy_image_sync);
610 READ_BOOL(update_on_time_change);
612 READ_BOOL(startup_path_enable);
613 READ_CHAR(startup_path);
615 READ_INT(duplicates_similarity_threshold);
617 READ_BOOL(progressive_key_scrolling);
619 READ_BOOL(enable_metadata_dirs);
621 READ_BOOL(mousewheel_scrolls);
623 READ_INT(open_recent_list_maxsize);
624 READ_INT(dnd_icon_size);
625 READ_BOOL(place_dialogs_under_mouse);
630 READ_INT(layout.style);
631 READ_CHAR(layout.order);
632 READ_BOOL(layout.view_as_icons);
633 READ_UINT(layout.dir_view_type);
634 READ_BOOL(layout.show_marks);
635 READ_BOOL(layout.show_thumbnails);
637 /* window positions */
639 READ_BOOL(layout.save_window_positions);
641 READ_INT(layout.main_window.x);
642 READ_INT(layout.main_window.y);
643 READ_INT(layout.main_window.w);
644 READ_INT(layout.main_window.h);
645 READ_BOOL(layout.main_window.maximized);
646 READ_INT(layout.float_window.x);
647 READ_INT(layout.float_window.y);
648 READ_INT(layout.float_window.w);
649 READ_INT(layout.float_window.h);
650 READ_INT(layout.float_window.vdivider_pos);
651 READ_INT(layout.main_window.hdivider_pos);
652 READ_INT(layout.main_window.vdivider_pos);
653 READ_BOOL(layout.tools_float);
654 READ_BOOL(layout.tools_hidden);
655 READ_BOOL(layout.tools_restore_state);
656 READ_BOOL(layout.toolbar_hidden);
660 if (strcasecmp(option, "image.zoom_mode") == 0)
662 if (strcasecmp(value, "original") == 0)
663 options->image.zoom_mode = ZOOM_RESET_ORIGINAL;
664 else if (strcasecmp(value, "fit") == 0)
665 options->image.zoom_mode = ZOOM_RESET_FIT_WINDOW;
666 else if (strcasecmp(value, "dont_change") == 0)
667 options->image.zoom_mode = ZOOM_RESET_NONE;
669 READ_BOOL(image.zoom_2pass);
670 READ_BOOL(image.zoom_to_fit_allow_expand);
671 READ_BOOL(image.fit_window_to_image);
672 READ_BOOL(image.limit_window_size);
673 READ_INT(image.max_window_size);
674 READ_BOOL(image.limit_autofit_size);
675 READ_INT(image.max_autofit_size);
676 READ_INT(image.scroll_reset_method);
677 READ_INT(image.tile_cache_max);
678 READ_INT_CLAMP(image.zoom_quality, GDK_INTERP_NEAREST, GDK_INTERP_HYPER);
679 READ_INT_CLAMP(image.dither_quality, GDK_RGB_DITHER_NONE, GDK_RGB_DITHER_MAX);
680 READ_INT(image.zoom_increment);
681 READ_BOOL(image.enable_read_ahead);
682 READ_BOOL(image.exif_rotate_enable);
683 READ_BOOL(image.use_custom_border_color);
684 READ_COLOR(image.border_color);
685 READ_INT_CLAMP(image.read_buffer_size, IMAGE_LOADER_READ_BUFFER_SIZE_MIN, IMAGE_LOADER_READ_BUFFER_SIZE_MAX);
686 READ_INT_CLAMP(image.idle_read_loop_count, IMAGE_LOADER_IDLE_READ_LOOP_COUNT_MIN, IMAGE_LOADER_IDLE_READ_LOOP_COUNT_MAX);
689 /* thumbnails options */
690 READ_INT_CLAMP(thumbnails.max_width, 16, 512);
691 READ_INT_CLAMP(thumbnails.max_height, 16, 512);
693 READ_BOOL(thumbnails.enable_caching);
694 READ_BOOL(thumbnails.cache_into_dirs);
695 READ_BOOL(thumbnails.fast);
696 READ_BOOL(thumbnails.use_xvpics);
697 READ_BOOL(thumbnails.spec_standard);
698 READ_INT_CLAMP(thumbnails.quality, GDK_INTERP_NEAREST, GDK_INTERP_HYPER);
700 /* file sorting options */
701 READ_UINT(file_sort.method);
702 READ_BOOL(file_sort.ascending);
703 READ_BOOL(file_sort.case_sensitive);
705 /* file operations options */
706 READ_BOOL(file_ops.enable_in_place_rename);
707 READ_BOOL(file_ops.confirm_delete);
708 READ_BOOL(file_ops.enable_delete_key);
709 READ_BOOL(file_ops.safe_delete_enable);
710 READ_CHAR(file_ops.safe_delete_path);
711 READ_INT(file_ops.safe_delete_folder_maxsize);
713 /* fullscreen options */
714 READ_INT(fullscreen.screen);
715 READ_BOOL(fullscreen.clean_flip);
716 READ_BOOL(fullscreen.disable_saver);
717 READ_BOOL(fullscreen.above);
720 COMPAT_READ_BOOL(fullscreen.show_info, image_overlay.common.show_at_startup);
721 COMPAT_READ_CHAR(fullscreen.info, image_overlay.common.template_string);
722 READ_BOOL(image_overlay.common.enabled);
723 READ_BOOL(image_overlay.common.show_at_startup);
724 READ_CHAR(image_overlay.common.template_string);
726 /* slideshow options */
727 READ_INT_UNIT(slideshow.delay, SLIDESHOW_SUBSECOND_PRECISION);
728 READ_BOOL(slideshow.random);
729 READ_BOOL(slideshow.repeat);
731 /* collection options */
733 READ_BOOL(collections.rectangular_selection);
735 /* filtering options */
737 READ_BOOL(file_filter.show_hidden_files);
738 READ_BOOL(file_filter.show_dot_directory);
739 READ_BOOL(file_filter.disable);
741 if (strcasecmp(option, "file_filter.ext") == 0)
743 filter_parse(value_all);
746 if (strcasecmp(option, "sidecar.ext") == 0)
748 sidecar_ext_parse(value_all, TRUE);
753 READ_BOOL(color_profile.enabled);
754 READ_BOOL(color_profile.use_image);
755 READ_INT(color_profile.input_type);
757 if (strncasecmp(option, "color_profile.input_file_", 25) == 0)
759 i = strtol(option + 25, NULL, 0) - 1;
760 if (i >= 0 && i < COLOR_PROFILE_INPUTS)
762 read_char_option(f, option, option, value, &options->color_profile.input_file[i]);
765 if (strncasecmp(option, "color_profile.input_name_", 25) == 0)
767 i = strtol(option + 25, NULL, 0) - 1;
768 if (i >= 0 && i < COLOR_PROFILE_INPUTS)
770 read_char_option(f, option, option, value, &options->color_profile.input_name[i]);
774 READ_INT(color_profile.screen_type);
775 READ_CHAR(color_profile.screen_file);
777 /* External Programs */
779 if (strncasecmp(option, "external_", 9) == 0)
781 i = strtol(option + 9, NULL, 0);
782 if (i > 0 && i <= GQ_EDITOR_SLOTS)
786 g_free(options->editor_name[i]);
787 g_free(options->editor_command[i]);
789 options->editor_name[i] = quoted_value(value_all, &ptr);
790 options->editor_command[i] = quoted_value(ptr, NULL);
795 if (0 == strncasecmp(option, "exif.display.", 13))
797 for (i = 0; ExifUIList[i].key; i++)
798 if (0 == strcasecmp(option + 13, ExifUIList[i].key))
799 ExifUIList[i].current = strtol(value, NULL, 10);