📄 renderer.c
字号:
/* Take out all badly placed form items. */ foreach (form, document->forms) { assertm(form->form_num <= form->form_end, "%p [%d : %d]", form, form->form_num, form->form_end); foreachsafe (fc, next, form->items) { if (form->form_num <= fc->position && fc->position <= form->form_end) continue; del_from_list(fc); add_to_list(form_controls, fc); } } /* Re-insert the form items the correct places. */ foreachsafe (fc, next, form_controls) { foreach (form, document->forms) { if (fc->position < form->form_num || form->form_end < fc->position) continue; del_from_list(fc); fc->form = form; add_to_list(form->items, fc); break; } } assert(list_empty(form_controls));}static inline voidcolor_link_lines(struct document *document){ struct color_pair colors = INIT_COLOR_PAIR(par_format.bgcolor, 0x0); enum color_mode color_mode = document->options.color_mode; enum color_flags color_flags = document->options.color_flags; int y; for (y = 0; y < document->height; y++) { int x; for (x = 0; x < document->data[y].length; x++) { struct screen_char *schar = &document->data[y].chars[x]; set_term_color(schar, &colors, color_flags, color_mode); /* XXX: Entering hack zone! Change to clink color after * link text has been recolored. */ if (schar->data == ':' && colors.foreground == 0x0) colors.foreground = format.clink; } colors.foreground = 0x0; }}static void *html_special(struct part *part, enum html_special_type c, ...){ va_list l; unsigned char *t; struct document *document = part->document; unsigned long seconds; struct form *form; struct form_control *fc; assert(part); if_assert_failed return NULL; va_start(l, c); switch (c) { case SP_TAG: t = va_arg(l, unsigned char *); if (document) html_special_tag(document, t, X(part->cx), Y(part->cy)); va_end(l); break; case SP_FORM: form = va_arg(l, struct form *); html_special_form(part, form); va_end(l); break; case SP_CONTROL: fc = va_arg(l, struct form_control *); html_special_form_control(part, fc); va_end(l); break; case SP_TABLE: va_end(l); return renderer_context.convert_table; case SP_USED: va_end(l); return (void *) (long) !!document; case SP_CACHE_CONTROL: { struct cache_entry *cached = renderer_context.cached; cached->cache_mode = CACHE_MODE_NEVER; cached->expire = 0; va_end(l); break; } case SP_CACHE_EXPIRES: { time_t expires = va_arg(l, time_t); struct cache_entry *cached = renderer_context.cached; va_end(l); if (!expires || cached->cache_mode == CACHE_MODE_NEVER) break; cached->max_age = expires; cached->expire = 1; break; } case SP_FRAMESET: { struct frameset_param *fsp = va_arg(l, struct frameset_param *); struct frameset_desc *frameset_desc; va_end(l); if (!fsp->parent && document->frame_desc) return NULL; frameset_desc = create_frameset(fsp); if (!fsp->parent && !document->frame_desc) document->frame_desc = frameset_desc; return frameset_desc; } case SP_FRAME: { struct frameset_desc *parent = va_arg(l, struct frameset_desc *); unsigned char *name = va_arg(l, unsigned char *); unsigned char *url = va_arg(l, unsigned char *); va_end(l); add_frameset_entry(parent, NULL, name, url); } break; case SP_NOWRAP: renderer_context.nowrap = va_arg(l, int); va_end(l); break; case SP_REFRESH: seconds = va_arg(l, unsigned long); t = va_arg(l, unsigned char *); va_end(l); document->refresh = init_document_refresh(t, seconds); break; case SP_COLOR_LINK_LINES: va_end(l); if (document && use_document_bg_colors(&document->options)) color_link_lines(document); break; case SP_STYLESHEET: {#ifdef CONFIG_CSS struct uri *uri = va_arg(l, struct uri *); if (document) add_to_uri_list(&document->css_imports, uri);#endif va_end(l); break; } case SP_SCRIPT: {#ifdef CONFIG_ECMASCRIPT struct uri *uri = va_arg(l, struct uri *); if (document) add_to_uri_list(&document->ecmascript_imports, uri);#endif va_end(l); break; } } return NULL;}voidfree_table_cache(void){ if (renderer_context.table_cache) { struct hash_item *item; int i; /* We do not free key here. */ foreach_hash_item (item, *renderer_context.table_cache, i) { mem_free_if(item->value); } free_hash(renderer_context.table_cache); } renderer_context.table_cache = NULL; renderer_context.table_cache_entries = 0;}struct part *format_html_part(unsigned char *start, unsigned char *end, int align, int margin, int width, struct document *document, int x, int y, unsigned char *head, int link_num){ struct part *part; struct html_element *html_state; int llm = renderer_context.last_link_to_move; struct tag *ltm = renderer_context.last_tag_to_move; /*struct tag *ltn = last_tag_for_newline;*/ int lm = html_context.margin; int ef = renderer_context.empty_format; struct table_cache_entry *tce; /* Hash creation if needed. */ if (!renderer_context.table_cache) { renderer_context.table_cache = init_hash(8, &strhash); } else if (!document) { /* Search for cached entry. */ struct table_cache_entry_key key; struct hash_item *item; /* Clear key to prevent potential alignment problem * when keys are compared. */ memset(&key, 0, sizeof(key)); key.start = start; key.end = end; key.align = align; key.margin = margin; key.width = width; key.x = x; key.link_num = link_num; item = get_hash_item(renderer_context.table_cache, (unsigned char *) &key, sizeof(key)); if (item) { /* We found it in cache, so just copy and return. */ part = mem_alloc(sizeof(*part)); if (part) { copy_struct(part, &((struct table_cache_entry *) item->value)->part); return part; } } } assertm(y >= 0, "format_html_part: y == %d", y); if_assert_failed return NULL; if (document) { struct node *node = mem_alloc(sizeof(*node)); if (node) { int node_width = !html_context.table_level ? INT_MAX : width; set_box(&node->box, x, y, node_width, 1); add_to_list(document->nodes, node); } renderer_context.last_link_to_move = document->nlinks; renderer_context.last_tag_to_move = (void *) &document->tags; renderer_context.last_tag_for_newline = (void *) &document->tags; } else { renderer_context.last_link_to_move = 0; renderer_context.last_tag_to_move = NULL; renderer_context.last_tag_for_newline = NULL; } html_context.margin = margin; renderer_context.empty_format = !document; done_link_state_info(); renderer_context.nobreak = 1; part = mem_calloc(1, sizeof(*part)); if (!part) goto ret; part->document = document; part->box.x = x; part->box.y = y; part->cx = -1; part->cy = 0; part->link_num = link_num; html_state = init_html_parser_state(ELEMENT_IMMORTAL, align, margin, width); parse_html(start, end, part, head); done_html_parser_state(html_state); int_lower_bound(&part->max_width, part->box.width); renderer_context.nobreak = 0; done_link_state_info(); mem_free_if(part->spaces); if (document) { struct node *node = document->nodes.next; node->box.height = y - node->box.y + part->box.height; }ret: renderer_context.last_link_to_move = llm; renderer_context.last_tag_to_move = ltm; /* renderer_context.last_tag_for_newline = ltn; */ html_context.margin = lm; renderer_context.empty_format = ef; if (html_context.table_level > 1 && !document && renderer_context.table_cache && renderer_context.table_cache_entries < MAX_TABLE_CACHE_ENTRIES) { /* Create a new entry. */ /* Clear memory to prevent bad key comparaison due to alignment * of key fields. */ tce = mem_calloc(1, sizeof(*tce)); /* A goto is used here to prevent a test or code * redundancy. */ if (!tce) goto end; tce->key.start = start; tce->key.end = end; tce->key.align = align; tce->key.margin = margin; tce->key.width = width; tce->key.x = x; tce->key.link_num = link_num; copy_struct(&tce->part, part); if (!add_hash_item(renderer_context.table_cache, (unsigned char *) &tce->key, sizeof(tce->key), tce)) { mem_free(tce); } else { renderer_context.table_cache_entries++; } }end: return part;}voidrender_html_document(struct cache_entry *cached, struct document *document, struct string *buffer){ struct part *part; unsigned char *start = NULL; unsigned char *end = NULL; struct string title; struct string head; int i; assert(cached && document); if_assert_failed return; if (!init_string(&head)) return; renderer_context.g_ctrl_num = 0; renderer_context.cached = cached; start = buffer->source; end = buffer->source + buffer->length; if (cached->head) add_to_string(&head, cached->head); init_html_parser(cached->uri, &document->options, start, end, &head, &title, put_chars_conv, line_break, html_special); renderer_context.convert_table = get_convert_table(head.source, document->options.cp, document->options.assume_cp, &document->cp, &document->cp_status, document->options.hard_assume); if (title.length) { document->title = convert_string(renderer_context.convert_table, title.source, title.length, CSM_DEFAULT, NULL, NULL, NULL); } done_string(&title); part = format_html_part(start, end, par_format.align, par_format.leftmargin, document->options.box.width, document, 0, 0, head.source, 1); /* Drop empty allocated lines at end of document if any * and adjust document height. */ for (i = document->height - 1; i >= 0 ; i--) { if (!document->data[i].length) { mem_free_if(document->data[i].chars); document->height--; } else break; } /* Calculate document width. */ document->width = 0; for (i = 0; i < document->height; i++) int_lower_bound(&document->width, document->data[i].length);#if 1 document->options.needs_width = 1;#else /* FIXME: This needs more tuning since if we are centering stuff it * does not work. */ document->options.needs_width = (document->width + (document->options.margin >= document->options.width));#endif document->bgcolor = par_format.bgcolor; done_html_parser(); /* Drop forms which has been serving as a placeholder for form items * added in the wrong order due to the ordering of table rendering. */ { struct form *form; foreach (form, document->forms) { if (form->form_num) continue; if (list_empty(form->items)) done_form(form); break; } } /* @part was residing in html_context so it has to stay alive until * done_html_parser(). */ done_string(&head); mem_free_if(part);#if 0 /* debug purpose */ { FILE *f = fopen("forms", "ab"); struct form_control *form; unsigned char *qq; fprintf(f,"FORM:\n"); foreach (form, document->forms) { fprintf(f, "g=%d f=%d c=%d t:%d\n", form->g_ctrl_num, form->form_num, form->ctrl_num, form->type); } fprintf(f,"fragment: \n"); for (qq = start; qq < end; qq++) fprintf(f, "%c", *qq); fprintf(f,"----------\n\n"); fclose(f); }#endif}intfind_tag(struct document *document, unsigned char *name, int namelen){ struct tag *tag; foreach (tag, document->tags) if (!strlcasecmp(tag->name, -1, name, namelen)) return tag->y; return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -