/** * $Id: html.c,v 1.17 2003/05/10 11:13:34 bursa Exp $ */ #include #include #include #include #include "netsurf/content/fetch.h" #include "netsurf/content/fetchcache.h" #include "netsurf/desktop/gui.h" #include "netsurf/render/html.h" #include "netsurf/render/layout.h" #include "netsurf/utils/utils.h" #include "netsurf/utils/log.h" struct fetch_data { struct content *c; unsigned int i; }; static void html_convert_css_callback(fetchcache_msg msg, struct content *css, void *p, const char *error); static void html_title(struct content *c, xmlNode *head); static void html_find_stylesheets(struct content *c, xmlNode *head); static void html_image_callback(fetchcache_msg msg, struct content *image, void *p, const char *error); void html_create(struct content *c) { c->data.html.parser = htmlCreatePushParserCtxt(0, 0, "", 0, 0, XML_CHAR_ENCODING_8859_1); c->data.html.layout = NULL; c->data.html.style = NULL; c->data.html.fonts = NULL; } #define CHUNK 4096 void html_process_data(struct content *c, char *data, unsigned long size) { unsigned long x; for (x = 0; x + CHUNK <= size; x += CHUNK) { htmlParseChunk(c->data.html.parser, data + x, CHUNK, 0); gui_multitask(); } htmlParseChunk(c->data.html.parser, data + x, (int) (size - x), 0); } int html_convert(struct content *c, unsigned int width, unsigned int height) { unsigned int i; xmlDoc *document; xmlNode *html, *head; /* finish parsing */ htmlParseChunk(c->data.html.parser, "", 0, 1); document = c->data.html.parser->myDoc; /*xmlDebugDumpDocument(stderr, c->data.html.parser->myDoc);*/ htmlFreeParserCtxt(c->data.html.parser); if (document == NULL) { LOG(("Parsing failed")); return 1; } /* locate html and head elements */ for (html = document->children; html != 0 && html->type != XML_ELEMENT_NODE; html = html->next) ; if (html == 0 || strcmp((const char *) html->name, "html") != 0) { LOG(("html element not found")); xmlFreeDoc(document); return 1; } for (head = html->children; head != 0 && head->type != XML_ELEMENT_NODE; head = head->next) ; if (strcmp((const char *) head->name, "head") != 0) { head = 0; LOG(("head element not found")); } if (head != 0) html_title(c, head); /* get stylesheets */ html_find_stylesheets(c, head); /* convert xml tree to box tree */ LOG(("XML to box")); xml_to_box(html, c); /*box_dump(c->data.html.layout->children, 0);*/ /* XML tree and stylesheets not required past this point */ xmlFreeDoc(document); cache_free(c->data.html.stylesheet_content[0]); if (c->data.html.stylesheet_content[1] != 0) content_destroy(c->data.html.stylesheet_content[1]); for (i = 2; i != c->data.html.stylesheet_count; i++) if (c->data.html.stylesheet_content[i] != 0) cache_free(c->data.html.stylesheet_content[i]); xfree(c->data.html.stylesheet_content); /* layout the box tree */ c->status_callback(c->status_p, "Formatting document"); LOG(("Layout document")); layout_document(c->data.html.layout->children, width); /*box_dump(c->data.html.layout->children, 0);*/ c->width = c->data.html.layout->children->width; c->height = c->data.html.layout->children->height; if (c->active != 0) c->status = CONTENT_PENDING; return 0; } void html_convert_css_callback(fetchcache_msg msg, struct content *css, void *p, const char *error) { struct fetch_data *data = p; struct content *c = data->c; unsigned int i = data->i; switch (msg) { case FETCHCACHE_OK: free(data); LOG(("got stylesheet '%s'", css->url)); c->data.html.stylesheet_content[i] = css; /*css_dump_stylesheet(css->data.css);*/ c->active--; break; case FETCHCACHE_BADTYPE: case FETCHCACHE_ERROR: free(data); c->data.html.stylesheet_content[i] = 0; c->active--; c->error = 1; break; case FETCHCACHE_STATUS: /* TODO: need to add a way of sending status to the * owning window */ break; default: assert(0); } } void html_title(struct content *c, xmlNode *head) { xmlNode *node; xmlChar *title; c->title = 0; for (node = head->children; node != 0; node = node->next) { if (strcmp(node->name, "title") == 0) { title = xmlNodeGetContent(node); c->title = squash_tolat1(title); xmlFree(title); return; } } } void html_find_stylesheets(struct content *c, xmlNode *head) { xmlNode *node, *node2; char *rel, *type, *media, *href, *data, *url; char status[80]; unsigned int i = 2; struct fetch_data *fetch_data; /* stylesheet 0 is the base style sheet, stylesheet 1 is any