📄 general.c
字号:
/* General element handlers */#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifndef _GNU_SOURCE#define _GNU_SOURCE /* strcasestr() */#endif#include <ctype.h>#include <errno.h>#include <stdlib.h>#include <string.h>#include "elinks.h"#include "config/options.h"#include "document/css/apply.h"#include "document/html/frames.h"#include "document/html/parser/general.h"#include "document/html/parser/link.h"#include "document/html/parser/stack.h"#include "document/html/parser/parse.h"#include "document/html/parser.h"#include "document/html/renderer.h"#include "document/html/tables.h"#include "document/options.h"#include "intl/charsets.h"#include "protocol/uri.h"#include "terminal/draw.h"#include "util/align.h"#include "util/box.h"#include "util/color.h"#include "util/conv.h"#include "util/error.h"#include "util/memdebug.h"#include "util/memory.h"#include "util/string.h"/* Unsafe macros */#include "document/html/internal.h"voidhtml_span(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){}voidhtml_bold(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ format.style.attr |= AT_BOLD;}voidhtml_italic(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ format.style.attr |= AT_ITALIC;}voidhtml_underline(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ format.style.attr |= AT_UNDERLINE;}voidhtml_fixed(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ format.style.attr |= AT_FIXED;}voidhtml_subscript(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ format.style.attr |= AT_SUBSCRIPT | AT_UPDATE_SUB;}voidhtml_superscript(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ format.style.attr |= AT_SUPERSCRIPT | AT_UPDATE_SUP;}voidhtml_font(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ unsigned char *al = get_attr_val(a, "size", html_context->options); if (al) { int p = 0; unsigned s; unsigned char *nn = al; unsigned char *end; if (*al == '+') p = 1, nn++; else if (*al == '-') p = -1, nn++; errno = 0; s = strtoul(nn, (char **) &end, 10); if (!errno && *nn && !*end) { if (s > 7) s = 7; if (!p) format.fontsize = s; else format.fontsize += p * s; if (format.fontsize < 1) format.fontsize = 1; else if (format.fontsize > 7) format.fontsize = 7; } mem_free(al); } get_color(html_context, a, "color", &format.style.fg);}voidhtml_body(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ get_color(html_context, a, "text", &format.style.fg); get_color(html_context, a, "link", &format.clink); get_color(html_context, a, "vlink", &format.vlink); if (get_bgcolor(html_context, a, &format.style.bg) != -1) html_context->was_body_background = 1; html_context->was_body = 1; /* this will be used by "meta inside body" */ html_apply_canvas_bgcolor(html_context);}voidhtml_apply_canvas_bgcolor(struct html_context *html_context){#ifdef CONFIG_CSS /* If there are any CSS twaks regarding bgcolor, make sure we will get * it _and_ prefer it over bgcolor attribute. */ if (html_context->options->css_enable) css_apply(html_context, &html_top, &html_context->css_styles, &html_context->stack);#endif if (par_format.bgcolor != format.style.bg) { /* Modify the root HTML element - format_html_part() will take * this from there. */ struct html_element *e = html_context->stack.prev; html_context->was_body_background = 1; e->parattr.bgcolor = e->attr.style.bg = par_format.bgcolor = format.style.bg; } if (html_context->has_link_lines && par_format.bgcolor != html_context->options->default_bg && !search_html_stack(html_context, "BODY")) { html_context->special_f(html_context, SP_COLOR_LINK_LINES); }}voidhtml_script(struct html_context *html_context, unsigned char *a, unsigned char *html, unsigned char *eof, unsigned char **end){#ifdef CONFIG_ECMASCRIPT /* TODO: <noscript> processing. Well, same considerations apply as to * CSS property display: none processing. */ /* TODO: Charsets for external scripts. */ unsigned char *type, *language, *src; int in_comment = 0;#endif html_skip(html_context, a);#ifdef CONFIG_ECMASCRIPT /* We try to process nested <script> if we didn't process the parent * one. That's why's all the fuzz. */ /* Ref: * http://www.ietf.org/internet-drafts/draft-hoehrmann-script-types-03.txt */ type = get_attr_val(a, "type", html_context->options); if (type) { unsigned char *pos = type; if (!strncasecmp(type, "text/", 5)) { pos += 5; } else if (!strncasecmp(type, "application/", 12)) { pos += 12; } else { mem_free(type);not_processed: /* Permit nested scripts and retreat. */ html_top.invisible++; return; } if (!strncasecmp(pos, "javascript", 10)) { int len = strlen(pos); if (len > 10 && !isdigit(pos[10])) { mem_free(type); goto not_processed; } } else if (strcasecmp(pos, "ecmascript") && strcasecmp(pos, "jscript") && strcasecmp(pos, "livescript") && strcasecmp(pos, "x-javascript") && strcasecmp(pos, "x-ecmascript")) { mem_free(type); goto not_processed; } mem_free(type); } /* Check that the script content is ecmascript. The value of the * language attribute can be JavaScript with optional version digits * postfixed (like: ``JavaScript1.1''). * That attribute is deprecated in favor of type by HTML 4.01 */ language = get_attr_val(a, "language", html_context->options); if (language) { int languagelen = strlen(language); if (languagelen < 10 || (languagelen > 10 && !isdigit(language[10])) || strncasecmp(language, "javascript", 10)) { mem_free(language); goto not_processed; } mem_free(language); } if (html_context->part->document && (src = get_attr_val(a, "src", html_context->options))) { /* External reference. */ unsigned char *import_url; struct uri *uri; if (!get_opt_bool("ecmascript.enable")) { mem_free(src); goto not_processed; } /* HTML <head> urls should already be fine but we can.t detect them. */ import_url = join_urls(html_context->base_href, src); mem_free(src); if (!import_url) goto imported; uri = get_uri(import_url, URI_BASE); if (!uri) goto imported; /* Request the imported script as part of the document ... */ html_context->special_f(html_context, SP_SCRIPT, uri); done_uri(uri); /* Create URL reference onload snippet. */ insert_in_string(&import_url, 0, "^", 1); add_to_string_list(&html_context->part->document->onload_snippets, import_url, -1);imported: /* Retreat. Do not permit nested scripts, tho'. */ if (import_url) mem_free(import_url); return; } /* Positive, grab the rest and interpret it. */ /* First position to the real script start. */ while (html < eof && *html <= ' ') html++; if (eof - html > 4 && !strncmp(html, "<!--", 4)) { in_comment = 1; /* We either skip to the end of line or to -->. */ for (; *html != '\n' && *html != '\r' && eof - html >= 3; html++) { if (!strncmp(html, "-->", 3)) { /* This means the document is probably broken. * We will now try to process the rest of * <script> contents, which is however likely * to be empty. Should we try to process the * comment too? Currently it seems safer but * less tolerant to broken pages, if there are * any like this. */ html += 3; in_comment = 0; break; } } } *end = html; /* Now look ahead for the script end. The <script> contents is raw * CDATA, so we just look for the ending tag and need not care for * any quote marks counting etc - YET, we are more tolerant and permit * </script> stuff inside of the script if the whole <script> element * contents is wrapped in a comment. See i.e. Mozilla bug 26857 for fun * reading regarding this. */ for (; *end < eof; (*end)++) { unsigned char *name; int namelen; if (in_comment) { /* TODO: If we ever get some standards-quirk mode * distinction, this should be disabled in the * standards mode (and we should just look for CDATA * end, which is "</"). --pasky */ if (eof - *end >= 3 && !strncmp(*end, "-->", 3)) { /* Next iteration will jump passed the ending '>' */ (*end) += 2; in_comment = 0; } continue; /* XXX: Scan for another comment? That's admittelly * already stretching things a little bit to an * extreme ;-). */ } if (**end != '<') continue; /* We want to land before the closing element, that's why we * don't pass @end also as the appropriate parse_element() * argument. */ if (parse_element(*end, eof, &name, &namelen, NULL, NULL)) continue; if (strlcasecmp(name, namelen, "/script", 7)) continue; /* We have won! */ break; } if (*end >= eof) { /* Either the document is not completely loaded yet or it's * broken. At any rate, run away screaming. */ *end = eof; /* Just for sanity. */ return; } if (html_context->part->document && *html != '^') { add_to_string_list(&html_context->part->document->onload_snippets, html, *end - html); }#endif}voidhtml_style(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ html_skip(html_context, a);}voidhtml_html(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ /* This is here just to get CSS stuff applied. */ /* Modify the root HTML element - format_html_part() will take * this from there. */ struct html_element *e = html_context->stack.prev; if (par_format.bgcolor != format.style.bg) e->parattr.bgcolor = e->attr.style.bg = par_format.bgcolor = format.style.bg;}voidhtml_head(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ /* This makes sure it gets to the stack and helps tame down unclosed * <title>. */}voidhtml_meta(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ /* html_handle_body_meta() does all the work. */}/* Handles meta tags in the HTML body. */voidhtml_handle_body_meta(struct html_context *html_context, unsigned char *meta, unsigned char *eof){ struct string head; if (!init_string(&head)) return; scan_http_equiv(meta, eof, &head, NULL, html_context->options); process_head(html_context, head.source); done_string(&head);}voidhtml_title(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ html_top.invisible = 1; html_top.type = ELEMENT_WEAK;}voidhtml_center(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ par_format.align = ALIGN_CENTER; if (!html_context->table_level) par_format.leftmargin = par_format.rightmargin = 0;}voidhtml_linebrk(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ unsigned char *al = get_attr_val(a, "align", html_context->options); if (al) { if (!strcasecmp(al, "left")) par_format.align = ALIGN_LEFT; else if (!strcasecmp(al, "right")) par_format.align = ALIGN_RIGHT; else if (!strcasecmp(al, "center")) { par_format.align = ALIGN_CENTER; if (!html_context->table_level) par_format.leftmargin = par_format.rightmargin = 0; } else if (!strcasecmp(al, "justify")) par_format.align = ALIGN_JUSTIFY; mem_free(al); }}voidhtml_br(struct html_context *html_context, unsigned char *a, unsigned char *html, unsigned char *eof, unsigned char **end){ html_linebrk(html_context, a, html, eof, end); if (html_context->was_br) ln_break(html_context, 2); else html_context->was_br = 1;}voidhtml_p(struct html_context *html_context, unsigned char *a, unsigned char *html, unsigned char *eof, unsigned char **end){ int_lower_bound(&par_format.leftmargin, html_context->margin); int_lower_bound(&par_format.rightmargin, html_context->margin); /*par_format.align = ALIGN_LEFT;*/ html_linebrk(html_context, a, html, eof, end);}voidhtml_address(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ par_format.leftmargin++; par_format.align = ALIGN_LEFT;}voidhtml_blockquote(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5){ par_format.leftmargin += 2; par_format.align = ALIGN_LEFT;}voidhtml_h(int h, unsigned char *a, enum format_align default_align, struct html_context *html_context, unsigned char *html, unsigned char *eof, unsigned char **end){ if (!par_format.align) par_format.align = default_align; html_linebrk(html_context, a, html, eof, end); h -= 2; if (h < 0) h = 0; switch (par_format.align) { case ALIGN_LEFT: par_format.leftmargin = h * 2; par_format.rightmargin = 0; break; case ALIGN_RIGHT: par_format.leftmargin = 0; par_format.rightmargin = h * 2; break; case ALIGN_CENTER: par_format.leftmargin = par_format.rightmargin = 0; break; case ALIGN_JUSTIFY: par_format.leftmargin = par_format.rightmargin = h * 2; break; }}voidhtml_h1(struct html_context *html_context, unsigned char *a, unsigned char *html, unsigned char *eof, unsigned char **end){ format.style.attr |= AT_BOLD; html_h(1, a, ALIGN_CENTER, html_context, html, eof, end);}voidhtml_h2(struct html_context *html_context, unsigned char *a, unsigned char *html, unsigned char *eof, unsigned char **end){ html_h(2, a, ALIGN_LEFT, html_context, html, eof, end);}voidhtml_h3(struct html_context *html_context, unsigned char *a, unsigned char *html, unsigned char *eof, unsigned char **end){ html_h(3, a, ALIGN_LEFT, html_context, html, eof, end);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -