/**
* $Id: html.c,v 1.15 2003/04/15 17:53:00 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);
free(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