flac: Saner EOF handling
[cmus.git] / options.c
blob4ea54276c03b5797234b325ae6d3655906db754a
1 /*
2 * Copyright 2006 Timo Hirvonen
3 */
5 #include "options.h"
6 #include "list.h"
7 #include "utils.h"
8 #include "xmalloc.h"
9 #include "player.h"
10 #include "buffer.h"
11 #include "ui_curses.h"
12 #include "format_print.h"
13 #include "cmus.h"
14 #include "misc.h"
15 #include "lib.h"
16 #include "pl.h"
17 #include "browser.h"
18 #include "keys.h"
19 #include "filters.h"
20 #include "command_mode.h"
21 #include "file.h"
22 #include "prog.h"
23 #include "output.h"
24 #include "config/datadir.h"
26 #include <stdio.h>
27 #include <errno.h>
29 #if defined(__sun__)
30 #include <ncurses.h>
31 #else
32 #include <curses.h>
33 #endif
35 /* initialized option variables */
37 char *output_plugin = NULL;
38 char *status_display_program = NULL;
39 char *server_password;
40 int auto_reshuffle = 0;
41 int confirm_run = 1;
42 int show_hidden = 0;
43 int show_remaining_time = 0;
44 int set_term_title = 1;
45 int play_library = 1;
46 int repeat = 0;
47 int shuffle = 0;
48 int pretty_artist_name;
49 int fuzzy_artist_sort;
51 int colors[NR_COLORS] = {
52 -1,
53 -1,
54 COLOR_RED | BRIGHT,
55 COLOR_YELLOW | BRIGHT,
57 COLOR_BLUE,
58 COLOR_WHITE,
59 COLOR_BLACK,
60 COLOR_BLUE,
62 COLOR_WHITE | BRIGHT,
63 -1,
64 COLOR_YELLOW | BRIGHT,
65 COLOR_BLUE,
67 COLOR_YELLOW | BRIGHT,
68 COLOR_BLUE | BRIGHT,
69 -1,
70 COLOR_WHITE,
72 COLOR_YELLOW | BRIGHT,
73 COLOR_WHITE,
74 COLOR_BLACK,
75 COLOR_BLUE,
77 COLOR_WHITE | BRIGHT,
78 COLOR_BLUE,
79 COLOR_WHITE | BRIGHT
82 /* uninitialized option variables */
83 char *track_win_format = NULL;
84 char *track_win_alt_format = NULL;
85 char *list_win_format = NULL;
86 char *list_win_alt_format = NULL;
87 char *current_format = NULL;
88 char *current_alt_format = NULL;
89 char *window_title_format = NULL;
90 char *window_title_alt_format = NULL;
91 char *id3_default_charset = NULL;
93 static void buf_int(char *buf, int val)
95 snprintf(buf, OPTION_MAX_SIZE, "%d", val);
98 static int parse_int(const char *buf, int minval, int maxval, int *val)
100 long int tmp;
102 if (str_to_int(buf, &tmp) == -1 || tmp < minval || tmp > maxval) {
103 error_msg("integer in range %d..%d expected", minval, maxval);
104 return 0;
106 *val = tmp;
107 return 1;
110 int parse_enum(const char *buf, int minval, int maxval, const char * const names[], int *val)
112 long int tmp;
113 int i;
115 if (str_to_int(buf, &tmp) == 0) {
116 if (tmp < minval || tmp > maxval)
117 goto err;
118 *val = tmp;
119 return 1;
122 for (i = 0; names[i]; i++) {
123 if (strcasecmp(buf, names[i]) == 0) {
124 *val = i + minval;
125 return 1;
128 err:
129 error_msg("name or integer in range %d..%d expected", minval, maxval);
130 return 0;
133 static const char * const bool_names[] = {
134 "false", "true", NULL
137 static int parse_bool(const char *buf, int *val)
139 return parse_enum(buf, 0, 1, bool_names, val);
142 /* this is used as id in struct cmus_opt */
143 enum format_id {
144 FMT_CURRENT_ALT,
145 FMT_PLAYLIST_ALT,
146 FMT_TITLE_ALT,
147 FMT_TRACKWIN_ALT,
148 FMT_CURRENT,
149 FMT_PLAYLIST,
150 FMT_TITLE,
151 FMT_TRACKWIN
153 #define NR_FMTS 8
155 /* callbacks for normal options {{{ */
157 #define SECOND_SIZE (44100 * 16 / 8 * 2)
158 static void get_buffer_seconds(unsigned int id, char *buf)
160 buf_int(buf, (player_get_buffer_chunks() * CHUNK_SIZE + SECOND_SIZE / 2) / SECOND_SIZE);
163 static void set_buffer_seconds(unsigned int id, const char *buf)
165 int sec;
167 if (parse_int(buf, 1, 20, &sec))
168 player_set_buffer_chunks((sec * SECOND_SIZE + CHUNK_SIZE / 2) / CHUNK_SIZE);
171 static void get_id3_default_charset(unsigned int id, char *buf)
173 strcpy(buf, id3_default_charset);
176 static void set_id3_default_charset(unsigned int id, const char *buf)
178 free(id3_default_charset);
179 id3_default_charset = xstrdup(buf);
182 static const char * const valid_sort_keys[] = {
183 "artist",
184 "album",
185 "title",
186 "tracknumber",
187 "discnumber",
188 "date",
189 "genre",
190 "comment",
191 "filename",
192 "albumartist",
193 NULL
196 static const char **parse_sort_keys(const char *value)
198 const char **keys;
199 const char *s, *e;
200 int size = 4;
201 int pos = 0;
203 size = 4;
204 keys = xnew(const char *, size);
206 s = value;
207 while (1) {
208 char buf[32];
209 int i, len;
211 while (*s == ' ')
212 s++;
214 e = s;
215 while (*e && *e != ' ')
216 e++;
218 len = e - s;
219 if (len == 0)
220 break;
221 if (len > 31)
222 len = 31;
224 memcpy(buf, s, len);
225 buf[len] = 0;
226 s = e;
228 for (i = 0; ; i++) {
229 if (valid_sort_keys[i] == NULL) {
230 error_msg("invalid sort key '%s'", buf);
231 free(keys);
232 return NULL;
235 if (strcmp(buf, valid_sort_keys[i]) == 0)
236 break;
239 if (pos == size - 1) {
240 size *= 2;
241 keys = xrenew(const char *, keys, size);
243 keys[pos++] = valid_sort_keys[i];
245 keys[pos] = NULL;
246 return keys;
249 static void get_lib_sort(unsigned int id, char *buf)
251 strcpy(buf, lib_editable.sort_str);
254 static void set_lib_sort(unsigned int id, const char *buf)
256 const char **keys = parse_sort_keys(buf);
258 if (keys)
259 editable_set_sort_keys(&lib_editable, keys);
262 static void get_pl_sort(unsigned int id, char *buf)
264 strcpy(buf, pl_editable.sort_str);
267 static void set_pl_sort(unsigned int id, const char *buf)
269 const char **keys = parse_sort_keys(buf);
271 if (keys)
272 editable_set_sort_keys(&pl_editable, keys);
275 static void get_output_plugin(unsigned int id, char *buf)
277 const char *value = op_get_current();
279 if (value)
280 strcpy(buf, value);
283 static void set_output_plugin(unsigned int id, const char *buf)
285 if (ui_initialized) {
286 if (!soft_vol)
287 mixer_close();
288 player_set_op(buf);
289 if (!soft_vol)
290 mixer_open();
291 } else {
292 /* must set it later manually */
293 output_plugin = xstrdup(buf);
297 static void get_passwd(unsigned int id, char *buf)
299 if (server_password)
300 strcpy(buf, server_password);
303 static void set_passwd(unsigned int id, const char *buf)
305 int len = strlen(buf);
307 if (len == 0) {
308 free(server_password);
309 server_password = NULL;
310 } else if (len < 6) {
311 error_msg("unsafe password");
312 } else {
313 free(server_password);
314 server_password = xstrdup(buf);
318 static void get_replaygain_preamp(unsigned int id, char *buf)
320 sprintf(buf, "%f", replaygain_preamp);
323 static void set_replaygain_preamp(unsigned int id, const char *buf)
325 double val;
326 char *end;
328 val = strtod(buf, &end);
329 if (end == buf) {
330 error_msg("floating point number expected (dB)");
331 return;
333 player_set_rg_preamp(val);
336 static void get_softvol_state(unsigned int id, char *buf)
338 sprintf(buf, "%d %d", soft_vol_l, soft_vol_r);
341 static void set_softvol_state(unsigned int id, const char *buf)
343 char buffer[OPTION_MAX_SIZE];
344 char *ptr;
345 long int l, r;
347 strcpy(buffer, buf);
348 ptr = strchr(buffer, ' ');
349 if (!ptr)
350 goto err;
351 while (*ptr == ' ')
352 *ptr++ = 0;
354 if (str_to_int(buffer, &l) == -1 || l < 0 || l > 100)
355 goto err;
356 if (str_to_int(ptr, &r) == -1 || r < 0 || r > 100)
357 goto err;
359 player_set_soft_volume(l, r);
360 return;
361 err:
362 error_msg("two integers in range 0..100 expected");
365 static void get_status_display_program(unsigned int id, char *buf)
367 if (status_display_program)
368 strcpy(buf, status_display_program);
371 static void set_status_display_program(unsigned int id, const char *buf)
373 free(status_display_program);
374 status_display_program = NULL;
375 if (buf[0])
376 status_display_program = xstrdup(buf);
379 /* }}} */
381 /* callbacks for toggle options {{{ */
383 static void get_auto_reshuffle(unsigned int id, char *buf)
385 strcpy(buf, bool_names[auto_reshuffle]);
388 static void set_auto_reshuffle(unsigned int id, const char *buf)
390 parse_bool(buf, &auto_reshuffle);
393 static void toggle_auto_reshuffle(unsigned int id)
395 auto_reshuffle ^= 1;
398 static void get_continue(unsigned int id, char *buf)
400 strcpy(buf, bool_names[player_cont]);
403 static void set_continue(unsigned int id, const char *buf)
405 if (!parse_bool(buf, &player_cont))
406 return;
407 update_statusline();
410 static void toggle_continue(unsigned int id)
412 player_cont ^= 1;
413 update_statusline();
416 static void get_repeat_current(unsigned int id, char *buf)
418 strcpy(buf, bool_names[player_repeat_current]);
421 static void set_repeat_current(unsigned int id, const char *buf)
423 if (!parse_bool(buf, &player_repeat_current))
424 return;
425 update_statusline();
428 static void toggle_repeat_current(unsigned int id)
430 player_repeat_current ^= 1;
431 update_statusline();
434 static void get_confirm_run(unsigned int id, char *buf)
436 strcpy(buf, bool_names[confirm_run]);
439 static void set_confirm_run(unsigned int id, const char *buf)
441 parse_bool(buf, &confirm_run);
444 static void toggle_confirm_run(unsigned int id)
446 confirm_run ^= 1;
449 const char * const view_names[NR_VIEWS + 1] = {
450 "tree", "sorted", "playlist", "queue", "browser", "filters", "settings", NULL
453 static void get_play_library(unsigned int id, char *buf)
455 strcpy(buf, bool_names[play_library]);
458 static void set_play_library(unsigned int id, const char *buf)
460 if (!parse_bool(buf, &play_library))
461 return;
462 update_statusline();
465 static void toggle_play_library(unsigned int id)
467 play_library ^= 1;
468 update_statusline();
471 static void get_play_sorted(unsigned int id, char *buf)
473 strcpy(buf, bool_names[play_sorted]);
476 static void set_play_sorted(unsigned int id, const char *buf)
478 int tmp;
480 if (!parse_bool(buf, &tmp))
481 return;
483 play_sorted = tmp;
484 update_statusline();
487 static void toggle_play_sorted(unsigned int id)
489 editable_lock();
490 play_sorted = play_sorted ^ 1;
492 /* shuffle would override play_sorted... */
493 if (play_sorted) {
494 /* play_sorted makes no sense in playlist */
495 play_library = 1;
496 shuffle = 0;
499 editable_unlock();
500 update_statusline();
503 static void get_fuzzy_artist_sort(unsigned int id, char *buf)
505 strcpy(buf, bool_names[fuzzy_artist_sort]);
508 static void set_fuzzy_artist_sort(unsigned int id, const char *buf)
510 if (parse_bool(buf, &fuzzy_artist_sort))
511 tree_sort_artists();
514 static void toggle_fuzzy_artist_sort(unsigned int id)
516 fuzzy_artist_sort ^= 1;
517 tree_sort_artists();
520 static void get_pretty_artist_name(unsigned int id, char *buf)
522 strcpy(buf, bool_names[pretty_artist_name]);
525 static void set_pretty_artist_name(unsigned int id, const char *buf)
527 parse_bool(buf, &pretty_artist_name);
528 lib_tree_win->changed = 1;
531 static void toggle_pretty_artist_name(unsigned int id)
533 pretty_artist_name ^= 1;
534 lib_tree_win->changed = 1;
537 const char * const aaa_mode_names[] = {
538 "all", "artist", "album", NULL
541 static void get_aaa_mode(unsigned int id, char *buf)
543 strcpy(buf, aaa_mode_names[aaa_mode]);
546 static void set_aaa_mode(unsigned int id, const char *buf)
548 int tmp;
550 if (!parse_enum(buf, 0, 2, aaa_mode_names, &tmp))
551 return;
553 aaa_mode = tmp;
554 update_statusline();
557 static void toggle_aaa_mode(unsigned int id)
559 editable_lock();
561 /* aaa mode makes no sense in playlist */
562 play_library = 1;
564 aaa_mode++;
565 aaa_mode %= 3;
566 editable_unlock();
567 update_statusline();
570 static void get_repeat(unsigned int id, char *buf)
572 strcpy(buf, bool_names[repeat]);
575 static void set_repeat(unsigned int id, const char *buf)
577 if (!parse_bool(buf, &repeat))
578 return;
579 update_statusline();
582 static void toggle_repeat(unsigned int id)
584 repeat ^= 1;
585 update_statusline();
588 static const char * const replaygain_names[] = {
589 "disabled", "track", "album", NULL
592 static void get_replaygain(unsigned int id, char *buf)
594 strcpy(buf, replaygain_names[replaygain]);
597 static void set_replaygain(unsigned int id, const char *buf)
599 int tmp;
601 if (!parse_enum(buf, 0, 2, replaygain_names, &tmp))
602 return;
603 player_set_rg(tmp);
606 static void toggle_replaygain(unsigned int id)
608 player_set_rg((replaygain + 1) % 3);
611 static void get_replaygain_limit(unsigned int id, char *buf)
613 strcpy(buf, bool_names[replaygain_limit]);
616 static void set_replaygain_limit(unsigned int id, const char *buf)
618 int tmp;
620 if (!parse_bool(buf, &tmp))
621 return;
622 player_set_rg_limit(tmp);
625 static void toggle_replaygain_limit(unsigned int id)
627 player_set_rg_limit(replaygain_limit ^ 1);
630 static void get_show_hidden(unsigned int id, char *buf)
632 strcpy(buf, bool_names[show_hidden]);
635 static void set_show_hidden(unsigned int id, const char *buf)
637 if (!parse_bool(buf, &show_hidden))
638 return;
639 browser_reload();
642 static void toggle_show_hidden(unsigned int id)
644 show_hidden ^= 1;
645 browser_reload();
648 static void get_show_remaining_time(unsigned int id, char *buf)
650 strcpy(buf, bool_names[show_remaining_time]);
653 static void set_show_remaining_time(unsigned int id, const char *buf)
655 if (!parse_bool(buf, &show_remaining_time))
656 return;
657 update_statusline();
660 static void toggle_show_remaining_time(unsigned int id)
662 show_remaining_time ^= 1;
663 update_statusline();
666 static void get_set_term_title(unsigned int id, char *buf)
668 strcpy(buf, bool_names[set_term_title]);
671 static void set_set_term_title(unsigned int id, const char *buf)
673 parse_bool(buf, &set_term_title);
676 static void toggle_set_term_title(unsigned int id)
678 set_term_title ^= 1;
681 static void get_shuffle(unsigned int id, char *buf)
683 strcpy(buf, bool_names[shuffle]);
686 static void set_shuffle(unsigned int id, const char *buf)
688 if (!parse_bool(buf, &shuffle))
689 return;
690 update_statusline();
693 static void toggle_shuffle(unsigned int id)
695 shuffle ^= 1;
696 update_statusline();
699 static void get_softvol(unsigned int id, char *buf)
701 strcpy(buf, bool_names[soft_vol]);
704 static void do_set_softvol(int soft)
706 if (!soft_vol)
707 mixer_close();
708 player_set_soft_vol(soft);
709 if (!soft_vol)
710 mixer_open();
711 update_statusline();
714 static void set_softvol(unsigned int id, const char *buf)
716 int soft;
718 if (!parse_bool(buf, &soft))
719 return;
720 do_set_softvol(soft);
723 static void toggle_softvol(unsigned int id)
725 do_set_softvol(soft_vol ^ 1);
728 /* }}} */
730 /* special callbacks (id set) {{{ */
732 static const char * const color_enum_names[1 + 8 * 2 + 1] = {
733 "default",
734 "black", "red", "green", "yellow", "blue", "magenta", "cyan", "gray",
735 "darkgray", "lightred", "lightgreen", "lightyellow", "lightblue", "lightmagenta", "lightcyan", "white",
736 NULL
739 static void get_color(unsigned int id, char *buf)
741 int val;
743 val = colors[id];
744 if (val < 16) {
745 strcpy(buf, color_enum_names[val + 1]);
746 } else {
747 buf_int(buf, val);
751 static void set_color(unsigned int id, const char *buf)
753 int color;
755 if (!parse_enum(buf, -1, 255, color_enum_names, &color))
756 return;
758 colors[id] = color;
759 update_colors();
760 update_full();
763 static char **id_to_fmt(enum format_id id)
765 switch (id) {
766 case FMT_CURRENT_ALT:
767 return &current_alt_format;
768 case FMT_PLAYLIST_ALT:
769 return &list_win_alt_format;
770 case FMT_TITLE_ALT:
771 return &window_title_alt_format;
772 case FMT_TRACKWIN_ALT:
773 return &track_win_alt_format;
774 case FMT_CURRENT:
775 return &current_format;
776 case FMT_PLAYLIST:
777 return &list_win_format;
778 case FMT_TITLE:
779 return &window_title_format;
780 case FMT_TRACKWIN:
781 return &track_win_format;
783 return NULL;
786 static void get_format(unsigned int id, char *buf)
788 char **fmtp = id_to_fmt(id);
790 strcpy(buf, *fmtp);
793 static void set_format(unsigned int id, const char *buf)
795 char **fmtp = id_to_fmt(id);
797 if (!format_valid(buf)) {
798 error_msg("invalid format string");
799 return;
801 free(*fmtp);
802 *fmtp = xstrdup(buf);
804 update_full();
807 /* }}} */
809 #define DN(name) { #name, get_ ## name, set_ ## name, NULL },
810 #define DT(name) { #name, get_ ## name, set_ ## name, toggle_ ## name },
812 static const struct {
813 const char *name;
814 opt_get_cb get;
815 opt_set_cb set;
816 opt_toggle_cb toggle;
817 } simple_options[] = {
818 DT(aaa_mode)
819 DT(auto_reshuffle)
820 DN(buffer_seconds)
821 DT(confirm_run)
822 DT(continue)
823 DT(fuzzy_artist_sort)
824 DN(id3_default_charset)
825 DN(lib_sort)
826 DN(output_plugin)
827 DN(passwd)
828 DN(pl_sort)
829 DT(play_library)
830 DT(play_sorted)
831 DT(pretty_artist_name)
832 DT(repeat)
833 DT(repeat_current)
834 DT(replaygain)
835 DT(replaygain_limit)
836 DN(replaygain_preamp)
837 DT(show_hidden)
838 DT(show_remaining_time)
839 DT(set_term_title)
840 DT(shuffle)
841 DT(softvol)
842 DN(softvol_state)
843 DN(status_display_program)
844 { NULL, NULL, NULL, NULL }
847 static const char * const color_names[NR_COLORS] = {
848 "color_cmdline_bg",
849 "color_cmdline_fg",
850 "color_error",
851 "color_info",
852 "color_separator",
853 "color_statusline_bg",
854 "color_statusline_fg",
855 "color_titleline_bg",
856 "color_titleline_fg",
857 "color_win_bg",
858 "color_win_cur",
859 "color_win_cur_sel_bg",
860 "color_win_cur_sel_fg",
861 "color_win_dir",
862 "color_win_fg",
863 "color_win_inactive_cur_sel_bg",
864 "color_win_inactive_cur_sel_fg",
865 "color_win_inactive_sel_bg",
866 "color_win_inactive_sel_fg",
867 "color_win_sel_bg",
868 "color_win_sel_fg",
869 "color_win_title_bg",
870 "color_win_title_fg"
873 /* default values for the variables which we must initialize but
874 * can't do it statically */
875 static const struct {
876 const char *name;
877 const char *value;
878 } str_defaults[] = {
879 { "altformat_current", " %F " },
880 { "altformat_playlist", " %f%= %d " },
881 { "altformat_title", "%f" },
882 { "altformat_trackwin", " %f%= %d " },
883 { "format_current", " %a - %l - %02n. %t%= %y " },
884 { "format_playlist", " %-20a %02n. %t%= %y %d " },
885 { "format_title", "%a - %l - %t (%y)" },
886 { "format_trackwin", " %02n. %t%= %y %d " },
888 { "lib_sort" , "artist album discnumber tracknumber title filename" },
889 { "pl_sort", "" },
890 { "id3_default_charset","ISO-8859-1" },
891 { NULL, NULL }
894 LIST_HEAD(option_head);
895 int nr_options = 0;
897 void option_add(const char *name, unsigned int id, opt_get_cb get,
898 opt_set_cb set, opt_toggle_cb toggle)
900 struct cmus_opt *opt = xnew(struct cmus_opt, 1);
901 struct list_head *item;
903 opt->name = name;
904 opt->id = id;
905 opt->get = get;
906 opt->set = set;
907 opt->toggle = toggle;
909 item = option_head.next;
910 while (item != &option_head) {
911 struct cmus_opt *o = container_of(item, struct cmus_opt, node);
913 if (strcmp(name, o->name) < 0)
914 break;
915 item = item->next;
917 /* add before item */
918 list_add_tail(&opt->node, item);
919 nr_options++;
922 struct cmus_opt *option_find(const char *name)
924 struct cmus_opt *opt;
926 list_for_each_entry(opt, &option_head, node) {
927 if (strcmp(name, opt->name) == 0)
928 return opt;
930 error_msg("no such option %s", name);
931 return NULL;
934 void option_set(const char *name, const char *value)
936 struct cmus_opt *opt = option_find(name);
938 if (opt)
939 opt->set(opt->id, value);
942 void options_add(void)
944 int i;
946 for (i = 0; simple_options[i].name; i++)
947 option_add(simple_options[i].name, 0, simple_options[i].get,
948 simple_options[i].set, simple_options[i].toggle);
950 for (i = 0; i < NR_FMTS; i++)
951 option_add(str_defaults[i].name, i, get_format, set_format, NULL);
953 for (i = 0; i < NR_COLORS; i++)
954 option_add(color_names[i], i, get_color, set_color, NULL);
956 op_add_options();
959 static int handle_line(void *data, const char *line)
961 run_command(line);
962 return 0;
965 int source_file(const char *filename)
967 return file_for_each_line(filename, handle_line, NULL);
970 void options_load(void)
972 char filename[512];
973 int i;
975 /* initialize those that can't be statically initialized */
976 for (i = 0; str_defaults[i].name; i++)
977 option_set(str_defaults[i].name, str_defaults[i].value);
979 /* load autosave config */
980 snprintf(filename, sizeof(filename), "%s/autosave", cmus_config_dir);
981 if (source_file(filename) == -1) {
982 const char *def = DATADIR "/cmus/rc";
984 if (errno != ENOENT)
985 error_msg("loading %s: %s", filename, strerror(errno));
987 /* load defaults */
988 if (source_file(def) == -1)
989 die_errno("loading %s", def);
992 /* load optional static config */
993 snprintf(filename, sizeof(filename), "%s/rc", cmus_config_dir);
994 if (source_file(filename) == -1) {
995 if (errno != ENOENT)
996 error_msg("loading %s: %s", filename, strerror(errno));
1000 void options_exit(void)
1002 struct cmus_opt *opt;
1003 struct filter_entry *filt;
1004 char filename[512];
1005 FILE *f;
1006 int i;
1008 snprintf(filename, sizeof(filename), "%s/autosave", cmus_config_dir);
1009 f = fopen(filename, "w");
1010 if (f == NULL) {
1011 warn_errno("creating %s", filename);
1012 return;
1015 /* save options */
1016 list_for_each_entry(opt, &option_head, node) {
1017 char buf[OPTION_MAX_SIZE];
1019 buf[0] = 0;
1020 opt->get(opt->id, buf);
1021 fprintf(f, "set %s=%s\n", opt->name, buf);
1024 /* save key bindings */
1025 for (i = 0; i < NR_CTXS; i++) {
1026 struct binding *b = key_bindings[i];
1028 while (b) {
1029 fprintf(f, "bind %s %s %s\n", key_context_names[i], b->key->name, b->cmd);
1030 b = b->next;
1034 /* save filters */
1035 list_for_each_entry(filt, &filters_head, node)
1036 fprintf(f, "fset %s=%s\n", filt->name, filt->filter);
1037 fprintf(f, "factivate");
1038 list_for_each_entry(filt, &filters_head, node) {
1039 switch (filt->act_stat) {
1040 case FS_YES:
1041 fprintf(f, " %s", filt->name);
1042 break;
1043 case FS_NO:
1044 fprintf(f, " !%s", filt->name);
1045 break;
1048 fprintf(f, "\n");
1050 fclose(f);