1 /* Option variables types handlers */
12 #include "bfu/dialog.h"
13 #include "config/options.h"
14 #include "config/opttypes.h"
15 #include "intl/charsets.h"
16 #include "intl/gettext/libintl.h"
17 #include "util/color.h"
18 #include "util/conv.h"
19 #include "util/error.h"
20 #include "util/memory.h"
21 #include "util/string.h"
24 /* Commandline handlers. */
26 /* TAKE CARE! Remember that your _rd handler can be used for commandline
27 * parameters as well - probably, you don't want to be so syntactically
28 * strict, and _ESPECIALLY_ you don't want to move any file pointers ahead,
29 * since you will parse the commandline _TWO TIMES_! Remember! :-) */
32 static unsigned char *
33 gen_cmd(struct option
*o
, unsigned char ***argv
, int *argc
)
38 if (!*argc
) return gettext("Parameter expected");
40 /* FIXME!! We will modify argv! (maybe) */
42 str
= option_types
[o
->type
].read(o
, *argv
, &dummy_line
);
45 /* We ate parameter */
47 if (option_types
[o
->type
].set(o
, str
)) {
54 return gettext("Read error");
57 /* If 0 follows, disable option and eat 0. If 1 follows, enable option and
58 * eat 1. If anything else follow, enable option and don't eat anything. */
59 static unsigned char *
60 bool_cmd(struct option
*o
, unsigned char ***argv
, int *argc
)
64 if (!*argc
) return NULL
;
66 /* Argument is empty or longer than 1 char.. */
67 if (!(*argv
)[0][0] || (*argv
)[0][1]) return NULL
;
69 switch ((*argv
)[0][0]) {
70 case '0': o
->value
.number
= 0; break;
71 case '1': o
->value
.number
= 1; break;
75 /* We ate parameter */
80 static unsigned char *
81 exec_cmd(struct option
*o
, unsigned char ***argv
, int *argc
)
83 return o
->value
.command(o
, argv
, argc
);
87 /* Wrappers for OPT_ALIAS. */
88 /* Note that they can wrap only to config_options now. I don't think it could be
89 * a problem, but who knows.. however, changing that will be pretty tricky -
90 * possibly changing ptr to structure containing target name and pointer to
91 * options list? --pasky */
93 #define wrap_or_(name_, call_, ret_) \
95 struct option *real = get_opt_rec(config_options, opt->value.string); \
97 assertm(real, "%s aliased to unknown option %s!", opt->name, opt->value.string); \
98 if_assert_failed { return ret_; } \
100 if (option_types[real->type].name_) \
101 return option_types[real->type].call_; \
106 static unsigned char *
107 redir_cmd(struct option
*opt
, unsigned char ***argv
, int *argc
)
109 struct option
*real
= get_opt_rec(config_options
, opt
->value
.string
);
110 unsigned char * ret
= NULL
;
112 assertm(real
, "%s aliased to unknown option %s!", opt
->name
, opt
->value
.string
);
113 if_assert_failed
{ return ret
; }
115 if (option_types
[real
->type
].cmdline
) {
116 ret
= option_types
[real
->type
].cmdline(real
, argv
, argc
);
117 if ((opt
->flags
& OPT_ALIAS_NEGATE
) && real
->type
== OPT_BOOL
) {
118 real
->value
.number
= !real
->value
.number
;
125 static unsigned char *
126 redir_rd(struct option
*opt
, unsigned char **file
, int *line
)
127 wrap_or_(read
, read(real
, file
, line
), NULL
);
130 redir_wr(struct option
*opt
, struct string
*string
)
132 struct option
*real
= get_opt_rec(config_options
, opt
->value
.string
);
134 assertm(real
, "%s aliased to unknown option %s!", opt
->name
, opt
->value
.string
);
135 if_assert_failed
{ return; }
137 if (option_types
[real
->type
].write
)
138 option_types
[real
->type
].write(real
, string
);
142 redir_set(struct option
*opt
, unsigned char *str
)
144 struct option
*real
= get_opt_rec(config_options
, opt
->value
.string
);
147 assertm(real
, "%s aliased to unknown option %s!", opt
->name
, opt
->value
.string
);
148 if_assert_failed
{ return ret
; }
150 if (option_types
[real
->type
].set
) {
153 if ((opt
->flags
& OPT_ALIAS_NEGATE
) && real
->type
== OPT_BOOL
) {
154 negated
= !*(long *) str
;
155 str
= (unsigned char *) &negated
;
157 ret
= option_types
[real
->type
].set(real
, str
);
165 /* Support functions for config file parsing. */
168 add_optstring_to_string(struct string
*s
, unsigned char *q
, int qlen
)
170 if (!commandline
) add_char_to_string(s
, '"');
171 add_quoted_to_string(s
, q
, qlen
);
172 if (!commandline
) add_char_to_string(s
, '"');
175 /* Config file handlers. */
177 static unsigned char *
178 num_rd(struct option
*opt
, unsigned char **file
, int *line
)
180 unsigned char *end
= *file
;
181 long *value
= mem_alloc(sizeof(*value
));
183 if (!value
) return NULL
;
185 /* We don't want to move file if (commandline), but strtolx() second
186 * parameter must not be NULL. */
187 *value
= strtolx(*file
, &end
);
188 if (!commandline
) *file
= end
;
190 /* Another trap for unwary - we need to check *end, not **file - reason
191 * is left as an exercise to the reader. */
192 if ((*end
!= 0 && (commandline
|| (!isspace(*end
) && *end
!= '#')))
193 || (*value
< opt
->min
|| *value
> opt
->max
)) {
198 return (unsigned char *) value
;
202 num_set(struct option
*opt
, unsigned char *str
)
204 opt
->value
.number
= *((long *) str
);
209 num_wr(struct option
*option
, struct string
*string
)
211 add_knum_to_string(string
, option
->value
.number
);
216 long_set(struct option
*opt
, unsigned char *str
)
218 opt
->value
.big_number
= *((long *) str
);
223 long_wr(struct option
*option
, struct string
*string
)
225 add_knum_to_string(string
, option
->value
.big_number
);
228 static unsigned char *
229 str_rd(struct option
*opt
, unsigned char **file
, int *line
)
231 unsigned char *str
= *file
;
234 if (!init_string(&str2
)) return NULL
;
236 /* We're getting used in some parser functions in conf.c as well, and
237 * that's w/ opt == NULL; so don't rely on opt to point anywhere. */
239 if (!isquote(*str
)) {
246 while (*str
&& (commandline
|| !isquote(*str
))) {
248 /* FIXME: This won't work on crlf systems. */
249 if (str
[1] == '\n') { str
[1] = ' '; str
++; }
250 /* When there's quote char, we will just move on there,
251 * thus we will never test for it in while () condition
252 * and we will treat it just as '"', ignoring the
253 * backslash itself. */
254 else if (isquote(str
[1])) str
++;
256 else if (str
[1] == '\\') str
++;
259 if (*str
== '\n') (*line
)++;
261 add_char_to_string(&str2
, *str
);
265 if (!commandline
&& !*str
) {
271 str
++; /* Skip the quote. */
272 if (!commandline
) *file
= str
;
274 if (opt
&& opt
->max
&& str2
.length
>= opt
->max
) {
283 str_set(struct option
*opt
, unsigned char *str
)
285 assert(opt
->value
.string
);
287 safe_strncpy(opt
->value
.string
, str
, MAX_STR_LEN
);
292 str_wr(struct option
*o
, struct string
*s
)
294 int len
= strlen(o
->value
.string
);
296 int_upper_bound(&len
, o
->max
- 1);
297 add_optstring_to_string(s
, o
->value
.string
, len
);
301 str_dup(struct option
*opt
, struct option
*template)
303 unsigned char *new = mem_alloc(MAX_STR_LEN
);
305 if (new) safe_strncpy(new, template->value
.string
, MAX_STR_LEN
);
306 opt
->value
.string
= new;
311 cp_set(struct option
*opt
, unsigned char *str
)
313 int ret
= get_cp_index(str
);
315 if (ret
< 0) return 0;
317 opt
->value
.number
= ret
;
322 cp_wr(struct option
*o
, struct string
*s
)
324 unsigned char *mime_name
= get_cp_mime_name(o
->value
.number
);
326 add_optstring_to_string(s
, mime_name
, strlen(mime_name
));
331 lang_set(struct option
*opt
, unsigned char *str
)
334 opt
->value
.number
= name_to_language(str
);
335 set_language(opt
->value
.number
);
341 lang_wr(struct option
*o
, struct string
*s
)
346 lang
= language_to_name(current_language
);
351 add_optstring_to_string(s
, lang
, strlen(lang
));
356 color_set(struct option
*opt
, unsigned char *str
)
358 return !decode_color(str
, strlen(str
), &opt
->value
.color
);
362 color_wr(struct option
*opt
, struct string
*str
)
364 color_T color
= opt
->value
.color
;
365 unsigned char hexcolor
[8];
366 unsigned char *strcolor
= get_color_string(color
, hexcolor
);
368 add_optstring_to_string(str
, strcolor
, strlen(strcolor
));
372 tree_dup(struct option
*opt
, struct option
*template)
374 struct list_head
*new = init_options_tree();
375 struct list_head
*tree
= template->value
.tree
;
376 struct option
*option
;
379 opt
->value
.tree
= new;
381 foreachback (option
, *tree
) {
382 struct option
*new_opt
= copy_option(option
);
384 if (!new_opt
) continue;
385 add_to_list_end(*new, new_opt
);
388 if (!new_opt
->box_item
) continue;
390 if (new_opt
->name
&& !strcmp(new_opt
->name
, "_template_"))
391 new_opt
->box_item
->visible
= get_opt_bool("config.show_template");
394 add_to_list(opt
->box_item
->child
,
400 const struct option_type_info option_types
[] = {
401 /* The OPT_ comments below are here to be found by grep. */
404 { N_("Boolean"), bool_cmd
, num_rd
, num_wr
, NULL
, num_set
, N_("[0|1]") },
406 { N_("Integer"), gen_cmd
, num_rd
, num_wr
, NULL
, num_set
, N_("<num>") },
408 { N_("Longint"), gen_cmd
, num_rd
, long_wr
, NULL
, long_set
, N_("<num>") },
410 { N_("String"), gen_cmd
, str_rd
, str_wr
, str_dup
, str_set
, N_("<str>") },
413 { N_("Codepage"), gen_cmd
, str_rd
, cp_wr
, NULL
, cp_set
, N_("<codepage>") },
415 { N_("Language"), gen_cmd
, str_rd
, lang_wr
, NULL
, lang_set
, N_("<language>") },
417 { N_("Color"), gen_cmd
, str_rd
, color_wr
, NULL
, color_set
, N_("<color|#rrggbb>") },
420 { N_("Special"), exec_cmd
, NULL
, NULL
, NULL
, NULL
, "" },
423 { N_("Alias"), redir_cmd
, redir_rd
, redir_wr
, NULL
, redir_set
, "" },
426 { N_("Folder"), NULL
, NULL
, NULL
, tree_dup
, NULL
, "" },
430 get_option_type_name(enum option_type type
)
432 assert(type
>= 0 && type
< sizeof(option_types
)/sizeof(struct option_type_info
));
433 if_assert_failed
return "";
435 return option_types
[type
].name
;