renderer.c
来自「elinks下lynx是最重要的二个文本浏览器, 在linux下非常实用, el」· C语言 代码 · 共 2,052 行 · 第 1/4 页
C
2,052 行
if (list_empty(part->document->forms)) { /* No forms encountered yet, that means a homeless form * control. Generate a dummy form for those Flying * Dutchmans. */ form = init_form(); form->form_num = 0; add_to_list(part->document->forms, form); } /* Attach this form control to the last form encountered. */ form = part->document->forms.next; fc->form = form; add_to_list(form->items, fc);}/* Reparents form items based on position in the source. */voidcheck_html_form_hierarchy(struct part *part){ struct document *document = part->document; INIT_LIST_HEAD(form_controls); struct form *form; struct form_control *fc, *next; if (list_empty(document->forms)) return; /* 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; move_to_top_of_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; fc->form = form; move_to_top_of_list(form->items, fc); break; } } assert(list_empty(form_controls));}static inline voidcolor_link_lines(struct html_context *html_context){ struct document *document = html_context->part->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 html_context *html_context, enum html_special_type c, ...){ va_list l; struct part *part; struct document *document; void *ret_val = NULL; assert(html_context); if_assert_failed return NULL; part = html_context->part; assert(part); if_assert_failed return NULL; document = part->document; va_start(l, c); switch (c) { case SP_TAG: if (document) { unsigned char *t = va_arg(l, unsigned char *); html_special_tag(document, t, X(part->cx), Y(part->cy)); } break; case SP_FORM: { struct form *form = va_arg(l, struct form *); html_special_form(part, form); break; } case SP_CONTROL: { struct form_control *fc = va_arg(l, struct form_control *); html_special_form_control(part, fc); break; } case SP_TABLE: ret_val = renderer_context.convert_table; break; case SP_USED: ret_val = (void *) (long) !!document; break; case SP_CACHE_CONTROL: { struct cache_entry *cached = renderer_context.cached; cached->cache_mode = CACHE_MODE_NEVER; cached->expire = 0; break; } case SP_CACHE_EXPIRES: { time_t expires = va_arg(l, time_t); struct cache_entry *cached = renderer_context.cached; if (!expires || cached->cache_mode == CACHE_MODE_NEVER) break; timeval_from_seconds(&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; if (!fsp->parent && document->frame_desc) break; frameset_desc = create_frameset(fsp); if (!fsp->parent && !document->frame_desc) document->frame_desc = frameset_desc; ret_val = frameset_desc; break; } 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 *); add_frameset_entry(parent, NULL, name, url); break; } case SP_NOWRAP: renderer_context.nowrap = !!va_arg(l, int); break; case SP_REFRESH: { unsigned long seconds = va_arg(l, unsigned long); unsigned char *t = va_arg(l, unsigned char *); document->refresh = init_document_refresh(t, seconds); break; } case SP_COLOR_LINK_LINES: if (document && use_document_bg_colors(&document->options)) color_link_lines(html_context); break; case SP_STYLESHEET:#ifdef CONFIG_CSS if (document) { struct uri *uri = va_arg(l, struct uri *); add_to_uri_list(&document->css_imports, uri); }#endif break; case SP_SCRIPT:#ifdef CONFIG_ECMASCRIPT if (document) { struct uri *uri = va_arg(l, struct uri *); add_to_uri_list(&document->ecmascript_imports, uri); }#endif break; } va_end(l); return ret_val;}voidfree_table_cache(void){ if (table_cache) { struct hash_item *item; int i; /* We do not free key here. */ foreach_hash_item (item, *table_cache, i) { mem_free_if(item->value); } free_hash(table_cache); } table_cache = NULL; table_cache_entries = 0;}struct part *format_html_part(struct html_context *html_context, 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; int ef = renderer_context.empty_format; int lm = html_context->margin; /* Hash creation if needed. */ if (!table_cache) { 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(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 = (struct tag *) &document->tags; renderer_context.last_tag_for_newline = (struct tag *) &document->tags; } else { renderer_context.last_link_to_move = 0; renderer_context.last_tag_to_move = (struct tag *) NULL; renderer_context.last_tag_for_newline = (struct tag *) 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(html_context, ELEMENT_IMMORTAL, align, margin, width); parse_html(start, end, part, head, html_context); done_html_parser_state(html_context, 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.empty_format = ef; html_context->margin = lm; if (html_context->table_level > 1 && !document && table_cache && table_cache_entries < MAX_TABLE_CACHE_ENTRIES) { /* Create a new entry. */ /* Clear memory to prevent bad key comparaison due to alignment * of key fields. */ struct table_cache_entry *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(table_cache, (unsigned char *) &tce->key, sizeof(tce->key), tce)) { mem_free(tce); } else { table_cache_entries++; } }end: return part;}voidrender_html_document(struct cache_entry *cached, struct document *document, struct string *buffer){ struct html_context *html_context; struct part *part; unsigned char *start; unsigned char *end; struct string title; struct string head; int i; assert(cached && document); if_assert_failed return; if (!init_string(&head)) return; if (cached->head) add_to_string(&head, cached->head); start = buffer->source; end = buffer->source + buffer->length; html_context = init_html_parser(cached->uri, &document->options, start, end, &head, &title, put_chars_conv, line_break, html_special); if (!html_context) return; renderer_context.g_ctrl_num = 0; renderer_context.cached = cached; 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, document->options.cp, CSM_DEFAULT, NULL, NULL, NULL); } done_string(&title); part = format_html_part(html_context, 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(html_context); /* 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 + =
减小字号Ctrl + -
显示快捷键?