📄 html.c
字号:
{"mediumturquoise", 0x48D1CC}, {"mediumvioletred", 0xC71585}, {"midnightblue", 0x191970}, {"mintcream", 0xF5FFFA}, {"mistyrose", 0xFFE4E1}, {"moccasin", 0xFFE4B5}, {"navajowhite", 0xFFDEAD}, {"navy", 0x000080}, {"oldlace", 0xFDF5E6}, {"olive", 0x808000}, {"olivedrab", 0x6B8E23}, {"orange", 0xFFA500}, {"orangered", 0xFF4500}, {"orchid", 0xDA70D6}, {"palegoldenrod", 0xEEE8AA}, {"palegreen", 0x98FB98}, {"paleturquoise", 0xAFEEEE}, {"palevioletred", 0xDB7093}, {"papayawhip", 0xFFEFD5}, {"peachpuff", 0xFFDAB9}, {"peru", 0xCD853F}, {"pink", 0xFFC0CB}, {"plum", 0xDDA0DD}, {"powderblue", 0xB0E0E6}, {"purple", 0x800080}, {"red", 0xFF0000}, {"rosybrown", 0xBC8F8F}, {"royalblue", 0x4169E1}, {"saddlebrown", 0x8B4513}, {"salmon", 0xFA8072}, {"sandybrown", 0xF4A460}, {"seagreen", 0x2E8B57}, {"seashell", 0xFFF5EE}, {"sienna", 0xA0522D}, {"silver", 0xC0C0C0}, {"skyblue", 0x87CEEB}, {"slateblue", 0x6A5ACD}, {"slategray", 0x708090}, {"snow", 0xFFFAFA}, {"springgreen", 0x00FF7F}, {"steelblue", 0x4682B4}, {"tan", 0xD2B48C}, {"teal", 0x008080}, {"thistle", 0xD8BFD8}, {"tomato", 0xFF6347}, {"turquoise", 0x40E0D0}, {"violet", 0xEE82EE}, {"wheat", 0xF5DEB3}, {"white", 0xFFFFFF}, {"whitesmoke", 0xF5F5F5}, {"yellow", 0xFFFF00}, {"yellowgreen", 0x9ACD32},};#define endof(T) ((T)+sizeof(T)/sizeof(*(T)))int decode_color(unsigned char *str, struct rgb *col){ unsigned long ch; if (*str != '#') { struct color_spec *cs; for (cs = color_specs; cs < endof(color_specs); cs++) if (!strcasecmp(cs->name, str)) { ch = cs->rgb; goto found; } str--; } str++; if (strlen(str) == 6) { char *end; ch = strtoul(str, &end, 16); if (!*end && ch < 0x1000000) {found: col->r = ch / 0x10000; col->g = ch / 0x100 % 0x100; col->b = ch % 0x100; return 0; } } return -1;}int get_color(unsigned char *a, unsigned char *c, struct rgb *rgb){ char *at; int r = -1; if (d_opt->col >= 1 || F) if ((at = get_attr_val(a, c))) { r = decode_color(at, rgb); mem_free(at); } return r;}int get_bgcolor(unsigned char *a, struct rgb *rgb){ if (d_opt->col < 2 && !F) return -1; return get_color(a, "bgcolor", rgb);}unsigned char *get_target(unsigned char *a){ return get_attr_val(a, "target");}void kill_html_stack_item(struct html_element *e){ html_format_changed = 1; if (e->dontkill == 2) { internal("trying to kill unkillable element"); return; } if (!e || (void *)e == &html_stack) { internal("trying to free bad html element"); return; } if (e->attr.fontface) mem_free(e->attr.fontface); if (e->attr.link) mem_free(e->attr.link); if (e->attr.target) mem_free(e->attr.target); if (e->attr.image) mem_free(e->attr.image); if (e->attr.href_base) mem_free(e->attr.href_base); if (e->attr.target_base) mem_free(e->attr.target_base); if (e->attr.select) mem_free(e->attr.select); free_js_event_spec(e->attr.js_event); del_from_list(e); mem_free(e); /*if ((void *)(html_stack.next) == &html_stack || !html_stack.next) { debug("killing last element"); }*/}static inline void kill_elem(char *e){ if ((size_t)html_top.namelen == strlen(e) && !casecmp(html_top.name, e, html_top.namelen)) kill_html_stack_item(&html_top);}#ifdef DEBUGvoid debug_stack(void){ struct html_element *e; printf("HTML stack debug: \n"); foreachback(e, html_stack) { int i; printf("\""); for (i = 0; i < e->namelen; i++) printf("%c", e->name[i]); printf("\"\n"); } printf("%c", 7); fflush(stdout); sleep(1);}#endifvoid html_stack_dup(void){ struct html_element *e; struct html_element *ep; html_format_changed = 1; if ((void *)(ep = html_stack.next) == &html_stack || !html_stack.next) { internal("html stack empty"); return; } e = mem_alloc(sizeof(struct html_element)); memcpy(e, ep, sizeof(struct html_element)); e->attr.fontface = stracpy(ep->attr.fontface); e->attr.link = stracpy(ep->attr.link); e->attr.target = stracpy(ep->attr.target); e->attr.image = stracpy(ep->attr.image); e->attr.href_base = stracpy(ep->attr.href_base); e->attr.target_base = stracpy(ep->attr.target_base); e->attr.select = stracpy(ep->attr.select); copy_js_event_spec(&e->attr.js_event, ep->attr.js_event); /*if (e->name) { if (e->attr.link) set_mem_comment(e->attr.link, e->name, e->namelen); if (e->attr.target) set_mem_comment(e->attr.target, e->name, e->namelen); if (e->attr.image) set_mem_comment(e->attr.image, e->name, e->namelen); if (e->attr.href_base) set_mem_comment(e->attr.href_base, e->name, e->namelen); if (e->attr.target_base) set_mem_comment(e->attr.target_base, e->name, e->namelen); if (e->attr.select) set_mem_comment(e->attr.select, e->name, e->namelen); }*/ e->name = e->options = NULL; e->namelen = 0; e->dontkill = 0; add_to_list(html_stack, e);}#ifdef JSvoid get_js_event(unsigned char *a, unsigned char *name, unsigned char **where){ unsigned char *v; if ((v = get_attr_val(a, name))) { if (*where) mem_free(*where); *where = v; }}int get_js_events_x(struct js_event_spec **spec, unsigned char *a){ if (!has_attr(a, "onkeyup") && !has_attr(a, "onkeydown") && !has_attr(a,"onkeypress") && !has_attr(a,"onchange") && !has_attr(a, "onfocus") && !has_attr(a,"onblur") && !has_attr(a, "onclick") && !has_attr(a, "ondblclick") && !has_attr(a, "onmousedown") && !has_attr(a, "onmousemove") && !has_attr(a, "onmouseout") && !has_attr(a, "onmouseover") && !has_attr(a, "onmouseup")) return 0; create_js_event_spec(spec); get_js_event(a, "onclick", &(*spec)->click_code); get_js_event(a, "ondblclick", &(*spec)->dbl_code); get_js_event(a, "onmousedown", &(*spec)->down_code); get_js_event(a, "onmouseup", &(*spec)->up_code); get_js_event(a, "onmouseover", &(*spec)->over_code); get_js_event(a, "onmouseout", &(*spec)->out_code); get_js_event(a, "onmousemove", &(*spec)->move_code); get_js_event(a, "onfocus", &(*spec)->focus_code); get_js_event(a, "onblur", &(*spec)->blur_code); get_js_event(a, "onchange", &(*spec)->change_code); get_js_event(a, "onkeypress", &(*spec)->keypress_code); get_js_event(a, "onkeyup", &(*spec)->keyup_code); get_js_event(a, "onkeydown", &(*spec)->keydown_code); return 1;}int get_js_events(unsigned char *a){ return get_js_events_x(&format.js_event, a);}#elseint get_js_events_x(struct js_event_spec **spec, unsigned char *a){ return 0;}int get_js_events(unsigned char *a){ return 0;}#endifvoid *ff;int (*put_chars_f)(void *, unsigned char *, int);void (*line_break_f)(void *);void *(*special_f)(void *, int, ...);unsigned char *eoff;unsigned char *eofff;unsigned char *startf;int line_breax;int pos;int putsp;int was_br;int table_level;int empty_format;void ln_break(int n, void (*line_break)(void *), void *f){ if (!n || html_top.invisible) return; while (n > line_breax) line_breax++, line_break(f); pos = 0; putsp = -1;}void put_chrs(unsigned char *start, int len, int (*put_chars)(void *, unsigned char *, int), void *f){ if (par_format.align == AL_NO) putsp = 0; if (!len || html_top.invisible) return; if (putsp == 1) pos += put_chars(f, " ", 1), putsp = -1; if (putsp == -1) { if (start[0] == ' ') start++, len--; putsp = 0; } if (!len) { putsp = -1; if (par_format.align == AL_NO) putsp = 0; return; } if (start[len - 1] == ' ') putsp = -1; if (par_format.align == AL_NO) putsp = 0; was_br = 0; pos += put_chars(f, start, len); line_breax = 0;}void kill_until(int ls, ...){ int l; struct html_element *e = &html_top; if (ls) e = e->next; while ((void *)e != &html_stack) { int sk = 0; va_list arg; va_start(arg, ls); while (1) { char *s = va_arg(arg, char *); if (!s) break; if (!*s) sk++; else if ((size_t)e->namelen == strlen(s) && !casecmp(e->name, s, strlen(s))) { if (!sk) { if (e->dontkill) break; va_end(arg); goto killll; } else if (sk == 1) { va_end(arg); goto killl; } else break; } } va_end(arg); if (e->dontkill || (e->namelen == 5 && !casecmp(e->name, "TABLE", 5))) break; if (e->namelen == 2 && upcase(e->name[0]) == 'T' && (upcase(e->name[1]) == 'D' || upcase(e->name[1]) == 'H' || upcase(e->name[1]) == 'R')) break; e = e->next; } return; killl: e = e->prev; killll: l = 0; while ((void *)e != &html_stack) { if (ls && e == html_stack.next) break; if (e->linebreak > l) l = e->linebreak; e = e->prev; kill_html_stack_item(e->next); } ln_break(l, line_break_f, ff);}int get_num(unsigned char *a, unsigned char *n){ char *al; if ((al = get_attr_val(a, n))) { char *end; unsigned long s = strtoul(al, &end, 10); if (!*al || *end || s > 10000) s = -1; mem_free(al); return s; } return -1;}/* trunc somehow clips the maximum values. Use 0 to disable truncastion. */int parse_width(unsigned char *w, int trunc){ unsigned char *end; int p = 0; long s; int l; int limit = par_format.width - (par_format.leftmargin + par_format.rightmargin) * gf_val(1, G_HTML_MARGIN); while (WHITECHAR(*w)) w++; for (l = 0; w[l] && w[l] != ','; l++) ; while (l && WHITECHAR(w[l - 1])) l--; if (!l) return -1; if (w[l - 1] == '%') l--, p = 1; while (l && WHITECHAR(w[l - 1])) l--; if (!l) return -1; s = strtoul((char *)w, (char **)(void *)&end, 10); if (end - w < l || s < 0 || s > 10000) return -1; if (p) { if (trunc) {#ifdef G if (trunc == 3) { return -1; /* limit = d_opt->yw - G_SCROLL_BAR_WIDTH; if (limit < 0) limit = 0; */ }#endif s = s * limit / 100; } else return -1; } else s = (s + (gf_val(HTML_CHAR_WIDTH, 1) - 1) / 2) / gf_val(HTML_CHAR_WIDTH, 1); if (trunc == 1 && s > limit) s = limit; if (s < 0) s = 0; return s;}/* trunc somehow clips the maximum values. Use 0 to disable truncastion. */int get_width(unsigned char *a, unsigned char *n, int trunc){ int r; unsigned char *w; if (!(w = get_attr_val(a, n))) return -1; r = parse_width(w, trunc); mem_free(w); return r;}/*int form_num;struct form form = { 0, NULL, 0 };int g_ctrl_num;*/struct form form = { NULL, NULL, NULL, NULL, 0, 0 };unsigned char *last_form_tag;unsigned char *last_form_attr;unsigned char *last_input_tag;static inline void set_link_attr(void){ memcpy(!(format.attr & AT_INVERT) ? &format.fg : &format.bg, &format.clink, sizeof(struct rgb));}void put_link_line(unsigned char *prefix, unsigned char *linkname, unsigned char *link, unsigned char *target){ html_stack_dup(); ln_break(1, line_break_f, ff); if (format.link) mem_free(format.link), format.link = NULL; if (format.target) mem_free(format.target), format.target = NULL; format.form = NULL; put_chrs(prefix, strlen(prefix), put_chars_f, ff); html_format_changed = 1; format.link = join_urls(format.href_base, link); format.target = stracpy(target); set_link_attr(); put_chrs(linkname, strlen(linkname), put_chars_f, ff); ln_break(1, line_break_f, ff); kill_html_stack_item(&html_top);}void html_span(unsigned char *a) { }void html_bold(unsigned char *a){ get_js_events(a); format.attr |= AT_BOLD; }void html_italic(unsigned char *a){ get_js_events(a); format.attr |= AT_ITALIC;}void html_underline(unsigned char *a){ get_js_events(a); format.attr |= AT_UNDERLINE;}void html_fixed(unsigned char *a){ get_js_events(a); format.attr |= AT_FIXED;}void html_invert(unsigned char *a){ struct rgb rgb; get_js_events(a); memcpy(&rgb, &format.fg, sizeof(struct rgb)); memcpy(&format.fg, &format.bg, sizeof(struct rgb)); memcpy(&format.bg, &rgb, sizeof(struct rgb)); format.attr ^= AT_INVERT;}void html_a(unsigned char *a){ char *al; int ev = get_js_events(a); if ((al = get_url_val(a, "href"))) { char *all = al; while (all[0] == ' ') all++; while (all[0] && all[strlen(all) - 1] == ' ') all[strlen(all) - 1] = 0; if (format.link) mem_free(format.link); format.link = join_urls(format.href_base, all); mem_free(al); if ((al = get_target(a))) { if (format.target) mem_free(format.target); format.target = al; } else { if (format.target) mem_free(format.target); format.target = stracpy(format.target_base); } /*format.attr ^= AT_BOLD;*/ set_link_attr(); } else if (!ev) kill_html_stack_item(&html_top); if ((al = get_attr_val(a, "name"))) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -