/**
* $Id: html.c,v 1.19 2003/06/17 19:24:21 bursa Exp $
*/
#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;
}
#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();
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);
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:
sprintf(c->status_message, "Loading %u stylesheets: %s",
c->active, css->status_message);
content_broadcast(c, CONTENT_MSG_STATUS, 0);
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