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 static unsigned char *
94 redir_cmd(struct option
*opt
, unsigned char ***argv
, int *argc
)
96 struct option
*real
= get_opt_rec(config_options
, opt
->value
.string
);
97 unsigned char * ret
= NULL
;
99 assertm(real
!= NULL
, "%s aliased to unknown option %s!", opt
->name
, opt
->value
.string
);
100 if_assert_failed
{ return ret
; }
102 if (option_types
[real
->type
].cmdline
) {
103 ret
= option_types
[real
->type
].cmdline(real
, argv
, argc
);
104 if ((opt
->flags
& OPT_ALIAS_NEGATE
) && real
->type
== OPT_BOOL
) {
105 real
->value
.number
= !real
->value
.number
;
112 static unsigned char *
113 redir_rd(struct option
*opt
, unsigned char **file
, int *line
)
115 struct option
*real
= get_opt_rec(config_options
, opt
->value
.string
);
116 unsigned char *ret
= NULL
;
118 assertm(real
!= NULL
, "%s aliased to unknown option %s!", opt
->name
, opt
->value
.string
);
119 if_assert_failed
{ return ret
; }
121 if (option_types
[real
->type
].read
) {
122 ret
= option_types
[real
->type
].read(real
, file
, line
);
123 if (ret
&& (opt
->flags
& OPT_ALIAS_NEGATE
) && real
->type
== OPT_BOOL
) {
124 *(long *) ret
= !*(long *) ret
;
132 redir_wr(struct option
*opt
, struct string
*string
)
134 struct option
*real
= get_opt_rec(config_options
, opt
->value
.string
);
136 assertm(real
!= NULL
, "%s aliased to unknown option %s!", opt
->name
, opt
->value
.string
);
137 if_assert_failed
{ return; }
139 if (option_types
[real
->type
].write
)
140 option_types
[real
->type
].write(real
, string
);
144 redir_set(struct option
*opt
, unsigned char *str
)
146 struct option
*real
= get_opt_rec(config_options
, opt
->value
.string
);
149 assertm(real
!= NULL
, "%s aliased to unknown option %s!", opt
->name
, opt
->value
.string
);
150 if_assert_failed
{ return ret
; }
152 if (option_types
[real
->type
].set
) {
155 if ((opt
->flags
& OPT_ALIAS_NEGATE
) && real
->type
== OPT_BOOL
) {
156 negated
= !*(long *) str
;
157 str
= (unsigned char *) &negated
;
159 ret
= option_types
[real
->type
].set(real
, str
);
166 redir_eq(struct option
*opt
, const unsigned char *str
)
168 struct option
*real
= get_opt_rec(config_options
, opt
->value
.string
);
171 assertm(real
!= NULL
, "%s aliased to unknown option %s!", opt
->name
, opt
->value
.string
);
172 if_assert_failed
{ return ret
; }
174 if (option_types
[real
->type
].equals
) {
177 if ((opt
->flags
& OPT_ALIAS_NEGATE
) && real
->type
== OPT_BOOL
) {
178 negated
= !*(const long *) str
;
179 str
= (unsigned char *) &negated
;
181 ret
= option_types
[real
->type
].equals(real
, str
);
189 /* Support functions for config file parsing. */
192 add_optstring_to_string(struct string
*s
, const unsigned char *q
, int qlen
)
194 if (!commandline
) add_char_to_string(s
, '"');
195 add_quoted_to_string(s
, q
, qlen
);
196 if (!commandline
) add_char_to_string(s
, '"');
199 /* Config file handlers. */
201 static unsigned char *
202 num_rd(struct option
*opt
, unsigned char **file
, int *line
)
204 unsigned char *end
= *file
;
205 long *value
= mem_alloc(sizeof(*value
));
207 if (!value
) return NULL
;
209 /* We don't want to move file if (commandline), but strtolx() second
210 * parameter must not be NULL. */
211 *value
= strtolx(*file
, &end
);
212 if (!commandline
) *file
= end
;
214 /* Another trap for unwary - we need to check *end, not **file - reason
215 * is left as an exercise to the reader. */
216 if ((*end
!= 0 && (commandline
|| (!isspace(*end
) && *end
!= '#')))
217 || (*value
< opt
->min
|| *value
> opt
->max
)) {
222 return (unsigned char *) value
;
226 num_set(struct option
*opt
, unsigned char *str
)
228 opt
->value
.number
= *((long *) str
);
233 num_eq(struct option
*opt
, const unsigned char *str
)
235 return str
&& opt
->value
.number
== *(const long *) str
;
239 num_wr(struct option
*option
, struct string
*string
)
241 add_knum_to_string(string
, option
->value
.number
);
246 long_set(struct option
*opt
, unsigned char *str
)
248 opt
->value
.big_number
= *((long *) str
);
253 long_eq(struct option
*opt
, const unsigned char *str
)
255 return str
&& opt
->value
.big_number
== *(const long *) str
;
259 long_wr(struct option
*option
, struct string
*string
)
261 add_knum_to_string(string
, option
->value
.big_number
);
264 static unsigned char *
265 str_rd(struct option
*opt
, unsigned char **file
, int *line
)
267 unsigned char *str
= *file
;
270 if (!init_string(&str2
)) return NULL
;
272 /* We're getting used in some parser functions in conf.c as well, and
273 * that's w/ opt == NULL; so don't rely on opt to point anywhere. */
275 if (!isquote(*str
)) {
282 while (*str
&& (commandline
|| !isquote(*str
))) {
284 /* FIXME: This won't work on crlf systems. */
285 if (str
[1] == '\n') { str
[1] = ' '; str
++; (*line
)++; }
286 /* When there's quote char, we will just move on there,
287 * thus we will never test for it in while () condition
288 * and we will treat it just as '"', ignoring the
289 * backslash itself. */
290 else if (isquote(str
[1])) str
++;
292 else if (str
[1] == '\\') str
++;
295 if (*str
== '\n') (*line
)++;
297 add_char_to_string(&str2
, *str
);
301 if (!commandline
&& !*str
) {
307 str
++; /* Skip the quote. */
308 if (!commandline
) *file
= str
;
310 if (opt
&& opt
->max
&& str2
.length
>= opt
->max
) {
319 str_set(struct option
*opt
, unsigned char *str
)
321 assert(opt
->value
.string
);
323 safe_strncpy(opt
->value
.string
, str
, MAX_STR_LEN
);
328 str_eq(struct option
*opt
, const unsigned char *str
)
330 return str
&& strcmp(opt
->value
.string
, str
) == 0;
334 str_wr(struct option
*o
, struct string
*s
)
336 int len
= strlen(o
->value
.string
);
338 int_upper_bound(&len
, o
->max
- 1);
339 add_optstring_to_string(s
, o
->value
.string
, len
);
343 str_dup(struct option
*opt
, struct option
*template, int flags
)
345 unsigned char *new = mem_alloc(MAX_STR_LEN
);
347 if (new) safe_strncpy(new, template->value
.string
, MAX_STR_LEN
);
348 opt
->value
.string
= new;
353 cp_set(struct option
*opt
, unsigned char *str
)
355 int ret
= get_cp_index(str
);
357 if (ret
< 0) return 0;
359 opt
->value
.number
= ret
;
364 cp_eq(struct option
*opt
, const unsigned char *str
)
366 return str
&& get_cp_index(str
) == opt
->value
.number
;
370 cp_wr(struct option
*o
, struct string
*s
)
372 unsigned char *mime_name
= get_cp_config_name(o
->value
.number
);
374 add_optstring_to_string(s
, mime_name
, strlen(mime_name
));
379 lang_set(struct option
*opt
, unsigned char *str
)
382 opt
->value
.number
= name_to_language(str
);
383 set_language(opt
->value
.number
);
389 lang_eq(struct option
*opt
, const unsigned char *str
)
392 return str
&& name_to_language(str
) == opt
->value
.number
;
394 return 1; /* All languages are the same. */
399 lang_wr(struct option
*o
, struct string
*s
)
404 lang
= language_to_name(current_language
);
409 add_optstring_to_string(s
, lang
, strlen(lang
));
414 color_set(struct option
*opt
, unsigned char *str
)
416 return !decode_color(str
, strlen(str
), &opt
->value
.color
);
420 color_eq(struct option
*opt
, const unsigned char *str
)
424 return str
&& !decode_color(str
, strlen(str
), &color
)
425 && color
== opt
->value
.color
;
429 color_wr(struct option
*opt
, struct string
*str
)
431 color_T color
= opt
->value
.color
;
432 unsigned char hexcolor
[8];
433 const unsigned char *strcolor
= get_color_string(color
, hexcolor
);
435 add_optstring_to_string(str
, strcolor
, strlen(strcolor
));
439 tree_dup(struct option
*opt
, struct option
*template, int flags
)
441 LIST_OF(struct option
) *new = init_options_tree();
442 LIST_OF(struct option
) *tree
= template->value
.tree
;
443 struct option
*option
;
446 opt
->value
.tree
= new;
448 if (flags
& CO_SHALLOW
) return;
450 foreachback (option
, *tree
) {
451 struct option
*new_opt
= copy_option(option
, flags
);
453 if (!new_opt
) continue;
454 object_nolock(new_opt
, "option");
455 add_to_list_end(*new, new_opt
);
456 object_lock(new_opt
);
459 if (!new_opt
->box_item
) continue;
461 if (new_opt
->name
&& !strcmp(new_opt
->name
, "_template_"))
462 new_opt
->box_item
->visible
= get_opt_bool("config.show_template", NULL
);
465 add_to_list(opt
->box_item
->child
,
471 const struct option_type_info option_types
[] = {
472 /* The OPT_ comments below are here to be found by grep. */
475 { N_("Boolean"), bool_cmd
, num_rd
, num_wr
, NULL
, num_set
, num_eq
, N_("[0|1]") },
477 { N_("Integer"), gen_cmd
, num_rd
, num_wr
, NULL
, num_set
, num_eq
, N_("<num>") },
479 { N_("Longint"), gen_cmd
, num_rd
, long_wr
, NULL
, long_set
, long_eq
, N_("<num>") },
481 { N_("String"), gen_cmd
, str_rd
, str_wr
, str_dup
, str_set
, str_eq
, N_("<str>") },
484 { N_("Codepage"), gen_cmd
, str_rd
, cp_wr
, NULL
, cp_set
, cp_eq
, N_("<codepage>") },
486 { N_("Language"), gen_cmd
, str_rd
, lang_wr
, NULL
, lang_set
, lang_eq
, N_("<language>") },
488 { N_("Color"), gen_cmd
, str_rd
, color_wr
, NULL
, color_set
, color_eq
, N_("<color|#rrggbb>") },
491 { N_("Special"), exec_cmd
, NULL
, NULL
, NULL
, NULL
, NULL
, "" },
494 { N_("Alias"), redir_cmd
, redir_rd
, redir_wr
, NULL
, redir_set
, redir_eq
, "" },
497 { N_("Folder"), NULL
, NULL
, NULL
, tree_dup
, NULL
, NULL
, "" },
501 get_option_type_name(enum option_type type
)
503 assert(type
>= 0 && type
< sizeof(option_types
)/sizeof(struct option_type_info
));
504 if_assert_failed
return "";
506 return option_types
[type
].name
;