htmlparser.c
来自「微型浏览器」· C语言 代码 · 共 1,021 行 · 第 1/2 页
C
1,021 行
free_html_tag_args(args); return ret ? "" : html;}/* * parse_dtd() */__inline const char *parse_dtd(html_t *ht, const char *html){ char *tag; /* char *rest; */ const char *tmp; register int ret = 0; tmp = html; while (*html && !isspace(*html) && *html != '>') ++html; tag = (char *)malloc(sizeof(char) * (html - tmp + 1)); if (!tag) return ""; strncpy(tag, tmp, html - tmp); tag[html - tmp] = 0; if (*html == '>') { ret = process_dtd(ht, tag, NULL); if (*html == '>') ++html; free(tag); return ((ret) ? "" : html); } /* Extract args */ /* Don't use a html_tag_args structure here since * dtd's have their own argument style and need to be * parsed differently */ while (*html && isspace(*html)) html++; tmp = html; while (*html && *html != '>') ++html;/* rest = (char *)malloc(sizeof(char) * (html - tmp + 1)); if (!rest) { free(tag); return ""; } strncpy(rest, tmp, html - tmp); rest[html - tmp] = 0; */ if(*html == '>') ++html; free(tag);/* free(rest); */ return html;}/* * parse_for_entities() */__inline int parse_for_entities(html_t *html, const char *text){ char *buf, *entity, *p; const char *tmp; int code; buf = (char *)malloc(sizeof(char) * strlen(text) + 1); if(!buf) return -1; p = buf; while(*text) { while(*text && *text != '&') *p++ = *text++; if(*text == '&') { tmp = ++text; while(*text && *text != ';') ++text; if(text - tmp) { entity = (char *)malloc(sizeof(char) * (text - tmp + 1)); if(!entity) return -1; strncpy(entity, tmp, text - tmp); entity[text - tmp] = 0; if(*text == ';') { if(*entity == '#') { char *num = &entity[1]; *p++ = atoi(num); } else { code = get_entity(entity); if(code >= 0) *p++ = get_entity(entity); } tmp = 0; ++text; } free(entity); } else { /* No entity, just a '&' and ';' together. * Go figure. */ *p++ = '&'; } } } *p = 0; process_text(html, buf); free(buf); return 0;}/* * create_html_struct() - create an html structure */static void handle_status(CheetahWindow *cw, const char *uri){ status_print(cw, uri);}static void follow_link(CheetahWindow *cw, const char *uri, GdkEventButton *event){ switch(event->button) { case 1: cheetah_load_uri(cw, uri); break; case 2: /* Middle button. Open in new window */ break; case 3: /* Right button. Pop up option menu */ break; }}html_t *create_html_struct(CheetahWindow *cw, const char *source){ html_t *html; DwWidget *widget; DwPage *page; DwStyle style_attrs; DwStyleFont font; if(!cw) return NULL; html = (html_t *)malloc(sizeof(html_t)); if(!html) { error("Out of memory."); return NULL; } html->cw = cw; widget = a_Dw_page_new(); page = DW_PAGE(widget); html->dw = widget; a_Dw_gtk_scrolled_window_set_dw(GTK_DW_SCROLLED_WINDOW(html->cw->docwin), widget); html->stack_max = 16; html->stack_top = 0; html->stack = (tag_info_t *)malloc(sizeof(tag_info_t) * html->stack_max); font.name = "helvetica"; font.size = 18.0; font.bold = FALSE; font.italic = FALSE; a_Dw_style_init_values(&style_attrs, html->cw->window->window); style_attrs.font = a_Dw_style_font_new(&font); style_attrs.color = a_Dw_style_color_new(0, html->cw->window->window); html->stack[0].style = a_Dw_style_new(&style_attrs, html->cw->window->window); a_Dw_widget_set_style(widget, html->stack[0].style); html->basefont = 0; html->script = FALSE; html->css = FALSE; html->preformatted = FALSE; html->formlist = NULL; gtk_signal_connect_object(GTK_OBJECT(page), "link_entered", GTK_SIGNAL_FUNC(handle_status), (gpointer)html->cw); gtk_signal_connect_object(GTK_OBJECT(page), "link_clicked", GTK_SIGNAL_FUNC(follow_link), (gpointer)html->cw); return html;} void free_html_struct(html_t *html){ int i; for(i = 0; i <= html->stack_top; i++) a_Dw_style_unref(html->stack[i].style); form_list_free(html->formlist); free(html->stack); free(html->baseuri); free(html);}/* * html_parse_document() - renders an html document */void html_parse_document(html_t *html, const char *source){ DwPage *page; if(!html || !source) return; page = (DwPage *)html->dw; a_Dw_page_update_begin(page); debug_print("Mmmm...HTML."); while(*source) { /* while(*source && isspace(*source)) ++source; */ if (html->script) { const char *script; char *tmp; script = source; /* Locate </script> */ while (*script) { if (*script == '<') { if (*(script + 2) == 's' || *(script + 2) == 'S') { if (*(script + 7) == 't' || *(script + 7) == 'T') { break; } } } ++script; } tmp = (char *) malloc(sizeof(char) * (script - source + 1)); if(!tmp) { error("Out of memory."); return; } strncpy(tmp, source, script - source); tmp[script - source] = 0; /* Pass tmp to script interpreter */ free(tmp); html->script = FALSE; source = script; } else if(html->css) { const char *style; char *buf; style = source; /* locate the </style> tag */ while(*style) { if(*(style+2) == 's' || *(style+2) == 'S') if(*(style+6) == 'e' || *(style+6) == 'E') break; ++style; } buf = (char *)malloc(sizeof(char) * (style - source + 1)); if(!buf) { error("Out of memory"); return; } strncpy(buf, source, style - source); buf[style - source] = 0; debug_print("Want some CSS? Here you go:"); debug_print("%s", buf); free(buf); html->css = FALSE; source = style; } if (*source == '<') { ++source; switch (*source) { case '!': ++source; source = (*source == '-') ? parse_comment(html, source) : parse_dtd(html, source); break; case '/': source = parse_closing_tag(html, source); break; default: source = parse_opening_tag(html, source); break; } } else source = parse_text(html, source); } a_Dw_page_update_end(page); return;}/* * html_render_document() - Begins the html rendering process */void old_html_render_document(CheetahWindow *cw, uri_t *uri, const char *source){ html_t *html; GuiMessage msg; html = create_html_struct(cw, source); if(!html) { error("Out of memory"); return; } html->baseuri = (char *)malloc(sizeof(char) * strlen(uri->host) + strlen(uri->abs_path) + 8); if(!html->baseuri) return; sprintf(html->baseuri, "%s%s", uri->host, uri->abs_path); html->message = &msg; html_parse_document(html, source); free_html_struct(html);}/* * structure used to pass data from html_render_document to html_do_render */typedef struct { uri_t *uri; CheetahWindow *cw; GuiMessage message; const char *source; int done;} HtmlThread;/* * Child process to actually start the rendering */void *html_do_render(void *p){ HtmlThread *thread; html_t *html; thread = (HtmlThread *)p;#ifdef HAVE_PTHREADS_CANCEL_FLAGS /* FreeBSD compatibility */ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,0); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,0);#endif html = create_html_struct(thread->cw, thread->source); if(!html) { error("Out of memory"); return NULL; } html->baseuri = (char *)malloc(sizeof(char) * strlen(thread->uri->host) + strlen(thread->uri->abs_path) + 8); if(!html->baseuri) return NULL; sprintf(html->baseuri, "%s%s", thread->uri->host, thread->uri->abs_path); html->message = &(thread->message); html_parse_document(html, thread->source); free_html_struct(html); thread->done = 1; pthread_exit(NULL); return NULL;}/* * Create a new thread to render the document */void html_render_document(CheetahWindow *cw, uri_t *uri, const char *source){ HtmlThread thread; pthread_t child; int last_seq = 0; if(!cw || !uri || !source) return; thread.cw = cw; thread.uri = uri; thread.source = source; thread.done = 0; pthread_create(&child, NULL, html_do_render, (void *)(&thread)); while(!thread.done) { if(cw->req_stop) { cw->req_stop = 0; pthread_cancel(child); strcpy(thread.message.text, "Interrupted."); thread.message.seq++; if(http_connection_open()) http_close(); break; } if(thread.message.seq > last_seq) { if(strlen(thread.message.text)) { status_print(cw, "%s", thread.message.text); last_seq = thread.message.seq; if(thread.message.pop == thread.message.seq) create_error_dialog(thread.message.text); } } if (gtk_events_pending()) gtk_main_iteration(); else usleep(50000); } pthread_join(child, NULL); if(thread.message.seq > last_seq) { status_print(cw, "%s", thread.message.text); last_seq = thread.message.seq; if(thread.message.pop == thread.message.seq) create_error_dialog(thread.message.text); } return;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?