Retry only for https protocol
[elinks.git] / src / config / opttypes.c
blob02e7144bb3697c20da9dac5f6e3f509d7e829c02
1 /* Option variables types handlers */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <stdio.h>
8 #include <string.h>
10 #include "elinks.h"
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! :-) */
30 int commandline = 0;
32 static unsigned char *
33 gen_cmd(struct option *o, unsigned char ***argv, int *argc)
35 unsigned char *str;
36 int dummy_line = 0;
38 if (!*argc) return gettext("Parameter expected");
40 /* FIXME!! We will modify argv! (maybe) */
41 commandline = 1;
42 str = option_types[o->type].read(o, *argv, &dummy_line);
43 commandline = 0;
44 if (str) {
45 /* We ate parameter */
46 (*argv)++; (*argc)--;
47 if (option_types[o->type].set(o, str)) {
48 mem_free(str);
49 return NULL;
51 mem_free(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)
62 o->value.number = 1;
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;
72 default: return NULL;
75 /* We ate parameter */
76 (*argv)++; (*argc)--;
77 return NULL;
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;
109 return ret;
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;
128 return ret;
131 static void
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);
143 static int
144 redir_set(struct option *opt, unsigned char *str)
146 struct option *real = get_opt_rec(config_options, opt->value.string);
147 int ret = 0;
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) {
153 long negated;
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);
162 return ret;
165 static int
166 redir_eq(struct option *opt, const unsigned char *str)
168 struct option *real = get_opt_rec(config_options, opt->value.string);
169 int ret = 0;
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) {
175 long negated;
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);
184 return ret;
189 /* Support functions for config file parsing. */
191 static void
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)) {
218 mem_free(value);
219 return NULL;
222 return (unsigned char *) value;
225 static int
226 num_set(struct option *opt, unsigned char *str)
228 /* In num_rd(), num_set(), and num_eq(), str always points
229 * to a long, even though these functions are only used for
230 * OPT_BOOL and OPT_INT, which use int option_value.number.
231 * redir_rd(), redir_set(), and redir_eq() expect this.
232 * So does l_set_option() in the Lua scripting backend. */
233 opt->value.number = *((long *) str);
234 return 1;
237 static int
238 num_eq(struct option *opt, const unsigned char *str)
240 return str && opt->value.number == *(const long *) str;
243 static void
244 num_wr(struct option *option, struct string *string)
246 add_knum_to_string(string, option->value.number);
250 static int
251 long_set(struct option *opt, unsigned char *str)
253 opt->value.big_number = *((long *) str);
254 return 1;
257 static int
258 long_eq(struct option *opt, const unsigned char *str)
260 return str && opt->value.big_number == *(const long *) str;
263 static void
264 long_wr(struct option *option, struct string *string)
266 add_knum_to_string(string, option->value.big_number);
269 static unsigned char *
270 str_rd(struct option *opt, unsigned char **file, int *line)
272 unsigned char *str = *file;
273 struct string str2;
275 if (!init_string(&str2)) return NULL;
277 /* We're getting used in some parser functions in conf.c as well, and
278 * that's w/ opt == NULL; so don't rely on opt to point anywhere. */
279 if (!commandline) {
280 if (!isquote(*str)) {
281 done_string(&str2);
282 return NULL;
284 str++;
287 while (*str && (commandline || !isquote(*str))) {
288 if (*str == '\\') {
289 /* FIXME: This won't work on crlf systems. */
290 if (str[1] == '\n') { str[1] = ' '; str++; (*line)++; }
291 /* When there's quote char, we will just move on there,
292 * thus we will never test for it in while () condition
293 * and we will treat it just as '"', ignoring the
294 * backslash itself. */
295 else if (isquote(str[1])) str++;
296 /* \\ means \. */
297 else if (str[1] == '\\') str++;
300 if (*str == '\n') (*line)++;
302 add_char_to_string(&str2, *str);
303 str++;
306 if (!commandline && !*str) {
307 done_string(&str2);
308 *file = str;
309 return NULL;
312 str++; /* Skip the quote. */
313 if (!commandline) *file = str;
315 if (opt && opt->max && str2.length >= opt->max) {
316 done_string(&str2);
317 return NULL;
320 return str2.source;
323 static int
324 str_set(struct option *opt, unsigned char *str)
326 assert(opt->value.string);
328 safe_strncpy(opt->value.string, str, MAX_STR_LEN);
329 return 1;
332 static int
333 str_eq(struct option *opt, const unsigned char *str)
335 return str && strcmp(opt->value.string, str) == 0;
338 static void
339 str_wr(struct option *o, struct string *s)
341 int len = strlen(o->value.string);
343 int_upper_bound(&len, o->max - 1);
344 add_optstring_to_string(s, o->value.string, len);
347 static void
348 str_dup(struct option *opt, struct option *template_, int flags)
350 unsigned char *new_ = mem_alloc(MAX_STR_LEN);
352 if (new_) safe_strncpy(new_, template_->value.string, MAX_STR_LEN);
353 opt->value.string = new_;
357 static int
358 cp_set(struct option *opt, unsigned char *str)
360 int ret = get_cp_index(str);
362 if (ret < 0) return 0;
364 opt->value.number = ret;
365 return 1;
368 static int
369 cp_eq(struct option *opt, const unsigned char *str)
371 return str && get_cp_index(str) == opt->value.number;
374 static void
375 cp_wr(struct option *o, struct string *s)
377 unsigned char *mime_name = get_cp_config_name(o->value.number);
379 add_optstring_to_string(s, mime_name, strlen(mime_name));
383 static int
384 lang_set(struct option *opt, unsigned char *str)
386 #ifdef CONFIG_NLS
387 opt->value.number = name_to_language(str);
388 set_language(opt->value.number);
389 #endif
390 return 1;
393 static int
394 lang_eq(struct option *opt, const unsigned char *str)
396 #ifdef CONFIG_NLS
397 return str && name_to_language(str) == opt->value.number;
398 #else
399 return 1; /* All languages are the same. */
400 #endif
403 static void
404 lang_wr(struct option *o, struct string *s)
406 unsigned char *lang;
408 #ifdef CONFIG_NLS
409 lang = language_to_name(current_language);
410 #else
411 lang = "System";
412 #endif
414 add_optstring_to_string(s, lang, strlen(lang));
418 static int
419 color_set(struct option *opt, unsigned char *str)
421 return !decode_color(str, strlen(str), &opt->value.color);
424 static int
425 color_eq(struct option *opt, const unsigned char *str)
427 color_T color;
429 return str && !decode_color(str, strlen(str), &color)
430 && color == opt->value.color;
433 static void
434 color_wr(struct option *opt, struct string *str)
436 color_T color = opt->value.color;
437 unsigned char hexcolor[8];
438 const unsigned char *strcolor = get_color_string(color, hexcolor);
440 add_optstring_to_string(str, strcolor, strlen(strcolor));
443 static void
444 tree_dup(struct option *opt, struct option *template_, int flags)
446 LIST_OF(struct option) *new_ = init_options_tree();
447 LIST_OF(struct option) *tree = template_->value.tree;
448 struct option *option;
450 if (!new_) return;
451 opt->value.tree = new_;
453 if (flags & CO_SHALLOW) return;
455 foreachback (option, *tree) {
456 struct option *new_opt = copy_option(option, flags);
458 if (!new_opt) continue;
459 object_nolock(new_opt, "option");
460 add_to_list_end(*new_, new_opt);
461 object_lock(new_opt);
462 new_opt->root = opt;
464 if (!new_opt->box_item) continue;
466 if (new_opt->name && !strcmp(new_opt->name, "_template_"))
467 new_opt->box_item->visible = get_opt_bool("config.show_template", NULL);
469 if (opt->box_item) {
470 add_to_list(opt->box_item->child,
471 new_opt->box_item);
476 const struct option_type_info option_types[] = {
477 /* The OPT_ comments below are here to be found by grep. */
479 /* OPT_BOOL */
480 { N_("Boolean"), bool_cmd, num_rd, num_wr, NULL, num_set, num_eq, N_("[0|1]") },
481 /* OPT_INT */
482 { N_("Integer"), gen_cmd, num_rd, num_wr, NULL, num_set, num_eq, N_("<num>") },
483 /* OPT_LONG */
484 { N_("Longint"), gen_cmd, num_rd, long_wr, NULL, long_set, long_eq, N_("<num>") },
485 /* OPT_STRING */
486 { N_("String"), gen_cmd, str_rd, str_wr, str_dup, str_set, str_eq, N_("<str>") },
488 /* OPT_CODEPAGE */
489 { N_("Codepage"), gen_cmd, str_rd, cp_wr, NULL, cp_set, cp_eq, N_("<codepage>") },
490 /* OPT_LANGUAGE */
491 { N_("Language"), gen_cmd, str_rd, lang_wr, NULL, lang_set, lang_eq, N_("<language>") },
492 /* OPT_COLOR */
493 { N_("Color"), gen_cmd, str_rd, color_wr, NULL, color_set, color_eq, N_("<color|#rrggbb>") },
495 /* OPT_COMMAND */
496 { N_("Special"), exec_cmd, NULL, NULL, NULL, NULL, NULL, "" },
498 /* OPT_ALIAS */
499 { N_("Alias"), redir_cmd, redir_rd, redir_wr, NULL, redir_set, redir_eq, "" },
501 /* OPT_TREE */
502 { N_("Folder"), NULL, NULL, NULL, tree_dup, NULL, NULL, "" },
505 unsigned char *
506 get_option_type_name(enum option_type type)
508 assert(type >= 0 && type < sizeof(option_types)/sizeof(struct option_type_info));
509 if_assert_failed return "";
511 return option_types[type].name;