📄 conf.c
字号:
while (!isspace(*file) && *file != '#' && *file) file++; /* Mirror what we already have */ if (mirror) add_bytes_to_string(mirror, orig_pos, file - orig_pos); } if (!mirror && err) { /* TODO: Make this a macro and report error directly * as it's stumbled upon; line info may not be accurate * anymore now (?). --pasky */ if (verbose >= VERBOSE_WARNINGS) { fprintf(stderr, "%s:%d: %s\n", name, line, error_msg[err]); error_occured = 1; } err = 0; } } if (!error_occured) return; /* If an error occurred make sure that the user is notified and is able * to see it. First sound the bell. Then, if the text viewer is going to * be started, sleep for a while so the message will be visible before * ELinks starts drawing to on the screen and overwriting any error * messages. This should not be necessary for terminals supporting the * alternate screen mode but better to be safe. (debian bug 305017) */ fputc('\a', stderr); if (get_cmd_opt_bool("dump") || get_cmd_opt_bool("source")) return; sleep(1);}static unsigned char *read_config_file(unsigned char *name){#define FILE_BUF 1024 unsigned char cfg_buffer[FILE_BUF]; struct string string; int fd, r; fd = open(name, O_RDONLY | O_NOCTTY); if (fd < 0) return NULL; set_bin(fd); if (!init_string(&string)) return NULL; while ((r = safe_read(fd, cfg_buffer, FILE_BUF)) > 0) { int i; /* Clear problems ;). */ for (i = 0; i < r; i++) if (!cfg_buffer[i]) cfg_buffer[i] = ' '; add_bytes_to_string(&string, cfg_buffer, r); } if (r < 0) done_string(&string); close(fd); return string.source;#undef FILE_BUF}/* Return 0 on success. */static intload_config_file(unsigned char *prefix, unsigned char *name, struct option *options, struct string *mirror){ unsigned char *config_str, *config_file; config_file = straconcat(prefix, "/", name, NULL); if (!config_file) return 1; config_str = read_config_file(config_file); if (!config_str) { mem_free(config_file); config_file = straconcat(prefix, "/.", name, NULL); if (!config_file) return 2; config_str = read_config_file(config_file); if (!config_str) { mem_free(config_file); return 3; } } parse_config_file(options, config_file, config_str, mirror); mem_free(config_str); mem_free(config_file); return 0;}static voidload_config_from(unsigned char *file, struct option *tree){ load_config_file(CONFDIR, file, tree, NULL); load_config_file(empty_string_or_(elinks_home), file, tree, NULL);}voidload_config(void){ load_config_from(get_cmd_opt_str("config-file"), config_options);}static int indentation = 2;/* 0 -> none, 1 -> only option full name+type, 2 -> only desc, 3 -> both */static int comments = 3;static int touching = 0;static inline unsigned char *conf_i18n(unsigned char *s, int i18n){ if (i18n) return gettext(s); return s;}static voidadd_indent_to_string(struct string *string, int depth){ if (!depth) return; add_xchar_to_string(string, ' ', depth * indentation);}static voidsmart_config_output_fn(struct string *string, struct option *option, unsigned char *path, int depth, int do_print_comment, int action, int i18n){ unsigned char *desc_i18n; if (option->type == OPT_ALIAS) return; /* XXX: OPT_LANGUAGE shouldn't have any bussiness here, but we're just * weird in that area. */ if (touching && !(option->flags & OPT_TOUCHED) && option->type != OPT_LANGUAGE) return; switch (action) { case 0: if (!(comments & 1)) break; add_indent_to_string(string, depth); add_to_string(string, "## "); if (path) { add_to_string(string, path); add_char_to_string(string, '.'); } add_to_string(string, option->name); add_char_to_string(string, ' '); add_to_string(string, option_types[option->type].help_str); add_char_to_string(string, '\n'); break; case 1: if (!(comments & 2)) break; if (!option->desc || !do_print_comment) break; desc_i18n = conf_i18n(option->desc, i18n); if (!*desc_i18n) break; add_indent_to_string(string, depth); add_to_string(string, "# "); { unsigned char *i = desc_i18n; unsigned char *j = i; unsigned char *last_space = NULL; int config_width = 80; int n = depth * indentation + 3; for (; *i; i++, n++) { if (*i == '\n') { last_space = i; goto split; } if (*i == ' ') last_space = i; if (n >= config_width && last_space) {split: add_bytes_to_string(string, j, last_space - j); add_char_to_string(string, '\n'); add_indent_to_string(string, depth); add_to_string(string, "# "); j = last_space + 1; n = depth * indentation + 2 + i - last_space; last_space = NULL; } } add_to_string(string, j); } add_char_to_string(string, '\n'); break; case 2: add_indent_to_string(string, depth); if (option->flags & OPT_DELETED) { add_to_string(string, "un"); } add_to_string(string, "set "); if (path) { add_to_string(string, path); add_char_to_string(string, '.'); } add_to_string(string, option->name); if (!(option->flags & OPT_DELETED)) { add_to_string(string, " = "); /* OPT_ALIAS won't ever. OPT_TREE won't reach action 2. * OPT_SPECIAL makes no sense in the configuration * context. */ assert(option_types[option->type].write); option_types[option->type].write(option, string); } add_char_to_string(string, '\n'); if (do_print_comment) add_char_to_string(string, '\n'); break; case 3: if (do_print_comment < 2) add_char_to_string(string, '\n'); break; }}static voidadd_cfg_header_to_string(struct string *string, unsigned char *text){ int n = strlen(text) + 2; int_bounds(&n, 10, 80); add_to_string(string, "\n\n\n"); add_xchar_to_string(string, '#', n); add_to_string(string, "\n# "); add_to_string(string, text); add_to_string(string, "#\n\n");}unsigned char *create_config_string(unsigned char *prefix, unsigned char *name, struct option *options){ struct string config; /* Don't write headers if nothing will be added anyway. */ struct string tmpstring; int origlen; int savestyle = get_opt_int("config.saving_style"); int i18n = get_opt_bool("config.i18n"); if (!init_string(&config)) return NULL; if (savestyle == 3) { touching = 1; savestyle = 1; } else { touching = 0; } if (savestyle == 2) watermark_deleted_options(options->value.tree); /* Scaring. */ if (savestyle == 2 || (savestyle < 2 && (load_config_file(prefix, name, options, &config) || !config.length))) { /* At first line, and in English, write ELinks version, may be * of some help in future. Please keep that format for it. * --Zas */ add_to_string(&config, "## ELinks " VERSION " configuration file\n\n"); assert(savestyle >= 0 && savestyle <= 2); switch (savestyle) { case 0: add_to_string(&config, conf_i18n(N_( "## This is ELinks configuration file. You can edit it manually,\n" "## if you wish so; this file is edited by ELinks when you save\n" "## options through UI, however only option values will be altered\n" "## and all your formatting, own comments etc will be kept as-is.\n"), i18n)); break; case 1: add_to_string(&config, conf_i18n(N_( "## This is ELinks configuration file. You can edit it manually,\n" "## if you wish so; this file is edited by ELinks when you save\n" "## options through UI, however only option values will be altered\n" "## and missing options will be added at the end of file; if option\n" "## is not written in this file, but in some file included from it,\n" "## it is NOT counted as missing. Note that all your formatting,\n" "## own comments and so on will be kept as-is.\n"), i18n)); break; case 2: add_to_string(&config, conf_i18n(N_( "## This is ELinks configuration file. You can edit it manually,\n" "## if you wish so, but keep in mind that this file is overwritten\n" "## by ELinks when you save options through UI and you are out of\n" "## luck with your formatting and own comments then, so beware.\n"), i18n)); break; } add_to_string(&config, "##\n"); add_to_string(&config, conf_i18n(N_( "## Obviously, if you don't like what ELinks is going to do with\n" "## this file, you can change it by altering the config.saving_style\n" "## option. Come on, aren't we friendly guys after all?\n"), i18n)); } if (savestyle == 0) goto get_me_out; indentation = get_opt_int("config.indentation"); comments = get_opt_int("config.comments"); if (!init_string(&tmpstring)) goto get_me_out; add_cfg_header_to_string(&tmpstring, conf_i18n(N_("Automatically saved options\n"), i18n)); origlen = tmpstring.length; smart_config_string(&tmpstring, 2, i18n, options->value.tree, NULL, 0, smart_config_output_fn); if (tmpstring.length > origlen) add_bytes_to_string(&config, tmpstring.source, tmpstring.length); done_string(&tmpstring); if (!init_string(&tmpstring)) goto get_me_out; add_cfg_header_to_string(&tmpstring, conf_i18n(N_("Automatically saved keybindings\n"), i18n)); origlen = tmpstring.length; bind_config_string(&tmpstring); if (tmpstring.length > origlen) add_bytes_to_string(&config, tmpstring.source, tmpstring.length); done_string(&tmpstring);get_me_out: unmark_options_tree(options->value.tree); return config.source;}static intwrite_config_file(unsigned char *prefix, unsigned char *name, struct option *options, struct terminal *term){ int ret = -1; struct secure_save_info *ssi; unsigned char *config_file = NULL; unsigned char *cfg_str = create_config_string(prefix, name, options); int prefixlen = strlen(prefix); int prefix_has_slash = (prefixlen && dir_sep(prefix[prefixlen - 1])); int name_has_slash = dir_sep(name[0]); unsigned char *slash = name_has_slash || prefix_has_slash ? "" : "/"; if (!cfg_str) return -1; if (name_has_slash && prefix_has_slash) name++; config_file = straconcat(prefix, slash, name, NULL); if (!config_file) goto free_cfg_str; ssi = secure_open(config_file, 0177); if (ssi) { secure_fputs(ssi, cfg_str); ret = secure_close(ssi); } write_config_dialog(term, config_file, secsave_errno, ret); mem_free(config_file);free_cfg_str: mem_free(cfg_str); return ret;}intwrite_config(struct terminal *term){ assert(term); if (!elinks_home) { write_config_dialog(term, get_cmd_opt_str("config-file"), SS_ERR_DISABLED, 0); return -1; } return write_config_file(elinks_home, get_cmd_opt_str("config-file"), config_options, term);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -