From 270ef59a98d34fef418fb6cd27e46f3edc912948 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sun, 28 Mar 2010 12:56:39 +0000 Subject: Merge jmb/new-cache; r=dsilvers,rs=vince svn path=/trunk/netsurf/; revision=10180 --- render/box.c | 76 ++-- render/box.h | 10 +- render/box_construct.c | 6 +- render/directory.c | 16 +- render/directory.h | 4 +- render/favicon.c | 163 ++++----- render/favicon.h | 3 +- render/form.c | 31 +- render/form.h | 13 +- render/html.c | 925 ++++++++++++++++++++++++++++--------------------- render/html.h | 43 ++- render/html_redraw.c | 157 +++++---- render/imagemap.c | 20 +- render/imagemap.h | 4 +- render/layout.c | 118 ++++--- render/textplain.c | 112 ++++-- render/textplain.h | 20 +- 17 files changed, 954 insertions(+), 767 deletions(-) (limited to 'render') diff --git a/render/box.c b/render/box.c index b355e68d1..e09a4772c 100644 --- a/render/box.c +++ b/render/box.c @@ -26,7 +26,8 @@ #include #include #include -#include "content/content.h" +#include "content/content_protected.h" +#include "content/hlcache.h" #include "css/css.h" #include "css/dump.h" #include "desktop/scroll.h" @@ -312,7 +313,7 @@ void box_bounds(struct box *box, struct rect *r) struct box *box_at_point(struct box *box, const int x, const int y, int *box_x, int *box_y, - struct content **content) + hlcache_handle **content) { int bx = *box_x, by = *box_y; struct box *child, *sibling; @@ -321,11 +322,14 @@ struct box *box_at_point(struct box *box, const int x, const int y, assert(box); /* drill into HTML objects */ - if (box->object) { - if (box->object->type == CONTENT_HTML && - box->object->data.html.layout) { + if (box->object != NULL) { + struct box *layout; + + if (content_get_type(box->object) == CONTENT_HTML && + (layout = html_get_box_tree(box->object)) != + NULL) { *content = box->object; - box = box->object->data.html.layout; + box = layout; } else { goto siblings; } @@ -503,20 +507,24 @@ bool box_contains_point(struct box *box, int x, int y, bool *physically) /** * Find the box containing an object at the given coordinates, if any. * - * \param c content to search, must have type CONTENT_HTML + * \param h content to search, must have type CONTENT_HTML * \param x coordinates in document units * \param y coordinates in document units */ -struct box *box_object_at_point(struct content *c, int x, int y) +struct box *box_object_at_point(hlcache_handle *h, int x, int y) { - struct box *box = c->data.html.layout; + struct content *c = hlcache_handle_get_content(h); + struct box *box; int box_x = 0, box_y = 0; - struct content *content = c; + hlcache_handle *content = h; struct box *object_box = 0; + assert(c != NULL); assert(c->type == CONTENT_HTML); + box = c->data.html.layout; + while ((box = box_at_point(box, x, y, &box_x, &box_y, &content))) { if (box->style && css_computed_visibility(box->style) == CSS_VISIBILITY_HIDDEN) @@ -533,20 +541,24 @@ struct box *box_object_at_point(struct content *c, int x, int y) /** * Find the box containing an href at the given coordinates, if any. * - * \param c content to search, must have type CONTENT_HTML + * \param h content to search, must have type CONTENT_HTML * \param x coordinates in document units * \param y coordinates in document units */ -struct box *box_href_at_point(struct content *c, int x, int y) +struct box *box_href_at_point(hlcache_handle *h, int x, int y) { - struct box *box = c->data.html.layout; + struct content *c = hlcache_handle_get_content(h); + struct box *box; int box_x = 0, box_y = 0; - struct content *content = c; + hlcache_handle *content = h; struct box *href_box = 0; + assert(c != NULL); assert(c->type == CONTENT_HTML); + box = c->data.html.layout; + while ((box = box_at_point(box, x, y, &box_x, &box_y, &content))) { if (box->style && css_computed_visibility(box->style) == CSS_VISIBILITY_HIDDEN) @@ -663,8 +675,10 @@ void box_dump(FILE *stream, struct box *box, unsigned int depth) (int) box->length, box->text); if (box->space) fprintf(stream, "space "); - if (box->object) - fprintf(stream, "(object '%s') ", box->object->url); + if (box->object) { + fprintf(stream, "(object '%s') ", + content_get_url(box->object)); + } if (box->gadget) fprintf(stream, "(gadget) "); if (box->style) @@ -860,42 +874,42 @@ bool box_duplicate_main_tree(struct box *box, struct content *c, int *count) box->last = prev; - if (box->object && option_suppress_images && ( + if (box->object != NULL && option_suppress_images && ( #ifdef WITH_JPEG - box->object->type == CONTENT_JPEG || + content_get_type(box->object) == CONTENT_JPEG || #endif #ifdef WITH_GIF - box->object->type == CONTENT_GIF || + content_get_type(box->object) == CONTENT_GIF || #endif #ifdef WITH_BMP - box->object->type == CONTENT_BMP || - box->object->type == CONTENT_ICO || + content_get_type(box->object) == CONTENT_BMP || + content_get_type(box->object) == CONTENT_ICO || #endif #if defined(WITH_MNG) || defined(WITH_PNG) - box->object->type == CONTENT_PNG || + content_get_type(box->object) == CONTENT_PNG || #endif #ifdef WITH_MNG - box->object->type == CONTENT_JNG || - box->object->type == CONTENT_MNG || + content_get_type(box->object) == CONTENT_JNG || + content_get_type(box->object) == CONTENT_MNG || #endif #if defined(WITH_SPRITE) || defined(WITH_NSSPRITE) - box->object->type == CONTENT_SPRITE || + content_get_type(box->object) == CONTENT_SPRITE || #endif #ifdef WITH_DRAW - box->object->type == CONTENT_DRAW || + content_get_type(box->object) == CONTENT_DRAW || #endif #ifdef WITH_PLUGIN - box->object->type == CONTENT_PLUGIN || + content_get_type(box->object) == CONTENT_PLUGIN || #endif - box->object->type == CONTENT_DIRECTORY || + content_get_type(box->object) == CONTENT_DIRECTORY || #ifdef WITH_THEME_INSTALL - box->object->type == CONTENT_THEME || + content_get_type(box->object) == CONTENT_THEME || #endif #ifdef WITH_ARTWORKS - box->object->type == CONTENT_ARTWORKS || + content_get_type(box->object) == CONTENT_ARTWORKS || #endif #if defined(WITH_NS_SVG) || defined(WITH_RSVG) - box->object->type == CONTENT_SVG || + content_get_type(box->object) == CONTENT_SVG || #endif false)) box->object = NULL; diff --git a/render/box.h b/render/box.h index b53e0481c..665565f2f 100644 --- a/render/box.h +++ b/render/box.h @@ -239,10 +239,10 @@ struct box { char *id; /**< value of id attribute (or name for anchors) */ /** Background image for this box, or 0 if none */ - struct content *background; + struct hlcache_handle *background; /** Object in this box (usually an image), or 0 if none. */ - struct content* object; + struct hlcache_handle* object; /** Parameters for the object, or 0. */ struct object_params *object_params; }; @@ -307,9 +307,9 @@ void box_free_object_params(struct object_params *op); void box_bounds(struct box *box, struct rect *r); void box_coords(struct box *box, int *x, int *y); struct box *box_at_point(struct box *box, const int x, const int y, - int *box_x, int *box_y, struct content **content); -struct box *box_object_at_point(struct content *c, int x, int y); -struct box *box_href_at_point(struct content *c, int x, int y); + int *box_x, int *box_y, struct hlcache_handle **content); +struct box *box_object_at_point(struct hlcache_handle *h, int x, int y); +struct box *box_href_at_point(struct hlcache_handle *h, int x, int y); struct box *box_find_by_id(struct box *box, const char *id); bool box_visible(struct box *box); void box_dump(FILE *stream, struct box *box, unsigned int depth); diff --git a/render/box_construct.c b/render/box_construct.c index bdab6159e..71d30ddae 100644 --- a/render/box_construct.c +++ b/render/box_construct.c @@ -35,7 +35,7 @@ #include #include #include "utils/config.h" -#include "content/content.h" +#include "content/content_protected.h" #include "css/css.h" #include "css/utils.h" #include "css/select.h" @@ -841,9 +841,9 @@ css_computed_style *box_get_style(struct content *c, if ((s = (char *) xmlGetProp(n, (const xmlChar *) "style"))) { inline_style = nscss_create_inline_style( (uint8_t *) s, strlen(s), - c->data.html.encoding, c->url, + c->data.html.encoding, content__get_url(c), c->data.html.quirks != BINDING_QUIRKS_MODE_NONE, - c->data.html.dict, myrealloc, c); + myrealloc, c); xmlFree(s); diff --git a/render/directory.c b/render/directory.c index 82f24efa2..9f002d831 100644 --- a/render/directory.c +++ b/render/directory.c @@ -28,7 +28,7 @@ #include #include #include -#include "content/content.h" +#include "content/content_protected.h" #include "render/directory.h" #include "render/html.h" #include "utils/messages.h" @@ -40,9 +40,8 @@ static const char header[] = "\n\n\n"; static const char footer[] = "</pre>\n</body>\n</html>\n"; -bool directory_create(struct content *c, struct content *parent, - const char *params[]) { - if (!html_create(c, parent, params)) +bool directory_create(struct content *c, const struct http_parameter *params) { + if (!html_create(c, params)) /* html_create() must have broadcast MSG_ERROR already, so we * don't need to. */ return false; @@ -64,7 +63,7 @@ bool directory_convert(struct content *c, int width, int height) { bool compare; char *up; - path = url_to_path(c->url); + path = url_to_path(content__get_url(c)); if (!path) { msg_data.error = messages_get("NoMemory"); content_broadcast(c, CONTENT_MSG_ERROR, msg_data); @@ -100,9 +99,9 @@ bool directory_convert(struct content *c, int width, int height) { binding_parse_chunk(c->data.html.parser_binding, (uint8_t *) buffer, strlen(buffer)); - res = url_parent(c->url, &up); + res = url_parent(content__get_url(c), &up); if (res == URL_FUNC_OK) { - res = url_compare(c->url, up, false, &compare); + res = url_compare(content__get_url(c), up, false, &compare); if ((res == URL_FUNC_OK) && !compare) { snprintf(buffer, sizeof(buffer), "<a href=\"..\">[..]</a>\n"); @@ -124,7 +123,8 @@ bool directory_convert(struct content *c, int width, int height) { continue; snprintf(buffer, sizeof(buffer), "<a href=\"%s/%s\">%s</a>\n", - c->url, entry->d_name, entry->d_name); + content__get_url(c), entry->d_name, + entry->d_name); binding_parse_chunk(c->data.html.parser_binding, (uint8_t *) buffer, strlen(buffer)); diff --git a/render/directory.h b/render/directory.h index a54d516fb..766593294 100644 --- a/render/directory.h +++ b/render/directory.h @@ -28,9 +28,9 @@ #include <stdbool.h> #include "content/content_type.h" +struct http_parameter; -bool directory_create(struct content *c, struct content *parent, - const char *params[]); +bool directory_create(struct content *c, const struct http_parameter *params); bool directory_convert(struct content *c, int width, int height); void directory_destroy(struct content *c); diff --git a/render/favicon.c b/render/favicon.c index ec5caeae0..191c55e8a 100644 --- a/render/favicon.c +++ b/render/favicon.c @@ -18,8 +18,8 @@ */ #include <string.h> -#include "content/fetch.h" -#include "content/fetchcache.h" +#include "content/content_protected.h" +#include "content/hlcache.h" #include "render/favicon.h" #include "render/html.h" #include "utils/log.h" @@ -29,8 +29,8 @@ #include "utils/utils.h" static char *favicon_get_icon_ref(struct content *c, xmlNode *html); -static void favicon_callback(content_msg msg, struct content *icon, - intptr_t p1, intptr_t p2, union content_msg_data data); +static nserror favicon_callback(hlcache_handle *icon, + const hlcache_event *event, void *pw); /** * retrieve 1 url reference to 1 favicon @@ -39,68 +39,80 @@ static void favicon_callback(content_msg msg, struct content *icon, */ char *favicon_get_icon_ref(struct content *c, xmlNode *html) { - xmlNode *node; - char *rel, *href, *url, *url2; + xmlNode *node = html; + char *rel, *href, *url, *url2 = NULL; url_func_result res; - union content_msg_data msg_data; - url2 = NULL; - node = html; while (node) { - if (node->children) { /* children */ + if (node->children != NULL) { /* children */ node = node->children; - } else if (node->next) { /* siblings */ + } else if (node->next != NULL) { /* siblings */ node = node->next; } else { /* ancestor siblings */ - while (node && !node->next) + while (node != NULL && node->next == NULL) node = node->parent; - if (!node) + + if (node == NULL) break; + node = node->next; } - assert(node); + + assert(node != NULL); if (node->type != XML_ELEMENT_NODE) continue; + if (strcmp((const char *) node->name, "link") == 0) { /* rel=<space separated list, including 'icon'> */ if ((rel = (char *) xmlGetProp(node, (const xmlChar *) "rel")) == NULL) continue; + if (strcasestr(rel, "icon") == 0) { xmlFree(rel); continue; } - LOG(("icon node found")); + if (strcasecmp(rel, "apple-touch-icon") == 0) { xmlFree(rel); continue; } + xmlFree(rel); - if (( href = (char *) xmlGetProp(node, + + if ((href = (char *) xmlGetProp(node, (const xmlChar *) "href")) == NULL) continue; - res = url_join(href, c->data.html.base_url, - &url); + + res = url_join(href, c->data.html.base_url, &url); + xmlFree(href); + if (res != URL_FUNC_OK) continue; - LOG(("most recent favicon '%s'", url)); + if (url2 != NULL) { free(url2); url2 = NULL; } + res = url_normalize(url, &url2); + free(url); + if (res != URL_FUNC_OK) { url2 = NULL; + if (res == URL_FUNC_NOMEM) - goto no_memory; + return NULL; + continue; } } } + if (url2 == NULL) { char *scheme; @@ -123,12 +135,8 @@ char *favicon_get_icon_ref(struct content *c, xmlNode *html) != URL_FUNC_OK) return NULL; } - LOG(("favicon %s", url2)); + return url2; -no_memory: - msg_data.error = messages_get("NoMemory"); - /* content_broadcast(c, CONTENT_MSG_ERROR, msg_data); */ - return false; } /** @@ -140,31 +148,27 @@ no_memory: bool favicon_get_icon(struct content *c, xmlNode *html) { - char *url = favicon_get_icon_ref(c, html); - struct content *favcontent = NULL; + char *url; + nserror error; + + url = favicon_get_icon_ref(c, html); if (url == NULL) return false; - - favcontent = fetchcache(url, favicon_callback, (intptr_t) c, 0, - c->width, c->height, true, 0, 0, false, false); - free(url); - if (favcontent == NULL) - return false; - c->data.html.favicon = favcontent; - - fetchcache_go(favcontent, c->url, favicon_callback, (intptr_t) c, 0, - c->width, c->height, 0, 0, false, c); + error = hlcache_handle_retrieve(url, 0, NULL, NULL, c->width, c->height, + favicon_callback, c, NULL, &c->data.html.favicon); + + free(url); - return true; + return error == NSERROR_OK; } /** * Callback for fetchcache() for linked favicon */ -void favicon_callback(content_msg msg, struct content *icon, - intptr_t p1, intptr_t p2, union content_msg_data data) +nserror favicon_callback(hlcache_handle *icon, + const hlcache_event *event, void *pw) { static const content_type permitted_types[] = { #ifdef WITH_BMP @@ -178,88 +182,57 @@ void favicon_callback(content_msg msg, struct content *icon, #endif CONTENT_UNKNOWN }; - struct content *c = (struct content *) p1; - unsigned int i = p2; + struct content *c = pw; const content_type *type; - - switch (msg) { + switch (event->type) { case CONTENT_MSG_LOADING: /* check that the favicon is really a correct image type */ for (type = permitted_types; *type != CONTENT_UNKNOWN; type++) - if (icon->type == *type) + if (content_get_type(icon) == *type) break; if (*type == CONTENT_UNKNOWN) { - c->data.html.favicon = 0; - LOG(("%s is not a favicon", icon->url)); + union content_msg_data msg_data; + + hlcache_handle_release(c->data.html.favicon); + c->data.html.favicon = NULL; + LOG(("%s is not a favicon", content_get_url(icon))); content_add_error(c, "NotFavIco", 0); - html_set_status(c, messages_get("NotFavIco")); - content_broadcast(c, CONTENT_MSG_STATUS, data); - content_remove_user(icon, - favicon_callback, - (intptr_t) c, i); - if (!icon->user_list->next) { - /* we were the only user and we don't want this - * content, so stop it fetching and mark it as - * having an error so it gets removed from the - * cache next time content_clean() gets called - */ - fetch_abort(icon->fetch); - icon->fetch = 0; - icon->status = CONTENT_STATUS_ERROR; - } + + msg_data.error = messages_get("NotFavIco"); + content_broadcast(c, CONTENT_MSG_STATUS, msg_data); } break; case CONTENT_MSG_READY: - break; - + /* Fall through */ case CONTENT_MSG_DONE: - LOG(("got favicon '%s'", icon->url)); break; - case CONTENT_MSG_LAUNCH: - /* Fall through */ case CONTENT_MSG_ERROR: - LOG(("favicon %s failed: %s", icon->url, data.error)); - /* The favicon we were fetching may have been - * redirected, in that case, the object pointers - * will differ, so ensure that the object that's - * in error is still in use by us before invalidating - * the pointer */ - if (c->data.html.favicon == icon) { - c->data.html.favicon = 0; - content_add_error(c, "?", 0); - } - break; + LOG(("favicon %s failed: %s", + content_get_url(icon), event->data.error)); + hlcache_handle_release(c->data.html.favicon); + c->data.html.favicon = NULL; - case CONTENT_MSG_STATUS: - html_set_status(c, icon->status_message); - content_broadcast(c, CONTENT_MSG_STATUS, data); - break; - - case CONTENT_MSG_NEWPTR: - c->data.html.favicon = icon; - break; - - case CONTENT_MSG_AUTH: - c->data.html.favicon = 0; content_add_error(c, "?", 0); break; - case CONTENT_MSG_SSL: - c->data.html.favicon = 0; - content_add_error(c, "?", 0); + case CONTENT_MSG_STATUS: + content_broadcast(c, CONTENT_MSG_STATUS, event->data); break; + case CONTENT_MSG_REDRAW: - /* currently no support for favicon animations */ + /* Fall through */ case CONTENT_MSG_REFRESH: - break; + /* Fall through */ case CONTENT_MSG_REFORMAT: - /* would be unusual :) */ break; + default: assert(0); } + + return NSERROR_OK; } diff --git a/render/favicon.h b/render/favicon.h index 30030101a..428655ecd 100644 --- a/render/favicon.h +++ b/render/favicon.h @@ -20,7 +20,8 @@ #define _NETSURF_RENDER_FAVICON_H_ #include <libxml/tree.h> -#include "content/content.h" + +struct content; bool favicon_get_icon(struct content *c, xmlNode *html); diff --git a/render/form.c b/render/form.c index 968397a21..b81d2ca34 100644 --- a/render/form.c +++ b/render/form.c @@ -30,6 +30,7 @@ #include <stdbool.h> #include <stdio.h> #include <string.h> +#include "content/fetch.h" #include "css/css.h" #include "css/utils.h" #include "desktop/gui.h" @@ -308,18 +309,18 @@ bool form_add_option(struct form_control *control, char *value, char *text, * \param form form to search for successful controls * \param submit_button control used to submit the form, if any * \param successful_controls updated to point to linked list of - * form_successful_control, 0 if no controls + * fetch_multipart_data, 0 if no controls * \return true on success, false on memory exhaustion * * See HTML 4.01 section 17.13.2. */ bool form_successful_controls(struct form *form, struct form_control *submit_button, - struct form_successful_control **successful_controls) + struct fetch_multipart_data **successful_controls) { struct form_control *control; struct form_option *option; - struct form_successful_control sentinel, *last_success, *success_new; + struct fetch_multipart_data sentinel, *last_success, *success_new; char *value = NULL; bool had_submit = false; char *charset; @@ -603,7 +604,7 @@ bool form_successful_controls(struct form *form, no_memory: warn_user("NoMemory", 0); - form_free_successful(sentinel.next); + fetch_multipart_data_destroy(sentinel.next); return false; #undef ENCODE_ITEM @@ -659,12 +660,12 @@ char *form_textarea_value(struct form_control *textarea) * Encode controls using application/x-www-form-urlencoded. * * \param form form to which successful controls relate - * \param control linked list of form_successful_control + * \param control linked list of fetch_multipart_data * \return URL-encoded form, or 0 on memory exhaustion */ char *form_url_encode(struct form *form, - struct form_successful_control *control) + struct fetch_multipart_data *control) { char *name, *value; char *s = malloc(1), *s2; @@ -713,24 +714,6 @@ char *form_url_encode(struct form *form, return s; } - -/** - * Free a linked list of form_successful_control. - * - * \param control Pointer to head of list to free - */ - -void form_free_successful(struct form_successful_control *control) -{ - struct form_successful_control *next; - for (; control; control = next) { - next = control->next; - free(control->name); - free(control->value); - free(control); - } -} - /** * Find an acceptable character set encoding with which to submit the form * diff --git a/render/form.h b/render/form.h index a31c24975..d5026e039 100644 --- a/render/form.h +++ b/render/form.h @@ -125,14 +125,6 @@ struct form_option { struct form_option* next; }; -/** Successful control, as defined by HTML 4.01 17.13. */ -struct form_successful_control { - bool file; /**< It's a file */ - char *name; /**< Control name. */ - char *value; /**< Current value. */ - struct form_successful_control *next; /**< Next in linked list. */ -}; - /** * Called by the select menu when it wants an area to be redrawn. The * coordinates are menu origin relative. @@ -157,10 +149,9 @@ bool form_add_option(struct form_control *control, char *value, char *text, bool selected); bool form_successful_controls(struct form *form, struct form_control *submit_button, - struct form_successful_control **successful_controls); + struct fetch_multipart_data **successful_controls); char *form_url_encode(struct form *form, - struct form_successful_control *control); -void form_free_successful(struct form_successful_control *control); + struct fetch_multipart_data *control); bool form_open_select_menu(void *client_data, struct form_control *control, diff --git a/render/html.c b/render/html.c index 82becef5c..d63c68764 100644 --- a/render/html.c +++ b/render/html.c @@ -29,9 +29,10 @@ #include <strings.h> #include <stdlib.h> #include "utils/config.h" -#include "content/content.h" +#include "content/content_protected.h" #include "content/fetch.h" #include "content/fetchcache.h" +#include "content/hlcache.h" #include "desktop/browser.h" #include "desktop/gui.h" #include "desktop/options.h" @@ -43,6 +44,7 @@ #include "render/html.h" #include "render/imagemap.h" #include "render/layout.h" +#include "utils/http.h" #include "utils/log.h" #include "utils/messages.h" #include "utils/talloc.h" @@ -57,16 +59,18 @@ #define ALWAYS_DUMP_FRAMESET 0 #define ALWAYS_DUMP_BOX 0 -static void html_convert_css_callback(content_msg msg, struct content *css, - intptr_t p1, intptr_t p2, union content_msg_data data); +static nserror html_convert_css_callback(hlcache_handle *css, + const hlcache_event *event, void *pw); static bool html_meta_refresh(struct content *c, xmlNode *head); static bool html_head(struct content *c, xmlNode *head); static bool html_find_stylesheets(struct content *c, xmlNode *html); static bool html_process_style_element(struct content *c, unsigned int *index, xmlNode *style); -static void html_object_callback(content_msg msg, struct content *object, - intptr_t p1, intptr_t p2, union content_msg_data data); -static void html_object_done(struct box *box, struct content *object, +static bool html_replace_object(struct content *c, unsigned int i, + const char *url); +static nserror html_object_callback(hlcache_handle *object, + const hlcache_event *event, void *pw); +static void html_object_done(struct box *box, hlcache_handle *object, bool background); static void html_object_failed(struct box *box, struct content *content, bool background); @@ -113,57 +117,45 @@ static void *myrealloc(void *ptr, size_t len, void *pw) * created. */ -bool html_create(struct content *c, struct content *parent, - const char *params[]) +bool html_create(struct content *c, const http_parameter *params) { - unsigned int i; struct content_html_data *html = &c->data.html; + const char *charset; union content_msg_data msg_data; binding_error error; - lwc_context *dict; - lwc_error lerror; + nserror nerror; html->parser_binding = NULL; - html->document = 0; + html->document = NULL; html->quirks = BINDING_QUIRKS_MODE_NONE; - html->encoding = 0; - html->base_url = c->url; + html->encoding = NULL; + html->base_url = (char *) content__get_url(c); html->base_target = NULL; - html->layout = 0; + html->layout = NULL; html->background_colour = NS_TRANSPARENT; html->stylesheet_count = 0; html->stylesheets = NULL; html->select_ctx = NULL; html->object_count = 0; - html->object = 0; - html->forms = 0; - html->imagemaps = 0; - html->bw = 0; - html->frameset = 0; - html->iframe = 0; - html->page = 0; + html->object = NULL; + html->forms = NULL; + html->imagemaps = NULL; + html->bw = NULL; + html->frameset = NULL; + html->iframe = NULL; + html->page = NULL; html->index = 0; - html->box = 0; + html->box = NULL; html->font_func = &nsfont; - lerror = lwc_create_context(myrealloc, c, &dict); - if (lerror != lwc_error_ok) { - error = BINDING_NOMEM; - goto error; - } - - html->dict = lwc_context_ref(dict); - - for (i = 0; params[i]; i += 2) { - if (strcasecmp(params[i], "charset") == 0) { - html->encoding = talloc_strdup(c, params[i + 1]); - if (!html->encoding) { - error = BINDING_NOMEM; - goto error; - } - html->encoding_source = ENCODING_SOURCE_HEADER; - break; + nerror = http_parameter_list_find_item(params, "charset", &charset); + if (nerror == NSERROR_OK) { + html->encoding = talloc_strdup(c, charset); + if (!html->encoding) { + error = BINDING_NOMEM; + goto error; } + html->encoding_source = ENCODING_SOURCE_HEADER; } /* Create the parser binding */ @@ -294,10 +286,17 @@ encoding_change: return false; } - /* Recurse to reprocess all that data. This is safe because - * the encoding is now specified at parser-start which means - * it cannot be changed again. */ - return html_process_data(c, c->source_data, c->source_size); + { + const char *source_data; + unsigned long source_size; + + source_data = content__get_source_data(c, &source_size); + + /* Recurse to reprocess all that data. This is safe because + * the encoding is now specified at parser-start which means + * it cannot be changed again. */ + return html_process_data(c, (char *) source_data, source_size); + } } /** @@ -321,11 +320,13 @@ bool html_convert(struct content *c, int width, int height) binding_error err; xmlNode *html, *head; union content_msg_data msg_data; + unsigned long size; unsigned int time_before, time_taken; struct form *f; /* finish parsing */ - if (c->source_size == 0) { + content__get_source_data(c, &size); + if (size == 0) { /* Destroy current binding */ binding_destroy_tree(c->data.html.parser_binding); @@ -502,8 +503,6 @@ bool html_convert(struct content *c, int width, int height) binding_destroy_tree(c->data.html.parser_binding); c->data.html.parser_binding = NULL; - c->size += lwc_context_size(c->data.html.dict); - if (c->active == 0) c->status = CONTENT_STATUS_DONE; else @@ -689,7 +688,7 @@ bool html_meta_refresh(struct content *c, xmlNode *head) /* Just delay specified, so refresh current page */ xmlFree(content); - c->refresh = talloc_strdup(c, c->url); + c->refresh = talloc_strdup(c, content__get_url(c)); if (!c->refresh) { msg_data.error = messages_get("NoMemory"); content_broadcast(c, @@ -808,67 +807,66 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) unsigned int last_active = 0; union content_msg_data msg_data; url_func_result res; - struct nscss_import *stylesheets; + struct html_stylesheet *stylesheets; + hlcache_child_context child; css_error error; + nserror ns_error; + + child.charset = c->data.html.encoding; + child.quirks = c->quirks; /* stylesheet 0 is the base style sheet, * stylesheet 1 is the quirks mode style sheet, * stylesheet 2 is the adblocking stylesheet */ - c->data.html.stylesheets = talloc_array(c, struct nscss_import, + c->data.html.stylesheets = talloc_array(c, struct html_stylesheet, STYLESHEET_START); if (c->data.html.stylesheets == NULL) goto no_memory; - c->data.html.stylesheets[STYLESHEET_BASE].c = NULL; - c->data.html.stylesheets[STYLESHEET_BASE].media = CSS_MEDIA_ALL; - c->data.html.stylesheets[STYLESHEET_QUIRKS].c = NULL; - c->data.html.stylesheets[STYLESHEET_QUIRKS].media = CSS_MEDIA_ALL; - c->data.html.stylesheets[STYLESHEET_ADBLOCK].c = NULL; - c->data.html.stylesheets[STYLESHEET_ADBLOCK].media = CSS_MEDIA_ALL; + c->data.html.stylesheets[STYLESHEET_BASE].type = + HTML_STYLESHEET_EXTERNAL; + c->data.html.stylesheets[STYLESHEET_BASE].data.external = NULL; + c->data.html.stylesheets[STYLESHEET_QUIRKS].type = + HTML_STYLESHEET_EXTERNAL; + c->data.html.stylesheets[STYLESHEET_QUIRKS].data.external = NULL; + c->data.html.stylesheets[STYLESHEET_ADBLOCK].type = + HTML_STYLESHEET_EXTERNAL; + c->data.html.stylesheets[STYLESHEET_ADBLOCK].data.external = NULL; c->data.html.stylesheet_count = STYLESHEET_START; c->active = 0; - c->data.html.stylesheets[STYLESHEET_BASE].c = fetchcache( - default_stylesheet_url, - html_convert_css_callback, (intptr_t) c, - STYLESHEET_BASE, c->width, c->height, - true, 0, 0, false, false); - if (c->data.html.stylesheets[STYLESHEET_BASE].c == NULL) + ns_error = hlcache_handle_retrieve(default_stylesheet_url, 0, + content__get_url(c), NULL, c->width, c->height, + html_convert_css_callback, c, &child, + &c->data.html.stylesheets[ + STYLESHEET_BASE].data.external); + if (ns_error != NSERROR_OK) goto no_memory; + c->active++; - fetchcache_go(c->data.html.stylesheets[STYLESHEET_BASE].c, - c->url, html_convert_css_callback, (intptr_t) c, - STYLESHEET_BASE, c->width, c->height, - 0, 0, false, c); if (c->data.html.quirks == BINDING_QUIRKS_MODE_FULL) { - c->data.html.stylesheets[STYLESHEET_QUIRKS].c = - fetchcache(quirks_stylesheet_url, - html_convert_css_callback, (intptr_t) c, - STYLESHEET_QUIRKS, c->width, c->height, - true, 0, 0, false, false); - if (c->data.html.stylesheets[STYLESHEET_QUIRKS].c == NULL) + ns_error = hlcache_handle_retrieve(quirks_stylesheet_url, 0, + content__get_url(c), NULL, c->width, c->height, + html_convert_css_callback, c, &child, + &c->data.html.stylesheets[ + STYLESHEET_QUIRKS].data.external); + if (ns_error != NSERROR_OK) goto no_memory; + c->active++; - fetchcache_go(c->data.html.stylesheets[STYLESHEET_QUIRKS].c, - c->url, html_convert_css_callback, - (intptr_t) c, STYLESHEET_QUIRKS, c->width, - c->height, 0, 0, false, c); } if (option_block_ads) { - c->data.html.stylesheets[STYLESHEET_ADBLOCK].c = - fetchcache(adblock_stylesheet_url, - html_convert_css_callback, (intptr_t) c, - STYLESHEET_ADBLOCK, c->width, - c->height, true, 0, 0, false, false); - if (c->data.html.stylesheets[STYLESHEET_ADBLOCK].c == NULL) + ns_error = hlcache_handle_retrieve(adblock_stylesheet_url, 0, + content__get_url(c), NULL, c->width, c->height, + html_convert_css_callback, c, &child, + &c->data.html.stylesheets[ + STYLESHEET_ADBLOCK].data.external); + if (ns_error != NSERROR_OK) goto no_memory; + c->active++; - fetchcache_go(c->data.html.stylesheets[STYLESHEET_ADBLOCK].c, - c->url, html_convert_css_callback, - (intptr_t) c, STYLESHEET_ADBLOCK, c->width, - c->height, 0, 0, false, c); } node = html; @@ -958,29 +956,30 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) /* start fetch */ stylesheets = talloc_realloc(c, c->data.html.stylesheets, - struct nscss_import, i + 1); + struct html_stylesheet, i + 1); if (stylesheets == NULL) { free(url2); goto no_memory; } c->data.html.stylesheets = stylesheets; - /** \todo Reflect actual media specified in link */ - c->data.html.stylesheets[i].media = CSS_MEDIA_ALL; - c->data.html.stylesheets[i].c = fetchcache(url2, - html_convert_css_callback, - (intptr_t) c, i, c->width, c->height, - true, 0, 0, false, false); + c->data.html.stylesheet_count++; + c->data.html.stylesheets[i].type = + HTML_STYLESHEET_EXTERNAL; + ns_error = hlcache_handle_retrieve(url2, 0, + content__get_url(c), NULL, + c->width, c->height, + html_convert_css_callback, c, &child, + &c->data.html.stylesheets[i]. + data.external); + free(url2); - if (c->data.html.stylesheets[i].c == NULL) + + if (ns_error != NSERROR_OK) goto no_memory; c->active++; - fetchcache_go(c->data.html.stylesheets[i].c, - c->url, - html_convert_css_callback, - (intptr_t) c, i, c->width, c->height, - 0, 0, false, c); + i++; } else if (strcmp((const char *) node->name, "style") == 0) { if (!html_process_style_element(c, &i, node)) @@ -988,7 +987,7 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) } } - c->data.html.stylesheet_count = i; + assert(c->data.html.stylesheet_count == i); /* complete the fetches */ while (c->active != 0) { @@ -1002,7 +1001,7 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) } /* check that the base stylesheet loaded; layout fails without it */ - if (c->data.html.stylesheets[STYLESHEET_BASE].c == NULL) { + if (c->data.html.stylesheets[STYLESHEET_BASE].data.external == NULL) { msg_data.error = "Base stylesheet failed to load"; content_broadcast(c, CONTENT_MSG_ERROR, msg_data); return false; @@ -1015,11 +1014,30 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) /* Add sheets to it */ for (i = STYLESHEET_BASE; i != c->data.html.stylesheet_count; i++) { - if (c->data.html.stylesheets[i].c != NULL) { + const struct html_stylesheet *hsheet = + &c->data.html.stylesheets[i]; + css_stylesheet *sheet; + css_origin origin = CSS_ORIGIN_AUTHOR; + + if (i < STYLESHEET_START) + origin = CSS_ORIGIN_UA; + + if (hsheet->type == HTML_STYLESHEET_EXTERNAL && + hsheet->data.external != NULL) { + struct content *s = hlcache_handle_get_content( + hsheet->data.external); + + sheet = s-> data.css.sheet; + } else if (hsheet->type == HTML_STYLESHEET_INTERNAL) { + sheet = hsheet->data.internal->sheet; + } else { + sheet = NULL; + } + + if (sheet != NULL) { error = css_select_ctx_append_sheet( - c->data.html.select_ctx, - c->data.html.stylesheets[i].c-> - data.css.sheet); + c->data.html.select_ctx, sheet, + origin, CSS_MEDIA_SCREEN); if (error != CSS_OK) goto no_memory; } @@ -1050,9 +1068,9 @@ bool html_process_style_element(struct content *c, unsigned int *index, xmlNode *child; char *type, *media, *data; union content_msg_data msg_data; - struct nscss_import *stylesheets; - struct nscss_import *sheet; - const char *params[] = { 0 }; + struct html_stylesheet *stylesheets; + struct content_css_data *sheet; + nserror error; /* type='text/css', or not present (invalid but common) */ if ((type = (char *) xmlGetProp(style, (const xmlChar *) "type"))) { @@ -1075,26 +1093,27 @@ bool html_process_style_element(struct content *c, unsigned int *index, /* Extend array */ stylesheets = talloc_realloc(c, c->data.html.stylesheets, - struct nscss_import, *index + 1); + struct html_stylesheet, *index + 1); if (stylesheets == NULL) goto no_memory; c->data.html.stylesheets = stylesheets; + c->data.html.stylesheet_count++; - /* create stylesheet */ - sheet = &c->data.html.stylesheets[(*index)]; + c->data.html.stylesheets[(*index)].type = HTML_STYLESHEET_INTERNAL; + c->data.html.stylesheets[(*index)].data.internal = NULL; - /** \todo Reflect specified media */ - sheet->media = CSS_MEDIA_ALL; - sheet->c = content_create(c->data.html.base_url); - if (sheet->c == NULL) + /* create stylesheet */ + sheet = talloc(c, struct content_css_data); + if (sheet == NULL) { + c->data.html.stylesheet_count--; goto no_memory; + } - if (content_set_type(sheet->c, - CONTENT_CSS, "text/css", params, c) == false) { - /** \todo not necessarily caused by - * memory exhaustion */ - sheet->c = NULL; + error = nscss_create_css_data(sheet, + c->data.html.base_url, NULL, c->data.html.quirks); + if (error != NSERROR_OK) { + c->data.html.stylesheet_count--; goto no_memory; } @@ -1103,43 +1122,29 @@ bool html_process_style_element(struct content *c, unsigned int *index, * the content */ for (child = style->children; child != 0; child = child->next) { data = (char *) xmlNodeGetContent(child); - if (content_process_data(sheet->c, data, strlen(data)) == + if (nscss_process_css_data(sheet, data, strlen(data)) == false) { xmlFree(data); + nscss_destroy_css_data(sheet); + talloc_free(sheet); + c->data.html.stylesheet_count--; /** \todo not necessarily caused by * memory exhaustion */ - sheet->c = NULL; goto no_memory; } xmlFree(data); } /* Convert the content -- manually, as we want the result */ - if (sheet->c->source_allocated != sheet->c->source_size) { - /* Minimise source data block */ - char *data = talloc_realloc(sheet->c, sheet->c->source_data, - char, sheet->c->source_size); - - if (data != NULL) { - sheet->c->source_data = data; - sheet->c->source_allocated = sheet->c->source_size; - } - } - - if (nscss_convert(sheet->c, c->width, c->height)) { - if (content_add_user(sheet->c, - html_convert_css_callback, - (intptr_t) c, (*index)) == false) { - /* no memory */ - sheet->c = NULL; - goto no_memory; - } - } else { + if (nscss_convert_css_data(sheet, c->width, c->height) != CSS_OK) { /* conversion failed */ - sheet->c = NULL; + nscss_destroy_css_data(sheet); + talloc_free(sheet); + sheet = NULL; } /* Update index */ + c->data.html.stylesheets[(*index)].data.internal = sheet; (*index)++; return true; @@ -1155,36 +1160,40 @@ no_memory: * Callback for fetchcache() for linked stylesheets. */ -void html_convert_css_callback(content_msg msg, struct content *css, - intptr_t p1, intptr_t p2, union content_msg_data data) +nserror html_convert_css_callback(hlcache_handle *css, + const hlcache_event *event, void *pw) { - struct content *c = (struct content *) p1; - unsigned int i = p2; + struct content *parent = pw; + unsigned int i; + struct html_stylesheet *s; + + /* Find sheet */ + for (i = 0, s = parent->data.html.stylesheets; + i != parent->data.html.stylesheet_count; i++, s++) { + if (s->type == HTML_STYLESHEET_EXTERNAL && + s->data.external == css) + break; + } + + assert(i != parent->data.html.stylesheet_count); - switch (msg) { + switch (event->type) { case CONTENT_MSG_LOADING: /* check that the stylesheet is really CSS */ - if (css->type != CONTENT_CSS) { - c->data.html.stylesheets[i].c = NULL; - c->active--; - LOG(("%s is not CSS", css->url)); - content_add_error(c, "NotCSS", 0); - html_set_status(c, messages_get("NotCSS")); - content_broadcast(c, CONTENT_MSG_STATUS, data); - content_remove_user(css, - html_convert_css_callback, - (intptr_t) c, i); - if (css->user_list->next == NULL) { - /* we were the only user and we - * don't want this content, so - * stop it fetching and mark it - * as having an error so it gets - * removed from the cache next time - * content_clean() gets called */ - fetch_abort(css->fetch); - css->fetch = 0; - css->status = CONTENT_STATUS_ERROR; - } + if (content_get_type(css) != CONTENT_CSS) { + hlcache_handle_release(css); + s->data.external = NULL; + + parent->active--; + + LOG(("%s is not CSS", content_get_url(css))); + + content_add_error(parent, "NotCSS", 0); + + html_set_status(parent, messages_get("NotCSS")); + + content_broadcast(parent, CONTENT_MSG_STATUS, + event->data); } break; @@ -1192,50 +1201,29 @@ void html_convert_css_callback(content_msg msg, struct content *css, break; case CONTENT_MSG_DONE: - LOG(("got stylesheet '%s'", css->url)); - c->active--; + LOG(("got stylesheet '%s'", content_get_url(css))); + parent->active--; break; - case CONTENT_MSG_LAUNCH: - /* Fall through */ case CONTENT_MSG_ERROR: - LOG(("stylesheet %s failed: %s", css->url, data.error)); - /* The stylesheet we were fetching may have been - * redirected, in that case, the object pointers - * will differ, so ensure that the object that's - * in error is still in use by us before invalidating - * the pointer */ - if (c->data.html.stylesheets[i].c == css) { - c->data.html.stylesheets[i].c = NULL; - c->active--; - content_add_error(c, "?", 0); - } + LOG(("stylesheet %s failed: %s", + content_get_url(css), event->data.error)); + hlcache_handle_release(css); + s->data.external = NULL; + parent->active--; + content_add_error(parent, "?", 0); break; case CONTENT_MSG_STATUS: - html_set_status(c, css->status_message); - content_broadcast(c, CONTENT_MSG_STATUS, data); - break; - - case CONTENT_MSG_NEWPTR: - c->data.html.stylesheets[i].c = css; - break; - - case CONTENT_MSG_AUTH: - c->data.html.stylesheets[i].c = NULL; - c->active--; - content_add_error(c, "?", 0); - break; - - case CONTENT_MSG_SSL: - c->data.html.stylesheets[i].c = NULL; - c->active--; - content_add_error(c, "?", 0); + html_set_status(parent, content_get_status_message(css)); + content_broadcast(parent, CONTENT_MSG_STATUS, event->data); break; default: assert(0); } + + return NSERROR_OK; } @@ -1260,9 +1248,14 @@ bool html_fetch_object(struct content *c, const char *url, struct box *box, { unsigned int i = c->data.html.object_count; struct content_html_object *object; - struct content *c_fetch; + hlcache_handle *c_fetch; + hlcache_child_context child; char *url2; url_func_result res; + nserror error; + + child.charset = c->data.html.encoding; + child.quirks = c->quirks; /* Normalize the URL */ res = url_normalize(url, &url2); @@ -1271,23 +1264,22 @@ bool html_fetch_object(struct content *c, const char *url, struct box *box, return res != URL_FUNC_NOMEM; } - /* initialise fetch */ - c_fetch = fetchcache(url2, html_object_callback, - (intptr_t) c, i, available_width, available_height, - true, 0, 0, false, false); + error = hlcache_handle_retrieve(url2, 0, content__get_url(c), NULL, + available_width, available_height, + html_object_callback, c, &child, + &c_fetch); /* No longer need normalized url */ free(url2); - if (!c_fetch) + if (error != NSERROR_OK) return false; /* add to object list */ object = talloc_realloc(c, c->data.html.object, struct content_html_object, i + 1); - if (!object) { - content_remove_user(c_fetch, html_object_callback, - (intptr_t) c, i); + if (object == NULL) { + hlcache_handle_release(c_fetch); return false; } c->data.html.object = object; @@ -1298,12 +1290,6 @@ bool html_fetch_object(struct content *c, const char *url, struct box *box, c->data.html.object_count++; c->active++; - /* start fetch */ - fetchcache_go(c_fetch, c->url, - html_object_callback, (intptr_t) c, i, - available_width, available_height, - 0, 0, false, c); - return true; } @@ -1314,31 +1300,31 @@ bool html_fetch_object(struct content *c, const char *url, struct box *box, * \param c content of type CONTENT_HTML * \param i index of object to replace in c->data.html.object * \param url URL of object to fetch (copied) - * \param post_urlenc url encoded post data, or 0 if none - * \param post_multipart multipart post data, or 0 if none * \return true on success, false on memory exhaustion */ -bool html_replace_object(struct content *c, unsigned int i, char *url, - char *post_urlenc, - struct form_successful_control *post_multipart) +bool html_replace_object(struct content *c, unsigned int i, const char *url) { - struct content *c_fetch; + hlcache_handle *c_fetch; + hlcache_child_context child; struct content *page; char *url2; url_func_result res; + nserror error; assert(c->type == CONTENT_HTML); + child.charset = c->data.html.encoding; + child.quirks = c->quirks; + if (c->data.html.object[i].content) { /* remove existing object */ - if (c->data.html.object[i].content->status != + if (content_get_status(c->data.html.object[i].content) != CONTENT_STATUS_DONE) c->active--; - content_remove_user(c->data.html.object[i].content, - html_object_callback, (intptr_t) c, i); - c->data.html.object[i].content = 0; - c->data.html.object[i].box->object = 0; + hlcache_handle_release(c->data.html.object[i].content); + c->data.html.object[i].content = NULL; + c->data.html.object[i].box->object = NULL; } res = url_normalize(url, &url2); @@ -1346,15 +1332,15 @@ bool html_replace_object(struct content *c, unsigned int i, char *url, return res != URL_FUNC_NOMEM; /* initialise fetch */ - c_fetch = fetchcache(url2, html_object_callback, - (intptr_t) c, i, + error = hlcache_handle_retrieve(url2, 0, content__get_url(c), NULL, c->data.html.object[i].box->width, c->data.html.object[i].box->height, - false, post_urlenc, post_multipart, false, false); + html_object_callback, c, &child, + &c_fetch); free(url2); - if (!c_fetch) + if (error != NSERROR_OK) return false; c->data.html.object[i].content = c_fetch; @@ -1365,13 +1351,6 @@ bool html_replace_object(struct content *c, unsigned int i, char *url, page->status = CONTENT_STATUS_READY; } - /* start fetch */ - fetchcache_go(c_fetch, c->url, - html_object_callback, (intptr_t) c, i, - c->data.html.object[i].box->width, - c->data.html.object[i].box->height, - post_urlenc, post_multipart, false, c); - return true; } @@ -1380,157 +1359,146 @@ bool html_replace_object(struct content *c, unsigned int i, char *url, * Callback for fetchcache() for objects. */ -void html_object_callback(content_msg msg, struct content *object, - intptr_t p1, intptr_t p2, union content_msg_data data) +nserror html_object_callback(hlcache_handle *object, + const hlcache_event *event, void *pw) { - struct content *c = (struct content *) p1; - unsigned int i = p2; + struct content *c = pw; + unsigned int i; + struct content_html_object *o; int x, y; - struct box *box = c->data.html.object[i].box; - - switch (msg) { - case CONTENT_MSG_LOADING: - /* check if the type is acceptable for this object */ - if (html_object_type_permitted(object->type, - c->data.html.object[i].permitted_types)) { - if (c->data.html.bw) - content_open(object, - c->data.html.bw, c, - i, box, - box->object_params); - break; - } + struct box *box; - /* not acceptable */ - c->data.html.object[i].content = 0; - c->active--; - content_add_error(c, "?", 0); - html_set_status(c, messages_get("BadObject")); - content_broadcast(c, CONTENT_MSG_STATUS, data); - content_remove_user(object, html_object_callback, - (intptr_t) c, i); - if (!object->user_list->next) { - /* we were the only user and we - * don't want this content, so - * stop it fetching and mark it - * as having an error so it gets - * removed from the cache next time - * content_clean() gets called */ - fetch_abort(object->fetch); - object->fetch = 0; - object->status = CONTENT_STATUS_ERROR; - } - html_object_failed(box, c, - c->data.html.object[i].background); + /* Find object record in parent */ + for (i = 0, o = c->data.html.object; i != c->data.html.object_count; + i++, o++) { + if (o->content == object) break; + } - case CONTENT_MSG_READY: - if (object->type == CONTENT_HTML) { - html_object_done(box, object, - c->data.html.object[i].background); - if (c->status == CONTENT_STATUS_READY || - c->status == - CONTENT_STATUS_DONE) - content_reformat(c, - c->available_width, - c->height); - } - break; + assert(i != c->data.html.object_count); - case CONTENT_MSG_DONE: - html_object_done(box, object, - c->data.html.object[i].background); - c->active--; - break; + box = o->box; - case CONTENT_MSG_LAUNCH: - /* Fall through */ - case CONTENT_MSG_ERROR: - /* The object we were fetching may have been - * redirected, in that case, the object pointers - * will differ, so ensure that the object that's - * in error is still in use by us before invalidating - * the pointer */ - if (c->data.html.object[i].content == object) { - c->data.html.object[i].content = 0; - c->active--; - content_add_error(c, "?", 0); - html_set_status(c, data.error); - content_broadcast(c, CONTENT_MSG_STATUS, - data); - html_object_failed(box, c, - c->data.html.object[i].background); - } + switch (event->type) { + case CONTENT_MSG_LOADING: + /* check if the type is acceptable for this object */ + if (html_object_type_permitted(content_get_type(object), + o->permitted_types)) { + if (c->data.html.bw != NULL) + content_open(object, + c->data.html.bw, c, + i, box, + box->object_params); break; + } - case CONTENT_MSG_STATUS: - html_set_status(c, object->status_message); - /* content_broadcast(c, CONTENT_MSG_STATUS, 0); */ - break; + /* not acceptable */ + hlcache_handle_release(object); - case CONTENT_MSG_REFORMAT: - break; + o->content = NULL; - case CONTENT_MSG_REDRAW: - if (!box_visible(box)) - break; - box_coords(box, &x, &y); - if (object == data.redraw.object) { - data.redraw.x = data.redraw.x * - box->width / object->width; - data.redraw.y = data.redraw.y * - box->height / object->height; - data.redraw.width = data.redraw.width * - box->width / object->width; - data.redraw.height = data.redraw.height * - box->height / object->height; - 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, CONTENT_MSG_REDRAW, data); - break; + c->active--; - case CONTENT_MSG_NEWPTR: - c->data.html.object[i].content = object; - break; + content_add_error(c, "?", 0); + html_set_status(c, messages_get("BadObject")); + content_broadcast(c, CONTENT_MSG_STATUS, event->data); - case CONTENT_MSG_AUTH: - c->data.html.object[i].content = 0; - c->active--; - content_add_error(c, "?", 0); - break; + html_object_failed(box, c, + c->data.html.object[i].background); + break; - case CONTENT_MSG_SSL: - c->data.html.object[i].content = 0; - c->active--; - content_add_error(c, "?", 0); - break; + case CONTENT_MSG_READY: + if (content_get_type(object) == CONTENT_HTML) { + html_object_done(box, object, o->background); + if (c->status == CONTENT_STATUS_READY || + c->status == CONTENT_STATUS_DONE) + content__reformat(c, + c->available_width, + c->height); + } + break; + + case CONTENT_MSG_DONE: + html_object_done(box, object, o->background); + c->active--; + break; + + case CONTENT_MSG_ERROR: + hlcache_handle_release(object); + + o->content = NULL; + + c->active--; + + content_add_error(c, "?", 0); + html_set_status(c, event->data.error); + content_broadcast(c, CONTENT_MSG_STATUS, event->data); + html_object_failed(box, c, o->background); + break; + + case CONTENT_MSG_STATUS: + html_set_status(c, content_get_status_message(object)); + /* content_broadcast(c, CONTENT_MSG_STATUS, 0); */ + break; + + case CONTENT_MSG_REFORMAT: + break; - case CONTENT_MSG_REFRESH: - if (object->type == CONTENT_HTML) - /* only for HTML objects */ - schedule(data.delay * 100, - html_object_refresh, object); + case CONTENT_MSG_REDRAW: + { + union content_msg_data data = event->data; + + if (!box_visible(box)) break; - default: - assert(0); + 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, 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, object); + break; + + default: + assert(0); } if (c->status == CONTENT_STATUS_READY && c->active == 0 && - (msg == CONTENT_MSG_LOADING || - msg == CONTENT_MSG_DONE || - msg == CONTENT_MSG_ERROR || - msg == CONTENT_MSG_AUTH)) { + (event->type == CONTENT_MSG_LOADING || + event->type == CONTENT_MSG_DONE || + event->type == CONTENT_MSG_ERROR)) { /* all objects have arrived */ - content_reformat(c, c->available_width, c->height); + content__reformat(c, c->available_width, c->height); html_set_status(c, ""); content_set_done(c); } + /* If 1) the configuration option to reflow pages while objects are * fetched is set * 2) an object is newly fetched & converted, @@ -1538,17 +1506,20 @@ void html_object_callback(content_msg msg, struct content *object, * 4) 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 (option_incremental_reflow && msg == CONTENT_MSG_DONE && + else if (option_incremental_reflow && + event->type == CONTENT_MSG_DONE && (c->status == CONTENT_STATUS_READY || c->status == CONTENT_STATUS_DONE) && (wallclock() > c->reformat_time)) { unsigned int time_before = wallclock(), time_taken; - content_reformat(c, c->available_width, c->height); + content__reformat(c, c->available_width, c->height); time_taken = wallclock() - time_before; c->reformat_time = wallclock() + ((time_taken < option_min_reflow_period ? option_min_reflow_period : time_taken * 1.25)); } + + return NSERROR_OK; } @@ -1556,7 +1527,7 @@ void html_object_callback(content_msg msg, struct content *object, * Update a box whose content has completed rendering. */ -void html_object_done(struct box *box, struct content *object, +void html_object_done(struct box *box, hlcache_handle *object, bool background) { struct box *b; @@ -1714,7 +1685,7 @@ void html_object_refresh(void *p) c->fresh = false; if (!html_replace_object(c->data.html.page, c->data.html.index, - c->refresh, 0, 0)) { + c->refresh)) { /** \todo handle memory exhaustion */ } } @@ -1726,24 +1697,22 @@ void html_object_refresh(void *p) void html_stop(struct content *c) { unsigned int i; - struct content *object; + hlcache_handle *object; assert(c->status == CONTENT_STATUS_READY); for (i = 0; i != c->data.html.object_count; i++) { object = c->data.html.object[i].content; - if (!object) + if (object == NULL) continue; - if (object->status == CONTENT_STATUS_DONE) + if (content_get_status(object) == CONTENT_STATUS_DONE) ; /* already loaded: do nothing */ - else if (object->status == CONTENT_STATUS_READY) - content_stop(object, html_object_callback, - (intptr_t) c, i); + else if (content_get_status(object) == CONTENT_STATUS_READY) + content_stop(object, html_object_callback, NULL); else { - content_remove_user(c->data.html.object[i].content, - html_object_callback, (intptr_t) c, i); - c->data.html.object[i].content = 0; + hlcache_handle_release(object); + c->data.html.object[i].content = NULL; } } c->status = CONTENT_STATUS_DONE; @@ -1836,11 +1805,14 @@ void html_destroy(struct content *c) /* Free stylesheets */ if (c->data.html.stylesheet_count) { for (i = 0; i != c->data.html.stylesheet_count; i++) { - if (c->data.html.stylesheets[i].c) - content_remove_user(c->data.html. - stylesheets[i].c, - html_convert_css_callback, - (intptr_t) c, i); + if (c->data.html.stylesheets[i].type == + HTML_STYLESHEET_EXTERNAL) { + hlcache_handle_release(c->data.html. + stylesheets[i].data.external); + } else { + nscss_destroy_css_data(c->data.html. + stylesheets[i].data.internal); + } } } @@ -1848,15 +1820,14 @@ void html_destroy(struct content *c) for (i = 0; i != c->data.html.object_count; i++) { LOG(("object %i %p", i, c->data.html.object[i].content)); if (c->data.html.object[i].content) { - content_remove_user(c->data.html.object[i].content, - html_object_callback, (intptr_t) c, i); - if (c->data.html.object[i].content->type == CONTENT_HTML) + if (content_get_type(c->data.html.object[i].content) == + CONTENT_HTML) schedule_remove(html_object_refresh, c->data.html.object[i].content); + + hlcache_handle_release(c->data.html.object[i].content); } } - - lwc_context_unref(c->data.html.dict); } void html_destroy_frameset(struct content_html_frames *frameset) { @@ -1942,7 +1913,8 @@ void html_open(struct content *c, struct browser_window *bw, for (i = 0; i != c->data.html.object_count; i++) { if (c->data.html.object[i].content == 0) continue; - if (c->data.html.object[i].content->type == CONTENT_UNKNOWN) + if (content_get_type(c->data.html.object[i].content) == + CONTENT_UNKNOWN) continue; content_open(c->data.html.object[i].content, bw, c, i, @@ -1964,7 +1936,8 @@ void html_close(struct content *c) for (i = 0; i != c->data.html.object_count; i++) { if (c->data.html.object[i].content == 0) continue; - if (c->data.html.object[i].content->type == CONTENT_UNKNOWN) + if (content_get_type(c->data.html.object[i].content) == + CONTENT_UNKNOWN) continue; content_close(c->data.html.object[i].content); } @@ -2023,3 +1996,173 @@ void html_dump_frameset(struct content_html_frames *frame, } #endif + +/** + * Retrieve HTML document tree + * + * \param h HTML content to retrieve document tree from + * \return Pointer to document tree + */ +xmlDoc *html_get_document(hlcache_handle *h) +{ + struct content *c = hlcache_handle_get_content(h); + + assert(c != NULL); + assert(c->type == CONTENT_HTML); + + return c->data.html.document; +} + +/** + * Retrieve box tree + * + * \param h HTML content to retrieve tree from + * \return Pointer to box tree + * + * \todo This API must die, as must all use of the box tree outside render/ + */ +struct box *html_get_box_tree(hlcache_handle *h) +{ + struct content *c = hlcache_handle_get_content(h); + + assert(c != NULL); + assert(c->type == CONTENT_HTML); + + return c->data.html.layout; +} + +/** + * Retrieve the charset of an HTML document + * + * \param h Content to retrieve charset from + * \return Pointer to charset, or NULL + */ +const char *html_get_encoding(hlcache_handle *h) +{ + struct content *c = hlcache_handle_get_content(h); + + assert(c != NULL); + assert(c->type == CONTENT_HTML); + + return c->data.html.encoding; +} + +/** + * Retrieve framesets used in an HTML document + * + * \param h Content to inspect + * \return Pointer to framesets, or NULL if none + */ +struct content_html_frames *html_get_frameset(hlcache_handle *h) +{ + struct content *c = hlcache_handle_get_content(h); + + assert(c != NULL); + assert(c->type == CONTENT_HTML); + + return c->data.html.frameset; +} + +/** + * Retrieve iframes used in an HTML document + * + * \param h Content to inspect + * \return Pointer to iframes, or NULL if none + */ +struct content_html_iframe *html_get_iframe(hlcache_handle *h) +{ + struct content *c = hlcache_handle_get_content(h); + + assert(c != NULL); + assert(c->type == CONTENT_HTML); + + return c->data.html.iframe; +} + +/** + * Retrieve an HTML content's base URL + * + * \param h Content to retrieve base target from + * \return Pointer to URL + */ +const char *html_get_base_url(hlcache_handle *h) +{ + struct content *c = hlcache_handle_get_content(h); + + assert(c != NULL); + assert(c->type == CONTENT_HTML); + + return c->data.html.base_url; +} + +/** + * Retrieve an HTML content's base target + * + * \param h Content to retrieve base target from + * \return Pointer to target, or NULL if none + */ +const char *html_get_base_target(hlcache_handle *h) +{ + struct content *c = hlcache_handle_get_content(h); + + assert(c != NULL); + assert(c->type == CONTENT_HTML); + + return c->data.html.base_target; +} + +/** + * Retrieve stylesheets used by HTML document + * + * \param h Content to retrieve stylesheets from + * \param n Pointer to location to receive number of sheets + * \return Pointer to array of stylesheets + */ +struct html_stylesheet *html_get_stylesheets(hlcache_handle *h, unsigned int *n) +{ + struct content *c = hlcache_handle_get_content(h); + + assert(c != NULL); + assert(c->type == CONTENT_HTML); + assert(n != NULL); + + *n = c->data.html.stylesheet_count; + + return c->data.html.stylesheets; +} + +/** + * 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 array of objects + */ +struct content_html_object *html_get_objects(hlcache_handle *h, unsigned int *n) +{ + struct content *c = hlcache_handle_get_content(h); + + assert(c != NULL); + assert(c->type == CONTENT_HTML); + assert(n != NULL); + + *n = c->data.html.object_count; + + return c->data.html.object; +} + +/** + * Retrieve favicon associated with an HTML document + * + * \param h HTML document to retrieve favicon from + * \return Pointer to favicon, or NULL if none + */ +hlcache_handle *html_get_favicon(hlcache_handle *h) +{ + struct content *c = hlcache_handle_get_content(h); + + assert(c != NULL); + assert(c->type == CONTENT_HTML); + + return c->data.html.favicon; +} diff --git a/render/html.h b/render/html.h index 51abba3ba..5ce92ba3d 100644 --- a/render/html.h +++ b/render/html.h @@ -31,11 +31,13 @@ #include "desktop/plot_style.h" #include "render/parser_binding.h" +struct fetch_multipart_data; struct box; struct rect; struct browser_window; struct content; -struct form_successful_control; +struct hlcache_handle; +struct http_parameter; struct imagemap; struct object_params; struct plotters; @@ -50,6 +52,18 @@ extern char *default_stylesheet_url; extern char *adblock_stylesheet_url; extern char *quirks_stylesheet_url; +/** + * Container for stylesheets used by an HTML document + */ +struct html_stylesheet { + /** Type of sheet */ + enum { HTML_STYLESHEET_EXTERNAL, HTML_STYLESHEET_INTERNAL } type; + union { + struct hlcache_handle *external; + struct content_css_data *internal; + } data; /**< Sheet data */ +}; + struct frame_dimension { float value; enum { @@ -68,7 +82,7 @@ typedef enum { /** An object (<img>, <object>, etc.) in a CONTENT_HTML document. */ struct content_html_object { - struct content *content; /**< Content, or 0. */ + struct hlcache_handle *content; /**< Content, or 0. */ struct box *box; /**< Node in box tree containing it. */ /** Pointer to array of permitted content_type, terminated by * CONTENT_UNKNOWN, or 0 if any type is acceptable. */ @@ -120,8 +134,6 @@ struct content_html_data { xmlDoc *document; binding_quirks_mode quirks; /**< Quirkyness of document */ - lwc_context *dict; /**< Internment context for this document */ - char *encoding; /**< Encoding of source, 0 if unknown. */ binding_encoding_source encoding_source; /**< Source of encoding information. */ @@ -133,12 +145,12 @@ struct content_html_data { colour background_colour; /**< Document background colour. */ const struct font_functions *font_func; - struct content *favicon; /**< the favicon for the page */ + struct hlcache_handle *favicon; /**< the favicon for the page */ /** Number of entries in stylesheet_content. */ unsigned int stylesheet_count; /** Stylesheets. Each may be 0. */ - struct nscss_import *stylesheets; + struct html_stylesheet *stylesheets; /**< Style selection context */ css_select_ctx *select_ctx; @@ -173,8 +185,7 @@ struct content_html_data { extern bool html_redraw_debug; -bool html_create(struct content *c, struct content *parent, - const char *params[]); +bool html_create(struct content *c, const struct http_parameter *params); bool html_process_data(struct content *c, char *data, unsigned int size); bool html_convert(struct content *c, int width, int height); void html_reformat(struct content *c, int width, int height); @@ -183,9 +194,6 @@ bool html_fetch_object(struct content *c, const char *url, struct box *box, const content_type *permitted_types, int available_width, int available_height, bool background); -bool html_replace_object(struct content *c, unsigned int i, char *url, - char *post_urlenc, - struct form_successful_control *post_multipart); void html_stop(struct content *c); void html_open(struct content *c, struct browser_window *bw, struct content *page, unsigned int index, struct box *box, @@ -212,4 +220,17 @@ bool text_redraw(const char *utf8_text, size_t utf8_len, float scale, bool excluded); +xmlDoc *html_get_document(struct hlcache_handle *h); +struct box *html_get_box_tree(struct hlcache_handle *h); +const char *html_get_encoding(struct hlcache_handle *h); +struct content_html_frames *html_get_frameset(struct hlcache_handle *h); +struct content_html_iframe *html_get_iframe(struct hlcache_handle *h); +const char *html_get_base_url(struct hlcache_handle *h); +const char *html_get_base_target(struct hlcache_handle *h); +struct html_stylesheet *html_get_stylesheets(struct hlcache_handle *h, + unsigned int *n); +struct content_html_object *html_get_objects(struct hlcache_handle *h, + unsigned int *n); +struct hlcache_handle *html_get_favicon(struct hlcache_handle *h); + #endif diff --git a/render/html_redraw.c b/render/html_redraw.c index 2a5154035..3165e1d38 100644 --- a/render/html_redraw.c +++ b/render/html_redraw.c @@ -31,7 +31,7 @@ #include <string.h> #include <math.h> #include "utils/config.h" -#include "content/content.h" +#include "content/content_protected.h" #include "css/css.h" #include "css/utils.h" #include "desktop/gui.h" @@ -1589,31 +1589,35 @@ bool html_redraw_background(int x, int y, struct box *box, float scale, } /* handle background-repeat */ switch (css_computed_background_repeat(background->style)) { - case CSS_BACKGROUND_REPEAT_REPEAT: - repeat_x = repeat_y = true; - /* optimisation: only plot the colour if - * bitmap is not opaque */ - if (background->background->bitmap) - plot_colour = !bitmap_get_opaque( - background->background->bitmap); - break; - case CSS_BACKGROUND_REPEAT_REPEAT_X: - repeat_x = true; - break; - case CSS_BACKGROUND_REPEAT_REPEAT_Y: - repeat_y = true; - break; - case CSS_BACKGROUND_REPEAT_NO_REPEAT: - break; - default: - break; + case CSS_BACKGROUND_REPEAT_REPEAT: + { + struct bitmap *bmp = content_get_bitmap( + background->background); + repeat_x = repeat_y = true; + /* optimisation: only plot the colour if + * bitmap is not opaque */ + if (bmp != NULL) + plot_colour = !bitmap_get_opaque(bmp); + } + break; + case CSS_BACKGROUND_REPEAT_REPEAT_X: + repeat_x = true; + break; + case CSS_BACKGROUND_REPEAT_REPEAT_Y: + repeat_y = true; + break; + case CSS_BACKGROUND_REPEAT_NO_REPEAT: + break; + default: + break; } /* handle background-position */ css_computed_background_position(background->style, &hpos, &hunit, &vpos, &vunit); if (hunit == CSS_UNIT_PCT) { - x += (width - background->background->width) * + x += (width - + content_get_width(background->background)) * scale * FIXTOFLT(hpos) / 100.; } else { x += (int) (FIXTOFLT(nscss_len2px(hpos, hunit, @@ -1621,7 +1625,8 @@ bool html_redraw_background(int x, int y, struct box *box, float scale, } if (vunit == CSS_UNIT_PCT) { - y += (height - background->background->height) * + y += (height - + content_get_height(background->background)) * scale * FIXTOFLT(vpos) / 100.; } else { y += (int) (FIXTOFLT(nscss_len2px(vpos, vunit, @@ -1651,6 +1656,8 @@ bool html_redraw_background(int x, int y, struct box *box, float scale, for (; clip_box; clip_box = clip_box->next) { /* clip to child boxes if needed */ if (clip_to_children) { + struct bitmap *bmp = NULL; + assert(clip_box->type == BOX_TABLE_CELL); /* update clip_* to the child cell */ @@ -1668,15 +1675,15 @@ bool html_redraw_background(int x, int y, struct box *box, float scale, if (clip_x1 > px1) clip_x1 = px1; if (clip_y1 > py1) clip_y1 = py1; + if (clip_box->background != NULL) + bmp = content_get_bitmap(clip_box->background); + /* <td> attributes override <tr> */ if ((clip_x0 >= clip_x1) || (clip_y0 >= clip_y1) || (css_computed_background_color( clip_box->style, &bgcol) != CSS_BACKGROUND_COLOR_TRANSPARENT) || - (clip_box->background && - clip_box->background->bitmap && - bitmap_get_opaque( - clip_box->background->bitmap))) + (bmp != NULL && bitmap_get_opaque(bmp))) continue; } @@ -1693,35 +1700,30 @@ bool html_redraw_background(int x, int y, struct box *box, float scale, } /* and plot the image */ if (plot_content) { + width = content_get_width(background->background); + height = content_get_height(background->background); + if (!repeat_x) { if (clip_x0 < x) clip_x0 = x; - if (clip_x1 > x + - background->background->width * - scale) - clip_x1 = x + background->background-> - width * scale; + if (clip_x1 > x + width * scale) + clip_x1 = x + width * scale; } if (!repeat_y) { if (clip_y0 < y) clip_y0 = y; - if (clip_y1 > y + - background->background->height * - scale) - clip_y1 = y + background->background-> - height * scale; + if (clip_y1 > y + height * scale) + clip_y1 = y + height * scale; } /* valid clipping rectangles only */ if ((clip_x0 < clip_x1) && (clip_y0 < clip_y1)) { if (!plot.clip(clip_x0, clip_y0, clip_x1, clip_y1)) return false; - if (!content_redraw_tiled(background-> - background, x, y, - ceilf(background->background-> - width * scale), - ceilf(background->background-> - height * scale), + if (!content_redraw_tiled( + background->background, x, y, + ceilf(width * scale), + ceilf(height * scale), clip_x0, clip_y0, clip_x1, clip_y1, scale, *background_colour, @@ -1784,32 +1786,35 @@ bool html_redraw_inline_background(int x, int y, struct box *box, float scale, if (plot_content) { /* handle background-repeat */ switch (css_computed_background_repeat(box->style)) { - case CSS_BACKGROUND_REPEAT_REPEAT: - repeat_x = repeat_y = true; - /* optimisation: only plot the colour if - * bitmap is not opaque */ - if (box->background->bitmap) - plot_colour = !bitmap_get_opaque( - box->background->bitmap); - break; - case CSS_BACKGROUND_REPEAT_REPEAT_X: - repeat_x = true; - break; - case CSS_BACKGROUND_REPEAT_REPEAT_Y: - repeat_y = true; - break; - case CSS_BACKGROUND_REPEAT_NO_REPEAT: - break; - default: - break; + case CSS_BACKGROUND_REPEAT_REPEAT: + { + struct bitmap *bmp = + content_get_bitmap(box->background); + repeat_x = repeat_y = true; + /* optimisation: only plot the colour if + * bitmap is not opaque */ + if (bmp != NULL) + plot_colour = !bitmap_get_opaque(bmp); + } + break; + case CSS_BACKGROUND_REPEAT_REPEAT_X: + repeat_x = true; + break; + case CSS_BACKGROUND_REPEAT_REPEAT_Y: + repeat_y = true; + break; + case CSS_BACKGROUND_REPEAT_NO_REPEAT: + break; + default: + break; } /* handle background-position */ css_computed_background_position(box->style, &hpos, &hunit, &vpos, &vunit); if (hunit == CSS_UNIT_PCT) { - x += (px1 - px0 - box->background->width * scale) * - FIXTOFLT(hpos) / 100.; + x += (px1 - px0 - content_get_width(box->background) * + scale) * FIXTOFLT(hpos) / 100.; if (!repeat_x && ((hpos < 2 && !first) || (hpos > 98 && !last))){ @@ -1821,8 +1826,8 @@ bool html_redraw_inline_background(int x, int y, struct box *box, float scale, } if (vunit == CSS_UNIT_PCT) { - y += (py1 - py0 - box->background->height * scale) * - FIXTOFLT(vpos) / 100.; + y += (py1 - py0 - content_get_height(box->background) * + scale) * FIXTOFLT(vpos) / 100.; } else { y += (int) (FIXTOFLT(nscss_len2px(vpos, vunit, box->style)) * scale); @@ -1843,35 +1848,29 @@ bool html_redraw_inline_background(int x, int y, struct box *box, float scale, } /* and plot the image */ if (plot_content) { + int width = content_get_width(box->background); + int height = content_get_height(box->background); + if (!repeat_x) { if (clip_x0 < x) clip_x0 = x; - if (clip_x1 > x + - box->background->width * - scale) - clip_x1 = x + box->background-> - width * scale; + if (clip_x1 > x + width * scale) + clip_x1 = x + width * scale; } if (!repeat_y) { if (clip_y0 < y) clip_y0 = y; - if (clip_y1 > y + - box->background->height * - scale) - clip_y1 = y + box->background-> - height * scale; + if (clip_y1 > y + height * scale) + clip_y1 = y + height * scale; } /* valid clipping rectangles only */ if ((clip_x0 < clip_x1) && (clip_y0 < clip_y1)) { if (!plot.clip(clip_x0, clip_y0, clip_x1, clip_y1)) return false; - if (!content_redraw_tiled(box-> - background, x, y, - ceilf(box->background-> - width * scale), - ceilf(box->background-> - height * scale), + if (!content_redraw_tiled(box->background, x, y, + ceilf(width * scale), + ceilf(height * scale), clip_x0, clip_y0, clip_x1, clip_y1, scale, *background_colour, diff --git a/render/imagemap.c b/render/imagemap.c index d52e5bdd4..07a46d404 100644 --- a/render/imagemap.c +++ b/render/imagemap.c @@ -24,7 +24,8 @@ #include <stdbool.h> #include <string.h> #include <strings.h> -#include "content/content.h" +#include "content/content_protected.h" +#include "content/hlcache.h" #include "render/box.h" #include "render/imagemap.h" #include "utils/log.h" @@ -626,20 +627,21 @@ void imagemap_freelist(struct mapentry *list) /** * Retrieve url associated with imagemap entry * - * \param c The containing content - * \param key The map name to search for - * \param x The left edge of the containing box - * \param y The top edge of the containing box - * \param click_x The horizontal location of the click - * \param click_y The vertical location of the click - * \param target Pointer to location to receive target pointer (if any) + * \param h The containing content + * \param key The map name to search for + * \param x The left edge of the containing box + * \param y The top edge of the containing box + * \param click_x The horizontal location of the click + * \param click_y The vertical location of the click + * \param target Pointer to location to receive target pointer (if any) * \return The url associated with this area, or NULL if not found */ -const char *imagemap_get(struct content *c, const char *key, +const char *imagemap_get(hlcache_handle *h, const char *key, unsigned long x, unsigned long y, unsigned long click_x, unsigned long click_y, const char **target) { + struct content *c = hlcache_handle_get_content(h); unsigned int slot = 0; struct imagemap *map; struct mapentry *entry; diff --git a/render/imagemap.h b/render/imagemap.h index 34a0c3b5f..87a84c3dd 100644 --- a/render/imagemap.h +++ b/render/imagemap.h @@ -22,11 +22,13 @@ #include <libxml/HTMLtree.h> struct content; +struct hlcache_handle; void imagemap_destroy(struct content *c); void imagemap_dump(struct content *c); bool imagemap_extract(xmlNode *node, struct content *c); -const char *imagemap_get(struct content *c, const char *key, + +const char *imagemap_get(struct hlcache_handle *h, const char *key, unsigned long x, unsigned long y, unsigned long click_x, unsigned long click_y, const char **target); diff --git a/render/layout.c b/render/layout.c index 45a075750..336be3e83 100644 --- a/render/layout.c +++ b/render/layout.c @@ -41,7 +41,7 @@ #include <math.h> #include "css/css.h" #include "css/utils.h" -#include "content/content.h" +#include "content/content_protected.h" #include "desktop/gui.h" #include "desktop/options.h" #include "desktop/scroll.h" @@ -256,12 +256,14 @@ bool layout_block_context(struct box *block, int viewport_height, if (!layout_block_object(block)) return false; if (block->height == AUTO) { - if (block->object->width) - block->height = block->object->height * - (float) block->width / - block->object->width; + if (content_get_width(block->object)) + block->height = + content_get_height(block->object) * + (float) block->width / + content_get_width(block->object); else - block->height = block->object->height; + block->height = + content_get_height(block->object); } return true; } @@ -691,13 +693,13 @@ void layout_minmax_block(struct box *block, } if (block->object) { - if (block->object->type == CONTENT_HTML) { - layout_minmax_block(block->object->data.html.layout, + if (content_get_type(block->object) == CONTENT_HTML) { + layout_minmax_block(html_get_box_tree(block->object), font_func); - min = block->object->data.html.layout->min_width; - max = block->object->data.html.layout->max_width; + min = html_get_box_tree(block->object)->min_width; + max = html_get_box_tree(block->object)->max_width; } else { - min = max = block->object->width; + min = max = content_get_width(block->object); } } else { /* recurse through children */ @@ -795,9 +797,9 @@ bool layout_block_object(struct box *block) LOG(("block %p, object %s, width %i", block, block->object->url, block->width)); - if (block->object->type == CONTENT_HTML) { + if (content_get_type(block->object) == CONTENT_HTML) { content_reformat(block->object, block->width, 1); - block->height = block->object->height; + block->height = content_get_height(block->object); } else { /* this case handled already in * layout_block_find_dimensions() */ @@ -837,25 +839,25 @@ void layout_block_find_dimensions(int available_width, int viewport_height, &width, &height, &max_width, &min_width, margin, padding, border); - if (box->object && box->object->type != CONTENT_HTML) { + if (box->object && content_get_type(box->object) != CONTENT_HTML) { /* block-level replaced element, see 10.3.4 and 10.6.2 */ if (width == AUTO && height == AUTO) { - width = box->object->width; - height = box->object->height; + width = content_get_width(box->object); + height = content_get_height(box->object); } else if (width == AUTO) { - if (box->object->height) - width = box->object->width * + if (content_get_height(box->object)) + width = content_get_width(box->object) * (float) height / - box->object->height; + content_get_height(box->object); else - width = box->object->width; + width = content_get_width(box->object); } else if (height == AUTO) { - if (box->object->width) - height = box->object->height * + if (content_get_width(box->object)) + height = content_get_height(box->object) * (float) width / - box->object->width; + content_get_width(box->object); else - height = box->object->height; + height = content_get_height(box->object); } } @@ -1168,18 +1170,20 @@ void layout_float_find_dimensions(int available_width, padding[RIGHT] += scrollbar_width; padding[BOTTOM] += scrollbar_width; - if (box->object && box->object->type != CONTENT_HTML) { + if (box->object && content_get_type(box->object) != CONTENT_HTML) { /* Floating replaced element, with intrinsic width or height. * See 10.3.6 and 10.6.2 */ if (width == AUTO && height == AUTO) { - width = box->object->width; - height = box->object->height; + width = content_get_width(box->object); + height = content_get_height(box->object); } else if (width == AUTO) - width = box->object->width * (float) height / - box->object->height; + width = content_get_width(box->object) * + (float) height / + content_get_height(box->object); else if (height == AUTO) - height = box->object->height * (float) width / - box->object->width; + height = content_get_height(box->object) * + (float) width / + content_get_width(box->object); } else if (box->gadget && (box->gadget->type == GADGET_TEXTBOX || box->gadget->type == GADGET_PASSWORD || box->gadget->type == GADGET_FILE || @@ -2079,22 +2083,25 @@ bool layout_line(struct box *first, int *width, int *y, if (b->object) { if (b->width == AUTO && b->height == AUTO) { - b->width = b->object->width; - b->height = b->object->height; + b->width = content_get_width(b->object); + b->height = content_get_height(b->object); } else if (b->width == AUTO) { - if (b->object->height) - b->width = b->object->width * - (float) b->height / - b->object->height; + if (content_get_height(b->object)) + b->width = + content_get_width(b->object) * + (float) b->height / + content_get_height(b->object); else - b->width = b->object->width; + b->width = content_get_width(b->object); } else if (b->height == AUTO) { - if (b->object->width) - b->height = b->object->height * - (float) b->width / - b->object->width; + if (content_get_width(b->object)) + b->height = + content_get_height(b->object) * + (float) b->width / + content_get_width(b->object); else - b->height = b->object->height; + b->height = + content_get_height(b->object); } } else { /* form control with no object */ @@ -2106,14 +2113,15 @@ bool layout_line(struct box *first, int *width, int *y, CSS_UNIT_EM, b->style)); } - if (b->object && b->object->type == CONTENT_HTML && - b->width != b->object->available_width) { + if (b->object && content_get_type(b->object) == CONTENT_HTML && + b->width != + content_get_available_width(b->object)) { htype = css_computed_height(b->style, &value, &unit); content_reformat(b->object, b->width, b->height); if (htype == CSS_HEIGHT_AUTO) - b->height = b->object->height; + b->height = content_get_height(b->object); } if (height < b->height) @@ -2745,14 +2753,14 @@ struct box *layout_minmax_line(struct box *first, if (b->object) { if (width == AUTO && height == AUTO) { - width = b->object->width; + width = content_get_width(b->object); } else if (width == AUTO) { - if (b->object->height) - width = b->object->width * - (float) height / - b->object->height; + if (content_get_height(b->object)) + width = content_get_width(b->object) * + (float) height / + content_get_height(b->object); else - width = b->object->width; + width = content_get_width(b->object); } fixed = frac = 0; calculate_mbp_width(b->style, LEFT, true, true, true, @@ -3709,9 +3717,11 @@ void layout_lists(struct box *box, if (child->list_marker) { marker = child->list_marker; if (marker->object) { - marker->width = marker->object->width; + marker->width = + content_get_width(marker->object); marker->x = -marker->width; - marker->height = marker->object->height; + marker->height = + content_get_height(marker->object); marker->y = (line_height(marker->style) - marker->height) / 2; } else if (marker->text) { diff --git a/render/textplain.c b/render/textplain.c index 07f37610c..befa9aa50 100644 --- a/render/textplain.c +++ b/render/textplain.c @@ -28,7 +28,8 @@ #include <strings.h> #include <math.h> #include <iconv.h> -#include "content/content.h" +#include "content/content_protected.h" +#include "content/hlcache.h" #include "css/css.h" #include "css/utils.h" #include "desktop/gui.h" @@ -39,6 +40,7 @@ #include "render/box.h" #include "render/font.h" #include "render/textplain.h" +#include "utils/http.h" #include "utils/log.h" #include "utils/messages.h" #include "utils/talloc.h" @@ -72,14 +74,13 @@ static float textplain_line_height(void); * Create a CONTENT_TEXTPLAIN. */ -bool textplain_create(struct content *c, struct content *parent, - const char *params[]) +bool textplain_create(struct content *c, const http_parameter *params) { - unsigned int i; char *utf8_data; - const char *encoding = "iso-8859-1"; + const char *encoding; iconv_t iconv_cd; union content_msg_data msg_data; + nserror error; textplain_style.size = (option_font_size * FONT_SIZE_SCALE) / 10; @@ -87,13 +88,9 @@ bool textplain_create(struct content *c, struct content *parent, if (!utf8_data) goto no_memory; - for (i = 0; params[i]; i += 2) { - if (strcasecmp(params[i], "charset") == 0) { - encoding = talloc_strdup(c, params[i + 1]); - if (!encoding) - goto no_memory; - break; - } + error = http_parameter_list_find_item(params, "charset", &encoding); + if (error != NSERROR_OK) { + encoding = "Windows-1252"; } iconv_cd = iconv_open("utf-8", encoding); @@ -141,18 +138,22 @@ bool textplain_process_data(struct content *c, char *data, unsigned int size) iconv_t iconv_cd = c->data.textplain.iconv_cd; size_t count; union content_msg_data msg_data; + const char *source_data; + unsigned long source_size; + + source_data = content__get_source_data(c, &source_size); do { - char *inbuf = c->source_data + c->data.textplain.converted; - size_t inbytesleft = c->source_size - + char *inbuf = (char *) source_data + c->data.textplain.converted; + size_t inbytesleft = source_size - c->data.textplain.converted; char *outbuf = c->data.textplain.utf8_data + c->data.textplain.utf8_data_size; size_t outbytesleft = c->data.textplain.utf8_data_allocated - c->data.textplain.utf8_data_size; count = iconv(iconv_cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); - c->data.textplain.converted = inbuf - c->source_data; + c->data.textplain.converted = inbuf - source_data; c->data.textplain.utf8_data_size = c->data.textplain. utf8_data_allocated - outbytesleft; @@ -180,7 +181,7 @@ bool textplain_process_data(struct content *c, char *data, unsigned int size) } gui_multitask(); - } while (!(c->data.textplain.converted == c->source_size || + } while (!(c->data.textplain.converted == source_size || (count == (size_t)(-1) && errno == EINVAL))); return true; @@ -466,6 +467,35 @@ bool textplain_redraw(struct content *c, int x, int y, return true; } +/** + * Retrieve number of lines in content + * + * \param h Content to retrieve line count from + * \return Number of lines + */ +unsigned long textplain_line_count(hlcache_handle *h) +{ + struct content *c = hlcache_handle_get_content(h); + + assert(c != NULL); + + return c->data.textplain.physical_line_count; +} + +/** + * Retrieve the size (in bytes) of text data + * + * \param h Content to retrieve size of + * \return Size, in bytes, of data + */ +size_t textplain_size(hlcache_handle *h) +{ + struct content *c = hlcache_handle_get_content(h); + + assert(c != NULL); + + return c->data.textplain.utf8_data_size; +} /** * Return byte offset within UTF8 textplain content, given the co-ordinates @@ -473,15 +503,16 @@ bool textplain_redraw(struct content *c, int x, int y, * which to search (-1 = above-left, +1 = below-right) if the co-ordinates are not * contained within a line. * - * \param c content of type CONTENT_TEXTPLAIN + * \param h content of type CONTENT_TEXTPLAIN * \param x x ordinate of point * \param y y ordinate of point * \param dir direction of search if not within line * \return byte offset of character containing (or nearest to) point */ -size_t textplain_offset_from_coords(struct content *c, int x, int y, int dir) +size_t textplain_offset_from_coords(hlcache_handle *h, int x, int y, int dir) { + struct content *c = hlcache_handle_get_content(h); float line_height = textplain_line_height(); struct textplain_line *line; const char *text; @@ -489,6 +520,7 @@ size_t textplain_offset_from_coords(struct content *c, int x, int y, int dir) size_t length; int idx; + assert(c != NULL); assert(c->type == CONTENT_TEXTPLAIN); y = (int)((float)(y - MARGIN) / line_height); @@ -552,19 +584,24 @@ size_t textplain_offset_from_coords(struct content *c, int x, int y, int dir) * Given a byte offset within the text, return the line number * of the line containing that offset (or -1 if offset invalid) * - * \param c content of type CONTENT_TEXTPLAIN + * \param h content of type CONTENT_TEXTPLAIN * \param offset byte offset within textual representation * \return line number, or -1 if offset invalid (larger than size) */ -int textplain_find_line(struct content *c, unsigned offset) +int textplain_find_line(hlcache_handle *h, unsigned offset) { - struct textplain_line *line = c->data.textplain.physical_line; - int nlines = c->data.textplain.physical_line_count; + struct content *c = hlcache_handle_get_content(h); + struct textplain_line *line; + int nlines; int lineno = 0; + assert(c != NULL); assert(c->type == CONTENT_TEXTPLAIN); + line = c->data.textplain.physical_line; + nlines = c->data.textplain.physical_line_count; + if (offset > c->data.textplain.utf8_data_size) return -1; @@ -622,30 +659,33 @@ int textplain_coord_from_offset(const char *text, size_t offset, size_t length) * Given a range of byte offsets within a UTF8 textplain content, * return a box that fully encloses the text * - * \param c content of type CONTENT_TEXTPLAIN + * \param h content of type CONTENT_TEXTPLAIN * \param start byte offset of start of text range * \param end byte offset of end * \param r rectangle to be completed */ -void textplain_coords_from_range(struct content *c, unsigned start, unsigned end, - struct rect *r) +void textplain_coords_from_range(hlcache_handle *h, unsigned start, + unsigned end, struct rect *r) { + struct content *c = hlcache_handle_get_content(h); float line_height = textplain_line_height(); - char *utf8_data = c->data.textplain.utf8_data; + char *utf8_data; struct textplain_line *line; unsigned lineno = 0; unsigned nlines; + assert(c != NULL); assert(c->type == CONTENT_TEXTPLAIN); assert(start <= end); assert(end <= c->data.textplain.utf8_data_size); + utf8_data = c->data.textplain.utf8_data; nlines = c->data.textplain.physical_line_count; line = c->data.textplain.physical_line; /* find start */ - lineno = textplain_find_line(c, start); + lineno = textplain_find_line(h, start); r->y0 = (int)(MARGIN + lineno * line_height); @@ -654,7 +694,7 @@ void textplain_coords_from_range(struct content *c, unsigned start, unsigned end forwards most of the time */ /* find end */ - lineno = textplain_find_line(c, end); + lineno = textplain_find_line(h, end); r->x0 = 0; r->x1 = c->data.textplain.formatted_width; @@ -677,18 +717,20 @@ void textplain_coords_from_range(struct content *c, unsigned start, unsigned end /** * Return a pointer to the requested line of text. * - * \param c content of type CONTENT_TEXTPLAIN + * \param h content of type CONTENT_TEXTPLAIN * \param lineno line number * \param poffset receives byte offset of line start within text * \param plen receives length of returned line * \return pointer to text, or NULL if invalid line number */ -char *textplain_get_line(struct content *c, unsigned lineno, +char *textplain_get_line(hlcache_handle *h, unsigned lineno, size_t *poffset, size_t *plen) { + struct content *c = hlcache_handle_get_content(h); struct textplain_line *line; + assert(c != NULL); assert(c->type == CONTENT_TEXTPLAIN); if (lineno >= c->data.textplain.physical_line_count) @@ -706,20 +748,24 @@ char *textplain_get_line(struct content *c, unsigned lineno, * text to fit the window width. Thus only hard newlines are preserved * in the saved/copied text of a selection. * - * \param c content of type CONTENT_TEXTPLAIN + * \param h content of type CONTENT_TEXTPLAIN * \param start starting byte offset within UTF-8 text * \param end ending byte offset * \param plen receives validated length * \return pointer to text, or NULL if no text */ -char *textplain_get_raw_data(struct content *c, unsigned start, unsigned end, +char *textplain_get_raw_data(hlcache_handle *h, unsigned start, unsigned end, size_t *plen) { - size_t utf8_size = c->data.textplain.utf8_data_size; + struct content *c = hlcache_handle_get_content(h); + size_t utf8_size; + assert(c != NULL); assert(c->type == CONTENT_TEXTPLAIN); + utf8_size = c->data.textplain.utf8_data_size; + /* any text at all? */ if (!utf8_size) return NULL; diff --git a/render/textplain.h b/render/textplain.h index 10609a71b..50e29c5be 100644 --- a/render/textplain.h +++ b/render/textplain.h @@ -28,6 +28,8 @@ #include <iconv.h> struct content; +struct hlcache_handle; +struct http_parameter; struct textplain_line { size_t start; @@ -46,8 +48,7 @@ struct content_textplain_data { int formatted_width; }; -bool textplain_create(struct content *c, struct content *parent, - const char *params[]); +bool textplain_create(struct content *c, const struct http_parameter *params); bool textplain_process_data(struct content *c, char *data, unsigned int size); bool textplain_convert(struct content *c, int width, int height); void textplain_reformat(struct content *c, int width, int height); @@ -58,16 +59,17 @@ bool textplain_redraw(struct content *c, int x, int y, float scale, colour background_colour); /* access to lines for text selection and searching */ -#define textplain_line_count(c) ((c)->data.textplain.physical_line_count) -#define textplain_size(c) ((c)->data.textplain.utf8_data_size) +unsigned long textplain_line_count(struct hlcache_handle *h); +size_t textplain_size(struct hlcache_handle *h); -size_t textplain_offset_from_coords(struct content *c, int x, int y, int dir); -void textplain_coords_from_range(struct content *c, +size_t textplain_offset_from_coords(struct hlcache_handle *h, int x, int y, + int dir); +void textplain_coords_from_range(struct hlcache_handle *h, unsigned start, unsigned end, struct rect *r); -char *textplain_get_line(struct content *c, unsigned lineno, +char *textplain_get_line(struct hlcache_handle *h, unsigned lineno, size_t *poffset, size_t *plen); -int textplain_find_line(struct content *c, unsigned offset); -char *textplain_get_raw_data(struct content *c, +int textplain_find_line(struct hlcache_handle *h, unsigned offset); +char *textplain_get_raw_data(struct hlcache_handle *h, unsigned start, unsigned end, size_t *plen); #endif -- cgit v1.2.3