mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-11-22 06:21:45 +03:00
[project @ 2003-06-17 19:24:20 by bursa]
Change fetchcache system to store loading contents in cache. svn path=/import/netsurf/; revision=180
This commit is contained in:
parent
ce6dbbb5db
commit
0c0ff3c596
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: cache.c,v 1.3 2003/04/15 17:53:00 bursa Exp $
|
||||
* $Id: cache.c,v 1.4 2003/06/17 19:24:20 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@ -11,7 +11,7 @@
|
||||
#include "netsurf/utils/log.h"
|
||||
|
||||
#ifndef TEST
|
||||
#include "netsurf/desktop/browser.h"
|
||||
#include "netsurf/content/content.h"
|
||||
#else
|
||||
#include <unistd.h>
|
||||
struct content {
|
||||
@ -29,15 +29,14 @@ void content_destroy(struct content *c);
|
||||
|
||||
struct cache_entry {
|
||||
struct content *content;
|
||||
unsigned int use_count;
|
||||
time_t t;
|
||||
struct cache_entry *next, *prev;
|
||||
};
|
||||
|
||||
/* doubly-linked lists using a sentinel */
|
||||
/* TODO: replace with a structure which can be searched faster */
|
||||
static struct cache_entry inuse_list_sentinel = {0, 0, 0, &inuse_list_sentinel, &inuse_list_sentinel};
|
||||
static struct cache_entry unused_list_sentinel = {0, 0, 0, &unused_list_sentinel, &unused_list_sentinel};
|
||||
static struct cache_entry inuse_list_sentinel = {0, 0, &inuse_list_sentinel, &inuse_list_sentinel};
|
||||
static struct cache_entry unused_list_sentinel = {0, 0, &unused_list_sentinel, &unused_list_sentinel};
|
||||
static struct cache_entry *inuse_list = &inuse_list_sentinel;
|
||||
static struct cache_entry *unused_list = &unused_list_sentinel;
|
||||
|
||||
@ -70,23 +69,24 @@ void cache_quit(void)
|
||||
struct content * cache_get(const char * const url)
|
||||
{
|
||||
struct cache_entry *e;
|
||||
LOG(("url %s", url));
|
||||
|
||||
/* search inuse_list first */
|
||||
for (e = inuse_list->next; e != inuse_list && strcmp(e->content->url, url) != 0; e = e->next)
|
||||
;
|
||||
if (e != inuse_list) {
|
||||
LOG(("'%s' in inuse_list, content %p, use_count %u", url, e->content, e->use_count));
|
||||
e->use_count++;
|
||||
LOG(("'%s' in inuse_list, content %p", url, e->content));
|
||||
return e->content;
|
||||
}
|
||||
|
||||
LOG(("not in inuse_list"));
|
||||
|
||||
/* search unused_list if not found */
|
||||
for (e = unused_list->next; e != unused_list && strcmp(e->content->url, url) != 0; e = e->next)
|
||||
;
|
||||
if (e != unused_list) {
|
||||
LOG(("'%s' in unused_list, content %p", url, e->content));
|
||||
/* move to inuse_list */
|
||||
e->use_count = 1;
|
||||
e->prev->next = e->next;
|
||||
e->next->prev = e->prev;
|
||||
e->prev = inuse_list->prev;
|
||||
@ -110,6 +110,7 @@ void cache_put(struct content * content)
|
||||
struct cache_entry * e;
|
||||
LOG(("content %p, url '%s', size %lu", content, content->url, content->size));
|
||||
|
||||
/* TODO: contents will grow in size as they load */
|
||||
current_size += content->size;
|
||||
/* clear old data from the usused_list until the size drops below max_size */
|
||||
while (max_size < current_size && unused_list->next != unused_list) {
|
||||
@ -126,7 +127,6 @@ void cache_put(struct content * content)
|
||||
/* add the new content to the inuse_list */
|
||||
e = xcalloc(1, sizeof(struct cache_entry));
|
||||
e->content = content;
|
||||
e->use_count = 1;
|
||||
e->prev = inuse_list->prev;
|
||||
e->next = inuse_list;
|
||||
inuse_list->prev->next = e;
|
||||
@ -136,41 +136,45 @@ void cache_put(struct content * content)
|
||||
|
||||
|
||||
/**
|
||||
* cache_free -- free a cache object if it is no longer used
|
||||
* cache_freeable -- inform cache that the content has no users
|
||||
*/
|
||||
|
||||
void cache_free(struct content * content)
|
||||
void cache_freeable(struct content * content)
|
||||
{
|
||||
struct cache_entry * e = content->cache;
|
||||
|
||||
assert(e != 0);
|
||||
LOG(("content %p, url '%s', use_count %u", content, content->url, e->use_count));
|
||||
LOG(("content %p, url '%s'", content, content->url));
|
||||
|
||||
assert(e->use_count != 0);
|
||||
e->use_count--;
|
||||
if (e->use_count == 0) {
|
||||
/* move to unused_list or destroy if insufficient space */
|
||||
e->use_count = 0;
|
||||
e->t = time(0);
|
||||
e->prev->next = e->next;
|
||||
e->next->prev = e->prev;
|
||||
if (max_size < current_size) {
|
||||
LOG(("size %lu, removing", current_size));
|
||||
/* TODO: move to disc cache */
|
||||
current_size -= e->content->size;
|
||||
content_destroy(e->content);
|
||||
xfree(e);
|
||||
} else {
|
||||
LOG(("size %lu, moving to unused_list", current_size));
|
||||
e->prev = unused_list->prev;
|
||||
e->next = unused_list;
|
||||
unused_list->prev->next = e;
|
||||
unused_list->prev = e;
|
||||
}
|
||||
/* move to unused_list or destroy if insufficient space */
|
||||
e->t = time(0);
|
||||
e->prev->next = e->next;
|
||||
e->next->prev = e->prev;
|
||||
if (max_size < current_size) {
|
||||
LOG(("size %lu, removing", current_size));
|
||||
/* TODO: move to disc cache */
|
||||
current_size -= e->content->size;
|
||||
content_destroy(e->content);
|
||||
xfree(e);
|
||||
} else {
|
||||
LOG(("size %lu, moving to unused_list", current_size));
|
||||
e->prev = unused_list->prev;
|
||||
e->next = unused_list;
|
||||
unused_list->prev->next = e;
|
||||
unused_list->prev = e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cache_destroy(struct content * content)
|
||||
{
|
||||
struct cache_entry * e = content->cache;
|
||||
e->prev->next = e->next;
|
||||
e->next->prev = e->prev;
|
||||
current_size -= content->size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* cache_dump -- dump contents of cache
|
||||
*/
|
||||
@ -180,10 +184,12 @@ void cache_dump(void) {
|
||||
LOG(("size %lu", current_size));
|
||||
LOG(("inuse_list:"));
|
||||
for (e = inuse_list->next; e != inuse_list; e = e->next)
|
||||
LOG((" content %p, url '%s', use_count %u", e->content, e->content->url, e->use_count));
|
||||
LOG((" content %p, size %lu, url '%s'", e->content,
|
||||
e->content->size, e->content->url));
|
||||
LOG(("unused_list (time now %lu):", time(0)));
|
||||
for (e = unused_list->next; e != unused_list; e = e->next)
|
||||
LOG((" content %p, url '%s', t %lu", e->content, e->content->url, e->t));
|
||||
LOG((" content %p, size %lu, url '%s', t %lu", e->content,
|
||||
e->content->size, e->content->url, e->t));
|
||||
LOG(("end"));
|
||||
}
|
||||
|
||||
|
@ -1,25 +1,28 @@
|
||||
/**
|
||||
* $Id: cache.h,v 1.2 2003/03/04 11:59:35 bursa Exp $
|
||||
* $Id: cache.h,v 1.3 2003/06/17 19:24:20 bursa Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
* Using the cache:
|
||||
* The cache contains a content structure for each url. If a structure is not
|
||||
* in state CONTENT_STATUS_DONE, then loading and converting must be actively
|
||||
* in progress, so that when a not done content is retrieved no action needs
|
||||
* to be taken to load it.
|
||||
*
|
||||
* cache_init();
|
||||
* ...
|
||||
* c = cache_get(url);
|
||||
* if (c == 0) {
|
||||
* ... (create c) ...
|
||||
* cache_put(c);
|
||||
* }
|
||||
* ...
|
||||
* cache_free(c);
|
||||
* ...
|
||||
* cache_quit();
|
||||
* Each content in the cache is either freeable or not freeable. If an entry
|
||||
* is freeable, the cache may destroy it through content_destroy at any time.
|
||||
*
|
||||
* cache_free informs the cache that the content is no longer being used, so
|
||||
* it can be deleted from the cache if necessary. There must be a call to
|
||||
* cache_free for each cache_get or cache_put.
|
||||
* cache_get attempts to retrieve an url from the cache, returning the
|
||||
* content and setting it to not freeable on success, and returning 0 on
|
||||
* failure.
|
||||
*
|
||||
* cache_put adds a content to the cache, setting it to not freeable.
|
||||
*
|
||||
* cache_freeable sets the content to freeable.
|
||||
*
|
||||
* cache_destroy informs the cache that a content is about to be destroyed,
|
||||
* and must be removed from the cache. This should be called when an error
|
||||
* occurs when loading an url and the content is destroyed. The content must
|
||||
* be non freeable.
|
||||
*/
|
||||
|
||||
#ifndef _NETSURF_DESKTOP_CACHE_H_
|
||||
@ -32,7 +35,8 @@ void cache_init(void);
|
||||
void cache_quit(void);
|
||||
struct content * cache_get(const char * const url);
|
||||
void cache_put(struct content * content);
|
||||
void cache_free(struct content * content);
|
||||
void cache_freeable(struct content * content);
|
||||
void cache_destroy(struct content * content);
|
||||
void cache_dump(void);
|
||||
|
||||
#endif
|
||||
|
@ -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 <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,18 +1,23 @@
|
||||
/**
|
||||
* $Id: content.h,v 1.11 2003/06/05 13:17:55 philpem Exp $
|
||||
* $Id: content.h,v 1.12 2003/06/17 19:24:20 bursa Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETSURF_DESKTOP_CONTENT_H_
|
||||
#define _NETSURF_DESKTOP_CONTENT_H_
|
||||
|
||||
#include "libxml/HTMLparser.h"
|
||||
#ifdef riscos
|
||||
#include "libpng/png.h"
|
||||
#include "libungif/gif_lib.h"
|
||||
#include "oslib/osspriteop.h"
|
||||
#endif
|
||||
#include "netsurf/content/cache.h"
|
||||
#include "netsurf/content/fetch.h"
|
||||
#include "netsurf/css/css.h"
|
||||
#include "netsurf/render/box.h"
|
||||
#ifdef riscos
|
||||
#include "netsurf/riscos/font.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
@ -32,11 +37,16 @@
|
||||
typedef enum {
|
||||
CONTENT_HTML,
|
||||
CONTENT_TEXTPLAIN,
|
||||
#ifdef riscos
|
||||
CONTENT_JPEG,
|
||||
#endif
|
||||
CONTENT_CSS,
|
||||
#ifdef riscos
|
||||
CONTENT_PNG,
|
||||
CONTENT_GIF,
|
||||
CONTENT_OTHER
|
||||
#endif
|
||||
CONTENT_OTHER,
|
||||
CONTENT_UNKNOWN /* content-type not received yet */
|
||||
} content_type;
|
||||
|
||||
struct box_position
|
||||
@ -49,16 +59,34 @@ struct box_position
|
||||
int char_offset;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CONTENT_MSG_LOADING, /* fetching or converting */
|
||||
CONTENT_MSG_READY, /* may be displayed */
|
||||
CONTENT_MSG_DONE, /* finished */
|
||||
CONTENT_MSG_ERROR, /* error occurred */
|
||||
CONTENT_MSG_STATUS /* new status string */
|
||||
} content_msg;
|
||||
|
||||
struct content_user
|
||||
{
|
||||
void (*callback)(content_msg msg, struct content *c, void *p1,
|
||||
void *p2, const char *error);
|
||||
void *p1;
|
||||
void *p2;
|
||||
struct content_user *next;
|
||||
};
|
||||
|
||||
struct content
|
||||
{
|
||||
char *url;
|
||||
content_type type;
|
||||
enum {
|
||||
CONTENT_LOADING, /* content is being fetched or converted
|
||||
and is not safe to display */
|
||||
CONTENT_PENDING, /* some parts of content still being
|
||||
loaded, but can be displayed */
|
||||
CONTENT_DONE /* all finished */
|
||||
CONTENT_STATUS_TYPE_UNKNOWN, /* type not yet known */
|
||||
CONTENT_STATUS_LOADING, /* content is being fetched or converted
|
||||
and is not safe to display */
|
||||
CONTENT_STATUS_READY, /* some parts of content still being
|
||||
loaded, but can be displayed */
|
||||
CONTENT_STATUS_DONE /* all finished */
|
||||
} status;
|
||||
unsigned long width, height;
|
||||
unsigned long available_width;
|
||||
@ -95,7 +123,7 @@ struct content
|
||||
char **import_url;
|
||||
struct content **import_content;
|
||||
} css;
|
||||
|
||||
#ifdef riscos
|
||||
struct
|
||||
{
|
||||
char * data;
|
||||
@ -122,6 +150,13 @@ struct content
|
||||
osspriteop_area *sprite_area; // Sprite area
|
||||
char *sprite_image; // Sprite image
|
||||
} gif;
|
||||
#endif
|
||||
/* downloads */
|
||||
struct
|
||||
{
|
||||
char *data;
|
||||
unsigned long length;
|
||||
} other;
|
||||
|
||||
} data;
|
||||
|
||||
@ -130,20 +165,31 @@ struct content
|
||||
char *title;
|
||||
unsigned int active;
|
||||
int error;
|
||||
void (*status_callback)(void *p, const char *status);
|
||||
void *status_p;
|
||||
struct content_user *user_list;
|
||||
char status_message[80];
|
||||
struct fetch *fetch;
|
||||
unsigned long fetch_size;
|
||||
};
|
||||
|
||||
|
||||
content_type content_lookup(const char *mime_type);
|
||||
struct content * content_create(content_type type, char *url);
|
||||
struct content * content_create(char *url);
|
||||
void content_set_type(struct content *c, content_type type);
|
||||
void content_process_data(struct content *c, char *data, unsigned long size);
|
||||
int content_convert(struct content *c, unsigned long width, unsigned long height);
|
||||
void content_convert(struct content *c, unsigned long width, unsigned long height);
|
||||
void content_revive(struct content *c, unsigned long width, unsigned long height);
|
||||
void content_reformat(struct content *c, unsigned long width, unsigned long height);
|
||||
void content_destroy(struct content *c);
|
||||
void content_redraw(struct content *c, long x, long y,
|
||||
unsigned long width, unsigned long height);
|
||||
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);
|
||||
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);
|
||||
void content_broadcast(struct content *c, content_msg msg, char *error);
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: fetch.c,v 1.9 2003/06/02 01:09:50 jmb Exp $
|
||||
* $Id: fetch.c,v 1.10 2003/06/17 19:24:20 bursa Exp $
|
||||
*
|
||||
* This module handles fetching of data from any url.
|
||||
*
|
||||
@ -285,6 +285,7 @@ void fetch_poll(void)
|
||||
CURLMsg * curl_msg;
|
||||
struct fetch *f;
|
||||
void *p;
|
||||
void (*callback)(fetch_msg msg, void *p, char *data, unsigned long size);
|
||||
|
||||
/* do any possible work on the current fetches */
|
||||
do {
|
||||
@ -305,20 +306,21 @@ void fetch_poll(void)
|
||||
|
||||
/* inform the caller that the fetch is done */
|
||||
finished = 0;
|
||||
callback = f->callback;
|
||||
p = f->p;
|
||||
if (curl_msg->data.result == CURLE_OK && f->had_headers)
|
||||
finished = 1;
|
||||
else if (curl_msg->data.result == CURLE_OK)
|
||||
f->callback(FETCH_ERROR, f->p, "No data received", 0);
|
||||
callback(FETCH_ERROR, f->p, "No data received", 0);
|
||||
else if (curl_msg->data.result != CURLE_WRITE_ERROR)
|
||||
f->callback(FETCH_ERROR, f->p, f->error_buffer, 0);
|
||||
callback(FETCH_ERROR, f->p, f->error_buffer, 0);
|
||||
|
||||
/* clean up fetch */
|
||||
fetch_abort(f);
|
||||
|
||||
/* postponed until after abort so that queue fetches are started */
|
||||
if (finished)
|
||||
f->callback(FETCH_FINISHED, p, 0, 0);
|
||||
callback(FETCH_FINISHED, p, 0, 0);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -1,117 +1,52 @@
|
||||
/**
|
||||
* $Id: fetchcache.c,v 1.9 2003/04/25 08:03:15 bursa Exp $
|
||||
* $Id: fetchcache.c,v 1.10 2003/06/17 19:24:20 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "netsurf/content/cache.h"
|
||||
#include "netsurf/content/content.h"
|
||||
#include "netsurf/content/fetchcache.h"
|
||||
#include "netsurf/content/fetch.h"
|
||||
#include "netsurf/utils/log.h"
|
||||
#include "netsurf/utils/utils.h"
|
||||
|
||||
|
||||
struct fetchcache {
|
||||
char *url;
|
||||
void (*callback)(fetchcache_msg msg, struct content *c, void *p, const char *error);
|
||||
void *p;
|
||||
struct fetch *f;
|
||||
struct content *c;
|
||||
unsigned long width, height;
|
||||
unsigned long size;
|
||||
content_type allowed;
|
||||
struct fetchcache *next;
|
||||
struct fetchcache *prev;
|
||||
struct fetchcache *next_request;
|
||||
int active;
|
||||
};
|
||||
|
||||
static struct fetchcache *fetchcache_list = 0;
|
||||
|
||||
static void fetchcache_free(struct fetchcache *fc);
|
||||
static void fetchcache_callback(fetchcache_msg msg, void *p, char *data, unsigned long size);
|
||||
static void status_callback(void *p, const char *status);
|
||||
static void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size);
|
||||
|
||||
|
||||
void fetchcache(const char *url, char *referer,
|
||||
void (*callback)(fetchcache_msg msg, struct content *c, void *p, const char *error),
|
||||
void *p, unsigned long width, unsigned long height, content_type allowed)
|
||||
struct content * fetchcache(const char *url, char *referer,
|
||||
void (*callback)(content_msg msg, struct content *c, void *p1,
|
||||
void *p2, const char *error),
|
||||
void *p1, void *p2, unsigned long width, unsigned long height)
|
||||
{
|
||||
struct content *c;
|
||||
struct fetchcache *fc, *fc_url;
|
||||
|
||||
LOG(("url %s", url));
|
||||
|
||||
c = cache_get(url);
|
||||
if (c != 0) {
|
||||
/* check type is allowed */
|
||||
if ((1 << c->type) & allowed) {
|
||||
callback(FETCHCACHE_STATUS, c, p, "Found in cache");
|
||||
content_revive(c, width, height);
|
||||
callback(FETCHCACHE_OK, c, p, 0);
|
||||
} else {
|
||||
callback(FETCHCACHE_BADTYPE, 0, p, "");
|
||||
cache_free(c);
|
||||
}
|
||||
return;
|
||||
content_add_user(c, callback, p1, p2);
|
||||
return c;
|
||||
}
|
||||
|
||||
callback(FETCHCACHE_STATUS, c, p, "Starting fetch");
|
||||
fc = xcalloc(1, sizeof(struct fetchcache));
|
||||
fc->url = xstrdup(url);
|
||||
fc->callback = callback;
|
||||
fc->p = p;
|
||||
fc->c = 0;
|
||||
fc->width = width;
|
||||
fc->height = height;
|
||||
fc->size = 0;
|
||||
fc->allowed = allowed;
|
||||
fc->next = 0;
|
||||
fc->prev = 0;
|
||||
fc->next_request = 0;
|
||||
fc->active = 1;
|
||||
|
||||
/* check if we're already fetching this url */
|
||||
for (fc_url = fetchcache_list;
|
||||
fc_url != 0 && strcmp(fc_url->url, url) != 0;
|
||||
fc_url = fc_url->next)
|
||||
;
|
||||
if (fc_url != 0) {
|
||||
/* already fetching: add ourselves to list of requestors */
|
||||
LOG(("already fetching"));
|
||||
fc->next_request = fc_url->next_request;
|
||||
fc_url->next_request = fc;
|
||||
|
||||
} else {
|
||||
/* not fetching yet */
|
||||
if (fetchcache_list != 0)
|
||||
fetchcache_list->prev = fc;
|
||||
fc->next = fetchcache_list;
|
||||
fetchcache_list = fc;
|
||||
fc->f = fetch_start(fc->url, referer, fetchcache_callback, fc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void fetchcache_free(struct fetchcache *fc)
|
||||
{
|
||||
free(fc->url);
|
||||
free(fc);
|
||||
if (fc->prev == 0)
|
||||
fetchcache_list = fc->next;
|
||||
else
|
||||
fc->prev->next = fc->next;
|
||||
if (fc->next != 0)
|
||||
fc->next->prev = fc->prev;
|
||||
c = content_create(url);
|
||||
content_add_user(c, callback, p1, p2);
|
||||
cache_put(c);
|
||||
c->fetch_size = 0;
|
||||
c->width = width;
|
||||
c->height = height;
|
||||
c->fetch = fetch_start(url, referer, fetchcache_callback, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size)
|
||||
{
|
||||
struct fetchcache *fc = p, *fc_url;
|
||||
struct content *c = p;
|
||||
content_type type;
|
||||
char *mime_type;
|
||||
char *semic;
|
||||
char status[40];
|
||||
int active = 0;
|
||||
|
||||
switch (msg) {
|
||||
case FETCH_TYPE:
|
||||
@ -119,89 +54,33 @@ void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size)
|
||||
if ((semic = strchr(mime_type, ';')) != 0)
|
||||
*semic = 0; /* remove "; charset=..." */
|
||||
type = content_lookup(mime_type);
|
||||
LOG(("FETCH_TYPE, type %u", type));
|
||||
|
||||
/* check if each request allows this type */
|
||||
for (fc_url = fc; fc_url != 0; fc_url = fc_url->next_request) {
|
||||
if (!fc_url->active)
|
||||
continue;
|
||||
if ((1 << type) & fc_url->allowed) {
|
||||
active++;
|
||||
} else {
|
||||
fc_url->active = 0;
|
||||
fc_url->callback(FETCHCACHE_BADTYPE, 0,
|
||||
fc_url->p, mime_type);
|
||||
}
|
||||
}
|
||||
if (active != 0) {
|
||||
/* someone is still interested */
|
||||
fc->c = content_create(type, fc->url);
|
||||
fc->c->status_callback = status_callback;
|
||||
fc->c->status_p = fc;
|
||||
} else {
|
||||
/* no request allows the type */
|
||||
fetch_abort(fc->f);
|
||||
for (; fc != 0; fc = fc_url) {
|
||||
fc_url = fc->next_request;
|
||||
fetchcache_free(fc);
|
||||
}
|
||||
}
|
||||
|
||||
free(mime_type);
|
||||
LOG(("FETCH_TYPE, type %u", type));
|
||||
content_set_type(c, type);
|
||||
break;
|
||||
|
||||
case FETCH_DATA:
|
||||
LOG(("FETCH_DATA"));
|
||||
assert(fc->c != 0);
|
||||
fc->size += size;
|
||||
sprintf(status, "Received %lu bytes", fc->size);
|
||||
for (fc_url = fc; fc_url != 0; fc_url = fc_url->next_request)
|
||||
if (fc_url->active)
|
||||
fc_url->callback(FETCHCACHE_STATUS, fc->c,
|
||||
fc_url->p, status);
|
||||
content_process_data(fc->c, data, size);
|
||||
c->fetch_size += size;
|
||||
sprintf(c->status_message, "Received %lu bytes", c->fetch_size);
|
||||
content_broadcast(c, CONTENT_MSG_STATUS, 0);
|
||||
content_process_data(c, data, size);
|
||||
break;
|
||||
|
||||
case FETCH_FINISHED:
|
||||
LOG(("FETCH_FINISHED"));
|
||||
assert(fc->c != 0);
|
||||
sprintf(status, "Converting %lu bytes", fc->size);
|
||||
for (fc_url = fc; fc_url != 0; fc_url = fc_url->next_request)
|
||||
if (fc_url->active)
|
||||
fc_url->callback(FETCHCACHE_STATUS, fc->c,
|
||||
fc_url->p, status);
|
||||
|
||||
if (content_convert(fc->c, fc->width, fc->height) == 0) {
|
||||
cache_put(fc->c);
|
||||
for (fc_url = fc; fc_url != 0; fc_url = fc_url->next_request)
|
||||
if (fc_url->active)
|
||||
fc_url->callback(FETCHCACHE_OK, cache_get(fc->url),
|
||||
fc_url->p, 0);
|
||||
cache_free(fc->c);
|
||||
} else {
|
||||
content_destroy(fc->c);
|
||||
for (fc_url = fc; fc_url != 0; fc_url = fc_url->next_request)
|
||||
if (fc_url->active)
|
||||
fc_url->callback(FETCHCACHE_ERROR, 0,
|
||||
fc_url->p, "Conversion failed");
|
||||
}
|
||||
for (; fc != 0; fc = fc_url) {
|
||||
fc_url = fc->next_request;
|
||||
fetchcache_free(fc);
|
||||
}
|
||||
sprintf(c->status_message, "Converting %lu bytes", c->fetch_size);
|
||||
c->fetch = 0;
|
||||
content_broadcast(c, CONTENT_MSG_STATUS, 0);
|
||||
content_convert(c, c->width, c->height);
|
||||
break;
|
||||
|
||||
case FETCH_ERROR:
|
||||
LOG(("FETCH_ERROR, '%s'", data));
|
||||
if (fc->c != 0)
|
||||
content_destroy(fc->c);
|
||||
for (fc_url = fc; fc_url != 0; fc_url = fc_url->next_request)
|
||||
if (fc_url->active)
|
||||
fc->callback(FETCHCACHE_ERROR, 0, fc_url->p, data);
|
||||
for (; fc != 0; fc = fc_url) {
|
||||
fc_url = fc->next_request;
|
||||
fetchcache_free(fc);
|
||||
}
|
||||
c->fetch = 0;
|
||||
content_broadcast(c, CONTENT_MSG_ERROR, data);
|
||||
cache_destroy(c);
|
||||
content_destroy(c);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -210,15 +89,6 @@ void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size)
|
||||
}
|
||||
|
||||
|
||||
void status_callback(void *p, const char *status)
|
||||
{
|
||||
struct fetchcache *fc = p, *fc_url;
|
||||
for (fc_url = fc; fc_url != 0; fc_url = fc_url->next_request)
|
||||
if (fc_url->active)
|
||||
fc_url->callback(FETCHCACHE_STATUS, fc->c, fc_url->p, status);
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <unistd.h>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: fetchcache.h,v 1.4 2003/04/09 21:57:09 bursa Exp $
|
||||
* $Id: fetchcache.h,v 1.5 2003/06/17 19:24:20 bursa Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETSURF_DESKTOP_FETCHCACHE_H_
|
||||
@ -7,10 +7,9 @@
|
||||
|
||||
#include "netsurf/content/content.h"
|
||||
|
||||
typedef enum {FETCHCACHE_OK, FETCHCACHE_BADTYPE, FETCHCACHE_ERROR, FETCHCACHE_STATUS} fetchcache_msg;
|
||||
|
||||
void fetchcache(const char *url, char *referer,
|
||||
void (*callback)(fetchcache_msg msg, struct content *c, void *p, const char *error),
|
||||
void *p, unsigned long width, unsigned long height, content_type allowed);
|
||||
struct content * fetchcache(const char *url, char *referer,
|
||||
void (*callback)(content_msg msg, struct content *c, void *p1,
|
||||
void *p2, const char *error),
|
||||
void *p1, void *p2, unsigned long width, unsigned long height);
|
||||
|
||||
#endif
|
||||
|
50
content/other.c
Normal file
50
content/other.c
Normal file
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* $Id: other.c,v 1.1 2003/06/17 19:24:20 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "netsurf/content/other.h"
|
||||
#include "netsurf/utils/utils.h"
|
||||
|
||||
|
||||
void other_create(struct content *c)
|
||||
{
|
||||
c->data.other.data = xcalloc(0, 1);
|
||||
c->data.other.length = 0;
|
||||
}
|
||||
|
||||
|
||||
void other_process_data(struct content *c, char *data, unsigned long size)
|
||||
{
|
||||
c->data.other.data = xrealloc(c->data.other.data, c->data.other.length + size);
|
||||
memcpy(c->data.other.data + c->data.other.length, data, size);
|
||||
c->data.other.length += size;
|
||||
c->size += size;
|
||||
}
|
||||
|
||||
|
||||
int other_convert(struct content *c, unsigned int width, unsigned int height)
|
||||
{
|
||||
c->status = CONTENT_STATUS_DONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void other_revive(struct content *c, unsigned int width, unsigned int height)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
void other_reformat(struct content *c, unsigned int width, unsigned int height)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
void other_destroy(struct content *c)
|
||||
{
|
||||
assert(0);
|
||||
}
|
17
content/other.h
Normal file
17
content/other.h
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* $Id: other.h,v 1.1 2003/06/17 19:24:20 bursa Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETSURF_RISCOS_OTHER_H_
|
||||
#define _NETSURF_RISCOS_OTHER_H_
|
||||
|
||||
#include "netsurf/content/content.h"
|
||||
|
||||
void other_create(struct content *c);
|
||||
void other_process_data(struct content *c, char *data, unsigned long size);
|
||||
int other_convert(struct content *c, unsigned int width, unsigned int height);
|
||||
void other_revive(struct content *c, unsigned int width, unsigned int height);
|
||||
void other_reformat(struct content *c, unsigned int width, unsigned int height);
|
||||
void other_destroy(struct content *c);
|
||||
|
||||
#endif
|
52
content/overview
Normal file
52
content/overview
Normal file
@ -0,0 +1,52 @@
|
||||
NetSurf fetch, cache, and content system
|
||||
========================================
|
||||
|
||||
There is a one-to-one mapping between URLs and content structures.
|
||||
|
||||
The resource at a URL may be required for two reasons:
|
||||
|
||||
1. The user requests a URL in the GUI by entering it or following a link.
|
||||
2. A page contains an object (such as an image).
|
||||
|
||||
When a URL is required, call fetchcache() as follows:
|
||||
|
||||
c = fetchcache(url, referer, callback, p1, p2, width, height);
|
||||
|
||||
p1 and p2 are the callers private pointers used to identify the resource, and
|
||||
they are passed to the callback. The triple (callback, p1, p2) must be unique.
|
||||
The call returns immediately with a struct content. The structure may be in the
|
||||
following states (c->status):
|
||||
|
||||
CONTENT_STATUS_TYPE_UNKNOWN -- the MIME type of the resource has not been
|
||||
determined yet.
|
||||
|
||||
CONTENT_STATUS_LOADING -- the resource is being fetched or converted, and can
|
||||
not be displayed.
|
||||
|
||||
CONTENT_STATUS_READY -- the resource is still loading, but may be displayed.
|
||||
|
||||
CONTENT_STATUS_DONE -- the resource has loaded completely.
|
||||
|
||||
States may only follow in the above order (but some may be skipped). The
|
||||
callback function is called when the state changes or at other times as follows:
|
||||
|
||||
CONTENT_MSG_LOADING -- state has changed from CONTENT_STATUS_TYPE_UNKNOWN to
|
||||
CONTENT_STATUS_LOADING. If the type is not acceptable content_remove_user()
|
||||
should be called (see below).
|
||||
|
||||
CONTENT_MSG_READY -- state has changed to CONTENT_STATUS_READY.
|
||||
|
||||
CONTENT_MSG_DONE -- state has changed to CONTENT_STATUS_DONE.
|
||||
|
||||
CONTENT_MSG_ERROR -- a fatal error with the resource has occurred. The error
|
||||
message is in the callback parameter. The content structure will be
|
||||
destroyed after this message and must not be used.
|
||||
|
||||
CONTENT_MSG_STATUS -- the content structure's status message has changed.
|
||||
|
||||
If at any time the resource is no longer required, call content_remove_user():
|
||||
|
||||
content_remove_user(c, callback, p1, p2);
|
||||
|
||||
with the same callback, p1, p2 as passed to fetchcache().
|
||||
|
88
css/css.c
88
css/css.c
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: css.c,v 1.8 2003/04/25 08:03:15 bursa Exp $
|
||||
* $Id: css.c,v 1.9 2003/06/17 19:24:21 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@ -13,7 +13,9 @@
|
||||
#include "netsurf/content/fetchcache.h"
|
||||
#include "netsurf/css/css.h"
|
||||
#include "netsurf/css/parser.h"
|
||||
#ifdef riscos
|
||||
#include "netsurf/desktop/gui.h"
|
||||
#endif
|
||||
#include "netsurf/utils/log.h"
|
||||
#include "netsurf/utils/utils.h"
|
||||
|
||||
@ -26,13 +28,8 @@ struct decl {
|
||||
struct rule * rule;
|
||||
};
|
||||
|
||||
struct fetch_data {
|
||||
struct content *c;
|
||||
unsigned int i;
|
||||
};
|
||||
|
||||
void css_atimport_callback(fetchcache_msg msg, struct content *css,
|
||||
void *p, const char *error);
|
||||
void css_atimport_callback(content_msg msg, struct content *css,
|
||||
void *p1, void *p2, const char *error);
|
||||
void css_dump_style(const struct css_style * const style);
|
||||
|
||||
|
||||
@ -136,6 +133,7 @@ int css_convert(struct content *c, unsigned int width, unsigned int height)
|
||||
gui_multitask();
|
||||
}
|
||||
|
||||
c->status = CONTENT_STATUS_DONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -143,15 +141,14 @@ int css_convert(struct content *c, unsigned int width, unsigned int height)
|
||||
void css_revive(struct content *c, unsigned int width, unsigned int height)
|
||||
{
|
||||
unsigned int i;
|
||||
struct fetch_data *fetch_data;
|
||||
/* imported stylesheets */
|
||||
for (i = 0; i != c->data.css.import_count; i++) {
|
||||
fetch_data = xcalloc(1, sizeof(*fetch_data));
|
||||
fetch_data->c = c;
|
||||
fetch_data->i = i;
|
||||
c->active++;
|
||||
fetchcache(c->data.css.import_url[i], c->url, css_atimport_callback,
|
||||
fetch_data, c->width, c->height, 1 << CONTENT_CSS);
|
||||
c->data.css.import_content[i] = fetchcache(
|
||||
c->data.css.import_url[i], c->url,
|
||||
css_atimport_callback, c, i,
|
||||
c->width, c->height);
|
||||
if (c->data.css.import_content[i]->status != CONTENT_STATUS_DONE)
|
||||
c->active++;
|
||||
}
|
||||
while (c->active != 0) {
|
||||
fetch_poll();
|
||||
@ -181,7 +178,8 @@ void css_destroy(struct content *c)
|
||||
for (i = 0; i != c->data.css.import_count; i++)
|
||||
if (c->data.css.import_content[i] != 0) {
|
||||
free(c->data.css.import_url[i]);
|
||||
cache_free(c->data.css.import_content[i]);
|
||||
content_remove_user(c->data.css.import_content[i],
|
||||
css_atimport_callback, c, i);
|
||||
}
|
||||
xfree(c->data.css.import_url);
|
||||
xfree(c->data.css.import_content);
|
||||
@ -226,7 +224,7 @@ void css_atimport(struct content *c, struct node *node)
|
||||
{
|
||||
char *s, *url;
|
||||
int string = 0, screen = 1;
|
||||
struct fetch_data *fetch_data;
|
||||
unsigned int i;
|
||||
|
||||
LOG(("@import rule"));
|
||||
|
||||
@ -293,43 +291,51 @@ void css_atimport(struct content *c, struct node *node)
|
||||
c->data.css.import_content = xrealloc(c->data.css.import_content,
|
||||
c->data.css.import_count * sizeof(*c->data.css.import_content));
|
||||
|
||||
fetch_data = xcalloc(1, sizeof(*fetch_data));
|
||||
fetch_data->c = c;
|
||||
fetch_data->i = c->data.css.import_count - 1;
|
||||
c->data.css.import_url[fetch_data->i] = url_join(url, c->url);
|
||||
c->active++;
|
||||
fetchcache(c->data.css.import_url[fetch_data->i], c->url, css_atimport_callback,
|
||||
fetch_data, c->width, c->height, 1 << CONTENT_CSS);
|
||||
i = c->data.css.import_count - 1;
|
||||
c->data.css.import_url[i] = url_join(url, c->url);
|
||||
c->data.css.import_content[i] = fetchcache(
|
||||
c->data.css.import_url[i], c->url, css_atimport_callback,
|
||||
c, i, c->width, c->height);
|
||||
if (c->data.css.import_content[i]->status != CONTENT_STATUS_DONE)
|
||||
c->active++;
|
||||
|
||||
free(url);
|
||||
}
|
||||
|
||||
|
||||
void css_atimport_callback(fetchcache_msg msg, struct content *css,
|
||||
void *p, const char *error)
|
||||
void css_atimport_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:
|
||||
if (css->type != CONTENT_CSS) {
|
||||
content_remove_user(css, css_atimport_callback, c, i);
|
||||
c->data.css.import_content[i] = 0;
|
||||
c->active--;
|
||||
c->error = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONTENT_MSG_READY:
|
||||
break;
|
||||
|
||||
case CONTENT_MSG_DONE:
|
||||
LOG(("got imported stylesheet '%s'", css->url));
|
||||
c->data.css.import_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.css.import_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:
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@ -371,11 +377,13 @@ void css_get_style(struct content *c, struct css_selector * selector,
|
||||
for (m = n->left; m != 0; m = m->next) {
|
||||
if (m->type == NODE_ID) {
|
||||
/* TODO: check if case sensitive */
|
||||
if (strcmp(selector[i].id, m->data + 1) != 0)
|
||||
if (selector[i].id == 0 ||
|
||||
strcmp(selector[i].id, m->data + 1) != 0)
|
||||
goto not_matched;
|
||||
} else if (m->type == NODE_CLASS) {
|
||||
/* TODO: check if case sensitive */
|
||||
if (strcmp(selector[i].class, m->data) != 0)
|
||||
if (selector[i].class == 0 ||
|
||||
strcmp(selector[i].class, m->data) != 0)
|
||||
goto not_matched;
|
||||
} else {
|
||||
goto not_matched;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: browser.c,v 1.39 2003/06/05 13:17:55 philpem Exp $
|
||||
* $Id: browser.c,v 1.40 2003/06/17 19:24:21 bursa Exp $
|
||||
*/
|
||||
|
||||
#include "netsurf/content/cache.h"
|
||||
@ -30,8 +30,8 @@ static int redraw_box_list(struct browser_window* bw, struct box* current,
|
||||
static void browser_window_redraw_boxes(struct browser_window* bw, struct box_position* start, struct box_position* end);
|
||||
static void browser_window_follow_link(struct browser_window* bw,
|
||||
unsigned long click_x, unsigned long click_y, int click_type);
|
||||
static void browser_window_callback(fetchcache_msg msg, struct content *c,
|
||||
void *p, const char *error);
|
||||
static void browser_window_callback(content_msg msg, struct content *c,
|
||||
void *p1, void *p2, const char *error);
|
||||
static void clear_radio_gadgets(struct browser_window* bw, struct box* box, struct gui_gadget* group);
|
||||
static void gui_redraw_gadget2(struct browser_window* bw, struct box* box, struct gui_gadget* g,
|
||||
unsigned long x, unsigned long y);
|
||||
@ -157,6 +157,7 @@ struct browser_window* create_browser_window(int flags, int width, int height)
|
||||
bw->scale.div = 1;
|
||||
|
||||
bw->current_content = NULL;
|
||||
bw->loading_content = NULL;
|
||||
bw->history = NULL;
|
||||
|
||||
bw->url = NULL;
|
||||
@ -178,7 +179,7 @@ void browser_window_destroy(struct browser_window* bw)
|
||||
assert(bw != 0);
|
||||
|
||||
if (bw->current_content != NULL)
|
||||
cache_free(bw->current_content);
|
||||
content_remove_user(bw->current_content, browser_window_callback, bw, 0);
|
||||
|
||||
if (bw->history != NULL)
|
||||
{
|
||||
@ -220,11 +221,12 @@ void browser_window_open_location_historical(struct browser_window* bw, const ch
|
||||
browser_window_set_status(bw, "Opening page...");
|
||||
browser_window_start_throbber(bw);
|
||||
bw->time0 = clock();
|
||||
fetchcache(url, 0, browser_window_callback, bw,
|
||||
gui_window_get_width(bw->window), 0,
|
||||
(1 << CONTENT_HTML) | (1 << CONTENT_TEXTPLAIN) |
|
||||
(1 << CONTENT_JPEG) | (1 << CONTENT_PNG) |
|
||||
(1 << CONTENT_GIF));
|
||||
bw->loading_content = fetchcache(url, 0, browser_window_callback, bw, 0,
|
||||
gui_window_get_width(bw->window), 0);
|
||||
if (bw->loading_content->status == CONTENT_STATUS_READY)
|
||||
browser_window_callback(CONTENT_MSG_READY, bw->loading_content, bw, 0, 0);
|
||||
else if (bw->loading_content->status == CONTENT_STATUS_DONE)
|
||||
browser_window_callback(CONTENT_MSG_DONE, bw->loading_content, bw, 0, 0);
|
||||
|
||||
LOG(("end"));
|
||||
}
|
||||
@ -247,17 +249,27 @@ void browser_window_open_location(struct browser_window* bw, const char* url0)
|
||||
LOG(("end"));
|
||||
}
|
||||
|
||||
void browser_window_callback(fetchcache_msg msg, struct content *c,
|
||||
void *p, const char *error)
|
||||
void browser_window_callback(content_msg msg, struct content *c,
|
||||
void *p1, void *p2, const char *error)
|
||||
{
|
||||
struct browser_window* bw = p;
|
||||
struct browser_window* bw = p1;
|
||||
gui_safety previous_safety;
|
||||
char status[40];
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case FETCHCACHE_OK:
|
||||
{
|
||||
case CONTENT_MSG_LOADING:
|
||||
if (c->type == CONTENT_OTHER) {
|
||||
/* TODO: implement downloads */
|
||||
/* we probably want to open a new window with a save icon and progress bar,
|
||||
* and transfer content_loading to it */
|
||||
}
|
||||
break;
|
||||
|
||||
case CONTENT_MSG_READY:
|
||||
case CONTENT_MSG_DONE:
|
||||
previous_safety = gui_window_set_redraw_safety(bw->window, UNSAFE);
|
||||
if (bw->loading_content == c) {
|
||||
struct gui_message gmsg;
|
||||
if (bw->url != 0)
|
||||
xfree(bw->url);
|
||||
@ -267,7 +279,6 @@ void browser_window_callback(fetchcache_msg msg, struct content *c,
|
||||
gmsg.data.set_url.url = bw->url;
|
||||
gui_window_message(bw->window, &gmsg);
|
||||
|
||||
previous_safety = gui_window_set_redraw_safety(bw->window, UNSAFE);
|
||||
if (bw->current_content != NULL)
|
||||
{
|
||||
if (bw->current_content->type == CONTENT_HTML)
|
||||
@ -278,34 +289,33 @@ void browser_window_callback(fetchcache_msg msg, struct content *c,
|
||||
gui_remove_gadget(bw->current_content->data.html.elements.gadgets[gc]);
|
||||
}
|
||||
}
|
||||
cache_free(bw->current_content);
|
||||
content_remove_user(bw->current_content, browser_window_callback, bw, 0);
|
||||
}
|
||||
bw->current_content = c;
|
||||
browser_window_reformat(bw);
|
||||
gui_window_set_redraw_safety(bw->window, previous_safety);
|
||||
if (bw->current_content->status == CONTENT_DONE) {
|
||||
sprintf(status, "Page complete (%gs)", ((float) (clock() - bw->time0)) / CLOCKS_PER_SEC);
|
||||
browser_window_set_status(bw, status);
|
||||
browser_window_stop_throbber(bw);
|
||||
} else {
|
||||
browser_window_set_status(bw, bw->current_content->status_message);
|
||||
}
|
||||
bw->loading_content = 0;
|
||||
}
|
||||
browser_window_reformat(bw);
|
||||
gui_window_set_redraw_safety(bw->window, previous_safety);
|
||||
if (bw->current_content->status == CONTENT_STATUS_DONE) {
|
||||
sprintf(status, "Page complete (%gs)", ((float) (clock() - bw->time0)) / CLOCKS_PER_SEC);
|
||||
browser_window_set_status(bw, status);
|
||||
browser_window_stop_throbber(bw);
|
||||
} else {
|
||||
browser_window_set_status(bw, c->status_message);
|
||||
}
|
||||
break;
|
||||
|
||||
case FETCHCACHE_ERROR:
|
||||
case CONTENT_MSG_ERROR:
|
||||
browser_window_set_status(bw, error);
|
||||
if (c == bw->loading_content)
|
||||
bw->loading_content = 0;
|
||||
else if (c == bw->current_content)
|
||||
bw->current_content = 0;
|
||||
browser_window_stop_throbber(bw);
|
||||
break;
|
||||
|
||||
case FETCHCACHE_BADTYPE:
|
||||
sprintf(status, "Unknown type '%s'", error);
|
||||
browser_window_set_status(bw, status);
|
||||
browser_window_stop_throbber(bw);
|
||||
break;
|
||||
|
||||
case FETCHCACHE_STATUS:
|
||||
browser_window_set_status(bw, error);
|
||||
case CONTENT_MSG_STATUS:
|
||||
browser_window_set_status(bw, c->status_message);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: browser.h,v 1.12 2003/04/15 17:53:00 bursa Exp $
|
||||
* $Id: browser.h,v 1.13 2003/06/17 19:24:21 bursa Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETSURF_DESKTOP_BROWSER_H_
|
||||
@ -48,6 +48,7 @@ struct browser_window
|
||||
struct { int mult; int div; } scale;
|
||||
|
||||
struct content* current_content;
|
||||
struct content* loading_content;
|
||||
struct history* history;
|
||||
clock_t time0;
|
||||
|
||||
|
4
makefile
4
makefile
@ -1,7 +1,7 @@
|
||||
# $Id: makefile,v 1.33 2003/06/05 14:39:54 bursa Exp $
|
||||
# $Id: makefile,v 1.34 2003/06/17 19:24:20 bursa Exp $
|
||||
|
||||
CC = riscos-gcc
|
||||
OBJECTS = cache.o content.o fetch.o fetchcache.o \
|
||||
OBJECTS = cache.o content.o fetch.o fetchcache.o other.o \
|
||||
css.o css_enum.o parser.o ruleset.o scanner.o \
|
||||
browser.o netsurf.o \
|
||||
box.o html.o layout.o textplain.o \
|
||||
|
12
render/box.c
12
render/box.c
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: box.c,v 1.50 2003/06/07 22:24:22 jmb Exp $
|
||||
* $Id: box.c,v 1.51 2003/06/17 19:24:21 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@ -10,13 +10,15 @@
|
||||
#include "libxml/HTMLparser.h"
|
||||
#include "netsurf/content/fetchcache.h"
|
||||
#include "netsurf/css/css.h"
|
||||
#include "netsurf/desktop/gui.h"
|
||||
#include "netsurf/render/box.h"
|
||||
#ifdef riscos
|
||||
#include "netsurf/desktop/gui.h"
|
||||
#include "netsurf/riscos/font.h"
|
||||
#endif
|
||||
#include "netsurf/riscos/plugin.h"
|
||||
#define NDEBUG
|
||||
#include "netsurf/utils/log.h"
|
||||
#include "netsurf/utils/utils.h"
|
||||
//#define NDEBUG
|
||||
|
||||
/**
|
||||
* internal functions
|
||||
@ -1052,7 +1054,7 @@ struct box* box_image(xmlNode *n, struct content *content,
|
||||
xmlFree(s);
|
||||
|
||||
/* start fetch */
|
||||
html_fetch_image(content, url, box);
|
||||
html_fetch_object(content, url, box);
|
||||
|
||||
return box;
|
||||
}
|
||||
@ -1368,7 +1370,7 @@ struct form* box_form(xmlNode* n)
|
||||
struct form* form;
|
||||
char* s;
|
||||
|
||||
form = xcalloc(1, sizeof(struct form*));
|
||||
form = xcalloc(1, sizeof(*form));
|
||||
|
||||
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "action"))) {
|
||||
form->action = s;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: box.h,v 1.25 2003/05/22 13:21:45 bursa Exp $
|
||||
* $Id: box.h,v 1.26 2003/06/17 19:24:21 bursa Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETSURF_RENDER_BOX_H_
|
||||
@ -8,7 +8,9 @@
|
||||
#include <limits.h>
|
||||
#include "libxml/HTMLparser.h"
|
||||
#include "netsurf/css/css.h"
|
||||
#ifdef riscos
|
||||
#include "netsurf/riscos/font.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* structures
|
||||
|
271
render/html.c
271
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);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: html.h,v 1.2 2003/04/15 17:53:00 bursa Exp $
|
||||
* $Id: html.h,v 1.3 2003/06/17 19:24:21 bursa Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETSURF_RENDER_HTML_H_
|
||||
@ -13,6 +13,6 @@ int html_convert(struct content *c, unsigned int width, unsigned int height);
|
||||
void html_revive(struct content *c, unsigned int width, unsigned int height);
|
||||
void html_reformat(struct content *c, unsigned int width, unsigned int height);
|
||||
void html_destroy(struct content *c);
|
||||
void html_fetch_image(struct content *c, char *url, struct box *box);
|
||||
void html_fetch_object(struct content *c, char *url, struct box *box);
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: layout.c,v 1.40 2003/04/15 17:53:00 bursa Exp $
|
||||
* $Id: layout.c,v 1.41 2003/06/17 19:24:21 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@ -8,11 +8,18 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "libxml/HTMLparser.h"
|
||||
#ifdef riscos
|
||||
#include "netsurf/desktop/gui.h"
|
||||
#endif
|
||||
#include "netsurf/content/content.h"
|
||||
#include "netsurf/render/box.h"
|
||||
#include "netsurf/css/css.h"
|
||||
#include "netsurf/render/layout.h"
|
||||
#ifdef riscos
|
||||
#include "netsurf/riscos/font.h"
|
||||
#else
|
||||
#include "netsurf/debug/font.h"
|
||||
#endif
|
||||
#include "netsurf/utils/utils.h"
|
||||
#define NDEBUG
|
||||
#include "netsurf/utils/log.h"
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Add better error handling
|
||||
* - especially where bad GIFs are concerned.
|
||||
*
|
||||
* $Id: gif.c,v 1.6 2003/06/07 13:07:48 philpem Exp $
|
||||
* $Id: gif.c,v 1.7 2003/06/17 19:24:21 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@ -274,6 +274,7 @@ int nsgif_convert(struct content *c, unsigned int iwidth, unsigned int iheight)
|
||||
|
||||
c->title = xcalloc(100, 1);
|
||||
sprintf(c->title, "GIF image (%lux%lu)", c->width, c->height);
|
||||
c->status = CONTENT_STATUS_DONE;
|
||||
|
||||
// Enable this if you want to debug the GIF loader
|
||||
// xosspriteop_save_sprite_file(osspriteop_USER_AREA, c->data.gif.sprite_area,
|
||||
|
15
riscos/gui.c
15
riscos/gui.c
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: gui.c,v 1.32 2003/06/14 11:34:02 bursa Exp $
|
||||
* $Id: gui.c,v 1.33 2003/06/17 19:24:21 bursa Exp $
|
||||
*/
|
||||
|
||||
#include "netsurf/desktop/options.h"
|
||||
@ -1170,19 +1170,6 @@ void ro_gui_throb(void)
|
||||
{
|
||||
if (g->type == GUI_BROWSER_WINDOW)
|
||||
{
|
||||
if (g->data.browser.bw->current_content->status == CONTENT_PENDING) {
|
||||
/* images still loading */
|
||||
gui_window_set_status(g, g->data.browser.bw->current_content->status_message);
|
||||
if (g->data.browser.bw->current_content->active == 0) {
|
||||
/* any image fetches have finished */
|
||||
browser_window_reformat(g->data.browser.bw);
|
||||
browser_window_stop_throbber(g->data.browser.bw);
|
||||
/* TODO: move this elsewhere: can't just move it to the image loader,
|
||||
* because then this if would be triggered when an old content is
|
||||
* present */
|
||||
g->data.browser.bw->current_content->status = CONTENT_DONE;
|
||||
}
|
||||
}
|
||||
if ((g->data.browser.bw->flags & browser_TOOLBAR) != 0)
|
||||
{
|
||||
if (g->data.browser.bw->throbbing != 0)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: jpeg.c,v 1.5 2003/06/14 11:34:02 bursa Exp $
|
||||
* $Id: jpeg.c,v 1.6 2003/06/17 19:24:21 bursa Exp $
|
||||
*
|
||||
* This is just a temporary implementation using the JPEG renderer
|
||||
* available in some versions of RISC OS.
|
||||
@ -42,6 +42,7 @@ int jpeg_convert(struct content *c, unsigned int width, unsigned int height)
|
||||
c->height = h;
|
||||
c->title = xcalloc(100, 1);
|
||||
sprintf(c->title, "JPEG image (%ux%u, %lu bytes)", w, h, c->data.jpeg.length);
|
||||
c->status = CONTENT_STATUS_DONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: plugin.c,v 1.9 2003/06/07 22:24:22 jmb Exp $
|
||||
* $Id: plugin.c,v 1.10 2003/06/17 19:24:21 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@ -156,7 +156,7 @@ void plugin_decode(struct content* content, char* url, struct box* box,
|
||||
*/
|
||||
xfree(po);
|
||||
LOG(("sending data to image handler"));
|
||||
html_fetch_image(content, url, box);
|
||||
html_fetch_object(content, url, box);
|
||||
return;
|
||||
}
|
||||
else { /* not an image; is sys var set? */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id: png.c,v 1.3 2003/06/14 11:34:02 bursa Exp $
|
||||
* $Id: png.c,v 1.4 2003/06/17 19:24:21 bursa Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@ -259,6 +259,7 @@ int nspng_convert(struct content *c, unsigned int width, unsigned int height)
|
||||
png_destroy_read_struct(&c->data.png.png, &c->data.png.info, 0);
|
||||
c->title = xcalloc(100, 1);
|
||||
sprintf(c->title, "png image (%ux%u)", c->width, c->height);
|
||||
c->status = CONTENT_STATUS_DONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user