From 0c0ff3c59631d0968c888279195ea40d4a7fd824 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Tue, 17 Jun 2003 19:24:21 +0000 Subject: [project @ 2003-06-17 19:24:20 by bursa] Change fetchcache system to store loading contents in cache. svn path=/import/netsurf/; revision=180 --- content/content.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 148 insertions(+), 26 deletions(-) (limited to 'content/content.c') diff --git a/content/content.c b/content/content.c index 0538d52c3..65e730ee5 100644 --- a/content/content.c +++ b/content/content.c @@ -1,17 +1,19 @@ /** - * $Id: content.c,v 1.10 2003/06/05 13:17:55 philpem Exp $ + * $Id: content.c,v 1.11 2003/06/17 19:24:20 bursa Exp $ */ #include #include #include #include "netsurf/content/content.h" +#include "netsurf/content/other.h" #include "netsurf/css/css.h" #include "netsurf/render/html.h" #include "netsurf/render/textplain.h" #include "netsurf/riscos/jpeg.h" #include "netsurf/riscos/png.h" #include "netsurf/riscos/gif.h" +#include "netsurf/utils/log.h" #include "netsurf/utils/utils.h" @@ -21,9 +23,11 @@ struct mime_entry { content_type type; }; static const struct mime_entry mime_map[] = { +#ifdef riscos {"image/gif", CONTENT_GIF}, {"image/jpeg", CONTENT_JPEG}, {"image/png", CONTENT_PNG}, +#endif {"text/css", CONTENT_CSS}, {"text/html", CONTENT_HTML}, {"text/plain", CONTENT_TEXTPLAIN}, @@ -46,14 +50,21 @@ static const struct handler_entry handler_map[] = { html_reformat, html_destroy, 0}, {textplain_create, textplain_process_data, textplain_convert, textplain_revive, textplain_reformat, textplain_destroy, 0}, +#ifdef riscos {jpeg_create, jpeg_process_data, jpeg_convert, jpeg_revive, jpeg_reformat, jpeg_destroy, jpeg_redraw}, +#endif {css_create, css_process_data, css_convert, css_revive, css_reformat, css_destroy, 0}, +#ifdef riscos {nspng_create, nspng_process_data, nspng_convert, nspng_revive, nspng_reformat, nspng_destroy, nspng_redraw}, {nsgif_create, nsgif_process_data, nsgif_convert, nsgif_revive, - nsgif_reformat, nsgif_destroy, nsgif_redraw} + nsgif_reformat, nsgif_destroy, nsgif_redraw}, +#endif + {other_create, other_process_data, other_convert, other_revive, + other_reformat, other_destroy, 0} }; +#define HANDLER_MAP_COUNT (sizeof(handler_map) / sizeof(handler_map[0])) /** @@ -72,25 +83,46 @@ content_type content_lookup(const char *mime_type) /** - * content_create -- create a content structure of the specified mime type + * content_create -- create a content structure */ -struct content * content_create(content_type type, char *url) +struct content * content_create(char *url) { struct content *c; - assert(type < CONTENT_OTHER); + struct content_user *user_sentinel; + LOG(("url %s", url)); c = xcalloc(1, sizeof(struct content)); c->url = xstrdup(url); - c->type = type; - c->status = CONTENT_LOADING; + c->type = CONTENT_UNKNOWN; + c->status = CONTENT_STATUS_TYPE_UNKNOWN; c->size = sizeof(struct content); - c->status_callback = 0; + c->fetch = 0; strcpy(c->status_message, "Loading"); - handler_map[type].create(c); + user_sentinel = xcalloc(1, sizeof(*user_sentinel)); + user_sentinel->callback = 0; + user_sentinel->p1 = user_sentinel->p2 = 0; + user_sentinel->next = 0; + c->user_list = user_sentinel; return c; } +/** + * content_set_type -- initialise the content for the specified mime type + */ + +void content_set_type(struct content *c, content_type type) +{ + assert(c->status == CONTENT_STATUS_TYPE_UNKNOWN); + assert(type < CONTENT_UNKNOWN); + LOG(("content %s, type %i", c->url, type)); + c->type = type; + c->status = CONTENT_STATUS_LOADING; + content_broadcast(c, CONTENT_MSG_LOADING, 0); + handler_map[type].create(c); +} + + /** * content_process_data -- process a block source data */ @@ -98,8 +130,8 @@ struct content * content_create(content_type type, char *url) void content_process_data(struct content *c, char *data, unsigned long size) { assert(c != 0); - assert(c->type < CONTENT_OTHER); - assert(c->status == CONTENT_LOADING); + assert(c->status == CONTENT_STATUS_LOADING); + LOG(("content %s, size %lu", c->url, size)); handler_map[c->type].process_data(c, data, size); } @@ -108,17 +140,25 @@ void content_process_data(struct content *c, char *data, unsigned long size) * content_convert -- all data has arrived, complete the conversion */ -int content_convert(struct content *c, unsigned long width, unsigned long height) +void content_convert(struct content *c, unsigned long width, unsigned long height) { assert(c != 0); - assert(c->type < CONTENT_OTHER); - assert(c->status == CONTENT_LOADING); + assert(c->type < HANDLER_MAP_COUNT); + assert(c->status == CONTENT_STATUS_LOADING); + LOG(("content %s", c->url)); c->available_width = width; - if (handler_map[c->type].convert(c, width, height)) - return 1; - if (c->status == CONTENT_LOADING) - c->status = CONTENT_DONE; - return 0; + if (handler_map[c->type].convert(c, width, height)) { + /* convert failed, destroy content */ + content_broadcast(c, CONTENT_MSG_ERROR, "Conversion failed"); + content_destroy(c); + return; + } + assert(c->status == CONTENT_STATUS_READY || + c->status == CONTENT_STATUS_DONE); + if (c->status == CONTENT_STATUS_READY) + content_broadcast(c, CONTENT_MSG_READY, 0); + else + content_broadcast(c, CONTENT_MSG_DONE, 0); } @@ -130,8 +170,7 @@ int content_convert(struct content *c, unsigned long width, unsigned long height void content_revive(struct content *c, unsigned long width, unsigned long height) { assert(c != 0); - assert(c->type < CONTENT_OTHER); - if (c->status != CONTENT_DONE) + if (c->status != CONTENT_STATUS_DONE) return; c->available_width = width; handler_map[c->type].revive(c, width, height); @@ -145,8 +184,8 @@ void content_revive(struct content *c, unsigned long width, unsigned long height void content_reformat(struct content *c, unsigned long width, unsigned long height) { assert(c != 0); - assert(c->type < CONTENT_OTHER); - assert(c->status != CONTENT_LOADING); + assert(c->status == CONTENT_STATUS_READY || + c->status == CONTENT_STATUS_DONE); c->available_width = width; handler_map[c->type].reformat(c, width, height); } @@ -158,9 +197,15 @@ void content_reformat(struct content *c, unsigned long width, unsigned long heig void content_destroy(struct content *c) { + struct content_user *user, *next; assert(c != 0); - assert(c->type < CONTENT_OTHER); - handler_map[c->type].destroy(c); + LOG(("content %p %s", c, c->url)); + if (c->type < HANDLER_MAP_COUNT) + handler_map[c->type].destroy(c); + for (user = c->user_list; user != 0; user = next) { + next = user->next; + xfree(user); + } xfree(c); } @@ -173,8 +218,85 @@ void content_redraw(struct content *c, long x, long y, unsigned long width, unsigned long height) { assert(c != 0); - assert(c->type < CONTENT_OTHER); if (handler_map[c->type].redraw != 0) handler_map[c->type].redraw(c, x, y, width, height); } + +/** + * content_add_user -- register a user for callbacks + */ + +void content_add_user(struct content *c, + void (*callback)(content_msg msg, struct content *c, void *p1, + void *p2, const char *error), + void *p1, void *p2) +{ + struct content_user *user; + LOG(("content %s, user %p %p %p", c->url, callback, p1, p2)); + user = xcalloc(1, sizeof(*user)); + user->callback = callback; + user->p1 = p1; + user->p2 = p2; + user->next = c->user_list->next; + c->user_list->next = user; +} + + +/** + * content_remove_user -- remove a callback user + */ + +void content_remove_user(struct content *c, + void (*callback)(content_msg msg, struct content *c, void *p1, + void *p2, const char *error), + void *p1, void *p2) +{ + struct content_user *user, *next; + LOG(("content %s, user %p %p %p", c->url, callback, p1, p2)); + + /* user_list starts with a sentinel */ + for (user = c->user_list; user->next != 0 && + !(user->next->callback == callback && + user->next->p1 == p1 && + user->next->p2 == p2); user = user->next) + ; + if (user->next == 0) { + LOG(("user not found in list")); + assert(0); + return; + } + next = user->next; + user->next = next->next; + xfree(next); + + /* if there are now no users, stop any loading in progress + * and destroy content structure if not in state READY or DONE */ + if (c->user_list->next == 0) { + LOG(("no users for %p %s", c, c->url)); + if (c->fetch != 0) + fetch_abort(c->fetch); + if (c->status < CONTENT_STATUS_READY) { + cache_destroy(c); + content_destroy(c); + } else + cache_freeable(c); + } +} + + +/** + * content_broadcast -- send a message to all users + */ + +void content_broadcast(struct content *c, content_msg msg, char *error) +{ + struct content_user *user, *next; + LOG(("content %s, message %i", c->url, msg)); + for (user = c->user_list->next; user != 0; user = next) { + next = user->next; /* user may be destroyed during callback */ + if (user->callback != 0) + user->callback(msg, c, user->p1, user->p2, error); + } +} + -- cgit v1.2.3