/* * This file is part of NetSurf, http://netsurf.sourceforge.net/ * Licensed under the GNU General Public License, * http://www.opensource.org/licenses/gpl-license * Copyright 2003 James Bursa */ #include #include #include #include #include "netsurf/content/content.h" #include "netsurf/content/fetch.h" #include "netsurf/content/fetchcache.h" #ifdef riscos #include "netsurf/desktop/gui.h" #endif #include "netsurf/render/html.h" #include "netsurf/render/layout.h" #include "netsurf/utils/utils.h" #include "netsurf/utils/log.h" static void html_convert_css_callback(content_msg msg, struct content *css, void *p1, void *p2, 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_object_callback(content_msg msg, struct content *object, void *p1, void *p2, 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; c->data.html.length = 0; c->data.html.source = xcalloc(0, 1); c->data.html.background_colour = TRANSPARENT; } #define CHUNK 4096 void html_process_data(struct content *c, char *data, unsigned long size) { unsigned long x; LOG(("content %s, size %lu", c->url, size)); cache_dump(); c->data.html.source = xrealloc(c->data.html.source, c->data.html.length + size); memcpy(c->data.html.source + c->data.html.length, data, size); c->data.html.length += size; c->size += size; 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")); sprintf(c->status_message, "Processing document"); content_broadcast(c, CONTENT_MSG_STATUS, 0); xml_to_box(html, c); /*box_dump(c->data.html.layout->children, 0);*/ /* XML tree and stylesheets not required past this point */ xmlFreeDoc(document); content_remove_user(c->data.html.stylesheet_content[0], html_convert_css_callback, c, 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) content_remove_user(c->data.html.stylesheet_content[i], html_convert_css_callback, c, i); xfree(c->data.html.stylesheet_content); /* layout the box tree */ sprintf(c->status_message, "Formatting document"); content_broadcast(c, CONTENT_MSG_STATUS, 0); 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_STATUS_DONE; else c->status = CONTENT_STATUS_READY; return 0; } void html_convert_css_callback(content_msg msg, struct content *css, void *p1, void *p2, const char *error) { struct content *c = p1; unsigned int i = (unsigned int) p2; switch (msg) { case CONTENT_MSG_LOADING: /* check that the stylesheet is really CSS */ if (css->type != CONTENT_CSS) { c->data.html.stylesheet_content[i] = 0; c->active--; c->error = 1; sprintf(c->status_message, "Warning: stylesheet is not CSS"); content_broadcast(c, CONTENT_MSG_STATUS, 0); content_remove_user(css, html_convert_css_callback, c, i); } break; case CONTENT_MSG_READY: break; case CONTENT_MSG_DONE: LOG(("got stylesheet '%s'", css->url)); c->active--; break; case CONTENT_MSG_ERROR: c->data.html.stylesheet_content[i] = 0; c->active--; c->error = 1; break; case CONTENT_MSG_STATUS: snprintf(c->status_message, 80, "Loading %u stylesheets: %s", c->active, css->status_message); content_broadcast(c, CONTENT_MSG_STATUS, 0); break; case CONTENT_MSG_REDIRECT: c->active--; c->data.html.stylesheet_content[i] = fetchcache( error, c->url, html_convert_css_callback, c, i, css->width, css->height, true); if (c->data.html.stylesheet_content[i] != 0 && c->data.html.stylesheet_content[i]->status != CONTENT_STATUS_DONE) c->active++; 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; unsigned int i = 2; unsigned int last_active = 0; /* stylesheet 0 is the base style sheet, stylesheet 1 is any