📄 parser.c
字号:
rows = get_attr_val(a, "rows"); if (!rows) { rows = stracpy("100%"); if (!rows) { mem_free(cols); return; } } if (!html_top.frameset) { width = global_doc_opts->box.width; height = global_doc_opts->box.height; global_doc_opts->needs_height = 1; } else { struct frameset_desc *frameset_desc = html_top.frameset; int offset; if (frameset_desc->box.y >= frameset_desc->box.height) goto free_and_return; offset = frameset_desc->box.x + frameset_desc->box.y * frameset_desc->box.width; width = frameset_desc->frame_desc[offset].width; height = frameset_desc->frame_desc[offset].height; } fp.width = fp.height = NULL; parse_frame_widths(cols, width, HTML_FRAME_CHAR_WIDTH, &fp.width, &fp.x); parse_frame_widths(rows, height, HTML_FRAME_CHAR_HEIGHT, &fp.height, &fp.y); fp.parent = html_top.frameset; if (fp.x && fp.y) { html_top.frameset = html_context.special_f(html_context.part, SP_FRAMESET, &fp); } mem_free_if(fp.width); mem_free_if(fp.height);free_and_return: mem_free(cols); mem_free(rows);}voidprocess_head(unsigned char *head){ unsigned char *refresh, *url; refresh = parse_header(head, "Refresh", NULL); if (refresh) { url = parse_header_param(refresh, "URL"); if (!url) { /* If the URL parameter is missing assume that the * document being processed should be refreshed. */ url = get_uri_string(html_context.base_href, URI_ORIGINAL); } if (url) { unsigned char *saved_url = url; /* Extraction of refresh time. */ unsigned long seconds; errno = 0; seconds = strtoul(refresh, NULL, 10); if (errno || seconds > 7200) seconds = 0; html_focusable(NULL); url = join_urls(html_context.base_href, saved_url); put_link_line("Refresh: ", saved_url, url, global_doc_opts->framename); html_context.special_f(html_context.part, SP_REFRESH, seconds, url); mem_free(url); mem_free(saved_url); } mem_free(refresh); } if (!get_opt_bool("document.cache.ignore_cache_control")) { unsigned char *d; int no_cache = 0; time_t expires = 0; /* XXX: Code duplication with HTTP protocol backend. */ /* I am not entirely sure in what order we should process these * headers and if we should still process Cache-Control max-age * if we already set max age to date mentioned in Expires. * --jonas */ if ((d = parse_header(head, "Pragma", NULL))) { if (strstr(d, "no-cache")) { no_cache = 1; } mem_free(d); } if (!no_cache && (d = parse_header(head, "Cache-Control", NULL))) { if (strstr(d, "no-cache") || strstr(d, "must-revalidate")) { no_cache = 1; } else { unsigned char *pos = strstr(d, "max-age="); assert(!no_cache); if (pos) { /* Grab the number of seconds. */ expires = time(NULL) + atol(pos + 8); } } mem_free(d); } if (!no_cache && (d = parse_header(head, "Expires", NULL))) { /* Convert date to seconds. */ if (strstr(d, "now")) { expires = time(NULL); } else { expires = parse_date(&d, NULL, 0, 1); } mem_free(d); } if (no_cache) html_context.special_f(html_context.part, SP_CACHE_CONTROL); else if (expires) html_context.special_f(html_context.part, SP_CACHE_EXPIRES, expires); }}static intlook_for_map(unsigned char **pos, unsigned char *eof, struct uri *uri){ unsigned char *al, *attr, *name; int namelen; while (*pos < eof && **pos != '<') { (*pos)++; } if (*pos >= eof) return 0; if (*pos + 2 <= eof && ((*pos)[1] == '!' || (*pos)[1] == '?')) { *pos = skip_comment(*pos, eof); return 1; } if (parse_element(*pos, eof, &name, &namelen, &attr, pos)) { (*pos)++; return 1; } if (strlcasecmp(name, namelen, "MAP", 3)) return 1; if (uri && uri->fragment) { al = get_attr_val(attr, "name"); if (!al) return 1; if (strlcasecmp(al, -1, uri->fragment, uri->fragmentlen)) { mem_free(al); return 1; } mem_free(al); } return 0;}static intlook_for_tag(unsigned char **pos, unsigned char *eof, unsigned char *name, int namelen, unsigned char **label){ unsigned char *pos2; struct string str; if (!init_string(&str)) { /* Is this the right way to bail out? --jonas */ *pos = eof; return 0; } pos2 = *pos; while (pos2 < eof && *pos2 != '<') { pos2++; } if (pos2 >= eof) { done_string(&str); *pos = eof; return 0; } if (pos2 - *pos) add_bytes_to_string(&str, *pos, pos2 - *pos); *label = str.source; *pos = pos2; if (*pos + 2 <= eof && ((*pos)[1] == '!' || (*pos)[1] == '?')) { *pos = skip_comment(*pos, eof); return 1; } if (parse_element(*pos, eof, NULL, NULL, NULL, &pos2)) return 1; if (strlcasecmp(name, namelen, "A", 1) && strlcasecmp(name, namelen, "/A", 2) && strlcasecmp(name, namelen, "MAP", 3) && strlcasecmp(name, namelen, "/MAP", 4) && strlcasecmp(name, namelen, "AREA", 4) && strlcasecmp(name, namelen, "/AREA", 5)) { *pos = pos2; return 1; } return 0;}static intlook_for_link(unsigned char **pos, unsigned char *eof, struct menu_item **menu, struct memory_list **ml, struct uri *href_base, unsigned char *target_base, struct conv_table *ct){ unsigned char *attr, *label, *href, *name, *target; struct link_def *ld; struct menu_item *nm; int nmenu; int namelen; while (*pos < eof && **pos != '<') { (*pos)++; } if (*pos >= eof) return 0; if (*pos + 2 <= eof && ((*pos)[1] == '!' || (*pos)[1] == '?')) { *pos = skip_comment(*pos, eof); return 1; } if (parse_element(*pos, eof, &name, &namelen, &attr, pos)) { (*pos)++; return 1; } if (!strlcasecmp(name, namelen, "A", 1)) { while (look_for_tag(pos, eof, name, namelen, &label)); if (*pos >= eof) return 0; } else if (!strlcasecmp(name, namelen, "AREA", 4)) { unsigned char *alt = get_attr_val(attr, "alt"); if (alt) { label = convert_string(ct, alt, strlen(alt), CSM_DEFAULT, NULL, NULL, NULL); mem_free(alt); } else { label = NULL; } } else if (!strlcasecmp(name, namelen, "/MAP", 4)) { /* This is the only successful return from here! */ add_to_ml(ml, *menu, NULL); return 0; } else { return 1; } target = get_target(attr); if (!target) target = null_or_stracpy(target_base); if (!target) target = stracpy(""); if (!target) { mem_free_if(label); return 1; } ld = mem_alloc(sizeof(*ld)); if (!ld) { mem_free_if(label); mem_free(target); return 1; } href = get_url_val(attr, "href"); if (!href) { mem_free_if(label); mem_free(target); mem_free(ld); return 1; } ld->link = join_urls(href_base, href); mem_free(href); if (!ld->link) { mem_free_if(label); mem_free(target); mem_free(ld); return 1; } ld->target = target; for (nmenu = 0; !mi_is_end_of_menu(&(*menu)[nmenu]); nmenu++) { struct link_def *ll = (*menu)[nmenu].data; if (!strcmp(ll->link, ld->link) && !strcmp(ll->target, ld->target)) { mem_free(ld->link); mem_free(ld->target); mem_free(ld); mem_free_if(label); return 1; } } if (label) { clr_spaces(label); if (!*label) { mem_free(label); label = NULL; } } if (!label) { label = stracpy(ld->link); if (!label) { mem_free(target); mem_free(ld->link); mem_free(ld); return 1; } } nm = mem_realloc(*menu, (nmenu + 2) * sizeof(*nm)); if (nm) { *menu = nm; memset(&nm[nmenu], 0, 2 * sizeof(*nm)); nm[nmenu].text = label; nm[nmenu].func = map_selected; nm[nmenu].data = ld; nm[nmenu].flags = NO_INTL; } add_to_ml(ml, ld, ld->link, ld->target, label, NULL); return 1;}intget_image_map(unsigned char *head, unsigned char *pos, unsigned char *eof, struct menu_item **menu, struct memory_list **ml, struct uri *uri, unsigned char *target_base, int to, int def, int hdef){ struct conv_table *ct; struct string hd; if (!init_string(&hd)) return -1; if (head) add_to_string(&hd, head); scan_http_equiv(pos, eof, &hd, NULL); ct = get_convert_table(hd.source, to, def, NULL, NULL, hdef); done_string(&hd); *menu = mem_calloc(1, sizeof(**menu)); if (!*menu) return -1; while (look_for_map(&pos, eof, uri)); if (pos >= eof) { mem_free(*menu); return -1; } *ml = NULL; while (look_for_link(&pos, eof, menu, ml, uri, target_base, ct)) ; if (pos >= eof) { freeml(*ml); mem_free(*menu); return -1; } return 0;}struct html_element *init_html_parser_state(enum html_element_type type, int align, int margin, int width){ struct html_element *element; html_stack_dup(type); element = &html_top; par_format.align = align; if (type <= ELEMENT_IMMORTAL) { par_format.leftmargin = margin; par_format.rightmargin = margin; par_format.width = width; par_format.list_level = 0; par_format.list_number = 0; par_format.dd_margin = 0; html_top.namelen = 0; } return element;}voiddone_html_parser_state(struct html_element *element){ html_context.line_breax = 1; while (&html_top != element) { kill_html_stack_item(&html_top);#if 0 /* I've preserved this bit to show an example of the Old Code * of the Mikulas days (I _HOPE_ it's by Mikulas, at least ;-). * I think this assert() can never fail, for one. --pasky */ assertm(&html_top && (void *) &html_top != (void *) &html_stack, "html stack trashed"); if_assert_failed break;#endif } html_top.type = ELEMENT_KILLABLE; kill_html_stack_item(&html_top);}voidinit_html_parser(struct uri *uri, struct document_options *options, unsigned char *start, unsigned char *end, struct string *head, struct string *title, void (*put_chars)(struct part *, unsigned char *, int), void (*line_break)(struct part *), void *(*special)(struct part *, enum html_special_type, ...)){ struct html_element *e; assert(uri && options); if_assert_failed return; init_list(html_context.stack); html_context.startf = start; html_context.put_chars_f = put_chars; html_context.line_break_f = line_break; html_context.special_f = special; html_context.base_href = get_uri_reference(uri); html_context.base_target = null_or_stracpy(options->framename); scan_http_equiv(start, end, head, title); e = mem_calloc(1, sizeof(*e)); if (!e) return; add_to_list(html_context.stack, e); format.style.attr = 0; format.fontsize = 3; format.link = format.target = format.image = NULL; format.onclick = format.ondblclick = format.onmouseover = format.onhover = format.onfocus = format.onmouseout = format.onblur = NULL; format.select = NULL; format.form = NULL; format.title = NULL; format.style.fg = options->default_fg; format.style.bg = options->default_bg; format.clink = options->default_link; format.vlink = options->default_vlink;#ifdef CONFIG_BOOKMARKS format.bookmark_link = options->default_bookmark_link;#endif format.image_link = options->default_image_link; par_format.align = ALIGN_LEFT; par_format.leftmargin = options->margin; par_format.rightmargin = options->margin; par_format.width = options->box.width; par_format.list_level = par_format.list_number = 0; par_format.dd_margin = options->margin; par_format.flags = P_NONE; par_format.bgcolor = options->default_bg; html_top.invisible = 0; html_top.name = NULL; html_top.namelen = 0; html_top.options = NULL; html_top.linebreak = 1; html_top.type = ELEMENT_DONT_KILL; html_context.has_link_lines = 0; html_context.table_level = 0;#ifdef CONFIG_CSS if (global_doc_opts->css_enable) mirror_css_stylesheet(&default_stylesheet, &html_context.css_styles);#endif}voiddone_html_parser(void){#ifdef CONFIG_CSS if (global_doc_opts->css_enable) done_css_stylesheet(&html_context.css_styles);#endif mem_free(html_context.base_target); done_uri(html_context.base_href); kill_html_stack_item(html_context.stack.next); assertm(list_empty(html_context.stack), "html stack not empty after operation"); if_assert_failed init_list(html_context.stack);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -