libwapcaplet: branch chris/sam460-ocm updated. 8d88e2c73fd87fcb4722d00866671de4b5747c09
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/libwapcaplet.git/shortlog/8d88e2c73fd87fcb...
...commit http://git.netsurf-browser.org/libwapcaplet.git/commit/8d88e2c73fd87fcb47...
...tree http://git.netsurf-browser.org/libwapcaplet.git/tree/8d88e2c73fd87fcb4722...
The branch, chris/sam460-ocm has been updated
via 8d88e2c73fd87fcb4722d00866671de4b5747c09 (commit)
from 617aa5e79e56b305619ef3661c4ae86952680ac9 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/libwapcaplet.git/commitdiff/8d88e2c73fd87f...
commit 8d88e2c73fd87fcb4722d00866671de4b5747c09
Author: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Move memory pool pointer list into lwc context
add destructor to clean up memory at exit
diff --git a/src/libwapcaplet.c b/src/libwapcaplet.c
index 8126e62..1b6ead4 100644
--- a/src/libwapcaplet.c
+++ b/src/libwapcaplet.c
@@ -41,6 +41,7 @@ lwc__calculate_hash(const char *str, size_t len)
typedef struct lwc_context_s {
lwc_string ** buckets;
lwc_hash bucketcount;
+ memory_pool_t * mp;
} lwc_context;
static lwc_context *ctx = NULL;
@@ -50,49 +51,48 @@ static lwc_context *ctx = NULL;
#define LWC_ALLOC_STR() str_alloc()
#define LWC_FREE_STR(p) str_free(p)
-memory_pool_t *mp = NULL;
-
typedef lwc_hash (*lwc_hasher)(const char *, size_t);
typedef int (*lwc_strncmp)(const char *, const char *, size_t);
typedef void (*lwc_memcpy)(char *, const char *, size_t);
static void *str_alloc(void);
static void str_free(void *p);
+void lwc__exit(void) __attribute__((destructor));
static void *str_alloc(void)
{
void *p;
- memory_pool_t *mpc;
+ memory_pool_t *mp;
- if(mp == NULL) {
- mp = memory_pool_create(sizeof(lwc_string), MEM_POOL_BLOCKS);
- if(mp == NULL) return NULL; /* out of memory */
+ if(ctx->mp == NULL) {
+ ctx->mp = memory_pool_create(sizeof(lwc_string), MEM_POOL_BLOCKS);
+ if(ctx->mp == NULL) return NULL; /* out of memory */
}
- mpc = mp;
+ mp = ctx->mp;
do {
- if((p = memory_pool_alloc(mpc))) {
+ if((p = memory_pool_alloc(mp))) {
return p;
}
- if(mpc->next == NULL) {
- mpc->next = memory_pool_create(sizeof(lwc_string), MEM_POOL_BLOCKS);
- if(mpc->next == NULL) return NULL; /* out of memory */
+ if(mp->next == NULL) {
+ mp->next = memory_pool_create(sizeof(lwc_string), MEM_POOL_BLOCKS);
+ if(mp->next == NULL) return NULL; /* out of memory */
}
- } while((mpc = mpc->next));
+ } while((mp = mp->next));
return NULL; /* should never get here */
}
static void str_free(void *p)
{
- memory_pool_t *mpc = mp;
+ memory_pool_t *mp = ctx->mp;
do {
- if(memory_pool_free(mpc, p))
+ if(memory_pool_free(mp, p))
return;
- }while((mpc = mpc->next));
+ }while((mp = mp->next));
}
static lwc_error
@@ -306,3 +306,32 @@ lwc_iterate_strings(lwc_iteration_callback_fn cb, void *pw)
cb(str, pw);
}
}
+
+/**** Cleanup ****/
+
+static void lwc__free_strings(lwc_string *str, void *pw)
+{
+ UNUSED(pw);
+
+ LWC_FREE(STR_OF(str));
+ LWC_FREE_STR(str);
+}
+
+void lwc__exit(void)
+{
+ memory_pool_t *mp_next = NULL;
+ memory_pool_t *mp = ctx->mp;
+
+ lwc_iterate_strings(lwc__free_strings, NULL);
+
+ do {
+ if((mp != NULL)) {
+ mp_next = mp->next;
+ memory_pool_destroy(mp);
+ }
+
+ } while((mp = mp_next));
+
+ LWC_FREE(ctx->buckets);
+ LWC_FREE(ctx);
+}
-----------------------------------------------------------------------
Summary of changes:
src/libwapcaplet.c | 59 ++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 44 insertions(+), 15 deletions(-)
diff --git a/src/libwapcaplet.c b/src/libwapcaplet.c
index 8126e62..1b6ead4 100644
--- a/src/libwapcaplet.c
+++ b/src/libwapcaplet.c
@@ -41,6 +41,7 @@ lwc__calculate_hash(const char *str, size_t len)
typedef struct lwc_context_s {
lwc_string ** buckets;
lwc_hash bucketcount;
+ memory_pool_t * mp;
} lwc_context;
static lwc_context *ctx = NULL;
@@ -50,49 +51,48 @@ static lwc_context *ctx = NULL;
#define LWC_ALLOC_STR() str_alloc()
#define LWC_FREE_STR(p) str_free(p)
-memory_pool_t *mp = NULL;
-
typedef lwc_hash (*lwc_hasher)(const char *, size_t);
typedef int (*lwc_strncmp)(const char *, const char *, size_t);
typedef void (*lwc_memcpy)(char *, const char *, size_t);
static void *str_alloc(void);
static void str_free(void *p);
+void lwc__exit(void) __attribute__((destructor));
static void *str_alloc(void)
{
void *p;
- memory_pool_t *mpc;
+ memory_pool_t *mp;
- if(mp == NULL) {
- mp = memory_pool_create(sizeof(lwc_string), MEM_POOL_BLOCKS);
- if(mp == NULL) return NULL; /* out of memory */
+ if(ctx->mp == NULL) {
+ ctx->mp = memory_pool_create(sizeof(lwc_string), MEM_POOL_BLOCKS);
+ if(ctx->mp == NULL) return NULL; /* out of memory */
}
- mpc = mp;
+ mp = ctx->mp;
do {
- if((p = memory_pool_alloc(mpc))) {
+ if((p = memory_pool_alloc(mp))) {
return p;
}
- if(mpc->next == NULL) {
- mpc->next = memory_pool_create(sizeof(lwc_string), MEM_POOL_BLOCKS);
- if(mpc->next == NULL) return NULL; /* out of memory */
+ if(mp->next == NULL) {
+ mp->next = memory_pool_create(sizeof(lwc_string), MEM_POOL_BLOCKS);
+ if(mp->next == NULL) return NULL; /* out of memory */
}
- } while((mpc = mpc->next));
+ } while((mp = mp->next));
return NULL; /* should never get here */
}
static void str_free(void *p)
{
- memory_pool_t *mpc = mp;
+ memory_pool_t *mp = ctx->mp;
do {
- if(memory_pool_free(mpc, p))
+ if(memory_pool_free(mp, p))
return;
- }while((mpc = mpc->next));
+ }while((mp = mp->next));
}
static lwc_error
@@ -306,3 +306,32 @@ lwc_iterate_strings(lwc_iteration_callback_fn cb, void *pw)
cb(str, pw);
}
}
+
+/**** Cleanup ****/
+
+static void lwc__free_strings(lwc_string *str, void *pw)
+{
+ UNUSED(pw);
+
+ LWC_FREE(STR_OF(str));
+ LWC_FREE_STR(str);
+}
+
+void lwc__exit(void)
+{
+ memory_pool_t *mp_next = NULL;
+ memory_pool_t *mp = ctx->mp;
+
+ lwc_iterate_strings(lwc__free_strings, NULL);
+
+ do {
+ if((mp != NULL)) {
+ mp_next = mp->next;
+ memory_pool_destroy(mp);
+ }
+
+ } while((mp = mp_next));
+
+ LWC_FREE(ctx->buckets);
+ LWC_FREE(ctx);
+}
--
String internment library
10 years, 7 months
libhubbub: branch master updated. 4e091eb81e7a5ada5d8aafa7990d094f276f2099
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/libhubbub.git/shortlog/4e091eb81e7a5ada5d8...
...commit http://git.netsurf-browser.org/libhubbub.git/commit/4e091eb81e7a5ada5d8aa...
...tree http://git.netsurf-browser.org/libhubbub.git/tree/4e091eb81e7a5ada5d8aafa...
The branch, master has been updated
via 4e091eb81e7a5ada5d8aafa7990d094f276f2099 (commit)
from 1dee56a7494a71a73dfc83a605d02e9450bf7e25 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/libhubbub.git/commitdiff/4e091eb81e7a5ada5...
commit 4e091eb81e7a5ada5d8aafa7990d094f276f2099
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Fix handling of encoding change
diff --git a/examples/libxml.c b/examples/libxml.c
index 1e787e2..e970e4c 100644
--- a/examples/libxml.c
+++ b/examples/libxml.c
@@ -213,19 +213,20 @@ int main(int argc, char **argv)
* change_encoding() will have put the new charset into
* c->encoding.
*/
- hubbub_parser *temp;
+ context *c2;
- if (hubbub_parser_create(c->encoding, true, myrealloc, NULL,
- &temp) != HUBBUB_OK) {
- destroy_context(c);
+ error = create_context(c->encoding, &c2);
+ if (error != OK) {
+ destroy_context(c2);
free(buf);
fclose(input);
- fprintf(stderr, "Failed recreating parser\n");
+ fprintf(stderr, "Failed recreating context\n");
return 1;
}
- hubbub_parser_destroy(c->parser);
- c->parser = temp;
+ destroy_context(c);
+
+ c = c2;
/* Retry the parse */
error = parse_chunk(c, buf, len);
-----------------------------------------------------------------------
Summary of changes:
examples/libxml.c | 15 ++++++++-------
1 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/examples/libxml.c b/examples/libxml.c
index 1e787e2..e970e4c 100644
--- a/examples/libxml.c
+++ b/examples/libxml.c
@@ -213,19 +213,20 @@ int main(int argc, char **argv)
* change_encoding() will have put the new charset into
* c->encoding.
*/
- hubbub_parser *temp;
+ context *c2;
- if (hubbub_parser_create(c->encoding, true, myrealloc, NULL,
- &temp) != HUBBUB_OK) {
- destroy_context(c);
+ error = create_context(c->encoding, &c2);
+ if (error != OK) {
+ destroy_context(c2);
free(buf);
fclose(input);
- fprintf(stderr, "Failed recreating parser\n");
+ fprintf(stderr, "Failed recreating context\n");
return 1;
}
- hubbub_parser_destroy(c->parser);
- c->parser = temp;
+ destroy_context(c);
+
+ c = c2;
/* Retry the parse */
error = parse_chunk(c, buf, len);
--
HTML5 parser library
10 years, 7 months
netsurf: branch master updated. 6b9f7c3094248c4b0594040bf93b7a5a071d8d6e
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/6b9f7c3094248c4b05940...
...commit http://git.netsurf-browser.org/netsurf.git/commit/6b9f7c3094248c4b0594040...
...tree http://git.netsurf-browser.org/netsurf.git/tree/6b9f7c3094248c4b0594040bf...
The branch, master has been updated
via 6b9f7c3094248c4b0594040bf93b7a5a071d8d6e (commit)
via cd3e073354dacbd18baf0039b71b2739bd266357 (commit)
via 97978e858b396157540d9e0bff91676bb8dcd500 (commit)
from 21cbb49a6bb9e2ad23b7c8d4ab6a9536dc4a2781 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commitdiff/6b9f7c3094248c4b059...
commit 6b9f7c3094248c4b0594040bf93b7a5a071d8d6e
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Use correct base URL for inline stylesheets
diff --git a/css/css.c b/css/css.c
index 8923bdc..0410f18 100644
--- a/css/css.c
+++ b/css/css.c
@@ -129,6 +129,7 @@ nserror nscss_create(const content_handler *handler,
{
nscss_content *result;
const char *charset = NULL;
+ const char *xnsbase = NULL;
lwc_string *charset_value = NULL;
union content_msg_data msg_data;
nserror error;
@@ -155,9 +156,14 @@ nserror nscss_create(const content_handler *handler,
charset = lwc_string_data(charset_value);
}
+ /* Compute base URL for stylesheet */
+ xnsbase = llcache_handle_get_header(llcache, "X-NS-Base");
+ if (xnsbase == NULL) {
+ xnsbase = nsurl_access(content_get_url(&result->base));
+ }
+
error = nscss_create_css_data(&result->data,
- nsurl_access(content_get_url(&result->base)),
- charset, result->base.quirks,
+ xnsbase, charset, result->base.quirks,
nscss_content_done, result);
if (error != NSERROR_OK) {
msg_data.error = messages_get("NoMemory");
diff --git a/render/html_css.c b/render/html_css.c
index b98632e..3eabec4 100644
--- a/render/html_css.c
+++ b/render/html_css.c
@@ -296,7 +296,7 @@ html_stylesheet_from_domnode(html_content *c,
return NSERROR_OK;
}
- error = html_css_fetcher_add_item(style, &key);
+ error = html_css_fetcher_add_item(style, c->base_url, &key);
if (error != NSERROR_OK) {
dom_string_unref(style);
return error;
diff --git a/render/html_css_fetcher.c b/render/html_css_fetcher.c
index 31e2cba..9bd3b21 100644
--- a/render/html_css_fetcher.c
+++ b/render/html_css_fetcher.c
@@ -37,6 +37,7 @@
typedef struct html_css_fetcher_item {
uint32_t key;
dom_string *data;
+ nsurl *base_url;
struct html_css_fetcher_item *r_next, *r_prev;
} html_css_fetcher_item;
@@ -142,6 +143,7 @@ static void html_css_fetcher_free(void *ctx)
nsurl_unref(c->url);
if (c->item != NULL) {
+ nsurl_unref(c->item->base_url);
dom_string_unref(c->item->data);
RING_REMOVE(items, c->item);
free(c->item);
@@ -195,7 +197,7 @@ static void html_css_fetcher_poll(lwc_string *scheme)
/* Nothing to do */
assert(c->locked == false);
} else if (c->item != NULL) {
- char header[64];
+ char header[4096];
fetch_set_http_code(c->parent_fetch, 200);
@@ -222,6 +224,18 @@ static void html_css_fetcher_poll(lwc_string *scheme)
}
if (c->aborted == false) {
+ snprintf(header, sizeof header,
+ "X-NS-Base: %.*s",
+ (int) nsurl_length(c->item->base_url),
+ nsurl_access(c->item->base_url));
+ msg.type = FETCH_HEADER;
+ msg.data.header_or_data.buf =
+ (const uint8_t *) header;
+ msg.data.header_or_data.len = strlen(header);
+ html_css_fetcher_send_callback(&msg, c);
+ }
+
+ if (c->aborted == false) {
msg.type = FETCH_DATA;
msg.data.header_or_data.buf =
(const uint8_t *)
@@ -280,7 +294,8 @@ void html_css_fetcher_register(void)
html_css_fetcher_finalise);
}
-nserror html_css_fetcher_add_item(dom_string *data, uint32_t *key)
+nserror html_css_fetcher_add_item(dom_string *data, nsurl *base_url,
+ uint32_t *key)
{
html_css_fetcher_item *item = malloc(sizeof(*item));
@@ -290,6 +305,7 @@ nserror html_css_fetcher_add_item(dom_string *data, uint32_t *key)
*key = item->key = current_key++;
item->data = dom_string_ref(data);
+ item->base_url = nsurl_ref(base_url);
RING_INSERT(items, item);
diff --git a/render/html_internal.h b/render/html_internal.h
index f92948b..90f0143 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -268,11 +268,13 @@ nserror html_css_free_stylesheets(html_content *html);
bool html_css_process_link(html_content *htmlc, dom_node *node);
bool html_css_update_style(html_content *c, dom_node *style);
-nserror html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx);
+nserror html_css_new_selection_context(html_content *c,
+ css_select_ctx **ret_select_ctx);
/* in render/html_css_fetcher.c */
void html_css_fetcher_register(void);
-nserror html_css_fetcher_add_item(dom_string *data, uint32_t *key);
+nserror html_css_fetcher_add_item(dom_string *data, nsurl *base_url,
+ uint32_t *key);
/* in render/html_object.c */
commitdiff http://git.netsurf-browser.org/netsurf.git/commitdiff/cd3e073354dacbd18ba...
commit cd3e073354dacbd18baf0039b71b2739bd266357
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Fix logging
diff --git a/desktop/browser.c b/desktop/browser.c
index 1eed1e0..45f33ab 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -844,10 +844,11 @@ nserror browser_window_navigate(struct browser_window *bw,
hlcache_child_context child;
nserror error;
- LOG(("bw %p, url %s", bw, url));
assert(bw);
assert(url);
+ LOG(("bw %p, url %s", bw, nsurl_access(url)));
+
/* don't allow massively nested framesets */
for (cur = bw; cur->parent; cur = cur->parent) {
depth++;
commitdiff http://git.netsurf-browser.org/netsurf.git/commitdiff/97978e858b396157540...
commit 97978e858b396157540d9e0bff91676bb8dcd500
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Use custom fetcher for inline CSS
diff --git a/Makefile.sources b/Makefile.sources
index b53d7c5..ab71ff3 100644
--- a/Makefile.sources
+++ b/Makefile.sources
@@ -14,8 +14,8 @@ S_CSS := css.c dump.c internal.c select.c utils.c
S_RENDER := box.c box_construct.c box_normalise.c box_textarea.c \
font.c form.c imagemap.c layout.c list.c search.c table.c \
textplain.c \
- html.c html_css.c html_script.c html_interaction.c \
- html_redraw.c html_forms.c html_object.c
+ html.c html_css.c html_css_fetcher.c html_script.c \
+ html_interaction.c html_redraw.c html_forms.c html_object.c
S_UTILS := base64.c corestrings.c filename.c filepath.c hashtable.c \
libdom.c locale.c log.c messages.c nsurl.c talloc.c url.c \
diff --git a/css/css.c b/css/css.c
index 2cd111b..8923bdc 100644
--- a/css/css.c
+++ b/css/css.c
@@ -36,6 +36,30 @@
/* Define to trace import fetches */
#undef NSCSS_IMPORT_TRACE
+struct content_css_data;
+
+/**
+ * Type of callback called when a CSS object has finished
+ *
+ * \param css CSS object that has completed
+ * \param pw Client-specific data
+ */
+typedef void (*nscss_done_callback)(struct content_css_data *css, void *pw);
+
+/**
+ * CSS content data
+ */
+struct content_css_data
+{
+ css_stylesheet *sheet; /**< Stylesheet object */
+ char *charset; /**< Character set of stylesheet */
+ struct nscss_import *imports; /**< Array of imported sheets */
+ uint32_t import_count; /**< Number of sheets imported */
+ uint32_t next_to_register; /**< Index of next import to register */
+ nscss_done_callback done; /**< Completion callback */
+ void *pw; /**< Client data */
+};
+
/**
* CSS content data
*/
@@ -67,6 +91,14 @@ static nserror nscss_clone(const struct content *old, struct content **newc);
static bool nscss_matches_quirks(const struct content *c, bool quirks);
static content_type nscss_content_type(void);
+static nserror nscss_create_css_data(struct content_css_data *c,
+ const char *url, const char *charset, bool quirks,
+ nscss_done_callback done, void *pw);
+static css_error nscss_process_css_data(struct content_css_data *c, const char *data,
+ unsigned int size);
+static css_error nscss_convert_css_data(struct content_css_data *c);
+static void nscss_destroy_css_data(struct content_css_data *c);
+
static void nscss_content_done(struct content_css_data *css, void *pw);
static css_error nscss_handle_import(void *pw, css_stylesheet *parent,
lwc_string *url, uint64_t media);
@@ -155,7 +187,7 @@ nserror nscss_create(const content_handler *handler,
* \param pw Client data for \a done
* \return NSERROR_OK on success, NSERROR_NOMEM on memory exhaustion
*/
-nserror nscss_create_css_data(struct content_css_data *c,
+static nserror nscss_create_css_data(struct content_css_data *c,
const char *url, const char *charset, bool quirks,
nscss_done_callback done, void *pw)
{
@@ -227,8 +259,8 @@ bool nscss_process_data(struct content *c, const char *data, unsigned int size)
* \param size Number of bytes to process
* \return CSS_OK on success, appropriate error otherwise
*/
-css_error nscss_process_css_data(struct content_css_data *c, const char *data,
- unsigned int size)
+static css_error nscss_process_css_data(struct content_css_data *c,
+ const char *data, unsigned int size)
{
return css_stylesheet_append_data(c->sheet,
(const uint8_t *) data, size);
@@ -262,7 +294,7 @@ bool nscss_convert(struct content *c)
* \param c CSS data to convert
* \return CSS error
*/
-css_error nscss_convert_css_data(struct content_css_data *c)
+static css_error nscss_convert_css_data(struct content_css_data *c)
{
css_error error;
@@ -310,7 +342,7 @@ void nscss_destroy(struct content *c)
*
* \param c CSS data to clean up
*/
-void nscss_destroy_css_data(struct content_css_data *c)
+static void nscss_destroy_css_data(struct content_css_data *c)
{
uint32_t i;
diff --git a/css/css.h b/css/css.h
index dc6053f..be8d4bc 100644
--- a/css/css.h
+++ b/css/css.h
@@ -25,33 +25,7 @@
#include "utils/errors.h"
-struct content;
-struct content_css_data;
struct hlcache_handle;
-struct http_parameter;
-struct nscss_import;
-
-/**
- * Type of callback called when a CSS object has finished
- *
- * \param css CSS object that has completed
- * \param pw Client-specific data
- */
-typedef void (*nscss_done_callback)(struct content_css_data *css, void *pw);
-
-/**
- * CSS content data
- */
-struct content_css_data
-{
- css_stylesheet *sheet; /**< Stylesheet object */
- char *charset; /**< Character set of stylesheet */
- struct nscss_import *imports; /**< Array of imported sheets */
- uint32_t import_count; /**< Number of sheets imported */
- uint32_t next_to_register; /**< Index of next import to register */
- nscss_done_callback done; /**< Completion callback */
- void *pw; /**< Client data */
-};
/**
* Imported stylesheet record
@@ -63,14 +37,6 @@ struct nscss_import {
nserror nscss_init(void);
-nserror nscss_create_css_data(struct content_css_data *c,
- const char *url, const char *charset, bool quirks,
- nscss_done_callback done, void *pw);
-css_error nscss_process_css_data(struct content_css_data *c, const char *data,
- unsigned int size);
-css_error nscss_convert_css_data(struct content_css_data *c);
-void nscss_destroy_css_data(struct content_css_data *c);
-
css_stylesheet *nscss_get_stylesheet(struct hlcache_handle *h);
struct nscss_import *nscss_get_imports(struct hlcache_handle *h, uint32_t *n);
diff --git a/desktop/browser.c b/desktop/browser.c
index fa0e6d1..1eed1e0 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -1954,10 +1954,8 @@ void browser_window_reload(struct browser_window *bw, bool all)
sheets = html_get_stylesheets(c, &count);
for (i = STYLESHEET_START; i != count; i++) {
- if (sheets[i].type == HTML_STYLESHEET_EXTERNAL &&
- sheets[i].data.external != NULL) {
- content_invalidate_reuse_data(
- sheets[i].data.external);
+ if (sheets[i].sheet != NULL) {
+ content_invalidate_reuse_data(sheets[i].sheet);
}
}
}
diff --git a/desktop/save_complete.c b/desktop/save_complete.c
index 621544d..0c67654 100644
--- a/desktop/save_complete.c
+++ b/desktop/save_complete.c
@@ -361,19 +361,10 @@ static bool save_complete_save_imported_sheets(save_complete_ctx *ctx,
static bool save_complete_save_html_stylesheet(save_complete_ctx *ctx,
struct html_stylesheet *sheet)
{
- if (sheet->type == HTML_STYLESHEET_INTERNAL) {
- if (save_complete_save_imported_sheets(ctx,
- sheet->data.internal.data->imports,
- sheet->data.internal.data->import_count) == false)
- return false;
-
- return true;
- }
-
- if (sheet->data.external == NULL)
+ if (sheet->sheet == NULL)
return true;
- return save_complete_save_stylesheet(ctx, sheet->data.external);
+ return save_complete_save_stylesheet(ctx, sheet->sheet);
}
static bool save_complete_save_html_stylesheets(save_complete_ctx *ctx,
diff --git a/render/box.h b/render/box.h
index 0953d9f..1ce26c2 100644
--- a/render/box.h
+++ b/render/box.h
@@ -94,6 +94,7 @@
#include "utils/nsurl.h"
#include "utils/types.h"
+struct content;
struct box;
struct browser_window;
struct column;
diff --git a/render/html.h b/render/html.h
index de9e294..a17e4a5 100644
--- a/render/html.h
+++ b/render/html.h
@@ -57,15 +57,8 @@ struct selection;
*/
struct html_stylesheet {
/** Type of sheet */
- enum { HTML_STYLESHEET_EXTERNAL, HTML_STYLESHEET_INTERNAL } type;
struct dom_node *node; /**< dom node associated with sheet */
- union {
- struct hlcache_handle *external;
- struct {
- struct content_css_data *data;
- bool done;
- } internal;
- } data; /**< Sheet data */
+ struct hlcache_handle *sheet;
};
/**
diff --git a/render/html_css.c b/render/html_css.c
index a1e9cd0..b98632e 100644
--- a/render/html_css.c
+++ b/render/html_css.c
@@ -73,7 +73,7 @@ static nserror css_error_to_nserror(css_error error)
}
/**
- * Callback for fetchcache() for linked stylesheets.
+ * Callback for fetchcache() for stylesheets.
*/
static nserror
@@ -89,8 +89,7 @@ html_convert_css_callback(hlcache_handle *css,
for (i = 0, s = parent->stylesheets;
i != parent->stylesheet_count;
i++, s++) {
- if (s->type == HTML_STYLESHEET_EXTERNAL &&
- s->data.external == css)
+ if (s->sheet == css)
break;
}
@@ -115,7 +114,7 @@ html_convert_css_callback(hlcache_handle *css,
nsurl_access(hlcache_handle_get_url(css)),
event->data.error));
hlcache_handle_release(css);
- s->data.external = NULL;
+ s->sheet = NULL;
parent->base.active--;
LOG(("%d fetches active", parent->base.active));
content_add_error(&parent->base, "?", 0);
@@ -170,13 +169,8 @@ nserror html_css_free_stylesheets(html_content *html)
unsigned int i;
for (i = 0; i != html->stylesheet_count; i++) {
- if ((html->stylesheets[i].type == HTML_STYLESHEET_EXTERNAL) &&
- (html->stylesheets[i].data.external != NULL)) {
- hlcache_handle_release(html->stylesheets[i].data.external);
- } else if ((html->stylesheets[i].type == HTML_STYLESHEET_INTERNAL) &&
- (html->stylesheets[i].data.internal.data != NULL)) {
- nscss_destroy_css_data(html->stylesheets[i].data.internal.data);
- free(html->stylesheets[i].data.internal.data);
+ if (html->stylesheets[i].sheet != NULL) {
+ hlcache_handle_release(html->stylesheets[i].sheet);
}
}
free(html->stylesheets);
@@ -200,7 +194,7 @@ nserror html_css_quirks_stylesheets(html_content *c)
0, content_get_url(&c->base), NULL,
html_convert_css_callback, c, &child,
CONTENT_CSS,
- &c->stylesheets[STYLESHEET_QUIRKS].data.external);
+ &c->stylesheets[STYLESHEET_QUIRKS].sheet);
if (ns_error != NSERROR_OK) {
return ns_error;
}
@@ -231,14 +225,10 @@ nserror html_css_new_stylesheets(html_content *c)
return NSERROR_NOMEM;
}
- c->stylesheets[STYLESHEET_BASE].type = HTML_STYLESHEET_EXTERNAL;
- c->stylesheets[STYLESHEET_BASE].data.external = NULL;
- c->stylesheets[STYLESHEET_QUIRKS].type = HTML_STYLESHEET_EXTERNAL;
- c->stylesheets[STYLESHEET_QUIRKS].data.external = NULL;
- c->stylesheets[STYLESHEET_ADBLOCK].type = HTML_STYLESHEET_EXTERNAL;
- c->stylesheets[STYLESHEET_ADBLOCK].data.external = NULL;
- c->stylesheets[STYLESHEET_USER].type = HTML_STYLESHEET_EXTERNAL;
- c->stylesheets[STYLESHEET_USER].data.external = NULL;
+ c->stylesheets[STYLESHEET_BASE].sheet = NULL;
+ c->stylesheets[STYLESHEET_QUIRKS].sheet = NULL;
+ c->stylesheets[STYLESHEET_ADBLOCK].sheet = NULL;
+ c->stylesheets[STYLESHEET_USER].sheet = NULL;
c->stylesheet_count = STYLESHEET_START;
child.charset = c->encoding;
@@ -247,7 +237,7 @@ nserror html_css_new_stylesheets(html_content *c)
ns_error = hlcache_handle_retrieve(html_default_stylesheet_url, 0,
content_get_url(&c->base), NULL,
html_convert_css_callback, c, &child, CONTENT_CSS,
- &c->stylesheets[STYLESHEET_BASE].data.external);
+ &c->stylesheets[STYLESHEET_BASE].sheet);
if (ns_error != NSERROR_OK) {
return ns_error;
}
@@ -260,8 +250,7 @@ nserror html_css_new_stylesheets(html_content *c)
ns_error = hlcache_handle_retrieve(html_adblock_stylesheet_url,
0, content_get_url(&c->base), NULL,
html_convert_css_callback, c, &child, CONTENT_CSS,
- &c->stylesheets[STYLESHEET_ADBLOCK].
- data.external);
+ &c->stylesheets[STYLESHEET_ADBLOCK].sheet);
if (ns_error != NSERROR_OK) {
return ns_error;
}
@@ -274,7 +263,7 @@ nserror html_css_new_stylesheets(html_content *c)
ns_error = hlcache_handle_retrieve(html_user_stylesheet_url, 0,
content_get_url(&c->base), NULL,
html_convert_css_callback, c, &child, CONTENT_CSS,
- &c->stylesheets[STYLESHEET_USER].data.external);
+ &c->stylesheets[STYLESHEET_USER].sheet);
if (ns_error != NSERROR_OK) {
return ns_error;
}
@@ -285,141 +274,57 @@ nserror html_css_new_stylesheets(html_content *c)
return ns_error;
}
-/**
- * Handle notification of inline style completion
- *
- * \param css Inline style object
- * \param pw Private data
- */
-static void html_inline_style_done(struct content_css_data *css, void *pw)
-{
- html_content *html = pw;
- size_t i;
-
- LOG(("Inline style %p done", css));
-
- /* Search HTML content for sheet */
- for (i = 0; i < html->stylesheet_count; i++) {
- if (html->stylesheets[i].type == HTML_STYLESHEET_INTERNAL &&
- html->stylesheets[i].data.internal.data == css)
- break;
- }
-
- /* Not found: must have been replaced, so destroy it */
- if (i == html->stylesheet_count) {
- LOG(("Not found: destroying"));
- nscss_destroy_css_data(css);
- free(css);
- } else {
- html->stylesheets[i].data.internal.done = true;
- }
-
- html->base.active--;
- LOG(("%d fetches active", html->base.active));
- if (html->base.active == 0) {
- html_begin_conversion(html);
- }
-}
-
static nserror
html_stylesheet_from_domnode(html_content *c,
- struct html_stylesheet *s,
- dom_node *node)
+ dom_node *node,
+ hlcache_handle **sheet)
{
- dom_node *child, *next;
+ hlcache_child_context child;
+ dom_string *style;
+ nsurl *url;
dom_exception exc;
- struct content_css_data *sheet, *old_sheet;
- bool old_sheet_done;
nserror error;
- css_error csserror;
+ uint32_t key;
+ char urlbuf[64];
- /* create stylesheet */
- sheet = calloc(1, sizeof(struct content_css_data));
- if (sheet == NULL) {
- return NSERROR_NOMEM;
+ child.charset = c->encoding;
+ child.quirks = c->base.quirks;
+
+ exc = dom_node_get_text_content(node, &style);
+ if ((exc != DOM_NO_ERR) || (style == NULL)) {
+ LOG(("No text content"));
+ return NSERROR_OK;
}
- error = nscss_create_css_data(sheet,
- nsurl_access(c->base_url), NULL, c->quirks,
- html_inline_style_done, c);
+ error = html_css_fetcher_add_item(style, &key);
if (error != NSERROR_OK) {
- free(sheet);
+ dom_string_unref(style);
return error;
}
- exc = dom_node_get_first_child(node, &child);
- if (exc != DOM_NO_ERR) {
- nscss_destroy_css_data(sheet);
- free(sheet);
- return NSERROR_DOM;
- }
-
- while (child != NULL) {
- dom_string *data;
-
- exc = dom_node_get_text_content(child, &data);
- if (exc != DOM_NO_ERR) {
- dom_node_unref(child);
- nscss_destroy_css_data(sheet);
- free(sheet);
- return NSERROR_DOM;
- }
-
- if (nscss_process_css_data(sheet,
- dom_string_data(data),
- dom_string_byte_length(data)) == false) {
- dom_string_unref(data);
- dom_node_unref(child);
- nscss_destroy_css_data(sheet);
- free(sheet);
- return NSERROR_CSS;
- }
+ dom_string_unref(style);
- dom_string_unref(data);
+ snprintf(urlbuf, sizeof(urlbuf), "x-ns-css:%u", key);
- exc = dom_node_get_next_sibling(child, &next);
- if (exc != DOM_NO_ERR) {
- dom_node_unref(child);
- nscss_destroy_css_data(sheet);
- free(sheet);
- return NSERROR_DOM;
- }
+ error = nsurl_create(urlbuf, &url);
+ if (error != NSERROR_OK) {
+ return error;
+ }
- dom_node_unref(child);
- child = next;
+ error = hlcache_handle_retrieve(url, 0,
+ content_get_url(&c->base), NULL,
+ html_convert_css_callback, c, &child, CONTENT_CSS,
+ sheet);
+ if (error != NSERROR_OK) {
+ nsurl_unref(url);
+ return error;
}
+ nsurl_unref(url);
+
c->base.active++;
LOG(("%d fetches active", c->base.active));
- LOG(("Updating sheet %p with %p", s->data.internal, sheet));
-
- /* Update index */
- old_sheet = s->data.internal.data;
- old_sheet_done = s->data.internal.done;
- s->data.internal.data = sheet;
- s->data.internal.done = false;
-
- /* Convert the content -- manually, as we want the result */
- csserror = nscss_convert_css_data(sheet);
- if (csserror != CSS_OK) {
- /* conversion failed */
- c->base.active--;
- LOG(("%d fetches active", c->base.active));
- nscss_destroy_css_data(sheet);
- free(sheet);
- s->data.internal.data = old_sheet;
- s->data.internal.done = old_sheet_done;
- return css_error_to_nserror(csserror);
- }
-
- /* Clean up old sheet if it was already complete */
- if (old_sheet != NULL && old_sheet_done) {
- LOG(("Destroying old sheet %p", old_sheet));
- nscss_destroy_css_data(old_sheet);
- free(old_sheet);
- }
-
return NSERROR_OK;
}
@@ -472,10 +377,8 @@ html_create_style_element(html_content *c, dom_node *style)
}
c->stylesheets = stylesheets;
- c->stylesheets[c->stylesheet_count].type = HTML_STYLESHEET_INTERNAL;
c->stylesheets[c->stylesheet_count].node = style;
- c->stylesheets[c->stylesheet_count].data.internal.data = NULL;
- c->stylesheets[c->stylesheet_count].data.internal.done = false;
+ c->stylesheets[c->stylesheet_count].sheet = NULL;
c->stylesheet_count++;
return c->stylesheets + (c->stylesheet_count - 1);
@@ -486,11 +389,11 @@ bool html_css_update_style(html_content *c, dom_node *style)
nserror error;
unsigned int i;
struct html_stylesheet *s;
+ hlcache_handle *sheet = NULL;
/* Find sheet */
for (i = 0, s = c->stylesheets; i != c->stylesheet_count; i++, s++) {
- if ((s->type == HTML_STYLESHEET_INTERNAL) &&
- (s->node == style))
+ if (s->node == style)
break;
}
if (i == c->stylesheet_count) {
@@ -504,13 +407,30 @@ bool html_css_update_style(html_content *c, dom_node *style)
LOG(("Found sheet %p slot %d for node %p", s, i, style));
- error = html_stylesheet_from_domnode(c, s, style);
+ error = html_stylesheet_from_domnode(c, style, &sheet);
if (error != NSERROR_OK) {
LOG(("Failed to update sheet"));
content_broadcast_errorcode(&c->base, error);
return false;
}
+ if (sheet != NULL) {
+ LOG(("Updating sheet %p with %p", s->sheet, sheet));
+
+ if (s->sheet != NULL) {
+ switch (content_get_status(s->sheet)) {
+ case CONTENT_STATUS_DONE:
+ break;
+ default:
+ hlcache_handle_abort(s->sheet);
+ c->base.active--;
+ LOG(("%d fetches active", c->base.active));
+ }
+ hlcache_handle_release(s->sheet);
+ }
+ s->sheet = sheet;
+ }
+
return true;
}
@@ -588,7 +508,6 @@ bool html_css_process_link(html_content *htmlc, dom_node *node)
}
htmlc->stylesheets = stylesheets;
- htmlc->stylesheets[htmlc->stylesheet_count].type = HTML_STYLESHEET_EXTERNAL;
/* start fetch */
child.charset = htmlc->encoding;
@@ -602,7 +521,7 @@ bool html_css_process_link(html_content *htmlc, dom_node *node)
htmlc,
&child,
CONTENT_CSS,
- &htmlc->stylesheets[htmlc->stylesheet_count].data.external);
+ &htmlc->stylesheets[htmlc->stylesheet_count].sheet);
nsurl_unref(joined);
@@ -629,7 +548,7 @@ html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx)
css_select_ctx *select_ctx;
/* check that the base stylesheet loaded; layout fails without it */
- if (c->stylesheets[STYLESHEET_BASE].data.external == NULL) {
+ if (c->stylesheets[STYLESHEET_BASE].sheet == NULL) {
return NSERROR_CSS_BASE;
}
@@ -651,11 +570,8 @@ html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx)
origin = CSS_ORIGIN_USER;
}
- if ((hsheet->type == HTML_STYLESHEET_EXTERNAL) &&
- (hsheet->data.external != NULL)) {
- sheet = nscss_get_stylesheet(hsheet->data.external);
- } else if (hsheet->type == HTML_STYLESHEET_INTERNAL) {
- sheet = hsheet->data.internal.data->sheet;
+ if (hsheet->sheet != NULL) {
+ sheet = nscss_get_stylesheet(hsheet->sheet);
}
if (sheet != NULL) {
@@ -679,6 +595,8 @@ nserror html_css_init(void)
{
nserror error;
+ html_css_fetcher_register();
+
error = nsurl_create("resource:default.css",
&html_default_stylesheet_url);
if (error != NSERROR_OK)
diff --git a/render/html_css_fetcher.c b/render/html_css_fetcher.c
new file mode 100644
index 0000000..31e2cba
--- /dev/null
+++ b/render/html_css_fetcher.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2008 Rob Kendrick <rjek(a)netsurf-browser.org>
+ * Copyright 2013 John-Mark Bell <jmb(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <dom/dom.h>
+
+#include <libwapcaplet/libwapcaplet.h>
+
+#include "utils/config.h"
+#include "content/fetch.h"
+#include "render/html_internal.h"
+#include "utils/log.h"
+#include "utils/ring.h"
+#include "utils/nsurl.h"
+#include "utils/utils.h"
+
+typedef struct html_css_fetcher_item {
+ uint32_t key;
+ dom_string *data;
+
+ struct html_css_fetcher_item *r_next, *r_prev;
+} html_css_fetcher_item;
+
+typedef struct html_css_fetcher_context {
+ struct fetch *parent_fetch;
+
+ nsurl *url;
+ html_css_fetcher_item *item;
+
+ bool aborted;
+ bool locked;
+
+ struct html_css_fetcher_context *r_next, *r_prev;
+} html_css_fetcher_context;
+
+static uint32_t current_key = 0;
+static html_css_fetcher_item *items = NULL;
+static html_css_fetcher_context *ring = NULL;
+
+static bool html_css_fetcher_initialise(lwc_string *scheme)
+{
+ LOG(("html_css_fetcher_initialise called for %s", lwc_string_data(scheme)));
+ return true;
+}
+
+static void html_css_fetcher_finalise(lwc_string *scheme)
+{
+ LOG(("html_css_fetcher_finalise called for %s", lwc_string_data(scheme)));
+}
+
+static bool html_css_fetcher_can_fetch(const nsurl *url)
+{
+ return true;
+}
+
+static void *html_css_fetcher_setup(struct fetch *parent_fetch, nsurl *url,
+ bool only_2xx, bool downgrade_tls, const char *post_urlenc,
+ const struct fetch_multipart_data *post_multipart,
+ const char **headers)
+{
+ html_css_fetcher_context *ctx;
+ lwc_string *path;
+ uint32_t key;
+ html_css_fetcher_item *item, *found = NULL;
+
+ /* format of a x-ns-css URL is:
+ * x-ns-url:<key>
+ * Where key is an unsigned 32bit integer
+ */
+
+ path = nsurl_get_component(url, NSURL_PATH);
+ /* The path must exist */
+ if (path == NULL) {
+ return NULL;
+ }
+
+ key = strtoul(lwc_string_data(path), NULL, 10);
+
+ lwc_string_unref(path);
+
+ /* There must be at least one item */
+ if (items == NULL) {
+ return NULL;
+ }
+
+ item = items;
+ do {
+ if (item->key == key) {
+ found = item;
+ break;
+ }
+
+ item = item->r_next;
+ } while (item != items);
+
+ /* We must have found the item */
+ if (found == NULL) {
+ return NULL;
+ }
+
+ ctx = calloc(1, sizeof(*ctx));
+ if (ctx == NULL)
+ return NULL;
+
+ ctx->parent_fetch = parent_fetch;
+ ctx->url = nsurl_ref(url);
+ ctx->item = found;
+
+ RING_INSERT(ring, ctx);
+
+ return ctx;
+}
+
+static bool html_css_fetcher_start(void *ctx)
+{
+ return true;
+}
+
+static void html_css_fetcher_free(void *ctx)
+{
+ html_css_fetcher_context *c = ctx;
+
+ nsurl_unref(c->url);
+ if (c->item != NULL) {
+ dom_string_unref(c->item->data);
+ RING_REMOVE(items, c->item);
+ free(c->item);
+ }
+ RING_REMOVE(ring, c);
+ free(ctx);
+}
+
+static void html_css_fetcher_abort(void *ctx)
+{
+ html_css_fetcher_context *c = ctx;
+
+ /* To avoid the poll loop having to deal with the fetch context
+ * disappearing from under it, we simply flag the abort here.
+ * The poll loop itself will perform the appropriate cleanup.
+ */
+ c->aborted = true;
+}
+
+static void html_css_fetcher_send_callback(const fetch_msg *msg,
+ html_css_fetcher_context *c)
+{
+ c->locked = true;
+ fetch_send_callback(msg, c->parent_fetch);
+ c->locked = false;
+}
+
+static void html_css_fetcher_poll(lwc_string *scheme)
+{
+ fetch_msg msg;
+ html_css_fetcher_context *c, *next;
+
+ if (ring == NULL) return;
+
+ /* Iterate over ring, processing each pending fetch */
+ c = ring;
+ do {
+ /* Ignore fetches that have been flagged as locked.
+ * This allows safe re-entrant calls to this function.
+ * Re-entrancy can occur if, as a result of a callback,
+ * the interested party causes fetch_poll() to be called
+ * again.
+ */
+ if (c->locked == true) {
+ next = c->r_next;
+ continue;
+ }
+
+ /* Only process non-aborted fetches */
+ if (c->aborted) {
+ /* Nothing to do */
+ assert(c->locked == false);
+ } else if (c->item != NULL) {
+ char header[64];
+
+ fetch_set_http_code(c->parent_fetch, 200);
+
+ /* Any callback can result in the fetch being aborted.
+ * Therefore, we _must_ check for this after _every_
+ * call to html_css_fetcher_send_callback().
+ */
+ snprintf(header, sizeof header,
+ "Content-Type: text/css; charset=utf-8");
+ msg.type = FETCH_HEADER;
+ msg.data.header_or_data.buf = (const uint8_t *) header;
+ msg.data.header_or_data.len = strlen(header);
+ html_css_fetcher_send_callback(&msg, c);
+
+ if (c->aborted == false) {
+ snprintf(header, sizeof header,
+ "Content-Length: %"SSIZET_FMT,
+ dom_string_byte_length(c->item->data));
+ msg.type = FETCH_HEADER;
+ msg.data.header_or_data.buf =
+ (const uint8_t *) header;
+ msg.data.header_or_data.len = strlen(header);
+ html_css_fetcher_send_callback(&msg, c);
+ }
+
+ if (c->aborted == false) {
+ msg.type = FETCH_DATA;
+ msg.data.header_or_data.buf =
+ (const uint8_t *)
+ dom_string_data(c->item->data);
+ msg.data.header_or_data.len =
+ dom_string_byte_length(c->item->data);
+ html_css_fetcher_send_callback(&msg, c);
+ }
+
+ if (c->aborted == false) {
+ msg.type = FETCH_FINISHED;
+ html_css_fetcher_send_callback(&msg, c);
+ }
+ } else {
+ LOG(("Processing of %s failed!",
+ nsurl_access(c->url)));
+
+ /* Ensure that we're unlocked here. If we aren't,
+ * then html_css_fetcher_process() is broken.
+ */
+ assert(c->locked == false);
+ }
+
+ /* Compute next fetch item at the last possible moment as
+ * processing this item may have added to the ring.
+ */
+ next = c->r_next;
+
+ fetch_remove_from_queues(c->parent_fetch);
+ fetch_free(c->parent_fetch);
+
+ /* Advance to next ring entry, exiting if we've reached
+ * the start of the ring or the ring has become empty
+ */
+ } while ( (c = next) != ring && ring != NULL);
+}
+
+void html_css_fetcher_register(void)
+{
+ lwc_string *scheme;
+
+ if (lwc_intern_string("x-ns-css", SLEN("x-ns-css"),
+ &scheme) != lwc_error_ok) {
+ die("Failed to initialise the fetch module "
+ "(couldn't intern \"x-ns-css\").");
+ }
+
+ fetch_add_fetcher(scheme,
+ html_css_fetcher_initialise,
+ html_css_fetcher_can_fetch,
+ html_css_fetcher_setup,
+ html_css_fetcher_start,
+ html_css_fetcher_abort,
+ html_css_fetcher_free,
+ html_css_fetcher_poll,
+ html_css_fetcher_finalise);
+}
+
+nserror html_css_fetcher_add_item(dom_string *data, uint32_t *key)
+{
+ html_css_fetcher_item *item = malloc(sizeof(*item));
+
+ if (item == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ *key = item->key = current_key++;
+ item->data = dom_string_ref(data);
+
+ RING_INSERT(items, item);
+
+ return NSERROR_OK;
+}
+
diff --git a/render/html_internal.h b/render/html_internal.h
index 428cd39..f92948b 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -270,6 +270,10 @@ bool html_css_update_style(html_content *c, dom_node *style);
nserror html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx);
+/* in render/html_css_fetcher.c */
+void html_css_fetcher_register(void);
+nserror html_css_fetcher_add_item(dom_string *data, uint32_t *key);
+
/* in render/html_object.c */
/**
-----------------------------------------------------------------------
Summary of changes:
Makefile.sources | 4 +-
css/css.c | 52 +++++++-
css/css.h | 34 -----
desktop/browser.c | 9 +-
desktop/save_complete.c | 13 +--
render/box.h | 1 +
render/html.h | 9 +-
render/html_css.c | 224 ++++++++++----------------------
render/html_css_fetcher.c | 314 +++++++++++++++++++++++++++++++++++++++++++++
render/html_internal.h | 8 +-
10 files changed, 447 insertions(+), 221 deletions(-)
create mode 100644 render/html_css_fetcher.c
diff --git a/Makefile.sources b/Makefile.sources
index b53d7c5..ab71ff3 100644
--- a/Makefile.sources
+++ b/Makefile.sources
@@ -14,8 +14,8 @@ S_CSS := css.c dump.c internal.c select.c utils.c
S_RENDER := box.c box_construct.c box_normalise.c box_textarea.c \
font.c form.c imagemap.c layout.c list.c search.c table.c \
textplain.c \
- html.c html_css.c html_script.c html_interaction.c \
- html_redraw.c html_forms.c html_object.c
+ html.c html_css.c html_css_fetcher.c html_script.c \
+ html_interaction.c html_redraw.c html_forms.c html_object.c
S_UTILS := base64.c corestrings.c filename.c filepath.c hashtable.c \
libdom.c locale.c log.c messages.c nsurl.c talloc.c url.c \
diff --git a/css/css.c b/css/css.c
index 2cd111b..0410f18 100644
--- a/css/css.c
+++ b/css/css.c
@@ -36,6 +36,30 @@
/* Define to trace import fetches */
#undef NSCSS_IMPORT_TRACE
+struct content_css_data;
+
+/**
+ * Type of callback called when a CSS object has finished
+ *
+ * \param css CSS object that has completed
+ * \param pw Client-specific data
+ */
+typedef void (*nscss_done_callback)(struct content_css_data *css, void *pw);
+
+/**
+ * CSS content data
+ */
+struct content_css_data
+{
+ css_stylesheet *sheet; /**< Stylesheet object */
+ char *charset; /**< Character set of stylesheet */
+ struct nscss_import *imports; /**< Array of imported sheets */
+ uint32_t import_count; /**< Number of sheets imported */
+ uint32_t next_to_register; /**< Index of next import to register */
+ nscss_done_callback done; /**< Completion callback */
+ void *pw; /**< Client data */
+};
+
/**
* CSS content data
*/
@@ -67,6 +91,14 @@ static nserror nscss_clone(const struct content *old, struct content **newc);
static bool nscss_matches_quirks(const struct content *c, bool quirks);
static content_type nscss_content_type(void);
+static nserror nscss_create_css_data(struct content_css_data *c,
+ const char *url, const char *charset, bool quirks,
+ nscss_done_callback done, void *pw);
+static css_error nscss_process_css_data(struct content_css_data *c, const char *data,
+ unsigned int size);
+static css_error nscss_convert_css_data(struct content_css_data *c);
+static void nscss_destroy_css_data(struct content_css_data *c);
+
static void nscss_content_done(struct content_css_data *css, void *pw);
static css_error nscss_handle_import(void *pw, css_stylesheet *parent,
lwc_string *url, uint64_t media);
@@ -97,6 +129,7 @@ nserror nscss_create(const content_handler *handler,
{
nscss_content *result;
const char *charset = NULL;
+ const char *xnsbase = NULL;
lwc_string *charset_value = NULL;
union content_msg_data msg_data;
nserror error;
@@ -123,9 +156,14 @@ nserror nscss_create(const content_handler *handler,
charset = lwc_string_data(charset_value);
}
+ /* Compute base URL for stylesheet */
+ xnsbase = llcache_handle_get_header(llcache, "X-NS-Base");
+ if (xnsbase == NULL) {
+ xnsbase = nsurl_access(content_get_url(&result->base));
+ }
+
error = nscss_create_css_data(&result->data,
- nsurl_access(content_get_url(&result->base)),
- charset, result->base.quirks,
+ xnsbase, charset, result->base.quirks,
nscss_content_done, result);
if (error != NSERROR_OK) {
msg_data.error = messages_get("NoMemory");
@@ -155,7 +193,7 @@ nserror nscss_create(const content_handler *handler,
* \param pw Client data for \a done
* \return NSERROR_OK on success, NSERROR_NOMEM on memory exhaustion
*/
-nserror nscss_create_css_data(struct content_css_data *c,
+static nserror nscss_create_css_data(struct content_css_data *c,
const char *url, const char *charset, bool quirks,
nscss_done_callback done, void *pw)
{
@@ -227,8 +265,8 @@ bool nscss_process_data(struct content *c, const char *data, unsigned int size)
* \param size Number of bytes to process
* \return CSS_OK on success, appropriate error otherwise
*/
-css_error nscss_process_css_data(struct content_css_data *c, const char *data,
- unsigned int size)
+static css_error nscss_process_css_data(struct content_css_data *c,
+ const char *data, unsigned int size)
{
return css_stylesheet_append_data(c->sheet,
(const uint8_t *) data, size);
@@ -262,7 +300,7 @@ bool nscss_convert(struct content *c)
* \param c CSS data to convert
* \return CSS error
*/
-css_error nscss_convert_css_data(struct content_css_data *c)
+static css_error nscss_convert_css_data(struct content_css_data *c)
{
css_error error;
@@ -310,7 +348,7 @@ void nscss_destroy(struct content *c)
*
* \param c CSS data to clean up
*/
-void nscss_destroy_css_data(struct content_css_data *c)
+static void nscss_destroy_css_data(struct content_css_data *c)
{
uint32_t i;
diff --git a/css/css.h b/css/css.h
index dc6053f..be8d4bc 100644
--- a/css/css.h
+++ b/css/css.h
@@ -25,33 +25,7 @@
#include "utils/errors.h"
-struct content;
-struct content_css_data;
struct hlcache_handle;
-struct http_parameter;
-struct nscss_import;
-
-/**
- * Type of callback called when a CSS object has finished
- *
- * \param css CSS object that has completed
- * \param pw Client-specific data
- */
-typedef void (*nscss_done_callback)(struct content_css_data *css, void *pw);
-
-/**
- * CSS content data
- */
-struct content_css_data
-{
- css_stylesheet *sheet; /**< Stylesheet object */
- char *charset; /**< Character set of stylesheet */
- struct nscss_import *imports; /**< Array of imported sheets */
- uint32_t import_count; /**< Number of sheets imported */
- uint32_t next_to_register; /**< Index of next import to register */
- nscss_done_callback done; /**< Completion callback */
- void *pw; /**< Client data */
-};
/**
* Imported stylesheet record
@@ -63,14 +37,6 @@ struct nscss_import {
nserror nscss_init(void);
-nserror nscss_create_css_data(struct content_css_data *c,
- const char *url, const char *charset, bool quirks,
- nscss_done_callback done, void *pw);
-css_error nscss_process_css_data(struct content_css_data *c, const char *data,
- unsigned int size);
-css_error nscss_convert_css_data(struct content_css_data *c);
-void nscss_destroy_css_data(struct content_css_data *c);
-
css_stylesheet *nscss_get_stylesheet(struct hlcache_handle *h);
struct nscss_import *nscss_get_imports(struct hlcache_handle *h, uint32_t *n);
diff --git a/desktop/browser.c b/desktop/browser.c
index fa0e6d1..45f33ab 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -844,10 +844,11 @@ nserror browser_window_navigate(struct browser_window *bw,
hlcache_child_context child;
nserror error;
- LOG(("bw %p, url %s", bw, url));
assert(bw);
assert(url);
+ LOG(("bw %p, url %s", bw, nsurl_access(url)));
+
/* don't allow massively nested framesets */
for (cur = bw; cur->parent; cur = cur->parent) {
depth++;
@@ -1954,10 +1955,8 @@ void browser_window_reload(struct browser_window *bw, bool all)
sheets = html_get_stylesheets(c, &count);
for (i = STYLESHEET_START; i != count; i++) {
- if (sheets[i].type == HTML_STYLESHEET_EXTERNAL &&
- sheets[i].data.external != NULL) {
- content_invalidate_reuse_data(
- sheets[i].data.external);
+ if (sheets[i].sheet != NULL) {
+ content_invalidate_reuse_data(sheets[i].sheet);
}
}
}
diff --git a/desktop/save_complete.c b/desktop/save_complete.c
index 621544d..0c67654 100644
--- a/desktop/save_complete.c
+++ b/desktop/save_complete.c
@@ -361,19 +361,10 @@ static bool save_complete_save_imported_sheets(save_complete_ctx *ctx,
static bool save_complete_save_html_stylesheet(save_complete_ctx *ctx,
struct html_stylesheet *sheet)
{
- if (sheet->type == HTML_STYLESHEET_INTERNAL) {
- if (save_complete_save_imported_sheets(ctx,
- sheet->data.internal.data->imports,
- sheet->data.internal.data->import_count) == false)
- return false;
-
- return true;
- }
-
- if (sheet->data.external == NULL)
+ if (sheet->sheet == NULL)
return true;
- return save_complete_save_stylesheet(ctx, sheet->data.external);
+ return save_complete_save_stylesheet(ctx, sheet->sheet);
}
static bool save_complete_save_html_stylesheets(save_complete_ctx *ctx,
diff --git a/render/box.h b/render/box.h
index 0953d9f..1ce26c2 100644
--- a/render/box.h
+++ b/render/box.h
@@ -94,6 +94,7 @@
#include "utils/nsurl.h"
#include "utils/types.h"
+struct content;
struct box;
struct browser_window;
struct column;
diff --git a/render/html.h b/render/html.h
index de9e294..a17e4a5 100644
--- a/render/html.h
+++ b/render/html.h
@@ -57,15 +57,8 @@ struct selection;
*/
struct html_stylesheet {
/** Type of sheet */
- enum { HTML_STYLESHEET_EXTERNAL, HTML_STYLESHEET_INTERNAL } type;
struct dom_node *node; /**< dom node associated with sheet */
- union {
- struct hlcache_handle *external;
- struct {
- struct content_css_data *data;
- bool done;
- } internal;
- } data; /**< Sheet data */
+ struct hlcache_handle *sheet;
};
/**
diff --git a/render/html_css.c b/render/html_css.c
index a1e9cd0..3eabec4 100644
--- a/render/html_css.c
+++ b/render/html_css.c
@@ -73,7 +73,7 @@ static nserror css_error_to_nserror(css_error error)
}
/**
- * Callback for fetchcache() for linked stylesheets.
+ * Callback for fetchcache() for stylesheets.
*/
static nserror
@@ -89,8 +89,7 @@ html_convert_css_callback(hlcache_handle *css,
for (i = 0, s = parent->stylesheets;
i != parent->stylesheet_count;
i++, s++) {
- if (s->type == HTML_STYLESHEET_EXTERNAL &&
- s->data.external == css)
+ if (s->sheet == css)
break;
}
@@ -115,7 +114,7 @@ html_convert_css_callback(hlcache_handle *css,
nsurl_access(hlcache_handle_get_url(css)),
event->data.error));
hlcache_handle_release(css);
- s->data.external = NULL;
+ s->sheet = NULL;
parent->base.active--;
LOG(("%d fetches active", parent->base.active));
content_add_error(&parent->base, "?", 0);
@@ -170,13 +169,8 @@ nserror html_css_free_stylesheets(html_content *html)
unsigned int i;
for (i = 0; i != html->stylesheet_count; i++) {
- if ((html->stylesheets[i].type == HTML_STYLESHEET_EXTERNAL) &&
- (html->stylesheets[i].data.external != NULL)) {
- hlcache_handle_release(html->stylesheets[i].data.external);
- } else if ((html->stylesheets[i].type == HTML_STYLESHEET_INTERNAL) &&
- (html->stylesheets[i].data.internal.data != NULL)) {
- nscss_destroy_css_data(html->stylesheets[i].data.internal.data);
- free(html->stylesheets[i].data.internal.data);
+ if (html->stylesheets[i].sheet != NULL) {
+ hlcache_handle_release(html->stylesheets[i].sheet);
}
}
free(html->stylesheets);
@@ -200,7 +194,7 @@ nserror html_css_quirks_stylesheets(html_content *c)
0, content_get_url(&c->base), NULL,
html_convert_css_callback, c, &child,
CONTENT_CSS,
- &c->stylesheets[STYLESHEET_QUIRKS].data.external);
+ &c->stylesheets[STYLESHEET_QUIRKS].sheet);
if (ns_error != NSERROR_OK) {
return ns_error;
}
@@ -231,14 +225,10 @@ nserror html_css_new_stylesheets(html_content *c)
return NSERROR_NOMEM;
}
- c->stylesheets[STYLESHEET_BASE].type = HTML_STYLESHEET_EXTERNAL;
- c->stylesheets[STYLESHEET_BASE].data.external = NULL;
- c->stylesheets[STYLESHEET_QUIRKS].type = HTML_STYLESHEET_EXTERNAL;
- c->stylesheets[STYLESHEET_QUIRKS].data.external = NULL;
- c->stylesheets[STYLESHEET_ADBLOCK].type = HTML_STYLESHEET_EXTERNAL;
- c->stylesheets[STYLESHEET_ADBLOCK].data.external = NULL;
- c->stylesheets[STYLESHEET_USER].type = HTML_STYLESHEET_EXTERNAL;
- c->stylesheets[STYLESHEET_USER].data.external = NULL;
+ c->stylesheets[STYLESHEET_BASE].sheet = NULL;
+ c->stylesheets[STYLESHEET_QUIRKS].sheet = NULL;
+ c->stylesheets[STYLESHEET_ADBLOCK].sheet = NULL;
+ c->stylesheets[STYLESHEET_USER].sheet = NULL;
c->stylesheet_count = STYLESHEET_START;
child.charset = c->encoding;
@@ -247,7 +237,7 @@ nserror html_css_new_stylesheets(html_content *c)
ns_error = hlcache_handle_retrieve(html_default_stylesheet_url, 0,
content_get_url(&c->base), NULL,
html_convert_css_callback, c, &child, CONTENT_CSS,
- &c->stylesheets[STYLESHEET_BASE].data.external);
+ &c->stylesheets[STYLESHEET_BASE].sheet);
if (ns_error != NSERROR_OK) {
return ns_error;
}
@@ -260,8 +250,7 @@ nserror html_css_new_stylesheets(html_content *c)
ns_error = hlcache_handle_retrieve(html_adblock_stylesheet_url,
0, content_get_url(&c->base), NULL,
html_convert_css_callback, c, &child, CONTENT_CSS,
- &c->stylesheets[STYLESHEET_ADBLOCK].
- data.external);
+ &c->stylesheets[STYLESHEET_ADBLOCK].sheet);
if (ns_error != NSERROR_OK) {
return ns_error;
}
@@ -274,7 +263,7 @@ nserror html_css_new_stylesheets(html_content *c)
ns_error = hlcache_handle_retrieve(html_user_stylesheet_url, 0,
content_get_url(&c->base), NULL,
html_convert_css_callback, c, &child, CONTENT_CSS,
- &c->stylesheets[STYLESHEET_USER].data.external);
+ &c->stylesheets[STYLESHEET_USER].sheet);
if (ns_error != NSERROR_OK) {
return ns_error;
}
@@ -285,141 +274,57 @@ nserror html_css_new_stylesheets(html_content *c)
return ns_error;
}
-/**
- * Handle notification of inline style completion
- *
- * \param css Inline style object
- * \param pw Private data
- */
-static void html_inline_style_done(struct content_css_data *css, void *pw)
-{
- html_content *html = pw;
- size_t i;
-
- LOG(("Inline style %p done", css));
-
- /* Search HTML content for sheet */
- for (i = 0; i < html->stylesheet_count; i++) {
- if (html->stylesheets[i].type == HTML_STYLESHEET_INTERNAL &&
- html->stylesheets[i].data.internal.data == css)
- break;
- }
-
- /* Not found: must have been replaced, so destroy it */
- if (i == html->stylesheet_count) {
- LOG(("Not found: destroying"));
- nscss_destroy_css_data(css);
- free(css);
- } else {
- html->stylesheets[i].data.internal.done = true;
- }
-
- html->base.active--;
- LOG(("%d fetches active", html->base.active));
- if (html->base.active == 0) {
- html_begin_conversion(html);
- }
-}
-
static nserror
html_stylesheet_from_domnode(html_content *c,
- struct html_stylesheet *s,
- dom_node *node)
+ dom_node *node,
+ hlcache_handle **sheet)
{
- dom_node *child, *next;
+ hlcache_child_context child;
+ dom_string *style;
+ nsurl *url;
dom_exception exc;
- struct content_css_data *sheet, *old_sheet;
- bool old_sheet_done;
nserror error;
- css_error csserror;
+ uint32_t key;
+ char urlbuf[64];
- /* create stylesheet */
- sheet = calloc(1, sizeof(struct content_css_data));
- if (sheet == NULL) {
- return NSERROR_NOMEM;
+ child.charset = c->encoding;
+ child.quirks = c->base.quirks;
+
+ exc = dom_node_get_text_content(node, &style);
+ if ((exc != DOM_NO_ERR) || (style == NULL)) {
+ LOG(("No text content"));
+ return NSERROR_OK;
}
- error = nscss_create_css_data(sheet,
- nsurl_access(c->base_url), NULL, c->quirks,
- html_inline_style_done, c);
+ error = html_css_fetcher_add_item(style, c->base_url, &key);
if (error != NSERROR_OK) {
- free(sheet);
+ dom_string_unref(style);
return error;
}
- exc = dom_node_get_first_child(node, &child);
- if (exc != DOM_NO_ERR) {
- nscss_destroy_css_data(sheet);
- free(sheet);
- return NSERROR_DOM;
- }
-
- while (child != NULL) {
- dom_string *data;
-
- exc = dom_node_get_text_content(child, &data);
- if (exc != DOM_NO_ERR) {
- dom_node_unref(child);
- nscss_destroy_css_data(sheet);
- free(sheet);
- return NSERROR_DOM;
- }
-
- if (nscss_process_css_data(sheet,
- dom_string_data(data),
- dom_string_byte_length(data)) == false) {
- dom_string_unref(data);
- dom_node_unref(child);
- nscss_destroy_css_data(sheet);
- free(sheet);
- return NSERROR_CSS;
- }
+ dom_string_unref(style);
- dom_string_unref(data);
+ snprintf(urlbuf, sizeof(urlbuf), "x-ns-css:%u", key);
- exc = dom_node_get_next_sibling(child, &next);
- if (exc != DOM_NO_ERR) {
- dom_node_unref(child);
- nscss_destroy_css_data(sheet);
- free(sheet);
- return NSERROR_DOM;
- }
+ error = nsurl_create(urlbuf, &url);
+ if (error != NSERROR_OK) {
+ return error;
+ }
- dom_node_unref(child);
- child = next;
+ error = hlcache_handle_retrieve(url, 0,
+ content_get_url(&c->base), NULL,
+ html_convert_css_callback, c, &child, CONTENT_CSS,
+ sheet);
+ if (error != NSERROR_OK) {
+ nsurl_unref(url);
+ return error;
}
+ nsurl_unref(url);
+
c->base.active++;
LOG(("%d fetches active", c->base.active));
- LOG(("Updating sheet %p with %p", s->data.internal, sheet));
-
- /* Update index */
- old_sheet = s->data.internal.data;
- old_sheet_done = s->data.internal.done;
- s->data.internal.data = sheet;
- s->data.internal.done = false;
-
- /* Convert the content -- manually, as we want the result */
- csserror = nscss_convert_css_data(sheet);
- if (csserror != CSS_OK) {
- /* conversion failed */
- c->base.active--;
- LOG(("%d fetches active", c->base.active));
- nscss_destroy_css_data(sheet);
- free(sheet);
- s->data.internal.data = old_sheet;
- s->data.internal.done = old_sheet_done;
- return css_error_to_nserror(csserror);
- }
-
- /* Clean up old sheet if it was already complete */
- if (old_sheet != NULL && old_sheet_done) {
- LOG(("Destroying old sheet %p", old_sheet));
- nscss_destroy_css_data(old_sheet);
- free(old_sheet);
- }
-
return NSERROR_OK;
}
@@ -472,10 +377,8 @@ html_create_style_element(html_content *c, dom_node *style)
}
c->stylesheets = stylesheets;
- c->stylesheets[c->stylesheet_count].type = HTML_STYLESHEET_INTERNAL;
c->stylesheets[c->stylesheet_count].node = style;
- c->stylesheets[c->stylesheet_count].data.internal.data = NULL;
- c->stylesheets[c->stylesheet_count].data.internal.done = false;
+ c->stylesheets[c->stylesheet_count].sheet = NULL;
c->stylesheet_count++;
return c->stylesheets + (c->stylesheet_count - 1);
@@ -486,11 +389,11 @@ bool html_css_update_style(html_content *c, dom_node *style)
nserror error;
unsigned int i;
struct html_stylesheet *s;
+ hlcache_handle *sheet = NULL;
/* Find sheet */
for (i = 0, s = c->stylesheets; i != c->stylesheet_count; i++, s++) {
- if ((s->type == HTML_STYLESHEET_INTERNAL) &&
- (s->node == style))
+ if (s->node == style)
break;
}
if (i == c->stylesheet_count) {
@@ -504,13 +407,30 @@ bool html_css_update_style(html_content *c, dom_node *style)
LOG(("Found sheet %p slot %d for node %p", s, i, style));
- error = html_stylesheet_from_domnode(c, s, style);
+ error = html_stylesheet_from_domnode(c, style, &sheet);
if (error != NSERROR_OK) {
LOG(("Failed to update sheet"));
content_broadcast_errorcode(&c->base, error);
return false;
}
+ if (sheet != NULL) {
+ LOG(("Updating sheet %p with %p", s->sheet, sheet));
+
+ if (s->sheet != NULL) {
+ switch (content_get_status(s->sheet)) {
+ case CONTENT_STATUS_DONE:
+ break;
+ default:
+ hlcache_handle_abort(s->sheet);
+ c->base.active--;
+ LOG(("%d fetches active", c->base.active));
+ }
+ hlcache_handle_release(s->sheet);
+ }
+ s->sheet = sheet;
+ }
+
return true;
}
@@ -588,7 +508,6 @@ bool html_css_process_link(html_content *htmlc, dom_node *node)
}
htmlc->stylesheets = stylesheets;
- htmlc->stylesheets[htmlc->stylesheet_count].type = HTML_STYLESHEET_EXTERNAL;
/* start fetch */
child.charset = htmlc->encoding;
@@ -602,7 +521,7 @@ bool html_css_process_link(html_content *htmlc, dom_node *node)
htmlc,
&child,
CONTENT_CSS,
- &htmlc->stylesheets[htmlc->stylesheet_count].data.external);
+ &htmlc->stylesheets[htmlc->stylesheet_count].sheet);
nsurl_unref(joined);
@@ -629,7 +548,7 @@ html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx)
css_select_ctx *select_ctx;
/* check that the base stylesheet loaded; layout fails without it */
- if (c->stylesheets[STYLESHEET_BASE].data.external == NULL) {
+ if (c->stylesheets[STYLESHEET_BASE].sheet == NULL) {
return NSERROR_CSS_BASE;
}
@@ -651,11 +570,8 @@ html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx)
origin = CSS_ORIGIN_USER;
}
- if ((hsheet->type == HTML_STYLESHEET_EXTERNAL) &&
- (hsheet->data.external != NULL)) {
- sheet = nscss_get_stylesheet(hsheet->data.external);
- } else if (hsheet->type == HTML_STYLESHEET_INTERNAL) {
- sheet = hsheet->data.internal.data->sheet;
+ if (hsheet->sheet != NULL) {
+ sheet = nscss_get_stylesheet(hsheet->sheet);
}
if (sheet != NULL) {
@@ -679,6 +595,8 @@ nserror html_css_init(void)
{
nserror error;
+ html_css_fetcher_register();
+
error = nsurl_create("resource:default.css",
&html_default_stylesheet_url);
if (error != NSERROR_OK)
diff --git a/render/html_css_fetcher.c b/render/html_css_fetcher.c
new file mode 100644
index 0000000..9bd3b21
--- /dev/null
+++ b/render/html_css_fetcher.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2008 Rob Kendrick <rjek(a)netsurf-browser.org>
+ * Copyright 2013 John-Mark Bell <jmb(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <dom/dom.h>
+
+#include <libwapcaplet/libwapcaplet.h>
+
+#include "utils/config.h"
+#include "content/fetch.h"
+#include "render/html_internal.h"
+#include "utils/log.h"
+#include "utils/ring.h"
+#include "utils/nsurl.h"
+#include "utils/utils.h"
+
+typedef struct html_css_fetcher_item {
+ uint32_t key;
+ dom_string *data;
+ nsurl *base_url;
+
+ struct html_css_fetcher_item *r_next, *r_prev;
+} html_css_fetcher_item;
+
+typedef struct html_css_fetcher_context {
+ struct fetch *parent_fetch;
+
+ nsurl *url;
+ html_css_fetcher_item *item;
+
+ bool aborted;
+ bool locked;
+
+ struct html_css_fetcher_context *r_next, *r_prev;
+} html_css_fetcher_context;
+
+static uint32_t current_key = 0;
+static html_css_fetcher_item *items = NULL;
+static html_css_fetcher_context *ring = NULL;
+
+static bool html_css_fetcher_initialise(lwc_string *scheme)
+{
+ LOG(("html_css_fetcher_initialise called for %s", lwc_string_data(scheme)));
+ return true;
+}
+
+static void html_css_fetcher_finalise(lwc_string *scheme)
+{
+ LOG(("html_css_fetcher_finalise called for %s", lwc_string_data(scheme)));
+}
+
+static bool html_css_fetcher_can_fetch(const nsurl *url)
+{
+ return true;
+}
+
+static void *html_css_fetcher_setup(struct fetch *parent_fetch, nsurl *url,
+ bool only_2xx, bool downgrade_tls, const char *post_urlenc,
+ const struct fetch_multipart_data *post_multipart,
+ const char **headers)
+{
+ html_css_fetcher_context *ctx;
+ lwc_string *path;
+ uint32_t key;
+ html_css_fetcher_item *item, *found = NULL;
+
+ /* format of a x-ns-css URL is:
+ * x-ns-url:<key>
+ * Where key is an unsigned 32bit integer
+ */
+
+ path = nsurl_get_component(url, NSURL_PATH);
+ /* The path must exist */
+ if (path == NULL) {
+ return NULL;
+ }
+
+ key = strtoul(lwc_string_data(path), NULL, 10);
+
+ lwc_string_unref(path);
+
+ /* There must be at least one item */
+ if (items == NULL) {
+ return NULL;
+ }
+
+ item = items;
+ do {
+ if (item->key == key) {
+ found = item;
+ break;
+ }
+
+ item = item->r_next;
+ } while (item != items);
+
+ /* We must have found the item */
+ if (found == NULL) {
+ return NULL;
+ }
+
+ ctx = calloc(1, sizeof(*ctx));
+ if (ctx == NULL)
+ return NULL;
+
+ ctx->parent_fetch = parent_fetch;
+ ctx->url = nsurl_ref(url);
+ ctx->item = found;
+
+ RING_INSERT(ring, ctx);
+
+ return ctx;
+}
+
+static bool html_css_fetcher_start(void *ctx)
+{
+ return true;
+}
+
+static void html_css_fetcher_free(void *ctx)
+{
+ html_css_fetcher_context *c = ctx;
+
+ nsurl_unref(c->url);
+ if (c->item != NULL) {
+ nsurl_unref(c->item->base_url);
+ dom_string_unref(c->item->data);
+ RING_REMOVE(items, c->item);
+ free(c->item);
+ }
+ RING_REMOVE(ring, c);
+ free(ctx);
+}
+
+static void html_css_fetcher_abort(void *ctx)
+{
+ html_css_fetcher_context *c = ctx;
+
+ /* To avoid the poll loop having to deal with the fetch context
+ * disappearing from under it, we simply flag the abort here.
+ * The poll loop itself will perform the appropriate cleanup.
+ */
+ c->aborted = true;
+}
+
+static void html_css_fetcher_send_callback(const fetch_msg *msg,
+ html_css_fetcher_context *c)
+{
+ c->locked = true;
+ fetch_send_callback(msg, c->parent_fetch);
+ c->locked = false;
+}
+
+static void html_css_fetcher_poll(lwc_string *scheme)
+{
+ fetch_msg msg;
+ html_css_fetcher_context *c, *next;
+
+ if (ring == NULL) return;
+
+ /* Iterate over ring, processing each pending fetch */
+ c = ring;
+ do {
+ /* Ignore fetches that have been flagged as locked.
+ * This allows safe re-entrant calls to this function.
+ * Re-entrancy can occur if, as a result of a callback,
+ * the interested party causes fetch_poll() to be called
+ * again.
+ */
+ if (c->locked == true) {
+ next = c->r_next;
+ continue;
+ }
+
+ /* Only process non-aborted fetches */
+ if (c->aborted) {
+ /* Nothing to do */
+ assert(c->locked == false);
+ } else if (c->item != NULL) {
+ char header[4096];
+
+ fetch_set_http_code(c->parent_fetch, 200);
+
+ /* Any callback can result in the fetch being aborted.
+ * Therefore, we _must_ check for this after _every_
+ * call to html_css_fetcher_send_callback().
+ */
+ snprintf(header, sizeof header,
+ "Content-Type: text/css; charset=utf-8");
+ msg.type = FETCH_HEADER;
+ msg.data.header_or_data.buf = (const uint8_t *) header;
+ msg.data.header_or_data.len = strlen(header);
+ html_css_fetcher_send_callback(&msg, c);
+
+ if (c->aborted == false) {
+ snprintf(header, sizeof header,
+ "Content-Length: %"SSIZET_FMT,
+ dom_string_byte_length(c->item->data));
+ msg.type = FETCH_HEADER;
+ msg.data.header_or_data.buf =
+ (const uint8_t *) header;
+ msg.data.header_or_data.len = strlen(header);
+ html_css_fetcher_send_callback(&msg, c);
+ }
+
+ if (c->aborted == false) {
+ snprintf(header, sizeof header,
+ "X-NS-Base: %.*s",
+ (int) nsurl_length(c->item->base_url),
+ nsurl_access(c->item->base_url));
+ msg.type = FETCH_HEADER;
+ msg.data.header_or_data.buf =
+ (const uint8_t *) header;
+ msg.data.header_or_data.len = strlen(header);
+ html_css_fetcher_send_callback(&msg, c);
+ }
+
+ if (c->aborted == false) {
+ msg.type = FETCH_DATA;
+ msg.data.header_or_data.buf =
+ (const uint8_t *)
+ dom_string_data(c->item->data);
+ msg.data.header_or_data.len =
+ dom_string_byte_length(c->item->data);
+ html_css_fetcher_send_callback(&msg, c);
+ }
+
+ if (c->aborted == false) {
+ msg.type = FETCH_FINISHED;
+ html_css_fetcher_send_callback(&msg, c);
+ }
+ } else {
+ LOG(("Processing of %s failed!",
+ nsurl_access(c->url)));
+
+ /* Ensure that we're unlocked here. If we aren't,
+ * then html_css_fetcher_process() is broken.
+ */
+ assert(c->locked == false);
+ }
+
+ /* Compute next fetch item at the last possible moment as
+ * processing this item may have added to the ring.
+ */
+ next = c->r_next;
+
+ fetch_remove_from_queues(c->parent_fetch);
+ fetch_free(c->parent_fetch);
+
+ /* Advance to next ring entry, exiting if we've reached
+ * the start of the ring or the ring has become empty
+ */
+ } while ( (c = next) != ring && ring != NULL);
+}
+
+void html_css_fetcher_register(void)
+{
+ lwc_string *scheme;
+
+ if (lwc_intern_string("x-ns-css", SLEN("x-ns-css"),
+ &scheme) != lwc_error_ok) {
+ die("Failed to initialise the fetch module "
+ "(couldn't intern \"x-ns-css\").");
+ }
+
+ fetch_add_fetcher(scheme,
+ html_css_fetcher_initialise,
+ html_css_fetcher_can_fetch,
+ html_css_fetcher_setup,
+ html_css_fetcher_start,
+ html_css_fetcher_abort,
+ html_css_fetcher_free,
+ html_css_fetcher_poll,
+ html_css_fetcher_finalise);
+}
+
+nserror html_css_fetcher_add_item(dom_string *data, nsurl *base_url,
+ uint32_t *key)
+{
+ html_css_fetcher_item *item = malloc(sizeof(*item));
+
+ if (item == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ *key = item->key = current_key++;
+ item->data = dom_string_ref(data);
+ item->base_url = nsurl_ref(base_url);
+
+ RING_INSERT(items, item);
+
+ return NSERROR_OK;
+}
+
diff --git a/render/html_internal.h b/render/html_internal.h
index 428cd39..90f0143 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -268,7 +268,13 @@ nserror html_css_free_stylesheets(html_content *html);
bool html_css_process_link(html_content *htmlc, dom_node *node);
bool html_css_update_style(html_content *c, dom_node *style);
-nserror html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx);
+nserror html_css_new_selection_context(html_content *c,
+ css_select_ctx **ret_select_ctx);
+
+/* in render/html_css_fetcher.c */
+void html_css_fetcher_register(void);
+nserror html_css_fetcher_add_item(dom_string *data, nsurl *base_url,
+ uint32_t *key);
/* in render/html_object.c */
--
NetSurf Browser
10 years, 7 months
libwapcaplet: branch chris/sam460-ocm created. 617aa5e79e56b305619ef3661c4ae86952680ac9
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/libwapcaplet.git/shortlog/617aa5e79e56b305...
...commit http://git.netsurf-browser.org/libwapcaplet.git/commit/617aa5e79e56b30561...
...tree http://git.netsurf-browser.org/libwapcaplet.git/tree/617aa5e79e56b305619e...
The branch, chris/sam460-ocm has been created
at 617aa5e79e56b305619ef3661c4ae86952680ac9 (commit)
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/libwapcaplet.git/commitdiff/617aa5e79e56b3...
commit 617aa5e79e56b305619ef3661c4ae86952680ac9
Author: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Don't artifically limit the number of memory pools we can have (note they don't get freed currently)
diff --git a/src/libwapcaplet.c b/src/libwapcaplet.c
index 4cbb555..8126e62 100644
--- a/src/libwapcaplet.c
+++ b/src/libwapcaplet.c
@@ -36,7 +36,6 @@ lwc__calculate_hash(const char *str, size_t len)
#define CSTR_OF(str) ((const char *)(str->string))
#define NR_BUCKETS_DEFAULT (4091)
-#define MAX_MEM_POOLS 2
#define MEM_POOL_BLOCKS (65536) / (sizeof(lwc_string) + sizeof(void *))
typedef struct lwc_context_s {
@@ -51,7 +50,7 @@ static lwc_context *ctx = NULL;
#define LWC_ALLOC_STR() str_alloc()
#define LWC_FREE_STR(p) str_free(p)
-memory_pool_t *mp[MAX_MEM_POOLS] = { NULL, NULL };
+memory_pool_t *mp = NULL;
typedef lwc_hash (*lwc_hasher)(const char *, size_t);
typedef int (*lwc_strncmp)(const char *, const char *, size_t);
@@ -63,29 +62,37 @@ static void str_free(void *p);
static void *str_alloc(void)
{
void *p;
- int i;
-
- for(i = 0; i < MAX_MEM_POOLS; i++) {
- if(mp[i] == NULL) {
- mp[i] = memory_pool_create(sizeof(lwc_string), MEM_POOL_BLOCKS);
- if(mp[i] == NULL) return NULL; /* out of memory */
- }
+ memory_pool_t *mpc;
+
+ if(mp == NULL) {
+ mp = memory_pool_create(sizeof(lwc_string), MEM_POOL_BLOCKS);
+ if(mp == NULL) return NULL; /* out of memory */
+ }
+
+ mpc = mp;
- if((p = memory_pool_alloc(mp[i]))) {
+ do {
+ if((p = memory_pool_alloc(mpc))) {
return p;
}
- }
- return NULL; /* out of memory pools */
+
+ if(mpc->next == NULL) {
+ mpc->next = memory_pool_create(sizeof(lwc_string), MEM_POOL_BLOCKS);
+ if(mpc->next == NULL) return NULL; /* out of memory */
+ }
+ } while((mpc = mpc->next));
+
+ return NULL; /* should never get here */
}
static void str_free(void *p)
{
- int i;
+ memory_pool_t *mpc = mp;
- for(i = 0; i < MAX_MEM_POOLS; i++) {
- if(memory_pool_free(mp[i], p))
+ do {
+ if(memory_pool_free(mpc, p))
return;
- }
+ }while((mpc = mpc->next));
}
static lwc_error
diff --git a/src/mempool.c b/src/mempool.c
index b0d0d26..5aa8f9d 100755
--- a/src/mempool.c
+++ b/src/mempool.c
@@ -22,6 +22,7 @@ memory_pool_t * memory_pool_create(size_t bs, size_t c)
mp->block_size = bs;
mp->count = c;
mp->pool = NULL;
+ mp->next = NULL;
#ifdef __amigaos4__
/* NB: This *always* allocates 64K, requests for more than 64K *must not*
diff --git a/src/mempool.h b/src/mempool.h
index 0d55a1b..6c0a663 100755
--- a/src/mempool.h
+++ b/src/mempool.h
@@ -12,6 +12,7 @@ typedef struct memory_pool_s
size_t block_size;
size_t count;
bool ocm;
+ void *next;
} __attribute__ ((__aligned__)) memory_pool_t;
memory_pool_t * memory_pool_create(size_t bs, size_t c);
commitdiff http://git.netsurf-browser.org/libwapcaplet.git/commitdiff/758155b3b4b44d...
commit 758155b3b4b44d51a9e5d6c79f9f6f66f2d5f25c
Author: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Fix mempool dump reporting
diff --git a/src/libwapcaplet.c b/src/libwapcaplet.c
index 44aa919..4cbb555 100644
--- a/src/libwapcaplet.c
+++ b/src/libwapcaplet.c
@@ -72,7 +72,7 @@ static void *str_alloc(void)
}
if((p = memory_pool_alloc(mp[i]))) {
- if(p != NULL) return p;
+ return p;
}
}
return NULL; /* out of memory pools */
diff --git a/src/mempool.c b/src/mempool.c
index 4abc772..b0d0d26 100755
--- a/src/mempool.c
+++ b/src/mempool.c
@@ -97,7 +97,7 @@ void memory_pool_dump(memory_pool_t *mp, void (* print_func) (void *value))
{
block = (void *) ((uint8_t *) mp->pool + (mp->block_size * i) +
sizeof(void *) * i);
- next = (void **) ((uint8_t *) block + sizeof(void *));
+ next = (void **) ((uint8_t *) block + mp->block_size);
printf("block #%i(%p):", i, block);
commitdiff http://git.netsurf-browser.org/libwapcaplet.git/commitdiff/07126ad732a9d9...
commit 07126ad732a9d90de6c0ddce5da4712754654eee
Author: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Only return if we've allocated memory, otherwise we're erroring out without trying the second pool.
diff --git a/src/libwapcaplet.c b/src/libwapcaplet.c
index 4cbb555..44aa919 100644
--- a/src/libwapcaplet.c
+++ b/src/libwapcaplet.c
@@ -72,7 +72,7 @@ static void *str_alloc(void)
}
if((p = memory_pool_alloc(mp[i]))) {
- return p;
+ if(p != NULL) return p;
}
}
return NULL; /* out of memory pools */
commitdiff http://git.netsurf-browser.org/libwapcaplet.git/commitdiff/92055076997294...
commit 92055076997294c7f360eaec53452a5468785489
Author: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Keep track of whether the pool allocation is on-chip or not. #ifdef the Amiga-specific parts.
diff --git a/src/mempool.c b/src/mempool.c
index 5dc5498..4abc772 100755
--- a/src/mempool.c
+++ b/src/mempool.c
@@ -16,46 +16,50 @@ struct OCMIFace *IOCM = NULL;
memory_pool_t * memory_pool_create(size_t bs, size_t c)
{
- memory_pool_t *mp = malloc(sizeof(memory_pool_t));
- if (!mp)
- return NULL;
+ memory_pool_t *mp = malloc(sizeof(memory_pool_t));
+ if (!mp) return NULL;
- mp->block_size = bs;
- mp->count = c;
+ mp->block_size = bs;
+ mp->count = c;
mp->pool = NULL;
+#ifdef __amigaos4__
+ /* NB: This *always* allocates 64K, requests for more than 64K *must not*
+ * be passed to this function. */
if((ocmb = IExec->OpenResource("onchipmem.resource"))) {
if((IOCM = (struct OCMIFace *)IExec->GetInterface((struct Library *)ocmb, "main", 1, NULL))) {
mp->pool = IOCM->ObtainOnChipMem();
+ mp->ocm = true;
}
}
+#endif
if(mp->pool == NULL) {
mp->pool = malloc((mp->block_size + sizeof(void *)) * mp->count);
+ mp->ocm = false;
}
- memory_pool_clear(mp);
-
- mp->empty_blocks = mp->pool;
+ memory_pool_clear(mp);
+ mp->empty_blocks = mp->pool;
- return mp;
+ return mp;
}
void memory_pool_destroy(memory_pool_t *mp)
{
- if (!mp)
- return;
+ if (!mp) return;
- memory_pool_clear(mp);
+ memory_pool_clear(mp);
-/**TODO: Track if this is an OCM or standard memory pool.
- * At the moment we have no way of freeing on exit so it doesn't matter.
-
- IOCM->ReleaseOnChipMem();
- IExec->DropInterface((struct Interface *)IOCM);
- free(mp->pool);
-*/
- free(mp);
+ if(mp->ocm == true) {
+#ifdef __amigaos4__
+ IOCM->ReleaseOnChipMem();
+ IExec->DropInterface((struct Interface *)IOCM);
+#endif
+ } else {
+ free(mp->pool);
+ }
+ free(mp);
}
void memory_pool_clear(memory_pool_t *mp)
diff --git a/src/mempool.h b/src/mempool.h
index c99f239..0d55a1b 100755
--- a/src/mempool.h
+++ b/src/mempool.h
@@ -1,22 +1,23 @@
-#ifndef MEMPOOL_H
-#define MEMPOOL_H 1
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-typedef struct memory_pool_s
-{
- void *pool;
- void *empty_blocks;
- size_t block_size;
- size_t count;
-} __attribute__ ((__aligned__)) memory_pool_t;
-
-memory_pool_t * memory_pool_create(size_t bs, size_t c);
-void memory_pool_destroy(memory_pool_t *mp);
-void memory_pool_clear(memory_pool_t *mp);
-void memory_pool_dump(memory_pool_t *mp, void (* print_func) (void *value));
-void *memory_pool_alloc(memory_pool_t *mp);
-bool memory_pool_free(memory_pool_t *mp, void *p);
-#endif /* MEMPOOL_H */
+#ifndef MEMPOOL_H
+#define MEMPOOL_H 1
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef struct memory_pool_s
+{
+ void *pool;
+ void *empty_blocks;
+ size_t block_size;
+ size_t count;
+ bool ocm;
+} __attribute__ ((__aligned__)) memory_pool_t;
+
+memory_pool_t * memory_pool_create(size_t bs, size_t c);
+void memory_pool_destroy(memory_pool_t *mp);
+void memory_pool_clear(memory_pool_t *mp);
+void memory_pool_dump(memory_pool_t *mp, void (* print_func) (void *value));
+void *memory_pool_alloc(memory_pool_t *mp);
+bool memory_pool_free(memory_pool_t *mp, void *p);
+#endif /* MEMPOOL_H */
commitdiff http://git.netsurf-browser.org/libwapcaplet.git/commitdiff/439f14b83969a5...
commit 439f14b83969a5bdbce21a3f0143a5d0fbffc8f2
Author: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Experiment 2: Allocate the lwc_string into memory pools (two of 64K each to cover the 4091 buckets). The first of these pools is allocated in OCM if available. The string itself is moved to a separate allocation in main memory to prevent variable-length allocations in the pools.
diff --git a/include/libwapcaplet/libwapcaplet.h b/include/libwapcaplet/libwapcaplet.h
index 47d93a6..dd1c401 100644
--- a/include/libwapcaplet/libwapcaplet.h
+++ b/include/libwapcaplet/libwapcaplet.h
@@ -43,6 +43,7 @@ typedef struct lwc_string_s {
lwc_hash hash;
lwc_refcounter refcnt;
struct lwc_string_s * insensitive;
+ char *string;
} lwc_string;
/**
@@ -215,7 +216,7 @@ lwc__intern_caseless_string(lwc_string *str);
* in future. Any code relying on it currently should be
* modified to use ::lwc_string_length if possible.
*/
-#define lwc_string_data(str) ((const char *)((str)+1))
+#define lwc_string_data(str) ((const char *)((str)->string))
/**
* Retrieve the data length for an interned string.
diff --git a/src/Makefile b/src/Makefile
index 4e03048..870989c 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,3 +1,3 @@
-DIR_SOURCES := libwapcaplet.c
+DIR_SOURCES := libwapcaplet.c mempool.c
include $(NSBUILD)/Makefile.subdir
diff --git a/src/libwapcaplet.c b/src/libwapcaplet.c
index ecc1fb9..4cbb555 100644
--- a/src/libwapcaplet.c
+++ b/src/libwapcaplet.c
@@ -10,13 +10,9 @@
#include <string.h>
#include <assert.h>
+#include "mempool.h"
#include "libwapcaplet/libwapcaplet.h"
-#ifdef __amigaos4__
-#include <proto/exec.h>
-#include <proto/onchipmem.h>
-#endif
-
#ifndef UNUSED
#define UNUSED(x) ((x) = (x))
#endif
@@ -36,10 +32,12 @@ lwc__calculate_hash(const char *str, size_t len)
return z;
}
-#define STR_OF(str) ((char *)(str + 1))
-#define CSTR_OF(str) ((const char *)(str + 1))
+#define STR_OF(str) ((char *)(str->string))
+#define CSTR_OF(str) ((const char *)(str->string))
#define NR_BUCKETS_DEFAULT (4091)
+#define MAX_MEM_POOLS 2
+#define MEM_POOL_BLOCKS (65536) / (sizeof(lwc_string) + sizeof(void *))
typedef struct lwc_context_s {
lwc_string ** buckets;
@@ -50,55 +48,45 @@ static lwc_context *ctx = NULL;
#define LWC_ALLOC(s) malloc(s)
#define LWC_FREE(p) free(p)
+#define LWC_ALLOC_STR() str_alloc()
+#define LWC_FREE_STR(p) str_free(p)
-#ifndef __amigaos4__
-#define LWC_ALLOC_BUCKET(s) malloc(s)
-#define LWC_FREE_BUCKET(p) free(p)
-#else
-#define LWC_ALLOC_BUCKET(s) onchipmem_malloc(s)
-#define LWC_FREE_BUCKET(p) onchipmem_free(p)
+memory_pool_t *mp[MAX_MEM_POOLS] = { NULL, NULL };
-struct Library *ocmb;
-struct OCMIFace *IOCM = NULL;
-bool using_onchipmem;
+typedef lwc_hash (*lwc_hasher)(const char *, size_t);
+typedef int (*lwc_strncmp)(const char *, const char *, size_t);
+typedef void (*lwc_memcpy)(char *, const char *, size_t);
-void *onchipmem_malloc(int s);
-void onchipmem_free(void *p);
+static void *str_alloc(void);
+static void str_free(void *p);
-void *onchipmem_malloc(int s)
+static void *str_alloc(void)
{
- /* NB: If using OCM this always allocates 64K, ie. a bucket size of 16384 */
- uint8 *ocm = NULL;
-
- if((ocmb = IExec->OpenResource("onchipmem.resource"))) {
- if((IOCM = (struct OCMIFace *)IExec->GetInterface((struct Library *)ocmb, "main", 1, NULL))) {
- ocm = (uint8 *)IOCM->ObtainOnChipMem();
+ void *p;
+ int i;
+
+ for(i = 0; i < MAX_MEM_POOLS; i++) {
+ if(mp[i] == NULL) {
+ mp[i] = memory_pool_create(sizeof(lwc_string), MEM_POOL_BLOCKS);
+ if(mp[i] == NULL) return NULL; /* out of memory */
}
- }
- if(ocm == NULL) {
- ocm = malloc(s);
- using_onchipmem = false;
- } else {
- using_onchipmem = true;
+ if((p = memory_pool_alloc(mp[i]))) {
+ return p;
+ }
}
- return ocm;
+ return NULL; /* out of memory pools */
}
-void onchipmem_free(void *p)
+static void str_free(void *p)
{
- if(using_onchipmem == true) {
- IOCM->ReleaseOnChipMem();
- IExec->DropInterface((struct Interface *)IOCM);
- } else {
- free(p);
+ int i;
+
+ for(i = 0; i < MAX_MEM_POOLS; i++) {
+ if(memory_pool_free(mp[i], p))
+ return;
}
}
-#endif
-
-typedef lwc_hash (*lwc_hasher)(const char *, size_t);
-typedef int (*lwc_strncmp)(const char *, const char *, size_t);
-typedef void (*lwc_memcpy)(char *, const char *, size_t);
static lwc_error
lwc__initialise(void)
@@ -114,10 +102,10 @@ lwc__initialise(void)
memset(ctx, 0, sizeof(lwc_context));
ctx->bucketcount = NR_BUCKETS_DEFAULT;
- ctx->buckets = LWC_ALLOC_BUCKET(sizeof(lwc_string *) * ctx->bucketcount);
+ ctx->buckets = LWC_ALLOC(sizeof(lwc_string *) * ctx->bucketcount);
if (ctx->buckets == NULL) {
- LWC_FREE_BUCKET(ctx);
+ LWC_FREE(ctx);
ctx = NULL;
return lwc_error_oom;
}
@@ -163,12 +151,16 @@ lwc__intern(const char *s, size_t slen,
str = str->next;
}
- /* Add one for the additional NUL. */
- *ret = str = LWC_ALLOC(sizeof(lwc_string) + slen + 1);
+ *ret = str = LWC_ALLOC_STR();
if (str == NULL)
return lwc_error_oom;
-
+
+ /* Add one for the additional NUL. */
+ str->string = LWC_ALLOC(slen + 1);
+ if (str->string == NULL)
+ return lwc_error_oom;
+
str->prevptr = &(ctx->buckets[bucket]);
str->next = ctx->buckets[bucket];
if (str->next != NULL)
@@ -230,7 +222,8 @@ lwc_string_destroy(lwc_string *str)
memset(str, 0xA5, sizeof(*str) + str->len);
#endif
- LWC_FREE(str);
+ LWC_FREE_STR(str);
+ LWC_FREE(STR_OF(str));
}
/**** Shonky caseless bits ****/
diff --git a/src/mempool.c b/src/mempool.c
new file mode 100755
index 0000000..5dc5498
--- /dev/null
+++ b/src/mempool.c
@@ -0,0 +1,147 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include "mempool.h"
+
+#ifdef __amigaos4__
+#include <proto/exec.h>
+#include <proto/onchipmem.h>
+
+struct Library *ocmb;
+struct OCMIFace *IOCM = NULL;
+#endif
+
+#define MEMORY_POOL_ALLOCED_CONST ((void *) 0xFFFFFFFFu)
+
+memory_pool_t * memory_pool_create(size_t bs, size_t c)
+{
+ memory_pool_t *mp = malloc(sizeof(memory_pool_t));
+ if (!mp)
+ return NULL;
+
+ mp->block_size = bs;
+ mp->count = c;
+ mp->pool = NULL;
+
+ if((ocmb = IExec->OpenResource("onchipmem.resource"))) {
+ if((IOCM = (struct OCMIFace *)IExec->GetInterface((struct Library *)ocmb, "main", 1, NULL))) {
+ mp->pool = IOCM->ObtainOnChipMem();
+ }
+ }
+
+ if(mp->pool == NULL) {
+ mp->pool = malloc((mp->block_size + sizeof(void *)) * mp->count);
+ }
+
+ memory_pool_clear(mp);
+
+ mp->empty_blocks = mp->pool;
+
+ return mp;
+}
+
+void memory_pool_destroy(memory_pool_t *mp)
+{
+ if (!mp)
+ return;
+
+ memory_pool_clear(mp);
+
+/**TODO: Track if this is an OCM or standard memory pool.
+ * At the moment we have no way of freeing on exit so it doesn't matter.
+
+ IOCM->ReleaseOnChipMem();
+ IExec->DropInterface((struct Interface *)IOCM);
+ free(mp->pool);
+*/
+ free(mp);
+}
+
+void memory_pool_clear(memory_pool_t *mp)
+{
+ if (!mp)
+ return;
+
+ size_t i;
+ void **p;
+
+ for (i = 0; i < mp->count - 1; i++)
+ {
+ p = (void **) ((uint8_t *) mp->pool + (mp->block_size * (i + 1) +
+ sizeof(void *) * i));
+ *p = (uint8_t *) mp->pool + (mp->block_size + sizeof(void *)) * (i + 1);
+ }
+
+ p = (void **) ((uint8_t *) mp->pool + (mp->block_size * mp->count +
+ sizeof(void *) * (mp->count - 1)));
+ *p = NULL;
+
+ mp->empty_blocks = mp->pool;
+}
+
+void memory_pool_dump(memory_pool_t *mp, void (* print_func) (void *value))
+{
+ printf("start: %p, size: %d, count: %d\n", mp->pool,
+ (mp->block_size + sizeof(void *)) * mp->count, mp->count);
+
+ void *block;
+ void **next;
+ size_t i;
+
+ for (i = 0; i < mp->count; i++)
+ {
+ block = (void *) ((uint8_t *) mp->pool + (mp->block_size * i) +
+ sizeof(void *) * i);
+ next = (void **) ((uint8_t *) block + sizeof(void *));
+
+ printf("block #%i(%p):", i, block);
+
+ if (*next == MEMORY_POOL_ALLOCED_CONST)
+ {
+ printf(" allocated");
+
+ if (print_func)
+ {
+ printf(", value: ");
+ print_func(block);
+ }
+
+ printf("\n");
+ } else
+ {
+ printf(" free, next address %p\n", *next);
+ }
+ }
+}
+
+void * memory_pool_alloc(memory_pool_t *mp)
+{
+ void *p;
+
+ if (mp->empty_blocks)
+ {
+ p = mp->empty_blocks;
+ mp->empty_blocks = * (void **) ((uint8_t *) mp->empty_blocks +
+ mp->block_size);
+ *(void **) ((uint8_t *) p + mp->block_size) = MEMORY_POOL_ALLOCED_CONST;
+ return p;
+ } else
+ {
+ return NULL;
+ }
+}
+
+bool memory_pool_free(memory_pool_t *mp, void *p)
+{
+ if (p && (p >= mp->pool) && (p <= (void *) ((uint8_t *) mp->pool +
+ (mp->block_size + sizeof(void *)) * mp->count)))
+ {
+ *(void **) ((uint8_t *) p + mp->block_size) = mp->empty_blocks;
+ mp->empty_blocks = p;
+ return true;
+ } else {
+ return false;
+ }
+}
+
diff --git a/src/mempool.h b/src/mempool.h
new file mode 100755
index 0000000..c99f239
--- /dev/null
+++ b/src/mempool.h
@@ -0,0 +1,22 @@
+#ifndef MEMPOOL_H
+#define MEMPOOL_H 1
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef struct memory_pool_s
+{
+ void *pool;
+ void *empty_blocks;
+ size_t block_size;
+ size_t count;
+} __attribute__ ((__aligned__)) memory_pool_t;
+
+memory_pool_t * memory_pool_create(size_t bs, size_t c);
+void memory_pool_destroy(memory_pool_t *mp);
+void memory_pool_clear(memory_pool_t *mp);
+void memory_pool_dump(memory_pool_t *mp, void (* print_func) (void *value));
+void *memory_pool_alloc(memory_pool_t *mp);
+bool memory_pool_free(memory_pool_t *mp, void *p);
+#endif /* MEMPOOL_H */
commitdiff http://git.netsurf-browser.org/libwapcaplet.git/commitdiff/53a1eb165791de...
commit 53a1eb165791de4976df55af63751d7adfd74c4c
Author: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Experiment with wapcaplet optimisations using the SAM460's on-chip memory
diff --git a/src/libwapcaplet.c b/src/libwapcaplet.c
index bd20abc..ecc1fb9 100644
--- a/src/libwapcaplet.c
+++ b/src/libwapcaplet.c
@@ -12,6 +12,11 @@
#include "libwapcaplet/libwapcaplet.h"
+#ifdef __amigaos4__
+#include <proto/exec.h>
+#include <proto/onchipmem.h>
+#endif
+
#ifndef UNUSED
#define UNUSED(x) ((x) = (x))
#endif
@@ -46,6 +51,51 @@ static lwc_context *ctx = NULL;
#define LWC_ALLOC(s) malloc(s)
#define LWC_FREE(p) free(p)
+#ifndef __amigaos4__
+#define LWC_ALLOC_BUCKET(s) malloc(s)
+#define LWC_FREE_BUCKET(p) free(p)
+#else
+#define LWC_ALLOC_BUCKET(s) onchipmem_malloc(s)
+#define LWC_FREE_BUCKET(p) onchipmem_free(p)
+
+struct Library *ocmb;
+struct OCMIFace *IOCM = NULL;
+bool using_onchipmem;
+
+void *onchipmem_malloc(int s);
+void onchipmem_free(void *p);
+
+void *onchipmem_malloc(int s)
+{
+ /* NB: If using OCM this always allocates 64K, ie. a bucket size of 16384 */
+ uint8 *ocm = NULL;
+
+ if((ocmb = IExec->OpenResource("onchipmem.resource"))) {
+ if((IOCM = (struct OCMIFace *)IExec->GetInterface((struct Library *)ocmb, "main", 1, NULL))) {
+ ocm = (uint8 *)IOCM->ObtainOnChipMem();
+ }
+ }
+
+ if(ocm == NULL) {
+ ocm = malloc(s);
+ using_onchipmem = false;
+ } else {
+ using_onchipmem = true;
+ }
+ return ocm;
+}
+
+void onchipmem_free(void *p)
+{
+ if(using_onchipmem == true) {
+ IOCM->ReleaseOnChipMem();
+ IExec->DropInterface((struct Interface *)IOCM);
+ } else {
+ free(p);
+ }
+}
+#endif
+
typedef lwc_hash (*lwc_hasher)(const char *, size_t);
typedef int (*lwc_strncmp)(const char *, const char *, size_t);
typedef void (*lwc_memcpy)(char *, const char *, size_t);
@@ -64,10 +114,10 @@ lwc__initialise(void)
memset(ctx, 0, sizeof(lwc_context));
ctx->bucketcount = NR_BUCKETS_DEFAULT;
- ctx->buckets = LWC_ALLOC(sizeof(lwc_string *) * ctx->bucketcount);
+ ctx->buckets = LWC_ALLOC_BUCKET(sizeof(lwc_string *) * ctx->bucketcount);
if (ctx->buckets == NULL) {
- LWC_FREE(ctx);
+ LWC_FREE_BUCKET(ctx);
ctx = NULL;
return lwc_error_oom;
}
-----------------------------------------------------------------------
--
String internment library
10 years, 7 months
netsurf: branch master updated. 21cbb49a6bb9e2ad23b7c8d4ab6a9536dc4a2781
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/21cbb49a6bb9e2ad23b7c...
...commit http://git.netsurf-browser.org/netsurf.git/commit/21cbb49a6bb9e2ad23b7c8d...
...tree http://git.netsurf-browser.org/netsurf.git/tree/21cbb49a6bb9e2ad23b7c8d4a...
The branch, master has been updated
via 21cbb49a6bb9e2ad23b7c8d4ab6a9536dc4a2781 (commit)
from c4a8d472345471c5f8e0c6ba4b099987408a77c4 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commitdiff/21cbb49a6bb9e2ad23b...
commit 21cbb49a6bb9e2ad23b7c8d4ab6a9536dc4a2781
Author: Ole Loots <ole(a)monochrom.net>
Commit: Ole Loots <ole(a)monochrom.net>
Fix toolbar flag setup.
diff --git a/atari/toolbar.c b/atari/toolbar.c
index fad3056..b1df206 100644
--- a/atari/toolbar.c
+++ b/atari/toolbar.c
@@ -313,8 +313,8 @@ struct s_toolbar *toolbar_create(struct s_gui_win_root *owner)
font_style_url.size =
toolbar_styles[t->style].font_height_pt * FONT_SIZE_SCALE;
+ textarea_flags ta_flags = TEXTAREA_INTERNAL_CARET;
textarea_setup ta_setup;
- ta_setup.flags = TEXTAREA_INTERNAL_CARET;
ta_setup.width = 300;
ta_setup.height = t->form[TOOLBAR_AREA_URL].ob_height;
ta_setup.pad_top = 0;
-----------------------------------------------------------------------
Summary of changes:
atari/toolbar.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/atari/toolbar.c b/atari/toolbar.c
index fad3056..b1df206 100644
--- a/atari/toolbar.c
+++ b/atari/toolbar.c
@@ -313,8 +313,8 @@ struct s_toolbar *toolbar_create(struct s_gui_win_root *owner)
font_style_url.size =
toolbar_styles[t->style].font_height_pt * FONT_SIZE_SCALE;
+ textarea_flags ta_flags = TEXTAREA_INTERNAL_CARET;
textarea_setup ta_setup;
- ta_setup.flags = TEXTAREA_INTERNAL_CARET;
ta_setup.width = 300;
ta_setup.height = t->form[TOOLBAR_AREA_URL].ob_height;
ta_setup.pad_top = 0;
--
NetSurf Browser
10 years, 7 months
netsurf: branch master updated. c4a8d472345471c5f8e0c6ba4b099987408a77c4
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/c4a8d472345471c5f8e0c...
...commit http://git.netsurf-browser.org/netsurf.git/commit/c4a8d472345471c5f8e0c6b...
...tree http://git.netsurf-browser.org/netsurf.git/tree/c4a8d472345471c5f8e0c6ba4...
The branch, master has been updated
via c4a8d472345471c5f8e0c6ba4b099987408a77c4 (commit)
from 405fa12f8d5c63553276b3319625fd139fb65665 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commitdiff/c4a8d472345471c5f8e...
commit c4a8d472345471c5f8e0c6ba4b099987408a77c4
Author: Ole Loots <ole(a)monochrom.net>
Commit: Ole Loots <ole(a)monochrom.net>
Removed unused variable.
diff --git a/atari/res/netsurf.rsm b/atari/res/netsurf.rsm
index 189c600..2ede405 100755
--- a/atari/res/netsurf.rsm
+++ b/atari/res/netsurf.rsm
@@ -3,7 +3,7 @@ ResourceMaster v3.65
#N 99@32@AZAaza___ _@AZAaza090___ _@@_@
#FoC-Header@rsm2out@C-Header@rsh@@@[C-Header@0@
#R 0@0@1@1@2@1@
-#M 20010100@0@7728@640@
+#M 20010100@0@7728@641@
#T 0@1@MAINMENU@@62@@
#O 4@32@T_FILE@@
#O 5@32@T_EDIT@@
diff --git a/atari/toolbar.c b/atari/toolbar.c
index c8d8eed..fad3056 100644
--- a/atari/toolbar.c
+++ b/atari/toolbar.c
@@ -61,11 +61,6 @@
#define THROBBER_MAX_INDEX 12
#define THROBBER_INACTIVE_INDEX 13
-#define TOOLBAR_URL_MARGIN_LEFT 2
-#define TOOLBAR_URL_MARGIN_RIGHT 2
-#define TOOLBAR_URL_MARGIN_TOP 2
-#define TOOLBAR_URL_MARGIN_BOTTOM 2
-
enum e_toolbar_button_states {
button_on = 0,
button_off = 1
@@ -281,7 +276,6 @@ void toolbar_exit(void)
struct s_toolbar *toolbar_create(struct s_gui_win_root *owner)
{
int i;
- GRECT url_area;
struct s_toolbar *t;
LOG((""));
@@ -319,13 +313,10 @@ struct s_toolbar *toolbar_create(struct s_gui_win_root *owner)
font_style_url.size =
toolbar_styles[t->style].font_height_pt * FONT_SIZE_SCALE;
- toolbar_get_grect(t, TOOLBAR_AREA_URL, &url_area);
- url_area.g_h -= (TOOLBAR_URL_MARGIN_TOP + TOOLBAR_URL_MARGIN_BOTTOM);
-
- textarea_flags ta_flags = TEXTAREA_INTERNAL_CARET;
textarea_setup ta_setup;
+ ta_setup.flags = TEXTAREA_INTERNAL_CARET;
ta_setup.width = 300;
- ta_setup.height = url_area.g_h;
+ ta_setup.height = t->form[TOOLBAR_AREA_URL].ob_height;
ta_setup.pad_top = 0;
ta_setup.pad_right = 4;
ta_setup.pad_bottom = 0;
@@ -587,7 +578,7 @@ void toolbar_set_dimensions(struct s_toolbar *tb, GRECT *area)
/* this will request an textarea redraw: */
textarea_set_dimensions(tb->url.textarea,
tb->form[TOOLBAR_AREA_URL].ob_width,
- tb->form[TOOLBAR_AREA_URL].ob_height);
+ tb->form[TOOLBAR_AREA_URL].ob_height-1);
}
else {
tb->area = *area;
@@ -810,8 +801,8 @@ void toolbar_mouse_input(struct s_toolbar *tb, short obj, short button)
window_process_redraws(tb->owner);
}
graf_mkstate( &mx, &my, &mb, &kstat );
- mx = mx - (work.g_x + TOOLBAR_URL_MARGIN_LEFT);
- my = my - (work.g_y + TOOLBAR_URL_MARGIN_TOP);
+ mx = mx - (work.g_x);
+ my = my - (work.g_y);
} while (mb & 1);
textarea_mouse_action( tb->url.textarea, BROWSER_MOUSE_HOVER, mx,
-----------------------------------------------------------------------
Summary of changes:
atari/res/netsurf.rsm | 2 +-
atari/toolbar.c | 19 +++++--------------
2 files changed, 6 insertions(+), 15 deletions(-)
diff --git a/atari/res/netsurf.rsm b/atari/res/netsurf.rsm
index 189c600..2ede405 100755
--- a/atari/res/netsurf.rsm
+++ b/atari/res/netsurf.rsm
@@ -3,7 +3,7 @@ ResourceMaster v3.65
#N 99@32@AZAaza___ _@AZAaza090___ _@@_@
#FoC-Header@rsm2out@C-Header@rsh@@@[C-Header@0@
#R 0@0@1@1@2@1@
-#M 20010100@0@7728@640@
+#M 20010100@0@7728@641@
#T 0@1@MAINMENU@@62@@
#O 4@32@T_FILE@@
#O 5@32@T_EDIT@@
diff --git a/atari/toolbar.c b/atari/toolbar.c
index c8d8eed..fad3056 100644
--- a/atari/toolbar.c
+++ b/atari/toolbar.c
@@ -61,11 +61,6 @@
#define THROBBER_MAX_INDEX 12
#define THROBBER_INACTIVE_INDEX 13
-#define TOOLBAR_URL_MARGIN_LEFT 2
-#define TOOLBAR_URL_MARGIN_RIGHT 2
-#define TOOLBAR_URL_MARGIN_TOP 2
-#define TOOLBAR_URL_MARGIN_BOTTOM 2
-
enum e_toolbar_button_states {
button_on = 0,
button_off = 1
@@ -281,7 +276,6 @@ void toolbar_exit(void)
struct s_toolbar *toolbar_create(struct s_gui_win_root *owner)
{
int i;
- GRECT url_area;
struct s_toolbar *t;
LOG((""));
@@ -319,13 +313,10 @@ struct s_toolbar *toolbar_create(struct s_gui_win_root *owner)
font_style_url.size =
toolbar_styles[t->style].font_height_pt * FONT_SIZE_SCALE;
- toolbar_get_grect(t, TOOLBAR_AREA_URL, &url_area);
- url_area.g_h -= (TOOLBAR_URL_MARGIN_TOP + TOOLBAR_URL_MARGIN_BOTTOM);
-
- textarea_flags ta_flags = TEXTAREA_INTERNAL_CARET;
textarea_setup ta_setup;
+ ta_setup.flags = TEXTAREA_INTERNAL_CARET;
ta_setup.width = 300;
- ta_setup.height = url_area.g_h;
+ ta_setup.height = t->form[TOOLBAR_AREA_URL].ob_height;
ta_setup.pad_top = 0;
ta_setup.pad_right = 4;
ta_setup.pad_bottom = 0;
@@ -587,7 +578,7 @@ void toolbar_set_dimensions(struct s_toolbar *tb, GRECT *area)
/* this will request an textarea redraw: */
textarea_set_dimensions(tb->url.textarea,
tb->form[TOOLBAR_AREA_URL].ob_width,
- tb->form[TOOLBAR_AREA_URL].ob_height);
+ tb->form[TOOLBAR_AREA_URL].ob_height-1);
}
else {
tb->area = *area;
@@ -810,8 +801,8 @@ void toolbar_mouse_input(struct s_toolbar *tb, short obj, short button)
window_process_redraws(tb->owner);
}
graf_mkstate( &mx, &my, &mb, &kstat );
- mx = mx - (work.g_x + TOOLBAR_URL_MARGIN_LEFT);
- my = my - (work.g_y + TOOLBAR_URL_MARGIN_TOP);
+ mx = mx - (work.g_x);
+ my = my - (work.g_y);
} while (mb & 1);
textarea_mouse_action( tb->url.textarea, BROWSER_MOUSE_HOVER, mx,
--
NetSurf Browser
10 years, 7 months
netsurf: branch master updated. 405fa12f8d5c63553276b3319625fd139fb65665
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/405fa12f8d5c63553276b...
...commit http://git.netsurf-browser.org/netsurf.git/commit/405fa12f8d5c63553276b33...
...tree http://git.netsurf-browser.org/netsurf.git/tree/405fa12f8d5c63553276b3319...
The branch, master has been updated
via 405fa12f8d5c63553276b3319625fd139fb65665 (commit)
from a35e66ffa16d98bcfdf9608cafbcfd85e18d5f02 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commitdiff/405fa12f8d5c6355327...
commit 405fa12f8d5c63553276b3319625fd139fb65665
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Fix handling of inline stylesheets with @import
diff --git a/desktop/save_complete.c b/desktop/save_complete.c
index d9bd507..621544d 100644
--- a/desktop/save_complete.c
+++ b/desktop/save_complete.c
@@ -363,8 +363,8 @@ static bool save_complete_save_html_stylesheet(save_complete_ctx *ctx,
{
if (sheet->type == HTML_STYLESHEET_INTERNAL) {
if (save_complete_save_imported_sheets(ctx,
- sheet->data.internal->imports,
- sheet->data.internal->import_count) == false)
+ sheet->data.internal.data->imports,
+ sheet->data.internal.data->import_count) == false)
return false;
return true;
diff --git a/render/html.h b/render/html.h
index 97899f1..de9e294 100644
--- a/render/html.h
+++ b/render/html.h
@@ -61,7 +61,10 @@ struct html_stylesheet {
struct dom_node *node; /**< dom node associated with sheet */
union {
struct hlcache_handle *external;
- struct content_css_data *internal;
+ struct {
+ struct content_css_data *data;
+ bool done;
+ } internal;
} data; /**< Sheet data */
};
diff --git a/render/html_css.c b/render/html_css.c
index e14a781..a1e9cd0 100644
--- a/render/html_css.c
+++ b/render/html_css.c
@@ -174,8 +174,9 @@ nserror html_css_free_stylesheets(html_content *html)
(html->stylesheets[i].data.external != NULL)) {
hlcache_handle_release(html->stylesheets[i].data.external);
} else if ((html->stylesheets[i].type == HTML_STYLESHEET_INTERNAL) &&
- (html->stylesheets[i].data.internal != NULL)) {
- nscss_destroy_css_data(html->stylesheets[i].data.internal);
+ (html->stylesheets[i].data.internal.data != NULL)) {
+ nscss_destroy_css_data(html->stylesheets[i].data.internal.data);
+ free(html->stylesheets[i].data.internal.data);
}
}
free(html->stylesheets);
@@ -293,19 +294,42 @@ nserror html_css_new_stylesheets(html_content *c)
static void html_inline_style_done(struct content_css_data *css, void *pw)
{
html_content *html = pw;
+ size_t i;
+
+ LOG(("Inline style %p done", css));
+
+ /* Search HTML content for sheet */
+ for (i = 0; i < html->stylesheet_count; i++) {
+ if (html->stylesheets[i].type == HTML_STYLESHEET_INTERNAL &&
+ html->stylesheets[i].data.internal.data == css)
+ break;
+ }
+
+ /* Not found: must have been replaced, so destroy it */
+ if (i == html->stylesheet_count) {
+ LOG(("Not found: destroying"));
+ nscss_destroy_css_data(css);
+ free(css);
+ } else {
+ html->stylesheets[i].data.internal.done = true;
+ }
html->base.active--;
LOG(("%d fetches active", html->base.active));
+ if (html->base.active == 0) {
+ html_begin_conversion(html);
+ }
}
static nserror
html_stylesheet_from_domnode(html_content *c,
- dom_node *node,
- struct content_css_data **ret_sheet)
+ struct html_stylesheet *s,
+ dom_node *node)
{
dom_node *child, *next;
dom_exception exc;
- struct content_css_data *sheet;
+ struct content_css_data *sheet, *old_sheet;
+ bool old_sheet_done;
nserror error;
css_error csserror;
@@ -368,6 +392,14 @@ html_stylesheet_from_domnode(html_content *c,
c->base.active++;
LOG(("%d fetches active", c->base.active));
+ LOG(("Updating sheet %p with %p", s->data.internal, sheet));
+
+ /* Update index */
+ old_sheet = s->data.internal.data;
+ old_sheet_done = s->data.internal.done;
+ s->data.internal.data = sheet;
+ s->data.internal.done = false;
+
/* Convert the content -- manually, as we want the result */
csserror = nscss_convert_css_data(sheet);
if (csserror != CSS_OK) {
@@ -376,10 +408,18 @@ html_stylesheet_from_domnode(html_content *c,
LOG(("%d fetches active", c->base.active));
nscss_destroy_css_data(sheet);
free(sheet);
+ s->data.internal.data = old_sheet;
+ s->data.internal.done = old_sheet_done;
return css_error_to_nserror(csserror);
}
- *ret_sheet = sheet;
+ /* Clean up old sheet if it was already complete */
+ if (old_sheet != NULL && old_sheet_done) {
+ LOG(("Destroying old sheet %p", old_sheet));
+ nscss_destroy_css_data(old_sheet);
+ free(old_sheet);
+ }
+
return NSERROR_OK;
}
@@ -434,7 +474,8 @@ html_create_style_element(html_content *c, dom_node *style)
c->stylesheets[c->stylesheet_count].type = HTML_STYLESHEET_INTERNAL;
c->stylesheets[c->stylesheet_count].node = style;
- c->stylesheets[c->stylesheet_count].data.internal = NULL;
+ c->stylesheets[c->stylesheet_count].data.internal.data = NULL;
+ c->stylesheets[c->stylesheet_count].data.internal.done = false;
c->stylesheet_count++;
return c->stylesheets + (c->stylesheet_count - 1);
@@ -442,7 +483,6 @@ html_create_style_element(html_content *c, dom_node *style)
bool html_css_update_style(html_content *c, dom_node *style)
{
- struct content_css_data *sheet = NULL;
nserror error;
unsigned int i;
struct html_stylesheet *s;
@@ -462,23 +502,15 @@ bool html_css_update_style(html_content *c, dom_node *style)
return false;
}
- LOG(("Found sheet %p slot %d for node %p", s,i, style));
+ LOG(("Found sheet %p slot %d for node %p", s, i, style));
- error = html_stylesheet_from_domnode(c, style, &sheet);
+ error = html_stylesheet_from_domnode(c, s, style);
if (error != NSERROR_OK) {
LOG(("Failed to update sheet"));
content_broadcast_errorcode(&c->base, error);
return false;
}
- LOG(("Updating sheet %p with %p", s->data.internal, sheet));
-
- /* Update index */
- if (s->data.internal != NULL) {
- nscss_destroy_css_data(s->data.internal);
- free(s->data.internal);
- }
- s->data.internal = sheet;
return true;
}
@@ -623,7 +655,7 @@ html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx)
(hsheet->data.external != NULL)) {
sheet = nscss_get_stylesheet(hsheet->data.external);
} else if (hsheet->type == HTML_STYLESHEET_INTERNAL) {
- sheet = hsheet->data.internal->sheet;
+ sheet = hsheet->data.internal.data->sheet;
}
if (sheet != NULL) {
-----------------------------------------------------------------------
Summary of changes:
desktop/save_complete.c | 4 +-
render/html.h | 5 +++-
render/html_css.c | 70 ++++++++++++++++++++++++++++++++++-------------
3 files changed, 57 insertions(+), 22 deletions(-)
diff --git a/desktop/save_complete.c b/desktop/save_complete.c
index d9bd507..621544d 100644
--- a/desktop/save_complete.c
+++ b/desktop/save_complete.c
@@ -363,8 +363,8 @@ static bool save_complete_save_html_stylesheet(save_complete_ctx *ctx,
{
if (sheet->type == HTML_STYLESHEET_INTERNAL) {
if (save_complete_save_imported_sheets(ctx,
- sheet->data.internal->imports,
- sheet->data.internal->import_count) == false)
+ sheet->data.internal.data->imports,
+ sheet->data.internal.data->import_count) == false)
return false;
return true;
diff --git a/render/html.h b/render/html.h
index 97899f1..de9e294 100644
--- a/render/html.h
+++ b/render/html.h
@@ -61,7 +61,10 @@ struct html_stylesheet {
struct dom_node *node; /**< dom node associated with sheet */
union {
struct hlcache_handle *external;
- struct content_css_data *internal;
+ struct {
+ struct content_css_data *data;
+ bool done;
+ } internal;
} data; /**< Sheet data */
};
diff --git a/render/html_css.c b/render/html_css.c
index e14a781..a1e9cd0 100644
--- a/render/html_css.c
+++ b/render/html_css.c
@@ -174,8 +174,9 @@ nserror html_css_free_stylesheets(html_content *html)
(html->stylesheets[i].data.external != NULL)) {
hlcache_handle_release(html->stylesheets[i].data.external);
} else if ((html->stylesheets[i].type == HTML_STYLESHEET_INTERNAL) &&
- (html->stylesheets[i].data.internal != NULL)) {
- nscss_destroy_css_data(html->stylesheets[i].data.internal);
+ (html->stylesheets[i].data.internal.data != NULL)) {
+ nscss_destroy_css_data(html->stylesheets[i].data.internal.data);
+ free(html->stylesheets[i].data.internal.data);
}
}
free(html->stylesheets);
@@ -293,19 +294,42 @@ nserror html_css_new_stylesheets(html_content *c)
static void html_inline_style_done(struct content_css_data *css, void *pw)
{
html_content *html = pw;
+ size_t i;
+
+ LOG(("Inline style %p done", css));
+
+ /* Search HTML content for sheet */
+ for (i = 0; i < html->stylesheet_count; i++) {
+ if (html->stylesheets[i].type == HTML_STYLESHEET_INTERNAL &&
+ html->stylesheets[i].data.internal.data == css)
+ break;
+ }
+
+ /* Not found: must have been replaced, so destroy it */
+ if (i == html->stylesheet_count) {
+ LOG(("Not found: destroying"));
+ nscss_destroy_css_data(css);
+ free(css);
+ } else {
+ html->stylesheets[i].data.internal.done = true;
+ }
html->base.active--;
LOG(("%d fetches active", html->base.active));
+ if (html->base.active == 0) {
+ html_begin_conversion(html);
+ }
}
static nserror
html_stylesheet_from_domnode(html_content *c,
- dom_node *node,
- struct content_css_data **ret_sheet)
+ struct html_stylesheet *s,
+ dom_node *node)
{
dom_node *child, *next;
dom_exception exc;
- struct content_css_data *sheet;
+ struct content_css_data *sheet, *old_sheet;
+ bool old_sheet_done;
nserror error;
css_error csserror;
@@ -368,6 +392,14 @@ html_stylesheet_from_domnode(html_content *c,
c->base.active++;
LOG(("%d fetches active", c->base.active));
+ LOG(("Updating sheet %p with %p", s->data.internal, sheet));
+
+ /* Update index */
+ old_sheet = s->data.internal.data;
+ old_sheet_done = s->data.internal.done;
+ s->data.internal.data = sheet;
+ s->data.internal.done = false;
+
/* Convert the content -- manually, as we want the result */
csserror = nscss_convert_css_data(sheet);
if (csserror != CSS_OK) {
@@ -376,10 +408,18 @@ html_stylesheet_from_domnode(html_content *c,
LOG(("%d fetches active", c->base.active));
nscss_destroy_css_data(sheet);
free(sheet);
+ s->data.internal.data = old_sheet;
+ s->data.internal.done = old_sheet_done;
return css_error_to_nserror(csserror);
}
- *ret_sheet = sheet;
+ /* Clean up old sheet if it was already complete */
+ if (old_sheet != NULL && old_sheet_done) {
+ LOG(("Destroying old sheet %p", old_sheet));
+ nscss_destroy_css_data(old_sheet);
+ free(old_sheet);
+ }
+
return NSERROR_OK;
}
@@ -434,7 +474,8 @@ html_create_style_element(html_content *c, dom_node *style)
c->stylesheets[c->stylesheet_count].type = HTML_STYLESHEET_INTERNAL;
c->stylesheets[c->stylesheet_count].node = style;
- c->stylesheets[c->stylesheet_count].data.internal = NULL;
+ c->stylesheets[c->stylesheet_count].data.internal.data = NULL;
+ c->stylesheets[c->stylesheet_count].data.internal.done = false;
c->stylesheet_count++;
return c->stylesheets + (c->stylesheet_count - 1);
@@ -442,7 +483,6 @@ html_create_style_element(html_content *c, dom_node *style)
bool html_css_update_style(html_content *c, dom_node *style)
{
- struct content_css_data *sheet = NULL;
nserror error;
unsigned int i;
struct html_stylesheet *s;
@@ -462,23 +502,15 @@ bool html_css_update_style(html_content *c, dom_node *style)
return false;
}
- LOG(("Found sheet %p slot %d for node %p", s,i, style));
+ LOG(("Found sheet %p slot %d for node %p", s, i, style));
- error = html_stylesheet_from_domnode(c, style, &sheet);
+ error = html_stylesheet_from_domnode(c, s, style);
if (error != NSERROR_OK) {
LOG(("Failed to update sheet"));
content_broadcast_errorcode(&c->base, error);
return false;
}
- LOG(("Updating sheet %p with %p", s->data.internal, sheet));
-
- /* Update index */
- if (s->data.internal != NULL) {
- nscss_destroy_css_data(s->data.internal);
- free(s->data.internal);
- }
- s->data.internal = sheet;
return true;
}
@@ -623,7 +655,7 @@ html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx)
(hsheet->data.external != NULL)) {
sheet = nscss_get_stylesheet(hsheet->data.external);
} else if (hsheet->type == HTML_STYLESHEET_INTERNAL) {
- sheet = hsheet->data.internal->sheet;
+ sheet = hsheet->data.internal.data->sheet;
}
if (sheet != NULL) {
--
NetSurf Browser
10 years, 7 months
netsurf: branch master updated. a35e66ffa16d98bcfdf9608cafbcfd85e18d5f02
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/a35e66ffa16d98bcfdf96...
...commit http://git.netsurf-browser.org/netsurf.git/commit/a35e66ffa16d98bcfdf9608...
...tree http://git.netsurf-browser.org/netsurf.git/tree/a35e66ffa16d98bcfdf9608ca...
The branch, master has been updated
via a35e66ffa16d98bcfdf9608cafbcfd85e18d5f02 (commit)
from 4e7b4259a44703ecc0994c922315b67df7096c90 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commitdiff/a35e66ffa16d98bcfdf...
commit a35e66ffa16d98bcfdf9608cafbcfd85e18d5f02
Author: Vincent Sanders <vince(a)netsurf-browser.org>
Commit: Vincent Sanders <vince(a)netsurf-browser.org>
split out object handling from render/html.c
diff --git a/Makefile.sources b/Makefile.sources
index 6810915..b53d7c5 100644
--- a/Makefile.sources
+++ b/Makefile.sources
@@ -12,10 +12,10 @@ S_FETCHERS := curl.c data.c file.c about.c resource.c
S_CSS := css.c dump.c internal.c select.c utils.c
S_RENDER := box.c box_construct.c box_normalise.c box_textarea.c \
- font.c form.c \
- html.c html_css.c html_script.c html_interaction.c \
- html_redraw.c html_forms.c imagemap.c layout.c list.c \
- search.c table.c textplain.c
+ font.c form.c imagemap.c layout.c list.c search.c table.c \
+ textplain.c \
+ html.c html_css.c html_script.c html_interaction.c \
+ html_redraw.c html_forms.c html_object.c
S_UTILS := base64.c corestrings.c filename.c filepath.c hashtable.c \
libdom.c locale.c log.c messages.c nsurl.c talloc.c url.c \
diff --git a/render/html.c b/render/html.c
index 7414ced..3157165 100644
--- a/render/html.c
+++ b/render/html.c
@@ -69,27 +69,6 @@ static const char *html_types[] = {
"text/html"
};
-/* forward declared functions */
-static void html_object_refresh(void *p);
-
-static void html_destroy_objects(html_content *html)
-{
- while (html->object_list != NULL) {
- struct content_html_object *victim = html->object_list;
-
- if (victim->content != NULL) {
- LOG(("object %p", victim->content));
-
- if (content_get_type(victim->content) == CONTENT_HTML)
- schedule_remove(html_object_refresh, victim);
-
- hlcache_handle_release(victim->content);
- }
-
- html->object_list = victim->next;
- free(victim);
- }
-}
/**
* Perform post-box-creation conversion of a document
@@ -107,7 +86,7 @@ static void html_box_convert_done(html_content *c, bool success)
/* Clean up and report error if unsuccessful or aborted */
if ((success == false) || (c->aborted)) {
- html_destroy_objects(c);
+ html_object_free_objects(c);
if (success == false) {
content_broadcast_errorcode(&c->base, NSERROR_BOX_CONVERT);
@@ -130,7 +109,7 @@ static void html_box_convert_done(html_content *c, bool success)
exc = dom_document_get_document_element(c->document, (void *) &html);
if ((exc != DOM_NO_ERR) || (html == NULL)) {
- /** @todo should this call html_destroy_objects(c);
+ /** @todo should this call html_object_free_objects(c);
* like the other error paths
*/
LOG(("error retrieving html element from dom"));
@@ -143,7 +122,7 @@ static void html_box_convert_done(html_content *c, bool success)
err = imagemap_extract(c);
if (err != NSERROR_OK) {
LOG(("imagemap extraction failed"));
- html_destroy_objects(c);
+ html_object_free_objects(c);
content_broadcast_errorcode(&c->base, err);
content_set_error(&c->base);
dom_node_unref(html);
@@ -217,7 +196,7 @@ void html_finish_conversion(html_content *c)
error = dom_to_box(html, c, html_box_convert_done);
if (error != NSERROR_OK) {
dom_node_unref(html);
- html_destroy_objects(c);
+ html_object_free_objects(c);
content_broadcast_errorcode(&c->base, error);
content_set_error(&c->base);
return;
@@ -1092,409 +1071,9 @@ static nserror html_meta_refresh(html_content *c, dom_node *head)
return ns_error;
}
-/**
- * Update a box whose content has completed rendering.
- */
-
-static void
-html_object_done(struct box *box,
- hlcache_handle *object,
- bool background)
-{
- struct box *b;
-
- if (background) {
- box->background = object;
- return;
- }
-
- box->object = object;
-
- if (!(box->flags & REPLACE_DIM)) {
- /* invalidate parent min, max widths */
- for (b = box; b; b = b->parent)
- b->max_width = UNKNOWN_MAX_WIDTH;
-
- /* delete any clones of this box */
- while (box->next && (box->next->flags & CLONE)) {
- /* box_free_box(box->next); */
- box->next = box->next->next;
- }
- }
-}
-
-/**
- * Handle object fetching or loading failure.
- *
- * \param box box containing object which failed to load
- * \param content document of type CONTENT_HTML
- * \param background the object was the background image for the box
- */
-
-static void
-html_object_failed(struct box *box, html_content *content, bool background)
-{
- /* Nothing to do */
- return;
-}
-
-/**
- * Callback for hlcache_handle_retrieve() for objects.
- */
-
-static nserror
-html_object_callback(hlcache_handle *object,
- const hlcache_event *event,
- void *pw)
-{
- struct content_html_object *o = pw;
- html_content *c = (html_content *) o->parent;
- int x, y;
- struct box *box;
-
- assert(c->base.status != CONTENT_STATUS_ERROR);
-
- box = o->box;
-
- switch (event->type) {
- case CONTENT_MSG_LOADING:
- if (c->base.status != CONTENT_STATUS_LOADING && c->bw != NULL)
- content_open(object,
- c->bw, &c->base,
- box->object_params);
- break;
-
- case CONTENT_MSG_READY:
- if (content_can_reformat(object)) {
- /* TODO: avoid knowledge of box internals here */
- content_reformat(object, false,
- box->max_width != UNKNOWN_MAX_WIDTH ?
- box->width : 0,
- box->max_width != UNKNOWN_MAX_WIDTH ?
- box->height : 0);
-
- /* Adjust parent content for new object size */
- html_object_done(box, object, o->background);
- if (c->base.status == CONTENT_STATUS_READY ||
- c->base.status == CONTENT_STATUS_DONE)
- content__reformat(&c->base, false,
- c->base.available_width,
- c->base.height);
- }
- break;
-
- case CONTENT_MSG_DONE:
- c->base.active--;
- LOG(("%d fetches active", c->base.active));
-
- html_object_done(box, object, o->background);
-
- if (c->base.status != CONTENT_STATUS_LOADING &&
- box->flags & REPLACE_DIM) {
- union content_msg_data data;
-
- if (!box_visible(box))
- break;
-
- box_coords(box, &x, &y);
-
- data.redraw.x = x + box->padding[LEFT];
- data.redraw.y = y + box->padding[TOP];
- data.redraw.width = box->width;
- data.redraw.height = box->height;
- data.redraw.full_redraw = true;
-
- content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
- }
- break;
-
- case CONTENT_MSG_ERROR:
- hlcache_handle_release(object);
-
- o->content = NULL;
-
- c->base.active--;
- LOG(("%d fetches active", c->base.active));
-
- content_add_error(&c->base, "?", 0);
- html_object_failed(box, c, o->background);
- break;
-
- case CONTENT_MSG_STATUS:
- if (event->data.explicit_status_text == NULL) {
- /* Object content's status text updated */
- union content_msg_data data;
- data.explicit_status_text =
- content_get_status_message(object);
- html_set_status(c, data.explicit_status_text);
- content_broadcast(&c->base, CONTENT_MSG_STATUS, data);
- } else {
- /* Object content wants to set explicit message */
- content_broadcast(&c->base, CONTENT_MSG_STATUS,
- event->data);
- }
- break;
-
- case CONTENT_MSG_REFORMAT:
- break;
-
- case CONTENT_MSG_REDRAW:
- if (c->base.status != CONTENT_STATUS_LOADING) {
- union content_msg_data data = event->data;
-
- if (!box_visible(box))
- break;
-
- box_coords(box, &x, &y);
-
- if (hlcache_handle_get_content(object) ==
- event->data.redraw.object) {
- data.redraw.x = data.redraw.x *
- box->width / content_get_width(object);
- data.redraw.y = data.redraw.y *
- box->height /
- content_get_height(object);
- data.redraw.width = data.redraw.width *
- box->width / content_get_width(object);
- data.redraw.height = data.redraw.height *
- box->height /
- content_get_height(object);
- data.redraw.object_width = box->width;
- data.redraw.object_height = box->height;
- }
-
- data.redraw.x += x + box->padding[LEFT];
- data.redraw.y += y + box->padding[TOP];
- data.redraw.object_x += x + box->padding[LEFT];
- data.redraw.object_y += y + box->padding[TOP];
-
- content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
- }
- break;
-
- case CONTENT_MSG_REFRESH:
- if (content_get_type(object) == CONTENT_HTML) {
- /* only for HTML objects */
- schedule(event->data.delay * 100,
- html_object_refresh, o);
- }
-
- break;
-
- case CONTENT_MSG_LINK:
- /* Don't care about favicons that aren't on top level content */
- break;
-
- case CONTENT_MSG_GETCTX:
- *(event->data.jscontext) = NULL;
- break;
-
- case CONTENT_MSG_SCROLL:
- if (box->scroll_x != NULL)
- scrollbar_set(box->scroll_x, event->data.scroll.x0,
- false);
- if (box->scroll_y != NULL)
- scrollbar_set(box->scroll_y, event->data.scroll.y0,
- false);
- break;
-
- case CONTENT_MSG_DRAGSAVE:
- {
- union content_msg_data msg_data;
- if (event->data.dragsave.content == NULL)
- msg_data.dragsave.content = object;
- else
- msg_data.dragsave.content =
- event->data.dragsave.content;
-
- content_broadcast(&c->base, CONTENT_MSG_DRAGSAVE, msg_data);
- }
- break;
-
- case CONTENT_MSG_SAVELINK:
- case CONTENT_MSG_POINTER:
- /* These messages are for browser window layer.
- * we're not interested, so pass them on. */
- content_broadcast(&c->base, event->type, event->data);
- break;
-
- case CONTENT_MSG_CARET:
- {
- union html_focus_owner focus_owner;
- focus_owner.content = box;
-
- switch (event->data.caret.type) {
- case CONTENT_CARET_REMOVE:
- case CONTENT_CARET_HIDE:
- html_set_focus(c, HTML_FOCUS_CONTENT, focus_owner,
- true, 0, 0, 0, NULL);
- break;
- case CONTENT_CARET_SET_POS:
- html_set_focus(c, HTML_FOCUS_CONTENT, focus_owner,
- false, event->data.caret.pos.x,
- event->data.caret.pos.y,
- event->data.caret.pos.height,
- event->data.caret.pos.clip);
- break;
- }
- }
- break;
-
- case CONTENT_MSG_DRAG:
- {
- html_drag_type drag_type = HTML_DRAG_NONE;
- union html_drag_owner drag_owner;
- drag_owner.content = box;
-
- switch (event->data.drag.type) {
- case CONTENT_DRAG_NONE:
- drag_type = HTML_DRAG_NONE;
- drag_owner.no_owner = true;
- break;
- case CONTENT_DRAG_SCROLL:
- drag_type = HTML_DRAG_CONTENT_SCROLL;
- break;
- case CONTENT_DRAG_SELECTION:
- drag_type = HTML_DRAG_CONTENT_SELECTION;
- break;
- }
- html_set_drag_type(c, drag_type, drag_owner,
- event->data.drag.rect);
- }
- break;
-
- case CONTENT_MSG_SELECTION:
- {
- html_selection_type sel_type;
- union html_selection_owner sel_owner;
-
- if (event->data.selection.selection) {
- sel_type = HTML_SELECTION_CONTENT;
- sel_owner.content = box;
- } else {
- sel_type = HTML_SELECTION_NONE;
- sel_owner.none = true;
- }
- html_set_selection(c, sel_type, sel_owner,
- event->data.selection.read_only);
- }
- break;
-
- default:
- assert(0);
- }
-
- if (c->base.status == CONTENT_STATUS_READY && c->base.active == 0 &&
- (event->type == CONTENT_MSG_LOADING ||
- event->type == CONTENT_MSG_DONE ||
- event->type == CONTENT_MSG_ERROR)) {
- /* all objects have arrived */
- content__reformat(&c->base, false, c->base.available_width,
- c->base.height);
- html_set_status(c, "");
- content_set_done(&c->base);
- }
-
- /* If 1) the configuration option to reflow pages while objects are
- * fetched is set
- * 2) an object is newly fetched & converted,
- * 3) the box's dimensions need to change due to being replaced
- * 4) the object's parent HTML is ready for reformat,
- * 5) the time since the previous reformat is more than the
- * configured minimum time between reformats
- * then reformat the page to display newly fetched objects */
- else if (nsoption_bool(incremental_reflow) &&
- event->type == CONTENT_MSG_DONE &&
- !(box->flags & REPLACE_DIM) &&
- (c->base.status == CONTENT_STATUS_READY ||
- c->base.status == CONTENT_STATUS_DONE) &&
- (wallclock() > c->base.reformat_time)) {
- content__reformat(&c->base, false, c->base.available_width,
- c->base.height);
- }
-
- return NSERROR_OK;
-}
-
-/**
- * Start a fetch for an object required by a page, replacing an existing object.
- *
- * \param object Object to replace
- * \param url URL of object to fetch (copied)
- * \return true on success, false on memory exhaustion
- */
-static bool html_replace_object(struct content_html_object *object, nsurl *url)
-{
- html_content *c;
- hlcache_child_context child;
- html_content *page;
- nserror error;
-
- assert(object != NULL);
- c = (html_content *) object->parent;
- child.charset = c->encoding;
- child.quirks = c->base.quirks;
-
- if (object->content != NULL) {
- /* remove existing object */
- if (content_get_status(object->content) != CONTENT_STATUS_DONE) {
- c->base.active--;
- LOG(("%d fetches active", c->base.active));
- }
-
- hlcache_handle_release(object->content);
- object->content = NULL;
-
- object->box->object = NULL;
- }
-
- /* initialise fetch */
- error = hlcache_handle_retrieve(url, HLCACHE_RETRIEVE_SNIFF_TYPE,
- content_get_url(&c->base), NULL,
- html_object_callback, object, &child,
- object->permitted_types,
- &object->content);
-
- if (error != NSERROR_OK)
- return false;
-
- for (page = c; page != NULL; page = page->page) {
- page->base.active++;
- LOG(("%d fetches active", c->base.active));
-
- page->base.status = CONTENT_STATUS_READY;
- }
-
- return true;
-}
-
-/**
- * schedule() callback for object refresh
- */
-
-static void html_object_refresh(void *p)
-{
- struct content_html_object *object = p;
- nsurl *refresh_url;
-
- assert(content_get_type(object->content) == CONTENT_HTML);
-
- refresh_url = content_get_refresh_url(object->content);
-
- /* Ignore if refresh URL has gone
- * (may happen if fetch errored) */
- if (refresh_url == NULL)
- return;
-
- content_invalidate_reuse_data(object->content);
-
- if (!html_replace_object(object, refresh_url)) {
- /** \todo handle memory exhaustion */
- }
-}
/**
@@ -1707,74 +1286,6 @@ html_begin_conversion(html_content *htmlc)
}
-
-
-/**
- * Start a fetch for an object required by a page.
- *
- * \param c content of type CONTENT_HTML
- * \param url URL of object to fetch (copied)
- * \param box box that will contain the object
- * \param permitted_types bitmap of acceptable types
- * \param available_width estimate of width of object
- * \param available_height estimate of height of object
- * \param background this is a background image
- * \return true on success, false on memory exhaustion
- */
-
-bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
- content_type permitted_types,
- int available_width, int available_height,
- bool background)
-{
- struct content_html_object *object;
- hlcache_child_context child;
- nserror error;
-
- /* If we've already been aborted, don't bother attempting the fetch */
- if (c->aborted)
- return true;
-
- child.charset = c->encoding;
- child.quirks = c->base.quirks;
-
- object = calloc(1, sizeof(struct content_html_object));
- if (object == NULL) {
- return false;
- }
-
- object->parent = (struct content *) c;
- object->next = NULL;
- object->content = NULL;
- object->box = box;
- object->permitted_types = permitted_types;
- object->background = background;
-
- error = hlcache_handle_retrieve(url,
- HLCACHE_RETRIEVE_SNIFF_TYPE,
- content_get_url(&c->base), NULL,
- html_object_callback, object, &child,
- object->permitted_types, &object->content);
- if (error != NSERROR_OK) {
- free(object);
- return error != NSERROR_NOMEM;
- }
-
- /* add to content object list */
- object->next = c->object_list;
- c->object_list = object;
-
- c->num_objects++;
- c->base.active++;
- LOG(("%d fetches active", c->base.active));
-
- return true;
-}
-
-
-
-
-
/**
* Stop loading a CONTENT_HTML.
*/
@@ -1782,7 +1293,6 @@ bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
static void html_stop(struct content *c)
{
html_content *htmlc = (html_content *) c;
- struct content_html_object *object;
switch (c->status) {
case CONTENT_STATUS_LOADING:
@@ -1790,31 +1300,9 @@ static void html_stop(struct content *c)
* html_convert/html_finish_conversion will do the rest */
htmlc->aborted = true;
break;
- case CONTENT_STATUS_READY:
- for (object = htmlc->object_list; object != NULL;
- object = object->next) {
- if (object->content == NULL)
- continue;
-
- if (content_get_status(object->content) ==
- CONTENT_STATUS_DONE)
- ; /* already loaded: do nothing */
- else if (content_get_status(object->content) ==
- CONTENT_STATUS_READY)
- hlcache_handle_abort(object->content);
- /* Active count will be updated when
- * html_object_callback receives
- * CONTENT_MSG_DONE from this object */
- else {
- hlcache_handle_abort(object->content);
- hlcache_handle_release(object->content);
- object->content = NULL;
-
- c->active--;
- LOG(("%d fetches active", c->active));
- }
- }
+ case CONTENT_STATUS_READY:
+ html_object_abort_objects(htmlc);
/* If there are no further active fetches and we're still
* in the READY state, transition to the DONE state. */
@@ -1824,9 +1312,11 @@ static void html_stop(struct content *c)
}
break;
+
case CONTENT_STATUS_DONE:
/* Nothing to do */
break;
+
default:
LOG(("Unexpected status %d", c->status));
assert(0);
@@ -2038,7 +1528,7 @@ static void html_destroy(struct content *c)
html_free_scripts(html);
/* Free objects */
- html_destroy_objects(html);
+ html_object_free_objects(html);
/* free layout */
html_free_layout(html);
@@ -2078,7 +1568,6 @@ html_open(struct content *c,
struct object_params *params)
{
html_content *html = (html_content *) c;
- struct content_html_object *object, *next;
html->bw = bw;
html->page = (html_content *) page;
@@ -2091,19 +1580,7 @@ html_open(struct content *c,
html->selection_type = HTML_SELECTION_NONE;
html->selection_owner.none = true;
- for (object = html->object_list; object != NULL; object = next) {
- next = object->next;
-
- if (object->content == NULL)
- continue;
-
- if (content_get_type(object->content) == CONTENT_NONE)
- continue;
-
- content_open(object->content,
- bw, c,
- object->box->object_params);
- }
+ html_object_open_objects(html, bw);
}
@@ -2114,7 +1591,6 @@ html_open(struct content *c,
static void html_close(struct content *c)
{
html_content *html = (html_content *) c;
- struct content_html_object *object, *next;
selection_clear(&html->sel, false);
@@ -2123,20 +1599,7 @@ static void html_close(struct content *c)
html->bw = NULL;
- for (object = html->object_list; object != NULL; object = next) {
- next = object->next;
-
- if (object->content == NULL)
- continue;
-
- if (content_get_type(object->content) == CONTENT_NONE)
- continue;
-
- if (content_get_type(object->content) == CONTENT_HTML)
- schedule_remove(html_object_refresh, object);
-
- content_close(object->content);
- }
+ html_object_close_objects(html);
}
@@ -2728,24 +2191,6 @@ const char *html_get_base_target(hlcache_handle *h)
return c->base_target;
}
-/**
- * Retrieve objects used by HTML document
- *
- * \param h Content to retrieve objects from
- * \param n Pointer to location to receive number of objects
- * \return Pointer to list of objects
- */
-struct content_html_object *html_get_objects(hlcache_handle *h, unsigned int *n)
-{
- html_content *c = (html_content *) hlcache_handle_get_content(h);
-
- assert(c != NULL);
- assert(n != NULL);
-
- *n = c->num_objects;
-
- return c->object_list;
-}
/**
* Retrieve layout coordinates of box with given id
diff --git a/render/html_internal.h b/render/html_internal.h
index 4c43345..428cd39 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -165,10 +165,6 @@ typedef struct html_content {
} html_content;
-bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
- content_type permitted_types,
- int available_width, int available_height,
- bool background);
void html_set_status(html_content *c, const char *extra);
@@ -274,6 +270,30 @@ bool html_css_update_style(html_content *c, dom_node *style);
nserror html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx);
+/* in render/html_object.c */
+
+/**
+ * Start a fetch for an object required by a page.
+ *
+ * \param c content of type CONTENT_HTML
+ * \param url URL of object to fetch (copied)
+ * \param box box that will contain the object
+ * \param permitted_types bitmap of acceptable types
+ * \param available_width estimate of width of object
+ * \param available_height estimate of height of object
+ * \param background this is a background image
+ * \return true on success, false on memory exhaustion
+ */
+bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
+ content_type permitted_types,
+ int available_width, int available_height,
+ bool background);
+
+nserror html_object_free_objects(html_content *html);
+nserror html_object_close_objects(html_content *html);
+nserror html_object_open_objects(html_content *html, struct browser_window *bw);
+nserror html_object_abort_objects(html_content *html);
+
/* Useful dom_string pointers */
struct dom_string;
diff --git a/render/html_object.c b/render/html_object.c
new file mode 100644
index 0000000..d4d0ff9
--- /dev/null
+++ b/render/html_object.c
@@ -0,0 +1,616 @@
+/*
+ * Copyright 2013 Vincent Sanders <vince(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Processing for html content object operations.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdint.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+
+#include "content/hlcache.h"
+#include "desktop/options.h"
+#include "desktop/scrollbar.h"
+#include "render/box.h"
+#include "render/html_internal.h"
+#include "utils/corestrings.h"
+#include "utils/config.h"
+#include "utils/log.h"
+#include "utils/schedule.h"
+
+/* break reference loop */
+static void html_object_refresh(void *p);
+
+/**
+ * Retrieve objects used by HTML document
+ *
+ * \param h Content to retrieve objects from
+ * \param n Pointer to location to receive number of objects
+ * \return Pointer to list of objects
+ */
+struct content_html_object *html_get_objects(hlcache_handle *h, unsigned int *n)
+{
+ html_content *c = (html_content *) hlcache_handle_get_content(h);
+
+ assert(c != NULL);
+ assert(n != NULL);
+
+ *n = c->num_objects;
+
+ return c->object_list;
+}
+
+/**
+ * Handle object fetching or loading failure.
+ *
+ * \param box box containing object which failed to load
+ * \param content document of type CONTENT_HTML
+ * \param background the object was the background image for the box
+ */
+
+static void
+html_object_failed(struct box *box, html_content *content, bool background)
+{
+ /* Nothing to do */
+ return;
+}
+
+/**
+ * Update a box whose content has completed rendering.
+ */
+
+static void
+html_object_done(struct box *box,
+ hlcache_handle *object,
+ bool background)
+{
+ struct box *b;
+
+ if (background) {
+ box->background = object;
+ return;
+ }
+
+ box->object = object;
+
+ if (!(box->flags & REPLACE_DIM)) {
+ /* invalidate parent min, max widths */
+ for (b = box; b; b = b->parent)
+ b->max_width = UNKNOWN_MAX_WIDTH;
+
+ /* delete any clones of this box */
+ while (box->next && (box->next->flags & CLONE)) {
+ /* box_free_box(box->next); */
+ box->next = box->next->next;
+ }
+ }
+}
+
+/**
+ * Callback for hlcache_handle_retrieve() for objects.
+ */
+
+static nserror
+html_object_callback(hlcache_handle *object,
+ const hlcache_event *event,
+ void *pw)
+{
+ struct content_html_object *o = pw;
+ html_content *c = (html_content *) o->parent;
+ int x, y;
+ struct box *box;
+
+ assert(c->base.status != CONTENT_STATUS_ERROR);
+
+ box = o->box;
+
+ switch (event->type) {
+ case CONTENT_MSG_LOADING:
+ if (c->base.status != CONTENT_STATUS_LOADING && c->bw != NULL)
+ content_open(object,
+ c->bw, &c->base,
+ box->object_params);
+ break;
+
+ case CONTENT_MSG_READY:
+ if (content_can_reformat(object)) {
+ /* TODO: avoid knowledge of box internals here */
+ content_reformat(object, false,
+ box->max_width != UNKNOWN_MAX_WIDTH ?
+ box->width : 0,
+ box->max_width != UNKNOWN_MAX_WIDTH ?
+ box->height : 0);
+
+ /* Adjust parent content for new object size */
+ html_object_done(box, object, o->background);
+ if (c->base.status == CONTENT_STATUS_READY ||
+ c->base.status == CONTENT_STATUS_DONE)
+ content__reformat(&c->base, false,
+ c->base.available_width,
+ c->base.height);
+ }
+ break;
+
+ case CONTENT_MSG_DONE:
+ c->base.active--;
+ LOG(("%d fetches active", c->base.active));
+
+ html_object_done(box, object, o->background);
+
+ if (c->base.status != CONTENT_STATUS_LOADING &&
+ box->flags & REPLACE_DIM) {
+ union content_msg_data data;
+
+ if (!box_visible(box))
+ break;
+
+ box_coords(box, &x, &y);
+
+ data.redraw.x = x + box->padding[LEFT];
+ data.redraw.y = y + box->padding[TOP];
+ data.redraw.width = box->width;
+ data.redraw.height = box->height;
+ data.redraw.full_redraw = true;
+
+ content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
+ }
+ break;
+
+ case CONTENT_MSG_ERROR:
+ hlcache_handle_release(object);
+
+ o->content = NULL;
+
+ c->base.active--;
+ LOG(("%d fetches active", c->base.active));
+
+ content_add_error(&c->base, "?", 0);
+ html_object_failed(box, c, o->background);
+ break;
+
+ case CONTENT_MSG_STATUS:
+ if (event->data.explicit_status_text == NULL) {
+ /* Object content's status text updated */
+ union content_msg_data data;
+ data.explicit_status_text =
+ content_get_status_message(object);
+ html_set_status(c, data.explicit_status_text);
+ content_broadcast(&c->base, CONTENT_MSG_STATUS, data);
+ } else {
+ /* Object content wants to set explicit message */
+ content_broadcast(&c->base, CONTENT_MSG_STATUS,
+ event->data);
+ }
+ break;
+
+ case CONTENT_MSG_REFORMAT:
+ break;
+
+ case CONTENT_MSG_REDRAW:
+ if (c->base.status != CONTENT_STATUS_LOADING) {
+ union content_msg_data data = event->data;
+
+ if (!box_visible(box))
+ break;
+
+ box_coords(box, &x, &y);
+
+ if (hlcache_handle_get_content(object) ==
+ event->data.redraw.object) {
+ data.redraw.x = data.redraw.x *
+ box->width / content_get_width(object);
+ data.redraw.y = data.redraw.y *
+ box->height /
+ content_get_height(object);
+ data.redraw.width = data.redraw.width *
+ box->width / content_get_width(object);
+ data.redraw.height = data.redraw.height *
+ box->height /
+ content_get_height(object);
+ data.redraw.object_width = box->width;
+ data.redraw.object_height = box->height;
+ }
+
+ data.redraw.x += x + box->padding[LEFT];
+ data.redraw.y += y + box->padding[TOP];
+ data.redraw.object_x += x + box->padding[LEFT];
+ data.redraw.object_y += y + box->padding[TOP];
+
+ content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
+ }
+ break;
+
+ case CONTENT_MSG_REFRESH:
+ if (content_get_type(object) == CONTENT_HTML) {
+ /* only for HTML objects */
+ schedule(event->data.delay * 100,
+ html_object_refresh, o);
+ }
+
+ break;
+
+ case CONTENT_MSG_LINK:
+ /* Don't care about favicons that aren't on top level content */
+ break;
+
+ case CONTENT_MSG_GETCTX:
+ *(event->data.jscontext) = NULL;
+ break;
+
+ case CONTENT_MSG_SCROLL:
+ if (box->scroll_x != NULL)
+ scrollbar_set(box->scroll_x, event->data.scroll.x0,
+ false);
+ if (box->scroll_y != NULL)
+ scrollbar_set(box->scroll_y, event->data.scroll.y0,
+ false);
+ break;
+
+ case CONTENT_MSG_DRAGSAVE:
+ {
+ union content_msg_data msg_data;
+ if (event->data.dragsave.content == NULL)
+ msg_data.dragsave.content = object;
+ else
+ msg_data.dragsave.content =
+ event->data.dragsave.content;
+
+ content_broadcast(&c->base, CONTENT_MSG_DRAGSAVE, msg_data);
+ }
+ break;
+
+ case CONTENT_MSG_SAVELINK:
+ case CONTENT_MSG_POINTER:
+ /* These messages are for browser window layer.
+ * we're not interested, so pass them on. */
+ content_broadcast(&c->base, event->type, event->data);
+ break;
+
+ case CONTENT_MSG_CARET:
+ {
+ union html_focus_owner focus_owner;
+ focus_owner.content = box;
+
+ switch (event->data.caret.type) {
+ case CONTENT_CARET_REMOVE:
+ case CONTENT_CARET_HIDE:
+ html_set_focus(c, HTML_FOCUS_CONTENT, focus_owner,
+ true, 0, 0, 0, NULL);
+ break;
+ case CONTENT_CARET_SET_POS:
+ html_set_focus(c, HTML_FOCUS_CONTENT, focus_owner,
+ false, event->data.caret.pos.x,
+ event->data.caret.pos.y,
+ event->data.caret.pos.height,
+ event->data.caret.pos.clip);
+ break;
+ }
+ }
+ break;
+
+ case CONTENT_MSG_DRAG:
+ {
+ html_drag_type drag_type = HTML_DRAG_NONE;
+ union html_drag_owner drag_owner;
+ drag_owner.content = box;
+
+ switch (event->data.drag.type) {
+ case CONTENT_DRAG_NONE:
+ drag_type = HTML_DRAG_NONE;
+ drag_owner.no_owner = true;
+ break;
+ case CONTENT_DRAG_SCROLL:
+ drag_type = HTML_DRAG_CONTENT_SCROLL;
+ break;
+ case CONTENT_DRAG_SELECTION:
+ drag_type = HTML_DRAG_CONTENT_SELECTION;
+ break;
+ }
+ html_set_drag_type(c, drag_type, drag_owner,
+ event->data.drag.rect);
+ }
+ break;
+
+ case CONTENT_MSG_SELECTION:
+ {
+ html_selection_type sel_type;
+ union html_selection_owner sel_owner;
+
+ if (event->data.selection.selection) {
+ sel_type = HTML_SELECTION_CONTENT;
+ sel_owner.content = box;
+ } else {
+ sel_type = HTML_SELECTION_NONE;
+ sel_owner.none = true;
+ }
+ html_set_selection(c, sel_type, sel_owner,
+ event->data.selection.read_only);
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+
+ if (c->base.status == CONTENT_STATUS_READY && c->base.active == 0 &&
+ (event->type == CONTENT_MSG_LOADING ||
+ event->type == CONTENT_MSG_DONE ||
+ event->type == CONTENT_MSG_ERROR)) {
+ /* all objects have arrived */
+ content__reformat(&c->base, false, c->base.available_width,
+ c->base.height);
+ html_set_status(c, "");
+ content_set_done(&c->base);
+ }
+
+ /* If 1) the configuration option to reflow pages while objects are
+ * fetched is set
+ * 2) an object is newly fetched & converted,
+ * 3) the box's dimensions need to change due to being replaced
+ * 4) the object's parent HTML is ready for reformat,
+ * 5) the time since the previous reformat is more than the
+ * configured minimum time between reformats
+ * then reformat the page to display newly fetched objects */
+ else if (nsoption_bool(incremental_reflow) &&
+ event->type == CONTENT_MSG_DONE &&
+ !(box->flags & REPLACE_DIM) &&
+ (c->base.status == CONTENT_STATUS_READY ||
+ c->base.status == CONTENT_STATUS_DONE) &&
+ (wallclock() > c->base.reformat_time)) {
+ content__reformat(&c->base, false, c->base.available_width,
+ c->base.height);
+ }
+
+ return NSERROR_OK;
+}
+
+/**
+ * Start a fetch for an object required by a page, replacing an existing object.
+ *
+ * \param object Object to replace
+ * \param url URL of object to fetch (copied)
+ * \return true on success, false on memory exhaustion
+ */
+
+static bool html_replace_object(struct content_html_object *object, nsurl *url)
+{
+ html_content *c;
+ hlcache_child_context child;
+ html_content *page;
+ nserror error;
+
+ assert(object != NULL);
+
+ c = (html_content *) object->parent;
+
+ child.charset = c->encoding;
+ child.quirks = c->base.quirks;
+
+ if (object->content != NULL) {
+ /* remove existing object */
+ if (content_get_status(object->content) != CONTENT_STATUS_DONE) {
+ c->base.active--;
+ LOG(("%d fetches active", c->base.active));
+ }
+
+ hlcache_handle_release(object->content);
+ object->content = NULL;
+
+ object->box->object = NULL;
+ }
+
+ /* initialise fetch */
+ error = hlcache_handle_retrieve(url, HLCACHE_RETRIEVE_SNIFF_TYPE,
+ content_get_url(&c->base), NULL,
+ html_object_callback, object, &child,
+ object->permitted_types,
+ &object->content);
+
+ if (error != NSERROR_OK)
+ return false;
+
+ for (page = c; page != NULL; page = page->page) {
+ page->base.active++;
+ LOG(("%d fetches active", c->base.active));
+
+ page->base.status = CONTENT_STATUS_READY;
+ }
+
+ return true;
+}
+
+/**
+ * schedule() callback for object refresh
+ */
+
+static void html_object_refresh(void *p)
+{
+ struct content_html_object *object = p;
+ nsurl *refresh_url;
+
+ assert(content_get_type(object->content) == CONTENT_HTML);
+
+ refresh_url = content_get_refresh_url(object->content);
+
+ /* Ignore if refresh URL has gone
+ * (may happen if fetch errored) */
+ if (refresh_url == NULL)
+ return;
+
+ content_invalidate_reuse_data(object->content);
+
+ if (!html_replace_object(object, refresh_url)) {
+ /** \todo handle memory exhaustion */
+ }
+}
+
+nserror html_object_open_objects(html_content *html, struct browser_window *bw)
+{
+ struct content_html_object *object, *next;
+
+ for (object = html->object_list; object != NULL; object = next) {
+ next = object->next;
+
+ if (object->content == NULL)
+ continue;
+
+ if (content_get_type(object->content) == CONTENT_NONE)
+ continue;
+
+ content_open(object->content,
+ bw,
+ &html->base,
+ object->box->object_params);
+ }
+ return NSERROR_OK;
+}
+
+nserror html_object_abort_objects(html_content *htmlc)
+{
+ struct content_html_object *object;
+
+ for (object = htmlc->object_list;
+ object != NULL;
+ object = object->next) {
+ if (object->content == NULL)
+ continue;
+
+ switch (content_get_status(object->content)) {
+ case CONTENT_STATUS_DONE:
+ /* already loaded: do nothing */
+ break;
+
+ case CONTENT_STATUS_READY:
+ hlcache_handle_abort(object->content);
+ /* Active count will be updated when
+ * html_object_callback receives
+ * CONTENT_MSG_DONE from this object
+ */
+ break;
+
+ default:
+ hlcache_handle_abort(object->content);
+ hlcache_handle_release(object->content);
+ object->content = NULL;
+
+ htmlc->base.active--;
+ LOG(("%d fetches active", htmlc->base.active));
+ break;
+
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+nserror html_object_close_objects(html_content *html)
+{
+ struct content_html_object *object, *next;
+
+ for (object = html->object_list; object != NULL; object = next) {
+ next = object->next;
+
+ if (object->content == NULL)
+ continue;
+
+ if (content_get_type(object->content) == CONTENT_NONE)
+ continue;
+
+ if (content_get_type(object->content) == CONTENT_HTML)
+ schedule_remove(html_object_refresh, object);
+
+ content_close(object->content);
+ }
+ return NSERROR_OK;
+}
+
+nserror html_object_free_objects(html_content *html)
+{
+ while (html->object_list != NULL) {
+ struct content_html_object *victim = html->object_list;
+
+ if (victim->content != NULL) {
+ LOG(("object %p", victim->content));
+
+ if (content_get_type(victim->content) == CONTENT_HTML)
+ schedule_remove(html_object_refresh, victim);
+
+ hlcache_handle_release(victim->content);
+ }
+
+ html->object_list = victim->next;
+ free(victim);
+ }
+ return NSERROR_OK;
+}
+
+
+
+/* exported interface documented in render/html_internal.h */
+bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
+ content_type permitted_types,
+ int available_width, int available_height,
+ bool background)
+{
+ struct content_html_object *object;
+ hlcache_child_context child;
+ nserror error;
+
+ /* If we've already been aborted, don't bother attempting the fetch */
+ if (c->aborted)
+ return true;
+
+ child.charset = c->encoding;
+ child.quirks = c->base.quirks;
+
+ object = calloc(1, sizeof(struct content_html_object));
+ if (object == NULL) {
+ return false;
+ }
+
+ object->parent = (struct content *) c;
+ object->next = NULL;
+ object->content = NULL;
+ object->box = box;
+ object->permitted_types = permitted_types;
+ object->background = background;
+
+ error = hlcache_handle_retrieve(url,
+ HLCACHE_RETRIEVE_SNIFF_TYPE,
+ content_get_url(&c->base), NULL,
+ html_object_callback, object, &child,
+ object->permitted_types, &object->content);
+ if (error != NSERROR_OK) {
+ free(object);
+ return error != NSERROR_NOMEM;
+ }
+
+ /* add to content object list */
+ object->next = c->object_list;
+ c->object_list = object;
+
+ c->num_objects++;
+ c->base.active++;
+ LOG(("%d fetches active", c->base.active));
+
+ return true;
+}
-----------------------------------------------------------------------
Summary of changes:
Makefile.sources | 8 +-
render/html.c | 577 +--------------------------------------------
render/html_internal.h | 28 ++-
render/html_object.c | 616 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 655 insertions(+), 574 deletions(-)
create mode 100644 render/html_object.c
diff --git a/Makefile.sources b/Makefile.sources
index 6810915..b53d7c5 100644
--- a/Makefile.sources
+++ b/Makefile.sources
@@ -12,10 +12,10 @@ S_FETCHERS := curl.c data.c file.c about.c resource.c
S_CSS := css.c dump.c internal.c select.c utils.c
S_RENDER := box.c box_construct.c box_normalise.c box_textarea.c \
- font.c form.c \
- html.c html_css.c html_script.c html_interaction.c \
- html_redraw.c html_forms.c imagemap.c layout.c list.c \
- search.c table.c textplain.c
+ font.c form.c imagemap.c layout.c list.c search.c table.c \
+ textplain.c \
+ html.c html_css.c html_script.c html_interaction.c \
+ html_redraw.c html_forms.c html_object.c
S_UTILS := base64.c corestrings.c filename.c filepath.c hashtable.c \
libdom.c locale.c log.c messages.c nsurl.c talloc.c url.c \
diff --git a/render/html.c b/render/html.c
index 7414ced..3157165 100644
--- a/render/html.c
+++ b/render/html.c
@@ -69,27 +69,6 @@ static const char *html_types[] = {
"text/html"
};
-/* forward declared functions */
-static void html_object_refresh(void *p);
-
-static void html_destroy_objects(html_content *html)
-{
- while (html->object_list != NULL) {
- struct content_html_object *victim = html->object_list;
-
- if (victim->content != NULL) {
- LOG(("object %p", victim->content));
-
- if (content_get_type(victim->content) == CONTENT_HTML)
- schedule_remove(html_object_refresh, victim);
-
- hlcache_handle_release(victim->content);
- }
-
- html->object_list = victim->next;
- free(victim);
- }
-}
/**
* Perform post-box-creation conversion of a document
@@ -107,7 +86,7 @@ static void html_box_convert_done(html_content *c, bool success)
/* Clean up and report error if unsuccessful or aborted */
if ((success == false) || (c->aborted)) {
- html_destroy_objects(c);
+ html_object_free_objects(c);
if (success == false) {
content_broadcast_errorcode(&c->base, NSERROR_BOX_CONVERT);
@@ -130,7 +109,7 @@ static void html_box_convert_done(html_content *c, bool success)
exc = dom_document_get_document_element(c->document, (void *) &html);
if ((exc != DOM_NO_ERR) || (html == NULL)) {
- /** @todo should this call html_destroy_objects(c);
+ /** @todo should this call html_object_free_objects(c);
* like the other error paths
*/
LOG(("error retrieving html element from dom"));
@@ -143,7 +122,7 @@ static void html_box_convert_done(html_content *c, bool success)
err = imagemap_extract(c);
if (err != NSERROR_OK) {
LOG(("imagemap extraction failed"));
- html_destroy_objects(c);
+ html_object_free_objects(c);
content_broadcast_errorcode(&c->base, err);
content_set_error(&c->base);
dom_node_unref(html);
@@ -217,7 +196,7 @@ void html_finish_conversion(html_content *c)
error = dom_to_box(html, c, html_box_convert_done);
if (error != NSERROR_OK) {
dom_node_unref(html);
- html_destroy_objects(c);
+ html_object_free_objects(c);
content_broadcast_errorcode(&c->base, error);
content_set_error(&c->base);
return;
@@ -1092,409 +1071,9 @@ static nserror html_meta_refresh(html_content *c, dom_node *head)
return ns_error;
}
-/**
- * Update a box whose content has completed rendering.
- */
-
-static void
-html_object_done(struct box *box,
- hlcache_handle *object,
- bool background)
-{
- struct box *b;
-
- if (background) {
- box->background = object;
- return;
- }
-
- box->object = object;
-
- if (!(box->flags & REPLACE_DIM)) {
- /* invalidate parent min, max widths */
- for (b = box; b; b = b->parent)
- b->max_width = UNKNOWN_MAX_WIDTH;
-
- /* delete any clones of this box */
- while (box->next && (box->next->flags & CLONE)) {
- /* box_free_box(box->next); */
- box->next = box->next->next;
- }
- }
-}
-
-/**
- * Handle object fetching or loading failure.
- *
- * \param box box containing object which failed to load
- * \param content document of type CONTENT_HTML
- * \param background the object was the background image for the box
- */
-
-static void
-html_object_failed(struct box *box, html_content *content, bool background)
-{
- /* Nothing to do */
- return;
-}
-
-/**
- * Callback for hlcache_handle_retrieve() for objects.
- */
-
-static nserror
-html_object_callback(hlcache_handle *object,
- const hlcache_event *event,
- void *pw)
-{
- struct content_html_object *o = pw;
- html_content *c = (html_content *) o->parent;
- int x, y;
- struct box *box;
-
- assert(c->base.status != CONTENT_STATUS_ERROR);
-
- box = o->box;
-
- switch (event->type) {
- case CONTENT_MSG_LOADING:
- if (c->base.status != CONTENT_STATUS_LOADING && c->bw != NULL)
- content_open(object,
- c->bw, &c->base,
- box->object_params);
- break;
-
- case CONTENT_MSG_READY:
- if (content_can_reformat(object)) {
- /* TODO: avoid knowledge of box internals here */
- content_reformat(object, false,
- box->max_width != UNKNOWN_MAX_WIDTH ?
- box->width : 0,
- box->max_width != UNKNOWN_MAX_WIDTH ?
- box->height : 0);
-
- /* Adjust parent content for new object size */
- html_object_done(box, object, o->background);
- if (c->base.status == CONTENT_STATUS_READY ||
- c->base.status == CONTENT_STATUS_DONE)
- content__reformat(&c->base, false,
- c->base.available_width,
- c->base.height);
- }
- break;
-
- case CONTENT_MSG_DONE:
- c->base.active--;
- LOG(("%d fetches active", c->base.active));
-
- html_object_done(box, object, o->background);
-
- if (c->base.status != CONTENT_STATUS_LOADING &&
- box->flags & REPLACE_DIM) {
- union content_msg_data data;
-
- if (!box_visible(box))
- break;
-
- box_coords(box, &x, &y);
-
- data.redraw.x = x + box->padding[LEFT];
- data.redraw.y = y + box->padding[TOP];
- data.redraw.width = box->width;
- data.redraw.height = box->height;
- data.redraw.full_redraw = true;
-
- content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
- }
- break;
-
- case CONTENT_MSG_ERROR:
- hlcache_handle_release(object);
-
- o->content = NULL;
-
- c->base.active--;
- LOG(("%d fetches active", c->base.active));
-
- content_add_error(&c->base, "?", 0);
- html_object_failed(box, c, o->background);
- break;
-
- case CONTENT_MSG_STATUS:
- if (event->data.explicit_status_text == NULL) {
- /* Object content's status text updated */
- union content_msg_data data;
- data.explicit_status_text =
- content_get_status_message(object);
- html_set_status(c, data.explicit_status_text);
- content_broadcast(&c->base, CONTENT_MSG_STATUS, data);
- } else {
- /* Object content wants to set explicit message */
- content_broadcast(&c->base, CONTENT_MSG_STATUS,
- event->data);
- }
- break;
-
- case CONTENT_MSG_REFORMAT:
- break;
-
- case CONTENT_MSG_REDRAW:
- if (c->base.status != CONTENT_STATUS_LOADING) {
- union content_msg_data data = event->data;
-
- if (!box_visible(box))
- break;
-
- box_coords(box, &x, &y);
-
- if (hlcache_handle_get_content(object) ==
- event->data.redraw.object) {
- data.redraw.x = data.redraw.x *
- box->width / content_get_width(object);
- data.redraw.y = data.redraw.y *
- box->height /
- content_get_height(object);
- data.redraw.width = data.redraw.width *
- box->width / content_get_width(object);
- data.redraw.height = data.redraw.height *
- box->height /
- content_get_height(object);
- data.redraw.object_width = box->width;
- data.redraw.object_height = box->height;
- }
-
- data.redraw.x += x + box->padding[LEFT];
- data.redraw.y += y + box->padding[TOP];
- data.redraw.object_x += x + box->padding[LEFT];
- data.redraw.object_y += y + box->padding[TOP];
-
- content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
- }
- break;
-
- case CONTENT_MSG_REFRESH:
- if (content_get_type(object) == CONTENT_HTML) {
- /* only for HTML objects */
- schedule(event->data.delay * 100,
- html_object_refresh, o);
- }
-
- break;
-
- case CONTENT_MSG_LINK:
- /* Don't care about favicons that aren't on top level content */
- break;
-
- case CONTENT_MSG_GETCTX:
- *(event->data.jscontext) = NULL;
- break;
-
- case CONTENT_MSG_SCROLL:
- if (box->scroll_x != NULL)
- scrollbar_set(box->scroll_x, event->data.scroll.x0,
- false);
- if (box->scroll_y != NULL)
- scrollbar_set(box->scroll_y, event->data.scroll.y0,
- false);
- break;
-
- case CONTENT_MSG_DRAGSAVE:
- {
- union content_msg_data msg_data;
- if (event->data.dragsave.content == NULL)
- msg_data.dragsave.content = object;
- else
- msg_data.dragsave.content =
- event->data.dragsave.content;
-
- content_broadcast(&c->base, CONTENT_MSG_DRAGSAVE, msg_data);
- }
- break;
-
- case CONTENT_MSG_SAVELINK:
- case CONTENT_MSG_POINTER:
- /* These messages are for browser window layer.
- * we're not interested, so pass them on. */
- content_broadcast(&c->base, event->type, event->data);
- break;
-
- case CONTENT_MSG_CARET:
- {
- union html_focus_owner focus_owner;
- focus_owner.content = box;
-
- switch (event->data.caret.type) {
- case CONTENT_CARET_REMOVE:
- case CONTENT_CARET_HIDE:
- html_set_focus(c, HTML_FOCUS_CONTENT, focus_owner,
- true, 0, 0, 0, NULL);
- break;
- case CONTENT_CARET_SET_POS:
- html_set_focus(c, HTML_FOCUS_CONTENT, focus_owner,
- false, event->data.caret.pos.x,
- event->data.caret.pos.y,
- event->data.caret.pos.height,
- event->data.caret.pos.clip);
- break;
- }
- }
- break;
-
- case CONTENT_MSG_DRAG:
- {
- html_drag_type drag_type = HTML_DRAG_NONE;
- union html_drag_owner drag_owner;
- drag_owner.content = box;
-
- switch (event->data.drag.type) {
- case CONTENT_DRAG_NONE:
- drag_type = HTML_DRAG_NONE;
- drag_owner.no_owner = true;
- break;
- case CONTENT_DRAG_SCROLL:
- drag_type = HTML_DRAG_CONTENT_SCROLL;
- break;
- case CONTENT_DRAG_SELECTION:
- drag_type = HTML_DRAG_CONTENT_SELECTION;
- break;
- }
- html_set_drag_type(c, drag_type, drag_owner,
- event->data.drag.rect);
- }
- break;
-
- case CONTENT_MSG_SELECTION:
- {
- html_selection_type sel_type;
- union html_selection_owner sel_owner;
-
- if (event->data.selection.selection) {
- sel_type = HTML_SELECTION_CONTENT;
- sel_owner.content = box;
- } else {
- sel_type = HTML_SELECTION_NONE;
- sel_owner.none = true;
- }
- html_set_selection(c, sel_type, sel_owner,
- event->data.selection.read_only);
- }
- break;
-
- default:
- assert(0);
- }
-
- if (c->base.status == CONTENT_STATUS_READY && c->base.active == 0 &&
- (event->type == CONTENT_MSG_LOADING ||
- event->type == CONTENT_MSG_DONE ||
- event->type == CONTENT_MSG_ERROR)) {
- /* all objects have arrived */
- content__reformat(&c->base, false, c->base.available_width,
- c->base.height);
- html_set_status(c, "");
- content_set_done(&c->base);
- }
-
- /* If 1) the configuration option to reflow pages while objects are
- * fetched is set
- * 2) an object is newly fetched & converted,
- * 3) the box's dimensions need to change due to being replaced
- * 4) the object's parent HTML is ready for reformat,
- * 5) the time since the previous reformat is more than the
- * configured minimum time between reformats
- * then reformat the page to display newly fetched objects */
- else if (nsoption_bool(incremental_reflow) &&
- event->type == CONTENT_MSG_DONE &&
- !(box->flags & REPLACE_DIM) &&
- (c->base.status == CONTENT_STATUS_READY ||
- c->base.status == CONTENT_STATUS_DONE) &&
- (wallclock() > c->base.reformat_time)) {
- content__reformat(&c->base, false, c->base.available_width,
- c->base.height);
- }
-
- return NSERROR_OK;
-}
-
-/**
- * Start a fetch for an object required by a page, replacing an existing object.
- *
- * \param object Object to replace
- * \param url URL of object to fetch (copied)
- * \return true on success, false on memory exhaustion
- */
-static bool html_replace_object(struct content_html_object *object, nsurl *url)
-{
- html_content *c;
- hlcache_child_context child;
- html_content *page;
- nserror error;
-
- assert(object != NULL);
- c = (html_content *) object->parent;
- child.charset = c->encoding;
- child.quirks = c->base.quirks;
-
- if (object->content != NULL) {
- /* remove existing object */
- if (content_get_status(object->content) != CONTENT_STATUS_DONE) {
- c->base.active--;
- LOG(("%d fetches active", c->base.active));
- }
-
- hlcache_handle_release(object->content);
- object->content = NULL;
-
- object->box->object = NULL;
- }
-
- /* initialise fetch */
- error = hlcache_handle_retrieve(url, HLCACHE_RETRIEVE_SNIFF_TYPE,
- content_get_url(&c->base), NULL,
- html_object_callback, object, &child,
- object->permitted_types,
- &object->content);
-
- if (error != NSERROR_OK)
- return false;
-
- for (page = c; page != NULL; page = page->page) {
- page->base.active++;
- LOG(("%d fetches active", c->base.active));
-
- page->base.status = CONTENT_STATUS_READY;
- }
-
- return true;
-}
-
-/**
- * schedule() callback for object refresh
- */
-
-static void html_object_refresh(void *p)
-{
- struct content_html_object *object = p;
- nsurl *refresh_url;
-
- assert(content_get_type(object->content) == CONTENT_HTML);
-
- refresh_url = content_get_refresh_url(object->content);
-
- /* Ignore if refresh URL has gone
- * (may happen if fetch errored) */
- if (refresh_url == NULL)
- return;
-
- content_invalidate_reuse_data(object->content);
-
- if (!html_replace_object(object, refresh_url)) {
- /** \todo handle memory exhaustion */
- }
-}
/**
@@ -1707,74 +1286,6 @@ html_begin_conversion(html_content *htmlc)
}
-
-
-/**
- * Start a fetch for an object required by a page.
- *
- * \param c content of type CONTENT_HTML
- * \param url URL of object to fetch (copied)
- * \param box box that will contain the object
- * \param permitted_types bitmap of acceptable types
- * \param available_width estimate of width of object
- * \param available_height estimate of height of object
- * \param background this is a background image
- * \return true on success, false on memory exhaustion
- */
-
-bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
- content_type permitted_types,
- int available_width, int available_height,
- bool background)
-{
- struct content_html_object *object;
- hlcache_child_context child;
- nserror error;
-
- /* If we've already been aborted, don't bother attempting the fetch */
- if (c->aborted)
- return true;
-
- child.charset = c->encoding;
- child.quirks = c->base.quirks;
-
- object = calloc(1, sizeof(struct content_html_object));
- if (object == NULL) {
- return false;
- }
-
- object->parent = (struct content *) c;
- object->next = NULL;
- object->content = NULL;
- object->box = box;
- object->permitted_types = permitted_types;
- object->background = background;
-
- error = hlcache_handle_retrieve(url,
- HLCACHE_RETRIEVE_SNIFF_TYPE,
- content_get_url(&c->base), NULL,
- html_object_callback, object, &child,
- object->permitted_types, &object->content);
- if (error != NSERROR_OK) {
- free(object);
- return error != NSERROR_NOMEM;
- }
-
- /* add to content object list */
- object->next = c->object_list;
- c->object_list = object;
-
- c->num_objects++;
- c->base.active++;
- LOG(("%d fetches active", c->base.active));
-
- return true;
-}
-
-
-
-
-
/**
* Stop loading a CONTENT_HTML.
*/
@@ -1782,7 +1293,6 @@ bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
static void html_stop(struct content *c)
{
html_content *htmlc = (html_content *) c;
- struct content_html_object *object;
switch (c->status) {
case CONTENT_STATUS_LOADING:
@@ -1790,31 +1300,9 @@ static void html_stop(struct content *c)
* html_convert/html_finish_conversion will do the rest */
htmlc->aborted = true;
break;
- case CONTENT_STATUS_READY:
- for (object = htmlc->object_list; object != NULL;
- object = object->next) {
- if (object->content == NULL)
- continue;
-
- if (content_get_status(object->content) ==
- CONTENT_STATUS_DONE)
- ; /* already loaded: do nothing */
- else if (content_get_status(object->content) ==
- CONTENT_STATUS_READY)
- hlcache_handle_abort(object->content);
- /* Active count will be updated when
- * html_object_callback receives
- * CONTENT_MSG_DONE from this object */
- else {
- hlcache_handle_abort(object->content);
- hlcache_handle_release(object->content);
- object->content = NULL;
-
- c->active--;
- LOG(("%d fetches active", c->active));
- }
- }
+ case CONTENT_STATUS_READY:
+ html_object_abort_objects(htmlc);
/* If there are no further active fetches and we're still
* in the READY state, transition to the DONE state. */
@@ -1824,9 +1312,11 @@ static void html_stop(struct content *c)
}
break;
+
case CONTENT_STATUS_DONE:
/* Nothing to do */
break;
+
default:
LOG(("Unexpected status %d", c->status));
assert(0);
@@ -2038,7 +1528,7 @@ static void html_destroy(struct content *c)
html_free_scripts(html);
/* Free objects */
- html_destroy_objects(html);
+ html_object_free_objects(html);
/* free layout */
html_free_layout(html);
@@ -2078,7 +1568,6 @@ html_open(struct content *c,
struct object_params *params)
{
html_content *html = (html_content *) c;
- struct content_html_object *object, *next;
html->bw = bw;
html->page = (html_content *) page;
@@ -2091,19 +1580,7 @@ html_open(struct content *c,
html->selection_type = HTML_SELECTION_NONE;
html->selection_owner.none = true;
- for (object = html->object_list; object != NULL; object = next) {
- next = object->next;
-
- if (object->content == NULL)
- continue;
-
- if (content_get_type(object->content) == CONTENT_NONE)
- continue;
-
- content_open(object->content,
- bw, c,
- object->box->object_params);
- }
+ html_object_open_objects(html, bw);
}
@@ -2114,7 +1591,6 @@ html_open(struct content *c,
static void html_close(struct content *c)
{
html_content *html = (html_content *) c;
- struct content_html_object *object, *next;
selection_clear(&html->sel, false);
@@ -2123,20 +1599,7 @@ static void html_close(struct content *c)
html->bw = NULL;
- for (object = html->object_list; object != NULL; object = next) {
- next = object->next;
-
- if (object->content == NULL)
- continue;
-
- if (content_get_type(object->content) == CONTENT_NONE)
- continue;
-
- if (content_get_type(object->content) == CONTENT_HTML)
- schedule_remove(html_object_refresh, object);
-
- content_close(object->content);
- }
+ html_object_close_objects(html);
}
@@ -2728,24 +2191,6 @@ const char *html_get_base_target(hlcache_handle *h)
return c->base_target;
}
-/**
- * Retrieve objects used by HTML document
- *
- * \param h Content to retrieve objects from
- * \param n Pointer to location to receive number of objects
- * \return Pointer to list of objects
- */
-struct content_html_object *html_get_objects(hlcache_handle *h, unsigned int *n)
-{
- html_content *c = (html_content *) hlcache_handle_get_content(h);
-
- assert(c != NULL);
- assert(n != NULL);
-
- *n = c->num_objects;
-
- return c->object_list;
-}
/**
* Retrieve layout coordinates of box with given id
diff --git a/render/html_internal.h b/render/html_internal.h
index 4c43345..428cd39 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -165,10 +165,6 @@ typedef struct html_content {
} html_content;
-bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
- content_type permitted_types,
- int available_width, int available_height,
- bool background);
void html_set_status(html_content *c, const char *extra);
@@ -274,6 +270,30 @@ bool html_css_update_style(html_content *c, dom_node *style);
nserror html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx);
+/* in render/html_object.c */
+
+/**
+ * Start a fetch for an object required by a page.
+ *
+ * \param c content of type CONTENT_HTML
+ * \param url URL of object to fetch (copied)
+ * \param box box that will contain the object
+ * \param permitted_types bitmap of acceptable types
+ * \param available_width estimate of width of object
+ * \param available_height estimate of height of object
+ * \param background this is a background image
+ * \return true on success, false on memory exhaustion
+ */
+bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
+ content_type permitted_types,
+ int available_width, int available_height,
+ bool background);
+
+nserror html_object_free_objects(html_content *html);
+nserror html_object_close_objects(html_content *html);
+nserror html_object_open_objects(html_content *html, struct browser_window *bw);
+nserror html_object_abort_objects(html_content *html);
+
/* Useful dom_string pointers */
struct dom_string;
diff --git a/render/html_object.c b/render/html_object.c
new file mode 100644
index 0000000..d4d0ff9
--- /dev/null
+++ b/render/html_object.c
@@ -0,0 +1,616 @@
+/*
+ * Copyright 2013 Vincent Sanders <vince(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Processing for html content object operations.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdint.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+
+#include "content/hlcache.h"
+#include "desktop/options.h"
+#include "desktop/scrollbar.h"
+#include "render/box.h"
+#include "render/html_internal.h"
+#include "utils/corestrings.h"
+#include "utils/config.h"
+#include "utils/log.h"
+#include "utils/schedule.h"
+
+/* break reference loop */
+static void html_object_refresh(void *p);
+
+/**
+ * Retrieve objects used by HTML document
+ *
+ * \param h Content to retrieve objects from
+ * \param n Pointer to location to receive number of objects
+ * \return Pointer to list of objects
+ */
+struct content_html_object *html_get_objects(hlcache_handle *h, unsigned int *n)
+{
+ html_content *c = (html_content *) hlcache_handle_get_content(h);
+
+ assert(c != NULL);
+ assert(n != NULL);
+
+ *n = c->num_objects;
+
+ return c->object_list;
+}
+
+/**
+ * Handle object fetching or loading failure.
+ *
+ * \param box box containing object which failed to load
+ * \param content document of type CONTENT_HTML
+ * \param background the object was the background image for the box
+ */
+
+static void
+html_object_failed(struct box *box, html_content *content, bool background)
+{
+ /* Nothing to do */
+ return;
+}
+
+/**
+ * Update a box whose content has completed rendering.
+ */
+
+static void
+html_object_done(struct box *box,
+ hlcache_handle *object,
+ bool background)
+{
+ struct box *b;
+
+ if (background) {
+ box->background = object;
+ return;
+ }
+
+ box->object = object;
+
+ if (!(box->flags & REPLACE_DIM)) {
+ /* invalidate parent min, max widths */
+ for (b = box; b; b = b->parent)
+ b->max_width = UNKNOWN_MAX_WIDTH;
+
+ /* delete any clones of this box */
+ while (box->next && (box->next->flags & CLONE)) {
+ /* box_free_box(box->next); */
+ box->next = box->next->next;
+ }
+ }
+}
+
+/**
+ * Callback for hlcache_handle_retrieve() for objects.
+ */
+
+static nserror
+html_object_callback(hlcache_handle *object,
+ const hlcache_event *event,
+ void *pw)
+{
+ struct content_html_object *o = pw;
+ html_content *c = (html_content *) o->parent;
+ int x, y;
+ struct box *box;
+
+ assert(c->base.status != CONTENT_STATUS_ERROR);
+
+ box = o->box;
+
+ switch (event->type) {
+ case CONTENT_MSG_LOADING:
+ if (c->base.status != CONTENT_STATUS_LOADING && c->bw != NULL)
+ content_open(object,
+ c->bw, &c->base,
+ box->object_params);
+ break;
+
+ case CONTENT_MSG_READY:
+ if (content_can_reformat(object)) {
+ /* TODO: avoid knowledge of box internals here */
+ content_reformat(object, false,
+ box->max_width != UNKNOWN_MAX_WIDTH ?
+ box->width : 0,
+ box->max_width != UNKNOWN_MAX_WIDTH ?
+ box->height : 0);
+
+ /* Adjust parent content for new object size */
+ html_object_done(box, object, o->background);
+ if (c->base.status == CONTENT_STATUS_READY ||
+ c->base.status == CONTENT_STATUS_DONE)
+ content__reformat(&c->base, false,
+ c->base.available_width,
+ c->base.height);
+ }
+ break;
+
+ case CONTENT_MSG_DONE:
+ c->base.active--;
+ LOG(("%d fetches active", c->base.active));
+
+ html_object_done(box, object, o->background);
+
+ if (c->base.status != CONTENT_STATUS_LOADING &&
+ box->flags & REPLACE_DIM) {
+ union content_msg_data data;
+
+ if (!box_visible(box))
+ break;
+
+ box_coords(box, &x, &y);
+
+ data.redraw.x = x + box->padding[LEFT];
+ data.redraw.y = y + box->padding[TOP];
+ data.redraw.width = box->width;
+ data.redraw.height = box->height;
+ data.redraw.full_redraw = true;
+
+ content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
+ }
+ break;
+
+ case CONTENT_MSG_ERROR:
+ hlcache_handle_release(object);
+
+ o->content = NULL;
+
+ c->base.active--;
+ LOG(("%d fetches active", c->base.active));
+
+ content_add_error(&c->base, "?", 0);
+ html_object_failed(box, c, o->background);
+ break;
+
+ case CONTENT_MSG_STATUS:
+ if (event->data.explicit_status_text == NULL) {
+ /* Object content's status text updated */
+ union content_msg_data data;
+ data.explicit_status_text =
+ content_get_status_message(object);
+ html_set_status(c, data.explicit_status_text);
+ content_broadcast(&c->base, CONTENT_MSG_STATUS, data);
+ } else {
+ /* Object content wants to set explicit message */
+ content_broadcast(&c->base, CONTENT_MSG_STATUS,
+ event->data);
+ }
+ break;
+
+ case CONTENT_MSG_REFORMAT:
+ break;
+
+ case CONTENT_MSG_REDRAW:
+ if (c->base.status != CONTENT_STATUS_LOADING) {
+ union content_msg_data data = event->data;
+
+ if (!box_visible(box))
+ break;
+
+ box_coords(box, &x, &y);
+
+ if (hlcache_handle_get_content(object) ==
+ event->data.redraw.object) {
+ data.redraw.x = data.redraw.x *
+ box->width / content_get_width(object);
+ data.redraw.y = data.redraw.y *
+ box->height /
+ content_get_height(object);
+ data.redraw.width = data.redraw.width *
+ box->width / content_get_width(object);
+ data.redraw.height = data.redraw.height *
+ box->height /
+ content_get_height(object);
+ data.redraw.object_width = box->width;
+ data.redraw.object_height = box->height;
+ }
+
+ data.redraw.x += x + box->padding[LEFT];
+ data.redraw.y += y + box->padding[TOP];
+ data.redraw.object_x += x + box->padding[LEFT];
+ data.redraw.object_y += y + box->padding[TOP];
+
+ content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
+ }
+ break;
+
+ case CONTENT_MSG_REFRESH:
+ if (content_get_type(object) == CONTENT_HTML) {
+ /* only for HTML objects */
+ schedule(event->data.delay * 100,
+ html_object_refresh, o);
+ }
+
+ break;
+
+ case CONTENT_MSG_LINK:
+ /* Don't care about favicons that aren't on top level content */
+ break;
+
+ case CONTENT_MSG_GETCTX:
+ *(event->data.jscontext) = NULL;
+ break;
+
+ case CONTENT_MSG_SCROLL:
+ if (box->scroll_x != NULL)
+ scrollbar_set(box->scroll_x, event->data.scroll.x0,
+ false);
+ if (box->scroll_y != NULL)
+ scrollbar_set(box->scroll_y, event->data.scroll.y0,
+ false);
+ break;
+
+ case CONTENT_MSG_DRAGSAVE:
+ {
+ union content_msg_data msg_data;
+ if (event->data.dragsave.content == NULL)
+ msg_data.dragsave.content = object;
+ else
+ msg_data.dragsave.content =
+ event->data.dragsave.content;
+
+ content_broadcast(&c->base, CONTENT_MSG_DRAGSAVE, msg_data);
+ }
+ break;
+
+ case CONTENT_MSG_SAVELINK:
+ case CONTENT_MSG_POINTER:
+ /* These messages are for browser window layer.
+ * we're not interested, so pass them on. */
+ content_broadcast(&c->base, event->type, event->data);
+ break;
+
+ case CONTENT_MSG_CARET:
+ {
+ union html_focus_owner focus_owner;
+ focus_owner.content = box;
+
+ switch (event->data.caret.type) {
+ case CONTENT_CARET_REMOVE:
+ case CONTENT_CARET_HIDE:
+ html_set_focus(c, HTML_FOCUS_CONTENT, focus_owner,
+ true, 0, 0, 0, NULL);
+ break;
+ case CONTENT_CARET_SET_POS:
+ html_set_focus(c, HTML_FOCUS_CONTENT, focus_owner,
+ false, event->data.caret.pos.x,
+ event->data.caret.pos.y,
+ event->data.caret.pos.height,
+ event->data.caret.pos.clip);
+ break;
+ }
+ }
+ break;
+
+ case CONTENT_MSG_DRAG:
+ {
+ html_drag_type drag_type = HTML_DRAG_NONE;
+ union html_drag_owner drag_owner;
+ drag_owner.content = box;
+
+ switch (event->data.drag.type) {
+ case CONTENT_DRAG_NONE:
+ drag_type = HTML_DRAG_NONE;
+ drag_owner.no_owner = true;
+ break;
+ case CONTENT_DRAG_SCROLL:
+ drag_type = HTML_DRAG_CONTENT_SCROLL;
+ break;
+ case CONTENT_DRAG_SELECTION:
+ drag_type = HTML_DRAG_CONTENT_SELECTION;
+ break;
+ }
+ html_set_drag_type(c, drag_type, drag_owner,
+ event->data.drag.rect);
+ }
+ break;
+
+ case CONTENT_MSG_SELECTION:
+ {
+ html_selection_type sel_type;
+ union html_selection_owner sel_owner;
+
+ if (event->data.selection.selection) {
+ sel_type = HTML_SELECTION_CONTENT;
+ sel_owner.content = box;
+ } else {
+ sel_type = HTML_SELECTION_NONE;
+ sel_owner.none = true;
+ }
+ html_set_selection(c, sel_type, sel_owner,
+ event->data.selection.read_only);
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+
+ if (c->base.status == CONTENT_STATUS_READY && c->base.active == 0 &&
+ (event->type == CONTENT_MSG_LOADING ||
+ event->type == CONTENT_MSG_DONE ||
+ event->type == CONTENT_MSG_ERROR)) {
+ /* all objects have arrived */
+ content__reformat(&c->base, false, c->base.available_width,
+ c->base.height);
+ html_set_status(c, "");
+ content_set_done(&c->base);
+ }
+
+ /* If 1) the configuration option to reflow pages while objects are
+ * fetched is set
+ * 2) an object is newly fetched & converted,
+ * 3) the box's dimensions need to change due to being replaced
+ * 4) the object's parent HTML is ready for reformat,
+ * 5) the time since the previous reformat is more than the
+ * configured minimum time between reformats
+ * then reformat the page to display newly fetched objects */
+ else if (nsoption_bool(incremental_reflow) &&
+ event->type == CONTENT_MSG_DONE &&
+ !(box->flags & REPLACE_DIM) &&
+ (c->base.status == CONTENT_STATUS_READY ||
+ c->base.status == CONTENT_STATUS_DONE) &&
+ (wallclock() > c->base.reformat_time)) {
+ content__reformat(&c->base, false, c->base.available_width,
+ c->base.height);
+ }
+
+ return NSERROR_OK;
+}
+
+/**
+ * Start a fetch for an object required by a page, replacing an existing object.
+ *
+ * \param object Object to replace
+ * \param url URL of object to fetch (copied)
+ * \return true on success, false on memory exhaustion
+ */
+
+static bool html_replace_object(struct content_html_object *object, nsurl *url)
+{
+ html_content *c;
+ hlcache_child_context child;
+ html_content *page;
+ nserror error;
+
+ assert(object != NULL);
+
+ c = (html_content *) object->parent;
+
+ child.charset = c->encoding;
+ child.quirks = c->base.quirks;
+
+ if (object->content != NULL) {
+ /* remove existing object */
+ if (content_get_status(object->content) != CONTENT_STATUS_DONE) {
+ c->base.active--;
+ LOG(("%d fetches active", c->base.active));
+ }
+
+ hlcache_handle_release(object->content);
+ object->content = NULL;
+
+ object->box->object = NULL;
+ }
+
+ /* initialise fetch */
+ error = hlcache_handle_retrieve(url, HLCACHE_RETRIEVE_SNIFF_TYPE,
+ content_get_url(&c->base), NULL,
+ html_object_callback, object, &child,
+ object->permitted_types,
+ &object->content);
+
+ if (error != NSERROR_OK)
+ return false;
+
+ for (page = c; page != NULL; page = page->page) {
+ page->base.active++;
+ LOG(("%d fetches active", c->base.active));
+
+ page->base.status = CONTENT_STATUS_READY;
+ }
+
+ return true;
+}
+
+/**
+ * schedule() callback for object refresh
+ */
+
+static void html_object_refresh(void *p)
+{
+ struct content_html_object *object = p;
+ nsurl *refresh_url;
+
+ assert(content_get_type(object->content) == CONTENT_HTML);
+
+ refresh_url = content_get_refresh_url(object->content);
+
+ /* Ignore if refresh URL has gone
+ * (may happen if fetch errored) */
+ if (refresh_url == NULL)
+ return;
+
+ content_invalidate_reuse_data(object->content);
+
+ if (!html_replace_object(object, refresh_url)) {
+ /** \todo handle memory exhaustion */
+ }
+}
+
+nserror html_object_open_objects(html_content *html, struct browser_window *bw)
+{
+ struct content_html_object *object, *next;
+
+ for (object = html->object_list; object != NULL; object = next) {
+ next = object->next;
+
+ if (object->content == NULL)
+ continue;
+
+ if (content_get_type(object->content) == CONTENT_NONE)
+ continue;
+
+ content_open(object->content,
+ bw,
+ &html->base,
+ object->box->object_params);
+ }
+ return NSERROR_OK;
+}
+
+nserror html_object_abort_objects(html_content *htmlc)
+{
+ struct content_html_object *object;
+
+ for (object = htmlc->object_list;
+ object != NULL;
+ object = object->next) {
+ if (object->content == NULL)
+ continue;
+
+ switch (content_get_status(object->content)) {
+ case CONTENT_STATUS_DONE:
+ /* already loaded: do nothing */
+ break;
+
+ case CONTENT_STATUS_READY:
+ hlcache_handle_abort(object->content);
+ /* Active count will be updated when
+ * html_object_callback receives
+ * CONTENT_MSG_DONE from this object
+ */
+ break;
+
+ default:
+ hlcache_handle_abort(object->content);
+ hlcache_handle_release(object->content);
+ object->content = NULL;
+
+ htmlc->base.active--;
+ LOG(("%d fetches active", htmlc->base.active));
+ break;
+
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+nserror html_object_close_objects(html_content *html)
+{
+ struct content_html_object *object, *next;
+
+ for (object = html->object_list; object != NULL; object = next) {
+ next = object->next;
+
+ if (object->content == NULL)
+ continue;
+
+ if (content_get_type(object->content) == CONTENT_NONE)
+ continue;
+
+ if (content_get_type(object->content) == CONTENT_HTML)
+ schedule_remove(html_object_refresh, object);
+
+ content_close(object->content);
+ }
+ return NSERROR_OK;
+}
+
+nserror html_object_free_objects(html_content *html)
+{
+ while (html->object_list != NULL) {
+ struct content_html_object *victim = html->object_list;
+
+ if (victim->content != NULL) {
+ LOG(("object %p", victim->content));
+
+ if (content_get_type(victim->content) == CONTENT_HTML)
+ schedule_remove(html_object_refresh, victim);
+
+ hlcache_handle_release(victim->content);
+ }
+
+ html->object_list = victim->next;
+ free(victim);
+ }
+ return NSERROR_OK;
+}
+
+
+
+/* exported interface documented in render/html_internal.h */
+bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
+ content_type permitted_types,
+ int available_width, int available_height,
+ bool background)
+{
+ struct content_html_object *object;
+ hlcache_child_context child;
+ nserror error;
+
+ /* If we've already been aborted, don't bother attempting the fetch */
+ if (c->aborted)
+ return true;
+
+ child.charset = c->encoding;
+ child.quirks = c->base.quirks;
+
+ object = calloc(1, sizeof(struct content_html_object));
+ if (object == NULL) {
+ return false;
+ }
+
+ object->parent = (struct content *) c;
+ object->next = NULL;
+ object->content = NULL;
+ object->box = box;
+ object->permitted_types = permitted_types;
+ object->background = background;
+
+ error = hlcache_handle_retrieve(url,
+ HLCACHE_RETRIEVE_SNIFF_TYPE,
+ content_get_url(&c->base), NULL,
+ html_object_callback, object, &child,
+ object->permitted_types, &object->content);
+ if (error != NSERROR_OK) {
+ free(object);
+ return error != NSERROR_NOMEM;
+ }
+
+ /* add to content object list */
+ object->next = c->object_list;
+ c->object_list = object;
+
+ c->num_objects++;
+ c->base.active++;
+ LOG(("%d fetches active", c->base.active));
+
+ return true;
+}
--
NetSurf Browser
10 years, 7 months
netsurf: branch master updated. 4e7b4259a44703ecc0994c922315b67df7096c90
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/4e7b4259a44703ecc0994...
...commit http://git.netsurf-browser.org/netsurf.git/commit/4e7b4259a44703ecc0994c9...
...tree http://git.netsurf-browser.org/netsurf.git/tree/4e7b4259a44703ecc0994c922...
The branch, master has been updated
via 4e7b4259a44703ecc0994c922315b67df7096c90 (commit)
from dd35da2cac223551c8041a7795eba82fa99ded87 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commitdiff/4e7b4259a44703ecc09...
commit 4e7b4259a44703ecc0994c922315b67df7096c90
Author: Vincent Sanders <vince(a)netsurf-browser.org>
Commit: Vincent Sanders <vince(a)netsurf-browser.org>
fix quirk stylesheet loading
diff --git a/render/html.c b/render/html.c
index 2e4e4dd..7414ced 100644
--- a/render/html.c
+++ b/render/html.c
@@ -287,6 +287,12 @@ dom_default_action_DOMSubtreeModified_cb(struct dom_event *evt, void *pw)
* selects a callback function for libdom to call based on the type and phase.
* dom_default_action_phase from events/document_event.h
*
+ * The principle events are:
+ * DOMSubtreeModified
+ * DOMAttrModified
+ * DOMNodeInserted
+ * DOMNodeInsertedIntoDocument
+ *
* @return callback function pointer or NULL for none
*/
static dom_default_action_callback
@@ -1508,10 +1514,30 @@ static void html_object_refresh(void *p)
static bool html_convert(struct content *c)
{
html_content *htmlc = (html_content *) c;
+ dom_exception exc; /* returned by libdom functions */
+
+ /* The quirk check and associated stylesheet fetch is "safe"
+ * once the root node has been inserted into the document
+ * which must have happened by this point in the parse.
+ *
+ * faliure to retrive the quirk mode or to start the
+ * stylesheet fetch is non fatal as this "only" affects the
+ * render and it would annoy the user to fail the entire
+ * render for want of a quirks stylesheet.
+ */
+ exc = dom_document_get_quirks_mode(htmlc->document, &htmlc->quirks);
+ if (exc == DOM_NO_ERR) {
+ html_css_quirks_stylesheets(htmlc);
+ LOG(("quirks set to %d", htmlc->quirks));
+ }
htmlc->base.active--; /* the html fetch is no longer active */
LOG(("%d fetches active", htmlc->base.active));
+ /* The parse cannot be completed here because it may be paused
+ * untill all the resources being fetched have completed.
+ */
+
/* if there are no active fetches in progress no scripts are
* being fetched or they completed already.
*/
@@ -1549,7 +1575,6 @@ html_begin_conversion(html_content *htmlc)
return false;
}
-
/* complete script execution */
html_scripts_exec(htmlc);
@@ -1557,14 +1582,6 @@ html_begin_conversion(html_content *htmlc)
* the Document.
*/
- /* quirks mode */
- exc = dom_document_get_quirks_mode(htmlc->document, &htmlc->quirks);
- if (exc != DOM_NO_ERR) {
- LOG(("error retrieving quirks"));
- /** @todo should this be fatal to the conversion? */
- }
- LOG(("quirks set to %d", htmlc->quirks));
-
/* get encoding */
if (htmlc->encoding == NULL) {
const char *encoding;
diff --git a/render/html_css.c b/render/html_css.c
index babe052..e14a781 100644
--- a/render/html_css.c
+++ b/render/html_css.c
@@ -184,6 +184,34 @@ nserror html_css_free_stylesheets(html_content *html)
}
/* exported interface documented in render/html_internal.h */
+nserror html_css_quirks_stylesheets(html_content *c)
+{
+ nserror ns_error = NSERROR_OK;
+ hlcache_child_context child;
+
+ assert(c->stylesheets != NULL);
+
+ if (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL) {
+ child.charset = c->encoding;
+ child.quirks = c->base.quirks;
+
+ ns_error = hlcache_handle_retrieve(html_quirks_stylesheet_url,
+ 0, content_get_url(&c->base), NULL,
+ html_convert_css_callback, c, &child,
+ CONTENT_CSS,
+ &c->stylesheets[STYLESHEET_QUIRKS].data.external);
+ if (ns_error != NSERROR_OK) {
+ return ns_error;
+ }
+
+ c->base.active++;
+ LOG(("%d fetches active", c->base.active));
+ }
+
+ return ns_error;
+}
+
+/* exported interface documented in render/html_internal.h */
nserror html_css_new_stylesheets(html_content *c)
{
nserror ns_error;
@@ -226,20 +254,6 @@ nserror html_css_new_stylesheets(html_content *c)
c->base.active++;
LOG(("%d fetches active", c->base.active));
- if (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL) {
- ns_error = hlcache_handle_retrieve(html_quirks_stylesheet_url,
- 0, content_get_url(&c->base), NULL,
- html_convert_css_callback, c, &child,
- CONTENT_CSS,
- &c->stylesheets[STYLESHEET_QUIRKS].data.external);
- if (ns_error != NSERROR_OK) {
- return ns_error;
- }
-
- c->base.active++;
- LOG(("%d fetches active", c->base.active));
-
- }
if (nsoption_bool(block_ads)) {
ns_error = hlcache_handle_retrieve(html_adblock_stylesheet_url,
diff --git a/render/html_internal.h b/render/html_internal.h
index 2dd1c51..4c43345 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -266,6 +266,7 @@ void html_css_fini(void);
* \return nserror
*/
nserror html_css_new_stylesheets(html_content *c);
+nserror html_css_quirks_stylesheets(html_content *c);
nserror html_css_free_stylesheets(html_content *html);
bool html_css_process_link(html_content *htmlc, dom_node *node);
-----------------------------------------------------------------------
Summary of changes:
render/html.c | 35 ++++++++++++++++++++++++++---------
render/html_css.c | 42 ++++++++++++++++++++++++++++--------------
render/html_internal.h | 1 +
3 files changed, 55 insertions(+), 23 deletions(-)
diff --git a/render/html.c b/render/html.c
index 2e4e4dd..7414ced 100644
--- a/render/html.c
+++ b/render/html.c
@@ -287,6 +287,12 @@ dom_default_action_DOMSubtreeModified_cb(struct dom_event *evt, void *pw)
* selects a callback function for libdom to call based on the type and phase.
* dom_default_action_phase from events/document_event.h
*
+ * The principle events are:
+ * DOMSubtreeModified
+ * DOMAttrModified
+ * DOMNodeInserted
+ * DOMNodeInsertedIntoDocument
+ *
* @return callback function pointer or NULL for none
*/
static dom_default_action_callback
@@ -1508,10 +1514,30 @@ static void html_object_refresh(void *p)
static bool html_convert(struct content *c)
{
html_content *htmlc = (html_content *) c;
+ dom_exception exc; /* returned by libdom functions */
+
+ /* The quirk check and associated stylesheet fetch is "safe"
+ * once the root node has been inserted into the document
+ * which must have happened by this point in the parse.
+ *
+ * faliure to retrive the quirk mode or to start the
+ * stylesheet fetch is non fatal as this "only" affects the
+ * render and it would annoy the user to fail the entire
+ * render for want of a quirks stylesheet.
+ */
+ exc = dom_document_get_quirks_mode(htmlc->document, &htmlc->quirks);
+ if (exc == DOM_NO_ERR) {
+ html_css_quirks_stylesheets(htmlc);
+ LOG(("quirks set to %d", htmlc->quirks));
+ }
htmlc->base.active--; /* the html fetch is no longer active */
LOG(("%d fetches active", htmlc->base.active));
+ /* The parse cannot be completed here because it may be paused
+ * untill all the resources being fetched have completed.
+ */
+
/* if there are no active fetches in progress no scripts are
* being fetched or they completed already.
*/
@@ -1549,7 +1575,6 @@ html_begin_conversion(html_content *htmlc)
return false;
}
-
/* complete script execution */
html_scripts_exec(htmlc);
@@ -1557,14 +1582,6 @@ html_begin_conversion(html_content *htmlc)
* the Document.
*/
- /* quirks mode */
- exc = dom_document_get_quirks_mode(htmlc->document, &htmlc->quirks);
- if (exc != DOM_NO_ERR) {
- LOG(("error retrieving quirks"));
- /** @todo should this be fatal to the conversion? */
- }
- LOG(("quirks set to %d", htmlc->quirks));
-
/* get encoding */
if (htmlc->encoding == NULL) {
const char *encoding;
diff --git a/render/html_css.c b/render/html_css.c
index babe052..e14a781 100644
--- a/render/html_css.c
+++ b/render/html_css.c
@@ -184,6 +184,34 @@ nserror html_css_free_stylesheets(html_content *html)
}
/* exported interface documented in render/html_internal.h */
+nserror html_css_quirks_stylesheets(html_content *c)
+{
+ nserror ns_error = NSERROR_OK;
+ hlcache_child_context child;
+
+ assert(c->stylesheets != NULL);
+
+ if (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL) {
+ child.charset = c->encoding;
+ child.quirks = c->base.quirks;
+
+ ns_error = hlcache_handle_retrieve(html_quirks_stylesheet_url,
+ 0, content_get_url(&c->base), NULL,
+ html_convert_css_callback, c, &child,
+ CONTENT_CSS,
+ &c->stylesheets[STYLESHEET_QUIRKS].data.external);
+ if (ns_error != NSERROR_OK) {
+ return ns_error;
+ }
+
+ c->base.active++;
+ LOG(("%d fetches active", c->base.active));
+ }
+
+ return ns_error;
+}
+
+/* exported interface documented in render/html_internal.h */
nserror html_css_new_stylesheets(html_content *c)
{
nserror ns_error;
@@ -226,20 +254,6 @@ nserror html_css_new_stylesheets(html_content *c)
c->base.active++;
LOG(("%d fetches active", c->base.active));
- if (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL) {
- ns_error = hlcache_handle_retrieve(html_quirks_stylesheet_url,
- 0, content_get_url(&c->base), NULL,
- html_convert_css_callback, c, &child,
- CONTENT_CSS,
- &c->stylesheets[STYLESHEET_QUIRKS].data.external);
- if (ns_error != NSERROR_OK) {
- return ns_error;
- }
-
- c->base.active++;
- LOG(("%d fetches active", c->base.active));
-
- }
if (nsoption_bool(block_ads)) {
ns_error = hlcache_handle_retrieve(html_adblock_stylesheet_url,
diff --git a/render/html_internal.h b/render/html_internal.h
index 2dd1c51..4c43345 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -266,6 +266,7 @@ void html_css_fini(void);
* \return nserror
*/
nserror html_css_new_stylesheets(html_content *c);
+nserror html_css_quirks_stylesheets(html_content *c);
nserror html_css_free_stylesheets(html_content *html);
bool html_css_process_link(html_content *htmlc, dom_node *node);
--
NetSurf Browser
10 years, 7 months
netsurf: branch master updated. dd35da2cac223551c8041a7795eba82fa99ded87
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/dd35da2cac223551c8041...
...commit http://git.netsurf-browser.org/netsurf.git/commit/dd35da2cac223551c8041a7...
...tree http://git.netsurf-browser.org/netsurf.git/tree/dd35da2cac223551c8041a779...
The branch, master has been updated
via dd35da2cac223551c8041a7795eba82fa99ded87 (commit)
via 3c373994f96914d0aec364c8954af857d3719bab (commit)
from 142922d10a533f5b068a616fc95e2d027c859fc5 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commitdiff/dd35da2cac223551c80...
commit dd35da2cac223551c8041a7795eba82fa99ded87
Merge: 3c37399 142922d
Author: Steve Fryatt <stevef(a)netsurf-browser.org>
Commit: Steve Fryatt <stevef(a)netsurf-browser.org>
Merge branch 'master' of git://git.netsurf-browser.org/netsurf
commitdiff http://git.netsurf-browser.org/netsurf.git/commitdiff/3c373994f96914d0aec...
commit 3c373994f96914d0aec364c8954af857d3719bab
Author: Steve Fryatt <stevef(a)netsurf-browser.org>
Commit: Steve Fryatt <stevef(a)netsurf-browser.org>
Set Message_DataRequest length correctly.
diff --git a/riscos/textselection.c b/riscos/textselection.c
index 7e24893..579936b 100644
--- a/riscos/textselection.c
+++ b/riscos/textselection.c
@@ -328,7 +328,7 @@ void ro_gui_selection_prepare_paste(wimp_w w,
ro_gui_discard_clipboard_contents();
- msg.size = sizeof(msg);
+ msg.size = 48; /* There's only one filetype listed. */
msg.your_ref = 0;
msg.action = message_DATA_REQUEST;
msg.w = w;
-----------------------------------------------------------------------
Summary of changes:
riscos/textselection.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/riscos/textselection.c b/riscos/textselection.c
index f344e47..a1a0288 100644
--- a/riscos/textselection.c
+++ b/riscos/textselection.c
@@ -328,7 +328,7 @@ void ro_gui_selection_prepare_paste(wimp_w w,
ro_gui_discard_clipboard_contents();
- msg.size = sizeof(msg);
+ msg.size = 48; /* There's only one filetype listed. */
msg.your_ref = 0;
msg.action = message_DATA_REQUEST;
msg.w = w;
--
NetSurf Browser
10 years, 7 months