📄 renderer.c
字号:
link->type = LINK_HYPERTEXT; link->where = where; link->color.background = document->options.default_bg; link->color.foreground = fgcolor; init_template(&template, link->color.background, link->color.foreground); render_dom_text(renderer, &template, string, length); for (point = link->points; length > 0; length--, point++, x++) { point->x = x; point->y = y; } document->nlinks++; return link;}/* DOM Tree Renderer */#ifdef DOM_TREE_RENDERERstatic struct dom_node *render_dom_tree(struct dom_navigator *navigator, struct dom_node *node, void *data){ struct dom_renderer *renderer = navigator->data; struct screen_char *template = &renderer->styles[node->type]; unsigned char *name, *value; assert(node && renderer); name = get_dom_node_name(node); value = memacpy(node->string, node->length); render_dom_printf(renderer, template, "%-16s: %s\n", name, value); if (name) mem_free(name); if (value) mem_free(value); return node;}static struct dom_node *render_dom_tree_id_leaf(struct dom_navigator *navigator, struct dom_node *node, void *data){ struct dom_renderer *renderer = navigator->data; struct document *document = renderer->document; struct screen_char *template = &renderer->styles[node->type]; unsigned char *name, *value, *id; assert(node && document); name = get_dom_node_name(node); value = get_dom_node_value(node); id = get_dom_node_type_name(node->type); renderer->canvas_x += navigator->depth; render_dom_printf(renderer, template, "%-16s: %s -> %s\n", id, name, value); if (name) mem_free(name); if (value) mem_free(value); return node;}static struct dom_node *render_dom_tree_leaf(struct dom_navigator *navigator, struct dom_node *node, void *data){ struct dom_renderer *renderer = navigator->data; struct document *document = renderer->document; struct screen_char *template = &renderer->styles[node->type]; unsigned char *name, *value; assert(node && document); name = get_dom_node_name(node); value = get_dom_node_value(node); renderer->canvas_x += navigator->depth; render_dom_printf(renderer, template, "%-16s: %s\n", name, value); if (name) mem_free(name); if (value) mem_free(value); return node;}static struct dom_node *render_dom_tree_branch(struct dom_navigator *navigator, struct dom_node *node, void *data){ struct dom_renderer *renderer = navigator->data; struct document *document = renderer->document; struct screen_char *template = &renderer->styles[node->type]; unsigned char *name, *id; assert(node && document); name = get_dom_node_name(node); id = get_dom_node_type_name(node->type); renderer->canvas_x += navigator->depth; render_dom_printf(renderer, template, "%-16s: %s\n", id, name); if (name) mem_free(name); return node;}static dom_navigator_callback_T dom_tree_renderer_callbacks[DOM_NODES] = { /* */ NULL, /* DOM_NODE_ELEMENT */ render_dom_tree_branch, /* DOM_NODE_ATTRIBUTE */ render_dom_tree_id_leaf, /* DOM_NODE_TEXT */ render_dom_tree_leaf, /* DOM_NODE_CDATA_SECTION */ render_dom_tree_id_leaf, /* DOM_NODE_ENTITY_REFERENCE */ render_dom_tree_id_leaf, /* DOM_NODE_ENTITY */ render_dom_tree_id_leaf, /* DOM_NODE_PROC_INSTRUCTION */ render_dom_tree_id_leaf, /* DOM_NODE_COMMENT */ render_dom_tree_leaf, /* DOM_NODE_DOCUMENT */ render_dom_tree, /* DOM_NODE_DOCUMENT_TYPE */ render_dom_tree_id_leaf, /* DOM_NODE_DOCUMENT_FRAGMENT */ render_dom_tree_id_leaf, /* DOM_NODE_NOTATION */ render_dom_tree_id_leaf,};#endif /* DOM_TREE_RENDERER *//* DOM Source Renderer */#define check_dom_node_source(renderer, str, len) \ ((renderer)->source <= (str) && (str) + (len) <= (renderer)->end)#define assert_source(renderer, str, len) \ assertm(check_dom_node_source(renderer, str, len), "renderer[%p : %p] str[%p : %p]", \ (renderer)->source, (renderer)->end, (str), (str) + (len))static inline voidrender_dom_flush(struct dom_renderer *renderer, unsigned char *string){ struct screen_char *template = &renderer->styles[DOM_NODE_TEXT]; int length = string - renderer->position; assert_source(renderer, renderer->position, 0); assert_source(renderer, string, 0); if (length <= 0) return; render_dom_text(renderer, template, renderer->position, length); renderer->position = string; assert_source(renderer, renderer->position, 0);}static inline voidrender_dom_node_text(struct dom_renderer *renderer, struct screen_char *template, struct dom_node *node){ unsigned char *string = node->string; int length = node->length; if (node->type == DOM_NODE_ENTITY_REFERENCE) { string -= 1; length += 2; } if (check_dom_node_source(renderer, string, length)) { render_dom_flush(renderer, string); renderer->position = string + length; assert_source(renderer, renderer->position, 0); } render_dom_text(renderer, template, string, length);}static struct dom_node *render_dom_node_source(struct dom_navigator *navigator, struct dom_node *node, void *data){ struct dom_renderer *renderer = navigator->data; assert(node && renderer && renderer->document); /* TODO: For (atleast) text, CDATA section and comment nodes check * for URIs ala document->options.plain_display_links */ render_dom_node_text(renderer, &renderer->styles[node->type], node); return node;}static struct dom_node *render_dom_proc_instr_source(struct dom_navigator *navigator, struct dom_node *node, void *data){ struct dom_renderer *renderer = navigator->data; unsigned char *value; int valuelen; assert(node && renderer && renderer->document); render_dom_node_text(renderer, &renderer->styles[node->type], node); value = node->data.proc_instruction.instruction; valuelen = node->data.proc_instruction.instructionlen; if (!value || node->data.proc_instruction.map) return node; if (check_dom_node_source(renderer, node->string, node->length)) { render_dom_flush(renderer, value); renderer->position = value + valuelen; } render_dom_text(renderer, &renderer->styles[DOM_NODE_ATTRIBUTE], value, valuelen); return node;}static struct dom_node *render_dom_element_source(struct dom_navigator *navigator, struct dom_node *node, void *data){ struct dom_renderer *renderer = navigator->data; assert(node && renderer && renderer->document); render_dom_node_text(renderer, &renderer->styles[node->type], node); return node;}static struct dom_node *render_dom_attribute_source(struct dom_navigator *navigator, struct dom_node *node, void *data){ struct dom_navigator_state *state = get_dom_navigator_parent(navigator); struct dom_renderer *renderer = navigator->data; struct screen_char *template = &renderer->styles[node->type]; struct dom_node *attribute = NULL; int i; assert(node && renderer->document); assert(state && state->list); /* The attributes are sorted but we want them in the original order */ foreach_dom_node(i, node, state->list) { if (node->string >= renderer->position && (!attribute || node->string < attribute->string)) attribute = node; } assert(attribute); node = attribute; render_dom_node_text(renderer, template, node); if (node->data.attribute.value) { int quoted = node->data.attribute.quoted == 1; unsigned char *value = node->data.attribute.value - quoted; int valuelen = node->data.attribute.valuelen + quoted * 2; if (check_dom_node_source(renderer, value, 0)) { render_dom_flush(renderer, value); renderer->position = value + valuelen; assert_source(renderer, renderer->position, 0); } if (node->data.attribute.reference && valuelen - quoted * 2 > 0) { int skips; /* Need to flush the first quoting delimiter and any * leading whitespace so that the renderers x position * is at the start of the value string. */ for (skips = 0; skips < valuelen; skips++) { if ((quoted && skips == 0) || isspace(value[skips]) || value[skips] < ' ') continue; break; } if (skips > 0) { render_dom_text(renderer, template, value, skips); value += skips; valuelen -= skips; } /* Figure out what should be skipped after the actual * link text. */ for (skips = 0; skips < valuelen; skips++) { if ((quoted && skips == 0) || isspace(value[valuelen - skips - 1]) || value[valuelen - skips - 1] < ' ') continue; break; } add_dom_link(renderer, value, valuelen - skips); if (skips > 0) { value += valuelen - skips; render_dom_text(renderer, template, value, skips); } } else { render_dom_text(renderer, template, value, valuelen); } } return node;}static dom_navigator_callback_T dom_source_renderer_callbacks[DOM_NODES] = { /* */ NULL, /* DOM_NODE_ELEMENT */ render_dom_element_source, /* DOM_NODE_ATTRIBUTE */ render_dom_attribute_source, /* DOM_NODE_TEXT */ render_dom_node_source, /* DOM_NODE_CDATA_SECTION */ render_dom_node_source, /* DOM_NODE_ENTITY_REFERENCE */ render_dom_node_source, /* DOM_NODE_ENTITY */ render_dom_node_source, /* DOM_NODE_PROC_INSTRUCTION */ render_dom_proc_instr_source, /* DOM_NODE_COMMENT */ render_dom_node_source, /* DOM_NODE_DOCUMENT */ NULL, /* DOM_NODE_DOCUMENT_TYPE */ render_dom_node_source, /* DOM_NODE_DOCUMENT_FRAGMENT */ render_dom_node_source, /* DOM_NODE_NOTATION */ render_dom_node_source,};/* Shared multiplexor between renderers */voidrender_dom_document(struct cache_entry *cached, struct document *document, struct string *buffer){ unsigned char *head = empty_string_or_(cached->head); struct dom_node *root = parse_sgml(cached, document, buffer); struct dom_renderer renderer; struct conv_table *convert_table; dom_navigator_callback_T *callbacks = dom_source_renderer_callbacks; struct dom_navigator navigator; assert(document->options.plain); if (!root) return; convert_table = get_convert_table(head, document->options.cp, document->options.assume_cp, &document->cp, &document->cp_status, document->options.hard_assume); init_dom_renderer(&renderer, document, buffer, root, convert_table); init_dom_navigator(&navigator, &renderer, callbacks, 0); document->bgcolor = global_doc_opts->default_bg; walk_dom_nodes(&navigator, root); /* If there are no non-element nodes after the last element node make * sure that we flush to the end of the cache entry source including * the '>' of the last element tag if it has one. (bug 519) */ if (check_dom_node_source(&renderer, renderer.position, 0)) { render_dom_flush(&renderer, renderer.end); } done_dom_node(root); done_dom_navigator(&navigator);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -