diff options
Diffstat (limited to 'render/html.c')
-rw-r--r-- | render/html.c | 271 |
1 files changed, 153 insertions, 118 deletions
diff --git a/render/html.c b/render/html.c index 304de133c..ab6b55560 100644 --- a/render/html.c +++ b/render/html.c @@ -1,32 +1,29 @@ /** - * $Id: html.c,v 1.18 2003/06/05 13:17:55 philpem Exp $ + * $Id: html.c,v 1.19 2003/06/17 19:24:21 bursa Exp $ */ #include <assert.h> #include <string.h> #include <strings.h> #include <stdlib.h> +#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" -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_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_image_callback(fetchcache_msg msg, struct content *image, - void *p, const char *error); +static void html_object_callback(content_msg msg, struct content *object, + void *p1, void *p2, const char *error); void html_create(struct content *c) @@ -43,6 +40,8 @@ void html_create(struct content *c) 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(); @@ -100,16 +99,19 @@ int html_convert(struct content *c, unsigned int width, unsigned int height) /* XML tree and stylesheets not required past this point */ xmlFreeDoc(document); - cache_free(c->data.html.stylesheet_content[0]); + 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) - cache_free(c->data.html.stylesheet_content[i]); + 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 */ - c->status_callback(c->status_p, "Formatting document"); + 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);*/ @@ -117,38 +119,53 @@ int html_convert(struct content *c, unsigned int width, unsigned int height) c->width = c->data.html.layout->children->width; c->height = c->data.html.layout->children->height; - if (c->active != 0) - c->status = CONTENT_PENDING; + if (c->active == 0) + c->status = CONTENT_STATUS_DONE; + else + c->status = CONTENT_STATUS_READY; return 0; } -void html_convert_css_callback(fetchcache_msg msg, struct content *css, - void *p, const char *error) +void html_convert_css_callback(content_msg msg, struct content *css, + void *p1, void *p2, const char *error) { - struct fetch_data *data = p; - struct content *c = data->c; - unsigned int i = data->i; + struct content *c = p1; + unsigned int i = (unsigned int) p2; switch (msg) { - case FETCHCACHE_OK: - free(data); + 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->data.html.stylesheet_content[i] = css; - /*css_dump_stylesheet(css->data.css);*/ c->active--; break; - case FETCHCACHE_BADTYPE: - case FETCHCACHE_ERROR: - free(data); + + case CONTENT_MSG_ERROR: 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 */ + + 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); } @@ -177,9 +194,8 @@ 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; + unsigned int last_active = 0; /* stylesheet 0 is the base style sheet, stylesheet 1 is any <style> elements */ c->data.html.stylesheet_content = xcalloc(2, sizeof(*c->data.html.stylesheet_content)); @@ -189,13 +205,17 @@ void html_find_stylesheets(struct content *c, xmlNode *head) c->error = 0; c->active = 0; - fetch_data = xcalloc(1, sizeof(*fetch_data)); - fetch_data->c = c; - fetch_data->i = 0; - c->active++; - fetchcache("file:///%3CNetSurf$Dir%3E/Resources/CSS", c->url, + c->data.html.stylesheet_content[0] = fetchcache( +#ifdef riscos + "file:///%3CNetSurf$Dir%3E/Resources/CSS", +#else + "file:///home/james/Projects/netsurf/CSS", +#endif + c->url, html_convert_css_callback, - fetch_data, c->width, c->height, 1 << CONTENT_CSS); + c, 0, c->width, c->height); + if (c->data.html.stylesheet_content[0]->status != CONTENT_STATUS_DONE) + c->active++; for (node = head == 0 ? 0 : head->children; node != 0; node = node->next) { if (strcmp(node->name, "link") == 0) { @@ -238,24 +258,23 @@ void html_find_stylesheets(struct content *c, xmlNode *head) /* start fetch */ c->data.html.stylesheet_content = xrealloc(c->data.html.stylesheet_content, (i + 1) * sizeof(*c->data.html.stylesheet_content)); - fetch_data = xcalloc(1, sizeof(*fetch_data)); - fetch_data->c = c; - fetch_data->i = i; - c->active++; - fetchcache(url, c->url, html_convert_css_callback, - fetch_data, c->width, c->height, 1 << CONTENT_CSS); + c->data.html.stylesheet_content[i] = fetchcache(url, c->url, + html_convert_css_callback, c, i, + c->width, c->height); + if (c->data.html.stylesheet_content[i]->status != CONTENT_STATUS_DONE) + c->active++; free(url); i++; } else if (strcmp(node->name, "style") == 0) { - /* type='text/css' */ - if (!(type = (char *) xmlGetProp(node, (const xmlChar *) "type"))) - continue; - if (strcmp(type, "text/css") != 0) { + /* type='text/css', or not present (invalid but common) */ + if ((type = (char *) xmlGetProp(node, (const xmlChar *) "type"))) { + if (strcmp(type, "text/css") != 0) { + xmlFree(type); + continue; + } xmlFree(type); - continue; } - xmlFree(type); /* media contains 'screen' or 'all' or not present */ if ((media = (char *) xmlGetProp(node, (const xmlChar *) "media"))) { @@ -269,8 +288,10 @@ void html_find_stylesheets(struct content *c, xmlNode *head) /* create stylesheet */ LOG(("style element")); - if (c->data.html.stylesheet_content[1] == 0) - c->data.html.stylesheet_content[1] = content_create(CONTENT_CSS, c->url); + if (c->data.html.stylesheet_content[1] == 0) { + c->data.html.stylesheet_content[1] = content_create(c->url); + content_set_type(c->data.html.stylesheet_content[1], CONTENT_CSS); + } /* can't just use xmlNodeGetContent(node), because that won't give * the content of comments which may be used to 'hide' the content */ @@ -290,71 +311,80 @@ void html_find_stylesheets(struct content *c, xmlNode *head) /* complete the fetches */ while (c->active != 0) { - if (c->status_callback != 0) { - sprintf(status, "Loading %u stylesheets", c->active); - c->status_callback(c->status_p, status); + if (c->active != last_active) { + sprintf(c->status_message, "Loading %u stylesheets", c->active); + content_broadcast(c, CONTENT_MSG_STATUS, 0); + last_active = c->active; } fetch_poll(); gui_multitask(); } if (c->error) { - c->status_callback(c->status_p, "Warning: some stylesheets failed to load"); + sprintf(c->status_message, "Warning: some stylesheets failed to load"); + content_broadcast(c, CONTENT_MSG_STATUS, 0); } } -void html_fetch_image(struct content *c, char *url, struct box *box) +void html_fetch_object(struct content *c, char *url, struct box *box) { struct fetch_data *fetch_data; + unsigned int i = c->data.html.object_count; /* add to object list */ c->data.html.object = xrealloc(c->data.html.object, - (c->data.html.object_count + 1) * - sizeof(*c->data.html.object)); - c->data.html.object[c->data.html.object_count].url = url; - c->data.html.object[c->data.html.object_count].content = 0; - c->data.html.object[c->data.html.object_count].box = box; + (i + 1) * sizeof(*c->data.html.object)); + c->data.html.object[i].url = url; + c->data.html.object[i].box = box; /* start fetch */ - fetch_data = xcalloc(1, sizeof(*fetch_data)); - fetch_data->c = c; - fetch_data->i = c->data.html.object_count; + c->data.html.object[i].content = fetchcache(url, c->url, + html_object_callback, + c, i, 0, 0); + if (c->data.html.object[i].content->status != CONTENT_STATUS_DONE) + c->active++; c->data.html.object_count++; - c->active++; - fetchcache(url, c->url, - html_image_callback, - fetch_data, 0, 0, - (1 << CONTENT_JPEG) | (1 << CONTENT_PNG) | - (1 << CONTENT_GIF)); } -void html_image_callback(fetchcache_msg msg, struct content *image, - void *p, const char *error) +void html_object_callback(content_msg msg, struct content *object, + void *p1, void *p2, const char *error) { - struct fetch_data *data = p; - struct content *c = data->c; - unsigned int i = data->i; + struct content *c = p1; + unsigned int i = (unsigned int) p2; struct box *box = c->data.html.object[i].box; switch (msg) { - case FETCHCACHE_OK: - LOG(("got image '%s'", image->url)); - box->object = image; - c->data.html.object[i].content = image; + case CONTENT_MSG_LOADING: + if (CONTENT_OTHER <= c->type) { + c->data.html.object[i].content = 0; + c->active--; + c->error = 1; + sprintf(c->status_message, "Warning: bad object type"); + content_broadcast(c, CONTENT_MSG_STATUS, 0); + content_remove_user(object, html_object_callback, c, i); + } + break; + + case CONTENT_MSG_READY: + break; + + case CONTENT_MSG_DONE: + LOG(("got object '%s'", object->url)); + box->object = object; /* set dimensions to object dimensions if auto */ if (box->style->width.width == CSS_WIDTH_AUTO) { box->style->width.width = CSS_WIDTH_LENGTH; box->style->width.value.length.unit = CSS_UNIT_PX; - box->style->width.value.length.value = image->width; - box->min_width = box->max_width = box->width = image->width; + box->style->width.value.length.value = object->width; + box->min_width = box->max_width = box->width = object->width; /* invalidate parent min, max widths */ if (box->parent->max_width != UNKNOWN_MAX_WIDTH) { struct box *b = box->parent; - if (b->min_width < image->width) - b->min_width = image->width; - if (b->max_width < image->width) - b->max_width = image->width; + if (b->min_width < object->width) + b->min_width = object->width; + if (b->max_width < object->width) + b->max_width = object->width; for (b = b->parent; b != 0 && b->max_width != UNKNOWN_MAX_WIDTH; b = b->parent) @@ -364,7 +394,7 @@ void html_image_callback(fetchcache_msg msg, struct content *image, if (box->style->height.height == CSS_HEIGHT_AUTO) { box->style->height.height = CSS_HEIGHT_LENGTH; box->style->height.length.unit = CSS_UNIT_PX; - box->style->height.length.value = image->height; + box->style->height.length.value = object->height; } /* remove alt text */ if (box->text != 0) { @@ -377,49 +407,53 @@ void html_image_callback(fetchcache_msg msg, struct content *image, box->children = 0; }*/ /* TODO: recalculate min, max width */ - /* drop through */ - case FETCHCACHE_BADTYPE: - case FETCHCACHE_ERROR: - if (c->active == 1 && c->status == CONTENT_PENDING) { - /* all images have arrived */ - content_reformat(c, c->available_width, 0); - /*box_dump(c->data.html.layout->children, 0);*/ - } c->active--; - if (c->active == 0) - sprintf(c->status_message, "Document done"); - else - sprintf(c->status_message, "Loading %i images", c->active); - free(data); break; - case FETCHCACHE_STATUS: - /* TODO: need to add a way of sending status to the - * owning window */ + + case CONTENT_MSG_ERROR: + c->data.html.object[i].content = 0; + c->active--; + c->error = 1; + sprintf(c->status_message, "Image error: %s", error); + content_broadcast(c, CONTENT_MSG_STATUS, 0); + break; + + case CONTENT_MSG_STATUS: + sprintf(c->status_message, "Loading %i objects: %s", + c->active, object->status_message); break; + default: assert(0); } + + LOG(("%i active", c->active)); + if (c->active == 0) { + /* all objects have arrived */ + content_reformat(c, c->available_width, 0); + c->status = CONTENT_STATUS_DONE; + content_broadcast(c, CONTENT_MSG_DONE, 0); + } + if (c->active == 0) + sprintf(c->status_message, "Document done"); + else + sprintf(c->status_message, "Loading %i objects", c->active); } void html_revive(struct content *c, unsigned int width, unsigned int height) { unsigned int i; - struct fetch_data *fetch_data; - /* reload images and fix pointers */ + /* reload objects and fix pointers */ for (i = 0; i != c->data.html.object_count; i++) { if (c->data.html.object[i].content != 0) { - fetch_data = xcalloc(1, sizeof(*fetch_data)); - fetch_data->c = c; - fetch_data->i = i; - c->active++; - fetchcache(c->data.html.object[i].url, c->url, - html_image_callback, - fetch_data, 0, 0, - (1 << CONTENT_JPEG) | - (1 << CONTENT_PNG) | - (1 << CONTENT_GIF)); + c->data.html.object[i].content = fetchcache( + c->data.html.object[i].url, c->url, + html_object_callback, + c, i, 0, 0); + if (c->data.html.object[i].content->status != CONTENT_STATUS_DONE) + c->active++; } } @@ -428,7 +462,7 @@ void html_revive(struct content *c, unsigned int width, unsigned int height) c->height = c->data.html.layout->children->height; if (c->active != 0) - c->status = CONTENT_PENDING; + c->status = CONTENT_STATUS_READY; } @@ -458,7 +492,8 @@ void html_destroy(struct content *c) for (i = 0; i != c->data.html.object_count; i++) { LOG(("object %i %p", i, c->data.html.object[i].content)); if (c->data.html.object[i].content != 0) - cache_free(c->data.html.object[i].content); + content_remove_user(c->data.html.object[i].content, + html_object_callback, c, i); free(c->data.html.object[i].url); } free(c->data.html.object); |