📄 html.c
字号:
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); 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(){ 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(){ struct html_element *e; struct html_element *ep; 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.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); /*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);}void *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;}int parse_width(unsigned char *w, int trunc){ unsigned char *end; int p = 0; long s; int l; 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) s = s * (par_format.width - par_format.leftmargin - par_format.rightmargin) / 100; else return -1; } else s = (s + (HTML_CHAR_WIDTH - 1) / 2) / HTML_CHAR_WIDTH; if (trunc && s > par_format.width - par_format.leftmargin - par_format.rightmargin) s = par_format.width - par_format.leftmargin - par_format.rightmargin; if (s < 0) s = 0; return s;}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, 0, 0 };unsigned char *last_form_tag;unsigned char *last_form_attr;unsigned char *last_input_tag;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); format.link = join_urls(format.href_base, link); format.target = stracpy(target); memcpy(&format.fg, &format.clink, sizeof(struct rgb)); 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) { format.attr |= AT_BOLD; }void html_italic(unsigned char *a) { format.attr |= AT_ITALIC; }void html_underline(unsigned char *a) { format.attr |= AT_UNDERLINE; }void html_fixed(unsigned char *a) { format.attr |= AT_FIXED; }void html_a(unsigned char *a){ char *al; 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;*/ memcpy(&format.fg, &format.clink, sizeof(struct rgb)); } else kill_html_stack_item(&html_top); if ((al = get_attr_val(a, "name"))) { special_f(ff, SP_TAG, al); mem_free(al); }}void html_font(unsigned char *a){ char *al; if ((al = get_attr_val(a, "size"))) { int p = 0; unsigned long s; char *nn = al; char *end; if (*al == '+') p = 1, nn++; if (*al == '-') p = -1, nn++; s = strtoul(nn, &end, 10); if (*nn && !*end) { if (s > 7) s = 7; if (!p) format.fontsize = s; else format.fontsize += p * s; if (format.fontsize < 1) format.fontsize = 1; if (format.fontsize > 7) format.fontsize = 7; } mem_free(al); } get_color(a, "color", &format.fg);}void html_img(unsigned char *a){ unsigned char *al; int ismap, usemap = 0; /*put_chrs(" ", 1, put_chars_f, ff);*/ if ((al = get_attr_val(a, "usemap"))) { unsigned char *u; usemap = 1; html_stack_dup(); if (format.link) mem_free(format.link); if (format.form) format.form = NULL; u = join_urls(format.href_base, al); format.link = mem_alloc(strlen(u) + 5); strcpy(format.link, "MAP@"); strcat(format.link, u); format.attr |= AT_BOLD; mem_free(u); mem_free(al); } ismap = format.link && has_attr(a, "ismap") && !usemap; if ((!(al = get_attr_val(a, "alt")) && !(al = get_attr_val(a, "title"))) || !*al) { if (al) mem_free(al); if (!d_opt->images && !format.link) return; if (usemap) al = stracpy("[USEMAP]"); else if (ismap) al = stracpy("[ISMAP]"); else al = stracpy("[IMG]"); } if (format.image) mem_free(format.image), format.image = NULL; if (al) { unsigned char *s; if ((s = get_url_val(a, "src")) || (s = get_attr_val(a, "dynsrc"))) { format.image = join_urls(format.href_base, s); mem_free(s); } if (ismap) { unsigned char *h; html_stack_dup(); h = stracpy(format.link); add_to_strn(&h, "?0,0"); mem_free(format.link); format.link = h; } put_chrs(al, strlen(al), put_chars_f, ff); if (ismap) kill_html_stack_item(&html_top); } if (format.image) mem_free(format.image), format.image = NULL; mem_free(al); if (usemap) kill_html_stack_item(&html_top); /*put_chrs(" ", 1, put_chars_f, ff);*/}void html_body(unsigned char *a){ get_color(a, "text", &format.fg); get_color(a, "link", &format.clink); get_color(a, "vlink", &format.vlink); get_bgcolor(a, &format.bg); get_bgcolor(a, &par_format.bgcolor);}void html_skip(unsigned char *a) { html_top.invisible = html_top.dontkill = 1; }void html_title(unsigned char *a) { html_top.invisible = html_top.dontkill = 1; }void html_center(unsigned char *a){ par_format.align = AL_CENTER; if (!table_level) par_format.leftmargin = par_format.rightmargin = 0;}void html_linebrk(unsigned char *a){ char *al; if ((al = get_attr_val(a, "align"))) { if (!strcasecmp(al, "left")) par_format.align = AL_LEFT; if (!strcasecmp(al, "right")) par_format.align = AL_RIGHT; if (!strcasecmp(al, "center")) { par_format.align = AL_CENTER; if (!table_level) par_format.leftmargin = par_format.rightmargin = 0; } if (!strcasecmp(al, "justify")) par_format.align = AL_BLOCK; mem_free(al); }}void html_br(unsigned char *a){ html_linebrk(a); if (was_br) ln_break(2, line_break_f, ff); was_br = 1;}void html_form(unsigned char *a){ was_br = 1;}void html_p(unsigned char *a){ if (par_format.leftmargin < margin) par_format.leftmargin = margin; if (par_format.rightmargin < margin) par_format.rightmargin = margin; /*par_format.align = AL_LEFT;*/ html_linebrk(a);}void html_address(unsigned char *a){ par_format.leftmargin += 1; par_format.align = AL_LEFT;}void html_blockquote(unsigned char *a){ par_format.leftmargin += 2; par_format.align = AL_LEFT;}void html_h(int h, char *a){ par_format.align = AL_LEFT; html_linebrk(a); switch (par_format.align) { case AL_LEFT: par_format.leftmargin = (h - 2) * 2; par_format.rightmargin = 0; break; case AL_RIGHT: par_format.leftmargin = 0; par_format.rightmargin = (h - 2) * 2; break; case AL_CENTER: par_format.leftmargin = par_format.rightmargin = 0; break; case AL_BLOCK: par_format.leftmargin = par_format.rightmargin = (h - 2) * 2; break; }}void html_h2(unsigned char *a) { html_h(2, a); }void html_h3(unsigned char *a) { html_h(3, a); }void html_h4(unsigned char *a) { html_h(4, a); }void html_h5(unsigned char *a) { html_h(5, a); }void html_h6(unsigned char *a) { html_h(6, a); }void html_pre(unsigned char *a){ par_format.align = AL_NO; par_format.leftmargin = par_format.leftmargin > 1; par_format.rightmargin = 0;}void html_hr(unsigned char *a){ int i/* = par_format.width - 10*/; unsigned char r = 205; int q = get_num(a, "size"); if (q >= 0 && q < 2) r = 196; html_stack_dup(); par_format.align = AL_CENTER; if (format.link) mem_free(format.link), format.link = NULL; format.form = NULL; html_linebrk(a); if (par_format.align == AL_BLOCK) par_format.align = AL_CENTER; par_format.leftmargin = margin; par_format.rightmargin = margin; if ((i = get_width(a, "width", 1)) == -1) i = par_format.width - 2 * margin - 4; format.attr = AT_GRAPHICS; special_f(ff, SP_NOWRAP, 1); while (i-- > 0) put_chrs(&r, 1, put_chars_f, ff); special_f(ff, SP_NOWRAP, 0); ln_break(2, line_break_f, ff); kill_html_stack_item(&html_top);}void html_table(unsigned char *a){ par_format.leftmargin = margin; par_format.rightmargin = margin; par_format.align = AL_LEFT; html_linebrk(a); format.attr = 0;}void html_tr(unsigned char *a){ html_linebrk(a);}void html_th(unsigned char *a){ /*html_linebrk(a);*/ kill_until(1, "TD", "TH", "", "TR", "TABLE", NULL); format.attr |= AT_BOLD; put_chrs(" ", 1, put_chars_f, ff);}void html_td(unsigned char *a){ /*html_linebrk(a);*/ kill_until(1, "TD", "TH", "", "TR", "TABLE", NULL); format.attr &= ~AT_BOLD; put_chrs(" ", 1, put_chars_f, ff);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -