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
);
167 /* Support functions for config file parsing. */
170 add_optstring_to_string(struct string
*s
, const unsigned char *q
, int qlen
)
172 if (!commandline
) add_char_to_string(s
, '"');
173 add_quoted_to_string(s
, q
, qlen
);
174 if (!commandline
) add_char_to_string(s
, '"');
177 /* Config file handlers. */
179 static unsigned char *
180 num_rd(struct option
*opt
, unsigned char **file
, int *line
)
182 unsigned char *end
= *file
;
183 long *value
= mem_alloc(sizeof(*value
));
185 if (!value
) return NULL
;
187 /* We don't want to move file if (commandline), but strtolx() second
188 * parameter must not be NULL. */
189 *value
= strtolx(*file
, &end
);
190 if (!commandline
) *file
= end
;
192 /* Another trap for unwary - we need to check *end, not **file - reason
193 * is left as an exercise to the reader. */
194 if ((*end
!= 0 && (commandline
|| (!isspace(*end
) && *end
!= '#')))
195 || (*value
< opt
->min
|| *value
> opt
->max
)) {
200 return (unsigned char *) value
;
204 num_set(struct option
*opt
, unsigned char *str
)
206 opt
->value
.number
= *((long *) str
);
211 num_wr(struct option
*option
, struct string
*string
)
213 add_knum_to_string(string
, option
->value
.number
);
218 long_set(struct option
*opt
, unsigned char *str
)
220 opt
->value
.big_number
= *((long *) str
);
225 long_wr(struct option
*option
, struct string
*string
)
227 add_knum_to_string(string
, option
->value
.big_number
);
230 static unsigned char *
231 str_rd(struct option
*opt
, unsigned char **file
, int *line
)
233 unsigned char *str
= *file
;
236 if (!init_string(&str2
)) return NULL
;
238 /* We're getting used in some parser functions in conf.c as well, and
239 * that's w/ opt == NULL; so don't rely on opt to point anywhere. */
241 if (!isquote(*str
)) {
248 while (*str
&& (commandline
|| !isquote(*str
))) {
250 /* FIXME: This won't work on crlf systems. */
251 if (str
[1] == '\n') { str
[1] = ' '; str
++; }
252 /* When there's quote char, we will just move on there,
253 * thus we will never test for it in while () condition
254 * and we will treat it just as '"', ignoring the
255 * backslash itself. */
256 else if (isquote(str
[1])) str
++;
258 else if (str
[1] == '\\') str
++;
261 if (*str
== '\n') (*line
)++;
263 add_char_to_string(&str2
, *str
);
267 if (!commandline
&& !*str
) {
273 str
++; /* Skip the quote. */
274 if (!commandline
) *file
= str
;
276 if (opt
&& opt
->max
&& str2
.length
>= opt
->max
) {
285 str_set(struct option
*opt
, unsigned char *str
)
287 assert(opt
->value
.string
);
289 safe_strncpy(opt
->value
.string
, str
, MAX_STR_LEN
);
294 str_wr(struct option
*o
, struct string
*s
)
296 int len
= strlen(o
->value
.string
);
298 int_upper_bound(&len
, o
->max
- 1);
299 add_optstring_to_string(s
, o
->value
.string
, len
);
303 str_dup(struct option
*opt
, struct option
*template)
305 unsigned char *new = mem_alloc(MAX_STR_LEN
);
307 if (new) safe_strncpy(new, template->value
.string
, MAX_STR_LEN
);
308 opt
->value
.string
= new;
313 cp_set(struct option
*opt
, unsigned char *str
)
315 int ret
= get_cp_index(str
);
317 if (ret
< 0) return 0;
319 opt
->value
.number
= ret
;
324 cp_wr(struct option
*o
, struct string
*s
)
326 unsigned char *mime_name
= get_cp_config_name(o
->value
.number
);
328 add_optstring_to_string(s
, mime_name
, strlen(mime_name
));
333 lang_set(struct option
*opt
, unsigned char *str
)
336 opt
->value
.number
= name_to_language(str
);
337 set_language(opt
->value
.number
);
343 lang_wr(struct option
*o
, struct string
*s
)
348 lang
= language_to_name(current_language
);
353 add_optstring_to_string(s
, lang
, strlen(lang
));
358 color_set(struct option
*opt
, unsigned char *str
)
360 return !decode_color(str
, strlen(str
), &opt
->value
.color
);
364 color_wr(struct option
*opt
, struct string
*str
)
366 color_T color
= opt
->value
.color
;
367 unsigned char hexcolor
[8];
368 const unsigned char *strcolor
= get_color_string(color
, hexcolor
);
370 add_optstring_to_string(str
, strcolor
, strlen(strcolor
));
374 tree_dup(struct option
*opt
, struct option
*template)
376 LIST_OF(struct option
) *new = init_options_tree();
377 LIST_OF(struct option
) *tree
= template->value
.tree
;
378 struct option
*option
;
381 opt
->value
.tree
= new;
383 foreachback (option
, *tree
) {
384 struct option
*new_opt
= copy_option(option
);
386 if (!new_opt
) continue;
387 object_nolock(new_opt
, "option");
388 add_to_list_end(*new, new_opt
);
391 if (!new_opt
->box_item
) continue;
393 if (new_opt
->name
&& !strcmp(new_opt
->name
, "_template_"))
394 new_opt
->box_item
->visible
= get_opt_bool("config.show_template");
397 add_to_list(opt
->box_item
->child
,
403 const struct option_type_info option_types
[] = {
404 /* The OPT_ comments below are here to be found by grep. */
407 { N_("Boolean"), bool_cmd
, num_rd
, num_wr
, NULL
, num_set
, N_("[0|1]") },
409 { N_("Integer"), gen_cmd
, num_rd
, num_wr
, NULL
, num_set
, N_("<num>") },
411 { N_("Longint"), gen_cmd
, num_rd
, long_wr
, NULL
, long_set
, N_("<num>") },
413 { N_("String"), gen_cmd
, str_rd
, str_wr
, str_dup
, str_set
, N_("<str>") },
416 { N_("Codepage"), gen_cmd
, str_rd
, cp_wr
, NULL
, cp_set
, N_("<codepage>") },
418 { N_("Language"), gen_cmd
, str_rd
, lang_wr
, NULL
, lang_set
, N_("<language>") },
420 { N_("Color"), gen_cmd
, str_rd
, color_wr
, NULL
, color_set
, N_("<color|#rrggbb>") },
423 { N_("Special"), exec_cmd
, NULL
, NULL
, NULL
, NULL
, "" },
426 { N_("Alias"), redir_cmd
, redir_rd
, redir_wr
, NULL
, redir_set
, "" },
429 { N_("Folder"), NULL
, NULL
, NULL
, tree_dup
, NULL
, "" },
433 get_option_type_name(enum option_type type
)
435 assert(type
>= 0 && type
< sizeof(option_types
)/sizeof(struct option_type_info
));
436 if_assert_failed
return "";
438 return option_types
[type
].name
;