📄 parse.c
字号:
}element: endingtag = *name == '/'; name += endingtag; namelen -= endingtag; if (!endingtag && html_context->putsp == HTML_SPACE_ADD && !html_top.invisible) put_chrs(html_context, " ", 1); put_chrs(html_context, base_pos, html - base_pos); if (!html_is_preformatted() && !endingtag && html_context->putsp == HTML_SPACE_NORMAL) { unsigned char *ee = end; unsigned char *nm; while (!parse_element(ee, eof, &nm, NULL, NULL, &ee)) if (*nm == '/') goto ng; if (ee < eof && isspace(*ee)) { put_chrs(html_context, " ", 1); }ng:; } html = process_element(name, namelen, endingtag, end, html, eof, attr, html_context); } if (noupdate) put_chrs(html_context, base_pos, html - base_pos); ln_break(html_context, 1); /* Restore the part in case the html_context was trashed in the last * iteration so that when destroying the stack in the caller we still * get the right part pointer. */ html_context->part = part; html_context->putsp = HTML_SPACE_SUPPRESS; html_context->position = 0; html_context->was_br = 0;}static unsigned char *start_element(struct element_info *ei, unsigned char *name, int namelen, unsigned char *html, unsigned char *eof, unsigned char *attr, struct html_context *html_context){#define ELEMENT_RENDER_PROLOGUE \ ln_break(html_context, ei->linebreak); \ a = get_attr_val(attr, "id", html_context->options); \ if (a) { \ html_context->special_f(html_context, SP_TAG, a); \ mem_free(a); \ } unsigned char *a; struct par_attrib old_format; int restore_format;#ifdef CONFIG_CSS struct css_selector *selector = NULL;#endif if (html_top.type == ELEMENT_WEAK) { kill_html_stack_item(html_context, &html_top); } /* We try to process nested <script> if we didn't process the parent * one. */ if (html_top.invisible && (ei->func != html_script || html_top.invisible < 2)) { ELEMENT_RENDER_PROLOGUE return html; } restore_format = html_is_preformatted(); old_format = par_format; /* Support for <meta refresh="..."> inside <body>. (bug 700) */ if (ei->func == html_meta && html_context->was_body) { html_handle_body_meta(html_context, name - 1, eof); html_context->was_body = 0; }#ifdef CONFIG_CSS if (ei->func == html_style && html_context->options->css_enable) { css_parse_stylesheet(&html_context->css_styles, html_context->base_href, html, eof); }#endif if (ei->type == ELEMENT_TYPE_NON_NESTABLE || ei->type == ELEMENT_TYPE_LI) { struct html_element *e; if (ei->type == ELEMENT_TYPE_NON_NESTABLE) { foreach (e, html_context->stack) { if (e->type < ELEMENT_KILLABLE) break; if (is_block_element(e) || is_inline_element(ei)) break; } } else foreach (e, html_context->stack) { if (is_block_element(e) && is_inline_element(ei)) break; if (e->type < ELEMENT_KILLABLE) break; if (!strlcasecmp(e->name, e->namelen, name, namelen)) break; } if (!strlcasecmp(e->name, e->namelen, name, namelen)) { while (e->prev != (void *) &html_context->stack) kill_html_stack_item(html_context, e->prev); if (e->type > ELEMENT_IMMORTAL) kill_html_stack_item(html_context, e); } } if (ei->type != ELEMENT_TYPE_NON_PAIRABLE) { html_stack_dup(html_context, ELEMENT_KILLABLE); html_top.name = name; html_top.namelen = namelen; html_top.options = attr; html_top.linebreak = ei->linebreak;#ifdef CONFIG_ECMASCRIPT if (has_attr(attr, "onClick", html_context->options)) { /* XXX: Put something better to format.link. --pasky */ mem_free_set(&format.link, stracpy("javascript:void(0);")); mem_free_set(&format.target, stracpy(html_context->base_target)); format.style.fg = format.clink; html_top.pseudo_class = ELEMENT_LINK; mem_free_set(&format.title, stracpy("onClick placeholder")); /* Er. I know. Well, double html_focusable()s shouldn't * really hurt. */ html_focusable(html_context, attr); }#endif }#ifdef CONFIG_CSS if (html_top.options && html_context->options->css_enable) { /* XXX: We should apply CSS otherwise as well, but that'll need * some deeper changes in order to have options filled etc. * Probably just applying CSS from more places, since we * usually have type != ELEMENT_TYPE_NESTABLE when we either (1) * rescan on your own from somewhere else (2) html_stack_dup() * in our own way. --pasky */ /* Call it now to gain some of the stuff which might affect * formatting of some elements. */ /* FIXME: The caching of the CSS selector is broken, since t can * lead to wrong styles being applied to following elements, so * disabled for now. */ selector = get_css_selector_for_element(html_context, &html_top, &html_context->css_styles, &html_context->stack); if (selector) { apply_css_selector_style(html_context, &html_top, selector); done_css_selector(selector); } } /* Now this was the reason for this whole funny ELEMENT_RENDER_PROLOGUE * bussiness. Only now we have the definitive linebreak value, since * that's what the display: property plays with. */#endif ELEMENT_RENDER_PROLOGUE if (ei->func) ei->func(html_context, attr, html, eof, &html);#ifdef CONFIG_CSS if (selector && html_top.options) { /* Call it now to override default colors of the elements. */ selector = get_css_selector_for_element(html_context, &html_top, &html_context->css_styles, &html_context->stack); if (selector) { apply_css_selector_style(html_context, &html_top, selector); done_css_selector(selector); } }#endif if (ei->func != html_br) html_context->was_br = 0; if (restore_format) par_format = old_format; return html;#undef ELEMENT_RENDER_PROLOGUE}static unsigned char *end_element(struct element_info *ei, unsigned char *name, int namelen, unsigned char *html, unsigned char *eof, unsigned char *attr, struct html_context *html_context){ struct html_element *e, *elt; int lnb = 0; int kill = 0; if (ei->func == html_xmp) html_context->was_xmp = 0; html_context->was_br = 0; if (ei->type == ELEMENT_TYPE_NON_PAIRABLE || ei->type == ELEMENT_TYPE_LI) return html; /* Apply background color from the <HTML> element. (bug 696) */ if (ei->func == html_html && html_top.type >= ELEMENT_KILLABLE && !html_context->was_body_background) html_apply_canvas_bgcolor(html_context); /* dump_html_stack(html_context); */ foreach (e, html_context->stack) { if (is_block_element(e) && is_inline_element(ei)) kill = 1; if (strlcasecmp(e->name, e->namelen, name, namelen)) { if (e->type < ELEMENT_KILLABLE) break; else continue; } if (kill) { kill_html_stack_item(html_context, e); break; } for (elt = e; elt != (void *) &html_context->stack; elt = elt->prev) if (elt->linebreak > lnb) lnb = elt->linebreak; /* This hack forces a line break after a list end. It is needed * when ending a list with the last <li> having no text the * line_breax is 2 so the ending list's linebreak will be * ignored when calling ln_break(). */ if (html_context->was_li) html_context->line_breax = 0; ln_break(html_context, lnb); while (e->prev != (void *) &html_context->stack) kill_html_stack_item(html_context, e->prev); kill_html_stack_item(html_context, e); break; } /* dump_html_stack(html_context); */ return html;}static unsigned char *process_element(unsigned char *name, int namelen, int endingtag, unsigned char *html, unsigned char *prev_html, unsigned char *eof, unsigned char *attr, struct html_context *html_context){ struct element_info *ei;#ifndef USE_FASTFIND { struct element_info elem; unsigned char tmp; tmp = name[namelen]; name[namelen] = '\0'; elem.name = name; ei = bsearch(&elem, elements, NUMBER_OF_TAGS, sizeof(elem), compar); name[namelen] = tmp; }#else ei = (struct element_info *) fastfind_search(&ff_tags_index, name, namelen);#endif if (html_context->was_xmp) { if (!ei || ei->func != html_xmp || !endingtag) { put_chrs(html_context, "<", 1); return prev_html + 1; } } if (!ei) return html; if (!endingtag) { return start_element(ei, name, namelen, html, eof, attr, html_context); } else { return end_element(ei, name, namelen, html, eof, attr, html_context); }}voidscan_http_equiv(unsigned char *s, unsigned char *eof, struct string *head, struct string *title, struct document_options *options){ unsigned char *name, *attr, *he, *c; int namelen; if (title && !init_string(title)) return; add_char_to_string(head, '\n');se: while (s < eof && *s != '<') {sp: s++; } if (s >= eof) return; if (s + 2 <= eof && (s[1] == '!' || s[1] == '?')) { s = skip_comment(s, eof); goto se; } if (parse_element(s, eof, &name, &namelen, &attr, &s)) goto sp;ps: if (!strlcasecmp(name, namelen, "HEAD", 4)) goto se; if (!strlcasecmp(name, namelen, "/HEAD", 5)) return; if (!strlcasecmp(name, namelen, "BODY", 4)) return; if (title && !title->length && !strlcasecmp(name, namelen, "TITLE", 5)) { unsigned char *s1;xse: s1 = s; while (s < eof && *s != '<') {xsp: s++; } if (s - s1) add_bytes_to_string(title, s1, s - s1); if (s >= eof) goto se; if (s + 2 <= eof && (s[1] == '!' || s[1] == '?')) { s = skip_comment(s, eof); goto xse; } if (parse_element(s, eof, &name, &namelen, &attr, &s)) { s1 = s; goto xsp; } clr_spaces(title->source); goto ps; } if (strlcasecmp(name, namelen, "META", 4)) goto se; he = get_attr_val(attr, "charset", options); if (he) { add_to_string(head, "Charset: "); add_to_string(head, he); mem_free(he); } he = get_attr_val(attr, "http-equiv", options); if (!he) goto se; add_to_string(head, he); mem_free(he); c = get_attr_val(attr, "content", options); if (c) { add_to_string(head, ": "); add_to_string(head, c); mem_free(c); } add_crlf_to_string(head); goto se;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -