void toggle_document_option(struct session *ses, unsigned char *option_name) { struct option *option; assert(ses && ses->doc_view && ses->tab && ses->tab->term); if_assert_failed return; if (!ses->doc_view->vs) { nowhere_box(ses->tab->term, NULL); return; } option = get_opt_rec(config_options, option_name); assert(option); if_assert_failed return; if (ses->option) option = get_option_shadow(option, config_options, ses->option); if (!option) return; toggle_option(ses, option); draw_formatted(ses, 1); }
static void redir_wr(struct option *opt, struct string *string) { struct option *real = get_opt_rec(config_options, opt->value.string); assertm(real, "%s aliased to unknown option %s!", opt->name, opt->value.string); if_assert_failed { return; } if (option_types[real->type].write) option_types[real->type].write(real, string); }
static unsigned char * redir_cmd(struct option *opt, unsigned char ***argv, int *argc) { struct option *real = get_opt_rec(config_options, opt->value.string); unsigned char * ret = NULL; assertm(real, "%s aliased to unknown option %s!", opt->name, opt->value.string); if_assert_failed { return ret; } if (option_types[real->type].cmdline) { ret = option_types[real->type].cmdline(real, argv, argc); if ((opt->flags & OPT_ALIAS_NEGATE) && real->type == OPT_BOOL) { real->value.number = !real->value.number; } } return ret; }
static unsigned char * redir_rd(struct option *opt, unsigned char **file, int *line) { struct option *real = get_opt_rec(config_options, opt->value.string); unsigned char *ret = NULL; assertm(real != NULL, "%s aliased to unknown option %s!", opt->name, opt->value.string); if_assert_failed { return ret; } if (option_types[real->type].read) { ret = option_types[real->type].read(real, file, line); if (ret && (opt->flags & OPT_ALIAS_NEGATE) && real->type == OPT_BOOL) { *(long *) ret = !*(long *) ret; } } return ret; }
static int redir_eq(struct option *opt, const unsigned char *str) { struct option *real = get_opt_rec(config_options, opt->value.string); int ret = 0; assertm(real != NULL, "%s aliased to unknown option %s!", opt->name, opt->value.string); if_assert_failed { return ret; } if (option_types[real->type].equals) { long negated; if ((opt->flags & OPT_ALIAS_NEGATE) && real->type == OPT_BOOL) { negated = !*(const long *) str; str = (unsigned char *) &negated; } ret = option_types[real->type].equals(real, str); } return ret; }
static enum parse_error parse_set_common(struct option *opt_tree, struct conf_parsing_state *state, struct string *mirror, int is_system_conf, int want_domain) { const unsigned char *domain_orig = NULL; size_t domain_len = 0; unsigned char *domain_copy = NULL; const unsigned char *optname_orig; size_t optname_len; unsigned char *optname_copy; skip_white(&state->pos); if (!*state->pos.look) return show_parse_error(state, ERROR_PARSE); if (want_domain) { domain_orig = state->pos.look; while (isident(*state->pos.look) || *state->pos.look == '*' || *state->pos.look == '.' || *state->pos.look == '+') state->pos.look++; domain_len = state->pos.look - domain_orig; skip_white(&state->pos); } /* Option name */ optname_orig = state->pos.look; while (is_option_name_char(*state->pos.look) || *state->pos.look == '.') state->pos.look++; optname_len = state->pos.look - optname_orig; skip_white(&state->pos); /* Equal sign */ if (*state->pos.look != '=') return show_parse_error(state, ERROR_PARSE); state->pos.look++; /* '=' */ skip_white(&state->pos); if (!*state->pos.look) return show_parse_error(state, ERROR_VALUE); optname_copy = memacpy(optname_orig, optname_len); if (!optname_copy) return show_parse_error(state, ERROR_NOMEM); if (want_domain) { domain_copy = memacpy(domain_orig, domain_len); if (!domain_copy) { mem_free(optname_copy); return show_parse_error(state, ERROR_NOMEM); } } /* Option value */ { struct option *opt; unsigned char *val; const struct conf_parsing_pos pos_before_value = state->pos; if (want_domain && *domain_copy) { struct option *domain_tree; domain_tree = get_domain_tree(domain_copy); if (!domain_tree) { mem_free(domain_copy); mem_free(optname_copy); skip_option_value(&state->pos); return show_parse_error(state, ERROR_NOMEM); } if (mirror) { opt = get_opt_rec_real(domain_tree, optname_copy); } else { opt = get_opt_rec(opt_tree, optname_copy); if (opt) { opt = get_option_shadow(opt, opt_tree, domain_tree); if (!opt) { mem_free(domain_copy); mem_free(optname_copy); skip_option_value(&state->pos); return show_parse_error(state, ERROR_NOMEM); } } } } else { opt = mirror ? get_opt_rec_real(opt_tree, optname_copy) : get_opt_rec(opt_tree, optname_copy); } if (want_domain) mem_free(domain_copy); domain_copy = NULL; mem_free(optname_copy); optname_copy = NULL; if (!opt || (opt->flags & OPT_HIDDEN)) { show_parse_error(state, ERROR_OPTION); skip_option_value(&state->pos); return ERROR_OPTION; /* TODO: Distinguish between two scenarios: * - A newer version of ELinks has saved an * option that this version does not recognize. * The option must be preserved. (This works.) * - The user has added an option, saved * elinks.conf, restarted ELinks, deleted the * option, and is now saving elinks.conf again. * The option should be rewritten to "unset". * (This does not work yet.) * In both cases, ELinks has no struct option * for that name. Possible fixes: * - If the tree has OPT_AUTOCREATE, then * assume the user had created that option, * and rewrite it to "unset". Otherwise, * keep it. * - When the user deletes an option, just mark * it with OPT_DELETED, and keep it in memory * as long as OPT_TOUCHED is set. */ } if (!option_types[opt->type].read) { show_parse_error(state, ERROR_VALUE); skip_option_value(&state->pos); return ERROR_VALUE; } val = option_types[opt->type].read(opt, &state->pos.look, &state->pos.line); if (!val) { /* The reader function failed. Jump back to * the beginning of the value and skip it with * the generic code. For the error message, * use the line number at the beginning of the * value, because the ending position is not * interesting if there is an unclosed quote. */ state->pos = pos_before_value; show_parse_error(state, ERROR_VALUE); skip_option_value(&state->pos); return ERROR_VALUE; } if (!mirror) { /* loading a configuration file */ if (!option_types[opt->type].set || !option_types[opt->type].set(opt, val)) { mem_free(val); return show_parse_error(state, ERROR_VALUE); } } else if (is_system_conf) { /* scanning a file that will not be rewritten */ struct option *flagsite = indirect_option(opt); if (!(flagsite->flags & OPT_DELETED) && option_types[opt->type].equals && option_types[opt->type].equals(opt, val)) flagsite->flags &= ~OPT_MUST_SAVE; else flagsite->flags |= OPT_MUST_SAVE; } else { /* rewriting a configuration file */ struct option *flagsite = indirect_option(opt); if (flagsite->flags & OPT_DELETED) { /* Replace the "set" command with an * "unset" command. */ add_to_string(mirror, "unset "); add_bytes_to_string(mirror, optname_orig, optname_len); state->mirrored = state->pos.look; } else if (option_types[opt->type].write) { add_bytes_to_string(mirror, state->mirrored, pos_before_value.look - state->mirrored); option_types[opt->type].write(opt, mirror); state->mirrored = state->pos.look; } /* Remember that the option need not be * written to the end of the file. */ flagsite->flags &= ~OPT_MUST_SAVE; } mem_free(val); } return ERROR_NONE; }