📄 options.c
字号:
} } free_options_tree(option->value.tree, recursive); mem_free(option->value.tree); break; default: break; } if (option->box_item) done_listbox_item(&option_browser, option->box_item); if (option->flags & OPT_ALLOC) { mem_free_if(option->name); mem_free(option); } else if (!option->capt) { /* We are probably dealing with a built-in autocreated option * that will be attempted to be deleted when shutting down. */ /* Clear it so nothing will be done later. */ memset(option, 0, sizeof(*option)); }}voidmark_option_as_deleted(struct option *option){ if (option->type == OPT_TREE) { struct option *unmarked; assert(option->value.tree); foreach (unmarked, *option->value.tree) mark_option_as_deleted(unmarked); } if (option->box_item) { done_listbox_item(&option_browser, option->box_item); option->box_item = NULL; } option->flags |= (OPT_TOUCHED | OPT_DELETED);}voiddelete_option(struct option *option){ delete_option_do(option, 1);}struct option *copy_option(struct option *template){ struct option *option = mem_calloc(1, sizeof(*option)); if (!option) return NULL; option->name = null_or_stracpy(template->name); option->flags = (template->flags | OPT_ALLOC); option->type = template->type; option->min = template->min; option->max = template->max; option->capt = template->capt; option->desc = template->desc; option->change_hook = template->change_hook; option->box_item = init_option_listbox_item(option); if (option->box_item) { if (template->box_item) { option->box_item->type = template->box_item->type; option->box_item->depth = template->box_item->depth; } } if (option_types[template->type].dup) { option_types[template->type].dup(option, template); } else { option->value = template->value; } return option;}struct list_head *init_options_tree(void){ struct list_head *ptr = mem_alloc(sizeof(*ptr)); if (ptr) init_list(*ptr); return ptr;}/* Some default pre-autocreated options. Doh. */static inline voidregister_autocreated_options(void){ /* TODO: Use table-driven initialization. --jonas */ get_opt_int("terminal.linux.type") = 2; get_opt_int("terminal.linux.colors") = 1; get_opt_bool("terminal.linux.m11_hack") = 1; get_opt_int("terminal.vt100.type") = 1; get_opt_int("terminal.vt110.type") = 1; get_opt_int("terminal.xterm.type") = 1; get_opt_bool("terminal.xterm.underline") = 1; get_opt_int("terminal.xterm-color.type") = 1; get_opt_int("terminal.xterm-color.colors") = COLOR_MODE_16; get_opt_bool("terminal.xterm-color.underline") = 1;#ifdef CONFIG_256_COLORS get_opt_int("terminal.xterm-256color.type") = 1; get_opt_int("terminal.xterm-256color.colors") = COLOR_MODE_256; get_opt_bool("terminal.xterm-256color.underline") = 1;#endif}static struct option_info config_options_info[];extern struct option_info cmdline_options_info[];static struct change_hook_info change_hooks[];voidinit_options(void){ cmdline_options = add_opt_tree_tree(&options_root, "", "", "cmdline", 0, ""); register_options(cmdline_options_info, cmdline_options); config_options = add_opt_tree_tree(&options_root, "", "", "config", OPT_SORT, ""); config_options->flags |= OPT_LISTBOX; config_options->box_item = &option_browser.root; register_options(config_options_info, config_options); register_autocreated_options(); register_change_hooks(change_hooks);}static voidfree_options_tree(struct list_head *tree, int recursive){ while (!list_empty(*tree)) delete_option_do(tree->next, recursive);}voiddone_options(void){ unregister_options(config_options_info, config_options); unregister_options(cmdline_options_info, cmdline_options); config_options->box_item = NULL; free_options_tree(&options_root_tree, 0);}voidregister_change_hooks(struct change_hook_info *change_hooks){ int i; for (i = 0; change_hooks[i].name; i++) { struct option *option = get_opt_rec(config_options, change_hooks[i].name); assert(option); option->change_hook = change_hooks[i].change_hook; }}voidunmark_options_tree(struct list_head *tree){ struct option *option; foreach (option, *tree) { option->flags &= ~OPT_WATERMARK; if (option->type == OPT_TREE) unmark_options_tree(option->value.tree); }}voidwatermark_deleted_options(struct list_head *tree){ struct option *option; foreach (option, *tree) { if (option->flags & OPT_DELETED) option->flags |= OPT_WATERMARK; else if (option->type == OPT_TREE) watermark_deleted_options(option->value.tree); }}static intcheck_nonempty_tree(struct list_head *options){ struct option *opt; foreach (opt, *options) { if (opt->type == OPT_TREE) { if (check_nonempty_tree(opt->value.tree)) return 1; } else if (!(opt->flags & OPT_WATERMARK)) { return 1; } } return 0;}voidsmart_config_string(struct string *str, int print_comment, int i18n, struct list_head *options, unsigned char *path, int depth, void (*fn)(struct string *, struct option *, unsigned char *, int, int, int, int)){ struct option *option; foreach (option, *options) { int do_print_comment = 1; if (option->flags & OPT_HIDDEN || option->flags & OPT_WATERMARK || option->type == OPT_ALIAS || !strcmp(option->name, "_template_")) continue; /* Is there anything to be printed anyway? */ if (option->type == OPT_TREE && !check_nonempty_tree(option->value.tree)) continue; /* We won't pop out the description when we're in autocreate * category and not template. It'd be boring flood of * repetitive comments otherwise ;). */ /* This print_comment parameter is weird. If it is negative, it * means that we shouldn't print comments at all. If it is 1, * we shouldn't print comment UNLESS the option is _template_ * or not-an-autocreating-tree (it is set for the first-level * autocreation tree). When it is 2, we can print out comments * normally. */ /* It is still broken somehow, as it didn't work for terminal.* * (the first autocreated level) by the time I wrote this. Good * summer job for bored mad hackers with spare boolean mental * power. I have better things to think about, personally. * Maybe we should just mark autocreated options somehow ;). */ if (!print_comment || (print_comment == 1 && (strcmp(option->name, "_template_") && (option->flags & OPT_AUTOCREATE && option->type == OPT_TREE)))) do_print_comment = 0; /* Pop out the comment */ /* For config file, we ignore do_print_comment everywhere * except 1, but sometimes we want to skip the option totally. */ fn(str, option, path, depth, option->type == OPT_TREE ? print_comment : do_print_comment, 0, i18n); fn(str, option, path, depth, do_print_comment, 1, i18n); /* And the option itself */ if (option_types[option->type].write) { fn(str, option, path, depth, do_print_comment, 2, i18n); } else if (option->type == OPT_TREE) { struct string newpath; int pc = print_comment; if (!init_string(&newpath)) continue; /* OK? */ if (pc == 2 && option->flags & OPT_AUTOCREATE) pc = 1; else if (pc == 1 && strcmp(option->name, "_template_")) pc = 0; fn(str, option, path, depth, /*pc*/1, 3, i18n); if (path) { add_to_string(&newpath, path); add_char_to_string(&newpath, '.'); } add_to_string(&newpath, option->name); smart_config_string(str, pc, i18n, option->value.tree, newpath.source, depth + 1, fn); done_string(&newpath); fn(str, option, path, depth, /*pc*/1, 3, i18n); } /* TODO: We should maybe clear the touched flag only when really * saving the stuff...? --pasky */ option->flags &= ~OPT_TOUCHED; }}static intchange_hook_cache(struct session *ses, struct option *current, struct option *changed){ shrink_memory(0); return 0;}static intchange_hook_connection(struct session *ses, struct option *current, struct option *changed){ register_bottom_half((void (*)(void *)) check_queue, NULL); return 0;}static intchange_hook_html(struct session *ses, struct option *current, struct option *changed){ draw_formatted(ses, 1); load_frames(ses, ses->doc_view); process_file_requests(ses); print_screen_status(ses); return 0;}static intchange_hook_insert_mode(struct session *ses, struct option *current, struct option *changed){ update_status(); return 0;}static intchange_hook_active_link(struct session *ses, struct option *current, struct option *changed){ if (!global_doc_opts) return 0; global_doc_opts->active_link_fg = get_opt_color("document.browse.links.active_link.colors.text"); global_doc_opts->active_link_bg = get_opt_color("document.browse.links.active_link.colors.background"); global_doc_opts->color_active_link = get_opt_bool("document.browse.links.active_link.enable_color"); global_doc_opts->invert_active_link = get_opt_bool("document.browse.links.active_link.invert"); global_doc_opts->underline_active_link = get_opt_bool("document.browse.links.active_link.underline"); global_doc_opts->bold_active_link = get_opt_bool("document.browse.links.active_link.bold"); return 0;}static intchange_hook_terminal(struct session *ses, struct option *current, struct option *changed){ cls_redraw_all_terminals(); return 0;}static intchange_hook_ui(struct session *ses, struct option *current, struct option *changed){ update_status(); return 0;}/* Bit 2 of show means we should always set visibility, otherwise we set it * only on templates. */static voidupdate_visibility(struct list_head *tree, int show){ struct option *opt; foreach (opt, *tree) { if (!strcmp(opt->name, "_template_")) { if (opt->box_item) opt->box_item->visible = (show & 1); if (opt->type == OPT_TREE) update_visibility(opt->value.tree, show | 2); } else { if (opt->box_item && (show & 2)) opt->box_item->visible = (show & 1); if (opt->type == OPT_TREE) update_visibility(opt->value.tree, show); } }}voidupdate_options_visibility(void){ update_visibility(config_options->value.tree, get_opt_bool("config.show_template"));}static intchange_hook_stemplate(struct session *ses, struct option *current, struct option *changed){ update_visibility(config_options->value.tree, changed->value.number); return 0;}static intchange_hook_language(struct session *ses, struct option *current, struct option *changed){#ifdef ENABLE_NLS set_language(changed->value.number);#endif return 0;}static struct change_hook_info change_hooks[] = { { "config.show_template", change_hook_stemplate }, { "connection", change_hook_connection }, { "document.browse", change_hook_html }, { "document.browse.forms.insert_mode", change_hook_insert_mode }, { "document.browse.links.active_link", change_hook_active_link }, { "document.cache", change_hook_cache }, { "document.codepage", change_hook_html }, { "document.colors", change_hook_html }, { "document.html", change_hook_html }, { "document.plain", change_hook_html }, { "terminal", change_hook_terminal }, { "ui.language", change_hook_language }, { "ui", change_hook_ui }, { NULL, NULL },};intcommit_option_values(struct option_resolver *resolvers, struct option *root, union option_value *values, int size){ int touched = 0; int i; assert(resolvers && root && values && size); for (i = 0; i < size; i++) { unsigned char *name = resolvers[i].name; struct option *option = get_opt_rec(root, name); int id = resolvers[i].id; if (memcmp(&option->value, &values[id], sizeof(union option_value))) { option->value = values[id]; option->flags |= OPT_TOUCHED; touched++; } } return touched;}voidcheckout_option_values(struct option_resolver *resolvers, struct option *root, union option_value *values, int size){ int i; for (i = 0; i < size; i++) { unsigned char *name = resolvers[i].name; struct option *option = get_opt_rec(root, name); int id = resolvers[i].id; values[id] = option->value; }}/********************************************************************** Options values**********************************************************************/#include "config/options.inc"voidregister_options(struct option_info info[], struct option *tree){ int i; for (i = 0; info[i].path; i++) { struct option *option = &info[i].option; unsigned char *string; debug_check_option_syntax(option); if (option->type != OPT_ALIAS && ((tree->flags & OPT_LISTBOX) || (option->flags & OPT_LISTBOX))) { option->box_item = init_option_listbox_item(option); if (!option->box_item) { delete_option(option); continue; } } switch (option->type) { case OPT_TREE: option->value.tree = init_options_tree(); if (!option->value.tree) { delete_option(option); continue; } break; case OPT_STRING: string = mem_alloc(MAX_STR_LEN); if (!string) { delete_option(option); continue; } safe_strncpy(string, option->value.string, MAX_STR_LEN); option->value.string = string; break; case OPT_COLOR: string = option->value.string; assert(string); decode_color(string, strlen(string), &option->value.color); break; case OPT_CODEPAGE: string = option->value.string; assert(string); option->value.number = get_cp_index(string); break; case OPT_BOOL: case OPT_INT: case OPT_LONG: case OPT_LANGUAGE: case OPT_COMMAND: case OPT_ALIAS: break; } add_opt_rec(tree, info[i].path, option); }}voidunregister_options(struct option_info info[], struct option *tree){ int i = 0; /* We need to remove the options in inverse order to the order how we * added them. */ while (info[i].path) i++; for (i--; i >= 0; i--) delete_option_do(&info[i].option, 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -