Review: Merge branch mmu_man/netsurf-gopher-support
by François Revol
Precis:
Gopher browsing is now mostly functional.
Due to having to wait for the full content before converting to html, large pages like search results might take some seconds to load, but otherwise it works not too bad.
Supported item-types:
- 0 (plain text)
- 1 (gopher dir) converted to html for display
- 3 (error, when first item should behave as an HTTP 404, not much tested)
- 7 (search) converted to html for display
- 8 generates a link to a telnet: URI
- g (GIF) adds a link (or optionally inlines the image as <img>)
- h (html) selectors begining with URL: are automatically converted to direct links to the specified URL, which then is not limited to http: either.
- i displays a text line
- I (image) links to the item but tries to display as text.
- 9 (binary) links to the item but tries to display as text.
- d (PDF, unofficial)
- p (seems to be PNG, unofficial)
- all other unknown types are just linked as is, and will probably work when the mime type is correctly sniffed.
Unsupported item-types:
- 2 (CSO search) I failed to find a sample link, it requires a complex and separate protocol.
- T (TN3270) Failed to find a sample link, it's an antique competitor to telnet.
Missing stuff, which will be considered in a second iteration:
- document the feature.
- document requirements for ports (like, OSX requires libcurl from MacPort to have the fetcher working).
- better error handling on non-existing files (will require an heuristic since gopher doesn't have out-of-band signaling).
- make the parser more robust.
- fix url escaping in generated html code, gopher selectors can include any character except tab, though no tested servers ever tried using reserved html chars yet.
- merge custom generated CSS with internal.css.
- improve the used CSS (reuse the blueish dirlist one ?).
- add text/dir/search icons like other usual clients (optional ?).
- links to ambiguous items (like type 'I' which can be JPEG or PNG or another image type, and binary types like '9') will attempt to load the target as a text file. Handling them correctly probably requires implementing LLCACHE_RETRIEVE_SNIFF_TYPE. Archive types could probably get a fake Content-disposition header forcing a download though.
- make gopher: URI scheme handling explicit to OS front-ends (done for BeOS).
- fix search field sending an extra = in the url (add a "GOPHER" form method maybe ?), though all tested search engines just skip it.
- maybe Gopher+ support but it seems most clients just ignore it.
Added files
Index: render/gopher.c
===================================================================
--- /dev/null 2011-05-04 14:01:53.000000000 +0200
+++ render/gopher.c 2011-05-04 12:18:42.000000000 +0200
@@ -0,0 +1,662 @@
+/*
+ * Copyright 2006 James Bursa <bursa(a)users.sourceforge.net>
+ * Copyright 2006 Adrian Lees <adrianl(a)users.sourceforge.net>
+ * Copyright 2011 François Revol <mmu_man(a)users.sourceforge.net>
+ *
+ * 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
+ * Content for text/x-gopher-directory (implementation).
+ */
+
+#include <errno.h>
+#include <stddef.h>
+#include <string.h>
+#include <strings.h>
+#include <math.h>
+
+#include "content/content_protected.h"
+#include "desktop/gui.h"
+#include "desktop/options.h"
+#include "render/gopher.h"
+#include "utils/http.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+
+static char *gen_nice_title(const char *path);
+static bool gopher_generate_top(char *buffer, int buffer_length);
+static bool gopher_generate_title(const char *title, char *buffer, int buffer_length);
+static bool gopher_generate_row(const char **data, size_t *size,
+ char *buffer, int buffer_length);
+static bool gopher_generate_bottom(char *buffer, int buffer_length);
+
+
+static struct {
+ char type;
+ const char *mime;
+} gopher_type_map[] = {
+ /* these come from http://tools.ietf.org/html/rfc1436 */
+ { '0', "text/plain" },
+ { '1', "text/x-gopher-directory;charset=UTF-8" }, /* gopher directory */
+ /* 2 CSO search */
+ /* 3 error message */
+ /* 4 binhex encoded text */
+ /* 5 binary archive file */
+ /* 6 uuencoded text */
+ { '7', "text/x-gopher-directory;charset=UTF-8" }, /* search query */
+ /* 8 telnet: */
+ /* 9 binary */
+ { 'g', "image/gif" },
+ { 'h', "text/html" },
+ /* i information text */
+ /* I image (depends, usually jpeg) */
+ /* s audio (wav?) */
+ /* T tn3270 session */
+
+ /* those are not standardized */
+ { 'd', "application/pdf" }, /* display?? seems to be only for PDF files so far */
+ { 'p', "image/png"}, /* at least on gopher://namcub.accelera-labs.com/1/pics */
+ { 0, NULL }
+};
+
+
+/**
+ * Create a CONTENT_GOPHER.
+ */
+
+bool gopher_create(struct content *c, const http_parameter *params)
+{
+ bool ok;
+ ok = html_create(c, params);
+ return ok;
+}
+
+
+/**
+ * Convert a CONTENT_GOPHER for display.
+ */
+
+bool gopher_convert(struct content *c)
+{
+ char *title;
+ char buffer[1024];
+ const char *data;
+ unsigned long size;
+ const char *p;
+ unsigned long left;
+ bool ok;
+
+ data = content__get_source_data(c, &size);
+
+ p = data;
+ left = size;
+ if (data == NULL || size == 0)
+ return false;
+
+ if (gopher_generate_bottom(buffer, sizeof(buffer))) {
+ ok = html_process_data(c, buffer, strlen(buffer));
+ if (!ok)
+ return false;
+ }
+ if (gopher_generate_top(buffer, sizeof(buffer))) {
+ ok = html_process_data(c, buffer, strlen(buffer));
+ if (!ok)
+ return false;
+ }
+ title = gen_nice_title(content__get_url(c));
+ if (gopher_generate_title(title, buffer, sizeof(buffer))) {
+ ok = html_process_data(c, buffer, strlen(buffer));
+ if (!ok)
+ return false;
+ }
+ free(title);
+
+ while (gopher_generate_row(&p, &left, buffer, sizeof(buffer))) {
+ ok = html_process_data(c, buffer, strlen(buffer));
+ if (!ok)
+ return false;
+ gui_multitask();
+ }
+
+ /* finally make it HTML so we don't have to bother for other calls */
+ c->type = CONTENT_HTML;
+ return html_convert(c);
+}
+
+
+static char *html_escape_string(char *str)
+{
+ char *nice_str, *cnv, *tmp;
+
+ if (str == NULL) {
+ return NULL;
+ }
+
+ /* Convert str for display */
+ nice_str = malloc(strlen(str) * SLEN("&") + 1);
+ if (nice_str == NULL) {
+ return NULL;
+ }
+
+ /* Escape special HTML characters */
+ for (cnv = nice_str, tmp = str; *tmp != '\0'; tmp++) {
+ if (*tmp == '<') {
+ *cnv++ = '&';
+ *cnv++ = 'l';
+ *cnv++ = 't';
+ *cnv++ = ';';
+ } else if (*tmp == '>') {
+ *cnv++ = '&';
+ *cnv++ = 'g';
+ *cnv++ = 't';
+ *cnv++ = ';';
+ } else if (*tmp == '&') {
+ *cnv++ = '&';
+ *cnv++ = 'a';
+ *cnv++ = 'm';
+ *cnv++ = 'p';
+ *cnv++ = ';';
+ } else {
+ *cnv++ = *tmp;
+ }
+ }
+ *cnv = '\0';
+
+ return nice_str;
+}
+
+
+static char *gen_nice_title(const char *path)
+{
+ const char *tmp;
+ char *nice_path, *cnv;
+ char *title;
+ int title_length;
+
+ /* Convert path for display */
+ nice_path = malloc(strlen(path) * SLEN("&") + 1);
+ if (nice_path == NULL) {
+ return NULL;
+ }
+
+ /* Escape special HTML characters */
+ for (cnv = nice_path, tmp = path; *tmp != '\0'; tmp++) {
+ if (*tmp == '<') {
+ *cnv++ = '&';
+ *cnv++ = 'l';
+ *cnv++ = 't';
+ *cnv++ = ';';
+ } else if (*tmp == '>') {
+ *cnv++ = '&';
+ *cnv++ = 'g';
+ *cnv++ = 't';
+ *cnv++ = ';';
+ } else if (*tmp == '&') {
+ *cnv++ = '&';
+ *cnv++ = 'a';
+ *cnv++ = 'm';
+ *cnv++ = 'p';
+ *cnv++ = ';';
+ } else {
+ *cnv++ = *tmp;
+ }
+ }
+ *cnv = '\0';
+
+ /* Construct a localised title string */
+ title_length = (cnv - nice_path) + strlen(messages_get("FileIndex"));
+ title = malloc(title_length + 1);
+
+ if (title == NULL) {
+ free(nice_path);
+ return NULL;
+ }
+
+ /* Set title to localised "Index of <nice_path>" */
+ snprintf(title, title_length, messages_get("FileIndex"), nice_path);
+
+ free(nice_path);
+
+ return title;
+}
+
+
+/**
+ * Convert the gopher item type to mime type
+ *
+ * \return MIME type string
+ *
+ */
+
+const char *gopher_type_to_mime(char type)
+{
+ int i;
+
+ for (i = 0; gopher_type_map[i].type; i++)
+ if (gopher_type_map[i].type == type)
+ return gopher_type_map[i].mime;
+ return NULL;
+}
+
+
+/**
+ * Tells if the gopher item type needs to be converted to html
+ *
+ * \return true iff the item must be converted
+ *
+ */
+
+bool gopher_need_generate(char type)
+{
+ switch (type) {
+ case '1':
+ case '7':
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+/**
+ * Generates the top part of an HTML directory listing page
+ *
+ * \return true iff buffer filled without error
+ *
+ * This is part of a series of functions. To generate a complete page,
+ * call the following functions in order:
+ *
+ * gopher_generate_top()
+ * gopher_generate_title()
+ * gopher_generate_row() -- call 'n' times for 'n' rows
+ * gopher_generate_bottom()
+ */
+
+static bool gopher_generate_top(char *buffer, int buffer_length)
+{
+ int error = snprintf(buffer, buffer_length,
+ "<html>\n"
+ "<head>\n"
+ /*"<!-- base href=\"%s\" -->\n"*//* XXX: needs the content url */
+ /* Don't do that:
+ * seems to trigger a reparsing of the gopher data itself as html...
+ * "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n"
+ */
+ /* TODO: move this to clean CSS in internal.css */
+ "<link rel=\"stylesheet\" title=\"Standard\" "
+ "type=\"text/css\" href=\"resource:internal.css\">\n"
+ "<style>\n"
+ /* XXX: white-space: pre-wrap would be better but is currently buggy */
+ "span { font-family: Courier, monospace; white-space: pre; }\n"
+ "body { margin: 10px; }\n");
+ if (error < 0 || error >= buffer_length)
+ /* Error or buffer too small */
+ return false;
+ else
+ /* OK */
+ return true;
+
+}
+
+
+/**
+ * Generates the part of an HTML directory listing page that contains the title
+ *
+ * \param title title to use
+ * \param buffer buffer to fill with generated HTML
+ * \param buffer_length maximum size of buffer
+ * \return true iff buffer filled without error
+ *
+ * This is part of a series of functions. To generate a complete page,
+ * call the following functions in order:
+ *
+ * gopher_generate_top()
+ * gopher_generate_title()
+ * gopher_generate_row() -- call 'n' times for 'n' rows
+ * gopher_generate_bottom()
+ */
+
+static bool gopher_generate_title(const char *title, char *buffer, int buffer_length)
+{
+ int error;
+
+ if (title == NULL)
+ title = "";
+
+ error = snprintf(buffer, buffer_length,
+ "</style>\n"
+ "<title>%s</title>\n"
+ "</head>\n"
+ "<body id=\"gopher\">\n"
+ "<h1>%s</h1>\n",
+ title, title);
+ if (error < 0 || error >= buffer_length)
+ /* Error or buffer too small */
+ return false;
+ else
+ /* OK */
+ return true;
+}
+
+/**
+ * Internal worker called by gopher_generate_row().
+ */
+
+static bool gopher_generate_row_internal(char type, char *fields[5],
+ char *buffer, int buffer_length)
+{
+ char *nice_text;
+ char *redirect_url = NULL;
+ int error;
+ bool alt_port = false;
+ char *username = NULL;
+
+ if (fields[3] && strcmp(fields[3], "70"))
+ alt_port = true;
+
+ /* escape html special characters */
+ nice_text = html_escape_string(fields[0]);
+
+ /* XXX: outputting \n generates better looking html code,
+ * but currently screws up indentation due to a bug.
+ */
+#define HTML_LF
+/*#define HTML_LF "\n"*/
+
+ switch (type) {
+ case '.':
+ /* end of the page */
+ *buffer = '\0';
+ break;
+ case '0': /* text/plain link */
+ case '9': /* binary */
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+ "<span class=\"dir\">%s</span><br/>"HTML_LF
+ "</a>"HTML_LF,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1], nice_text);
+ break;
+ case '1':
+ /*
+ * directory link
+ */
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+ "<span class=\"text\">%s</span><br/>"HTML_LF
+ "</a>"HTML_LF,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1], nice_text);
+ break;
+ case '3':
+ /* Error
+ */
+ error = snprintf(buffer, buffer_length,
+ "<span class=\"error\">%s</span><br/>"HTML_LF,
+ nice_text);
+ break;
+ case '7':
+ /* TODO: handle search better.
+ * For now we use an unnamed input field and accept sending ?=foo
+ * as it seems at least Veronica-2 ignores the = but it's unclean.
+ */
+ error = snprintf(buffer, buffer_length,
+ "<form method=\"get\" action=\"gopher://%s%s%s/%c%s\">"HTML_LF
+ "<span class=\"query\"><label>%s <input name=\"\" type=\"text\" align=\"right\" /></label></span><br/>"HTML_LF
+ "</form>"HTML_LF,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1], nice_text);
+ break;
+ case '8':
+ /* telnet: links
+ * cf. gopher://78.80.30.202/1/ps3
+ * -> gopher://78.80.30.202:23/8/ps3/new -> new(a)78.80.30.202
+ */
+ alt_port = false;
+ if (fields[3] && strcmp(fields[3], "23"))
+ alt_port = true;
+ username = strrchr(fields[1], '/');
+ if (username)
+ username++;
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"telnet://%s%s%s%s%s\">"HTML_LF
+ "<span class=\"dir\">%s</span><br/>"HTML_LF
+ "</a>"HTML_LF,
+ username ? username : "",
+ username ? "@" : "",
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ nice_text);
+ break;
+ case 'g':
+ case 'I':
+ case 'p':
+ /* quite dangerous, cf. gopher://namcub.accela-labs.com/1/pics */
+ if (option_gopher_inline_images) {
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+ "<span class=\"img\">%s "HTML_LF /* </span><br/> */
+ //"<span class=\"img\" >"HTML_LF
+ "<img src=\"gopher://%s%s%s/%c%s\" alt=\"%s\"/>"HTML_LF
+ "</span>"
+ "<br/>"
+ "</a>"HTML_LF,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1],
+ nice_text,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1],
+ nice_text);
+ break;
+ }
+ /* fallback to default, link them */
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+ "<span class=\"dir\">%s</span><br/>"HTML_LF
+ "</a>"HTML_LF,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1], nice_text);
+ break;
+ case 'h':
+ if (fields[1] && strncmp(fields[1], "URL:", 4) == 0)
+ redirect_url = fields[1] + 4;
+ /* cf. gopher://pineapple.vg/1 */
+ if (fields[1] && strncmp(fields[1], "/URL:", 5) == 0)
+ redirect_url = fields[1] + 5;
+ if (redirect_url) {
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"%s\">"HTML_LF
+ "<span class=\"link\">%s</span><br/>"HTML_LF
+ "</a>"HTML_LF,
+ redirect_url,
+ nice_text);
+ } else {
+ /* cf. gopher://sdf.org/1/sdf/classes/ */
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+ "<span class=\"dir\">%s</span><br/>"HTML_LF
+ "</a>"HTML_LF,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1], nice_text);
+ }
+ break;
+ case 'i':
+ error = snprintf(buffer, buffer_length,
+ "<span class=\"info\">%s</span><br/>"HTML_LF,
+ nice_text);
+ break;
+ default:
+ LOG(("warning: unknown gopher item type 0x%02x '%c'\n", type, type));
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+ "<span class=\"dir\">%s</span><br/>"HTML_LF
+ "</a>"HTML_LF,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1], nice_text);
+ break;
+ }
+
+ free(nice_text);
+
+ if (error < 0 || error >= buffer_length)
+ /* Error or buffer too small */
+ return false;
+ else
+ /* OK */
+ return true;
+}
+
+
+/**
+ * Generates the part of an HTML directory listing page that displays a row
+ * of the gopher data
+ *
+ * \param size pointer to the data buffer pointer
+ * \param size pointer to the remaining data size
+ * \param buffer buffer to fill with generated HTML
+ * \param buffer_length maximum size of buffer
+ * \return true iff buffer filled without error
+ *
+ * This is part of a series of functions. To generate a complete page,
+ * call the following functions in order:
+ *
+ * gopher_generate_top()
+ * gopher_generate_title()
+ * gopher_generate_row() -- call 'n' times for 'n' rows
+ * gopher_generate_bottom()
+ */
+
+static bool gopher_generate_row(const char **data, size_t *size,
+ char *buffer, int buffer_length)
+{
+ bool ok = false;
+ char type = 0;
+ int field = 0;
+ /* name, selector, host, port, gopher+ flag */
+ char *fields[5] = { NULL, NULL, NULL, NULL, NULL };
+ const char *s = *data;
+ const char *p = *data;
+ int i;
+
+ for (; *size && *p; p++, (*size)--) {
+ if (!type) {
+ type = *p;
+ if (!type || type == '\n' || type == '\r') {
+ LOG(("warning: invalid gopher item type 0x%02x\n", type));
+ }
+ s++;
+ continue;
+ }
+ switch (*p) {
+ case '\n':
+ if (field > 0) {
+ LOG(("warning: unterminated gopher item '%c'\n", type));
+ }
+ //FALLTHROUGH
+ case '\r':
+ if (*size < 1 || p[1] != '\n') {
+ LOG(("warning: CR without LF in gopher item '%c'\n", type));
+ }
+ if (field < 3 && type != '.') {
+ LOG(("warning: unterminated gopher item '%c'\n", type));
+ }
+ fields[field] = malloc(p - s + 1);
+ memcpy(fields[field], s, p - s);
+ fields[field][p - s] = '\0';
+ if (type == '.' && field == 0 && p == s) {
+ ;/* XXX: signal end of page? For now we just ignore it. */
+ }
+ ok = gopher_generate_row_internal(type, fields, buffer, buffer_length);
+ for (i = 0; i < 5; i++) {
+ free(fields[i]);
+ fields[i] = NULL;
+ }
+ (*size)--;
+ p++;
+ if (*size && *p == '\n') {
+ p++;
+ (*size)--;
+ }
+ *data = p;
+ field = 0;
+ return ok;
+ case '\x09':
+ if (field >= 4) {
+ LOG(("warning: extra tab in gopher item '%c'\n", type));
+ break;
+ }
+ fields[field] = malloc(p - s + 1);
+ memcpy(fields[field], s, p - s);
+ fields[field][p - s] = '\0';
+ field++;
+ s = p + 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return false;
+}
+
+
+/**
+ * Generates the bottom part of an HTML directory listing page
+ *
+ * \return Bottom of directory listing HTML
+ *
+ * This is part of a series of functions. To generate a complete page,
+ * call the following functions in order:
+ *
+ * gopher_generate_top()
+ * gopher_generate_title()
+ * gopher_generate_row() -- call 'n' times for 'n' rows
+ * gopher_generate_bottom()
+ */
+
+static bool gopher_generate_bottom(char *buffer, int buffer_length)
+{
+ int error = snprintf(buffer, buffer_length,
+ "</div>\n"
+ "</body>\n"
+ "</html>\n");
+ if (error < 0 || error >= buffer_length)
+ /* Error or buffer too small */
+ return false;
+ else
+ /* OK */
+ return true;
+}
+
+
Index: render/gopher.h
===================================================================
--- /dev/null 2011-05-04 14:01:53.000000000 +0200
+++ render/gopher.h 2011-05-04 12:18:42.000000000 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2006 James Bursa <bursa(a)users.sourceforge.net>
+ * Copyright 2006 Adrian Lees <adrianl(a)users.sourceforge.net>
+ * Copyright 2011 François Revol <mmu_man(a)users.sourceforge.net>
+ *
+ * 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
+ * Content for text/x-gopher-directory (interface).
+ */
+
+#ifndef _NETSURF_RENDER_GOPHER_H_
+#define _NETSURF_RENDER_GOPHER_H_
+
+#include <stddef.h>
+
+struct content;
+struct http_parameter;
+
+bool gopher_create(struct content *c, const struct http_parameter *params);
+bool gopher_convert(struct content *c);
+
+
+const char *gopher_type_to_mime(char type);
+bool gopher_need_generate(char type);
+
+#endif
Changed files
Makefile.sources | 3 +-
beos/beos_res.rdef | 2 +
content/content.c | 6 ++++
content/content_type.h | 1
content/fetchers/curl.c | 71 +++++++++++++++++++++++++++++++++++++++++++++---
desktop/options.c | 3 ++
desktop/options.h | 1
utils/url.c | 32 +++++++++++++++++++++
utils/url.h | 1
9 files changed, 116 insertions(+), 4 deletions(-)
Index: beos/beos_res.rdef
===================================================================
--- beos/beos_res.rdef (revision 12271)
+++ beos/beos_res.rdef (working copy)
@@ -108,9 +108,11 @@
"types" = "image/jpeg",
"types" = "application/x-vnd.Be-bookmark",
"types" = "text",
+ "types" = "text/x-gopher-directory",
"types" = "application/x-vnd.Be-doc_bookmark",
"types" = "application/x-vnd.Be.URL.file",
"types" = "application/x-vnd.Be.URL.ftp",
+ "types" = "application/x-vnd.Be.URL.gopher",
"types" = "application/x-vnd.Be.URL.http",
"types" = "application/x-vnd.Be.URL.https"
};
Index: Makefile.sources
===================================================================
--- Makefile.sources (revision 12271)
+++ Makefile.sources (working copy)
@@ -12,7 +12,8 @@
S_RENDER := box.c box_construct.c box_normalise.c favicon.c \
font.c form.c html.c html_interaction.c html_redraw.c \
- hubbub_binding.c imagemap.c layout.c list.c table.c textplain.c
+ hubbub_binding.c imagemap.c layout.c list.c table.c textplain.c \
+ gopher.c
S_UTILS := base64.c filename.c hashtable.c http.c locale.c messages.c \
talloc.c url.c utf8.c utils.c useragent.c filepath.c log.c
Index: utils/url.c
===================================================================
--- utils/url.c (revision 12271)
+++ utils/url.c (working copy)
@@ -856,6 +856,38 @@
}
/**
+ * Extract the gopher document type from an URL
+ *
+ * \param url an absolute URL
+ * \param result pointer to buffer to hold result
+ * \return URL_FUNC_OK on success
+ */
+
+url_func_result url_gopher_type(const char *url, char *result)
+{
+ url_func_result status;
+ struct url_components components;
+
+ assert(url);
+
+ status = url_get_components(url, &components);
+ if (status == URL_FUNC_OK) {
+ if (!components.path) {
+ status = URL_FUNC_FAILED;
+ } else {
+ if (strlen(components.path) < 2)
+ *result = '1';
+ else if (components.path[0] == '/')
+ *result = components.path[1];
+ else
+ status = URL_FUNC_FAILED;
+ }
+ }
+ url_destroy_components(&components);
+ return status;
+}
+
+/**
* Attempt to find a nice filename for a URL.
*
* \param url an absolute URL
Index: utils/url.h
===================================================================
--- utils/url.h (revision 12271)
+++ utils/url.h (working copy)
@@ -60,6 +60,7 @@
url_func_result url_path(const char *url, char **result);
url_func_result url_leafname(const char *url, char **result);
url_func_result url_fragment(const char *url, char **result);
+url_func_result url_gopher_type(const char *url, char *result);
url_func_result url_compare(const char *url1, const char *url2,
bool nofrag, bool *result);
Index: desktop/options.h
===================================================================
--- desktop/options.h (revision 12271)
+++ desktop/options.h (working copy)
@@ -49,6 +49,7 @@
extern int option_http_proxy_auth;
extern char *option_http_proxy_auth_user;
extern char *option_http_proxy_auth_pass;
+extern bool option_gopher_inline_images;
extern int option_font_size;
extern int option_font_min_size;
extern char *option_accept_language;
Index: desktop/options.c
===================================================================
--- desktop/options.c (revision 12271)
+++ desktop/options.c (working copy)
@@ -69,6 +69,8 @@
char *option_http_proxy_auth_user = 0;
/** Proxy authentication password */
char *option_http_proxy_auth_pass = 0;
+/** Inline image items in Gopher pages. Dangerous. */
+bool option_gopher_inline_images = false;
/** Default font size / 0.1pt. */
int option_font_size = 128;
/** Minimum font size. */
@@ -248,6 +250,7 @@
{ "http_proxy_auth", OPTION_INTEGER, &option_http_proxy_auth },
{ "http_proxy_auth_user", OPTION_STRING, &option_http_proxy_auth_user },
{ "http_proxy_auth_pass", OPTION_STRING, &option_http_proxy_auth_pass },
+ { "gopher_inline_images", OPTION_BOOL, &option_gopher_inline_images },
{ "font_size", OPTION_INTEGER, &option_font_size },
{ "font_min_size", OPTION_INTEGER, &option_font_min_size },
{ "font_sans", OPTION_STRING, &option_font_sans },
Index: content/content.c
===================================================================
--- content/content.c (revision 12271)
+++ content/content.c (working copy)
@@ -40,6 +40,7 @@
#include "desktop/options.h"
#include "render/html.h"
#include "render/textplain.h"
+#include "render/gopher.h"
#ifdef WITH_JPEG
#include "image/jpeg.h"
#endif
@@ -207,6 +208,7 @@
{"text/css", CONTENT_CSS},
{"text/html", CONTENT_HTML},
{"text/plain", CONTENT_TEXTPLAIN},
+ {"text/x-gopher-directory", CONTENT_GOPHER},
#ifdef WITH_MNG
{"video/mng", CONTENT_MNG},
{"video/x-mng", CONTENT_MNG},
@@ -263,6 +265,7 @@
#ifdef WITH_APPLE_IMAGE
"APPLE_IMAGE",
#endif
+ "GOPHER",
"OTHER",
"UNKNOWN"
};
@@ -403,6 +406,9 @@
{0, 0, apple_image_convert, 0, apple_image_destroy, 0, 0, 0,
apple_image_redraw, apple_image_redraw_tiled, 0, 0, apple_image_clone, false},
#endif
+ {gopher_create, 0, gopher_convert,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ true},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false}
};
#define HANDLER_MAP_COUNT (sizeof(handler_map) / sizeof(handler_map[0]))
Index: content/content_type.h
===================================================================
--- content/content_type.h (revision 12271)
+++ content/content_type.h (working copy)
@@ -77,6 +77,7 @@
#ifdef WITH_APPLE_IMAGE
CONTENT_APPLE_IMAGE,
#endif
+ CONTENT_GOPHER,
/* these must be the last two */
CONTENT_OTHER,
CONTENT_UNKNOWN /**< content-type not received yet */
Index: content/fetchers/curl.c
===================================================================
--- content/fetchers/curl.c (revision 12271)
+++ content/fetchers/curl.c (working copy)
@@ -44,6 +44,7 @@
#include "content/urldb.h"
#include "desktop/netsurf.h"
#include "desktop/options.h"
+#include "render/gopher.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/schedule.h"
@@ -72,6 +73,7 @@
bool abort; /**< Abort requested. */
bool stopped; /**< Download stopped on purpose. */
bool only_2xx; /**< Only HTTP 2xx responses acceptable. */
+ bool gopher_type; /**< Indicates the type of document for gopher: url */
char *url; /**< URL of this fetch. */
char *host; /**< The hostname of this fetch. */
struct curl_slist *headers; /**< List of request headers. */
@@ -111,6 +113,10 @@
bool only_2xx, const char *post_urlenc,
const struct fetch_multipart_data *post_multipart,
const char **headers);
+static void * fetch_curl_setup_gopher(struct fetch *parent_fetch, const char *url,
+ bool only_2xx, const char *post_urlenc,
+ const struct fetch_multipart_data *post_multipart,
+ const char **headers);
static bool fetch_curl_start(void *vfetch);
static bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch,
CURL *handle);
@@ -220,14 +226,19 @@
data = curl_version_info(CURLVERSION_NOW);
for (i = 0; data->protocols[i]; i++) {
+ fetcher_setup_fetch setup_hook;
/* Ignore non-http(s) protocols */
- if (strcmp(data->protocols[i], "http") != 0 &&
- strcmp(data->protocols[i], "https") != 0)
+ if (strcmp(data->protocols[i], "http") == 0 ||
+ strcmp(data->protocols[i], "https") == 0)
+ setup_hook = fetch_curl_setup;
+ else if (strcmp(data->protocols[i], "gopher") == 0)
+ setup_hook = fetch_curl_setup_gopher;
+ else
continue;
if (!fetch_add_fetcher(data->protocols[i],
fetch_curl_initialise,
- fetch_curl_setup,
+ setup_hook,
fetch_curl_start,
fetch_curl_abort,
fetch_curl_free,
@@ -339,6 +350,7 @@
fetch->abort = false;
fetch->stopped = false;
fetch->only_2xx = only_2xx;
+ fetch->gopher_type = 0;
fetch->url = strdup(url);
fetch->headers = 0;
fetch->host = host;
@@ -410,6 +422,41 @@
}
+void * fetch_curl_setup_gopher(struct fetch *parent_fetch, const char *url,
+ bool only_2xx, const char *post_urlenc,
+ const struct fetch_multipart_data *post_multipart,
+ const char **headers)
+{
+ struct curl_fetch_info *f;
+ const char *mime;
+ char type;
+ f = fetch_curl_setup(parent_fetch, url, only_2xx, post_urlenc,
+ post_multipart, headers);
+ if (url_gopher_type(url, &type) == URL_FUNC_OK && type)
+ f->gopher_type = type;
+ else
+ f->http_code = 404;
+
+ mime = gopher_type_to_mime(type);
+ /* TODO: add a fetch_mimetype_by_ext() or fetch_mimetype_sniff_data() */
+ /*
+ if (mime == NULL)
+ mime = "application/octet-stream";
+ */
+
+ if (mime) {
+ char s[80];
+ /* fprintf(stderr, "gopher mime is '%s'\n", mime); */
+ snprintf(s, sizeof s, "Content-type: %s\r\n", mime);
+ s[sizeof s - 1] = 0;
+ fetch_send_callback(FETCH_HEADER, f->fetch_handle, s, strlen(s),
+ FETCH_ERROR_NO_ERROR);
+ }
+
+ return f;
+}
+
+
/**
* Dispatch a single job
*/
@@ -771,6 +818,8 @@
LOG(("done %s", f->url));
if (abort_fetch == false && result == CURLE_OK) {
+ //if (f->gopher_type)
+ //fetch_curl_gopher_data(NULL, 0, 0, f);
/* fetch completed normally */
if (f->stopped ||
(!f->had_headers &&
@@ -978,6 +1027,22 @@
struct curl_fetch_info *f = _f;
CURLcode code;
+ /* gopher data receives special treatment */
+ if (f->gopher_type && gopher_need_generate(f->gopher_type)) {
+ /* type 3 items report an error */
+ if (!f->http_code) {
+ if (data[0] == '3') {
+ /* TODO: try to guess better from the string ?
+ * like "3 '/bcd' doesn't exist!"
+ * TODO: what about other file types ?
+ */
+ f->http_code = 404;
+ } else {
+ f->http_code = 200;
+ }
+ }
+ }
+
/* ensure we only have to get this information once */
if (!f->http_code)
{
Conflicted files
Removed files
11 years, 8 months
Re: Review: Content factory
by Chris Young
Hi John-Mark
I notice there are still a few CONTENT_SVGs hanging around in my
platform code, so it won't compile immediately. Unless there's an
easier way I guess I need to add some magic to check the MIME type of
the content and then do a reverse lookup to check if it is SVG? (I
handle SVGs differently in a few places so they end up on the
clipboard or export as DR2D (vector) instead of ILBM (bitmap))
Something like content_type_name(mimetype) which returns an arbitrary
type string (human-readable filetype) could be useful for doing
reverse lookups, or simple filetyping for file extensions etc on saves
for platforms that need that.
I see the RISC OS code has its own little MIME to RISC OS type code
that performs this function, but something that converts known NetSurf
MIME types to more complex types in the core would be useful for all
the front ends I think.
Chris
11 years, 9 months
Review: Content factory
by John-Mark Bell
Precis:
This changeset introduces a content factory with which content handlers may be dynamically registered.
Additionally, it inverts the inheritance model of contents such that each content handler becomes self-contained.
Added files
Index: render/html_internal.h
===================================================================
--- /dev/null 2009-04-16 19:17:07.000000000 +0100
+++ render/html_internal.h 2011-05-04 22:29:08.000000000 +0100
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2004 James Bursa <bursa(a)users.sourceforge.net>
+ *
+ * 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
+ * Content for text/html (private data).
+ */
+
+#ifndef _NETSURF_RENDER_HTML_INTERNAL_H_
+#define _NETSURF_RENDER_HTML_INTERNAL_H_
+
+#include "content/content_protected.h"
+#include "render/html.h"
+
+/** Data specific to CONTENT_HTML. */
+typedef struct html_content {
+ struct content base;
+
+ void *parser_binding;
+ xmlDoc *document;
+ binding_quirks_mode quirks; /**< Quirkyness of document */
+
+ char *encoding; /**< Encoding of source, 0 if unknown. */
+ binding_encoding_source encoding_source;
+ /**< Source of encoding information. */
+
+ char *base_url; /**< Base URL (may be a copy of content->url). */
+ char *base_target; /**< Base target */
+
+ struct box *layout; /**< Box tree, or 0. */
+ colour background_colour; /**< Document background colour. */
+ const struct font_functions *font_func;
+
+ /** Number of entries in stylesheet_content. */
+ unsigned int stylesheet_count;
+ /** Stylesheets. Each may be 0. */
+ struct html_stylesheet *stylesheets;
+ /**< Style selection context */
+ css_select_ctx *select_ctx;
+
+ /** Number of entries in object_list. */
+ unsigned int num_objects;
+ /** List of objects. */
+ struct content_html_object *object_list;
+ /** Forms, in reverse order to document. */
+ struct form *forms;
+ /** Hash table of imagemaps. */
+ struct imagemap **imagemaps;
+
+ /** Browser window containing this document, or 0 if not open. */
+ struct browser_window *bw;
+
+ /** Frameset information */
+ struct content_html_frames *frameset;
+
+ /** Inline frame information */
+ struct content_html_iframe *iframe;
+
+ /** Content of type CONTENT_HTML containing this, or 0 if not an object
+ * within a page. */
+ struct html_content *page;
+ /** Box containing this, or 0 if not an object. */
+ struct box *box;
+} html_content;
+
+
+bool html_fetch_object(html_content *c, const char *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);
+
+/* in render/html_redraw.c */
+bool html_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+
+/* in render/html_interaction.c */
+void html_mouse_track(struct content *c, struct browser_window *bw,
+ browser_mouse_state mouse, int x, int y);
+void html_mouse_action(struct content *c, struct browser_window *bw,
+ browser_mouse_state mouse, int x, int y);
+void html_overflow_scroll_callback(void *client_data,
+ struct scroll_msg_data *scroll_data);
+
+#endif
+
+
Index: image/image.c
===================================================================
--- /dev/null 2009-04-16 19:17:07.000000000 +0100
+++ image/image.c 2011-05-04 22:29:39.000000000 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2011 John-Mark Bell <jmb(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/>.
+ */
+
+#include "image/image.h"
+
+#include "image/bmp.h"
+#include "image/gif.h"
+#include "image/ico.h"
+#include "image/jpeg.h"
+#include "image/mng.h"
+#include "image/nssprite.h"
+#include "image/png.h"
+#include "image/rsvg.h"
+#include "image/svg.h"
+#include "image/webp.h"
+
+nserror image_init(void)
+{
+ nserror error;
+
+ error = nsbmp_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ error = nsgif_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ error = nsico_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ error = nsjpeg_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ /* Prefer libpng over libmng for pngs */
+ error = nsmng_init();
+ if (error != NSERROR_OK)
+ return error;
+ error = nspng_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ error = nssprite_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ /* Prefer rsvg over libsvgtiny for svgs */
+ error = svg_init();
+ if (error != NSERROR_OK)
+ return error;
+ error = nsrsvg_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ error = webp_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ return NSERROR_OK;
+}
+
+void image_fini(void)
+{
+ nsbmp_fini();
+ nsgif_fini();
+ nsico_fini();
+ nsjpeg_fini();
+ nsmng_fini();
+ nssprite_fini();
+ nspng_fini();
+ nsrsvg_fini();
+ svg_fini();
+ webp_fini();
+}
+
Index: image/image.h
===================================================================
--- /dev/null 2009-04-16 19:17:07.000000000 +0100
+++ image/image.h 2011-05-04 22:29:40.000000000 +0100
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011 John-Mark Bell <jmb(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
+ * Initialisation/finalisation of image handlers.
+ */
+
+#ifndef NETSURF_IMAGE_IMAGE_H_
+#define NETSURF_IMAGE_IMAGE_H_
+
+#include "utils/errors.h"
+
+nserror image_init(void);
+void image_fini(void);
+
+#endif
Index: content/content_factory.c
===================================================================
--- /dev/null 2009-04-16 19:17:07.000000000 +0100
+++ content/content_factory.c 2011-05-04 22:30:17.000000000 +0100
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2011 John-Mark Bell <jmb(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/>.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "content/content.h"
+#include "content/content_factory.h"
+#include "content/content_protected.h"
+#include "content/llcache.h"
+
+typedef struct content_handler_entry {
+ struct content_handler_entry *next;
+
+ lwc_string *mime_type;
+ const content_handler *handler;
+} content_handler_entry;
+
+static content_handler_entry *content_handlers;
+
+nserror content_factory_register_handler(lwc_string *mime_type,
+ const content_handler *handler)
+{
+ content_handler_entry *e;
+ bool match;
+
+ for (e = content_handlers; e != NULL; e = e->next) {
+ if (lwc_string_caseless_isequal(mime_type, e->mime_type,
+ &match) == lwc_error_ok && match)
+ break;
+ }
+
+ if (e == NULL) {
+ e = malloc(sizeof(content_handler_entry));
+ if (e == NULL)
+ return NSERROR_NOMEM;
+
+ e->next = content_handlers;
+ content_handlers = e;
+
+ e->mime_type = lwc_string_ref(mime_type);
+ }
+
+ e->handler = handler;
+
+ return NSERROR_OK;
+}
+
+/**
+ * Find a handler for a MIME type.
+ */
+
+static const content_handler *content_lookup(lwc_string *mime_type)
+{
+ content_handler_entry *e;
+ bool match;
+
+ for (e = content_handlers; e != NULL; e = e->next) {
+ if (lwc_string_caseless_isequal(mime_type, e->mime_type,
+ &match) == lwc_error_ok && match)
+ break;
+ }
+
+ if (e != NULL)
+ return e->handler;
+
+ return NULL;
+}
+
+content_type content_factory_type_from_mime_type(const char *mime_type)
+{
+ const content_handler *handler;
+ lwc_string *imime_type;
+ lwc_error lerror;
+ content_type type;
+
+ lerror = lwc_intern_string(mime_type, strlen(mime_type), &imime_type);
+ if (lerror != lwc_error_ok)
+ return CONTENT_NONE;
+
+ handler = content_lookup(imime_type);
+ if (handler == NULL) {
+ lwc_string_unref(imime_type);
+ return CONTENT_NONE;
+ }
+
+ type = handler->type(imime_type);
+
+ lwc_string_unref(imime_type);
+
+ return type;
+}
+
+struct content *content_factory_create_content(llcache_handle *llcache,
+ const char *fallback_charset, bool quirks)
+{
+ struct content *c;
+ const char *content_type_header;
+ const content_handler *handler;
+ char *mime_type;
+ http_parameter *params;
+ lwc_string *imime_type;
+ lwc_error lerr;
+ nserror error;
+
+ content_type_header =
+ llcache_handle_get_header(llcache, "Content-Type");
+ if (content_type_header == NULL)
+ content_type_header = "text/plain";
+
+ error = http_parse_content_type(content_type_header, &mime_type,
+ ¶ms);
+ if (error != NSERROR_OK)
+ return NULL;
+
+ lerr = lwc_intern_string(mime_type, strlen(mime_type), &imime_type);
+ if (lerr != lwc_error_ok) {
+ http_parameter_list_destroy(params);
+ free(mime_type);
+ return NULL;
+ }
+
+ free(mime_type);
+
+ handler = content_lookup(imime_type);
+ if (handler == NULL) {
+ lwc_string_unref(imime_type);
+ http_parameter_list_destroy(params);
+ return NULL;
+ }
+
+ assert(handler->create != NULL);
+
+ error = handler->create(handler, imime_type, params, llcache,
+ fallback_charset, quirks, &c);
+ if (error != NSERROR_OK) {
+ lwc_string_unref(imime_type);
+ http_parameter_list_destroy(params);
+ return NULL;
+ }
+
+ lwc_string_unref(imime_type);
+ http_parameter_list_destroy(params);
+
+ return c;
+}
+
Index: content/content_factory.h
===================================================================
--- /dev/null 2009-04-16 19:17:07.000000000 +0100
+++ content/content_factory.h 2011-05-04 22:30:17.000000000 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2011 John-Mark Bell <jmb(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/>.
+ */
+
+#ifndef NETSURF_CONTENT_CONTENT_FACTORY_H_
+#define NETSURF_CONTENT_CONTENT_FACTORY_H_
+
+#include <stdbool.h>
+
+#include <libwapcaplet/libwapcaplet.h>
+
+#include "content/content_type.h"
+#include "utils/errors.h"
+
+struct content;
+struct llcache_handle;
+
+typedef struct content_handler content_handler;
+
+nserror content_factory_register_handler(lwc_string *mime_type,
+ const content_handler *handler);
+
+struct content *content_factory_create_content(struct llcache_handle *llcache,
+ const char *fallback_charset, bool quirks);
+
+content_type content_factory_type_from_mime_type(const char *mime_type);
+
+#endif
Changed files
Makefile.sources | 9
amiga/Makefile.target | 4
amiga/filetype.c | 48 --
amiga/gui.c | 20 -
amiga/icon.c | 149 +++++++-
amiga/icon.h | 20 -
amiga/menu.c | 9
amiga/plugin.c | 191 +++++++---
amiga/plugin.h | 18
amiga/save_complete.c | 4
atari/gui.c | 2
beos/beos_save_complete.cpp | 2
cocoa/NetsurfApp.m | 5
cocoa/apple_image.h | 30 -
cocoa/apple_image.m | 142 +++++++
cocoa/gui.m | 5
cocoa/save.m | 2
content/content.c | 613 +++++----------------------------
content/content.h | 10
content/content_protected.h | 158 ++------
content/content_type.h | 63 ---
content/hlcache.c | 39 --
content/hlcache.h | 6
css/css.c | 214 +++++++++--
css/css.h | 14
css/select.c | 46 +-
css/select.h | 14
desktop/browser.c | 2
desktop/netsurf.c | 29 +
desktop/save_complete.c | 39 +-
desktop/save_complete.h | 5
desktop/searchweb.c | 13
desktop/textinput.c | 2
desktop/tree.c | 3
desktop/tree_url_node.c | 37 --
framebuffer/save.c | 2
framebuffer/tree.c | 30 -
gtk/save.c | 2
gtk/scaffolding.c | 10
gtk/treeview.c | 30 -
image/bmp.c | 225 ++++++++++--
image/bmp.h | 26 -
image/gif.c | 322 ++++++++++++-----
image/gif.h | 24 -
image/ico.c | 222 +++++++++---
image/ico.h | 27 -
image/jpeg.c | 142 +++++++
image/jpeg.h | 23 -
image/mng.c | 430 +++++++++++++++++------
image/mng.h | 29 -
image/nssprite.c | 149 +++++++-
image/nssprite.h | 16
image/png.c | 287 +++++++++++----
image/png.h | 34 -
image/rsvg.c | 189 +++++++++-
image/rsvg.h | 28 -
image/svg.c | 188 ++++++++--
image/svg.h | 29 -
image/webp.c | 136 +++++++
image/webp.h | 18
monkey/utils.c | 2
render/box.c | 16
render/box.h | 6
render/box_construct.c | 189 +++-------
render/box_normalise.c | 73 ++-
render/form.c | 1
render/html.c | 812 +++++++++++++++++++++++---------------------
render/html.h | 103 -----
render/html_interaction.c | 2
render/html_redraw.c | 9
render/imagemap.c | 53 +-
render/imagemap.h | 8
render/layout.c | 45 +-
render/layout.h | 5
render/textplain.c | 325 ++++++++++++-----
render/textplain.h | 32 -
riscos/artworks.c | 220 +++++++++--
riscos/artworks.h | 26 -
riscos/draw.c | 156 +++++++-
riscos/draw.h | 20 -
riscos/filetype.c | 92 ++--
riscos/gui.c | 11
riscos/gui.h | 2
riscos/gui/url_bar.c | 6
riscos/plugin.c | 442 +++++++++++++----------
riscos/plugin.h | 20 -
riscos/print.c | 15
riscos/save.c | 121 ++----
riscos/sprite.c | 148 +++++++-
riscos/sprite.h | 21 -
riscos/treeview.c | 30 -
riscos/window.c | 56 ---
utils/errors.h | 3
windows/gui.c | 2
94 files changed, 4614 insertions(+), 3043 deletions(-)
Index: render/box_normalise.c
===================================================================
--- render/box_normalise.c (revision 12276)
+++ render/box_normalise.c (working copy)
@@ -28,6 +28,7 @@
#include "css/css.h"
#include "css/select.h"
#include "render/box.h"
+#include "render/html_internal.h"
#include "render/table.h"
#include "desktop/gui.h"
#include "utils/log.h"
@@ -61,19 +62,19 @@
};
-static bool box_normalise_table(struct box *table, struct content *c);
+static bool box_normalise_table(struct box *table, html_content *c);
static bool box_normalise_table_spans(struct box *table,
- struct span_info *spans, struct content *c);
+ struct span_info *spans, html_content *c);
static bool box_normalise_table_row_group(struct box *row_group,
struct columns *col_info,
- struct content *c);
+ html_content *c);
static bool box_normalise_table_row(struct box *row,
struct columns *col_info,
- struct content *c);
+ html_content *c);
static bool calculate_table_row(struct columns *col_info,
unsigned int col_span, unsigned int row_span,
unsigned int *start_column);
-static bool box_normalise_inline_container(struct box *cont, struct content *c);
+static bool box_normalise_inline_container(struct box *cont, html_content *c);
/**
* Ensure the box tree is correctly nested by adding and removing nodes.
@@ -96,12 +97,13 @@
* \endcode
*/
-bool box_normalise_block(struct box *block, struct content *c)
+bool box_normalise_block(struct box *block, html_content *c)
{
struct box *child;
struct box *next_child;
struct box *table;
css_computed_style *style;
+ nscss_select_ctx ctx;
assert(block != NULL);
@@ -152,7 +154,11 @@
/* insert implied table */
assert(block->style != NULL);
- style = nscss_get_blank_style(c, block->style,
+ ctx.ctx = c->select_ctx;
+ ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL);
+ ctx.base_url = c->base_url;
+
+ style = nscss_get_blank_style(&ctx, block->style,
box_style_alloc, NULL);
if (style == NULL)
return false;
@@ -203,13 +209,14 @@
}
-bool box_normalise_table(struct box *table, struct content * c)
+bool box_normalise_table(struct box *table, html_content * c)
{
struct box *child;
struct box *next_child;
struct box *row_group;
css_computed_style *style;
struct columns col_info;
+ nscss_select_ctx ctx;
assert(table != NULL);
assert(table->type == BOX_TABLE);
@@ -248,7 +255,11 @@
/* insert implied table row group */
assert(table->style != NULL);
- style = nscss_get_blank_style(c, table->style,
+ ctx.ctx = c->select_ctx;
+ ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL);
+ ctx.base_url = c->base_url;
+
+ style = nscss_get_blank_style(&ctx, table->style,
box_style_alloc, NULL);
if (style == NULL) {
free(col_info.spans);
@@ -330,7 +341,11 @@
assert(table->style != NULL);
- style = nscss_get_blank_style(c, table->style,
+ ctx.ctx = c->select_ctx;
+ ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL);
+ ctx.base_url = c->base_url;
+
+ style = nscss_get_blank_style(&ctx, table->style,
box_style_alloc, NULL);
if (style == NULL) {
free(col_info.spans);
@@ -346,7 +361,7 @@
}
row_group->type = BOX_TABLE_ROW_GROUP;
- style = nscss_get_blank_style(c, row_group->style,
+ style = nscss_get_blank_style(&ctx, row_group->style,
box_style_alloc, NULL);
if (style == NULL) {
box_free(row_group);
@@ -402,13 +417,14 @@
*/
bool box_normalise_table_spans(struct box *table, struct span_info *spans,
- struct content *c)
+ html_content *c)
{
struct box *table_row_group;
struct box *table_row;
struct box *table_cell;
unsigned int rows_left = table->rows;
unsigned int col;
+ nscss_select_ctx ctx;
/* Clear span data */
memset(spans, 0, table->columns * sizeof(struct span_info));
@@ -459,7 +475,12 @@
col++;
}
- style = nscss_get_blank_style(c,
+ ctx.ctx = c->select_ctx;
+ ctx.quirks = (c->quirks ==
+ BINDING_QUIRKS_MODE_FULL);
+ ctx.base_url = c->base_url;
+
+ style = nscss_get_blank_style(&ctx,
table_row->style,
box_style_alloc, NULL);
if (style == NULL)
@@ -531,12 +552,13 @@
bool box_normalise_table_row_group(struct box *row_group,
struct columns *col_info,
- struct content * c)
+ html_content * c)
{
struct box *child;
struct box *next_child;
struct box *row;
css_computed_style *style;
+ nscss_select_ctx ctx;
assert(row_group != 0);
assert(row_group->type == BOX_TABLE_ROW_GROUP);
@@ -563,7 +585,11 @@
/* insert implied table row */
assert(row_group->style != NULL);
- style = nscss_get_blank_style(c, row_group->style,
+ ctx.ctx = c->select_ctx;
+ ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL);
+ ctx.base_url = c->base_url;
+
+ style = nscss_get_blank_style(&ctx, row_group->style,
box_style_alloc, NULL);
if (style == NULL)
return false;
@@ -633,7 +659,11 @@
assert(row_group->style != NULL);
- style = nscss_get_blank_style(c, row_group->style,
+ ctx.ctx = c->select_ctx;
+ ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL);
+ ctx.base_url = c->base_url;
+
+ style = nscss_get_blank_style(&ctx, row_group->style,
box_style_alloc, NULL);
if (style == NULL) {
return false;
@@ -664,13 +694,14 @@
bool box_normalise_table_row(struct box *row,
struct columns *col_info,
- struct content * c)
+ html_content * c)
{
struct box *child;
struct box *next_child;
struct box *cell = NULL;
css_computed_style *style;
unsigned int i;
+ nscss_select_ctx ctx;
assert(row != NULL);
assert(row->type == BOX_TABLE_ROW);
@@ -697,7 +728,11 @@
/* insert implied table cell */
assert(row->style != NULL);
- style = nscss_get_blank_style(c, row->style,
+ ctx.ctx = c->select_ctx;
+ ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL);
+ ctx.base_url = c->base_url;
+
+ style = nscss_get_blank_style(&ctx, row->style,
box_style_alloc, NULL);
if (style == NULL)
return false;
@@ -856,7 +891,7 @@
}
-bool box_normalise_inline_container(struct box *cont, struct content * c)
+bool box_normalise_inline_container(struct box *cont, html_content * c)
{
struct box *child;
struct box *next_child;
Index: render/html_interaction.c
===================================================================
--- render/html_interaction.c (revision 12276)
+++ render/html_interaction.c (working copy)
@@ -37,7 +37,7 @@
#include "render/box.h"
#include "render/font.h"
#include "render/form.h"
-#include "render/html.h"
+#include "render/html_internal.h"
#include "render/imagemap.h"
#include "utils/messages.h"
#include "utils/utils.h"
Index: render/form.c
===================================================================
--- render/form.c (revision 12276)
+++ render/form.c (working copy)
@@ -1466,7 +1466,6 @@
url_func_result res;
assert(form != NULL);
- assert(content_get_type(h) == CONTENT_HTML);
if (form_successful_controls(form, submit_button, &success) == false) {
warn_user("NoMemory", 0);
Index: render/html.c
===================================================================
--- render/html.c (revision 12276)
+++ render/html.c (working copy)
@@ -36,10 +36,9 @@
#include "desktop/options.h"
#include "image/bitmap.h"
#include "render/box.h"
-#include "render/favicon.h"
#include "render/font.h"
#include "render/form.h"
-#include "render/html.h"
+#include "render/html_internal.h"
#include "render/imagemap.h"
#include "render/layout.h"
#include "utils/http.h"
@@ -58,13 +57,32 @@
#define ALWAYS_DUMP_FRAMESET 0
#define ALWAYS_DUMP_BOX 0
-static void html_finish_conversion(struct content *c);
+static nserror html_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror html_create_html_data(html_content *c,
+ const http_parameter *params);
+static bool html_process_data(struct content *c, const char *data,
+ unsigned int size);
+static bool html_convert(struct content *c);
+static void html_reformat(struct content *c, int width, int height);
+static void html_destroy(struct content *c);
+static void html_stop(struct content *c);
+static void html_open(struct content *c, struct browser_window *bw,
+ struct content *page, struct box *box,
+ struct object_params *params);
+static void html_close(struct content *c);
+static nserror html_clone(const struct content *old, struct content **newc);
+static content_type html_content_type(lwc_string *mime_type);
+
+static void html_finish_conversion(html_content *c);
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,
+static bool html_meta_refresh(html_content *c, xmlNode *head);
+static bool html_head(html_content *c, xmlNode *head);
+static bool html_find_stylesheets(html_content *c, xmlNode *html);
+static bool html_process_style_element(html_content *c, unsigned int *index,
xmlNode *style);
static void html_inline_style_done(struct content_css_data *css, void *pw);
static bool html_replace_object(struct content_html_object *object,
@@ -73,10 +91,8 @@
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,
+static void html_object_failed(struct box *box, html_content *content,
bool background);
-static bool html_object_type_permitted(const content_type type,
- const content_type *permitted_types);
static void html_object_refresh(void *p);
static void html_destroy_frameset(struct content_html_frames *frameset);
static void html_destroy_iframe(struct content_html_iframe *iframe);
@@ -85,6 +101,25 @@
unsigned int depth);
#endif
+static const content_handler html_content_handler = {
+ html_create,
+ html_process_data,
+ html_convert,
+ html_reformat,
+ html_destroy,
+ html_stop,
+ html_mouse_track,
+ html_mouse_action,
+ html_redraw,
+ NULL,
+ html_open,
+ html_close,
+ html_clone,
+ NULL,
+ html_content_type,
+ true
+};
+
static const char empty_document[] =
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\""
" \"http://www.w3.org/TR/html4/strict.dtd\">"
@@ -98,6 +133,52 @@
"</body>"
"</html>";
+static const char *html_types[] = {
+ "application/xhtml+xml",
+ "text/html"
+};
+
+static lwc_string *html_mime_types[NOF_ELEMENTS(html_types)];
+
+nserror html_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(html_mime_types); i++) {
+ lerror = lwc_intern_string(html_types[i],
+ strlen(html_types[i]),
+ &html_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(html_mime_types[i],
+ &html_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ html_fini();
+
+ return error;
+}
+
+void html_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(html_mime_types); i++) {
+ if (html_mime_types[i] != NULL)
+ lwc_string_unref(html_mime_types[i]);
+ }
+}
+
/**
* Create a CONTENT_HTML.
*
@@ -105,72 +186,101 @@
* created.
*/
-bool html_create(struct content *c, const http_parameter *params)
+nserror html_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
{
- struct content_html_data *html = &c->data.html;
+ html_content *html;
+ nserror error;
+
+ html = talloc_zero(0, html_content);
+ if (html == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&html->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(html);
+ return error;
+ }
+
+ error = html_create_html_data(html, params);
+ if (error != NSERROR_OK) {
+ talloc_free(html);
+ return error;
+ }
+
+ *c = (struct content *) html;
+
+ return NSERROR_OK;
+}
+
+nserror html_create_html_data(html_content *c, const http_parameter *params)
+{
const char *charset;
union content_msg_data msg_data;
binding_error error;
nserror nerror;
- html->parser_binding = NULL;
- html->document = NULL;
- html->quirks = BINDING_QUIRKS_MODE_NONE;
- html->encoding = NULL;
- html->base_url = (char *) content__get_url(c);
- html->base_target = NULL;
- html->layout = NULL;
- html->background_colour = NS_TRANSPARENT;
- html->stylesheet_count = 0;
- html->stylesheets = NULL;
- html->select_ctx = NULL;
- html->num_objects = 0;
- html->object_list = NULL;
- html->forms = NULL;
- html->imagemaps = NULL;
- html->bw = NULL;
- html->frameset = NULL;
- html->iframe = NULL;
- html->page = NULL;
- html->box = NULL;
- html->font_func = &nsfont;
+ c->parser_binding = NULL;
+ c->document = NULL;
+ c->quirks = BINDING_QUIRKS_MODE_NONE;
+ c->encoding = NULL;
+ c->base_url = (char *) content__get_url(&c->base);
+ c->base_target = NULL;
+ c->layout = NULL;
+ c->background_colour = NS_TRANSPARENT;
+ c->stylesheet_count = 0;
+ c->stylesheets = NULL;
+ c->select_ctx = NULL;
+ c->num_objects = 0;
+ c->object_list = NULL;
+ c->forms = NULL;
+ c->imagemaps = NULL;
+ c->bw = NULL;
+ c->frameset = NULL;
+ c->iframe = NULL;
+ c->page = NULL;
+ c->box = NULL;
+ c->font_func = &nsfont;
nerror = http_parameter_list_find_item(params, "charset", &charset);
if (nerror == NSERROR_OK) {
- html->encoding = talloc_strdup(c, charset);
- if (!html->encoding) {
+ c->encoding = talloc_strdup(c, charset);
+ if (!c->encoding) {
error = BINDING_NOMEM;
goto error;
}
- html->encoding_source = ENCODING_SOURCE_HEADER;
+ c->encoding_source = ENCODING_SOURCE_HEADER;
}
/* Create the parser binding */
- error = binding_create_tree(c, html->encoding, &html->parser_binding);
- if (error == BINDING_BADENCODING && html->encoding != NULL) {
+ error = binding_create_tree(c, c->encoding, &c->parser_binding);
+ if (error == BINDING_BADENCODING && c->encoding != NULL) {
/* Ok, we don't support the declared encoding. Bailing out
* isn't exactly user-friendly, so fall back to autodetect */
- talloc_free(html->encoding);
- html->encoding = NULL;
+ talloc_free(c->encoding);
+ c->encoding = NULL;
- error = binding_create_tree(c, html->encoding,
- &html->parser_binding);
+ error = binding_create_tree(c, c->encoding, &c->parser_binding);
}
if (error != BINDING_OK)
goto error;
- return true;
+ return NSERROR_OK;
error:
if (error == BINDING_BADENCODING) {
- LOG(("Bad encoding: %s", html->encoding ? html->encoding : ""));
+ LOG(("Bad encoding: %s", c->encoding ? c->encoding : ""));
msg_data.error = messages_get("ParsingFail");
} else
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+
+ return NSERROR_NOMEM;
}
@@ -182,12 +292,13 @@
bool html_process_data(struct content *c, const char *data, unsigned int size)
{
+ html_content *html = (html_content *) c;
unsigned long x;
binding_error err;
const char *encoding;
for (x = 0; x + CHUNK <= size; x += CHUNK) {
- err = binding_parse_chunk(c->data.html.parser_binding,
+ err = binding_parse_chunk(html->parser_binding,
(const uint8_t *) data + x, CHUNK);
if (err == BINDING_ENCODINGCHANGE) {
goto encoding_change;
@@ -203,7 +314,7 @@
gui_multitask();
}
- err = binding_parse_chunk(c->data.html.parser_binding,
+ err = binding_parse_chunk(html->parser_binding,
(const uint8_t *) data + x, (size - x));
if (err == BINDING_ENCODINGCHANGE) {
goto encoding_change;
@@ -222,14 +333,14 @@
/* Retrieve new encoding */
encoding = binding_get_encoding(
- c->data.html.parser_binding,
- &c->data.html.encoding_source);
+ html->parser_binding,
+ &html->encoding_source);
- if (c->data.html.encoding != NULL)
- talloc_free(c->data.html.encoding);
+ if (html->encoding != NULL)
+ talloc_free(html->encoding);
- c->data.html.encoding = talloc_strdup(c, encoding);
- if (c->data.html.encoding == NULL) {
+ html->encoding = talloc_strdup(c, encoding);
+ if (html->encoding == NULL) {
union content_msg_data msg_data;
msg_data.error = messages_get("NoMemory");
@@ -238,17 +349,16 @@
}
/* Destroy binding */
- binding_destroy_tree(c->data.html.parser_binding);
+ binding_destroy_tree(html->parser_binding);
/* Create new binding, using the new encoding */
- err = binding_create_tree(c, c->data.html.encoding,
- &c->data.html.parser_binding);
+ err = binding_create_tree(html, html->encoding, &html->parser_binding);
if (err == BINDING_BADENCODING) {
/* Ok, we don't support the declared encoding. Bailing out
* isn't exactly user-friendly, so fall back to Windows-1252 */
- talloc_free(c->data.html.encoding);
- c->data.html.encoding = talloc_strdup(c, "Windows-1252");
- if (c->data.html.encoding == NULL) {
+ talloc_free(html->encoding);
+ html->encoding = talloc_strdup(c, "Windows-1252");
+ if (html->encoding == NULL) {
union content_msg_data msg_data;
msg_data.error = messages_get("NoMemory");
@@ -256,16 +366,16 @@
return false;
}
- err = binding_create_tree(c, c->data.html.encoding,
- &c->data.html.parser_binding);
+ err = binding_create_tree(html, html->encoding,
+ &html->parser_binding);
}
if (err != BINDING_OK) {
union content_msg_data msg_data;
if (err == BINDING_BADENCODING) {
- LOG(("Bad encoding: %s", c->data.html.encoding
- ? c->data.html.encoding : ""));
+ LOG(("Bad encoding: %s", html->encoding
+ ? html->encoding : ""));
msg_data.error = messages_get("ParsingFail");
} else
msg_data.error = messages_get("NoMemory");
@@ -293,7 +403,6 @@
*
* - parsing to an XML tree is completed
* - stylesheets are fetched
- * - favicon is retrieved
* - the XML tree is converted to a box tree and object fetches are started
*
* On exit, the content status will be either CONTENT_STATUS_DONE if the
@@ -303,6 +412,7 @@
bool html_convert(struct content *c)
{
+ html_content *htmlc = (html_content *) c;
binding_error err;
xmlNode *html, *head;
union content_msg_data msg_data;
@@ -313,23 +423,22 @@
content__get_source_data(c, &size);
if (size == 0) {
/* Destroy current binding */
- binding_destroy_tree(c->data.html.parser_binding);
+ binding_destroy_tree(htmlc->parser_binding);
/* Also, any existing encoding information,
* as it's not guaranteed to match the error page.
*/
- talloc_free(c->data.html.encoding);
- c->data.html.encoding = NULL;
+ talloc_free(htmlc->encoding);
+ htmlc->encoding = NULL;
/* Create new binding, using default charset */
- err = binding_create_tree(c, NULL,
- &c->data.html.parser_binding);
+ err = binding_create_tree(c, NULL, &htmlc->parser_binding);
if (err != BINDING_OK) {
union content_msg_data msg_data;
if (err == BINDING_BADENCODING) {
- LOG(("Bad encoding: %s", c->data.html.encoding
- ? c->data.html.encoding : ""));
+ LOG(("Bad encoding: %s", htmlc->encoding
+ ? htmlc->encoding : ""));
msg_data.error = messages_get("ParsingFail");
} else
msg_data.error = messages_get("NoMemory");
@@ -343,7 +452,7 @@
return false;
}
- err = binding_parse_completed(c->data.html.parser_binding);
+ err = binding_parse_completed(htmlc->parser_binding);
if (err != BINDING_OK) {
union content_msg_data msg_data;
@@ -353,25 +462,24 @@
return false;
}
- c->data.html.document =
- binding_get_document(c->data.html.parser_binding,
- &c->data.html.quirks);
- /*xmlDebugDumpDocument(stderr, c->data.html.document);*/
+ htmlc->document =binding_get_document(htmlc->parser_binding,
+ &htmlc->quirks);
+ /*xmlDebugDumpDocument(stderr, htmlc->document);*/
- if (!c->data.html.document) {
+ if (!htmlc->document) {
LOG(("Parsing failed"));
msg_data.error = messages_get("ParsingFail");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
- if (c->data.html.encoding == NULL) {
+ if (htmlc->encoding == NULL) {
const char *encoding = binding_get_encoding(
- c->data.html.parser_binding,
- &c->data.html.encoding_source);
+ htmlc->parser_binding,
+ &htmlc->encoding_source);
- c->data.html.encoding = talloc_strdup(c, encoding);
- if (c->data.html.encoding == NULL) {
+ htmlc->encoding = talloc_strdup(c, encoding);
+ if (htmlc->encoding == NULL) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
@@ -379,7 +487,7 @@
}
/* locate html and head elements */
- html = xmlDocGetRootElement(c->data.html.document);
+ html = xmlDocGetRootElement(htmlc->document);
if (html == 0 || strcmp((const char *) html->name, "html") != 0) {
LOG(("html element not found"));
msg_data.error = messages_get("ParsingFail");
@@ -396,20 +504,20 @@
}
if (head) {
- if (!html_head(c, head)) {
+ if (!html_head(htmlc, head)) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
/* handle meta refresh */
- if (!html_meta_refresh(c, head))
+ if (!html_meta_refresh(htmlc, head))
return false;
}
/* Retrieve forms from parser */
- c->data.html.forms = binding_get_forms(c->data.html.parser_binding);
- for (f = c->data.html.forms; f != NULL; f = f->prev) {
+ htmlc->forms = binding_get_forms(htmlc->parser_binding);
+ for (f = htmlc->forms; f != NULL; f = f->prev) {
char *action;
url_func_result res;
@@ -417,10 +525,9 @@
if (f->action == NULL || f->action[0] == '\0') {
/* HTML5 4.10.22.3 step 11 */
res = url_join(content__get_url(c),
- c->data.html.base_url, &action);
+ htmlc->base_url, &action);
} else {
- res = url_join(f->action,
- c->data.html.base_url, &action);
+ res = url_join(f->action, htmlc->base_url, &action);
}
if (res != URL_FUNC_OK) {
@@ -434,7 +541,7 @@
/* Ensure each form has a document encoding */
if (f->document_charset == NULL) {
- f->document_charset = strdup(c->data.html.encoding);
+ f->document_charset = strdup(htmlc->encoding);
if (f->document_charset == NULL) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR,
@@ -445,7 +552,7 @@
}
/* get stylesheets */
- if (!html_find_stylesheets(c, html))
+ if (!html_find_stylesheets(htmlc, html))
return false;
return true;
@@ -456,37 +563,36 @@
*
* \param c Content to convert
*/
-void html_finish_conversion(struct content *c)
+void html_finish_conversion(html_content *c)
{
union content_msg_data msg_data;
xmlNode *html;
uint32_t i;
css_error error;
- html = xmlDocGetRootElement(c->data.html.document);
+ html = xmlDocGetRootElement(c->document);
assert(html != NULL);
/* check that the base stylesheet loaded; layout fails without it */
- if (c->data.html.stylesheets[STYLESHEET_BASE].data.external == NULL) {
+ if (c->stylesheets[STYLESHEET_BASE].data.external == NULL) {
msg_data.error = "Base stylesheet failed to load";
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- c->status = CONTENT_STATUS_ERROR;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ c->base.status = CONTENT_STATUS_ERROR;
return;
}
/* Create selection context */
- error = css_select_ctx_create(ns_realloc, c, &c->data.html.select_ctx);
+ error = css_select_ctx_create(ns_realloc, c, &c->select_ctx);
if (error != CSS_OK) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- c->status = CONTENT_MSG_ERROR;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ c->base.status = CONTENT_MSG_ERROR;
return;
}
/* Add sheets to it */
- for (i = STYLESHEET_BASE; i != c->data.html.stylesheet_count; i++) {
- const struct html_stylesheet *hsheet =
- &c->data.html.stylesheets[i];
+ for (i = STYLESHEET_BASE; i != c->stylesheet_count; i++) {
+ const struct html_stylesheet *hsheet = &c->stylesheets[i];
css_stylesheet *sheet;
css_origin origin = CSS_ORIGIN_AUTHOR;
@@ -495,10 +601,7 @@
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;
+ sheet = nscss_get_stylesheet(hsheet->data.external);
} else if (hsheet->type == HTML_STYLESHEET_INTERNAL) {
sheet = hsheet->data.internal->sheet;
} else {
@@ -507,59 +610,54 @@
if (sheet != NULL) {
error = css_select_ctx_append_sheet(
- c->data.html.select_ctx, sheet,
+ c->select_ctx, sheet,
origin, CSS_MEDIA_SCREEN);
if (error != CSS_OK) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR,
+ content_broadcast(&c->base, CONTENT_MSG_ERROR,
msg_data);
- c->status = CONTENT_STATUS_ERROR;
+ c->base.status = CONTENT_STATUS_ERROR;
return;
}
}
}
-#ifdef FAVICONS_ARE_NOT_A_PERFORMANCE_HOLE
- /* get icon */
- favicon_get_icon(c, html);
-#endif
-
/* convert xml tree to box tree */
LOG(("XML to box"));
- content_set_status(c, messages_get("Processing"));
- content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
+ content_set_status(&c->base, messages_get("Processing"));
+ content_broadcast(&c->base, CONTENT_MSG_STATUS, msg_data);
if (!xml_to_box(html, c)) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- c->status = CONTENT_STATUS_ERROR;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ c->base.status = CONTENT_STATUS_ERROR;
return;
}
#if ALWAYS_DUMP_BOX
- box_dump(stderr, c->data.html.layout->children, 0);
+ box_dump(stderr, c->layout->children, 0);
#endif
#if ALWAYS_DUMP_FRAMESET
- if (c->data.html.frameset)
- html_dump_frameset(c->data.html.frameset, 0);
+ if (c->frameset)
+ html_dump_frameset(c->frameset, 0);
#endif
/* extract image maps - can't do this sensibly in xml_to_box */
if (!imagemap_extract(html, c)) {
LOG(("imagemap extraction failed"));
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- c->status = CONTENT_STATUS_ERROR;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ c->base.status = CONTENT_STATUS_ERROR;
return;
}
/*imagemap_dump(c);*/
/* Destroy the parser binding */
- binding_destroy_tree(c->data.html.parser_binding);
- c->data.html.parser_binding = NULL;
+ binding_destroy_tree(c->parser_binding);
+ c->parser_binding = NULL;
- content_set_ready(c);
+ content_set_ready(&c->base);
- if (c->active == 0)
- content_set_done(c);
+ if (c->base.active == 0)
+ content_set_done(&c->base);
html_set_status(c, "");
}
@@ -575,7 +673,7 @@
* The title and base href are extracted if present.
*/
-bool html_head(struct content *c, xmlNode *head)
+bool html_head(html_content *c, xmlNode *head)
{
xmlNode *node;
xmlChar *s;
@@ -584,7 +682,7 @@
if (node->type != XML_ELEMENT_NODE)
continue;
- if (c->title == NULL && strcmp((const char *) node->name,
+ if (c->base.title == NULL && strcmp((const char *) node->name,
"title") == 0) {
xmlChar *title = xmlNodeGetContent(node);
char *title2;
@@ -594,7 +692,7 @@
xmlFree(title);
if (!title2)
return false;
- if (content__set_title(c, title2) == false) {
+ if (content__set_title(&c->base, title2) == false) {
free(title2);
return false;
}
@@ -609,8 +707,7 @@
url_func_result res;
res = url_normalize(href, &url);
if (res == URL_FUNC_OK) {
- c->data.html.base_url =
- talloc_strdup(c, url);
+ c->base_url = talloc_strdup(c, url);
free(url);
}
xmlFree(href);
@@ -626,10 +723,9 @@
"_self")) ||
('a' <= s[0] && s[0] <= 'z') ||
('A' <= s[0] && s[0] <= 'Z')) { /* [6.16] */
- c->data.html.base_target =
- talloc_strdup(c,
+ c->base_target = talloc_strdup(c,
(const char *) s);
- if (!c->data.html.base_target) {
+ if (!c->base_target) {
xmlFree(s);
return false;
}
@@ -652,7 +748,7 @@
* \return true on success, false otherwise (error reported)
*/
-bool html_meta_refresh(struct content *c, xmlNode *head)
+bool html_meta_refresh(html_content *c, xmlNode *head)
{
xmlNode *n;
xmlChar *equiv, *content;
@@ -669,7 +765,7 @@
if (!html_meta_refresh(c, n)) {
/* Some error occurred */
return false;
- } else if (c->refresh) {
+ } else if (c->base.refresh) {
/* Meta refresh found - stop */
return true;
}
@@ -739,15 +835,17 @@
/* Just delay specified, so refresh current page */
xmlFree(content);
- c->refresh = talloc_strdup(c, content__get_url(c));
- if (!c->refresh) {
+ c->base.refresh = talloc_strdup(c,
+ content__get_url(&c->base));
+ if (!c->base.refresh) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c,
+ content_broadcast(&c->base,
CONTENT_MSG_ERROR, msg_data);
return false;
}
- content_broadcast(c, CONTENT_MSG_REFRESH, msg_data);
+ content_broadcast(&c->base, CONTENT_MSG_REFRESH,
+ msg_data);
break;
}
@@ -810,30 +908,32 @@
if (url < end)
*url = '\0';
- res = url_join(refresh, c->data.html.base_url, &refresh);
+ res = url_join(refresh, c->base_url, &refresh);
xmlFree(content);
if (res == URL_FUNC_NOMEM) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ content_broadcast(&c->base, CONTENT_MSG_ERROR,
+ msg_data);
return false;
} else if (res == URL_FUNC_FAILED) {
/* This isn't fatal so carry on looking */
continue;
}
- c->refresh = talloc_strdup(c, refresh);
+ c->base.refresh = talloc_strdup(c, refresh);
free(refresh);
- if (!c->refresh) {
+ if (!c->base.refresh) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ content_broadcast(&c->base, CONTENT_MSG_ERROR,
+ msg_data);
return false;
}
- content_broadcast(c, CONTENT_MSG_REFRESH, msg_data);
+ content_broadcast(&c->base, CONTENT_MSG_REFRESH, msg_data);
}
return true;
@@ -850,9 +950,9 @@
* \return true on success, false if an error occurred
*/
-bool html_find_stylesheets(struct content *c, xmlNode *html)
+bool html_find_stylesheets(html_content *c, xmlNode *html)
{
- static const content_type accept[] = { CONTENT_CSS, CONTENT_UNKNOWN };
+ content_type accept = CONTENT_CSS;
xmlNode *node;
char *rel, *type, *media, *href, *url, *url2;
unsigned int i = STYLESHEET_START;
@@ -862,61 +962,57 @@
hlcache_child_context child;
nserror ns_error;
- child.charset = c->data.html.encoding;
- child.quirks = c->quirks;
+ child.charset = c->encoding;
+ child.quirks = c->base.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 html_stylesheet,
+ c->stylesheets = talloc_array(c, struct html_stylesheet,
STYLESHEET_START);
- if (c->data.html.stylesheets == NULL)
+ if (c->stylesheets == NULL)
goto no_memory;
- 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->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->stylesheet_count = STYLESHEET_START;
- c->active = 0;
+ c->base.active = 0;
ns_error = hlcache_handle_retrieve(default_stylesheet_url, 0,
- content__get_url(c), NULL,
+ content__get_url(&c->base), NULL,
html_convert_css_callback, c, &child, accept,
- &c->data.html.stylesheets[
- STYLESHEET_BASE].data.external);
+ &c->stylesheets[STYLESHEET_BASE].data.external);
if (ns_error != NSERROR_OK)
goto no_memory;
- c->active++;
+ c->base.active++;
- if (c->data.html.quirks == BINDING_QUIRKS_MODE_FULL) {
+ if (c->quirks == BINDING_QUIRKS_MODE_FULL) {
ns_error = hlcache_handle_retrieve(quirks_stylesheet_url, 0,
- content__get_url(c), NULL,
+ content__get_url(&c->base), NULL,
html_convert_css_callback, c, &child, accept,
- &c->data.html.stylesheets[
- STYLESHEET_QUIRKS].data.external);
+ &c->stylesheets[STYLESHEET_QUIRKS].
+ data.external);
if (ns_error != NSERROR_OK)
goto no_memory;
- c->active++;
+ c->base.active++;
}
if (option_block_ads) {
ns_error = hlcache_handle_retrieve(adblock_stylesheet_url, 0,
- content__get_url(c), NULL,
+ content__get_url(&c->base), NULL,
html_convert_css_callback, c, &child, accept,
- &c->data.html.stylesheets[
- STYLESHEET_ADBLOCK].data.external);
+ &c->stylesheets[STYLESHEET_ADBLOCK].
+ data.external);
if (ns_error != NSERROR_OK)
goto no_memory;
- c->active++;
+ c->base.active++;
}
node = html;
@@ -986,7 +1082,7 @@
* those with a title attribute) should be loaded
* (see HTML4 14.3) */
- res = url_join(href, c->data.html.base_url, &url);
+ res = url_join(href, c->base_url, &url);
xmlFree(href);
if (res != URL_FUNC_OK)
continue;
@@ -1005,30 +1101,28 @@
/* start fetch */
stylesheets = talloc_realloc(c,
- c->data.html.stylesheets,
+ c->stylesheets,
struct html_stylesheet, i + 1);
if (stylesheets == NULL) {
free(url2);
goto no_memory;
}
- c->data.html.stylesheets = stylesheets;
- c->data.html.stylesheet_count++;
- c->data.html.stylesheets[i].type =
- HTML_STYLESHEET_EXTERNAL;
+ c->stylesheets = stylesheets;
+ c->stylesheet_count++;
+ c->stylesheets[i].type = HTML_STYLESHEET_EXTERNAL;
ns_error = hlcache_handle_retrieve(url2, 0,
- content__get_url(c), NULL,
+ content__get_url(&c->base), NULL,
html_convert_css_callback, c, &child,
accept,
- &c->data.html.stylesheets[i].
- data.external);
+ &c->stylesheets[i].data.external);
free(url2);
if (ns_error != NSERROR_OK)
goto no_memory;
- c->active++;
+ c->base.active++;
i++;
} else if (strcmp((const char *) node->name, "style") == 0) {
@@ -1037,13 +1131,13 @@
}
}
- assert(c->data.html.stylesheet_count == i);
+ assert(c->stylesheet_count == i);
return true;
no_memory:
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
return false;
}
@@ -1058,7 +1152,7 @@
* \return true on success, false if an error occurred
*/
-bool html_process_style_element(struct content *c, unsigned int *index,
+bool html_process_style_element(html_content *c, unsigned int *index,
xmlNode *style)
{
xmlNode *child;
@@ -1088,29 +1182,29 @@
}
/* Extend array */
- stylesheets = talloc_realloc(c, c->data.html.stylesheets,
+ stylesheets = talloc_realloc(c, c->stylesheets,
struct html_stylesheet, *index + 1);
if (stylesheets == NULL)
goto no_memory;
- c->data.html.stylesheets = stylesheets;
- c->data.html.stylesheet_count++;
+ c->stylesheets = stylesheets;
+ c->stylesheet_count++;
- c->data.html.stylesheets[(*index)].type = HTML_STYLESHEET_INTERNAL;
- c->data.html.stylesheets[(*index)].data.internal = NULL;
+ c->stylesheets[(*index)].type = HTML_STYLESHEET_INTERNAL;
+ c->stylesheets[(*index)].data.internal = NULL;
/* create stylesheet */
sheet = talloc(c, struct content_css_data);
if (sheet == NULL) {
- c->data.html.stylesheet_count--;
+ c->stylesheet_count--;
goto no_memory;
}
error = nscss_create_css_data(sheet,
- c->data.html.base_url, NULL, c->data.html.quirks,
+ c->base_url, NULL, c->quirks,
html_inline_style_done, c);
if (error != NSERROR_OK) {
- c->data.html.stylesheet_count--;
+ c->stylesheet_count--;
goto no_memory;
}
@@ -1124,7 +1218,7 @@
xmlFree(data);
nscss_destroy_css_data(sheet);
talloc_free(sheet);
- c->data.html.stylesheet_count--;
+ c->stylesheet_count--;
/** \todo not necessarily caused by
* memory exhaustion */
goto no_memory;
@@ -1132,26 +1226,26 @@
xmlFree(data);
}
- c->active++;
+ c->base.active++;
/* Convert the content -- manually, as we want the result */
if (nscss_convert_css_data(sheet) != CSS_OK) {
/* conversion failed */
- c->active--;
+ c->base.active--;
nscss_destroy_css_data(sheet);
talloc_free(sheet);
sheet = NULL;
}
/* Update index */
- c->data.html.stylesheets[(*index)].data.internal = sheet;
+ c->stylesheets[(*index)].data.internal = sheet;
(*index)++;
return true;
no_memory:
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
return false;
}
@@ -1163,9 +1257,9 @@
*/
void html_inline_style_done(struct content_css_data *css, void *pw)
{
- struct content *html = pw;
+ html_content *html = pw;
- if (--html->active == 0)
+ if (--html->base.active == 0)
html_finish_conversion(html);
}
@@ -1176,26 +1270,22 @@
nserror html_convert_css_callback(hlcache_handle *css,
const hlcache_event *event, void *pw)
{
- struct content *parent = pw;
+ html_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++) {
+ for (i = 0, s = parent->stylesheets;
+ i != parent->stylesheet_count; i++, s++) {
if (s->type == HTML_STYLESHEET_EXTERNAL &&
s->data.external == css)
break;
}
- assert(i != parent->data.html.stylesheet_count);
+ assert(i != parent->stylesheet_count);
switch (event->type) {
case CONTENT_MSG_LOADING:
- /* check that the stylesheet is really CSS */
- if (content_get_type(css) != CONTENT_CSS) {
- assert(0 && "Non-CSS type unexpected");
- }
break;
case CONTENT_MSG_READY:
@@ -1203,7 +1293,7 @@
case CONTENT_MSG_DONE:
LOG(("got stylesheet '%s'", content_get_url(css)));
- parent->active--;
+ parent->base.active--;
break;
case CONTENT_MSG_ERROR:
@@ -1211,20 +1301,21 @@
content_get_url(css), event->data.error));
hlcache_handle_release(css);
s->data.external = NULL;
- parent->active--;
- content_add_error(parent, "?", 0);
+ parent->base.active--;
+ content_add_error(&parent->base, "?", 0);
break;
case CONTENT_MSG_STATUS:
html_set_status(parent, content_get_status_message(css));
- content_broadcast(parent, CONTENT_MSG_STATUS, event->data);
+ content_broadcast(&parent->base, CONTENT_MSG_STATUS,
+ event->data);
break;
default:
assert(0);
}
- if (parent->active == 0)
+ if (parent->base.active == 0)
html_finish_conversion(parent);
return NSERROR_OK;
@@ -1237,16 +1328,15 @@
* \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 array of types, terminated by CONTENT_UNKNOWN,
- * or 0 if all types except OTHER and UNKNOWN acceptable
+ * \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(struct content *c, const char *url, struct box *box,
- const content_type *permitted_types,
+bool html_fetch_object(html_content *c, const char *url, struct box *box,
+ content_type permitted_types,
int available_width, int available_height,
bool background)
{
@@ -1256,8 +1346,8 @@
url_func_result res;
nserror error;
- child.charset = c->data.html.encoding;
- child.quirks = c->quirks;
+ child.charset = c->encoding;
+ child.quirks = c->base.quirks;
/* Normalize the URL */
res = url_normalize(url, &url2);
@@ -1272,16 +1362,16 @@
return false;
}
- object->parent = c;
+ 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(url2, 0, content__get_url(c), NULL,
- html_object_callback, object, &child, permitted_types,
- &object->content);
+ error = hlcache_handle_retrieve(url2, 0, content__get_url(&c->base),
+ NULL, html_object_callback, object, &child,
+ permitted_types, &object->content);
/* No longer need normalized url */
free(url2);
@@ -1292,11 +1382,11 @@
}
/* add to object list */
- object->next = c->data.html.object_list;
- c->data.html.object_list = object;
+ object->next = c->object_list;
+ c->object_list = object;
- c->data.html.num_objects++;
- c->active++;
+ c->num_objects++;
+ c->base.active++;
return error != NSERROR_NOMEM;
}
@@ -1312,24 +1402,24 @@
bool html_replace_object(struct content_html_object *object, const char *url)
{
- struct content *c;
+ html_content *c;
hlcache_child_context child;
- struct content *page;
+ html_content *page;
char *url2;
url_func_result res;
nserror error;
assert(object != NULL);
- c = object->parent;
+ c = (html_content *) object->parent;
- child.charset = c->data.html.encoding;
- child.quirks = c->quirks;
+ 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->active--;
+ c->base.active--;
hlcache_handle_release(object->content);
object->content = NULL;
@@ -1342,8 +1432,8 @@
return res != URL_FUNC_NOMEM;
/* initialise fetch */
- error = hlcache_handle_retrieve(url2, 0, content__get_url(c), NULL,
- html_object_callback, object, &child,
+ error = hlcache_handle_retrieve(url2, 0, content__get_url(&c->base),
+ NULL, html_object_callback, object, &child,
object->permitted_types,
&object->content);
@@ -1352,10 +1442,9 @@
if (error != NSERROR_OK)
return false;
- for (page = c; page; page = page->data.html.page) {
- assert(page->type == CONTENT_HTML);
- page->active++;
- page->status = CONTENT_STATUS_READY;
+ for (page = c; page != NULL; page = page->page) {
+ page->base.active++;
+ page->base.status = CONTENT_STATUS_READY;
}
return true;
@@ -1370,7 +1459,7 @@
const hlcache_event *event, void *pw)
{
struct content_html_object *o = pw;
- struct content *c = o->parent;
+ html_content *c = (html_content *) o->parent;
int x, y;
struct box *box;
@@ -1378,48 +1467,29 @@
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,
- box,
- box->object_params);
- break;
- }
-
- /* not acceptable */
- hlcache_handle_release(object);
-
- o->content = NULL;
-
- c->active--;
-
- content_add_error(c, "?", 0);
- html_set_status(c, messages_get("BadObject"));
- content_broadcast(c, CONTENT_MSG_STATUS, event->data);
-
- html_object_failed(box, c, o->background);
+ if (c->bw != NULL)
+ content_open(object,
+ c->bw, &c->base,
+ box,
+ box->object_params);
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);
+ if (c->base.status == CONTENT_STATUS_READY ||
+ c->base.status == CONTENT_STATUS_DONE)
+ content__reformat(&c->base,
+ c->base.available_width,
+ c->base.height);
}
break;
case CONTENT_MSG_DONE:
-
if (box->flags & REPLACE_DIM) {
union content_msg_data data;
- c->active--;
+ c->base.active--;
html_object_done(box, object, o->background);
if (!box_visible(box))
@@ -1433,9 +1503,9 @@
data.redraw.height = box->height;
data.redraw.full_redraw = true;
- content_broadcast(c, CONTENT_MSG_REDRAW, data);
+ content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
} else {
- c->active--;
+ c->base.active--;
html_object_done(box, object, o->background);
}
break;
@@ -1445,17 +1515,17 @@
o->content = NULL;
- c->active--;
+ c->base.active--;
- content_add_error(c, "?", 0);
+ content_add_error(&c->base, "?", 0);
html_set_status(c, event->data.error);
- content_broadcast(c, CONTENT_MSG_STATUS, event->data);
+ content_broadcast(&c->base, 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); */
+ /* content_broadcast(&c->base, CONTENT_MSG_STATUS, 0); */
break;
case CONTENT_MSG_REFORMAT:
@@ -1491,7 +1561,7 @@
data.redraw.object_x += x + box->padding[LEFT];
data.redraw.object_y += y + box->padding[TOP];
- content_broadcast(c, CONTENT_MSG_REDRAW, data);
+ content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
}
break;
@@ -1508,14 +1578,15 @@
assert(0);
}
- if (c->status == CONTENT_STATUS_READY && c->active == 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, c->available_width, c->height);
+ content__reformat(&c->base, c->base.available_width,
+ c->base.height);
html_set_status(c, "");
- content_set_done(c);
+ content_set_done(&c->base);
}
/* If 1) the configuration option to reflow pages while objects are
@@ -1529,10 +1600,11 @@
else if (option_incremental_reflow &&
event->type == CONTENT_MSG_DONE &&
!(box->flags & REPLACE_DIM) &&
- (c->status == CONTENT_STATUS_READY ||
- c->status == CONTENT_STATUS_DONE) &&
- (wallclock() > c->reformat_time)) {
- content__reformat(c, c->available_width, c->height);
+ (c->base.status == CONTENT_STATUS_READY ||
+ c->base.status == CONTENT_STATUS_DONE) &&
+ (wallclock() > c->base.reformat_time)) {
+ content__reformat(&c->base, c->base.available_width,
+ c->base.height);
}
return NSERROR_OK;
@@ -1577,7 +1649,7 @@
* \param background the object was the background image for the box
*/
-void html_object_failed(struct box *box, struct content *content,
+void html_object_failed(struct box *box, html_content *content,
bool background)
{
/* Nothing to do */
@@ -1586,29 +1658,6 @@
/**
- * Check if a type is in a list.
- *
- * \param type the content_type to search for
- * \param permitted_types array of types, terminated by CONTENT_UNKNOWN,
- * or 0 if all types except OTHER and UNKNOWN acceptable
- * \return the type is in the list or acceptable
- */
-
-bool html_object_type_permitted(const content_type type,
- const content_type *permitted_types)
-{
- if (permitted_types) {
- for (; *permitted_types != CONTENT_UNKNOWN; permitted_types++)
- if (*permitted_types == type)
- return true;
- } else if (type < CONTENT_OTHER) {
- return true;
- }
- return false;
-}
-
-
-/**
* schedule() callback for object refresh
*/
@@ -1639,11 +1688,12 @@
void html_stop(struct content *c)
{
+ html_content *htmlc = (html_content *) c;
struct content_html_object *object;
assert(c->status == CONTENT_STATUS_READY);
- for (object = c->data.html.object_list; object != NULL;
+ for (object = htmlc->object_list; object != NULL;
object = object->next) {
if (object->content == NULL)
continue;
@@ -1668,13 +1718,14 @@
void html_reformat(struct content *c, int width, int height)
{
+ html_content *htmlc = (html_content *) c;
struct box *layout;
unsigned int time_before, time_taken;
time_before = wallclock();
- layout_document(c, width, height);
- layout = c->data.html.layout;
+ layout_document(htmlc, width, height);
+ layout = htmlc->layout;
/* width and height are at least margin box of document */
c->width = layout->x + layout->padding[LEFT] + layout->width +
@@ -1722,14 +1773,12 @@
void html_destroy(struct content *c)
{
+ html_content *html = (html_content *) c;
unsigned int i;
struct form *f, *g;
- struct content_html_data *html;
LOG(("content %p", c));
- html = &c->data.html;
-
/* Destroy forms */
for (f = html->forms; f != NULL; f = g) {
g = f->prev;
@@ -1737,13 +1786,8 @@
form_free(f);
}
- if (html->favicon != NULL) {
- hlcache_handle_release(html->favicon);
- html->favicon = NULL;
- }
+ imagemap_destroy(html);
- imagemap_destroy(c);
-
if (html->parser_binding != NULL)
binding_destroy_tree(html->parser_binding);
@@ -1849,7 +1893,7 @@
}
}
-bool html_clone(const struct content *old, struct content *new_content)
+nserror html_clone(const struct content *old, struct content **newc)
{
/** \todo Clone HTML specifics */
@@ -1865,22 +1909,21 @@
* Set the content status.
*/
-void html_set_status(struct content *c, const char *extra)
+void html_set_status(html_content *c, const char *extra)
{
unsigned int stylesheets = 0, objects = 0;
- if (c->data.html.num_objects == 0)
- stylesheets = c->data.html.stylesheet_count - c->active;
+ if (c->num_objects == 0)
+ stylesheets = c->stylesheet_count - c->base.active;
else {
- stylesheets = c->data.html.stylesheet_count;
- objects = c->data.html.num_objects - c->active;
+ stylesheets = c->stylesheet_count;
+ objects = c->num_objects - c->base.active;
}
- content_set_status(c, "%u/%u %s %u/%u %s %s",
- stylesheets, c->data.html.stylesheet_count,
- messages_get((c->data.html.stylesheet_count == 1) ?
+ content_set_status(&c->base, "%u/%u %s %u/%u %s %s",
+ stylesheets, c->stylesheet_count,
+ messages_get((c->stylesheet_count == 1) ?
"styl" : "styls"),
- objects, c->data.html.num_objects,
- messages_get((c->data.html.num_objects == 1) ?
- "obj" : "objs"),
+ objects, c->num_objects,
+ messages_get((c->num_objects == 1) ? "obj" : "objs"),
extra);
}
@@ -1893,19 +1936,20 @@
struct content *page, struct box *box,
struct object_params *params)
{
+ html_content *html = (html_content *) c;
struct content_html_object *object, *next;
- c->data.html.bw = bw;
- c->data.html.page = page;
- c->data.html.box = box;
+ html->bw = bw;
+ html->page = (html_content *) page;
+ html->box = box;
- for (object = c->data.html.object_list; object != NULL; 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_UNKNOWN)
+ if (content_get_type(object->content) == CONTENT_NONE)
continue;
content_open(object->content,
@@ -1922,17 +1966,18 @@
void html_close(struct content *c)
{
+ html_content *html = (html_content *) c;
struct content_html_object *object, *next;
- c->data.html.bw = 0;
+ html->bw = NULL;
- for (object = c->data.html.object_list; object != NULL; 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_UNKNOWN)
+ if (content_get_type(object->content) == CONTENT_NONE)
continue;
if (content_get_type(object->content) == CONTENT_HTML)
@@ -2004,12 +2049,11 @@
*/
xmlDoc *html_get_document(hlcache_handle *h)
{
- struct content *c = hlcache_handle_get_content(h);
+ html_content *c = (html_content *) hlcache_handle_get_content(h);
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
- return c->data.html.document;
+ return c->document;
}
/**
@@ -2022,12 +2066,11 @@
*/
struct box *html_get_box_tree(hlcache_handle *h)
{
- struct content *c = hlcache_handle_get_content(h);
+ html_content *c = (html_content *) hlcache_handle_get_content(h);
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
- return c->data.html.layout;
+ return c->layout;
}
/**
@@ -2038,12 +2081,11 @@
*/
const char *html_get_encoding(hlcache_handle *h)
{
- struct content *c = hlcache_handle_get_content(h);
+ html_content *c = (html_content *) hlcache_handle_get_content(h);
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
- return c->data.html.encoding;
+ return c->encoding;
}
/**
@@ -2054,12 +2096,11 @@
*/
binding_encoding_source html_get_encoding_source(hlcache_handle *h)
{
- struct content *c = hlcache_handle_get_content(h);
+ html_content *c = (html_content *) hlcache_handle_get_content(h);
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
- return c->data.html.encoding_source;
+ return c->encoding_source;
}
/**
@@ -2070,12 +2111,11 @@
*/
struct content_html_frames *html_get_frameset(hlcache_handle *h)
{
- struct content *c = hlcache_handle_get_content(h);
+ html_content *c = (html_content *) hlcache_handle_get_content(h);
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
- return c->data.html.frameset;
+ return c->frameset;
}
/**
@@ -2086,12 +2126,11 @@
*/
struct content_html_iframe *html_get_iframe(hlcache_handle *h)
{
- struct content *c = hlcache_handle_get_content(h);
+ html_content *c = (html_content *) hlcache_handle_get_content(h);
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
- return c->data.html.iframe;
+ return c->iframe;
}
/**
@@ -2102,12 +2141,11 @@
*/
const char *html_get_base_url(hlcache_handle *h)
{
- struct content *c = hlcache_handle_get_content(h);
+ html_content *c = (html_content *) hlcache_handle_get_content(h);
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
- return c->data.html.base_url;
+ return c->base_url;
}
/**
@@ -2118,12 +2156,11 @@
*/
const char *html_get_base_target(hlcache_handle *h)
{
- struct content *c = hlcache_handle_get_content(h);
+ html_content *c = (html_content *) hlcache_handle_get_content(h);
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
- return c->data.html.base_target;
+ return c->base_target;
}
/**
@@ -2135,15 +2172,14 @@
*/
struct html_stylesheet *html_get_stylesheets(hlcache_handle *h, unsigned int *n)
{
- struct content *c = hlcache_handle_get_content(h);
+ html_content *c = (html_content *) hlcache_handle_get_content(h);
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
assert(n != NULL);
- *n = c->data.html.stylesheet_count;
+ *n = c->stylesheet_count;
- return c->data.html.stylesheets;
+ return c->stylesheets;
}
/**
@@ -2155,15 +2191,14 @@
*/
struct content_html_object *html_get_objects(hlcache_handle *h, unsigned int *n)
{
- struct content *c = hlcache_handle_get_content(h);
+ html_content *c = (html_content *) hlcache_handle_get_content(h);
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
assert(n != NULL);
- *n = c->data.html.num_objects;
+ *n = c->num_objects;
- return c->data.html.object_list;
+ return c->object_list;
}
/**
@@ -2174,12 +2209,11 @@
*/
hlcache_handle *html_get_favicon(hlcache_handle *h)
{
- struct content *c = hlcache_handle_get_content(h);
+ html_content *c = (html_content *) hlcache_handle_get_content(h);
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
- return c->data.html.favicon;
+ return NULL;
}
@@ -2208,3 +2242,15 @@
}
return false;
}
+
+/**
+ * Compute the type of a content
+ *
+ * \param c Content to consider
+ * \return CONTENT_HTML
+ */
+content_type html_content_type(lwc_string *mime_type)
+{
+ return CONTENT_HTML;
+}
+
Index: render/html_redraw.c
===================================================================
--- render/html_redraw.c (revision 12276)
+++ render/html_redraw.c (working copy)
@@ -47,6 +47,7 @@
#include "render/box.h"
#include "render/font.h"
#include "render/form.h"
+#include "render/html_internal.h"
#include "render/layout.h"
#include "utils/log.h"
#include "utils/messages.h"
@@ -114,6 +115,7 @@
int width, int height, const struct rect *clip,
float scale, colour background_colour)
{
+ html_content *html = (html_content *) c;
struct box *box;
bool result = true;
bool select, select_only;
@@ -122,7 +124,7 @@
.fill_colour = background_colour,
};
- box = c->data.html.layout;
+ box = html->layout;
assert(box);
/* The select menu needs special treating because, when opened, it
@@ -145,9 +147,8 @@
/* clear to background colour */
result = plot.clip(clip);
- if (c->data.html.background_colour != NS_TRANSPARENT)
- pstyle_fill_bg.fill_colour =
- c->data.html.background_colour;
+ if (html->background_colour != NS_TRANSPARENT)
+ pstyle_fill_bg.fill_colour = html->background_colour;
result &= plot.rectangle(clip->x0, clip->y0, clip->x1, clip->y1,
&pstyle_fill_bg);
Index: render/textplain.c
===================================================================
--- render/textplain.c (revision 12276)
+++ render/textplain.c (working copy)
@@ -50,7 +50,25 @@
#include "utils/utils.h"
#include "utils/utf8.h"
+struct textplain_line {
+ size_t start;
+ size_t length;
+};
+typedef struct textplain_content {
+ struct content base;
+
+ char *encoding;
+ void *inputstream;
+ char *utf8_data;
+ size_t utf8_data_size;
+ size_t utf8_data_allocated;
+ unsigned long physical_line_count;
+ struct textplain_line *physical_line;
+ int formatted_width;
+} textplain_content;
+
+
#define CHUNK 32768 /* Must be a power of 2 */
#define MARGIN 4
@@ -69,35 +87,126 @@
static int textplain_tab_width = 256; /* try for a sensible default */
-static bool textplain_create_internal(struct content *c, const char *encoding);
+static nserror textplain_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror textplain_create_internal(textplain_content *c,
+ const char *charset);
+static bool textplain_process_data(struct content *c,
+ const char *data, unsigned int size);
+static bool textplain_convert(struct content *c);
+static void textplain_mouse_track(struct content *c, struct browser_window *bw,
+ browser_mouse_state mouse, int x, int y);
+static void textplain_mouse_action(struct content *c, struct browser_window *bw,
+ browser_mouse_state mouse, int x, int y);
+static void textplain_reformat(struct content *c, int width, int height);
+static void textplain_destroy(struct content *c);
+static bool textplain_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static nserror textplain_clone(const struct content *old,
+ struct content **newc);
+static content_type textplain_content_type(lwc_string *mime_type);
+
static parserutils_error textplain_charset_hack(const uint8_t *data, size_t len,
uint16_t *mibenum, uint32_t *source);
-static bool textplain_drain_input(struct content *c,
+static bool textplain_drain_input(textplain_content *c,
parserutils_inputstream *stream, parserutils_error terminator);
-static bool textplain_copy_utf8_data(struct content *c,
+static bool textplain_copy_utf8_data(textplain_content *c,
const uint8_t *buf, size_t len);
static int textplain_coord_from_offset(const char *text, size_t offset,
size_t length);
static float textplain_line_height(void);
+static const content_handler textplain_content_handler = {
+ textplain_create,
+ textplain_process_data,
+ textplain_convert,
+ textplain_reformat,
+ textplain_destroy,
+ NULL,
+ textplain_mouse_track,
+ textplain_mouse_action,
+ textplain_redraw,
+ NULL,
+ NULL,
+ NULL,
+ textplain_clone,
+ NULL,
+ textplain_content_type,
+ true
+};
+static lwc_string *textplain_mime_type;
+
/**
+ * Initialise the text content handler
+ */
+nserror textplain_init(void)
+{
+ lwc_error lerror;
+ nserror error;
+
+ lerror = lwc_intern_string("text/plain", SLEN("text/plain"),
+ &textplain_mime_type);
+ if (lerror != lwc_error_ok)
+ return NSERROR_NOMEM;
+
+ error = content_factory_register_handler(textplain_mime_type,
+ &textplain_content_handler);
+ if (error != NSERROR_OK)
+ lwc_string_unref(textplain_mime_type);
+
+ return error;
+}
+
+/**
+ * Clean up after the text content handler
+ */
+void textplain_fini(void)
+{
+ lwc_string_unref(textplain_mime_type);
+}
+
+/**
* Create a CONTENT_TEXTPLAIN.
*/
-bool textplain_create(struct content *c, const http_parameter *params)
+nserror textplain_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
{
+ textplain_content *text;
+ nserror error;
const char *encoding;
- nserror error;
- textplain_style.size = (option_font_size * FONT_SIZE_SCALE) / 10;
+ text = talloc_zero(0, textplain_content);
+ if (text == NULL)
+ return NSERROR_NOMEM;
+ error = content__init(&text->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(text);
+ return error;
+ }
+
error = http_parameter_list_find_item(params, "charset", &encoding);
if (error != NSERROR_OK) {
encoding = "Windows-1252";
}
- return textplain_create_internal(c, encoding);
+ error = textplain_create_internal(text, encoding);
+ if (error != NSERROR_OK) {
+ talloc_free(text);
+ return error;
+ }
+
+ *c = (struct content *) text;
+
+ return NSERROR_OK;
}
/*
@@ -116,13 +225,15 @@
return PARSERUTILS_OK;
}
-bool textplain_create_internal(struct content *c, const char *encoding)
+nserror textplain_create_internal(textplain_content *c, const char *encoding)
{
char *utf8_data;
parserutils_inputstream *stream;
parserutils_error error;
union content_msg_data msg_data;
+ textplain_style.size = (option_font_size * FONT_SIZE_SCALE) / 10;
+
utf8_data = talloc_array(c, char, CHUNK);
if (utf8_data == NULL)
goto no_memory;
@@ -140,30 +251,31 @@
goto no_memory;
}
- c->data.textplain.encoding = strdup(encoding);
- if (c->data.textplain.encoding == NULL) {
+ c->encoding = strdup(encoding);
+ if (c->encoding == NULL) {
talloc_free(utf8_data);
parserutils_inputstream_destroy(stream);
goto no_memory;
}
- c->data.textplain.inputstream = stream;
- c->data.textplain.utf8_data = utf8_data;
- c->data.textplain.utf8_data_size = 0;
- c->data.textplain.utf8_data_allocated = CHUNK;
- c->data.textplain.physical_line = 0;
- c->data.textplain.physical_line_count = 0;
- c->data.textplain.formatted_width = 0;
+ c->inputstream = stream;
+ c->utf8_data = utf8_data;
+ c->utf8_data_size = 0;
+ c->utf8_data_allocated = CHUNK;
+ c->physical_line = 0;
+ c->physical_line_count = 0;
+ c->formatted_width = 0;
- return true;
+ return NSERROR_OK;
no_memory:
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
-bool textplain_drain_input(struct content *c, parserutils_inputstream *stream,
+bool textplain_drain_input(textplain_content *c,
+ parserutils_inputstream *stream,
parserutils_error terminator)
{
static const uint8_t *u_fffd = (const uint8_t *) "\xef\xbf\xfd";
@@ -228,26 +340,25 @@
return true;
}
-bool textplain_copy_utf8_data(struct content *c, const uint8_t *buf, size_t len)
+bool textplain_copy_utf8_data(textplain_content *c,
+ const uint8_t *buf, size_t len)
{
- if (c->data.textplain.utf8_data_size + len >=
- c->data.textplain.utf8_data_allocated) {
+ if (c->utf8_data_size + len >= c->utf8_data_allocated) {
/* Compute next multiple of chunk above the required space */
- size_t allocated = (c->data.textplain.utf8_data_size + len +
+ size_t allocated = (c->utf8_data_size + len +
CHUNK - 1) & ~(CHUNK - 1);
char *utf8_data = talloc_realloc(c,
- c->data.textplain.utf8_data,
+ c->utf8_data,
char, allocated);
if (utf8_data == NULL)
return false;
- c->data.textplain.utf8_data = utf8_data;
- c->data.textplain.utf8_data_allocated = allocated;
+ c->utf8_data = utf8_data;
+ c->utf8_data_allocated = allocated;
}
- memcpy(c->data.textplain.utf8_data +
- c->data.textplain.utf8_data_size, buf, len);
- c->data.textplain.utf8_data_size += len;
+ memcpy(c->utf8_data + c->utf8_data_size, buf, len);
+ c->utf8_data_size += len;
return true;
}
@@ -260,7 +371,8 @@
bool textplain_process_data(struct content *c,
const char *data, unsigned int size)
{
- parserutils_inputstream *stream = c->data.textplain.inputstream;
+ textplain_content *text = (textplain_content *) c;
+ parserutils_inputstream *stream = text->inputstream;
union content_msg_data msg_data;
parserutils_error error;
@@ -270,7 +382,7 @@
goto no_memory;
}
- if (textplain_drain_input(c, stream, PARSERUTILS_NEEDDATA) == false)
+ if (textplain_drain_input(text, stream, PARSERUTILS_NEEDDATA) == false)
goto no_memory;
return true;
@@ -288,7 +400,8 @@
bool textplain_convert(struct content *c)
{
- parserutils_inputstream *stream = c->data.textplain.inputstream;
+ textplain_content *text = (textplain_content *) c;
+ parserutils_inputstream *stream = text->inputstream;
parserutils_error error;
error = parserutils_inputstream_append(stream, NULL, 0);
@@ -296,11 +409,11 @@
return false;
}
- if (textplain_drain_input(c, stream, PARSERUTILS_EOF) == false)
+ if (textplain_drain_input(text, stream, PARSERUTILS_EOF) == false)
return false;
parserutils_inputstream_destroy(stream);
- c->data.textplain.inputstream = NULL;
+ text->inputstream = NULL;
content_set_ready(c);
content_set_done(c);
@@ -316,10 +429,11 @@
void textplain_reformat(struct content *c, int width, int height)
{
- char *utf8_data = c->data.textplain.utf8_data;
- size_t utf8_data_size = c->data.textplain.utf8_data_size;
+ textplain_content *text = (textplain_content *) c;
+ char *utf8_data = text->utf8_data;
+ size_t utf8_data_size = text->utf8_data_size;
unsigned long line_count = 0;
- struct textplain_line *line = c->data.textplain.physical_line;
+ struct textplain_line *line = text->physical_line;
struct textplain_line *line1;
size_t i, space, col;
size_t columns = 80;
@@ -333,12 +447,12 @@
columns = (width - MARGIN - MARGIN) * 8 / character_width;
textplain_tab_width = (TAB_WIDTH * character_width) / 8;
- c->data.textplain.formatted_width = width;
+ text->formatted_width = width;
- c->data.textplain.physical_line_count = 0;
+ text->physical_line_count = 0;
if (!line) {
- c->data.textplain.physical_line = line =
+ text->physical_line = line =
talloc_array(c, struct textplain_line, 1024 + 3);
if (!line)
goto no_memory;
@@ -359,8 +473,7 @@
struct textplain_line, line_count + 1024 + 3);
if (!line1)
goto no_memory;
- c->data.textplain.physical_line =
- line = line1;
+ text->physical_line = line = line1;
}
if (term) {
line[line_count-1].length = i - line_start;
@@ -392,7 +505,7 @@
line[line_count-1].length = i - line[line_count-1].start;
line[line_count].start = utf8_data_size;
- c->data.textplain.physical_line_count = line_count;
+ text->physical_line_count = line_count;
c->width = width;
c->height = line_count * textplain_line_height() + MARGIN + MARGIN;
@@ -410,39 +523,64 @@
void textplain_destroy(struct content *c)
{
- if (c->data.textplain.encoding != NULL)
- free(c->data.textplain.encoding);
+ textplain_content *text = (textplain_content *) c;
- if (c->data.textplain.inputstream != NULL)
- parserutils_inputstream_destroy(c->data.textplain.inputstream);
+ if (text->encoding != NULL)
+ free(text->encoding);
+
+ if (text->inputstream != NULL)
+ parserutils_inputstream_destroy(text->inputstream);
}
-bool textplain_clone(const struct content *old, struct content *new_content)
+nserror textplain_clone(const struct content *old, struct content **newc)
{
+ const textplain_content *old_text = (textplain_content *) old;
+ textplain_content *text;
+ nserror error;
const char *data;
unsigned long size;
+ text = talloc_zero(0, textplain_content);
+ if (text == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &text->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&text->base);
+ return error;
+ }
+
/* Simply replay create/process/convert */
- if (textplain_create_internal(new_content,
- old->data.textplain.encoding) == false)
- return false;
+ error = textplain_create_internal(text, old_text->encoding);
+ if (error != NSERROR_OK) {
+ content_destroy(&text->base);
+ return error;
+ }
- data = content__get_source_data(new_content, &size);
+ data = content__get_source_data(&text->base, &size);
if (size > 0) {
- if (textplain_process_data(new_content, data, size) == false)
- return false;
+ if (textplain_process_data(&text->base, data, size) == false) {
+ content_destroy(&text->base);
+ return NSERROR_NOMEM;
+ }
}
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (textplain_convert(new_content) == false)
- return false;
+ if (textplain_convert(&text->base) == false) {
+ content_destroy(&text->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ return NSERROR_OK;
}
+content_type textplain_content_type(lwc_string *mime_type)
+{
+ return CONTENT_TEXTPLAIN;
+}
/**
* Handle mouse tracking (including drags) in a TEXTPLAIN content window.
@@ -551,15 +689,16 @@
int width, int height, const struct rect *clip,
float scale, colour background_colour)
{
+ textplain_content *text = (textplain_content *) c;
struct browser_window *bw = current_redraw_browser;
- char *utf8_data = c->data.textplain.utf8_data;
+ char *utf8_data = text->utf8_data;
long lineno;
- unsigned long line_count = c->data.textplain.physical_line_count;
+ unsigned long line_count = text->physical_line_count;
float line_height = textplain_line_height();
float scaled_line_height = line_height * scale;
long line0 = (clip->y0 - y * scale) / scaled_line_height - 1;
long line1 = (clip->y1 - y * scale) / scaled_line_height + 1;
- struct textplain_line *line = c->data.textplain.physical_line;
+ struct textplain_line *line = text->physical_line;
size_t length;
plot_style_t *plot_style_highlight;
@@ -682,11 +821,12 @@
*/
unsigned long textplain_line_count(hlcache_handle *h)
{
- struct content *c = hlcache_handle_get_content(h);
+ textplain_content *c =
+ (textplain_content *) hlcache_handle_get_content(h);
assert(c != NULL);
- return c->data.textplain.physical_line_count;
+ return c->physical_line_count;
}
/**
@@ -697,11 +837,12 @@
*/
size_t textplain_size(hlcache_handle *h)
{
- struct content *c = hlcache_handle_get_content(h);
+ textplain_content *c =
+ (textplain_content *) hlcache_handle_get_content(h);
assert(c != NULL);
- return c->data.textplain.utf8_data_size;
+ return c->utf8_data_size;
}
/**
@@ -719,7 +860,8 @@
size_t textplain_offset_from_coords(hlcache_handle *h, int x, int y, int dir)
{
- struct content *c = hlcache_handle_get_content(h);
+ textplain_content *c =
+ (textplain_content *) hlcache_handle_get_content(h);
float line_height = textplain_line_height();
struct textplain_line *line;
const char *text;
@@ -728,12 +870,11 @@
int idx;
assert(c != NULL);
- assert(c->type == CONTENT_TEXTPLAIN);
y = (int)((float)(y - MARGIN) / line_height);
x -= MARGIN;
- nlines = c->data.textplain.physical_line_count;
+ nlines = c->physical_line_count;
if (!nlines)
return 0;
@@ -741,8 +882,8 @@
else if ((unsigned)y >= nlines)
y = nlines - 1;
- line = &c->data.textplain.physical_line[y];
- text = c->data.textplain.utf8_data + line->start;
+ line = &c->physical_line[y];
+ text = c->utf8_data + line->start;
length = line->length;
idx = 0;
@@ -798,18 +939,18 @@
int textplain_find_line(hlcache_handle *h, unsigned offset)
{
- struct content *c = hlcache_handle_get_content(h);
+ textplain_content *c =
+ (textplain_content *) 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;
+ line = c->physical_line;
+ nlines = c->physical_line_count;
- if (offset > c->data.textplain.utf8_data_size)
+ if (offset > c->utf8_data_size)
return -1;
/* \todo - implement binary search here */
@@ -875,7 +1016,8 @@
void textplain_coords_from_range(hlcache_handle *h, unsigned start,
unsigned end, struct rect *r)
{
- struct content *c = hlcache_handle_get_content(h);
+ textplain_content *c =
+ (textplain_content *) hlcache_handle_get_content(h);
float line_height = textplain_line_height();
char *utf8_data;
struct textplain_line *line;
@@ -883,13 +1025,12 @@
unsigned nlines;
assert(c != NULL);
- assert(c->type == CONTENT_TEXTPLAIN);
assert(start <= end);
- assert(end <= c->data.textplain.utf8_data_size);
+ assert(end <= c->utf8_data_size);
- utf8_data = c->data.textplain.utf8_data;
- nlines = c->data.textplain.physical_line_count;
- line = c->data.textplain.physical_line;
+ utf8_data = c->utf8_data;
+ nlines = c->physical_line_count;
+ line = c->physical_line;
/* find start */
lineno = textplain_find_line(h, start);
@@ -904,7 +1045,7 @@
lineno = textplain_find_line(h, end);
r->x0 = 0;
- r->x1 = c->data.textplain.formatted_width;
+ r->x1 = c->formatted_width;
}
else {
/* single line */
@@ -934,19 +1075,19 @@
char *textplain_get_line(hlcache_handle *h, unsigned lineno,
size_t *poffset, size_t *plen)
{
- struct content *c = hlcache_handle_get_content(h);
+ textplain_content *c =
+ (textplain_content *) 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)
+ if (lineno >= c->physical_line_count)
return NULL;
- line = &c->data.textplain.physical_line[lineno];
+ line = &c->physical_line[lineno];
*poffset = line->start;
*plen = line->length;
- return c->data.textplain.utf8_data + line->start;
+ return c->utf8_data + line->start;
}
@@ -965,13 +1106,13 @@
char *textplain_get_raw_data(hlcache_handle *h, unsigned start, unsigned end,
size_t *plen)
{
- struct content *c = hlcache_handle_get_content(h);
+ textplain_content *c =
+ (textplain_content *) 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;
+ utf8_size = c->utf8_data_size;
/* any text at all? */
if (!utf8_size) return NULL;
@@ -982,7 +1123,7 @@
*plen = end - start;
- return c->data.textplain.utf8_data + start;
+ return c->utf8_data + start;
}
/**
Index: render/html.h
===================================================================
--- render/html.h (revision 12276)
+++ render/html.h (working copy)
@@ -45,16 +45,6 @@
struct scroll;
struct scroll_msg_data;
-/* entries in stylesheet_content */
-#define STYLESHEET_BASE 0 /* base style sheet */
-#define STYLESHEET_QUIRKS 1 /* quirks mode stylesheet */
-#define STYLESHEET_ADBLOCK 2 /* adblocking stylesheet */
-#define STYLESHEET_START 3 /* start of document stylesheets */
-
-extern char *default_stylesheet_url;
-extern char *adblock_stylesheet_url;
-extern char *quirks_stylesheet_url;
-
/**
* Container for stylesheets used by an HTML document
*/
@@ -90,9 +80,8 @@
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. */
- const content_type *permitted_types;
+ /** Bitmap of acceptable content types */
+ content_type permitted_types;
bool background; /**< This object is a background image. */
};
@@ -134,92 +123,24 @@
struct content_html_iframe *next;
};
-/** Data specific to CONTENT_HTML. */
-struct content_html_data {
- void *parser_binding;
- xmlDoc *document;
- binding_quirks_mode quirks; /**< Quirkyness of document */
+/* entries in stylesheet_content */
+#define STYLESHEET_BASE 0 /* base style sheet */
+#define STYLESHEET_QUIRKS 1 /* quirks mode stylesheet */
+#define STYLESHEET_ADBLOCK 2 /* adblocking stylesheet */
+#define STYLESHEET_START 3 /* start of document stylesheets */
- char *encoding; /**< Encoding of source, 0 if unknown. */
- binding_encoding_source encoding_source;
- /**< Source of encoding information. */
+extern char *default_stylesheet_url;
+extern char *adblock_stylesheet_url;
+extern char *quirks_stylesheet_url;
- char *base_url; /**< Base URL (may be a copy of content->url). */
- char *base_target; /**< Base target */
-
- struct box *layout; /**< Box tree, or 0. */
- colour background_colour; /**< Document background colour. */
- const struct font_functions *font_func;
-
- 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 html_stylesheet *stylesheets;
- /**< Style selection context */
- css_select_ctx *select_ctx;
-
- /** Number of entries in object_list. */
- unsigned int num_objects;
- /** List of objects. */
- struct content_html_object *object_list;
- /** Forms, in reverse order to document. */
- struct form *forms;
- /** Hash table of imagemaps. */
- struct imagemap **imagemaps;
-
- /** Browser window containing this document, or 0 if not open. */
- struct browser_window *bw;
-
- /** Frameset information */
- struct content_html_frames *frameset;
-
- /** Inline frame information */
- struct content_html_iframe *iframe;
-
- /** Content of type CONTENT_HTML containing this, or 0 if not an object
- * within a page. */
- struct content *page;
- /** Box containing this, or 0 if not an object. */
- struct box *box;
-};
-
/** Render padding and margin box outlines in html_redraw(). */
extern bool html_redraw_debug;
+nserror html_init(void);
+void html_fini(void);
-bool html_create(struct content *c, const struct http_parameter *params);
-bool html_process_data(struct content *c, const char *data, unsigned int size);
-bool html_convert(struct content *c);
-void html_reformat(struct content *c, int width, int height);
-void html_destroy(struct content *c);
-bool html_clone(const struct content *old, struct content *new_content);
-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);
-void html_stop(struct content *c);
-void html_open(struct content *c, struct browser_window *bw,
- struct content *page, struct box *box,
- struct object_params *params);
-void html_close(struct content *c);
-void html_set_status(struct content *c, const char *extra);
-
void html_redraw_a_box(struct hlcache_handle *h, struct box *box);
-/* in render/html_redraw.c */
-bool html_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-
-/* in render/html_interaction.c */
-void html_mouse_track(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y);
-void html_mouse_action(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y);
-void html_overflow_scroll_callback(void *client_data,
- struct scroll_msg_data *scroll_data);
void html_overflow_scroll_drag_end(struct scroll *scroll,
browser_mouse_state mouse, int x, int y);
size_t html_selection_drag_end(struct hlcache_handle *h,
Index: render/layout.c
===================================================================
--- render/layout.c (revision 12276)
+++ render/layout.c (working copy)
@@ -49,6 +49,7 @@
#include "render/box.h"
#include "render/font.h"
#include "render/form.h"
+#include "render/html_internal.h"
#include "render/layout.h"
#include "render/table.h"
#include "utils/log.h"
@@ -66,7 +67,7 @@
static bool layout_block_context(struct box *block, int viewport_height,
- struct content *content);
+ html_content *content);
static void layout_minmax_block(struct box *block,
const struct font_functions *font_func);
static struct box* layout_next_margin_block(struct box *box, struct box *block,
@@ -99,16 +100,16 @@
static bool layout_line(struct box *first, int *width, int *y,
int cx, int cy, struct box *cont, bool indent,
bool has_text_children,
- struct content *content, struct box **next_box);
+ html_content *content, struct box **next_box);
static struct box *layout_minmax_line(struct box *first, int *min, int *max,
bool first_line, bool *line_has_height,
const struct font_functions *font_func);
static int layout_text_indent(const css_computed_style *style, int width);
-static bool layout_float(struct box *b, int width, struct content *content);
+static bool layout_float(struct box *b, int width, html_content *content);
static void place_float_below(struct box *c, int width, int cx, int y,
struct box *cont);
static bool layout_table(struct box *box, int available_width,
- struct content *content);
+ html_content *content);
static void layout_move_children(struct box *box, int x, int y);
static void calculate_mbp_width(const css_computed_style *style,
unsigned int side, bool margin, bool border, bool padding,
@@ -121,10 +122,10 @@
static bool layout_position_absolute(struct box *box,
struct box *containing_block,
int cx, int cy,
- struct content *content);
+ html_content *content);
static bool layout_absolute(struct box *box, struct box *containing_block,
int cx, int cy,
- struct content *content);
+ html_content *content);
static void layout_compute_offsets(struct box *box,
struct box *containing_block,
int *top, int *right, int *bottom, int *left);
@@ -139,14 +140,12 @@
* \return true on success, false on memory exhaustion
*/
-bool layout_document(struct content *content, int width, int height)
+bool layout_document(html_content *content, int width, int height)
{
bool ret;
- struct box *doc = content->data.html.layout;
- const struct font_functions *font_func = content->data.html.font_func;
+ struct box *doc = content->layout;
+ const struct font_functions *font_func = content->font_func;
- assert(content->type == CONTENT_HTML);
-
layout_minmax_block(doc, font_func);
layout_block_find_dimensions(width, height, 0, 0, doc);
@@ -202,7 +201,7 @@
*/
bool layout_block_context(struct box *block, int viewport_height,
- struct content *content)
+ html_content *content)
{
struct box *box;
int cx, cy; /**< current coordinates */
@@ -1264,8 +1263,8 @@
overflow = css_computed_overflow(box->style);
if (overflow == CSS_OVERFLOW_SCROLL || overflow == CSS_OVERFLOW_AUTO ||
- (box->object &&
- content_get_type(box->object) == CONTENT_HTML)) {
+ (box->object && content_get_type(box->object) ==
+ CONTENT_HTML)) {
/* make space for scrollbars, unless height/width are AUTO */
if (which == BOTTOM && box->height != AUTO &&
(overflow == CSS_OVERFLOW_SCROLL ||
@@ -1987,7 +1986,7 @@
*/
bool layout_inline_container(struct box *inline_container, int width,
- struct box *cont, int cx, int cy, struct content *content)
+ struct box *cont, int cx, int cy, html_content *content)
{
bool first_line = true;
bool has_text_children;
@@ -2141,13 +2140,13 @@
* containing the text after new_length excluding the initial space character.
*/
-static bool layout_text_box_split(struct content *content,
+static bool layout_text_box_split(html_content *content,
plot_font_style_t *fstyle, struct box *split_box,
size_t new_length, int new_width)
{
int space_width = split_box->space;
struct box *c2;
- const struct font_functions *font_func = content->data.html.font_func;
+ const struct font_functions *font_func = content->font_func;
if (space_width == 0) {
/* Currently split_box has no space. */
@@ -2226,7 +2225,7 @@
bool layout_line(struct box *first, int *width, int *y,
int cx, int cy, struct box *cont, bool indent,
bool has_text_children,
- struct content *content, struct box **next_box)
+ html_content *content, struct box **next_box)
{
int height, used_height;
int x0 = 0;
@@ -2244,7 +2243,7 @@
int space_before = 0, space_after = 0;
unsigned int inline_count = 0;
unsigned int i;
- const struct font_functions *font_func = content->data.html.font_func;
+ const struct font_functions *font_func = content->font_func;
plot_font_style_t fstyle;
#ifdef LAYOUT_DEBUG
@@ -3233,7 +3232,7 @@
* \return true on success, false on memory exhaustion
*/
-bool layout_float(struct box *b, int width, struct content *content)
+bool layout_float(struct box *b, int width, html_content *content)
{
assert(b->type == BOX_TABLE || b->type == BOX_BLOCK ||
b->type == BOX_INLINE_BLOCK);
@@ -3313,7 +3312,7 @@
*/
bool layout_table(struct box *table, int available_width,
- struct content *content)
+ html_content *content)
{
unsigned int columns = table->columns; /* total columns */
unsigned int i;
@@ -4363,7 +4362,7 @@
bool layout_position_absolute(struct box *box,
struct box *containing_block,
int cx, int cy,
- struct content *content)
+ html_content *content)
{
struct box *c;
@@ -4430,7 +4429,7 @@
bool layout_absolute(struct box *box, struct box *containing_block,
int cx, int cy,
- struct content *content)
+ html_content *content)
{
int static_left, static_top; /* static position */
int top, right, bottom, left;
Index: render/textplain.h
===================================================================
--- render/textplain.h (revision 12276)
+++ render/textplain.h (working copy)
@@ -32,37 +32,9 @@
struct http_parameter;
struct rect;
-struct textplain_line {
- size_t start;
- size_t length;
-};
+nserror textplain_init(void);
+void textplain_fini(void);
-struct content_textplain_data {
- char *encoding;
- void *inputstream;
- char *utf8_data;
- size_t utf8_data_size;
- size_t utf8_data_allocated;
- unsigned long physical_line_count;
- struct textplain_line *physical_line;
- int formatted_width;
-};
-
-bool textplain_create(struct content *c, const struct http_parameter *params);
-bool textplain_process_data(struct content *c,
- const char *data, unsigned int size);
-bool textplain_convert(struct content *c);
-void textplain_mouse_track(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y);
-void textplain_mouse_action(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y);
-void textplain_reformat(struct content *c, int width, int height);
-void textplain_destroy(struct content *c);
-bool textplain_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool textplain_clone(const struct content *old, struct content *new_content);
-
/* access to lines for text selection and searching */
unsigned long textplain_line_count(struct hlcache_handle *h);
size_t textplain_size(struct hlcache_handle *h);
Index: render/imagemap.c
===================================================================
--- render/imagemap.c (revision 12276)
+++ render/imagemap.c (working copy)
@@ -27,6 +27,7 @@
#include "content/content_protected.h"
#include "content/hlcache.h"
#include "render/box.h"
+#include "render/html_internal.h"
#include "render/imagemap.h"
#include "utils/log.h"
#include "utils/utils.h"
@@ -71,10 +72,10 @@
struct imagemap *next; /**< next entry in this hash chain */
};
-static bool imagemap_add(struct content *c, const char *key,
+static bool imagemap_add(html_content *c, const char *key,
struct mapentry *list);
-static bool imagemap_create(struct content *c);
-static bool imagemap_extract_map(xmlNode *node, struct content *c,
+static bool imagemap_create(html_content *c);
+static bool imagemap_extract_map(xmlNode *node, html_content *c,
struct mapentry **entry);
static bool imagemap_addtolist(xmlNode *n, char *base_url,
struct mapentry **entry);
@@ -92,13 +93,12 @@
* \param list List of map regions
* \return true on succes, false otherwise
*/
-bool imagemap_add(struct content *c, const char *key, struct mapentry *list)
+bool imagemap_add(html_content *c, const char *key, struct mapentry *list)
{
struct imagemap *map;
unsigned int slot;
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
assert(key != NULL);
assert(list != NULL);
@@ -119,8 +119,8 @@
slot = imagemap_hash(key);
- map->next = c->data.html.imagemaps[slot];
- c->data.html.imagemaps[slot] = map;
+ map->next = c->imagemaps[slot];
+ c->imagemaps[slot] = map;
return true;
}
@@ -131,15 +131,13 @@
* \param c The containing content
* \return true on success, false otherwise
*/
-bool imagemap_create(struct content *c)
+bool imagemap_create(html_content *c)
{
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
- if (c->data.html.imagemaps == NULL) {
- c->data.html.imagemaps = calloc(HASH_SIZE,
- sizeof(struct imagemap));
- if (c->data.html.imagemaps == NULL) {
+ if (c->imagemaps == NULL) {
+ c->imagemaps = calloc(HASH_SIZE, sizeof(struct imagemap));
+ if (c->imagemaps == NULL) {
return false;
}
}
@@ -152,21 +150,20 @@
*
* \param c The containing content
*/
-void imagemap_destroy(struct content *c)
+void imagemap_destroy(html_content *c)
{
unsigned int i;
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
/* no imagemaps -> return */
- if (c->data.html.imagemaps == NULL)
+ if (c->imagemaps == NULL)
return;
for (i = 0; i != HASH_SIZE; i++) {
struct imagemap *map, *next;
- map = c->data.html.imagemaps[i];
+ map = c->imagemaps[i];
while (map != NULL) {
next = map->next;
imagemap_freelist(map->list);
@@ -176,7 +173,7 @@
}
}
- free(c->data.html.imagemaps);
+ free(c->imagemaps);
}
/**
@@ -184,23 +181,22 @@
*
* \param c The containing content
*/
-void imagemap_dump(struct content *c)
+void imagemap_dump(html_content *c)
{
unsigned int i;
int j;
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
- if (c->data.html.imagemaps == NULL)
+ if (c->imagemaps == NULL)
return;
for (i = 0; i != HASH_SIZE; i++) {
struct imagemap *map;
struct mapentry *entry;
- map = c->data.html.imagemaps[i];
+ map = c->imagemaps[i];
while (map != NULL) {
LOG(("Imagemap: %s", map->key));
@@ -248,7 +244,7 @@
* \param c The containing content
* \return false on memory exhaustion, true otherwise
*/
-bool imagemap_extract(xmlNode *node, struct content *c)
+bool imagemap_extract(xmlNode *node, html_content *c)
{
xmlNode *this_node;
struct mapentry *entry = NULL;
@@ -306,7 +302,7 @@
* \param entry List of map entries
* \return false on memory exhaustion, true otherwise
*/
-bool imagemap_extract_map(xmlNode *node, struct content *c,
+bool imagemap_extract_map(xmlNode *node, html_content *c,
struct mapentry **entry)
{
xmlNode *this_node;
@@ -320,7 +316,7 @@
*/
if (strcmp((const char *) node->name, "area") == 0 ||
strcmp((const char *) node->name, "a") == 0) {
- if (imagemap_addtolist(node, c->data.html.base_url,
+ if (imagemap_addtolist(node, c->base_url,
entry) == false)
return false;
}
@@ -641,24 +637,23 @@
unsigned long click_x, unsigned long click_y,
const char **target)
{
- struct content *c = hlcache_handle_get_content(h);
+ html_content *c = (html_content *) hlcache_handle_get_content(h);
unsigned int slot = 0;
struct imagemap *map;
struct mapentry *entry;
unsigned long cx, cy;
assert(c != NULL);
- assert(c->type == CONTENT_HTML);
if (key == NULL)
return NULL;
- if (c->data.html.imagemaps == NULL)
+ if (c->imagemaps == NULL)
return NULL;
slot = imagemap_hash(key);
- for (map = c->data.html.imagemaps[slot]; map != NULL; map = map->next) {
+ for (map = c->imagemaps[slot]; map != NULL; map = map->next) {
if (map->key != NULL && strcasecmp(map->key, key) == 0)
break;
}
Index: render/layout.h
===================================================================
--- render/layout.h (revision 12276)
+++ render/layout.h (working copy)
@@ -28,10 +28,11 @@
#define _NETSURF_RENDER_LAYOUT_H_
struct box;
+struct html_content;
-bool layout_document(struct content *content, int width, int height);
+bool layout_document(struct html_content *content, int width, int height);
bool layout_inline_container(struct box *box, int width,
- struct box *cont, int cx, int cy, struct content *content);
+ struct box *cont, int cx, int cy, struct html_content *content);
void layout_calculate_descendant_bboxes(struct box *box);
void layout_minmax_table(struct box *table,
const struct font_functions *font_func);
Index: render/imagemap.h
===================================================================
--- render/imagemap.h (revision 12276)
+++ render/imagemap.h (working copy)
@@ -21,12 +21,12 @@
#include <libxml/HTMLtree.h>
-struct content;
+struct html_content;
struct hlcache_handle;
-void imagemap_destroy(struct content *c);
-void imagemap_dump(struct content *c);
-bool imagemap_extract(xmlNode *node, struct content *c);
+void imagemap_destroy(struct html_content *c);
+void imagemap_dump(struct html_content *c);
+bool imagemap_extract(xmlNode *node, struct html_content *c);
const char *imagemap_get(struct hlcache_handle *h, const char *key,
unsigned long x, unsigned long y,
Index: render/box.c
===================================================================
--- render/box.c (revision 12276)
+++ render/box.c (working copy)
@@ -35,7 +35,7 @@
#include "desktop/options.h"
#include "render/box.h"
#include "render/form.h"
-#include "render/html.h"
+#include "render/html_internal.h"
#include "utils/log.h"
#include "utils/talloc.h"
#include "utils/utils.h"
@@ -563,17 +563,13 @@
struct box *box_object_at_point(hlcache_handle *h, int x, int y)
{
- struct content *c = hlcache_handle_get_content(h);
struct box *box;
int box_x = 0, box_y = 0;
hlcache_handle *content = h;
struct box *object_box = 0;
- assert(c != NULL);
- assert(c->type == CONTENT_HTML);
+ box = html_get_box_tree(h);
- 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)
@@ -597,17 +593,13 @@
struct box *box_href_at_point(hlcache_handle *h, int x, int y)
{
- struct content *c = hlcache_handle_get_content(h);
struct box *box;
int box_x = 0, box_y = 0;
hlcache_handle *content = h;
struct box *href_box = 0;
- assert(c != NULL);
- assert(c->type == CONTENT_HTML);
+ box = html_get_box_tree(h);
- 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)
@@ -804,7 +796,7 @@
{
struct box *text_box = NULL;
- if (h && content_get_type(h) == CONTENT_HTML) {
+ if (h != NULL && content_get_type(h) == CONTENT_HTML) {
struct box *box = html_get_box_tree(h);
int nr_xd, nr_yd;
int bx = box->margin[LEFT];
Index: render/box_construct.c
===================================================================
--- render/box_construct.c (revision 12276)
+++ render/box_construct.c (working copy)
@@ -42,7 +42,7 @@
#include "desktop/options.h"
#include "render/box.h"
#include "render/form.h"
-#include "render/html.h"
+#include "render/html_internal.h"
#include "desktop/gui.h"
#include "utils/locale.h"
#include "utils/log.h"
@@ -52,45 +52,7 @@
#include "utils/utils.h"
-static const content_type image_types[] = {
-#ifdef WITH_JPEG
- CONTENT_JPEG,
-#endif
-#ifdef WITH_GIF
- CONTENT_GIF,
-#endif
-#ifdef WITH_BMP
- CONTENT_BMP,
-#endif
-#if defined(WITH_MNG) || defined(WITH_PNG)
- CONTENT_PNG,
-#endif
-#ifdef WITH_MNG
- CONTENT_JNG,
- CONTENT_MNG,
-#endif
-#if defined(WITH_NS_SVG) || defined(WITH_RSVG)
- CONTENT_SVG,
-#endif
-#if defined(WITH_SPRITE) || defined(WITH_NSSPRITE)
- CONTENT_SPRITE,
-#endif
-#ifdef WITH_DRAW
- CONTENT_DRAW,
-#endif
-#ifdef WITH_ARTWORKS
- CONTENT_ARTWORKS,
-#endif
-#ifdef WITH_WEBP
- CONTENT_WEBP,
-#endif
-#ifdef WITH_AMIGA_ICON
- CONTENT_AMIGA_ICON,
-#endif
-#ifdef WITH_APPLE_IMAGE
- CONTENT_APPLE_IMAGE,
-#endif
- CONTENT_UNKNOWN };
+static const content_type image_types = CONTENT_IMAGE;
/* the strings are not important, since we just compare the pointers */
const char *TARGET_SELF = "_self";
@@ -98,25 +60,25 @@
const char *TARGET_TOP = "_top";
const char *TARGET_BLANK = "_blank";
-static bool convert_xml_to_box(xmlNode *n, struct content *content,
+static bool convert_xml_to_box(xmlNode *n, html_content *content,
const css_computed_style *parent_style,
struct box *parent, struct box **inline_container,
char *href, const char *target, char *title);
-bool box_construct_element(xmlNode *n, struct content *content,
+bool box_construct_element(xmlNode *n, html_content *content,
const css_computed_style *parent_style,
struct box *parent, struct box **inline_container,
char *href, const char *target, char *title);
-void box_construct_generate(xmlNode *n, struct content *content,
+void box_construct_generate(xmlNode *n, html_content *content,
struct box *box, const css_computed_style *style);
-bool box_construct_text(xmlNode *n, struct content *content,
+bool box_construct_text(xmlNode *n, html_content *content,
const css_computed_style *parent_style,
struct box *parent, struct box **inline_container,
char *href, const char *target, char *title);
-static css_select_results * box_get_style(struct content *c,
+static css_select_results * box_get_style(html_content *c,
const css_computed_style *parent_style, xmlNode *n);
static void box_text_transform(char *s, unsigned int len,
enum css_text_transform_e tt);
-#define BOX_SPECIAL_PARAMS xmlNode *n, struct content *content, \
+#define BOX_SPECIAL_PARAMS xmlNode *n, html_content *content, \
struct box *box, bool *convert_children
static bool box_a(BOX_SPECIAL_PARAMS);
static bool box_body(BOX_SPECIAL_PARAMS);
@@ -129,7 +91,7 @@
static bool box_button(BOX_SPECIAL_PARAMS);
static bool box_frameset(BOX_SPECIAL_PARAMS);
static bool box_create_frameset(struct content_html_frames *f, xmlNode *n,
- struct content *content);
+ html_content *content);
static bool box_select_add_option(struct form_control *control, xmlNode *n);
static bool box_object(BOX_SPECIAL_PARAMS);
static bool box_embed(BOX_SPECIAL_PARAMS);
@@ -173,13 +135,11 @@
* \return true on success, false on memory exhaustion
*/
-bool xml_to_box(xmlNode *n, struct content *c)
+bool xml_to_box(xmlNode *n, html_content *c)
{
struct box root;
struct box *inline_container = NULL;
- assert(c->type == CONTENT_HTML);
-
root.type = BOX_BLOCK;
root.style = NULL;
root.next = NULL;
@@ -198,8 +158,8 @@
if (!box_normalise_block(&root, c))
return false;
- c->data.html.layout = root.children;
- c->data.html.layout->parent = NULL;
+ c->layout = root.children;
+ c->layout->parent = NULL;
return true;
}
@@ -243,7 +203,7 @@
* \return true on success, false on memory exhaustion
*/
-bool convert_xml_to_box(xmlNode *n, struct content *content,
+bool convert_xml_to_box(xmlNode *n, html_content *content,
const css_computed_style *parent_style,
struct box *parent, struct box **inline_container,
char *href, const char *target, char *title)
@@ -277,7 +237,7 @@
* \return true on success, false on memory exhaustion
*/
-bool box_construct_element(xmlNode *n, struct content *content,
+bool box_construct_element(xmlNode *n, html_content *content,
const css_computed_style *parent_style,
struct box *parent, struct box **inline_container,
char *href, const char *target, char *title)
@@ -543,7 +503,7 @@
if (!html_fetch_object(content,
lwc_string_data(image_uri),
marker, image_types,
- content->available_width,
+ content->base.available_width,
1000, false))
return false;
}
@@ -607,7 +567,7 @@
bgimage_uri != NULL) {
if (!html_fetch_object(content,
lwc_string_data(bgimage_uri),
- box, image_types, content->available_width,
+ box, image_types, content->base.available_width,
1000, true))
return false;
}
@@ -645,7 +605,7 @@
* We don't actually support generated content yet.
*/
-void box_construct_generate(xmlNode *n, struct content *content,
+void box_construct_generate(xmlNode *n, html_content *content,
struct box *box, const css_computed_style *style)
{
struct box *gen = NULL;
@@ -694,7 +654,7 @@
* \return true on success, false on memory exhaustion
*/
-bool box_construct_text(xmlNode *n, struct content *content,
+bool box_construct_text(xmlNode *n, html_content *content,
const css_computed_style *parent_style,
struct box *parent, struct box **inline_container,
char *href, const char *target, char *title)
@@ -915,7 +875,7 @@
* \param n node in xml tree
* \return the new style, or NULL on memory exhaustion
*/
-css_select_results *box_get_style(struct content *c,
+css_select_results *box_get_style(html_content *c,
const css_computed_style *parent_style, xmlNode *n)
{
char *s;
@@ -923,13 +883,14 @@
css_error error;
css_stylesheet *inline_style = NULL;
css_select_results *styles;
+ nscss_select_ctx ctx;
/* Firstly, construct inline stylesheet, if any */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "style"))) {
inline_style = nscss_create_inline_style(
(uint8_t *) s, strlen(s),
- c->data.html.encoding, content__get_url(c),
- c->data.html.quirks != BINDING_QUIRKS_MODE_NONE,
+ c->encoding, content__get_url(&c->base),
+ c->quirks != BINDING_QUIRKS_MODE_NONE,
box_style_alloc, NULL);
xmlFree(s);
@@ -938,8 +899,13 @@
return NULL;
}
+ /* Populate selection context */
+ ctx.ctx = c->select_ctx;
+ ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL);
+ ctx.base_url = c->base_url;
+
/* Select partial style for element */
- styles = nscss_get_style(c, n, CSS_MEDIA_SCREEN, inline_style,
+ styles = nscss_get_style(&ctx, n, CSS_MEDIA_SCREEN, inline_style,
box_style_alloc, NULL);
/* No longer need inline style */
@@ -1066,9 +1032,9 @@
css_computed_background_color(box->style, &color);
if (nscss_color_is_transparent(color))
- content->data.html.background_colour = NS_TRANSPARENT;
+ content->background_colour = NS_TRANSPARENT;
else
- content->data.html.background_colour = nscss_color_to_ns(color);
+ content->background_colour = nscss_color_to_ns(color);
return true;
}
@@ -1106,7 +1072,7 @@
if ((s = xmlGetProp(n, (const xmlChar *) "href"))) {
ok = box_extract_link((const char *) s,
- content->data.html.base_url, &url);
+ content->base_url, &url);
xmlFree(s);
if (!ok)
return false;
@@ -1191,7 +1157,7 @@
/* get image URL */
if (!(src = xmlGetProp(n, (const xmlChar *) "src")))
return true;
- if (!box_extract_link((char *) src, content->data.html.base_url, &url))
+ if (!box_extract_link((char *) src, content->base_url, &url))
return false;
xmlFree(src);
if (!url)
@@ -1199,7 +1165,7 @@
/* start fetch */
ok = html_fetch_object(content, url, box, image_types,
- content->available_width, 1000, false);
+ content->base.available_width, 1000, false);
free(url);
wtype = css_computed_width(box->style, &value, &wunit);
@@ -1250,13 +1216,13 @@
* (codebase is the base for the other two) */
if ((codebase = xmlGetProp(n, (const xmlChar *) "codebase"))) {
if (!box_extract_link((char *) codebase,
- content->data.html.base_url,
+ content->base_url,
¶ms->codebase))
return false;
xmlFree(codebase);
}
if (!params->codebase)
- params->codebase = content->data.html.base_url;
+ params->codebase = content->base_url;
if ((classid = xmlGetProp(n, (const xmlChar *) "classid"))) {
if (!box_extract_link((char *) classid, params->codebase,
@@ -1277,14 +1243,10 @@
return true;
/* Don't include ourself */
- if (params->classid &&
- strcmp(content->data.html.base_url,
- params->classid) == 0)
+ if (params->classid && strcmp(content->base_url, params->classid) == 0)
return true;
- if (params->data &&
- strcmp(content->data.html.base_url,
- params->data) == 0)
+ if (params->data && strcmp(content->base_url, params->data) == 0)
return true;
/* codetype and type are MIME types */
@@ -1298,12 +1260,14 @@
* !classid && !data => invalid; ignored */
if (params->classid && !params->data && params->codetype &&
- content_lookup(params->codetype) == CONTENT_OTHER)
+ content_factory_type_from_mime_type(params->codetype) ==
+ CONTENT_NONE)
/* can't handle this MIME type */
return true;
if (params->data && params->type &&
- content_lookup(params->type) == CONTENT_OTHER)
+ content_factory_type_from_mime_type(params->type) ==
+ CONTENT_NONE)
/* can't handle this MIME type */
return true;
@@ -1349,7 +1313,8 @@
/* start fetch (MIME type is ok or not specified) */
if (!html_fetch_object(content,
params->data ? params->data : params->classid,
- box, 0, content->available_width, 1000, false))
+ box, CONTENT_ANY, content->base.available_width, 1000,
+ false))
return false;
*convert_children = false;
@@ -1503,7 +1468,7 @@
{
bool ok;
- if (content->data.html.frameset) {
+ if (content->frameset) {
LOG(("Error: multiple framesets in document."));
/* Don't convert children */
if (convert_children)
@@ -1513,12 +1478,11 @@
return true;
}
- content->data.html.frameset = talloc_zero(content,
- struct content_html_frames);
- if (!content->data.html.frameset)
+ content->frameset = talloc_zero(content, struct content_html_frames);
+ if (!content->frameset)
return false;
- ok = box_create_frameset(content->data.html.frameset, n, content);
+ ok = box_create_frameset(content->frameset, n, content);
if (ok)
box->type = BOX_NONE;
@@ -1528,7 +1492,7 @@
}
bool box_create_frameset(struct content_html_frames *f, xmlNode *n,
- struct content *content) {
+ html_content *content) {
unsigned int row, col, index, i;
unsigned int rows = 1, cols = 1;
char *s, *url;
@@ -1645,15 +1609,14 @@
url = NULL;
if ((s = (char *) xmlGetProp(c,
(const xmlChar *) "src"))) {
- box_extract_link(s, content->data.html.base_url,
- &url);
+ box_extract_link(s, content->base_url, &url);
xmlFree(s);
}
/* copy url */
if (url) {
/* no self-references */
- if (strcmp(content->data.html.base_url, url))
+ if (strcmp(content->base_url, url))
frame->url = talloc_strdup(content,
url);
free(url);
@@ -1738,7 +1701,7 @@
if (!(s = (char *) xmlGetProp(n,
(const xmlChar *) "src")))
return true;
- if (!box_extract_link(s, content->data.html.base_url, &url)) {
+ if (!box_extract_link(s, content->base_url, &url)) {
xmlFree(s);
return false;
}
@@ -1747,7 +1710,7 @@
return true;
/* don't include ourself */
- if (strcmp(content->data.html.base_url, url) == 0) {
+ if (strcmp(content->base_url, url) == 0) {
free(url);
return true;
}
@@ -1767,17 +1730,15 @@
iframe->border = true;
/* Add this iframe to the linked list of iframes */
- iframe->next = content->data.html.iframe;
- content->data.html.iframe = iframe;
+ iframe->next = content->iframe;
+ content->iframe = iframe;
/* fill in specified values */
- if ((s = (char *) xmlGetProp(n,
- (const xmlChar *) "name"))) {
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name"))) {
iframe->name = talloc_strdup(content, s);
xmlFree(s);
}
- if ((s = (char *) xmlGetProp(n,
- (const xmlChar *) "frameborder"))) {
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "frameborder"))) {
i = atoi(s);
iframe->border = (i != 0);
xmlFree(s);
@@ -1790,21 +1751,18 @@
xmlFree(s);
}
- if ((s = (char *) xmlGetProp(n,
- (const xmlChar *) "scrolling"))) {
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "scrolling"))) {
if (!strcasecmp(s, "yes"))
iframe->scrolling = SCROLLING_YES;
else if (!strcasecmp(s, "no"))
iframe->scrolling = SCROLLING_NO;
xmlFree(s);
}
- if ((s = (char *) xmlGetProp(n,
- (const xmlChar *) "marginwidth"))) {
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "marginwidth"))) {
iframe->margin_width = atoi(s);
xmlFree(s);
}
- if ((s = (char *) xmlGetProp(n,
- (const xmlChar *) "marginheight"))) {
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "marginheight"))) {
iframe->margin_height = atoi(s);
xmlFree(s);
}
@@ -1835,8 +1793,7 @@
type = (char *) xmlGetProp(n, (const xmlChar *) "type");
- gadget = binding_get_control_for_node(content->data.html.parser_binding,
- n);
+ gadget = binding_get_control_for_node(content->parser_binding, n);
if (!gadget)
goto no_memory;
box->gadget = gadget;
@@ -1901,8 +1858,7 @@
n->parent == NULL) != CSS_DISPLAY_NONE) {
if ((s = (char *) xmlGetProp(n,
(const xmlChar*) "src"))) {
- res = url_join(s,
- content->data.html.base_url, &url);
+ res = url_join(s, content->base_url, &url);
xmlFree(s);
/* if url is equivalent to the parent's url,
* we've got infinite inclusion. stop it here
@@ -1910,11 +1866,10 @@
*/
if (res == URL_FUNC_OK &&
strcasecmp(url,
- content->data.
- html.base_url) != 0) {
+ content->base_url) != 0) {
if (!html_fetch_object(content, url,
box, image_types,
- content->
+ content->base.
available_width,
1000, false)) {
free(url);
@@ -1997,8 +1952,7 @@
{
struct form_control *gadget;
- gadget = binding_get_control_for_node(content->data.html.parser_binding,
- n);
+ gadget = binding_get_control_for_node(content->parser_binding, n);
if (!gadget)
return false;
@@ -2024,8 +1978,7 @@
struct form_control *gadget;
xmlNode *c, *c2;
- gadget = binding_get_control_for_node(content->data.html.parser_binding,
- n);
+ gadget = binding_get_control_for_node(content->parser_binding, n);
if (!gadget)
return false;
@@ -2171,8 +2124,7 @@
size_t len;
box->type = BOX_INLINE_BLOCK;
- box->gadget = binding_get_control_for_node(
- content->data.html.parser_binding, n);
+ box->gadget = binding_get_control_for_node(content->parser_binding, n);
if (!box->gadget)
return false;
box->gadget->box = box;
@@ -2301,15 +2253,14 @@
/* src is a URL */
if (!(src = xmlGetProp(n, (const xmlChar *) "src")))
return true;
- if (!box_extract_link((char *) src, content->data.html.base_url,
- ¶ms->data))
+ if (!box_extract_link((char *) src, content->base_url, ¶ms->data))
return false;
xmlFree(src);
if (!params->data)
return true;
/* Don't include ourself */
- if (strcmp(content->data.html.base_url, params->data) == 0)
+ if (strcmp(content->base_url, params->data) == 0)
return true;
/* add attributes as parameters to linked list */
@@ -2339,8 +2290,8 @@
box->object_params = params;
/* start fetch */
- return html_fetch_object(content, params->data, box, 0,
- content->available_width, 1000, false);
+ return html_fetch_object(content, params->data, box, CONTENT_ANY,
+ content->base.available_width, 1000, false);
}
/**
Index: render/box.h
===================================================================
--- render/box.h (revision 12276)
+++ render/box.h (working copy)
@@ -99,8 +99,8 @@
struct column;
struct object_params;
struct object_param;
+struct html_content;
-
#define UNKNOWN_WIDTH INT_MAX
#define UNKNOWN_MAX_WIDTH INT_MAX
@@ -332,8 +332,8 @@
bool box_vscrollbar_present(const struct box *box);
bool box_hscrollbar_present(const struct box *box);
-bool xml_to_box(xmlNode *n, struct content *c);
+bool xml_to_box(xmlNode *n, struct html_content *c);
-bool box_normalise_block(struct box *block, struct content *c);
+bool box_normalise_block(struct box *block, struct html_content *c);
#endif
Index: image/svg.c
===================================================================
--- image/svg.c (revision 12276)
+++ image/svg.c (working copy)
@@ -33,29 +33,145 @@
#include "desktop/plotters.h"
#include "image/svg.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
+typedef struct svg_content {
+ struct content base;
+ struct svgtiny_diagram *diagram;
+ bool done_parse;
+} svg_content;
+
+static nserror svg_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror svg_create_svg_data(svg_content *c);
+static bool svg_convert(struct content *c);
+static void svg_destroy(struct content *c);
+static void svg_reformat(struct content *c, int width, int height);
+static bool svg_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static nserror svg_clone(const struct content *old, struct content **newc);
+static content_type svg_content_type(lwc_string *mime_type);
+
+static const content_handler svg_content_handler = {
+ svg_create,
+ NULL,
+ svg_convert,
+ svg_reformat,
+ svg_destroy,
+ NULL,
+ NULL,
+ NULL,
+ svg_redraw,
+ NULL,
+ NULL,
+ NULL,
+ svg_clone,
+ NULL,
+ svg_content_type,
+ false
+};
+
+static const char *svg_types[] = {
+ "image/svg",
+ "image/svg+xml"
+};
+
+static lwc_string *svg_mime_types[NOF_ELEMENTS(svg_types)];
+
+nserror svg_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(svg_mime_types); i++) {
+ lerror = lwc_intern_string(svg_types[i],
+ strlen(svg_types[i]),
+ &svg_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(svg_mime_types[i],
+ &svg_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ svg_fini();
+
+ return error;
+}
+
+void svg_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(svg_mime_types); i++) {
+ if (svg_mime_types[i] != NULL)
+ lwc_string_unref(svg_mime_types[i]);
+ }
+}
+
/**
* Create a CONTENT_SVG.
*/
-bool svg_create(struct content *c, const struct http_parameter *params)
+nserror svg_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
{
+ svg_content *svg;
+ nserror error;
+
+ svg = talloc_zero(0, svg_content);
+ if (svg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&svg->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(svg);
+ return error;
+ }
+
+ error = svg_create_svg_data(svg);
+ if (error != NSERROR_OK) {
+ talloc_free(svg);
+ return error;
+ }
+
+ *c = (struct content *) svg;
+
+ return NSERROR_OK;
+}
+
+nserror svg_create_svg_data(svg_content *c)
+{
union content_msg_data msg_data;
- c->data.svg.diagram = svgtiny_create();
- if (!c->data.svg.diagram)
+ c->diagram = svgtiny_create();
+ if (c->diagram == NULL)
goto no_memory;
- c->data.svg.done_parse = false;
+ c->done_parse = false;
- return true;
+ return NSERROR_OK;
no_memory:
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
@@ -84,22 +200,23 @@
void svg_reformat(struct content *c, int width, int height)
{
+ svg_content *svg = (svg_content *) c;
const char *source_data;
unsigned long source_size;
- assert(c->data.svg.diagram);
+ assert(svg->diagram);
- if (c->data.svg.done_parse == false) {
+ if (svg->done_parse == false) {
source_data = content__get_source_data(c, &source_size);
- svgtiny_parse(c->data.svg.diagram, source_data, source_size,
+ svgtiny_parse(svg->diagram, source_data, source_size,
content__get_url(c), width, height);
- c->data.svg.done_parse = true;
+ svg->done_parse = true;
}
- c->width = c->data.svg.diagram->width;
- c->height = c->data.svg.diagram->height;
+ c->width = svg->diagram->width;
+ c->height = svg->diagram->height;
}
@@ -111,8 +228,9 @@
int width, int height, const struct rect *clip,
float scale, colour background_colour)
{
+ svg_content *svg = (svg_content *) c;
float transform[6];
- struct svgtiny_diagram *diagram = c->data.svg.diagram;
+ struct svgtiny_diagram *diagram = svg->diagram;
bool ok;
int px, py;
unsigned int i;
@@ -173,25 +291,51 @@
void svg_destroy(struct content *c)
{
- if (c->data.svg.diagram)
- svgtiny_free(c->data.svg.diagram);
+ svg_content *svg = (svg_content *) c;
+
+ if (svg->diagram != NULL)
+ svgtiny_free(svg->diagram);
}
-bool svg_clone(const struct content *old, struct content *new_content)
+nserror svg_clone(const struct content *old, struct content **newc)
{
+ svg_content *svg;
+ nserror error;
+
+ svg = talloc_zero(0, svg_content);
+ if (svg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &svg->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&svg->base);
+ return error;
+ }
+
/* Simply replay create/convert */
- if (svg_create(new_content, NULL) == false)
- return false;
+ error = svg_create_svg_data(svg);
+ if (error != NSERROR_OK) {
+ content_destroy(&svg->base);
+ return error;
+ }
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (svg_convert(new_content) == false)
- return false;
+ if (svg_convert(&svg->base) == false) {
+ content_destroy(&svg->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) svg;
+
+ return NSERROR_OK;
}
+content_type svg_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
#endif /* WITH_NS_SVG */
Index: image/webp.h
===================================================================
--- image/webp.h (revision 12276)
+++ image/webp.h (working copy)
@@ -28,20 +28,16 @@
#include <stdbool.h>
-struct content;
-struct rect;
+#include "utils/errors.h"
-struct content_webp_data {
-/* empty */
-};
+nserror webp_init(void);
+void webp_fini(void);
-bool webp_convert(struct content *c);
-void webp_destroy(struct content *c);
-bool webp_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool webp_clone(const struct content *old, struct content *new_content);
+#else
+#define webp_init() NSERROR_OK
+#define webp_fini() ((void) 0)
+
#endif /* WITH_WEBP */
#endif
Index: image/svg.h
===================================================================
--- image/svg.h (revision 12276)
+++ image/svg.h (working copy)
@@ -23,25 +23,22 @@
#ifndef _NETSURF_IMAGE_SVG_H_
#define _NETSURF_IMAGE_SVG_H_
+#include "utils/config.h"
+
+#ifdef WITH_NS_SVG
+
#include <stdbool.h>
-struct content;
-struct http_parameter;
-struct svgtiny_diagram;
-struct rect;
+#include "utils/errors.h"
-struct content_svg_data {
- struct svgtiny_diagram *diagram;
- bool done_parse;
-};
+nserror svg_init(void);
+void svg_fini(void);
-bool svg_create(struct content *c, const struct http_parameter *params);
-bool svg_convert(struct content *c);
-void svg_destroy(struct content *c);
-void svg_reformat(struct content *c, int width, int height);
-bool svg_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool svg_clone(const struct content *old, struct content *new_content);
+#else
+#define svg_init() NSERROR_OK
+#define svg_fini() ((void) 0)
+
#endif
+
+#endif
Index: image/gif.c
===================================================================
--- image/gif.c (revision 12276)
+++ image/gif.c (working copy)
@@ -38,6 +38,7 @@
#include <libnsgif.h>
#include "utils/config.h"
#include "content/content_protected.h"
+#include "content/hlcache.h"
#include "desktop/options.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
@@ -45,8 +46,34 @@
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/schedule.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
+typedef struct nsgif_content {
+ struct content base;
+
+ struct gif_animation *gif; /**< GIF animation data */
+ int current_frame; /**< current frame to display [0...(max-1)] */
+} nsgif_content;
+
+static nserror nsgif_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror nsgif_create_gif_data(nsgif_content *c);
+static bool nsgif_convert(struct content *c);
+static void nsgif_destroy(struct content *c);
+static bool nsgif_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static bool nsgif_redraw_tiled(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror nsgif_clone(const struct content *old, struct content **newc);
+static content_type nsgif_content_type(lwc_string *mime_type);
+
+static void *nsgif_bitmap_create(int width, int height);
static void nsgif_invalidate(void *bitmap, void *private_word);
static void nsgif_animate(void *p);
static gif_result nsgif_get_frame(struct content *c);
@@ -63,39 +90,131 @@
.bitmap_modified = bitmap_modified
};
+static const content_handler nsgif_content_handler = {
+ nsgif_create,
+ NULL,
+ nsgif_convert,
+ NULL,
+ nsgif_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nsgif_redraw,
+ nsgif_redraw_tiled,
+ NULL,
+ NULL,
+ nsgif_clone,
+ NULL,
+ nsgif_content_type,
+ false
+};
-bool nsgif_create(struct content *c, const struct http_parameter *params)
+static const char *nsgif_types[] = {
+ "image/gif"
+};
+
+static lwc_string *nsgif_mime_types[NOF_ELEMENTS(nsgif_types)];
+
+nserror nsgif_init(void)
{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(nsgif_mime_types); i++) {
+ lerror = lwc_intern_string(nsgif_types[i],
+ strlen(nsgif_types[i]),
+ &nsgif_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(nsgif_mime_types[i],
+ &nsgif_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nsgif_fini();
+
+ return error;
+}
+
+void nsgif_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(nsgif_mime_types); i++) {
+ if (nsgif_mime_types[i] != NULL)
+ lwc_string_unref(nsgif_mime_types[i]);
+ }
+}
+
+nserror nsgif_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ nsgif_content *result;
+ nserror error;
+
+ result = talloc_zero(0, nsgif_content);
+ if (result == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&result->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(result);
+ return error;
+ }
+
+ error = nsgif_create_gif_data(result);
+ if (error != NSERROR_OK) {
+ talloc_free(result);
+ return error;
+ }
+
+ *c = (struct content *) result;
+
+ return NSERROR_OK;
+}
+
+nserror nsgif_create_gif_data(nsgif_content *c)
+{
union content_msg_data msg_data;
+
/* Initialise our data structure */
- c->data.gif.gif = calloc(sizeof(gif_animation), 1);
- if (!c->data.gif.gif) {
+ c->gif = calloc(sizeof(gif_animation), 1);
+ if (c->gif == NULL) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
- gif_create(c->data.gif.gif, &gif_bitmap_callbacks);
- return true;
+ gif_create(c->gif, &gif_bitmap_callbacks);
+ return NSERROR_OK;
}
bool nsgif_convert(struct content *c)
{
+ nsgif_content *gif = (nsgif_content *) c;
int res;
- struct gif_animation *gif;
union content_msg_data msg_data;
const char *data;
unsigned long size;
char title[100];
/* Get the animation */
- gif = c->data.gif.gif;
-
data = content__get_source_data(c, &size);
/* Initialise the GIF */
do {
- res = gif_initialise(gif, size, (unsigned char *) data);
+ res = gif_initialise(gif->gif, size, (unsigned char *) data);
if (res != GIF_OK && res != GIF_WORKING &&
res != GIF_INSUFFICIENT_FRAME_DATA) {
switch (res) {
@@ -114,30 +233,31 @@
} while (res != GIF_OK && res != GIF_INSUFFICIENT_FRAME_DATA);
/* Abort on bad GIFs */
- if ((gif->frame_count_partial == 0) || (gif->width == 0) ||
- (gif->height == 0)) {
+ if ((gif->gif->frame_count_partial == 0) || (gif->gif->width == 0) ||
+ (gif->gif->height == 0)) {
msg_data.error = messages_get("BadGIF");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
/* Store our content width and description */
- c->width = gif->width;
- c->height = gif->height;
+ c->width = gif->gif->width;
+ c->height = gif->gif->height;
snprintf(title, sizeof(title), messages_get("GIFTitle"),
c->width, c->height, size);
content__set_title(c, title);
- c->size += (gif->width * gif->height * 4) + 16 + 44;
+ c->size += (gif->gif->width * gif->gif->height * 4) + 16 + 44;
/* Schedule the animation if we have one */
- c->data.gif.current_frame = 0;
- if (gif->frame_count_partial > 1)
- schedule(gif->frames[0].frame_delay, nsgif_animate, c);
+ gif->current_frame = 0;
+ if (gif->gif->frame_count_partial > 1)
+ schedule(gif->gif->frames[0].frame_delay, nsgif_animate, c);
else
- bitmap_set_suspendable(gif->frame_image, gif, nsgif_invalidate);
+ bitmap_set_suspendable(gif->gif->frame_image, gif->gif,
+ nsgif_invalidate);
/* Exit as a success */
- c->bitmap = gif->frame_image;
+ c->bitmap = gif->gif->frame_image;
content_set_ready(c);
content_set_done(c);
/* Done: update status bar */
@@ -156,10 +276,12 @@
int width, int height, const struct rect *clip,
float scale, colour background_colour)
{
- if (c->data.gif.current_frame != c->data.gif.gif->decoded_frame)
+ nsgif_content *gif = (nsgif_content *) c;
+
+ if (gif->current_frame != gif->gif->decoded_frame)
if (nsgif_get_frame(c) != GIF_OK)
return false;
- c->bitmap = c->data.gif.gif->frame_image;
+ c->bitmap = gif->gif->frame_image;
if ((width == -1) && (height == -1))
return true;
return plot.bitmap(x, y, width, height, c->bitmap,
@@ -172,13 +294,14 @@
float scale, colour background_colour,
bool repeat_x, bool repeat_y)
{
+ nsgif_content *gif = (nsgif_content *) c;
bitmap_flags_t flags = BITMAPF_NONE;
- if (c->data.gif.current_frame != c->data.gif.gif->decoded_frame)
+ if (gif->current_frame != gif->gif->decoded_frame)
if (nsgif_get_frame(c) != GIF_OK)
return false;
- c->bitmap = c->data.gif.gif->frame_image;
+ c->bitmap = gif->gif->frame_image;
if (repeat_x)
flags |= BITMAPF_REPEAT_X;
@@ -191,28 +314,54 @@
void nsgif_destroy(struct content *c)
{
+ nsgif_content *gif = (nsgif_content *) c;
+
/* Free all the associated memory buffers */
schedule_remove(nsgif_animate, c);
- gif_finalise(c->data.gif.gif);
- free(c->data.gif.gif);
+ gif_finalise(gif->gif);
+ free(gif->gif);
}
-bool nsgif_clone(const struct content *old, struct content *new_content)
+nserror nsgif_clone(const struct content *old, struct content **newc)
{
+ nsgif_content *gif;
+ nserror error;
+
+ gif = talloc_zero(0, nsgif_content);
+ if (gif == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &gif->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&gif->base);
+ return error;
+ }
+
/* Simply replay creation and conversion of content */
- if (nsgif_create(new_content, NULL) == false)
- return false;
+ error = nsgif_create_gif_data(gif);
+ if (error != NSERROR_OK) {
+ content_destroy(&gif->base);
+ return error;
+ }
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nsgif_convert(new_content) == false)
- return false;
+ if (nsgif_convert(&gif->base) == false) {
+ content_destroy(&gif->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) gif;
+
+ return NSERROR_OK;
}
+content_type nsgif_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
/**
* Updates the GIF bitmap to display the current frame
@@ -221,18 +370,19 @@
*/
gif_result nsgif_get_frame(struct content *c)
{
+ nsgif_content *gif = (nsgif_content *) c;
int previous_frame, current_frame, frame;
gif_result res = GIF_OK;
- current_frame = c->data.gif.current_frame;
+ current_frame = gif->current_frame;
if (!option_animate_images)
current_frame = 0;
- if (current_frame < c->data.gif.gif->decoded_frame)
+ if (current_frame < gif->gif->decoded_frame)
previous_frame = 0;
else
- previous_frame = c->data.gif.gif->decoded_frame + 1;
+ previous_frame = gif->gif->decoded_frame + 1;
for (frame = previous_frame; frame <= current_frame; frame++)
- res = gif_decode_frame(c->data.gif.gif, frame);
+ res = gif_decode_frame(gif->gif, frame);
return res;
}
@@ -245,105 +395,105 @@
*/
void nsgif_animate(void *p)
{
- struct content *c = p;
+ nsgif_content *gif = p;
union content_msg_data data;
- struct gif_animation *gif;
int delay;
int f;
/* Advance by a frame, updating the loop count accordingly */
- gif = c->data.gif.gif;
- c->data.gif.current_frame++;
- if (c->data.gif.current_frame == (int)gif->frame_count_partial) {
- c->data.gif.current_frame = 0;
+ gif->current_frame++;
+ if (gif->current_frame == (int)gif->gif->frame_count_partial) {
+ gif->current_frame = 0;
/* A loop count of 0 has a special meaning of infinite */
- if (gif->loop_count != 0) {
- gif->loop_count--;
- if (gif->loop_count == 0) {
- c->data.gif.current_frame =
- gif->frame_count_partial - 1;
- gif->loop_count = -1;
+ if (gif->gif->loop_count != 0) {
+ gif->gif->loop_count--;
+ if (gif->gif->loop_count == 0) {
+ gif->current_frame =
+ gif->gif->frame_count_partial - 1;
+ gif->gif->loop_count = -1;
}
}
}
/* Continue animating if we should */
- if (gif->loop_count >= 0) {
- delay = gif->frames[c->data.gif.current_frame].frame_delay;
+ if (gif->gif->loop_count >= 0) {
+ delay = gif->gif->frames[gif->current_frame].frame_delay;
if (delay < option_minimum_gif_delay)
delay = option_minimum_gif_delay;
- schedule(delay, nsgif_animate, c);
+ schedule(delay, nsgif_animate, gif);
}
if ((!option_animate_images) ||
- (!gif->frames[c->data.gif.current_frame].display))
+ (!gif->gif->frames[gif->current_frame].display))
return;
/* area within gif to redraw */
- f = c->data.gif.current_frame;
- data.redraw.x = gif->frames[f].redraw_x;
- data.redraw.y = gif->frames[f].redraw_y;
- data.redraw.width = gif->frames[f].redraw_width;
- data.redraw.height = gif->frames[f].redraw_height;
+ f = gif->current_frame;
+ data.redraw.x = gif->gif->frames[f].redraw_x;
+ data.redraw.y = gif->gif->frames[f].redraw_y;
+ data.redraw.width = gif->gif->frames[f].redraw_width;
+ data.redraw.height = gif->gif->frames[f].redraw_height;
/* redraw background (true) or plot on top (false) */
- if (c->data.gif.current_frame > 0) {
- data.redraw.full_redraw = gif->frames[f - 1].redraw_required;
+ if (gif->current_frame > 0) {
+ data.redraw.full_redraw =
+ gif->gif->frames[f - 1].redraw_required;
/* previous frame needed clearing: expand the redraw area to
* cover it */
if (data.redraw.full_redraw) {
if (data.redraw.x >
- (int)(gif->frames[f - 1].redraw_x)) {
+ (int)(gif->gif->frames[f - 1].redraw_x)) {
data.redraw.width += data.redraw.x -
- gif->frames[f - 1].redraw_x;
- data.redraw.x = gif->frames[f - 1].redraw_x;
+ gif->gif->frames[f - 1].redraw_x;
+ data.redraw.x =
+ gif->gif->frames[f - 1].redraw_x;
}
if (data.redraw.y >
- (int)(gif->frames[f - 1].redraw_y)) {
+ (int)(gif->gif->frames[f - 1].redraw_y)) {
data.redraw.height += (data.redraw.y -
- gif->frames[f - 1].redraw_y);
- data.redraw.y = gif->frames[f - 1].redraw_y;
+ gif->gif->frames[f - 1].redraw_y);
+ data.redraw.y =
+ gif->gif->frames[f - 1].redraw_y;
}
- if ((int)(gif->frames[f - 1].redraw_x +
- gif->frames[f - 1].redraw_width) >
+ if ((int)(gif->gif->frames[f - 1].redraw_x +
+ gif->gif->frames[f - 1].redraw_width) >
(data.redraw.x + data.redraw.width))
data.redraw.width =
- gif->frames[f - 1].redraw_x -
- data.redraw.x +
- gif->frames[f - 1].redraw_width;
- if ((int)(gif->frames[f - 1].redraw_y +
- gif->frames[f - 1].redraw_height) >
+ gif->gif->frames[f - 1].redraw_x -
+ data.redraw.x +
+ gif->gif->frames[f - 1].redraw_width;
+ if ((int)(gif->gif->frames[f - 1].redraw_y +
+ gif->gif->frames[f - 1].redraw_height) >
(data.redraw.y + data.redraw.height))
data.redraw.height =
- gif->frames[f - 1].redraw_y -
- data.redraw.y +
- gif->frames[f - 1].
- redraw_height;
+ gif->gif->frames[f - 1].redraw_y -
+ data.redraw.y +
+ gif->gif->frames[f - 1].redraw_height;
}
} else {
/* do advanced check */
if ((data.redraw.x == 0) && (data.redraw.y == 0) &&
- (data.redraw.width == (int)(gif->width)) &&
- (data.redraw.height == (int)(gif->height))) {
- data.redraw.full_redraw = !gif->frames[f].opaque;
+ (data.redraw.width == (int)(gif->gif->width)) &&
+ (data.redraw.height == (int)(gif->gif->height))) {
+ data.redraw.full_redraw = !gif->gif->frames[f].opaque;
} else {
data.redraw.full_redraw = true;
data.redraw.x = 0;
data.redraw.y = 0;
- data.redraw.width = gif->width;
- data.redraw.height = gif->height;
+ data.redraw.width = gif->gif->width;
+ data.redraw.height = gif->gif->height;
}
}
/* other data */
- data.redraw.object = c;
+ data.redraw.object = (struct content *) gif;
data.redraw.object_x = 0;
data.redraw.object_y = 0;
- data.redraw.object_width = c->width;
- data.redraw.object_height = c->height;
+ data.redraw.object_width = gif->base.width;
+ data.redraw.object_height = gif->base.height;
- content_broadcast(c, CONTENT_MSG_REDRAW, data);
+ content_broadcast(&gif->base, CONTENT_MSG_REDRAW, data);
}
Index: image/nssprite.c
===================================================================
--- image/nssprite.c (revision 12276)
+++ image/nssprite.c (working copy)
@@ -29,13 +29,33 @@
#include <stdlib.h>
#include <librosprite.h>
#include "utils/config.h"
+#include "content/content_protected.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
-#include "content/content_protected.h"
+#include "image/nssprite.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
+typedef struct nssprite_content {
+ struct content base;
+
+ struct rosprite_area* sprite_area;
+} nssprite_content;
+
+static nserror nssprite_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool nssprite_convert(struct content *c);
+static void nssprite_destroy(struct content *c);
+static bool nssprite_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static nserror nssprite_clone(const struct content *old, struct content **newc);
+static content_type nssprite_content_type(lwc_string *mime_type);
+
#define ERRCHK(x) do { \
rosprite_error err = x; \
if (err == ROSPRITE_EOF) { \
@@ -50,6 +70,94 @@
} \
} while(0)
+static const content_handler nssprite_content_handler = {
+ nssprite_create,
+ NULL,
+ nssprite_convert,
+ NULL,
+ nssprite_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nssprite_redraw,
+ NULL,
+ NULL,
+ NULL,
+ nssprite_clone,
+ NULL,
+ nssprite_content_type,
+ false
+};
+
+static const char *nssprite_types[] = {
+ "image/x-riscos-sprite"
+};
+
+static lwc_string *nssprite_mime_types[NOF_ELEMENTS(nssprite_types)];
+
+nserror nssprite_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(nssprite_mime_types); i++) {
+ lerror = lwc_intern_string(nssprite_types[i],
+ strlen(nssprite_types[i]),
+ &nssprite_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(nssprite_mime_types[i],
+ &nssprite_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nssprite_fini();
+
+ return error;
+}
+
+void nssprite_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(nssprite_mime_types); i++) {
+ if (nssprite_mime_types[i] != NULL)
+ lwc_string_unref(nssprite_mime_types[i]);
+ }
+}
+
+nserror nssprite_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ nssprite_content *sprite;
+ nserror error;
+
+ sprite = talloc_zero(0, nssprite_content);
+ if (sprite == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&sprite->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(sprite);
+ return error;
+ }
+
+ *c = (struct content *) sprite;
+
+ return NSERROR_OK;
+}
+
/**
* Convert a CONTENT_SPRITE for display.
*
@@ -58,6 +166,7 @@
bool nssprite_convert(struct content *c)
{
+ nssprite_content *nssprite = (nssprite_content *) c;
union content_msg_data msg_data;
struct rosprite_mem_context* ctx;
@@ -72,7 +181,7 @@
struct rosprite_area* sprite_area;
ERRCHK(rosprite_load(rosprite_mem_reader, ctx, &sprite_area));
rosprite_destroy_mem_context(ctx);
- c->data.nssprite.sprite_area = sprite_area;
+ nssprite->sprite_area = sprite_area;
assert(sprite_area->sprite_count > 0);
@@ -126,8 +235,10 @@
void nssprite_destroy(struct content *c)
{
- if (c->data.nssprite.sprite_area != NULL)
- rosprite_destroy_sprite_area(c->data.nssprite.sprite_area);
+ nssprite_content *sprite = (nssprite_content *) c;
+
+ if (sprite->sprite_area != NULL)
+ rosprite_destroy_sprite_area(sprite->sprite_area);
if (c->bitmap != NULL)
bitmap_destroy(c->bitmap);
}
@@ -146,16 +257,38 @@
}
-bool nssprite_clone(const struct content *old, struct content *new_content)
+nserror nssprite_clone(const struct content *old, struct content **newc)
{
+ nssprite_content *sprite;
+ nserror error;
+
+ sprite = talloc_zero(0, nssprite_content);
+ if (sprite == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &sprite->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&sprite->base);
+ return error;
+ }
+
/* Simply replay convert */
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nssprite_convert(new_content) == false)
- return false;
+ if (nssprite_convert(&sprite->base) == false) {
+ content_destroy(&sprite->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) sprite;
+
+ return NSERROR_OK;
}
+content_type nssprite_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
+
#endif
Index: image/ico.c
===================================================================
--- image/ico.c (revision 12276)
+++ image/ico.c (working copy)
@@ -33,42 +33,164 @@
#include "content/hlcache.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
+#include "image/bmp.h"
#include "image/ico.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
-bool nsico_create(struct content *c, const struct http_parameter *params)
+typedef struct nsico_content {
+ struct content base;
+
+ struct ico_collection *ico; /** ICO collection data */
+} nsico_content;
+
+static nserror nsico_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror nsico_create_ico_data(nsico_content *c);
+static bool nsico_convert(struct content *c);
+static void nsico_destroy(struct content *c);
+static bool nsico_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static bool nsico_redraw_tiled(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror nsico_clone(const struct content *old, struct content **newc);
+static content_type nsico_content_type(lwc_string *mime_type);
+
+static const content_handler nsico_content_handler = {
+ nsico_create,
+ NULL,
+ nsico_convert,
+ NULL,
+ nsico_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nsico_redraw,
+ nsico_redraw_tiled,
+ NULL,
+ NULL,
+ nsico_clone,
+ NULL,
+ nsico_content_type,
+ false
+};
+
+static const char *nsico_types[] = {
+ "application/ico",
+ "application/x-ico",
+ "image/ico",
+ "image/vnd.microsoft.icon",
+ "image/x-icon"
+};
+
+static lwc_string *nsico_mime_types[NOF_ELEMENTS(nsico_types)];
+
+nserror nsico_init(void)
{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(nsico_mime_types); i++) {
+ lerror = lwc_intern_string(nsico_types[i],
+ strlen(nsico_types[i]),
+ &nsico_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(nsico_mime_types[i],
+ &nsico_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nsico_fini();
+
+ return error;
+}
+
+void nsico_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(nsico_mime_types); i++) {
+ if (nsico_mime_types[i] != NULL)
+ lwc_string_unref(nsico_mime_types[i]);
+ }
+}
+
+nserror nsico_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ nsico_content *result;
+ nserror error;
+
+ result = talloc_zero(0, nsico_content);
+ if (result == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&result->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(result);
+ return error;
+ }
+
+ error = nsico_create_ico_data(result);
+ if (error != NSERROR_OK) {
+ talloc_free(result);
+ return error;
+ }
+
+ *c = (struct content *) result;
+
+ return NSERROR_OK;
+}
+
+nserror nsico_create_ico_data(nsico_content *c)
+{
union content_msg_data msg_data;
- c->data.ico.ico = calloc(sizeof(ico_collection), 1);
- if (!c->data.ico.ico) {
+
+ c->ico = calloc(sizeof(ico_collection), 1);
+ if (c->ico == NULL) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
- ico_collection_create(c->data.ico.ico, &bmp_bitmap_callbacks);
- return true;
+ ico_collection_create(c->ico, &bmp_bitmap_callbacks);
+ return NSERROR_OK;
}
bool nsico_convert(struct content *c)
{
+ nsico_content *ico = (nsico_content *) c;
struct bmp_image *bmp;
bmp_result res;
- ico_collection *ico;
union content_msg_data msg_data;
const char *data;
unsigned long size;
char title[100];
/* set the ico data */
- ico = c->data.ico.ico;
-
data = content__get_source_data(c, &size);
/* analyse the ico */
- res = ico_analyse(ico, size, (unsigned char *) data);
+ res = ico_analyse(ico->ico, size, (unsigned char *) data);
switch (res) {
case BMP_OK:
@@ -85,15 +207,15 @@
}
/* Store our content width and description */
- c->width = ico->width;
- c->height = ico->height;
+ c->width = ico->ico->width;
+ c->height = ico->ico->height;
snprintf(title, sizeof(title), messages_get("ICOTitle"),
c->width, c->height, size);
content__set_title(c, title);
- c->size += (ico->width * ico->height * 4) + 16 + 44;
+ c->size += (ico->ico->width * ico->ico->height * 4) + 16 + 44;
/* exit as a success */
- bmp = ico_find(c->data.ico.ico, 255, 255);
+ bmp = ico_find(ico->ico, 255, 255);
assert(bmp);
c->bitmap = bmp->bitmap;
bitmap_modified(c->bitmap);
@@ -110,7 +232,8 @@
int width, int height, const struct rect *clip,
float scale, colour background_colour)
{
- struct bmp_image *bmp = ico_find(c->data.ico.ico, width, height);
+ nsico_content *ico = (nsico_content *) c;
+ struct bmp_image *bmp = ico_find(ico->ico, width, height);
if (!bmp->decoded)
if (bmp_decode(bmp) != BMP_OK)
return false;
@@ -119,33 +242,13 @@
background_colour, BITMAPF_NONE);
}
-/** sets the bitmap for an ico according to the dimensions */
-
-bool nsico_set_bitmap_from_size(hlcache_handle *h, int width, int height)
-{
- struct content *c = hlcache_handle_get_content(h);
- struct bmp_image *bmp;
-
- assert(c != NULL);
-
- bmp = ico_find(c->data.ico.ico, width, height);
- if (bmp == NULL)
- return false;
-
- if ((bmp->decoded == false) && (bmp_decode(bmp) != BMP_OK))
- return false;
-
- c->bitmap = bmp->bitmap;
-
- return true;
-}
-
bool nsico_redraw_tiled(struct content *c, int x, int y,
int width, int height, const struct rect *clip,
float scale, colour background_colour,
bool repeat_x, bool repeat_y)
{
- struct bmp_image *bmp = ico_find(c->data.ico.ico, width, height);
+ nsico_content *ico = (nsico_content *) c;
+ struct bmp_image *bmp = ico_find(ico->ico, width, height);
bitmap_flags_t flags = BITMAPF_NONE;
if (!bmp->decoded)
@@ -165,23 +268,50 @@
void nsico_destroy(struct content *c)
{
- ico_finalise(c->data.ico.ico);
- free(c->data.ico.ico);
+ nsico_content *ico = (nsico_content *) c;
+
+ ico_finalise(ico->ico);
+ free(ico->ico);
}
-bool nsico_clone(const struct content *old, struct content *new_content)
+nserror nsico_clone(const struct content *old, struct content **newc)
{
+ nsico_content *ico;
+ nserror error;
+
+ ico = talloc_zero(0, nsico_content);
+ if (ico == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &ico->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&ico->base);
+ return error;
+ }
+
/* Simply replay creation and conversion */
- if (nsico_create(new_content, NULL) == false)
- return false;
+ error = nsico_create_ico_data(ico);
+ if (error != NSERROR_OK) {
+ content_destroy(&ico->base);
+ return error;
+ }
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nsico_convert(new_content) == false)
- return false;
+ if (nsico_convert(&ico->base) == false) {
+ content_destroy(&ico->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) ico;
+
+ return NSERROR_OK;
}
+content_type nsico_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
+
#endif
Index: image/gif.h
===================================================================
--- image/gif.h (revision 12276)
+++ image/gif.h (working copy)
@@ -30,27 +30,13 @@
#include <stdbool.h>
#include <libnsgif.h>
-struct content;
-struct http_parameter;
-struct rect;
+nserror nsgif_init(void);
+void nsgif_fini(void);
-struct content_gif_data {
- struct gif_animation *gif; /**< GIF animation data */
- int current_frame; /**< current frame to display [0...(max-1)] */
-};
+#else
-bool nsgif_create(struct content *c, const struct http_parameter *params);
-bool nsgif_convert(struct content *c);
-void nsgif_destroy(struct content *c);
-bool nsgif_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool nsgif_redraw_tiled(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y);
-bool nsgif_clone(const struct content *old, struct content *new_content);
-void *nsgif_bitmap_create(int width, int height);
+#define nsgif_init() NSERROR_OK
+#define nsgif_fini() ((void) 0)
#endif /* WITH_GIF */
Index: image/nssprite.h
===================================================================
--- image/nssprite.h (revision 12276)
+++ image/nssprite.h (working copy)
@@ -28,19 +28,13 @@
#include <stdbool.h>
-struct content;
-struct rect;
+nserror nssprite_init(void);
+void nssprite_fini(void);
-struct content_nssprite_data {
- struct rosprite_area* sprite_area;
-};
+#else
-bool nssprite_convert(struct content *c);
-void nssprite_destroy(struct content *c);
-bool nssprite_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool nssprite_clone(const struct content *old, struct content *new_content);
+#define nssprite_init() NSERROR_OK
+#define nssprite_fini() ((void) 0)
#endif /* WITH_NSSPRITE */
Index: image/bmp.c
===================================================================
--- image/bmp.c (revision 12276)
+++ image/bmp.c (working copy)
@@ -31,13 +31,40 @@
#include <libnsbmp.h>
#include "utils/config.h"
#include "content/content_protected.h"
+#include "content/hlcache.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "image/bmp.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
+typedef struct nsbmp_content {
+ struct content base;
+
+ bmp_image *bmp; /** BMP image data */
+} nsbmp_content;
+
+static nserror nsbmp_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror nsbmp_create_bmp_data(nsbmp_content *bmp);
+static bool nsbmp_convert(struct content *c);
+static void nsbmp_destroy(struct content *c);
+static bool nsbmp_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static bool nsbmp_redraw_tiled(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror nsbmp_clone(const struct content *old, struct content **newc);
+static content_type nsbmp_content_type(lwc_string *mime_type);
+
+static void *nsbmp_bitmap_create(int width, int height, unsigned int bmp_state);
+
/* The Bitmap callbacks function table;
* necessary for interaction with nsbmplib.
*/
@@ -49,25 +76,131 @@
.bitmap_get_bpp = bitmap_get_bpp
};
-bool nsbmp_create(struct content *c, const struct http_parameter *params)
+static const content_handler nsbmp_content_handler = {
+ nsbmp_create,
+ NULL,
+ nsbmp_convert,
+ NULL,
+ nsbmp_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nsbmp_redraw,
+ nsbmp_redraw_tiled,
+ NULL,
+ NULL,
+ nsbmp_clone,
+ NULL,
+ nsbmp_content_type,
+ false
+};
+
+static const char *nsbmp_types[] = {
+ "application/bmp",
+ "application/preview",
+ "application/x-bmp",
+ "application/x-win-bitmap",
+ "image/bmp",
+ "image/ms-bmp",
+ "image/x-bitmap",
+ "image/x-bmp",
+ "image/x-ms-bmp",
+ "image/x-win-bitmap",
+ "image/x-windows-bmp",
+ "image/x-xbitmap"
+};
+
+static lwc_string *nsbmp_mime_types[NOF_ELEMENTS(nsbmp_types)];
+
+nserror nsbmp_init(void)
{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(nsbmp_mime_types); i++) {
+ lerror = lwc_intern_string(nsbmp_types[i],
+ strlen(nsbmp_types[i]),
+ &nsbmp_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(nsbmp_mime_types[i],
+ &nsbmp_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nsbmp_fini();
+
+ return error;
+}
+
+void nsbmp_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(nsbmp_mime_types); i++) {
+ if (nsbmp_mime_types[i] != NULL)
+ lwc_string_unref(nsbmp_mime_types[i]);
+ }
+}
+
+nserror nsbmp_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ nsbmp_content *bmp;
+ nserror error;
+
+ bmp = talloc_zero(0, nsbmp_content);
+ if (bmp == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&bmp->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(bmp);
+ return error;
+ }
+
+ error = nsbmp_create_bmp_data(bmp);
+ if (error != NSERROR_OK) {
+ talloc_free(bmp);
+ return error;
+ }
+
+ *c = (struct content *) bmp;
+
+ return NSERROR_OK;
+}
+
+nserror nsbmp_create_bmp_data(nsbmp_content *bmp)
+{
union content_msg_data msg_data;
- c->data.bmp.bmp = calloc(sizeof(struct bmp_image), 1);
- if (!c->data.bmp.bmp) {
+ bmp->bmp = calloc(sizeof(struct bmp_image), 1);
+ if (bmp->bmp == NULL) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&bmp->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
- bmp_create(c->data.bmp.bmp, &bmp_bitmap_callbacks);
- return true;
+
+ bmp_create(bmp->bmp, &bmp_bitmap_callbacks);
+
+ return NSERROR_OK;
}
-
bool nsbmp_convert(struct content *c)
{
+ nsbmp_content *bmp = (nsbmp_content *) c;
bmp_result res;
- bmp_image *bmp;
union content_msg_data msg_data;
uint32_t swidth;
const char *data;
@@ -75,12 +208,10 @@
char title[100];
/* set the bmp data */
- bmp = c->data.bmp.bmp;
-
data = content__get_source_data(c, &size);
/* analyse the BMP */
- res = bmp_analyse(bmp, size, (unsigned char *) data);
+ res = bmp_analyse(bmp->bmp, size, (unsigned char *) data);
switch (res) {
case BMP_OK:
break;
@@ -96,17 +227,18 @@
}
/* Store our content width and description */
- c->width = bmp->width;
- c->height = bmp->height;
+ c->width = bmp->bmp->width;
+ c->height = bmp->bmp->height;
LOG(("BMP width %u height %u", c->width, c->height));
snprintf(title, sizeof(title), messages_get("BMPTitle"),
c->width, c->height, size);
content__set_title(c, title);
- swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
- c->size += (swidth * bmp->height) + 16 + 44;
+ swidth = bmp->bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bmp->bitmap) *
+ bmp->bmp->width;
+ c->size += (swidth * bmp->bmp->height) + 16 + 44;
/* exit as a success */
- c->bitmap = bmp->bitmap;
+ c->bitmap = bmp->bmp->bitmap;
bitmap_modified(c->bitmap);
content_set_ready(c);
@@ -122,11 +254,14 @@
int width, int height, const struct rect *clip,
float scale, colour background_colour)
{
+ nsbmp_content *bmp = (nsbmp_content *) c;
- if (!c->data.bmp.bmp->decoded)
- if (bmp_decode(c->data.bmp.bmp) != BMP_OK)
+ if (bmp->bmp->decoded == false)
+ if (bmp_decode(bmp->bmp) != BMP_OK)
return false;
- c->bitmap = c->data.bmp.bmp->bitmap;
+
+ c->bitmap = bmp->bmp->bitmap;
+
return plot.bitmap(x, y, width, height, c->bitmap,
background_colour, BITMAPF_NONE);
}
@@ -137,13 +272,14 @@
float scale, colour background_colour,
bool repeat_x, bool repeat_y)
{
+ nsbmp_content *bmp = (nsbmp_content *) c;
bitmap_flags_t flags = BITMAPF_NONE;
- if (!c->data.bmp.bmp->decoded)
- if (bmp_decode(c->data.bmp.bmp) != BMP_OK)
+ if (bmp->bmp->decoded == false)
+ if (bmp_decode(bmp->bmp) != BMP_OK)
return false;
- c->bitmap = c->data.bmp.bmp->bitmap;
+ c->bitmap = bmp->bmp->bitmap;
if (repeat_x)
flags |= BITMAPF_REPEAT_X;
@@ -157,27 +293,52 @@
void nsbmp_destroy(struct content *c)
{
- bmp_finalise(c->data.bmp.bmp);
- free(c->data.bmp.bmp);
+ nsbmp_content *bmp = (nsbmp_content *) c;
+
+ bmp_finalise(bmp->bmp);
+ free(bmp->bmp);
}
+nserror nsbmp_clone(const struct content *old, struct content **newc)
+{
+ nsbmp_content *new_bmp;
+ nserror error;
-bool nsbmp_clone(const struct content *old, struct content *new_content)
-{
+ new_bmp = talloc_zero(0, nsbmp_content);
+ if (new_bmp == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &new_bmp->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&new_bmp->base);
+ return error;
+ }
+
/* We "clone" the old content by replaying creation and conversion */
- if (nsbmp_create(new_content, NULL) == false)
- return false;
+ error = nsbmp_create_bmp_data(new_bmp);
+ if (error != NSERROR_OK) {
+ content_destroy(&new_bmp->base);
+ return error;
+ }
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nsbmp_convert(new_content) == false)
- return false;
+ if (nsbmp_convert(&new_bmp->base) == false) {
+ content_destroy(&new_bmp->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) new_bmp;
+
+ return NSERROR_OK;
}
+content_type nsbmp_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
/**
* Callback for libnsbmp; forwards the call to bitmap_create()
Index: image/ico.h
===================================================================
--- image/ico.h (revision 12276)
+++ image/ico.h (working copy)
@@ -29,29 +29,16 @@
#include <stdbool.h>
#include <libnsbmp.h>
-struct content;
-struct hlcache_handle;
-struct http_parameter;
-struct rect;
+#include "utils/errors.h"
-struct content_ico_data {
- struct ico_collection *ico; /** ICO collection data */
-};
+nserror nsico_init(void);
+void nsico_fini(void);
-bool nsico_create(struct content *c, const struct http_parameter *params);
-bool nsico_convert(struct content *c);
-void nsico_destroy(struct content *c);
-bool nsico_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool nsico_redraw_tiled(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y);
-bool nsico_clone(const struct content *old, struct content *new_content);
-bool nsico_set_bitmap_from_size(struct hlcache_handle *h,
- int width, int height);
+#else
+#define nsico_init() NSERROR_OK
+#define nsico_fini() ((void) 0)
+
#endif /* WITH_BMP */
#endif
Index: image/rsvg.c
===================================================================
--- image/rsvg.c (revision 12276)
+++ image/rsvg.c (working copy)
@@ -32,6 +32,7 @@
#include <stdbool.h>
#include <assert.h>
+#include <string.h>
#include <sys/types.h>
#include <librsvg/rsvg.h>
@@ -46,33 +47,151 @@
#include "utils/messages.h"
#include "utils/talloc.h"
+typedef struct rsvg_content {
+ struct content base;
+
+ RsvgHandle *rsvgh; /**< Context handle for RSVG renderer */
+ cairo_surface_t *cs; /**< The surface built inside a nsbitmap */
+ cairo_t *ct; /**< Cairo drawing context */
+ struct bitmap *bitmap; /**< Created NetSurf bitmap */
+} rsvg_content;
+
+static nserror rsvg_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror rsvg_create_svg_data(rsvg_content *c);
+static bool rsvg_process_data(struct content *c, const char *data,
+ unsigned int size);
+static bool rsvg_convert(struct content *c);
+static void rsvg_destroy(struct content *c);
+static bool rsvg_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static nserror rsvg_clone(const struct content *old, struct content **newc);
+static content_type rsvg_content_type(lwc_string *mime_type);
+
static inline void rsvg_argb_to_abgr(uint8_t *pixels,
int width, int height, size_t rowstride);
-bool rsvg_create(struct content *c, const struct http_parameter *params)
+static const content_handler rsvg_content_handler = {
+ rsvg_create,
+ rsvg_process_data,
+ rsvg_convert,
+ NULL,
+ rsvg_destroy,
+ NULL,
+ NULL,
+ NULL,
+ rsvg_redraw,
+ NULL,
+ NULL,
+ NULL,
+ rsvg_clone,
+ NULL,
+ rsvg_content_type,
+ false
+};
+
+static const char *rsvg_types[] = {
+ "image/svg",
+ "image/svg+xml"
+};
+
+static lwc_string *rsvg_mime_types[NOF_ELEMENTS(rsvg_types)];
+
+nserror nsrsvg_init(void)
{
- struct content_rsvg_data *d = &c->data.rsvg;
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(rsvg_mime_types); i++) {
+ lerror = lwc_intern_string(rsvg_types[i],
+ strlen(rsvg_types[i]),
+ &rsvg_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(rsvg_mime_types[i],
+ &rsvg_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nsrsvg_fini();
+
+ return error;
+}
+
+void nsrsvg_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(rsvg_mime_types); i++) {
+ if (rsvg_mime_types[i] != NULL)
+ lwc_string_unref(rsvg_mime_types[i]);
+ }
+}
+
+nserror rsvg_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ rsvg_content *svg;
+ nserror error;
+
+ svg = talloc_zero(0, rsvg_content);
+ if (svg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&svg->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(svg);
+ return error;
+ }
+
+ error = rsvg_create_svg_data(svg);
+ if (error != NSERROR_OK) {
+ talloc_free(svg);
+ return error;
+ }
+
+ *c = (struct content *) svg;
+
+ return NSERROR_OK;
+}
+
+nserror rsvg_create_svg_data(rsvg_content *c)
+{
union content_msg_data msg_data;
- d->rsvgh = NULL;
- d->cs = NULL;
- d->ct = NULL;
- d->bitmap = NULL;
+ c->rsvgh = NULL;
+ c->cs = NULL;
+ c->ct = NULL;
+ c->bitmap = NULL;
- if ((d->rsvgh = rsvg_handle_new()) == NULL) {
+ if ((c->rsvgh = rsvg_handle_new()) == NULL) {
LOG(("rsvg_handle_new() returned NULL."));
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
- return true;
+ return NSERROR_OK;
}
bool rsvg_process_data(struct content *c, const char *data,
unsigned int size)
{
- struct content_rsvg_data *d = &c->data.rsvg;
+ rsvg_content *d = (rsvg_content *) c;
union content_msg_data msg_data;
GError *err = NULL;
@@ -118,7 +237,7 @@
bool rsvg_convert(struct content *c)
{
- struct content_rsvg_data *d = &c->data.rsvg;
+ rsvg_content *d = (rsvg_content *) c;
union content_msg_data msg_data;
RsvgDimensionData rsvgsize;
GError *err = NULL;
@@ -191,7 +310,7 @@
void rsvg_destroy(struct content *c)
{
- struct content_rsvg_data *d = &c->data.rsvg;
+ rsvg_content *d = (rsvg_content *) c;
if (d->bitmap != NULL) bitmap_destroy(d->bitmap);
if (d->rsvgh != NULL) rsvg_handle_free(d->rsvgh);
@@ -201,28 +320,54 @@
return;
}
-bool rsvg_clone(const struct content *old, struct content *new_content)
+nserror rsvg_clone(const struct content *old, struct content **newc)
{
+ rsvg_content *svg;
+ nserror error;
const char *data;
unsigned long size;
+ svg = talloc_zero(0, rsvg_content);
+ if (svg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &svg->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&svg->base);
+ return error;
+ }
+
/* Simply replay create/process/convert */
- if (rsvg_create(new_content, NULL) == false)
- return false;
+ error = rsvg_create_svg_data(svg);
+ if (error != NSERROR_OK) {
+ content_destroy(&svg->base);
+ return error;
+ }
- data = content__get_source_data(new_content, &size);
+ data = content__get_source_data(&svg->base, &size);
if (size > 0) {
- if (rsvg_process_data(new_content, data, size) == false)
- return false;
+ if (rsvg_process_data(&svg->base, data, size) == false) {
+ content_destroy(&svg->base);
+ return NSERROR_NOMEM;
+ }
}
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (rsvg_convert(new_content) == false)
- return false;
+ if (rsvg_convert(&svg->base) == false) {
+ content_destroy(&svg->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) svg;
+
+ return NSERROR_OK;
}
+content_type rsvg_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
+
#endif /* WITH_RSVG */
Index: image/mng.c
===================================================================
--- image/mng.c (revision 12276)
+++ image/mng.c (working copy)
@@ -23,9 +23,6 @@
#include "utils/config.h"
#ifdef WITH_MNG
-/* This must come first due to libpng issues */
-#include "content/content_protected.h"
-
#include <assert.h>
#include <stdbool.h>
#include <string.h>
@@ -33,6 +30,7 @@
#include <sys/time.h>
#include <time.h>
#include <libmng.h>
+#include "content/content_protected.h"
#include "desktop/options.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
@@ -40,13 +38,45 @@
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/schedule.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
/* We do not currently support any form of colour/gamma correction, nor do
we support dynamic MNGs.
*/
+typedef struct nsmng_content
+{
+ struct content base;
+
+ bool opaque_test_pending;
+ bool read_start;
+ bool read_resume;
+ int read_size;
+ bool waiting;
+ bool displayed;
+ void *handle;
+} nsmng_content;
+static nserror nsmng_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror nsmng_create_mng_data(nsmng_content *c);
+static bool nsmng_process_data(struct content *c, const char *data,
+ unsigned int size);
+static bool nsmng_convert(struct content *c);
+static void nsmng_destroy(struct content *c);
+static bool nsmng_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static bool nsmng_redraw_tiled(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror nsmng_clone(const struct content *old, struct content **newc);
+static content_type nsmng_content_type(lwc_string *mime_type);
+
static mng_bool nsmng_openstream(mng_handle mng);
static mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer,
mng_uint32 size, mng_uint32 *bytesread);
@@ -59,7 +89,7 @@
mng_uint32 w, mng_uint32 h);
static mng_bool nsmng_settimer(mng_handle mng, mng_uint32 msecs);
static void nsmng_animate(void *p);
-static bool nsmng_broadcast_error(struct content *c, mng_retcode code);
+static nserror nsmng_broadcast_error(nsmng_content *c, mng_retcode code);
static mng_bool nsmng_errorproc(mng_handle mng, mng_int32 code,
mng_int8 severity, mng_chunkid chunktype, mng_uint32 chunkseq,
mng_int32 extra1, mng_int32 extra2, mng_pchar text);
@@ -68,9 +98,132 @@
static void nsmng_free(mng_ptr p, mng_size_t n);
#endif
+static const content_handler nsmng_content_handler = {
+ nsmng_create,
+ nsmng_process_data,
+ nsmng_convert,
+ NULL,
+ nsmng_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nsmng_redraw,
+ nsmng_redraw_tiled,
+ NULL,
+ NULL,
+ nsmng_clone,
+ NULL,
+ nsmng_content_type,
+ false
+};
-bool nsmng_create(struct content *c, const struct http_parameter *params)
+static const char *jng_types[] = {
+ "image/jng",
+ "image/x-jng"
+};
+
+static const char *mng_types[] = {
+ "image/mng",
+ "image/x-mng",
+ "video/mng",
+ "video/x-mng"
+};
+
+static const char *png_types[] = {
+ "image/png"
+};
+
+static lwc_string *jng_mime_types[NOF_ELEMENTS(jng_types)];
+static lwc_string *mng_mime_types[NOF_ELEMENTS(mng_types)];
+static lwc_string *png_mime_types[NOF_ELEMENTS(png_types)];
+
+nserror nsmng_init(void)
{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+#define register_types(type) \
+ for (i = 0; i < NOF_ELEMENTS(type##_mime_types); i++) { \
+ lerror = lwc_intern_string(type##_types[i], \
+ strlen(type##_types[i]), \
+ &type##_mime_types[i]); \
+ if (lerror != lwc_error_ok) { \
+ error = NSERROR_NOMEM; \
+ goto error; \
+ } \
+ \
+ error = content_factory_register_handler( \
+ type##_mime_types[i], \
+ &nsmng_content_handler); \
+ if (error != NSERROR_OK) \
+ goto error; \
+ }
+
+ register_types(jng)
+ register_types(mng)
+ register_types(png)
+
+ return NSERROR_OK;
+
+error:
+ nsmng_fini();
+
+ return error;
+}
+
+void nsmng_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(jng_mime_types); i++) {
+ if (jng_mime_types[i] != NULL)
+ lwc_string_unref(jng_mime_types[i]);
+ }
+
+ for (i = 0; i < NOF_ELEMENTS(mng_mime_types); i++) {
+ if (mng_mime_types[i] != NULL)
+ lwc_string_unref(mng_mime_types[i]);
+ }
+
+ for (i = 0; i < NOF_ELEMENTS(png_mime_types); i++) {
+ if (png_mime_types[i] != NULL)
+ lwc_string_unref(png_mime_types[i]);
+ }
+}
+
+nserror nsmng_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ nsmng_content *mng;
+ nserror error;
+
+ mng = talloc_zero(0, nsmng_content);
+ if (mng == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&mng->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(mng);
+ return error;
+ }
+
+ error = nsmng_create_mng_data(mng);
+ if (error != NSERROR_OK) {
+ talloc_free(mng);
+ return error;
+ }
+
+ *c = (struct content *) mng;
+
+ return NSERROR_OK;
+}
+
+nserror nsmng_create_mng_data(nsmng_content *c)
+{
mng_retcode code;
union content_msg_data msg_data;
@@ -79,20 +232,20 @@
/* Initialise the library
*/
#ifdef MNG_INTERNAL_MEMMNGMT
- c->data.mng.handle = mng_initialize(c, MNG_NULL, MNG_NULL, MNG_NULL);
+ c->handle = mng_initialize(c, MNG_NULL, MNG_NULL, MNG_NULL);
#else
- c->data.mng.handle = mng_initialize(c, nsmng_alloc, nsmng_free, MNG_NULL);
+ c->handle = mng_initialize(c, nsmng_alloc, nsmng_free, MNG_NULL);
#endif
- if (c->data.mng.handle == MNG_NULL) {
+ if (c->handle == MNG_NULL) {
LOG(("Unable to initialise MNG library."));
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
/* We need to decode in suspension mode
*/
- code = mng_set_suspensionmode(c->data.mng.handle, MNG_TRUE);
+ code = mng_set_suspensionmode(c->handle, MNG_TRUE);
if (code) {
LOG(("Unable to set suspension mode."));
return nsmng_broadcast_error(c, code);
@@ -100,22 +253,22 @@
/* We need to register our callbacks
*/
- code = mng_setcb_openstream(c->data.mng.handle, nsmng_openstream);
+ code = mng_setcb_openstream(c->handle, nsmng_openstream);
if (code) {
LOG(("Unable to set openstream callback."));
return nsmng_broadcast_error(c, code);
}
- code = mng_setcb_readdata(c->data.mng.handle, nsmng_readdata);
+ code = mng_setcb_readdata(c->handle, nsmng_readdata);
if (code) {
LOG(("Unable to set readdata callback."));
return nsmng_broadcast_error(c, code);
}
- code = mng_setcb_closestream(c->data.mng.handle, nsmng_closestream);
+ code = mng_setcb_closestream(c->handle, nsmng_closestream);
if (code) {
LOG(("Unable to set closestream callback."));
return nsmng_broadcast_error(c, code);
}
- code = mng_setcb_processheader(c->data.mng.handle, nsmng_processheader);
+ code = mng_setcb_processheader(c->handle, nsmng_processheader);
if (code) {
LOG(("Unable to set processheader callback."));
return nsmng_broadcast_error(c, code);
@@ -123,29 +276,29 @@
/* Register our callbacks for displaying
*/
- code = mng_setcb_getcanvasline(c->data.mng.handle, nsmng_getcanvasline);
+ code = mng_setcb_getcanvasline(c->handle, nsmng_getcanvasline);
if (code) {
LOG(("Unable to set getcanvasline callback."));
return nsmng_broadcast_error(c, code);
}
- code = mng_setcb_refresh(c->data.mng.handle, nsmng_refresh);
+ code = mng_setcb_refresh(c->handle, nsmng_refresh);
if (code) {
LOG(("Unable to set refresh callback."));
return nsmng_broadcast_error(c, code);
}
- code = mng_setcb_gettickcount(c->data.mng.handle, nsmng_gettickcount);
+ code = mng_setcb_gettickcount(c->handle, nsmng_gettickcount);
if (code) {
LOG(("Unable to set gettickcount callback."));
return nsmng_broadcast_error(c, code);
}
- code = mng_setcb_settimer(c->data.mng.handle, nsmng_settimer);
+ code = mng_setcb_settimer(c->handle, nsmng_settimer);
if (code) {
LOG(("Unable to set settimer callback."));
return nsmng_broadcast_error(c, code);
}
/* register error handling function */
- code = mng_setcb_errorproc(c->data.mng.handle, nsmng_errorproc);
+ code = mng_setcb_errorproc(c->handle, nsmng_errorproc);
if (code) {
LOG(("Unable to set errorproc"));
return nsmng_broadcast_error(c, code);
@@ -153,13 +306,14 @@
/* Initialise the reading
*/
- c->data.mng.read_start = true;
- c->data.mng.read_resume = false;
- c->data.mng.read_size = 0;
- c->data.mng.waiting = false;
+ c->read_start = true;
+ c->read_resume = false;
+ c->read_size = 0;
+ c->waiting = false;
- c->data.mng.displayed = false;
- return true;
+ c->displayed = false;
+
+ return NSERROR_OK;
}
@@ -176,7 +330,7 @@
mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer, mng_uint32 size,
mng_uint32 *bytesread)
{
- struct content *c;
+ nsmng_content *c;
const char *data;
unsigned long data_size;
@@ -186,19 +340,19 @@
/* Get our content back
*/
- c = (struct content *) mng_get_userdata(mng);
+ c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
/* Copy any data we have (maximum of 'size')
*/
- data = content__get_source_data(c, &data_size);
+ data = content__get_source_data(&c->base, &data_size);
- *bytesread = ((data_size - c->data.mng.read_size) < size) ?
- (data_size - c->data.mng.read_size) : size;
+ *bytesread = ((data_size - c->read_size) < size) ?
+ (data_size - c->read_size) : size;
if ((*bytesread) > 0) {
- memcpy(buffer, data + c->data.mng.read_size, *bytesread);
- c->data.mng.read_size += *bytesread;
+ memcpy(buffer, data + c->read_size, *bytesread);
+ c->read_size += *bytesread;
}
/* Return success
@@ -215,7 +369,7 @@
mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width,
mng_uint32 height)
{
- struct content *c;
+ nsmng_content *c;
union content_msg_data msg_data;
uint8_t *buffer;
@@ -224,31 +378,31 @@
/* This function is called when the header has been read and we
know the dimensions of the canvas.
*/
- c = (struct content *)mng_get_userdata(mng);
+ c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
- c->bitmap = bitmap_create(width, height, BITMAP_NEW);
- if (!c->bitmap) {
+ c->base.bitmap = bitmap_create(width, height, BITMAP_NEW);
+ if (c->base.bitmap == NULL) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
LOG(("Insufficient memory to create canvas."));
return MNG_FALSE;
}
/* Get the buffer to ensure that it is allocated and the calls in
* nsmng_getcanvasline() succeed. */
- buffer = bitmap_get_buffer(c->bitmap);
- if (!buffer) {
+ buffer = bitmap_get_buffer(c->base.bitmap);
+ if (buffer == NULL) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
LOG(("Insufficient memory to create canvas."));
return MNG_FALSE;
}
/* Initialise the content size
*/
- c->width = width;
- c->height = height;
+ c->base.width = width;
+ c->base.height = height;
/* Set the canvas style
*/
@@ -268,6 +422,7 @@
bool nsmng_process_data(struct content *c, const char *data, unsigned int size)
{
+ nsmng_content *mng = (nsmng_content *) c;
mng_retcode status;
assert(c != NULL);
@@ -275,21 +430,21 @@
/* We only need to do any processing if we're starting/resuming reading.
*/
- if ((!c->data.mng.read_resume) && (!c->data.mng.read_start))
+ if ((!mng->read_resume) && (!mng->read_start))
return true;
/* Try to start processing, or process some more data
*/
- if (c->data.mng.read_start) {
- status = mng_read(c->data.mng.handle);
- c->data.mng.read_start = false;
+ if (mng->read_start) {
+ status = mng_read(mng->handle);
+ mng->read_start = false;
} else {
- status = mng_read_resume(c->data.mng.handle);
+ status = mng_read_resume(mng->handle);
}
- c->data.mng.read_resume = (status == MNG_NEEDMOREDATA);
+ mng->read_resume = (status == MNG_NEEDMOREDATA);
if ((status != MNG_NOERROR) && (status != MNG_NEEDMOREDATA)) {
LOG(("Failed to start/continue reading (%i).", status));
- return nsmng_broadcast_error(c, status);
+ return nsmng_broadcast_error(mng, status) == NSERROR_OK;
}
/* Continue onwards
@@ -300,9 +455,14 @@
bool nsmng_convert(struct content *c)
{
+ nsmng_content *mng = (nsmng_content *) c;
mng_retcode status;
const char *data;
unsigned long size;
+ lwc_string *content_type;
+ bool match;
+ bool is_mng = false;
+ uint32_t i;
char title[100];
assert(c != NULL);
@@ -312,15 +472,26 @@
/* by this point, the png should have been parsed
* and the bitmap created, so ensure that's the case
*/
- if (!c->bitmap)
- return nsmng_broadcast_error(c, -1);
+ if (content__get_bitmap(c) == NULL)
+ return nsmng_broadcast_error(mng, -1) == NSERROR_OK;
/* Set the title
*/
- if (c->type == CONTENT_MNG) {
+ content_type = content__get_mime_type(c);
+
+ for (i = 0; i < NOF_ELEMENTS(mng_mime_types); i++) {
+ if (lwc_string_caseless_isequal(content_type, mng_mime_types[i],
+ &match) == lwc_error_ok && match) {
+ is_mng = true;
+ break;
+ }
+ }
+
+ if (is_mng) {
snprintf(title, sizeof(title), messages_get("MNGTitle"),
c->width, c->height, size);
- } else if (c->type == CONTENT_PNG) {
+ } else if (lwc_string_caseless_isequal(content_type, png_mime_types[0],
+ &match) == lwc_error_ok && match) {
snprintf(title, sizeof(title), messages_get("PNGTitle"),
c->width, c->height, size);
} else {
@@ -329,6 +500,8 @@
}
content__set_title(c, title);
+ lwc_string_unref(content_type);
+
c->size += c->width * c->height * 4;
content_set_ready(c);
content_set_done(c);
@@ -349,28 +522,27 @@
*/
/* Start displaying
*/
- status = mng_display(c->data.mng.handle);
+ status = mng_display(mng->handle);
if ((status != MNG_NOERROR) && (status != MNG_NEEDTIMERWAIT)) {
LOG(("Unable to start display (%i)", status));
- return nsmng_broadcast_error(c, status);
+ return nsmng_broadcast_error(mng, status) == NSERROR_OK;
}
bitmap_modified(c->bitmap);
/* Optimise the plotting of JNG/PNGs
*/
- c->data.mng.opaque_test_pending = (c->type == CONTENT_PNG) ||
- (c->type == CONTENT_JNG);
- if (c->data.mng.opaque_test_pending)
+ mng->opaque_test_pending = (is_mng == false);
+ if (mng->opaque_test_pending)
bitmap_set_opaque(c->bitmap, false);
/* free associated memory except for mngs where it may be subsequently needed for
* animation decoding. */
- if (c->type != CONTENT_MNG) {
- mng_handle handle = c->data.mng.handle;
+ if (is_mng == false) {
+ mng_handle handle = mng->handle;
mng_cleanup(&handle);
- c->data.mng.handle = NULL;
+ mng->handle = NULL;
}
return true;
@@ -383,19 +555,19 @@
mng_ptr nsmng_getcanvasline(mng_handle mng, mng_uint32 line)
{
- struct content *c;
+ nsmng_content *c;
assert(mng != NULL);
/* Get our content back
*/
- c = (struct content *)mng_get_userdata(mng);
+ c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
/* Calculate the address
*/
- return bitmap_get_buffer(c->bitmap) +
- bitmap_get_rowstride(c->bitmap) * line;
+ return bitmap_get_buffer(c->base.bitmap) +
+ bitmap_get_rowstride(c->base.bitmap) * line;
}
@@ -433,13 +605,13 @@
mng_uint32 w, mng_uint32 h)
{
union content_msg_data data;
- struct content *c;
+ nsmng_content *c;
assert(mng != NULL);
/* Get our content back
*/
- c = (struct content *)mng_get_userdata(mng);
+ c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
/* Set the minimum redraw area
@@ -463,11 +635,11 @@
/* Set the object characteristics
*/
- data.redraw.object = c;
+ data.redraw.object = &c->base;
data.redraw.object_x = 0;
data.redraw.object_y = 0;
- data.redraw.object_width = c->width;
- data.redraw.object_height = c->height;
+ data.redraw.object_width = c->base.width;
+ data.redraw.object_height = c->base.height;
/* Only attempt to force the redraw if we've been requested to
* display the image in the first place (i.e. nsmng_redraw has
@@ -475,21 +647,21 @@
* an image that shouldn't be shown (e.g. if the image is a fallback
* for an object that can't be rendered)
*/
- if (c->data.mng.displayed)
- content_broadcast(c, CONTENT_MSG_REDRAW, data);
+ if (c->displayed)
+ content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
return MNG_TRUE;
}
mng_bool nsmng_settimer(mng_handle mng, mng_uint32 msecs)
{
- struct content *c;
+ nsmng_content *c;
assert(mng != NULL);
/* Get our content back
*/
- c = (struct content *)mng_get_userdata(mng);
+ c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
/* Perform the scheduling
@@ -505,18 +677,20 @@
void nsmng_destroy(struct content *c)
{
+ nsmng_content *mng = (nsmng_content *) c;
assert (c != NULL);
/* Cleanup the MNG structure and release the canvas memory
*/
schedule_remove(nsmng_animate, c);
- if (c->type == CONTENT_MNG) {
- mng_handle handle = c->data.mng.handle;
+ if (mng->handle != NULL) {
+ mng_handle handle = mng->handle;
+
mng_cleanup(&handle);
- c->data.mng.handle = NULL;
+ mng->handle = NULL;
}
if (c->bitmap)
@@ -528,14 +702,15 @@
int width, int height, const struct rect *clip,
float scale, colour background_colour)
{
+ nsmng_content *mng = (nsmng_content *) c;
bool ret;
/* mark image as having been requested to display */
- c->data.mng.displayed = true;
+ mng->displayed = true;
- if ((c->bitmap) && (c->data.mng.opaque_test_pending)) {
+ if ((c->bitmap) && (mng->opaque_test_pending)) {
bitmap_set_opaque(c->bitmap, bitmap_test_opaque(c->bitmap));
- c->data.mng.opaque_test_pending = false;
+ mng->opaque_test_pending = false;
}
ret = plot.bitmap(x, y, width, height,
@@ -543,7 +718,7 @@
/* Check if we need to restart the animation
*/
- if ((c->data.mng.waiting) && (option_animate_images))
+ if ((mng->waiting) && (option_animate_images))
nsmng_animate(c);
return ret;
@@ -555,15 +730,16 @@
float scale, colour background_colour,
bool repeat_x, bool repeat_y)
{
+ nsmng_content *mng = (nsmng_content *) c;
bool ret;
bitmap_flags_t flags = BITMAPF_NONE;
/* mark image as having been requested to display */
- c->data.mng.displayed = true;
+ mng->displayed = true;
- if ((c->bitmap) && (c->data.mng.opaque_test_pending)) {
+ if ((c->bitmap) && (mng->opaque_test_pending)) {
bitmap_set_opaque(c->bitmap, bitmap_test_opaque(c->bitmap));
- c->data.mng.opaque_test_pending = false;
+ mng->opaque_test_pending = false;
}
if (repeat_x)
@@ -577,58 +753,84 @@
/* Check if we need to restart the animation
*/
- if ((c->data.mng.waiting) && (option_animate_images))
+ if ((mng->waiting) && (option_animate_images))
nsmng_animate(c);
return ret;
}
-bool nsmng_clone(const struct content *old, struct content *new_content)
+nserror nsmng_clone(const struct content *old, struct content **newc)
{
+ nsmng_content *mng;
+ nserror error;
const char *data;
unsigned long size;
+ mng = talloc_zero(0, nsmng_content);
+ if (mng == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &mng->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&mng->base);
+ return error;
+ }
+
/* Simply replay create/process/convert */
- if (nsmng_create(new_content, NULL) == false)
- return false;
+ error = nsmng_create_mng_data(mng);
+ if (error != NSERROR_OK) {
+ content_destroy(&mng->base);
+ return error;
+ }
- data = content__get_source_data(new_content, &size);
+ data = content__get_source_data(&mng->base, &size);
if (size > 0) {
- if (nsmng_process_data(new_content, data, size) == false)
- return false;
+ if (nsmng_process_data(&mng->base, data, size) == false) {
+ content_destroy(&mng->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nsmng_convert(new_content) == false)
- return false;
+ if (nsmng_convert(&mng->base) == false) {
+ content_destroy(&mng->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) mng;
+
+ return NSERROR_OK;
}
+content_type nsmng_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
+
/**
* Animates to the next frame
*/
void nsmng_animate(void *p)
{
- struct content *c;
+ nsmng_content *c;
assert(p != NULL);
- c = (struct content *)p;
+ c = (nsmng_content *) p;
/* If we used the last animation we advance, if not we try again later
*/
- if (c->user_list->next == NULL) {
- c->data.mng.waiting = true;
+ if (c->base.user_list->next == NULL) {
+ c->waiting = true;
} else {
- c->data.mng.waiting = false;
- mng_display_resume(c->data.mng.handle);
- c->data.mng.opaque_test_pending = true;
- if (c->bitmap)
- bitmap_modified(c->bitmap);
+ c->waiting = false;
+ mng_display_resume(c->handle);
+ c->opaque_test_pending = true;
+ if (c->base.bitmap)
+ bitmap_modified(c->base.bitmap);
}
}
@@ -638,9 +840,9 @@
* Broadcasts an error message and returns false
*
* \param c the content to broadcast for
- * \return false
+ * \return Appropriate error
*/
-bool nsmng_broadcast_error(struct content *c, mng_retcode code)
+nserror nsmng_broadcast_error(nsmng_content *c, mng_retcode code)
{
union content_msg_data msg_data;
char error[100];
@@ -649,14 +851,14 @@
if (code == MNG_OUTOFMEMORY) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
snprintf(error, sizeof error, messages_get("MNGError"), code);
msg_data.error = error;
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_MNG_ERROR;
}
@@ -664,12 +866,12 @@
mng_int8 severity, mng_chunkid chunktype, mng_uint32 chunkseq,
mng_int32 extra1, mng_int32 extra2, mng_pchar text)
{
- struct content *c;
+ nsmng_content *c;
char chunk[5];
assert(mng != NULL);
- c = (struct content *)mng_get_userdata(mng);
+ c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
chunk[0] = (char)((chunktype >> 24) & 0xFF);
@@ -679,11 +881,11 @@
chunk[4] = '\0';
LOG(("error playing '%s' chunk %s (%d):",
- content__get_url(c), chunk, chunkseq));
+ content__get_url(&c->base), chunk, chunkseq));
LOG(("code %d severity %d extra1 %d extra2 %d text:'%s'", code,
severity, extra1, extra2, text));
- return (0);
+ return (0);
}
Index: image/bmp.h
===================================================================
--- image/bmp.h (revision 12276)
+++ image/bmp.h (working copy)
@@ -31,29 +31,15 @@
#include <libnsbmp.h>
#include "image/bitmap.h"
-struct content;
-struct bitmap;
-struct http_parameter;
-struct rect;
+extern bmp_bitmap_callback_vt bmp_bitmap_callbacks; /** Only to be used by ICO code. */
-struct content_bmp_data {
- bmp_image *bmp; /** BMP image data */
-};
+nserror nsbmp_init(void);
+void nsbmp_fini(void);
-extern bmp_bitmap_callback_vt bmp_bitmap_callbacks; /** Only to be used by ICO code. */
+#else
-bool nsbmp_create(struct content *c, const struct http_parameter *params);
-bool nsbmp_convert(struct content *c);
-void nsbmp_destroy(struct content *c);
-bool nsbmp_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool nsbmp_redraw_tiled(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y);
-bool nsbmp_clone(const struct content *old, struct content *new_content);
-void *nsbmp_bitmap_create(int width, int height, unsigned int bmp_state);
+#define nsbmp_init() NSERROR_OK
+#define nsbmp_fini() ((void) 0)
#endif /* WITH_BMP */
Index: image/png.c
===================================================================
--- image/png.c (revision 12276)
+++ image/png.c (working copy)
@@ -23,8 +23,7 @@
#include <string.h>
#include <stdlib.h>
-/* Ugh -- setjmp.h weirdness ensues if this isn't first... */
-#include "image/png.h"
+#include <png.h>
#include "utils/config.h"
@@ -33,14 +32,16 @@
#include "content/content_protected.h"
#include "image/bitmap.h"
+#include "image/png.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
#ifdef WITH_PNG
-/* accomodate for old versions of libpng (beware security holes!) */
+/* accommodate for old versions of libpng (beware security holes!) */
#ifndef png_jmpbuf
#warning you have an antique libpng
@@ -51,72 +52,190 @@
#define png_set_expand_gray_1_2_4_to_8(png) png_set_gray_1_2_4_to_8(png)
#endif
-/* libpng uses names starting png_, so use nspng_ here to avoid clashes */
+typedef struct nspng_content {
+ struct content base;
+ png_structp png;
+ png_infop info;
+ int interlace;
+ struct bitmap *bitmap; /**< Created NetSurf bitmap */
+ size_t rowstride, bpp; /**< Bitmap rowstride and bpp */
+ size_t rowbytes; /**< Number of bytes per row */
+} nspng_content;
+
+static nserror nspng_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror nspng_create_png_data(nspng_content *c);
+static bool nspng_process_data(struct content *c, const char *data,
+ unsigned int size);
+static bool nspng_convert(struct content *c);
+static void nspng_destroy(struct content *c);
+static bool nspng_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static bool nspng_redraw_tiled(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror nspng_clone(const struct content *old, struct content **newc);
+static content_type nspng_content_type(lwc_string *mime_type);
+
static void info_callback(png_structp png, png_infop info);
static void row_callback(png_structp png, png_bytep new_row,
png_uint_32 row_num, int pass);
static void end_callback(png_structp png, png_infop info);
+static const content_handler nspng_content_handler = {
+ nspng_create,
+ nspng_process_data,
+ nspng_convert,
+ NULL,
+ nspng_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nspng_redraw,
+ nspng_redraw_tiled,
+ NULL,
+ NULL,
+ nspng_clone,
+ NULL,
+ nspng_content_type,
+ false
+};
-bool nspng_create(struct content *c, const struct http_parameter *params)
+static const char *nspng_types[] = {
+ "image/png"
+};
+
+static lwc_string *nspng_mime_types[NOF_ELEMENTS(nspng_types)];
+
+nserror nspng_init(void)
{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(nspng_mime_types); i++) {
+ lerror = lwc_intern_string(nspng_types[i],
+ strlen(nspng_types[i]),
+ &nspng_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(nspng_mime_types[i],
+ &nspng_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nspng_fini();
+
+ return error;
+}
+
+void nspng_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(nspng_mime_types); i++) {
+ if (nspng_mime_types[i] != NULL)
+ lwc_string_unref(nspng_mime_types[i]);
+ }
+}
+
+nserror nspng_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ nspng_content *png;
+ nserror error;
+
+ png = talloc_zero(0, nspng_content);
+ if (png == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&png->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(png);
+ return error;
+ }
+
+ error = nspng_create_png_data(png);
+ if (error != NSERROR_OK) {
+ talloc_free(png);
+ return error;
+ }
+
+ *c = (struct content *) png;
+
+ return NSERROR_OK;
+}
+
+nserror nspng_create_png_data(nspng_content *c)
+{
union content_msg_data msg_data;
- c->data.png.bitmap = NULL;
+ c->bitmap = NULL;
- c->data.png.png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
- 0, 0, 0);
- if (c->data.png.png == NULL) {
+ c->png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
+ if (c->png == NULL) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
warn_user("NoMemory", 0);
- return false;
+ return NSERROR_NOMEM;
}
- c->data.png.info = png_create_info_struct(c->data.png.png);
- if (c->data.png.info == NULL) {
- png_destroy_read_struct(&c->data.png.png,
- &c->data.png.info, 0);
+ c->info = png_create_info_struct(c->png);
+ if (c->info == NULL) {
+ png_destroy_read_struct(&c->png, &c->info, 0);
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
warn_user("NoMemory", 0);
- return false;
+ return NSERROR_NOMEM;
}
- if (setjmp(png_jmpbuf(c->data.png.png))) {
- png_destroy_read_struct(&c->data.png.png,
- &c->data.png.info, 0);
+ if (setjmp(png_jmpbuf(c->png))) {
+ png_destroy_read_struct(&c->png, &c->info, 0);
LOG(("Failed to set callbacks"));
- c->data.png.png = NULL;
- c->data.png.info = NULL;
+ c->png = NULL;
+ c->info = NULL;
msg_data.error = messages_get("PNGError");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
- png_set_progressive_read_fn(c->data.png.png, c,
+ png_set_progressive_read_fn(c->png, c,
info_callback, row_callback, end_callback);
- return true;
+ return NSERROR_OK;
}
bool nspng_process_data(struct content *c, const char *data, unsigned int size)
{
+ nspng_content *png = (nspng_content *) c;
union content_msg_data msg_data;
- if (setjmp(png_jmpbuf(c->data.png.png))) {
- png_destroy_read_struct(&c->data.png.png,
- &c->data.png.info, 0);
+ if (setjmp(png_jmpbuf(png->png))) {
+ png_destroy_read_struct(&png->png, &png->info, 0);
LOG(("Failed to process data"));
- c->data.png.png = NULL;
- c->data.png.info = NULL;
- if (c->data.png.bitmap != NULL) {
- bitmap_destroy(c->data.png.bitmap);
- c->data.png.bitmap = NULL;
+ png->png = NULL;
+ png->info = NULL;
+ if (png->bitmap != NULL) {
+ bitmap_destroy(png->bitmap);
+ png->bitmap = NULL;
}
msg_data.error = messages_get("PNGError");
@@ -124,8 +243,7 @@
return false;
}
- png_process_data(c->data.png.png, c->data.png.info,
- (uint8_t *) data, size);
+ png_process_data(png->png, png->info, (uint8_t *) data, size);
return true;
}
@@ -141,21 +259,21 @@
int bit_depth, color_type, interlace, intent;
double gamma;
png_uint_32 width, height;
- struct content *c = png_get_progressive_ptr(png);
+ nspng_content *c = png_get_progressive_ptr(png);
/* Read the PNG details */
png_get_IHDR(png, info, &width, &height, &bit_depth,
&color_type, &interlace, 0, 0);
/* Claim the required memory for the converted PNG */
- c->data.png.bitmap = bitmap_create(width, height, BITMAP_NEW);
- if (c->data.png.bitmap == NULL) {
+ c->bitmap = bitmap_create(width, height, BITMAP_NEW);
+ if (c->bitmap == NULL) {
/* Failed -- bail out */
longjmp(png_jmpbuf(png), 1);
}
- c->data.png.rowstride = bitmap_get_rowstride(c->data.png.bitmap);
- c->data.png.bpp = bitmap_get_bpp(c->data.png.bitmap);
+ c->rowstride = bitmap_get_rowstride(c->bitmap);
+ c->bpp = bitmap_get_bpp(c->bitmap);
/* Set up our transformations */
if (color_type == PNG_COLOR_TYPE_PALETTE)
@@ -187,13 +305,13 @@
png_read_update_info(png, info);
- c->data.png.rowbytes = png_get_rowbytes(png, info);
- c->data.png.interlace = (interlace == PNG_INTERLACE_ADAM7);
- c->width = width;
- c->height = height;
+ c->rowbytes = png_get_rowbytes(png, info);
+ c->interlace = (interlace == PNG_INTERLACE_ADAM7);
+ c->base.width = width;
+ c->base.height = height;
LOG(("size %li * %li, bpp %i, rowbytes %zu", (unsigned long)width,
- (unsigned long)height, bit_depth, c->data.png.rowbytes));
+ (unsigned long)height, bit_depth, c->rowbytes));
}
@@ -205,13 +323,13 @@
void row_callback(png_structp png, png_bytep new_row,
png_uint_32 row_num, int pass)
{
- struct content *c = png_get_progressive_ptr(png);
- unsigned long i, j, rowbytes = c->data.png.rowbytes;
+ nspng_content *c = png_get_progressive_ptr(png);
+ unsigned long i, j, rowbytes = c->rowbytes;
unsigned int start, step;
unsigned char *buffer, *row;
/* Give up if there's no bitmap */
- if (c->data.png.bitmap == NULL)
+ if (c->bitmap == NULL)
return;
/* Abort if we've not got any data */
@@ -219,17 +337,17 @@
return;
/* Get bitmap buffer */
- buffer = bitmap_get_buffer(c->data.png.bitmap);
+ buffer = bitmap_get_buffer(c->bitmap);
if (buffer == NULL) {
/* No buffer, bail out */
longjmp(png_jmpbuf(png), 1);
}
/* Calculate address of row start */
- row = buffer + (c->data.png.rowstride * row_num);
+ row = buffer + (c->rowstride * row_num);
/* Handle interlaced sprites using the Adam7 algorithm */
- if (c->data.png.interlace) {
+ if (c->interlace) {
start = interlace_start[pass];
step = interlace_step[pass];
row_num = interlace_row_start[pass] +
@@ -237,7 +355,7 @@
/* Copy the data to our current row taking interlacing
* into consideration */
- row = buffer + (c->data.png.rowstride * row_num);
+ row = buffer + (c->rowstride * row_num);
for (j = 0, i = start; i < rowbytes; i += step) {
row[i++] = new_row[j++];
@@ -260,14 +378,15 @@
bool nspng_convert(struct content *c)
{
+ nspng_content *png = (nspng_content *) c;
const char *data;
unsigned long size;
char title[100];
- assert(c->data.png.png != NULL);
- assert(c->data.png.info != NULL);
+ assert(png->png != NULL);
+ assert(png->info != NULL);
- if (c->data.png.bitmap == NULL) {
+ if (png->bitmap == NULL) {
union content_msg_data msg_data;
msg_data.error = messages_get("PNGError");
@@ -278,7 +397,7 @@
data = content__get_source_data(c, &size);
- png_destroy_read_struct(&c->data.png.png, &c->data.png.info, 0);
+ png_destroy_read_struct(&png->png, &png->info, 0);
snprintf(title, sizeof(title), messages_get("PNGTitle"),
c->width, c->height, size);
@@ -286,7 +405,7 @@
c->size += (c->width * c->height * 4);
- c->bitmap = c->data.png.bitmap;
+ c->bitmap = png->bitmap;
bitmap_set_opaque(c->bitmap, bitmap_test_opaque(c->bitmap));
bitmap_modified(c->bitmap);
content_set_ready(c);
@@ -299,9 +418,11 @@
void nspng_destroy(struct content *c)
{
- if (c->data.png.bitmap != NULL) {
- bitmap_destroy(c->data.png.bitmap);
- }
+ nspng_content *png = (nspng_content *) c;
+
+ if (png->bitmap != NULL) {
+ bitmap_destroy(png->bitmap);
+ }
}
@@ -333,28 +454,54 @@
background_colour, flags);
}
-bool nspng_clone(const struct content *old, struct content *new_content)
+nserror nspng_clone(const struct content *old, struct content **newc)
{
+ nspng_content *png;
+ nserror error;
const char *data;
unsigned long size;
+ png = talloc_zero(0, nspng_content);
+ if (png == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &png->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&png->base);
+ return error;
+ }
+
/* Simply replay create/process/convert */
- if (nspng_create(new_content, NULL) == false)
- return false;
+ error = nspng_create_png_data(png);
+ if (error != NSERROR_OK) {
+ content_destroy(&png->base);
+ return error;
+ }
- data = content__get_source_data(new_content, &size);
+ data = content__get_source_data(&png->base, &size);
if (size > 0) {
- if (nspng_process_data(new_content, data, size) == false)
- return false;
+ if (nspng_process_data(&png->base, data, size) == false) {
+ content_destroy(&png->base);
+ return NSERROR_NOMEM;
+ }
}
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nspng_convert(new_content) == false)
- return false;
+ if (nspng_convert(&png->base) == false) {
+ content_destroy(&png->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) png;
+
+ return NSERROR_OK;
}
+content_type nspng_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
+
#endif
Index: image/jpeg.c
===================================================================
--- image/jpeg.c (revision 12276)
+++ image/jpeg.c (working copy)
@@ -26,20 +26,19 @@
#include "utils/config.h"
#ifdef WITH_JPEG
-/* This must come first due to libpng issues */
-#include "content/content_protected.h"
-
#include <assert.h>
#include <setjmp.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include "content/content_protected.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
#define JPEG_INTERNAL_OPTIONS
@@ -57,12 +56,30 @@
static char nsjpeg_error_buffer[JMSG_LENGTH_MAX];
+typedef struct nsjpeg_content {
+ struct content base;
+} nsjpeg_content;
struct nsjpeg_error_mgr {
struct jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
+static nserror nsjpeg_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool nsjpeg_convert(struct content *c);
+static void nsjpeg_destroy(struct content *c);
+static bool nsjpeg_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static bool nsjpeg_redraw_tiled(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror nsjpeg_clone(const struct content *old, struct content **newc);
+static content_type nsjpeg_content_type(lwc_string *mime_type);
static void nsjpeg_error_exit(j_common_ptr cinfo);
static void nsjpeg_init_source(j_decompress_ptr cinfo);
@@ -70,7 +87,96 @@
static void nsjpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes);
static void nsjpeg_term_source(j_decompress_ptr cinfo);
+static const content_handler nsjpeg_content_handler = {
+ nsjpeg_create,
+ NULL,
+ nsjpeg_convert,
+ NULL,
+ nsjpeg_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nsjpeg_redraw,
+ nsjpeg_redraw_tiled,
+ NULL,
+ NULL,
+ nsjpeg_clone,
+ NULL,
+ nsjpeg_content_type,
+ false
+};
+static const char *nsjpeg_types[] = {
+ "image/jpeg",
+ "image/jpg",
+ "image/pjpeg"
+};
+
+static lwc_string *nsjpeg_mime_types[NOF_ELEMENTS(nsjpeg_types)];
+
+nserror nsjpeg_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(nsjpeg_mime_types); i++) {
+ lerror = lwc_intern_string(nsjpeg_types[i],
+ strlen(nsjpeg_types[i]),
+ &nsjpeg_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(nsjpeg_mime_types[i],
+ &nsjpeg_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nsjpeg_fini();
+
+ return error;
+}
+
+void nsjpeg_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(nsjpeg_mime_types); i++) {
+ if (nsjpeg_mime_types[i] != NULL)
+ lwc_string_unref(nsjpeg_mime_types[i]);
+ }
+}
+
+nserror nsjpeg_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ nsjpeg_content *jpeg;
+ nserror error;
+
+ jpeg = talloc_zero(0, nsjpeg_content);
+ if (jpeg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&jpeg->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(jpeg);
+ return error;
+ }
+
+ *c = (struct content *) jpeg;
+
+ return NSERROR_OK;
+}
+
/**
* Convert a CONTENT_JPEG for display.
*/
@@ -286,16 +392,38 @@
}
-bool nsjpeg_clone(const struct content *old, struct content *new_content)
+nserror nsjpeg_clone(const struct content *old, struct content **newc)
{
+ nsjpeg_content *jpeg;
+ nserror error;
+
+ jpeg = talloc_zero(0, nsjpeg_content);
+ if (jpeg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &jpeg->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&jpeg->base);
+ return error;
+ }
+
/* Simply replay conversion */
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nsjpeg_convert(new_content) == false)
- return false;
+ if (nsjpeg_convert(&jpeg->base) == false) {
+ content_destroy(&jpeg->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) jpeg;
+
+ return NSERROR_OK;
}
+content_type nsjpeg_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
+
#endif /* WITH_JPEG */
Index: image/mng.h
===================================================================
--- image/mng.h (revision 12276)
+++ image/mng.h (working copy)
@@ -28,32 +28,13 @@
#include <stdbool.h>
-struct content;
-struct http_parameter;
-struct rect;
+nserror nsmng_init(void);
+void nsmng_fini(void);
-struct content_mng_data {
- bool opaque_test_pending;
- bool read_start;
- bool read_resume;
- int read_size;
- bool waiting;
- bool displayed;
- void *handle;
-};
+#else
-bool nsmng_create(struct content *c, const struct http_parameter *params);
-bool nsmng_process_data(struct content *c, const char *data, unsigned int size);
-bool nsmng_convert(struct content *c);
-void nsmng_destroy(struct content *c);
-bool nsmng_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool nsmng_redraw_tiled(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y);
-bool nsmng_clone(const struct content *old, struct content *new_content);
+#define nsmng_init() NSERROR_OK
+#define nsmng_fini() ((void) 0)
#endif /* WITH_MNG */
Index: image/rsvg.h
===================================================================
--- image/rsvg.h (revision 12276)
+++ image/rsvg.h (working copy)
@@ -27,31 +27,17 @@
#ifdef WITH_RSVG
#include <stdbool.h>
-#include <librsvg/rsvg.h>
-#include <cairo.h>
-#include "desktop/plot_style.h"
-#include "image/bitmap.h"
-struct content;
-struct http_parameter;
-struct rect;
+#include "utils/errors.h"
-struct content_rsvg_data {
- RsvgHandle *rsvgh; /**< Context handle for RSVG renderer */
- cairo_surface_t *cs; /**< The surface built inside a nsbitmap */
- cairo_t *ct; /**< Cairo drawing context */
- struct bitmap *bitmap; /**< Created NetSurf bitmap */
-};
+nserror nsrsvg_init(void);
+void nsrsvg_fini(void);
-bool rsvg_create(struct content *c, const struct http_parameter *params);
-bool rsvg_process_data(struct content *c, const char *data, unsigned int size);
-bool rsvg_convert(struct content *c);
-void rsvg_destroy(struct content *c);
-bool rsvg_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool rsvg_clone(const struct content *old, struct content *new_content);
+#else
+#define nsrsvg_init() NSERROR_OK
+#define nsrsvg_fini() ((void) 0)
+
#endif /* WITH_RSVG */
#endif
Index: image/png.h
===================================================================
--- image/png.h (revision 12276)
+++ image/png.h (working copy)
@@ -24,38 +24,18 @@
#ifdef WITH_PNG
-#include "desktop/plot_style.h"
-
#include <stdbool.h>
-#include <png.h>
-struct content;
-struct bitmap;
-struct http_parameter;
-struct rect;
+#include "utils/errors.h"
-struct content_png_data {
- png_structp png;
- png_infop info;
- int interlace;
- struct bitmap *bitmap; /**< Created NetSurf bitmap */
- size_t rowstride, bpp; /**< Bitmap rowstride and bpp */
- size_t rowbytes; /**< Number of bytes per row */
-};
+nserror nspng_init(void);
+void nspng_fini(void);
-bool nspng_create(struct content *c, const struct http_parameter *params);
-bool nspng_process_data(struct content *c, const char *data, unsigned int size);
-bool nspng_convert(struct content *c);
-void nspng_destroy(struct content *c);
-bool nspng_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool nspng_redraw_tiled(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y);
-bool nspng_clone(const struct content *old, struct content *new_content);
+#else
+#define nspng_init() NSERROR_OK
+#define nspng_fini() ((void) 0)
+
#endif
#endif
Index: image/jpeg.h
===================================================================
--- image/jpeg.h (revision 12276)
+++ image/jpeg.h (working copy)
@@ -28,25 +28,16 @@
#include <stdbool.h>
-struct bitmap;
-struct content;
-struct rect;
+#include "utils/errors.h"
-struct content_jpeg_data {
- int dummy; /* NOT USED but to satisfy Norcroft */
-};
+nserror nsjpeg_init(void);
+void nsjpeg_fini(void);
-bool nsjpeg_convert(struct content *c);
-void nsjpeg_destroy(struct content *c);
-bool nsjpeg_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool nsjpeg_redraw_tiled(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y);
-bool nsjpeg_clone(const struct content *old, struct content *new_content);
+#else
+#define nsjpeg_init() NSERROR_OK
+#define nsjpeg_fini() ((void) 0)
+
#endif /* WITH_JPEG */
#endif
Index: image/webp.c
===================================================================
--- image/webp.c (revision 12276)
+++ image/webp.c (working copy)
@@ -33,8 +33,114 @@
#include "content/content_protected.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
+typedef struct webp_content
+{
+ struct content base;
+} webp_content;
+
+static nserror webp_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool webp_convert(struct content *c);
+static void webp_destroy(struct content *c);
+static bool webp_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static nserror webp_clone(const struct content *old, struct content **newc);
+static content_type webp_content_type(lwc_string *mime_type);
+
+static const content_handler webp_content_handler = {
+ webp_create,
+ NULL,
+ webp_convert,
+ webp_reformat,
+ webp_destroy,
+ NULL,
+ NULL,
+ NULL,
+ webp_redraw,
+ NULL,
+ NULL,
+ NULL,
+ webp_clone,
+ NULL,
+ webp_content_type,
+ false
+};
+
+static const char *webp_types[] = {
+ "image/webp"
+};
+
+static lwc_string *webp_mime_types[NOF_ELEMENTS(webp_types)];
+
+nserror webp_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(webp_mime_types); i++) {
+ lerror = lwc_intern_string(webp_types[i],
+ strlen(webp_types[i]),
+ &webp_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(webp_mime_types[i],
+ &webp_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nswebp_fini();
+
+ return error;
+}
+
+void webp_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(webp_mime_types); i++) {
+ if (webp_mime_types[i] != NULL)
+ lwc_string_unref(webp_mime_types[i]);
+ }
+}
+
+nserror webp_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ webp_content *webp;
+ nserror error;
+
+ webp = talloc_zero(0, webp_content);
+ if (webp == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&webp->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(webp);
+ return error;
+ }
+
+ *c = (struct content *) webp;
+
+ return NSERROR_OK;
+}
+
/**
* Convert a CONTENT_WEBP for display.
*
@@ -124,16 +230,38 @@
}
-bool webp_clone(const struct content *old, struct content *new_content)
+nserror webp_clone(const struct content *old, struct content **newc)
{
+ webp_content *webp;
+ nserror error;
+
+ webp = talloc_zero(0, webp_content);
+ if (webp == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &webp->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&webp->base);
+ return error;
+ }
+
/* Simply replay convert */
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (webp_convert(new_content) == false)
- return false;
+ if (webp_convert(&webp->base) == false) {
+ content_destroy(&webp->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) webp;
+
+ return NSERROR_OK;
}
+content_type webp_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
+
#endif
Index: cocoa/NetsurfApp.m
===================================================================
--- cocoa/NetsurfApp.m (revision 12276)
+++ cocoa/NetsurfApp.m (working copy)
@@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#import "cocoa/apple_image.h"
#import "cocoa/NetsurfApp.h"
#import "cocoa/gui.h"
#import "cocoa/plotter.h"
@@ -178,6 +179,8 @@
option_ca_bundle = strdup( [[[NSBundle mainBundle] pathForResource: @"ca-bundle" ofType: @""] UTF8String] );
netsurf_init(&argc, &argv, options, messages);
+
+ apple_image_init();
NSApplication *app = cocoa_prepare_app();
@@ -191,6 +194,8 @@
[app run];
netsurf_exit();
+
+ apple_image_fini();
return 0;
}
Index: cocoa/apple_image.h
===================================================================
--- cocoa/apple_image.h (revision 12276)
+++ cocoa/apple_image.h (working copy)
@@ -20,35 +20,19 @@
#ifndef _NETSURF_COCOA_APPLE_IMAGE_H_
#define _NETSURF_COCOA_APPLE_IMAGE_H_
-#ifdef WITH_APPLE_IMAGE
-
-#ifdef WITH_JPEG
-#error "Don't define WITH_JPEG and WITH_APPLE_IMAGE"
-#endif
-
#include "utils/config.h"
-#include "desktop/plot_style.h"
+#include "utils/errors.h"
-struct bitmap;
-struct content;
-struct rect;
+#ifdef WITH_APPLE_IMAGE
-struct content_apple_image_data {
-};
+nserror apple_image_init(void);
+void apple_image_fini(void);
-bool apple_image_convert(struct content *c);
-void apple_image_destroy(struct content *c);
+#else
-bool apple_image_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool apple_image_redraw_tiled(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y);
+#define apple_image_init() NSERROR_OK
+#define apple_image_fini() ((void) 0)
-bool apple_image_clone(const struct content *old, struct content *new_content);
-
#endif /* WITH_APPLE_IMAGE */
#endif
Index: cocoa/apple_image.m
===================================================================
--- cocoa/apple_image.m (revision 12276)
+++ cocoa/apple_image.m (working copy)
@@ -24,7 +24,120 @@
#include "content/content_protected.h"
#include "image/bitmap.h"
#include "desktop/plotters.h"
+#include "utils/talloc.h"
+typedef struct apple_image_content {
+ struct content base;
+} apple_image_content;
+
+static nserror apple_image_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool apple_image_convert(struct content *c);
+static void apple_image_destroy(struct content *c);
+static bool apple_image_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static bool apple_image_redraw_tiled(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror apple_image_clone(const struct content *old,
+ struct content **newc);
+static content_type apple_image_content_type(lwc_string *mime_type);
+
+static const content_handler apple_image_content_handler = {
+ apple_image_create,
+ NULL,
+ apple_image_convert,
+ NULL,
+ apple_image_destroy,
+ NULL,
+ NULL,
+ NULL,
+ apple_image_redraw,
+ apple_image_redraw_tiled,
+ NULL,
+ NULL,
+ apple_image_clone,
+ NULL,
+ apple_image_content_type,
+ false
+};
+
+static const char *apple_image_types[] = {
+ "image/jpeg",
+ "image/jpg",
+ "image/pjpeg"
+};
+
+static lwc_string *apple_image_mime_types[NOF_ELEMENTS(apple_image_types)];
+
+nserror apple_image_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(apple_image_mime_types); i++) {
+ lerror = lwc_intern_string(apple_image_types[i],
+ strlen(apple_image_types[i]),
+ &apple_image_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(
+ apple_image_mime_types[i],
+ &apple_image_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ apple_image_fini();
+
+ return error;
+}
+
+void apple_image_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(apple_image_mime_types); i++) {
+ if (apple_image_mime_types[i] != NULL)
+ lwc_string_unref(apple_image_mime_types[i]);
+ }
+}
+
+nserror apple_image_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ apple_image_content *ai;
+ nserror error;
+
+ ai = talloc_zero(0, apple_image_content);
+ if (ai == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&ai->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(ai);
+ return error;
+ }
+
+ *c = (struct content *) ai;
+
+ return NSERROR_OK;
+}
+
/**
* Convert a CONTENT_APPLE_IMAGE for display.
*/
@@ -67,18 +180,37 @@
}
-bool apple_image_clone(const struct content *old, struct content *new_content)
+nserror apple_image_clone(const struct content *old, struct content **newc)
{
+ apple_image_content *ai;
+ nserror error;
+
+ ai = talloc_zero(0, apple_image_content);
+ if (ai == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &ai->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&ai->base);
+ return error;
+ }
+
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- new_content->width = old->width;
- new_content->height = old->height;
- new_content->bitmap = (void *)[(id)old->bitmap retain];
+ ai->base.width = old->width;
+ ai->base.height = old->height;
+ ai->base.bitmap = (void *)[(id)old->bitmap retain];
}
+
+ *newc = (struct content *) ai;
- return true;
+ return NSERROR_OK;
}
+content_type apple_image_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
/**
* Redraw a CONTENT_APPLE_IMAGE.
Index: cocoa/gui.m
===================================================================
--- cocoa/gui.m (revision 12276)
+++ cocoa/gui.m (working copy)
@@ -258,11 +258,6 @@
void gui_window_set_icon(struct gui_window *g, hlcache_handle *icon)
{
-#ifdef WITH_BMP
- if (icon != NULL && content_get_type( icon ) == CONTENT_ICO)
- nsico_set_bitmap_from_size( icon, 16, 16 );
-#endif
-
NSBitmapImageRep *bmp = icon != NULL ? (NSBitmapImageRep *)content_get_bitmap( icon ) : NULL;
NSImage *image = nil;
Index: cocoa/save.m
===================================================================
--- cocoa/save.m (revision 12276)
+++ cocoa/save.m (working copy)
@@ -23,7 +23,7 @@
#define UNIMPL() NSLog( @"Function '%s' unimplemented", __func__ )
bool save_complete_gui_save(const char *path, const char *filename,
- size_t len, const char *sourcedata, content_type type)
+ size_t len, const char *sourcedata, lwc_string *mime_type)
{
UNIMPL();
return false;
Index: framebuffer/save.c
===================================================================
--- framebuffer/save.c (revision 12276)
+++ framebuffer/save.c (working copy)
@@ -30,7 +30,7 @@
*/
bool save_complete_gui_save(const char *path, const char *filename, size_t len,
- const char *sourcedata, content_type type)
+ const char *sourcedata, lwc_string *mime_type)
{
return false;
}
Index: framebuffer/tree.c
===================================================================
--- framebuffer/tree.c (revision 12276)
+++ framebuffer/tree.c (working copy)
@@ -37,35 +37,7 @@
case CONTENT_HTML:
case CONTENT_TEXTPLAIN:
case CONTENT_CSS:
-#if defined(WITH_MNG) || defined(WITH_PNG)
- case CONTENT_PNG:
-#endif
-#ifdef WITH_MNG
- case CONTENT_JNG:
- case CONTENT_MNG:
-#endif
-#ifdef WITH_JPEG
- case CONTENT_JPEG:
-#endif
-#ifdef WITH_GIF
- case CONTENT_GIF:
-#endif
-#ifdef WITH_BMP
- case CONTENT_BMP:
- case CONTENT_ICO:
-#endif
-#ifdef WITH_SPRITE
- case CONTENT_SPRITE:
-#endif
-#ifdef WITH_DRAW
- case CONTENT_DRAW:
-#endif
-#ifdef WITH_ARTWORKS
- case CONTENT_ARTWORKS:
-#endif
-#ifdef WITH_NS_SVG
- case CONTENT_SVG:
-#endif
+ case CONTENT_IMAGE:
default:
sprintf(buffer, tree_content_icon_name);
break;
Index: gtk/scaffolding.c
===================================================================
--- gtk/scaffolding.c (revision 12276)
+++ gtk/scaffolding.c (working copy)
@@ -1994,11 +1994,6 @@
if (g->top_level != _g)
return;
-#ifdef WITH_BMP
- if (icon != NULL && content_get_type(icon) == CONTENT_ICO)
- nsico_set_bitmap_from_size(icon, 16, 16);
-#endif
-
icon_bitmap = (icon != NULL) ? content_get_bitmap(icon) : NULL;
if (icon_bitmap != NULL) {
@@ -2039,11 +2034,6 @@
if (ico == NULL && (ico = search_web_ico()) == NULL)
return;
-#ifdef WITH_BMP
- if (content_get_type(ico) == CONTENT_ICO)
- nsico_set_bitmap_from_size(ico, 20, 20);
-#endif
-
ico_bitmap = content_get_bitmap(ico);
if (ico_bitmap == NULL)
return;
Index: gtk/save.c
===================================================================
--- gtk/save.c (revision 12276)
+++ gtk/save.c (working copy)
@@ -36,7 +36,7 @@
*/
bool save_complete_gui_save(const char *path, const char *filename,
- size_t len, const char *sourcedata, content_type type)
+ size_t len, const char *sourcedata, lwc_string *mime_type)
{
int res;
int namelen;
Index: gtk/treeview.c
===================================================================
--- gtk/treeview.c (revision 12276)
+++ gtk/treeview.c (working copy)
@@ -98,35 +98,7 @@
case CONTENT_HTML:
case CONTENT_TEXTPLAIN:
case CONTENT_CSS:
-#if defined(WITH_MNG) || defined(WITH_PNG)
- case CONTENT_PNG:
-#endif
-#ifdef WITH_MNG
- case CONTENT_JNG:
- case CONTENT_MNG:
-#endif
-#ifdef WITH_JPEG
- case CONTENT_JPEG:
-#endif
-#ifdef WITH_GIF
- case CONTENT_GIF:
-#endif
-#ifdef WITH_BMP
- case CONTENT_BMP:
- case CONTENT_ICO:
-#endif
-#ifdef WITH_SPRITE
- case CONTENT_SPRITE:
-#endif
-#ifdef WITH_DRAW
- case CONTENT_DRAW:
-#endif
-#ifdef WITH_ARTWORKS
- case CONTENT_ARTWORKS:
-#endif
-#ifdef WITH_NS_SVG
- case CONTENT_SVG:
-#endif
+ case CONTENT_IMAGE:
default:
sprintf(buffer, tree_content_icon_name);
break;
Index: beos/beos_save_complete.cpp
===================================================================
--- beos/beos_save_complete.cpp (revision 12276)
+++ beos/beos_save_complete.cpp (working copy)
@@ -39,7 +39,7 @@
*/
bool save_complete_gui_save(const char *path, const char *filename,
- size_t len, const char *sourcedata, content_type type)
+ size_t len, const char *sourcedata, lwc_string *mime_type)
{
int res;
int namelen;
Index: css/select.c
===================================================================
--- css/select.c (revision 12276)
+++ css/select.c (working copy)
@@ -99,7 +99,7 @@
static bool parse_number(const char *data, bool non_negative, bool real,
css_fixed *value, size_t *consumed);
-static css_computed_style *nscss_get_initial_style(struct content *html,
+static css_computed_style *nscss_get_initial_style(nscss_select_ctx *ctx,
css_allocator_fn, void *pw);
static bool isWhitespace(char c);
@@ -211,7 +211,7 @@
/**
* Get a style selection results (partial computed styles) for an element
*
- * \param html HTML document
+ * \param ctx CSS selection context
* \param n Element to select for
* \param media Permitted media types
* \param inline_style Inline style associated with element, or NULL
@@ -220,17 +220,15 @@
* \return Pointer to selection results (containing partial computed styles),
* or NULL on failure
*/
-css_select_results *nscss_get_style(struct content *html, xmlNode *n,
+css_select_results *nscss_get_style(nscss_select_ctx *ctx, xmlNode *n,
uint64_t media, const css_stylesheet *inline_style,
css_allocator_fn alloc, void *pw)
{
css_select_results *styles;
css_error error;
- assert(html->type == CONTENT_HTML);
-
- error = css_select_style(html->data.html.select_ctx, n, media,
- inline_style, &selection_handler, html, &styles);
+ error = css_select_style(ctx->ctx, n, media, inline_style,
+ &selection_handler, ctx, &styles);
if (error != CSS_OK) {
return NULL;
}
@@ -241,24 +239,22 @@
/**
* Get an initial style
*
- * \param html HTML document
+ * \param ctx CSS selection context
* \param alloc Memory allocation function
* \param pw Private word for allocator
* \return Pointer to partial computed style, or NULL on failure
*/
-css_computed_style *nscss_get_initial_style(struct content *html,
+css_computed_style *nscss_get_initial_style(nscss_select_ctx *ctx,
css_allocator_fn alloc, void *pw)
{
css_computed_style *style;
css_error error;
- assert(html->type == CONTENT_HTML);
-
error = css_computed_style_create(alloc, pw, &style);
if (error != CSS_OK)
return NULL;
- error = css_computed_style_initialise(style, &selection_handler, html);
+ error = css_computed_style_initialise(style, &selection_handler, ctx);
if (error != CSS_OK) {
css_computed_style_destroy(style);
return NULL;
@@ -270,22 +266,20 @@
/**
* Get a blank style
*
- * \param html HTML document
+ * \param ctx CSS selection context
* \param parent Parent style to cascade inherited properties from
* \param alloc Memory allocation function
* \param pw Private word for allocator
* \return Pointer to blank style, or NULL on failure
*/
-css_computed_style *nscss_get_blank_style(struct content *html,
+css_computed_style *nscss_get_blank_style(nscss_select_ctx *ctx,
const css_computed_style *parent,
css_allocator_fn alloc, void *pw)
{
css_computed_style *partial;
css_error error;
- assert(html->type == CONTENT_HTML);
-
- partial = nscss_get_initial_style(html, alloc, pw);
+ partial = nscss_get_initial_style(ctx, alloc, pw);
if (partial == NULL)
return NULL;
@@ -877,7 +871,7 @@
css_error node_has_class(void *pw, void *node,
lwc_string *name, bool *match)
{
- struct content *html = pw;
+ nscss_select_ctx *ctx = pw;
xmlNode *n = node;
xmlAttr *class;
xmlChar *value = NULL;
@@ -888,7 +882,7 @@
int (*cmp)(const char *, const char *, size_t);
/* Class names are case insensitive in quirks mode */
- if (html->data.html.quirks == BINDING_QUIRKS_MODE_FULL)
+ if (ctx->quirks)
cmp = strncasecmp;
else
cmp = strncmp;
@@ -1418,7 +1412,7 @@
/** \todo Implement visted check in a more performant way */
#ifdef SUPPORT_VISITED
- struct content *html = pw;
+ nscss_select_ctx *ctx = pw;
xmlNode *n = node;
if (strcasecmp((const char *) n->name, "a") == 0) {
@@ -1430,8 +1424,7 @@
return CSS_OK;
/* Make href absolute */
- res = url_join((const char *) href,
- html->data.html.base_url, &url);
+ res = url_join((const char *) href, ctx->base_url, &url);
xmlFree(href);
@@ -1632,7 +1625,7 @@
css_error node_presentational_hint(void *pw, void *node,
uint32_t property, css_hint *hint)
{
- struct content *html = pw;
+ nscss_select_ctx *ctx = pw;
xmlNode *n = node;
if (property == CSS_PROP_BACKGROUND_IMAGE) {
@@ -1644,8 +1637,7 @@
return CSS_PROPERTY_NOT_SET;
- res = url_join((const char *) bg,
- html->data.html.base_url, &url);
+ res = url_join((const char *) bg, ctx->base_url, &url);
xmlFree(bg);
@@ -1707,7 +1699,7 @@
css_error error;
bool is_link, is_visited;
- error = node_is_link(html, n, &is_link);
+ error = node_is_link(ctx, n, &is_link);
if (error != CSS_OK)
return error;
@@ -1720,7 +1712,7 @@
break;
}
- error = node_is_visited(html, n, &is_visited);
+ error = node_is_visited(ctx, n, &is_visited);
if (error != CSS_OK)
return error;
Index: css/select.h
===================================================================
--- css/select.h (revision 12276)
+++ css/select.h (working copy)
@@ -27,15 +27,25 @@
struct content;
+/**
+ * Selection context
+ */
+typedef struct nscss_select_ctx
+{
+ css_select_ctx *ctx;
+ bool quirks;
+ const char *base_url;
+} nscss_select_ctx;
+
css_stylesheet *nscss_create_inline_style(const uint8_t *data, size_t len,
const char *charset, const char *url, bool allow_quirks,
css_allocator_fn alloc, void *pw);
-css_select_results *nscss_get_style(struct content *html, xmlNode *n,
+css_select_results *nscss_get_style(nscss_select_ctx *ctx, xmlNode *n,
uint64_t media, const css_stylesheet *inline_style,
css_allocator_fn alloc, void *pw);
-css_computed_style *nscss_get_blank_style(struct content *html,
+css_computed_style *nscss_get_blank_style(nscss_select_ctx *ctx,
const css_computed_style *parent,
css_allocator_fn alloc, void *pw);
Index: css/css.c
===================================================================
--- css/css.c (revision 12276)
+++ css/css.c (working copy)
@@ -31,11 +31,22 @@
#include "utils/http.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
/* Define to trace import fetches */
#undef NSCSS_IMPORT_TRACE
/**
+ * CSS content data
+ */
+typedef struct nscss_content
+{
+ struct content base; /**< Underlying content object */
+
+ struct content_css_data data; /**< CSS data */
+} nscss_content;
+
+/**
* Context for import fetches
*/
typedef struct {
@@ -44,6 +55,18 @@
* imports array */
} nscss_import_ctx;
+static nserror nscss_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool nscss_process_data(struct content *c, const char *data,
+ unsigned int size);
+static bool nscss_convert(struct content *c);
+static void nscss_destroy(struct content *c);
+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(lwc_string *mime_type);
+
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);
@@ -55,13 +78,56 @@
static css_error nscss_register_import(struct content_css_data *c,
const hlcache_handle *import);
+static const content_handler css_content_handler = {
+ nscss_create,
+ nscss_process_data,
+ nscss_convert,
+ NULL,
+ nscss_destroy,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ nscss_clone,
+ nscss_matches_quirks,
+ nscss_content_type,
+ false
+};
+
+static lwc_string *css_mime_type;
static css_stylesheet *blank_import;
/**
- * Clean up after the CSS subsystem
+ * Initialise the CSS content handler
*/
-void css_cleanup(void)
+nserror css_init(void)
{
+ lwc_error lerror;
+ nserror error;
+
+ lerror = lwc_intern_string("text/css", SLEN("text/css"),
+ &css_mime_type);
+ if (lerror != lwc_error_ok)
+ return NSERROR_NOMEM;
+
+ error = content_factory_register_handler(css_mime_type,
+ &css_content_handler);
+ if (error != NSERROR_OK)
+ lwc_string_unref(css_mime_type);
+
+ return error;
+}
+
+/**
+ * Clean up after the CSS content handler
+ */
+void css_fini(void)
+{
+ lwc_string_unref(css_mime_type);
+
if (blank_import != NULL)
css_stylesheet_destroy(blank_import);
}
@@ -73,32 +139,49 @@
* \param params Content-Type parameters
* \return true on success, false on failure
*/
-bool nscss_create(struct content *c, const http_parameter *params)
+nserror nscss_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
{
+ nscss_content *result;
const char *charset = NULL;
union content_msg_data msg_data;
nserror error;
- /** \todo what happens about the allocator? */
- /** \todo proper error reporting */
+ result = talloc_zero(0, nscss_content);
+ if (result == NULL)
+ return NSERROR_NOMEM;
+ error = content__init(&result->base, handler, imime_type,
+ params, llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(result);
+ return error;
+ }
+
/* Find charset specified on HTTP layer, if any */
error = http_parameter_list_find_item(params, "charset", &charset);
if (error != NSERROR_OK || *charset == '\0') {
/* No charset specified, use fallback, if any */
/** \todo libcss will take this as gospel, which is wrong */
- charset = c->fallback_charset;
+ charset = fallback_charset;
}
- if (nscss_create_css_data(&c->data.css, content__get_url(c),
- charset, c->quirks,
- nscss_content_done, c) != NSERROR_OK) {
+ error = nscss_create_css_data(&result->data,
+ content__get_url(&result->base),
+ charset, result->base.quirks,
+ nscss_content_done, result);
+ if (error != NSERROR_OK) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&result->base, CONTENT_MSG_ERROR, msg_data);
+ talloc_free(result);
+ return error;
}
- return true;
+ *c = (struct content *) result;
+
+ return NSERROR_OK;
}
/**
@@ -163,10 +246,11 @@
*/
bool nscss_process_data(struct content *c, const char *data, unsigned int size)
{
+ nscss_content *css = (nscss_content *) c;
union content_msg_data msg_data;
css_error error;
- error = nscss_process_css_data(&c->data.css, data, size);
+ error = nscss_process_css_data(&css->data, data, size);
if (error != CSS_OK && error != CSS_NEEDDATA) {
msg_data.error = "?";
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
@@ -198,10 +282,11 @@
*/
bool nscss_convert(struct content *c)
{
+ nscss_content *css = (nscss_content *) c;
union content_msg_data msg_data;
css_error error;
- error = nscss_convert_css_data(&c->data.css);
+ error = nscss_convert_css_data(&css->data);
if (error != CSS_OK) {
msg_data.error = "?";
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
@@ -256,7 +341,9 @@
*/
void nscss_destroy(struct content *c)
{
- nscss_destroy_css_data(&c->data.css);
+ nscss_content *css = (nscss_content *) c;
+
+ nscss_destroy_css_data(&css->data);
}
/**
@@ -285,35 +372,78 @@
free(c->charset);
}
-bool nscss_clone(const struct content *old, struct content *new_content)
+nserror nscss_clone(const struct content *old, struct content **newc)
{
+ const nscss_content *old_css = (const nscss_content *) old;
+ nscss_content *new_css;
const char *data;
unsigned long size;
+ nserror error;
+ new_css = talloc_zero(0, nscss_content);
+ if (new_css == NULL)
+ return NSERROR_NOMEM;
+
+ /* Clone content */
+ error = content__clone(old, &new_css->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&new_css->base);
+ return error;
+ }
+
/* Simply replay create/process/convert */
- if (nscss_create_css_data(&new_content->data.css,
- content__get_url(new_content),
- old->data.css.charset,
- new_content->quirks,
- nscss_content_done, new_content) != NSERROR_OK)
- return false;
+ error = nscss_create_css_data(&new_css->data,
+ content__get_url(&new_css->base),
+ old_css->data.charset,
+ new_css->base.quirks,
+ nscss_content_done, new_css);
+ if (error != NSERROR_OK) {
+ content_destroy(&new_css->base);
+ return error;
+ }
- data = content__get_source_data(new_content, &size);
+ data = content__get_source_data(&new_css->base, &size);
if (size > 0) {
- if (nscss_process_data(new_content, data, size) == false)
- return false;
+ if (nscss_process_data(&new_css->base, data, size) == false) {
+ content_destroy(&new_css->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nscss_convert(new_content) == false)
- return false;
+ if (nscss_convert(&new_css->base) == false) {
+ content_destroy(&new_css->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) new_css;
+
+ return NSERROR_OK;
}
+bool nscss_matches_quirks(const struct content *c, bool quirks)
+{
+ return c->quirks == quirks;
+}
+
/**
+ * Retrieve the stylesheet object associated with a CSS content
+ *
+ * \param h Stylesheet content
+ * \return Pointer to stylesheet object
+ */
+css_stylesheet *nscss_get_stylesheet(struct hlcache_handle *h)
+{
+ nscss_content *c = (nscss_content *) hlcache_handle_get_content(h);
+
+ assert(c != NULL);
+
+ return c->data.sheet;
+}
+
+/**
* Retrieve imported stylesheets
*
* \param h Stylesheet containing imports
@@ -322,17 +452,27 @@
*/
struct nscss_import *nscss_get_imports(hlcache_handle *h, uint32_t *n)
{
- struct content *c = hlcache_handle_get_content(h);
+ nscss_content *c = (nscss_content *) hlcache_handle_get_content(h);
assert(c != NULL);
- assert(c->type == CONTENT_CSS);
assert(n != NULL);
- *n = c->data.css.import_count;
+ *n = c->data.import_count;
- return c->data.css.imports;
+ return c->data.imports;
}
+/**
+ * Compute the type of a content
+ *
+ * \param mime_type MIME type
+ * \return CONTENT_CSS
+ */
+content_type nscss_content_type(lwc_string *mime_type)
+{
+ return CONTENT_CSS;
+}
+
/*****************************************************************************
* Object completion *
*****************************************************************************/
@@ -394,7 +534,7 @@
css_error nscss_handle_import(void *pw, css_stylesheet *parent,
lwc_string *url, uint64_t media)
{
- static const content_type accept[] = { CONTENT_CSS, CONTENT_UNKNOWN };
+ content_type accept = CONTENT_CSS;
struct content_css_data *c = pw;
nscss_import_ctx *ctx;
hlcache_child_context child;
@@ -478,9 +618,6 @@
switch (event->type) {
case CONTENT_MSG_LOADING:
- if (content_get_type(handle) != CONTENT_CSS) {
- assert(0 && "Non-CSS type unexpected");
- }
break;
case CONTENT_MSG_READY:
break;
@@ -589,8 +726,9 @@
css_error error;
if (import != NULL) {
- struct content *s = hlcache_handle_get_content(import);
- sheet = s->data.css.sheet;
+ nscss_content *s =
+ (nscss_content *) hlcache_handle_get_content(import);
+ sheet = s->data.sheet;
} else {
/* Create a blank sheet if needed. */
if (blank_import == NULL) {
Index: css/css.h
===================================================================
--- css/css.h (revision 12276)
+++ css/css.h (working copy)
@@ -61,18 +61,9 @@
uint64_t media; /**< Media types that sheet applies to */
};
-void css_cleanup(void);
+nserror css_init(void);
+void css_fini(void);
-bool nscss_create(struct content *c, const struct http_parameter *params);
-
-bool nscss_process_data(struct content *c, const char *data, unsigned int size);
-
-bool nscss_convert(struct content *c);
-
-void nscss_destroy(struct content *c);
-
-bool nscss_clone(const struct content *old, struct content *new_content);
-
nserror nscss_create_css_data(struct content_css_data *c,
const char *url, const char *charset, bool quirks,
nscss_done_callback done, void *pw);
@@ -81,6 +72,7 @@
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);
#endif
Index: windows/gui.c
===================================================================
--- windows/gui.c (revision 12276)
+++ windows/gui.c (working copy)
@@ -1733,7 +1733,7 @@
const char *filename,
size_t len,
const char *sourcedata,
- content_type type)
+ lwc_string *mime_type)
{
return false;
}
Index: Makefile.sources
===================================================================
--- Makefile.sources (revision 12276)
+++ Makefile.sources (working copy)
@@ -4,13 +4,14 @@
# Included by main makefile -- indicates generic sources for every build.
#
-S_CONTENT := content.c dirlist.c fetch.c hlcache.c llcache.c urldb.c
+S_CONTENT := content.c content_factory.c dirlist.c fetch.c hlcache.c \
+ llcache.c urldb.c
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 favicon.c \
+S_RENDER := box.c box_construct.c box_normalise.c \
font.c form.c html.c html_interaction.c html_redraw.c \
hubbub_binding.c imagemap.c layout.c list.c table.c textplain.c
@@ -31,8 +32,8 @@
$(addprefix desktop/,$(S_DESKTOP))
# S_IMAGE are sources related to image management
-S_IMAGE := bmp.c gif.c ico.c jpeg.c mng.c nssprite.c png.c svg.c rsvg.c \
- webp.c
+S_IMAGE := bmp.c gif.c ico.c image.c jpeg.c mng.c nssprite.c png.c \
+ svg.c rsvg.c webp.c
S_IMAGE := $(addprefix image/,$(S_IMAGE))
# S_PDF are sources of the pdf plotter + the ones for paged-printing
Index: utils/errors.h
===================================================================
--- utils/errors.h (revision 12276)
+++ utils/errors.h (working copy)
@@ -39,8 +39,9 @@
NSERROR_CLONE_FAILED, /**< Failed to clone handle */
- NSERROR_INIT_FAILED /**< Initialisation failed */
+ NSERROR_INIT_FAILED, /**< Initialisation failed */
+ NSERROR_MNG_ERROR /**< An MNG error occurred */
} nserror;
#endif
Index: atari/gui.c
===================================================================
--- atari/gui.c (revision 12276)
+++ atari/gui.c (working copy)
@@ -637,7 +637,7 @@
const char *filename,
size_t len,
const char *sourcedata,
- content_type type)
+ lwc_string *mime_type)
{
TODO();
LOG(("%s", filename));
Index: riscos/sprite.c
===================================================================
--- riscos/sprite.c (revision 12276)
+++ riscos/sprite.c (working copy)
@@ -21,28 +21,131 @@
*
* No conversion is necessary: we can render RISC OS sprites directly under
* RISC OS.
- *
- * Unfortunately we have to make a copy of the bitmap data, because sprite areas
- * need a length word at the start.
*/
#include <string.h>
#include <stdlib.h>
#include "oslib/osspriteop.h"
#include "utils/config.h"
+#include "content/content_protected.h"
#include "desktop/plotters.h"
-#include "content/content_protected.h"
#include "riscos/gui.h"
#include "riscos/image.h"
#include "riscos/sprite.h"
#include "utils/config.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
#ifdef WITH_SPRITE
+typedef struct sprite_content {
+ struct content base;
+ void *data;
+} sprite_content;
+
+static nserror sprite_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool sprite_convert(struct content *c);
+static void sprite_destroy(struct content *c);
+static bool sprite_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static nserror sprite_clone(const struct content *old, struct content **newc);
+static content_type sprite_content_type(lwc_string *mime_type);
+
+static const content_handler sprite_content_handler = {
+ sprite_create,
+ NULL,
+ sprite_convert,
+ NULL,
+ sprite_destroy,
+ NULL,
+ NULL,
+ NULL,
+ sprite_redraw,
+ NULL,
+ NULL,
+ NULL,
+ sprite_clone,
+ NULL,
+ sprite_content_type,
+ false
+};
+
+static const char *sprite_types[] = {
+ "image/x-riscos-sprite"
+};
+
+static lwc_string *sprite_mime_types[NOF_ELEMENTS(sprite_types)];
+
+nserror sprite_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(sprite_mime_types); i++) {
+ lerror = lwc_intern_string(sprite_types[i],
+ strlen(sprite_types[i]),
+ &sprite_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(sprite_mime_types[i],
+ &sprite_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ sprite_fini();
+
+ return error;
+}
+
+void sprite_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(sprite_mime_types); i++) {
+ if (sprite_mime_types[i] != NULL)
+ lwc_string_unref(sprite_mime_types[i]);
+ }
+}
+
+nserror sprite_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ sprite_content *sprite;
+ nserror error;
+
+ sprite = talloc_zero(0, sprite_content);
+ if (sprite == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&sprite->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(sprite);
+ return error;
+ }
+
+ *c = (struct content *) sprite;
+
+ return NSERROR_OK;
+}
+
/**
* Convert a CONTENT_SPRITE for display.
*
@@ -51,6 +154,7 @@
bool sprite_convert(struct content *c)
{
+ sprite_content *sprite = (sprite_content *) c;
os_error *error;
int w, h;
union content_msg_data msg_data;
@@ -63,7 +167,7 @@
sprite_data = source_data - 4;
osspriteop_area *area = (osspriteop_area*) sprite_data;
- c->data.sprite.data = area;
+ sprite->data = area;
/* check for bad data */
if ((int)source_size + 4 != area->used) {
@@ -116,10 +220,12 @@
int width, int height, const struct rect *clip,
float scale, colour background_colour)
{
+ sprite_content *sprite = (sprite_content *) c;
+
if (plot.flush && !plot.flush())
return false;
- return image_redraw(c->data.sprite.data,
+ return image_redraw(sprite->data,
ro_plot_origin_x + x * 2,
ro_plot_origin_y - y * 2,
width, height,
@@ -130,18 +236,40 @@
IMAGE_PLOT_OS);
}
-bool sprite_clone(const struct content *old, struct content *new_content)
+nserror sprite_clone(const struct content *old, struct content **newc)
{
+ sprite_content *sprite;
+ nserror error;
+
+ sprite = talloc_zero(0, sprite_content);
+ if (sprite == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &sprite->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&sprite->base);
+ return error;
+ }
+
/* Simply rerun convert */
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (sprite_convert(new_content) == false)
- return false;
+ if (sprite_convert(&sprite->base) == false) {
+ content_destroy(&sprite->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) sprite;
+
+ return NSERROR_OK;
}
+content_type sprite_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
+
#endif
Index: riscos/sprite.h
===================================================================
--- riscos/sprite.h (revision 12276)
+++ riscos/sprite.h (working copy)
@@ -23,24 +23,19 @@
#ifndef _NETSURF_RISCOS_SPRITE_H_
#define _NETSURF_RISCOS_SPRITE_H_
-#include <stdbool.h>
-#include "oslib/osspriteop.h"
#include "utils/config.h"
+#include "utils/errors.h"
#ifdef WITH_SPRITE
-struct content;
-struct rect;
-struct content_sprite_data {
- void *data;
-};
+nserror sprite_init(void);
+void sprite_fini(void);
-bool sprite_convert(struct content *c);
-void sprite_destroy(struct content *c);
-bool sprite_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool sprite_clone(const struct content *old, struct content *new_content);
+#else
+
+#define sprite_init() NSERROR_OK
+#define sprite_fini() ((void) 0)
+
#endif
byte sprite_bpp(const osspriteop_header *s);
Index: riscos/draw.c
===================================================================
--- riscos/draw.c (revision 12276)
+++ riscos/draw.c (working copy)
@@ -29,14 +29,124 @@
#include <stdlib.h>
#include "oslib/drawfile.h"
#include "utils/config.h"
+#include "content/content_protected.h"
#include "desktop/plotters.h"
-#include "content/content_protected.h"
#include "riscos/draw.h"
#include "riscos/gui.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
-#include "utils/messages.h"
-#include "utils/log.h"
+typedef struct draw_content {
+ struct content base;
+
+ int x0, y0;
+} draw_content;
+
+static nserror draw_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool draw_convert(struct content *c);
+static void draw_destroy(struct content *c);
+static bool draw_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static nserror draw_clone(const struct content *old, struct content **newc);
+static content_type draw_content_type(lwc_string *mime_type);
+
+static const content_handler draw_content_handler = {
+ draw_create,
+ NULL,
+ draw_convert,
+ NULL,
+ draw_destroy,
+ NULL,
+ NULL,
+ NULL,
+ draw_redraw,
+ NULL,
+ NULL,
+ NULL,
+ draw_clone,
+ NULL,
+ draw_content_type,
+ false
+};
+
+static const char *draw_types[] = {
+ "application/drawfile",
+ "application/x-drawfile",
+ "image/drawfile",
+ "image/x-drawfile"
+};
+
+static lwc_string *draw_mime_types[NOF_ELEMENTS(draw_types)];
+
+nserror draw_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(draw_mime_types); i++) {
+ lerror = lwc_intern_string(draw_types[i],
+ strlen(draw_types[i]),
+ &draw_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(draw_mime_types[i],
+ &draw_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ draw_fini();
+
+ return error;
+}
+
+void draw_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(draw_mime_types); i++) {
+ if (draw_mime_types[i] != NULL)
+ lwc_string_unref(draw_mime_types[i]);
+ }
+}
+
+nserror draw_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ draw_content *draw;
+ nserror error;
+
+ draw = talloc_zero(0, draw_content);
+ if (draw == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&draw->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(draw);
+ return error;
+ }
+
+ *c = (struct content *) draw;
+
+ return NSERROR_OK;
+}
+
/**
* Convert a CONTENT_DRAW for display.
*
@@ -46,6 +156,7 @@
bool draw_convert(struct content *c)
{
+ draw_content *draw = (draw_content *) c;
union content_msg_data msg_data;
const char *source_data;
unsigned long source_size;
@@ -78,8 +189,8 @@
/* invalid/undefined bounding box */
c->height = c->width = 0;
- c->data.draw.x0 = bbox.x0;
- c->data.draw.y0 = bbox.y0;
+ draw->x0 = bbox.x0;
+ draw->y0 = bbox.y0;
snprintf(title, sizeof(title), messages_get("DrawTitle"), c->width,
c->height, source_size);
content__set_title(c, title);
@@ -109,6 +220,7 @@
int width, int height, const struct rect *clip,
float scale, colour background_colour)
{
+ draw_content *draw = (draw_content *) c;
os_trfm matrix;
const char *source_data;
unsigned long source_size;
@@ -131,9 +243,9 @@
matrix.entries[1][1] = height * 65536 / c->height;
/* Draw units. (x,y) = bottom left */
matrix.entries[2][0] = ro_plot_origin_x * 256 + x * 512 -
- c->data.draw.x0 * width / c->width;
+ draw->x0 * width / c->width;
matrix.entries[2][1] = ro_plot_origin_y * 256 - (y + height) * 512 -
- c->data.draw.y0 * height / c->height;
+ draw->y0 * height / c->height;
error = xdrawfile_render(0, (drawfile_diagram *) data,
(int) source_size, &matrix, 0, 0);
@@ -150,16 +262,38 @@
* Clone a CONTENT_DRAW
*/
-bool draw_clone(const struct content *old, struct content *new_content)
+nserror draw_clone(const struct content *old, struct content **newc)
{
+ draw_content *draw;
+ nserror error;
+
+ draw = talloc_zero(0, draw_content);
+ if (draw == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &draw->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&draw->base);
+ return error;
+ }
+
/* Simply rerun convert */
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (draw_convert(new_content) == false)
- return false;
+ if (draw_convert(&draw->base) == false) {
+ content_destroy(&draw->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) draw;
+
+ return NSERROR_OK;
}
+content_type draw_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
+
#endif
Index: riscos/draw.h
===================================================================
--- riscos/draw.h (revision 12276)
+++ riscos/draw.h (working copy)
@@ -24,24 +24,18 @@
#define _NETSURF_RISCOS_DRAW_H_
#include "utils/config.h"
+#include "utils/errors.h"
+
#ifdef WITH_DRAW
-#include <stdbool.h>
+nserror draw_init(void);
+void draw_fini(void);
-struct content;
-struct rect;
+#else
-struct content_draw_data {
- int x0, y0;
-};
+#define draw_init() NSERROR_OK
+#define draw_fini() ((void) 0)
-bool draw_convert(struct content *c);
-void draw_destroy(struct content *c);
-bool draw_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool draw_clone(const struct content *old, struct content *new_content);
-
#endif /* WITH_DRAW */
#endif
Index: riscos/gui/url_bar.c
===================================================================
--- riscos/gui/url_bar.c (revision 12276)
+++ riscos/gui/url_bar.c (working copy)
@@ -875,7 +875,7 @@
bool ro_gui_url_bar_set_site_favicon(struct url_bar *url_bar,
struct hlcache_handle *h)
{
- content_type type = CONTENT_OTHER;
+ content_type type = CONTENT_NONE;
if (url_bar == NULL)
return false;
@@ -885,7 +885,7 @@
// \TODO -- Maybe test for CONTENT_ICO ???
- if (type != CONTENT_OTHER && type != CONTENT_UNKNOWN) {
+ if (type == CONTENT_IMAGE) {
url_bar->favicon_content = h;
url_bar->favicon_width = content_get_width(h);
url_bar->favicon_height = content_get_height(h);
@@ -938,7 +938,7 @@
return false;
if (h != NULL)
- type = ro_content_filetype_from_type(content_get_type(h));
+ type = ro_content_filetype(h);
if (type != 0) {
snprintf(sprite, URLBAR_FAVICON_NAME_LENGTH,
Index: riscos/gui.c
===================================================================
--- riscos/gui.c (revision 12276)
+++ riscos/gui.c (working copy)
@@ -67,10 +67,12 @@
#include "render/box.h"
#include "render/font.h"
#include "render/html.h"
+#include "riscos/artworks.h"
#include "riscos/bitmap.h"
#include "riscos/buffer.h"
#include "riscos/cookies.h"
#include "riscos/dialog.h"
+#include "riscos/draw.h"
#include "riscos/global_history.h"
#include "riscos/gui.h"
#include "riscos/help.h"
@@ -86,6 +88,7 @@
#include "riscos/query.h"
#include "riscos/save.h"
#include "riscos/sslcert.h"
+#include "riscos/sprite.h"
#include "riscos/system_colour.h"
#include "riscos/textselection.h"
#include "riscos/theme.h"
@@ -774,6 +777,10 @@
netsurf_init(&argc, &argv, "NetSurf:Choices", NULL);
+ artworks_init();
+ draw_init();
+ sprite_init();
+
/* Choose the interface language to use */
ro_gui_choose_language();
@@ -793,6 +800,10 @@
netsurf_exit();
+ sprite_fini();
+ draw_fini();
+ artworks_fini();
+
return 0;
}
Index: riscos/gui.h
===================================================================
--- riscos/gui.h (revision 12276)
+++ riscos/gui.h (working copy)
@@ -171,6 +171,8 @@
/* in filetype.c */
int ro_content_filetype(struct hlcache_handle *c);
+int ro_content_native_type(struct hlcache_handle *c);
+int ro_content_filetype_from_mime_type(lwc_string *mime_type);
int ro_content_filetype_from_type(content_type type);
bits ro_filetype_from_unix_path(const char *unix_path);
Index: riscos/treeview.c
===================================================================
--- riscos/treeview.c (revision 12276)
+++ riscos/treeview.c (working copy)
@@ -1241,35 +1241,7 @@
case CONTENT_HTML:
case CONTENT_TEXTPLAIN:
case CONTENT_CSS:
-#if defined(WITH_MNG) || defined(WITH_PNG)
- case CONTENT_PNG:
-#endif
-#ifdef WITH_MNG
- case CONTENT_JNG:
- case CONTENT_MNG:
-#endif
-#ifdef WITH_JPEG
- case CONTENT_JPEG:
-#endif
-#ifdef WITH_GIF
- case CONTENT_GIF:
-#endif
-#ifdef WITH_BMP
- case CONTENT_BMP:
- case CONTENT_ICO:
-#endif
-#ifdef WITH_SPRITE
- case CONTENT_SPRITE:
-#endif
-#ifdef WITH_DRAW
- case CONTENT_DRAW:
-#endif
-#ifdef WITH_ARTWORKS
- case CONTENT_ARTWORKS:
-#endif
-#ifdef WITH_NS_SVG
- case CONTENT_SVG:
-#endif
+ case CONTENT_IMAGE:
default:
sprintf(buffer, tree_content_icon_name);
break;
Index: riscos/plugin.c
===================================================================
--- riscos/plugin.c (revision 12276)
+++ riscos/plugin.c (working copy)
@@ -53,9 +53,8 @@
#include "oslib/plugin.h"
#include "oslib/wimp.h"
#include "utils/config.h"
-#include "content/content.h"
+#include "content/content_protected.h"
#include "content/fetch.h"
-#include "content/fetchcache.h"
#include "desktop/browser.h"
#include "desktop/gui.h"
#include "render/html.h"
@@ -66,10 +65,32 @@
#include "riscos/toolbar.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/schedule.h"
+#include "utils/talloc.h"
#include "utils/url.h"
#include "utils/utils.h"
+struct plugin_stream;
+/* We have one content per instance of a plugin */
+typedef struct plugin_content {
+ struct content base;
+
+ struct browser_window *bw; /* window containing this content */
+ struct content *page; /* parent content */
+ struct box *box; /* box containing this content */
+ char *taskname; /* plugin task to launch */
+ char *filename; /* filename of parameters file */
+ bool opened; /* has this plugin been opened? */
+ int repeated; /* indication of opening state */
+ unsigned int browser; /* browser handle */
+ unsigned int plugin; /* plugin handle */
+ unsigned int plugin_task; /* plugin task handle */
+ bool reformat_pending; /* is a reformat pending? */
+ int width, height; /* reformat width & height */
+ struct plugin_stream *streams; /* list of active streams */
+} plugin_content;
+
typedef enum {
PLUGIN_PARAMETER_DATA = 1,
PLUGIN_PARAMETER_URL = 2,
@@ -96,8 +117,8 @@
struct plugin_stream {
struct plugin_stream *next; /* next in list */
- struct content *plugin; /* the plugin content */
- struct content *c; /* the content being fetched for
+ plugin_content *plugin; /* the plugin content */
+ plugin_content *c; /* the content being fetched for
* this stream (may be the same as
* plugin iff we've been asked to
* fetch the data resource for the
@@ -148,9 +169,26 @@
#define HELPER_PREFIX "Alias$@HelperType_"
#define SYSVAR_BUF_SIZE (25) /* size of buffer to hold system variable */
-static bool plugin_create_sysvar(const char *mime_type, char* sysvar,
+static nserror plugin_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror plugin_create_plugin_data(plugin_content *c);
+static bool plugin_convert(struct content *c);
+static void plugin_reformat(struct content *c, int width, int height);
+static void plugin_destroy(struct content *c);
+static bool plugin_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static void plugin_open(struct content *c, struct browser_window *bw,
+ struct content *page, struct box *box,
+ struct object_params *params);
+static void plugin_close(struct content *c);
+static nserror plugin_clone(const struct content *old, struct content **newc);
+
+static bool plugin_create_sysvar(lwc_string *mime_type, char *sysvar,
bool helper);
-static void plugin_create_stream(struct content *plugin, struct content *c,
+static void plugin_create_stream(plugin_content *plugin, plugin_content *c,
const char *url);
static bool plugin_send_stream_new(struct plugin_stream *p);
static void plugin_write_stream(struct plugin_stream *p,
@@ -160,7 +198,7 @@
static void plugin_write_stream_as_file(struct plugin_stream *p);
static void plugin_destroy_stream(struct plugin_stream *p,
plugin_stream_destroy_reason reason);
-static bool plugin_write_parameters_file(struct content *c,
+static bool plugin_write_parameters_file(plugin_content *c,
struct object_params *params, const char *base);
static int plugin_calculate_rsize(const char* name, const char* data,
const char* mime);
@@ -176,32 +214,61 @@
static void plugin_fetch_callback(fetch_msg msg, void *p, const void *data,
unsigned long size);
+nserror plugin_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ plugin_content *plugin;
+ nserror error;
+
+ plugin = talloc_zero(0, plugin_content);
+ if (plugin == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&plugin->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(plugin);
+ return error;
+ }
+
+ error = plugin_create_plugin_data(plugin);
+ if (error != NSERROR_OK) {
+ talloc_free(plugin);
+ return error;
+ }
+
+ *c = (struct content *) plugin;
+
+ return NSERROR_OK;
+}
+
/**
* Initialises plugin system in readiness for receiving object data
*
* \param c The content to hold the data
- * \param params Parameters associated with the content
- * \return true on success, false otherwise
+ * \return NSERROR_OK on success, appropriate error otherwise
*/
-bool plugin_create(struct content *c, const http_parameter *params)
+nserror plugin_create_plugin_data(plugin_content *c)
{
LOG(("plugin_create"));
- c->data.plugin.bw = 0;
- c->data.plugin.page = 0;
- c->data.plugin.box = 0;
- c->data.plugin.taskname = 0;
- c->data.plugin.filename = 0;
- c->data.plugin.opened = false;
- c->data.plugin.repeated = 0;
- c->data.plugin.browser = 0;
- c->data.plugin.plugin = 0;
- c->data.plugin.plugin_task = 0;
- c->data.plugin.reformat_pending = false;
- c->data.plugin.width = 0;
- c->data.plugin.height = 0;
- c->data.plugin.streams = 0;
+ c->bw = 0;
+ c->page = 0;
+ c->box = 0;
+ c->taskname = 0;
+ c->filename = 0;
+ c->opened = false;
+ c->repeated = 0;
+ c->browser = 0;
+ c->plugin = 0;
+ c->plugin_task = 0;
+ c->reformat_pending = false;
+ c->width = 0;
+ c->height = 0;
+ c->streams = 0;
- return true;
+ return NSERROR_OK;
}
/**
@@ -229,11 +296,13 @@
*/
void plugin_destroy(struct content *c)
{
+ plugin_content *plugin = (plugin_content *) c;
+
LOG(("plugin_destroy"));
- if (c->data.plugin.taskname)
- free(c->data.plugin.taskname);
- if (c->data.plugin.filename)
- free(c->data.plugin.filename);
+ if (plugin->taskname)
+ free(plugin->taskname);
+ if (plugin->filename)
+ free(plugin->filename);
}
/**
@@ -271,6 +340,7 @@
struct content *page, struct box *box,
struct object_params *params)
{
+ plugin_content *plugin = (plugin_content *) c;
bool standalone = false, helper = false;
const char *base;
char sysvar[SYSVAR_BUF_SIZE];
@@ -278,10 +348,13 @@
plugin_full_message_open pmo;
wimp_window_state state;
os_error *error;
+ lwc_string *mime_type;
if (option_no_plugins)
return;
+ mime_type = content__get_mime_type(c);
+
if (!params) {
/* this is a standalone plugin, so fudge the parameters */
params = calloc(1, sizeof(struct object_params));
@@ -290,12 +363,14 @@
goto error;
}
- params->data = strdup(c->url);
+ params->data = strdup(content__get_url(c));
if (!params->data) {
warn_user("NoMemory", 0);
goto error;
}
- params->type = strdup(c->mime_type);
+
+ params->type = strndup(lwc_string_data(mime_type),
+ lwc_string_length(mime_type));
if (!params->type) {
warn_user("NoMemory", 0);
goto error;
@@ -305,9 +380,9 @@
/* we only do this here because the box is needed by
* write_parameters_file. Ideally it would be at the
- * end of this function with the other writes to c->data.plugin
+ * end of this function with the other writes to plugin
*/
- c->data.plugin.box = box;
+ plugin->box = box;
if (params->codebase)
base = params->codebase;
@@ -317,11 +392,11 @@
base = c->url;
LOG(("writing parameters file"));
- if (!plugin_write_parameters_file(c, params, base))
+ if (!plugin_write_parameters_file(plugin, params, base))
goto error;
/* get contents of Alias$@PlugInType_xxx variable */
- if (!plugin_create_sysvar(c->mime_type, sysvar, false))
+ if (!plugin_create_sysvar(mime_type, sysvar, false))
goto error;
varval = getenv(sysvar);
@@ -340,14 +415,14 @@
}
/* The browser instance handle is the content struct pointer */
- c->data.plugin.browser = (unsigned int)c;
+ plugin->browser = (unsigned int)c;
pmo.size = 60;
pmo.your_ref = 0;
pmo.action = message_PLUG_IN_OPEN;
pmo.flags = helper ? plugin_OPEN_AS_HELPER : 0;
pmo.reserved = 0;
- pmo.browser = (plugin_b)c->data.plugin.browser;
+ pmo.browser = (plugin_b)plugin->browser;
pmo.parent_window = bw->window->window;
/* initial position/dimensions */
@@ -371,14 +446,14 @@
pmo.bbox.y1 = 100;
}
- error = xmimemaptranslate_mime_type_to_filetype(c->mime_type,
- &pmo.file_type);
+ error = xmimemaptranslate_mime_type_to_filetype(
+ lwc_string_data(mime_type), &pmo.file_type);
if (error) {
goto error;
}
- pmo.filename.pointer = c->data.plugin.filename;
+ pmo.filename.pointer = plugin->filename;
- c->data.plugin.repeated = 0;
+ plugin->repeated = 0;
LOG(("sending message"));
error = xwimp_send_message(wimp_USER_MESSAGE_RECORDED,
@@ -389,9 +464,9 @@
goto error;
}
- c->data.plugin.bw = bw;
- c->data.plugin.page = page;
- c->data.plugin.taskname = strdup(varval);
+ plugin->bw = bw;
+ plugin->page = page;
+ plugin->taskname = strdup(varval);
error:
/* clean up standalone stuff */
@@ -401,6 +476,8 @@
free(params);
}
+ lwc_string_unref(mime_type);
+
LOG(("done"));
}
@@ -412,17 +489,18 @@
*/
void plugin_close(struct content *c)
{
+ plugin_content *plugin = (plugin_content *) c;
struct plugin_stream *p, *q;
plugin_full_message_close pmc;
os_error *error;
LOG(("plugin_close"));
- if (!plugin_active(c) || !c->data.plugin.opened)
+ if (!plugin_active(c) || !plugin->opened)
return;
/* destroy all active streams */
- for (p = c->data.plugin.streams; p; p = q) {
+ for (p = plugin->streams; p; p = q) {
q = p->next;
plugin_destroy_stream(p, plugin_STREAM_DESTROY_USER_REQUEST);
@@ -432,18 +510,18 @@
pmc.your_ref = 0;
pmc.action = message_PLUG_IN_CLOSE;
pmc.flags = 0;
- pmc.browser = (plugin_b)c->data.plugin.browser;
- pmc.plugin = (plugin_p)c->data.plugin.plugin;
+ pmc.browser = (plugin_b)plugin->browser;
+ pmc.plugin = (plugin_p)plugin->plugin;
LOG(("sending message"));
error = xwimp_send_message(wimp_USER_MESSAGE_RECORDED,
- (wimp_message *)&pmc, (wimp_t)c->data.plugin.plugin_task);
+ (wimp_message *)&pmc, (wimp_t)plugin->plugin_task);
if (error) {
return;
}
/* delete any temporary files */
- for (p = c->data.plugin.streams; p; p = q) {
+ for (p = plugin->streams; p; p = q) {
q = p->next;
assert(p->type == AS_FILE);
@@ -458,7 +536,7 @@
}
/* paranoia */
- c->data.plugin.streams = 0;
+ plugin->streams = 0;
}
/**
@@ -470,6 +548,7 @@
*/
void plugin_reformat(struct content *c, int width, int height)
{
+ plugin_content *plugin = (plugin_content *) c;
plugin_full_message_reshape pmr;
int x, y;
os_error *error;
@@ -480,26 +559,26 @@
return;
/* if the plugin hasn't yet been opened, queue the reformat */
- if (!c->data.plugin.opened) {
+ if (!plugin->opened) {
LOG(("queuing"));
- c->data.plugin.reformat_pending = true;
- c->data.plugin.width = width;
- c->data.plugin.height = height;
+ plugin->reformat_pending = true;
+ plugin->width = width;
+ plugin->height = height;
return;
}
- c->data.plugin.reformat_pending = false;
+ plugin->reformat_pending = false;
/* top left of plugin area, relative to top left of browser window */
- if (c->data.plugin.box) {
- box_coords(c->data.plugin.box, &x, &y);
+ if (plugin->box) {
+ box_coords(plugin->box, &x, &y);
}
else {
/* standalone */
x = 10 / 2;
/* avoid toolbar */
y = (10 + ro_toolbar_height(
- c->data.plugin.bw->window->toolbar0)) / 2;
+ plugin->bw->window->toolbar)) / 2;
}
pmr.size = 52;
@@ -507,15 +586,15 @@
pmr.action = message_PLUG_IN_RESHAPE;
pmr.flags = 0;
- pmr.plugin = (plugin_p)c->data.plugin.plugin;
- pmr.browser = (plugin_b)c->data.plugin.browser;
- pmr.parent_window = c->data.plugin.bw->window->window;
+ pmr.plugin = (plugin_p)plugin->plugin;
+ pmr.browser = (plugin_b)plugin->browser;
+ pmr.parent_window = plugin->bw->window->window;
pmr.bbox.x0 = x * 2;
pmr.bbox.y1 = -y * 2;
- if (c->data.plugin.box) {
- pmr.bbox.x1 = pmr.bbox.x0 + c->data.plugin.box->width * 2;
- pmr.bbox.y0 = pmr.bbox.y1 - c->data.plugin.box->height * 2;
+ if (plugin->box) {
+ pmr.bbox.x1 = pmr.bbox.x0 + plugin->box->width * 2;
+ pmr.bbox.y0 = pmr.bbox.y1 - plugin->box->height * 2;
}
else {
/* standalone */
@@ -525,27 +604,46 @@
LOG(("sending message"));
error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message *) &pmr,
- (wimp_t)c->data.plugin.plugin_task);
+ (wimp_t)plugin->plugin_task);
if (error) {
return;
}
}
-bool plugin_clone(const struct content *old, struct content *new_content)
+nserror plugin_clone(const struct content *old, struct content **newc)
{
+ plugin_content *plugin;
+ nserror error;
+
LOG(("plugin_clone"));
+
+ plugin = talloc_zero(0, plugin_content);
+ if (plugin == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &plugin->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&plugin->base);
+ return error;
+ }
+
/* We "clone" the old content by replaying creation and conversion */
- if (plugin_create(new_content, NULL) == false)
- return false;
+ error = plugin_create_plugin_data(plugin);
+ if (error != NSERROR_OK) {
+ content_destroy(&plugin->base);
+ return error;
+ }
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (plugin_convert(new_content) == false)
- return false;
+ if (plugin_convert(&plugin->base) == false) {
+ content_destroy(&plugin->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ return NSERROR_OK;
}
@@ -558,12 +656,13 @@
* \param helper Whether we're interested in the helper variable
* \return true on success, false otherwise.
*/
-bool plugin_create_sysvar(const char *mime_type, char* sysvar, bool helper)
+bool plugin_create_sysvar(lwc_string *mime_type, char* sysvar, bool helper)
{
unsigned int *fv;
os_error *e;
- e = xmimemaptranslate_mime_type_to_filetype(mime_type, (bits *) &fv);
+ e = xmimemaptranslate_mime_type_to_filetype(
+ lwc_string_data(mime_type), (bits *) &fv);
if (e) {
return false;
}
@@ -576,65 +675,37 @@
}
/**
- * Determines whether a content is handleable by a plugin
- *
- * \param mime_type The mime type of the content
- * \return true if the content is handleable, false otherwise
- */
-bool plugin_handleable(const char *mime_type)
-{
- char sysvar[SYSVAR_BUF_SIZE];
-
- /* Look for Alias$@PluginType_xxx */
- if (plugin_create_sysvar(mime_type, sysvar, false)) {
- if (getenv(sysvar) != 0) {
- return true;
- }
- }
-#if 0
- /* Look for Alias$@HelperType_xxx */
- if (plugin_create_sysvar(mime_type, sysvar, true)) {
- if (getenv(sysvar) != 0) {
- return true;
- }
- }
-#endif
- return false;
-}
-
-
-/**
* Handle a bounced plugin_open message
*
* \param message The message to handle
*/
void plugin_open_msg(wimp_message *message)
{
- struct content *c;
+ plugin_content *c;
os_error *error;
plugin_message_open *pmo = (plugin_message_open *)&message->data;
/* retrieve our content */
- c = (struct content *)pmo->browser;
+ c = (plugin_content *)pmo->browser;
/* check we expect this message */
- if (!c || !plugin_active(c))
+ if (!c || !plugin_active(&c->base))
return;
LOG(("bounced"));
/* bail if we've already tried twice */
- if (c->data.plugin.repeated >= 1)
+ if (c->repeated >= 1)
return;
/* start plugin app */
- error = xwimp_start_task((char const*)c->data.plugin.taskname, 0);
+ error = xwimp_start_task((char const*)c->taskname, 0);
if (error) {
return;
}
/* indicate we've already sent this message once */
- c->data.plugin.repeated++;
+ c->repeated++;
/* and resend the message */
LOG(("resending"));
@@ -653,29 +724,28 @@
*/
void plugin_opening(wimp_message *message)
{
- struct content *c;
+ plugin_content *c;
plugin_message_opening *pmo =
(plugin_message_opening *)&message->data;
/* retrieve our content */
- c = (struct content *)pmo->browser;
+ c = (plugin_content *)pmo->browser;
/* check we expect this message */
- if (!c || !plugin_active(c))
+ if (!c || !plugin_active(&c->base))
return;
- c->data.plugin.repeated = 2; /* make sure open_msg does nothing */
- c->data.plugin.plugin = (unsigned int)pmo->plugin;
- c->data.plugin.plugin_task = (unsigned int)message->sender;
- c->data.plugin.opened = true;
+ c->repeated = 2; /* make sure open_msg does nothing */
+ c->plugin = (unsigned int)pmo->plugin;
+ c->plugin_task = (unsigned int)message->sender;
+ c->opened = true;
LOG(("opening"));
/* if there's a reformat pending, do so now */
- if (c->data.plugin.reformat_pending) {
+ if (c->reformat_pending) {
LOG(("do pending reformat"));
- plugin_reformat(c, c->data.plugin.width,
- c->data.plugin.height);
+ plugin_reformat(&c->base, c->width, c->height);
}
if (pmo->flags & plugin_OPENING_WANTS_DATA_FETCHING) {
@@ -686,7 +756,7 @@
if (!(pmo->flags & plugin_OPENING_WILL_DELETE_PARAMETERS)) {
LOG(("we delete file"));
/* we don't care if this fails */
- xosfile_delete(c->data.plugin.filename, 0, 0, 0, 0, 0);
+ xosfile_delete(c->filename, 0, 0, 0, 0, 0);
}
}
@@ -709,25 +779,24 @@
*/
void plugin_closed(wimp_message *message)
{
- struct content *c;
+ plugin_content *c;
plugin_message_closed *pmc = (plugin_message_closed *)&message->data;
/* retrieve our content */
- c = (struct content*)pmc->browser;
+ c = (plugin_content*)pmc->browser;
/* check we expect this message */
- if (!c || !plugin_active(c))
+ if (!c || !plugin_active(&c->base))
return;
LOG(("died"));
- c->data.plugin.opened = false;
+ c->opened = false;
if (pmc->flags & plugin_CLOSED_WITH_ERROR) {
LOG(("plugin_closed: 0x%x: %s", pmc->error_number,
pmc->error_text));
/* not really important enough to do a warn_user */
- gui_window_set_status(c->data.plugin.bw->window,
- pmc->error_text);
+ gui_window_set_status(c->bw->window, pmc->error_text);
}
}
@@ -738,16 +807,16 @@
*/
void plugin_reshape_request(wimp_message *message)
{
- struct content *c;
+ plugin_content *c;
struct box *b;
union content_msg_data data;
plugin_message_reshape_request *pmrr = (plugin_message_reshape_request*)&message->data;
/* retrieve our content */
- c = (struct content *)pmrr->browser;
+ c = (plugin_content *)pmrr->browser;
/* check we expect this message */
- if (!c || !plugin_active(c))
+ if (!c || !plugin_active(&c->base))
return;
LOG(("handling reshape request"));
@@ -756,28 +825,26 @@
* so we set it up here. This is ok as the content won't change
* under us. However, the box may not exist (if we're standalone)
*/
- if (c->data.plugin.box)
- c->data.plugin.box->object = c;
+ if (c->box)
+ c->box->object = c;
/* should probably shift by x and y eig values here */
- c->width = pmrr->size.x / 2;
- c->height = pmrr->size.y / 2;
+ c->base.width = pmrr->size.x / 2;
+ c->base.height = pmrr->size.y / 2;
- if (c->data.plugin.box)
+ if (c->box)
/* invalidate parent box widths */
- for (b = c->data.plugin.box->parent; b; b = b->parent)
+ for (b = c->box->parent; b; b = b->parent)
b->max_width = UNKNOWN_MAX_WIDTH;
- if (c->data.plugin.page)
+ if (c->page)
/* force a reformat of the parent */
- content_reformat(c->data.plugin.page,
- c->data.plugin.page->available_width, 0);
+ content__reformat(c->page, c->page->available_width, 0);
/* redraw the window */
- content_broadcast(c->data.plugin.bw->current_content,
- CONTENT_MSG_REFORMAT, data);
+ content_broadcast(c->bw->current_content, CONTENT_MSG_REFORMAT, data);
/* reshape the plugin */
- plugin_reformat(c, c->width, c->height);
+ plugin_reformat(&c->base, c->base.width, c->base.height);
}
/**
@@ -787,17 +854,17 @@
*/
void plugin_status(wimp_message *message)
{
- struct content *c;
+ plugin_content *c;
plugin_message_status *pms = (plugin_message_status*)&message->data;
/* retrieve our content */
- c = (struct content *)pms->browser;
+ c = (plugin_content *)pms->browser;
/* check we expect this message */
- if (!c || !plugin_active(c))
+ if (!c || !plugin_active(&c->base))
return;
- gui_window_set_status(c->data.plugin.bw->window,
+ gui_window_set_status(c->bw->window,
(const char*)plugin_get_string_value(pms->message,
(char*)pms));
}
@@ -819,7 +886,7 @@
p = (struct plugin_stream *)pmsn->browser_stream;
/* check we expect this message */
- if (!p || !p->plugin || !plugin_active(p->plugin))
+ if (!p || !p->plugin || !plugin_active(&p->plugin->base))
return;
/* response to a message we sent */
@@ -884,7 +951,7 @@
p = (struct plugin_stream *)pmsw->browser_stream;
/* check we expect this message */
- if (!p || !p->plugin || !plugin_active(p->plugin))
+ if (!p || !p->plugin || !plugin_active(&p->plugin->base))
return;
LOG(("got written"));
@@ -899,7 +966,7 @@
*/
void plugin_url_access(wimp_message *message)
{
- struct content *c;
+ plugin_content *c;
plugin_full_message_notify pmn;
os_error *error;
plugin_message_url_access *pmua =
@@ -913,10 +980,10 @@
file = (pmua->flags & plugin_URL_ACCESS_POST_FILE);
/* retrieve our content */
- c = (struct content *)pmua->browser;
+ c = (plugin_content *)pmua->browser;
/* check we expect this message */
- if (!c || !plugin_active(c))
+ if (!c || !plugin_active(&c->base))
return;
/* fetch url to window */
@@ -930,7 +997,7 @@
*/
if (!post) { /* GET request */
if (strcasecmp(url,
- c->data.plugin.bw->current_content->url) &&
+ c->bw->current_content->url) &&
(strcasecmp(window, "_self") == 0 ||
strcasecmp(window, "_parent") == 0 ||
strcasecmp(window, "_top") == 0 ||
@@ -940,7 +1007,7 @@
* end up in an infinite loop of fetching
* the same page
*/
- browser_window_go(c->data.plugin.bw, url, 0, true);
+ browser_window_go(c->bw, url, 0, true);
}
else if (!option_block_popups &&
strcasecmp(window, "_blank") == 0) {
@@ -992,13 +1059,12 @@
* \param c The content being fetched, or NULL.
* \param url The url of the resource to fetch, or NULL if content provided.
*/
-void plugin_create_stream(struct content *plugin, struct content *c,
+void plugin_create_stream(plugin_content *plugin, plugin_content *c,
const char *url)
{
struct plugin_stream *p;
- assert(plugin && plugin->type == CONTENT_PLUGIN &&
- ((c && !url) || (!c && url)));
+ assert(plugin && ((c && !url) || (!c && url)));
p = malloc(sizeof(struct plugin_stream));
if (!p)
@@ -1019,8 +1085,8 @@
p->stream.normal.consumed = 0;
/* add to head of list */
- p->next = plugin->data.plugin.streams;
- plugin->data.plugin.streams = p;
+ p->next = plugin->streams;
+ plugin->streams = p;
if (url)
/* we'll send this later, once some data is arriving */
@@ -1044,11 +1110,11 @@
pmsn.your_ref = 0;
pmsn.action = message_PLUG_IN_STREAM_NEW;
pmsn.flags = 0;
- pmsn.plugin = (plugin_p)p->plugin->data.plugin.plugin;
- pmsn.browser = (plugin_b)p->plugin->data.plugin.browser;
+ pmsn.plugin = (plugin_p)p->plugin->plugin;
+ pmsn.browser = (plugin_b)p->plugin->browser;
pmsn.stream = (plugin_s)0;
pmsn.browser_stream = (plugin_bs)p;
- pmsn.url.pointer = p->c->url;
+ pmsn.url.pointer = (char *) content__get_url(&p->c->base);
pmsn.end = p->c->total_size;
pmsn.last_modified_date = 0;
pmsn.notify_data = 0;
@@ -1058,7 +1124,7 @@
LOG(("Sending message &4D548"));
error = xwimp_send_message(wimp_USER_MESSAGE_RECORDED,
(wimp_message*)&pmsn,
- (wimp_t)p->plugin->data.plugin.plugin_task);
+ (wimp_t)p->plugin->plugin_task);
if (error) {
plugin_stream_free(p);
return false;
@@ -1086,11 +1152,11 @@
pmsw.your_ref = 0;
pmsw.action = message_PLUG_IN_STREAM_WRITE;
pmsw.flags = 0;
- pmsw.plugin = (plugin_p)p->plugin->data.plugin.plugin;
- pmsw.browser = (plugin_b)p->plugin->data.plugin.browser;
+ pmsw.plugin = (plugin_p)p->plugin->plugin;
+ pmsw.browser = (plugin_b)p->plugin->browser;
pmsw.stream = (plugin_s)p->pluginh;
pmsw.browser_stream = (plugin_bs)p;
- pmsw.url.pointer = p->c->url;
+ pmsw.url.pointer = (char *) content__get_url(&p->c->base);
/* end of stream is p->c->total_size
* (which is conveniently 0 if unknown)
*/
@@ -1116,7 +1182,7 @@
LOG(("Sending message &4D54A"));
error = xwimp_send_message(wimp_USER_MESSAGE_RECORDED,
(wimp_message *)&pmsw,
- (wimp_t)p->plugin->data.plugin.plugin_task);
+ (wimp_t)p->plugin->plugin_task);
if (error) {
plugin_destroy_stream(p,
plugin_STREAM_DESTROY_ERROR);
@@ -1166,7 +1232,8 @@
schedule_remove(plugin_stream_as_file_callback, p);
if (s->c->source_size < s->c->total_size ||
- s->c->status != CONTENT_STATUS_DONE) {
+ content__get_status(&s->c->base) !=
+ CONTENT_STATUS_DONE) {
/* not got all the data so wait some more */
schedule(PLUGIN_SCHEDULE_WAIT,
plugin_stream_as_file_callback, p);
@@ -1211,11 +1278,11 @@
pmsaf.your_ref = 0;
pmsaf.action = message_PLUG_IN_STREAM_AS_FILE;
pmsaf.flags = 0;
- pmsaf.plugin = (plugin_p)p->plugin->data.plugin.plugin;
- pmsaf.browser = (plugin_b)p->plugin->data.plugin.browser;
+ pmsaf.plugin = (plugin_p)p->plugin->plugin;
+ pmsaf.browser = (plugin_b)p->plugin->browser;
pmsaf.stream = (plugin_s)p->pluginh;
pmsaf.browser_stream = (plugin_bs)p;
- pmsaf.url.pointer = p->c->url;
+ pmsaf.url.pointer = (char *) content__get_url(&p->c->base);
pmsaf.end = p->c->total_size;
pmsaf.last_modified_date = 0;
pmsaf.notify_data = 0;
@@ -1239,7 +1306,7 @@
LOG(("Sending message &4D54C"));
error = xwimp_send_message(wimp_USER_MESSAGE,
(wimp_message *)&pmsaf,
- (wimp_t)p->plugin->data.plugin.plugin_task);
+ (wimp_t)p->plugin->plugin_task);
if (error) {
plugin_destroy_stream(p, plugin_STREAM_DESTROY_ERROR);
return;
@@ -1274,11 +1341,11 @@
pmsd.your_ref = 0;
pmsd.action = message_PLUG_IN_STREAM_DESTROY;
pmsd.flags = 0;
- pmsd.plugin = (plugin_p)p->plugin->data.plugin.plugin;
- pmsd.browser = (plugin_b)p->plugin->data.plugin.browser;
+ pmsd.plugin = (plugin_p)p->plugin->plugin;
+ pmsd.browser = (plugin_b)p->plugin->browser;
pmsd.stream = (plugin_s)p->pluginh;
pmsd.browser_stream = (plugin_bs)p;
- pmsd.url.pointer = p->c->url;
+ pmsd.url.pointer = (char *) content__get_url(&p->c->base);
pmsd.end = p->c->total_size;
pmsd.last_modified_date = 0;
pmsd.notify_data = 0;
@@ -1287,7 +1354,7 @@
LOG(("Sending message &4D549"));
error = xwimp_send_message(wimp_USER_MESSAGE,
(wimp_message *)&pmsd,
- (wimp_t)p->plugin->data.plugin.plugin_task);
+ (wimp_t)p->plugin->plugin_task);
if (error) {
LOG(("0x%x %s", error->errnum, error->errmess));
}
@@ -1303,7 +1370,7 @@
* \param base base URL for object
* \return true on success, false otherwise
*/
-bool plugin_write_parameters_file(struct content *c,
+bool plugin_write_parameters_file(plugin_content *c,
struct object_params *params, const char *base)
{
struct object_param *p;
@@ -1316,17 +1383,17 @@
xosfile_create_dir("<Wimp$ScrapDir>.WWW", 77);
xosfile_create_dir("<Wimp$ScrapDir>.WWW.NetSurf", 77);
/* path + filename + terminating NUL */
- c->data.plugin.filename =
+ c->filename =
calloc(strlen(getenv("Wimp$ScrapDir"))+13+10, sizeof(char));
- if (!c->data.plugin.filename) {
+ if (!c->filename) {
LOG(("malloc failed"));
warn_user("NoMemory", 0);
return false;
}
- sprintf(c->data.plugin.filename, "%s.WWW.NetSurf.p%x",
+ sprintf(c->filename, "%s.WWW.NetSurf.p%x",
getenv("Wimp$ScrapDir"), (unsigned int)params);
- LOG(("filename: %s", c->data.plugin.filename));
+ LOG(("filename: %s", c->filename));
/* Write object attributes first */
@@ -1413,11 +1480,10 @@
goto error;
/* BGCOLOR */
- if (c->data.plugin.box && c->data.plugin.box->style &&
- c->data.plugin.box->style->background_color
- <= 0xFFFFFF)
+ if (c->box && c->box->style &&
+ c->box->style->background_color <= 0xFFFFFF)
sprintf(bgcolor, "%X00",
- (unsigned int)c->data.plugin.box->style->background_color);
+ (unsigned int)c->box->style->background_color);
else
sprintf(bgcolor, "FFFFFF");
if (!plugin_add_item_to_pilist(&pilist, PLUGIN_PARAMETER_SPECIAL,
@@ -1427,7 +1493,7 @@
goto error;
/* Write file */
- fp = fopen(c->data.plugin.filename, "wb+");
+ fp = fopen(c->filename, "wb+");
while (pilist != 0) {
fwrite(&pilist->type, sizeof(int), 1, fp);
@@ -1481,8 +1547,8 @@
ppi = 0;
}
- free(c->data.plugin.filename);
- c->data.plugin.filename = 0;
+ free(c->filename);
+ c->filename = 0;
return false;
}
@@ -1634,14 +1700,14 @@
/* free normal stream context. file streams get freed later */
if (p->type == NORMAL) {
struct plugin_stream *q;
- for (q = p->plugin->data.plugin.streams; q && q->next != p;
+ for (q = p->plugin->streams; q && q->next != p;
q = q->next)
/* do nothing */;
- assert(q || p == p->plugin->data.plugin.streams);
+ assert(q || p == p->plugin->streams);
if (q)
q->next = p->next;
else
- p->plugin->data.plugin.streams = p->next;
+ p->plugin->streams = p->next;
free(p);
}
Index: riscos/save.c
===================================================================
--- riscos/save.c (revision 12276)
+++ riscos/save.c (working copy)
@@ -1013,7 +1013,7 @@
*/
bool save_complete_gui_save(const char *path, const char *filename, size_t len,
- const char *sourcedata, content_type type)
+ const char *sourcedata, lwc_string *mime_type)
{
char *fullpath;
os_error *error;
@@ -1025,7 +1025,7 @@
return false;
}
snprintf(fullpath, namelen, "%s.%s", path, filename);
- rotype = ro_content_filetype_from_type(type);
+ rotype = ro_content_filetype_from_mime_type(mime_type);
error = xosfile_save_stamped(fullpath, rotype, (byte *) sourcedata,
(byte *) sourcedata + len);
free(fullpath);
@@ -1162,63 +1162,43 @@
bool ro_gui_save_object_native(hlcache_handle *h, char *path)
{
- const char *source_data;
- unsigned long source_size;
+ int file_type = ro_content_filetype(h);
- switch (content_get_type(h)) {
-#ifdef WITH_JPEG
- case CONTENT_JPEG:
-#endif
-#if defined(WITH_MNG) || defined(WITH_PNG)
- case CONTENT_PNG:
-#endif
-#ifdef WITH_MNG
- case CONTENT_JNG:
- case CONTENT_MNG:
-#endif
-#ifdef WITH_GIF
- case CONTENT_GIF:
-#endif
-#ifdef WITH_BMP
- case CONTENT_BMP:
- case CONTENT_ICO:
-#endif
+ if (file_type == osfile_TYPE_SPRITE || file_type == osfile_TYPE_DRAW) {
+ /* Native sprite or drawfile */
+ const char *source_data;
+ unsigned long source_size;
+ os_error *error;
+
+ source_data = content_get_source_data(h, &source_size);
+ error = xosfile_save_stamped(path, file_type,
+ (byte *) source_data,
+ (byte *) source_data + source_size);
+ if (error != NULL) {
+ LOG(("xosfile_save_stamped: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("SaveError", error->errmess);
+ return false;
+ }
+ } else {
+ /* Non-native type: export */
+ switch (ro_content_native_type(h)) {
+ case osfile_TYPE_SPRITE:
{
unsigned flags = (os_version == 0xA9) ?
BITMAP_SAVE_FULL_ALPHA : 0;
bitmap_save(content_get_bitmap(h), path, flags);
- return true;
}
- break;
-#ifdef WITH_SPRITE
- case CONTENT_SPRITE:
-#endif
-#ifdef WITH_DRAW
- case CONTENT_DRAW:
-#endif
- {
- os_error *error;
- source_data = content_get_source_data(h, &source_size);
- error = xosfile_save_stamped(path,
- ro_content_filetype(h),
- (byte *) source_data,
- (byte *) source_data + source_size);
- if (error) {
- LOG(("xosfile_save_stamped: 0x%x: %s",
- error->errnum, error->errmess));
- warn_user("SaveError", error->errmess);
- return false;
- }
- return true;
- }
- break;
-#if defined(WITH_NS_SVG) || defined(WITH_RSVG)
- case CONTENT_SVG:
+ break;
+ case osfile_TYPE_DRAW:
+ /* Must be SVG */
return save_as_draw(h, path);
-#endif
default:
return false;
+ }
}
+
+ return true;
}
@@ -1306,40 +1286,15 @@
gui_save_filetype = gui_save_table[save_type].filetype;
if (!gui_save_filetype && h) {
if (save_type == GUI_SAVE_OBJECT_NATIVE) {
- switch (content_get_type(h)) {
- /* bitmap images */
-#ifdef WITH_JPEG
- case CONTENT_JPEG:
-#endif
-#if defined(WITH_MNG) || defined(WITH_PNG)
- case CONTENT_PNG:
-#endif
-#ifdef WITH_MNG
- case CONTENT_JNG:
- case CONTENT_MNG:
-#endif
-#ifdef WITH_GIF
- case CONTENT_GIF:
-#endif
-#ifdef WITH_BMP
- case CONTENT_BMP:
- case CONTENT_ICO:
-#endif
- gui_save_filetype = osfile_TYPE_SPRITE;
- break;
- /* vector formats */
-#if defined(WITH_NS_SVG) || defined(WITH_RSVG)
- case CONTENT_SVG:
- gui_save_filetype = osfile_TYPE_DRAW;
- break;
-#endif
-#ifdef WITH_DRAW
- case CONTENT_DRAW:
- gui_save_filetype = osfile_TYPE_DRAW;
- break;
-#endif
- default:
- break;
+ switch (ro_content_native_type(h)) {
+ case osfile_TYPE_SPRITE:
+ gui_save_filetype = osfile_TYPE_SPRITE;
+ break;
+ case osfile_TYPE_DRAW:
+ gui_save_filetype = osfile_TYPE_DRAW;
+ break;
+ default:
+ break;
}
}
if (!gui_save_filetype)
Index: riscos/plugin.h
===================================================================
--- riscos/plugin.h (revision 12276)
+++ riscos/plugin.h (working copy)
@@ -22,30 +22,10 @@
#include "utils/config.h"
#ifdef WITH_PLUGIN
-#include "desktop/plugin.h"
#include <stdbool.h>
#include "oslib/plugin.h"
#include "oslib/wimp.h"
-struct plugin_stream;
-
-/* We have one content per instance of a plugin */
-struct content_plugin_data {
- struct browser_window *bw; /* window containing this content */
- struct content *page; /* parent content */
- struct box *box; /* box containing this content */
- char *taskname; /* plugin task to launch */
- char *filename; /* filename of parameters file */
- bool opened; /* has this plugin been opened? */
- int repeated; /* indication of opening state */
- unsigned int browser; /* browser handle */
- unsigned int plugin; /* plugin handle */
- unsigned int plugin_task; /* plugin task handle */
- bool reformat_pending; /* is a reformat pending? */
- int width, height; /* reformat width & height */
- struct plugin_stream *streams; /* list of active streams */
-};
-
/* message handlers */
void plugin_open_msg(wimp_message *message);
void plugin_opening(wimp_message *message);
Index: riscos/window.c
===================================================================
--- riscos/window.c (revision 12276)
+++ riscos/window.c (working copy)
@@ -3893,46 +3893,20 @@
if (export_sprite != NULL)
*export_sprite = false;
- if (h != NULL) {
- switch (content_get_type(h)) {
- /* bitmap types (Sprite export possible) */
-#ifdef WITH_JPEG
- case CONTENT_JPEG:
-#endif
-#ifdef WITH_MNG
- case CONTENT_JNG:
- case CONTENT_MNG:
-#endif
-#ifdef WITH_GIF
- case CONTENT_GIF:
-#endif
-#ifdef WITH_BMP
- case CONTENT_BMP:
- case CONTENT_ICO:
-#endif
-#if defined(WITH_MNG) || defined(WITH_PNG)
- case CONTENT_PNG:
-#endif
-#ifdef WITH_SPRITE
- case CONTENT_SPRITE:
-#endif
+ if (h != NULL && content_get_type(h) == CONTENT_IMAGE) {
+ switch (ro_content_native_type(h)) {
+ case osfile_TYPE_SPRITE:
+ /* bitmap types (Sprite export possible) */
found_type = true;
if (export_sprite != NULL)
*export_sprite = true;
break;
-
- /* vector types (Draw export possible) */
-#if defined(WITH_NS_SVG) || defined(WITH_RSVG)
- case CONTENT_SVG:
-#endif
-#ifdef WITH_DRAW
- case CONTENT_DRAW:
-#endif
+ case osfile_TYPE_DRAW:
+ /* vector types (Draw export possible) */
found_type = true;
if (export_draw != NULL)
*export_draw = true;
break;
-
default:
break;
}
@@ -3988,7 +3962,8 @@
char enc_buf[40];
char enc_token[10] = "Encoding0";
const char *icon = icon_buf;
- const char *title, *url, *mime;
+ const char *title, *url;
+ lwc_string *mime;
const char *enc = "-";
assert(h);
@@ -4000,8 +3975,6 @@
if (url == NULL)
url = "-";
mime = content_get_mime_type(h);
- if (mime == NULL)
- mime = "-";
sprintf(icon_buf, "file_%x", ro_content_filetype(h));
if (!ro_gui_wimp_sprite_exists(icon_buf))
@@ -4028,7 +4001,9 @@
ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_ENC,
enc, true);
ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_TYPE,
- mime, true);
+ lwc_string_data(mime), true);
+
+ lwc_string_unref(mime);
}
@@ -4042,7 +4017,8 @@
void ro_gui_window_prepare_objectinfo(hlcache_handle *object, const char *href)
{
char icon_buf[20] = "file_xxx";
- const char *url, *mime;
+ const char *url;
+ lwc_string *mime;
const char *target = "-";
sprintf(icon_buf, "file_%.3x",
@@ -4054,8 +4030,6 @@
if (url == NULL)
url = "-";
mime = content_get_mime_type(object);
- if (mime == NULL)
- mime = "-";
if (href)
target = href;
@@ -4067,7 +4041,9 @@
ro_gui_set_icon_string(dialog_objinfo, ICON_OBJINFO_TARGET,
target, true);
ro_gui_set_icon_string(dialog_objinfo, ICON_OBJINFO_TYPE,
- mime, true);
+ lwc_string_data(mime), true);
+
+ lwc_string_unref(mime);
}
Index: riscos/artworks.c
===================================================================
--- riscos/artworks.c (revision 12276)
+++ riscos/artworks.c (working copy)
@@ -32,14 +32,15 @@
#include "oslib/os.h"
#include "oslib/wimp.h"
#include "utils/config.h"
+#include "content/content_protected.h"
#include "desktop/plotters.h"
-#include "content/content_protected.h"
#include "riscos/artworks.h"
#include "riscos/gui.h"
#include "riscos/wimputils.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
-#include "utils/messages.h"
-#include "utils/log.h"
#define AWRender_FileInitAddress 0x46080
#define AWRender_RenderAddress 0x46081
@@ -53,7 +54,21 @@
#define INITIAL_BLOCK_SIZE 0x1000
+typedef struct artworks_content {
+ struct content base;
+ int x0, y0, x1, y1;
+
+ void *render_routine;
+ void *render_workspace;
+
+ /* dynamically-resizable block required by
+ ArtWorksRenderer rendering routine */
+
+ void *block;
+ size_t size;
+} artworks_content;
+
struct awinfo_block {
int ditherx;
int dithery;
@@ -72,12 +87,12 @@
/* Assembler routines for interfacing with the ArtworksRenderer module */
-os_error *awrender_init(const char **doc,
+extern os_error *awrender_init(const char **doc,
unsigned long *doc_size,
void *routine,
void *workspace);
-os_error *awrender_render(const char *doc,
+extern os_error *awrender_render(const char *doc,
const struct awinfo_block *info,
const os_trfm *trans,
const int *vdu_vars,
@@ -89,8 +104,106 @@
void *routine,
void *workspace);
+static nserror artworks_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool artworks_convert(struct content *c);
+static void artworks_destroy(struct content *c);
+static bool artworks_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static nserror artworks_clone(const struct content *old, struct content **newc);
+static content_type artworks_content_type(lwc_string *mime_type);
+static const content_handler artworks_content_handler = {
+ artworks_create,
+ NULL,
+ artworks_convert,
+ NULL,
+ artworks_destroy,
+ NULL,
+ NULL,
+ NULL,
+ artworks_redraw,
+ NULL,
+ NULL,
+ NULL,
+ artworks_clone,
+ NULL,
+ artworks_content_type,
+ false
+};
+static const char *artworks_types[] = {
+ "image/x-artworks"
+};
+
+static lwc_string *artworks_mime_types[NOF_ELEMENTS(artworks_types)];
+
+nserror artworks_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(artworks_mime_types); i++) {
+ lerror = lwc_intern_string(artworks_types[i],
+ strlen(artworks_types[i]),
+ &artworks_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(artworks_mime_types[i],
+ &artworks_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ artworks_fini();
+
+ return error;
+}
+
+void artworks_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(artworks_mime_types); i++) {
+ if (artworks_mime_types[i] != NULL)
+ lwc_string_unref(artworks_mime_types[i]);
+ }
+}
+
+nserror artworks_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ artworks_content *aw;
+ nserror error;
+
+ aw = talloc_zero(0, artworks_content);
+ if (aw == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&aw->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(aw);
+ return error;
+ }
+
+ *c = (struct content *) aw;
+
+ return NSERROR_OK;
+}
+
/**
* Convert a CONTENT_ARTWORKS for display.
*
@@ -100,6 +213,7 @@
bool artworks_convert(struct content *c)
{
+ artworks_content *aw = (artworks_content *) c;
union content_msg_data msg_data;
const char *source_data;
unsigned long source_size;
@@ -142,8 +256,8 @@
}
error = (os_error*)_swix(AWRender_RenderAddress, _OUT(0) | _OUT(1),
- &c->data.artworks.render_routine,
- &c->data.artworks.render_workspace);
+ &aw->render_routine,
+ &aw->render_workspace);
if (error) {
LOG(("AWRender_RenderAddress: 0x%x: %s",
error->errnum, error->errmess));
@@ -165,12 +279,13 @@
return false;
}
- error = (os_error*)_swix(AWRender_DocBounds, _IN(0) | _OUT(2) | _OUT(3) | _OUT(4) | _OUT(5),
+ error = (os_error*)_swix(AWRender_DocBounds,
+ _IN(0) | _OUT(2) | _OUT(3) | _OUT(4) | _OUT(5),
source_data,
- &c->data.artworks.x0,
- &c->data.artworks.y0,
- &c->data.artworks.x1,
- &c->data.artworks.y1);
+ &aw->x0,
+ &aw->y0,
+ &aw->x1,
+ &aw->y1);
if (error) {
LOG(("AWRender_DocBounds: 0x%x: %s",
@@ -180,24 +295,22 @@
return false;
}
- LOG(("bounding box: %d,%d,%d,%d",
- c->data.artworks.x0, c->data.artworks.y0,
- c->data.artworks.x1, c->data.artworks.y1));
+ LOG(("bounding box: %d,%d,%d,%d", aw->x0, aw->y0, aw->x1, aw->y1));
/* create the resizable workspace required by the
ArtWorksRenderer rendering routine */
- c->data.artworks.size = INITIAL_BLOCK_SIZE;
- c->data.artworks.block = malloc(INITIAL_BLOCK_SIZE);
- if (!c->data.artworks.block) {
+ aw->size = INITIAL_BLOCK_SIZE;
+ aw->block = malloc(INITIAL_BLOCK_SIZE);
+ if (!aw->block) {
LOG(("failed to create block for ArtworksRenderer"));
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
- c->width = (c->data.artworks.x1 - c->data.artworks.x0) / 512;
- c->height = (c->data.artworks.y1 - c->data.artworks.y0) / 512;
+ c->width = (aw->x1 - aw->x0) / 512;
+ c->height = (aw->y1 - aw->y0) / 512;
snprintf(title, sizeof(title), messages_get("ArtWorksTitle"),
c->width, c->height, source_size);
@@ -216,7 +329,9 @@
void artworks_destroy(struct content *c)
{
- free(c->data.artworks.block);
+ artworks_content *aw = (artworks_content *) c;
+
+ free(aw->block);
}
@@ -236,6 +351,7 @@
os_VDUVAR_END_LIST
}
};
+ artworks_content *aw = (artworks_content *) c;
struct awinfo_block info;
const char *source_data;
unsigned long source_size;
@@ -254,8 +370,8 @@
/* pick up render addresses again in case they've changed
(eg. newer AWRender module loaded since we first loaded this file) */
(void)_swix(AWRender_RenderAddress, _OUT(0) | _OUT(1),
- &c->data.artworks.render_routine,
- &c->data.artworks.render_workspace);
+ &aw->render_routine,
+ &aw->render_workspace);
/* Scaled image. Transform units (65536*OS units) */
matrix.entries[0][0] = width * 65536 / c->width;
@@ -264,9 +380,9 @@
matrix.entries[1][1] = height * 65536 / c->height;
/* Draw units. (x,y) = bottom left */
matrix.entries[2][0] = ro_plot_origin_x * 256 + x * 512 -
- c->data.artworks.x0 * width / c->width;
+ aw->x0 * width / c->width;
matrix.entries[2][1] = ro_plot_origin_y * 256 - (y + height) * 512 -
- c->data.artworks.y0 * height / c->height;
+ aw->y0 * height / c->height;
info.ditherx = ro_plot_origin_x;
info.dithery = ro_plot_origin_y;
@@ -277,16 +393,16 @@
clip_y1 -= y;
if (scale == 1.0) {
- info.clip_x0 = (clip_x0 * 512) + c->data.artworks.x0 - 511;
- info.clip_y0 = ((c->height - clip_y1) * 512) + c->data.artworks.y0 - 511;
- info.clip_x1 = (clip_x1 * 512) + c->data.artworks.x0 + 511;
- info.clip_y1 = ((c->height - clip_y0) * 512) + c->data.artworks.y0 + 511;
+ info.clip_x0 = (clip_x0 * 512) + aw->x0 - 511;
+ info.clip_y0 = ((c->height - clip_y1) * 512) + aw->y0 - 511;
+ info.clip_x1 = (clip_x1 * 512) + aw->x0 + 511;
+ info.clip_y1 = ((c->height - clip_y0) * 512) + aw->y0 + 511;
}
else {
- info.clip_x0 = (clip_x0 * 512 / scale) + c->data.artworks.x0 - 511;
- info.clip_y0 = ((c->height - (clip_y1 / scale)) * 512) + c->data.artworks.y0 - 511;
- info.clip_x1 = (clip_x1 * 512 / scale) + c->data.artworks.x0 + 511;
- info.clip_y1 = ((c->height - (clip_y0 / scale)) * 512) + c->data.artworks.y0 + 511;
+ info.clip_x0 = (clip_x0 * 512 / scale) + aw->x0 - 511;
+ info.clip_y0 = ((c->height - (clip_y1 / scale)) * 512) + aw->y0 - 511;
+ info.clip_x1 = (clip_x1 * 512 / scale) + aw->x0 + 511;
+ info.clip_y1 = ((c->height - (clip_y0 / scale)) * 512) + aw->y0 + 511;
}
info.print_lowx = 0;
@@ -314,13 +430,13 @@
&info,
&matrix,
vals,
- &c->data.artworks.block,
- &c->data.artworks.size,
+ &aw->block,
+ &aw->size,
110, /* fully anti-aliased */
0,
source_size,
- c->data.artworks.render_routine,
- c->data.artworks.render_workspace);
+ aw->render_routine,
+ aw->render_workspace);
if (error) {
LOG(("awrender_render: 0x%x: %s",
@@ -331,16 +447,38 @@
return true;
}
-bool artworks_clone(const struct content *old, struct content *new_content)
+nserror artworks_clone(const struct content *old, struct content **newc)
{
+ artworks_content *aw;
+ nserror error;
+
+ aw = talloc_zero(0, artworks_content);
+ if (aw == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &aw->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&aw->base);
+ return error;
+ }
+
/* Simply re-run convert */
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (artworks_convert(new_content) == false)
- return false;
+ if (artworks_convert(&aw->base) == false) {
+ content_destroy(&aw->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) aw;
+
+ return NSERROR_OK;
}
+content_type artworks_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
+
#endif
Index: riscos/artworks.h
===================================================================
--- riscos/artworks.h (revision 12276)
+++ riscos/artworks.h (working copy)
@@ -23,27 +23,19 @@
#ifndef _NETSURF_RISCOS_ARTWORKS_H_
#define _NETSURF_RISCOS_ARTWORKS_H_
-struct content;
-struct rect;
+#include "utils/config.h"
+#include "utils/errors.h"
-struct content_artworks_data {
- int x0, y0, x1, y1;
+#ifdef WITH_ARTWORKS
- void *render_routine;
- void *render_workspace;
+nserror artworks_init(void);
+void artworks_fini(void);
- /* dunamically-resizable block required by
- ArtWorksRenderer rendering routine */
+#else
- void *block;
- size_t size;
-};
+#define artworks_init() NSERROR_OK
+#define artworks_fini() ((void) 0)
-bool artworks_convert(struct content *c);
-void artworks_destroy(struct content *c);
-bool artworks_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool artworks_clone(const struct content *old, struct content *new_content);
+#endif
#endif
Index: riscos/filetype.c
===================================================================
--- riscos/filetype.c (revision 12276)
+++ riscos/filetype.c (working copy)
@@ -253,22 +253,69 @@
*/
int ro_content_filetype(hlcache_handle *c)
{
+ lwc_string *mime_type;
int file_type;
- os_error *error;
file_type = ro_content_filetype_from_type(content_get_type(c));
if (file_type != 0)
return file_type;
+ mime_type = content_get_mime_type(c);
+
+ file_type = ro_content_filetype_from_mime_type(mime_type);
+
+ lwc_string_unref(mime_type);
+
+ return file_type;
+}
+
+/**
+ * Determine the native RISC OS filetype to export a content as
+ *
+ * \param c The content to examine
+ * \return Native RISC OS filetype for export
+ */
+int ro_content_native_type(hlcache_handle *c)
+{
+ switch (ro_content_filetype(c)) {
+ case 0xc85: /* jpeg */
+ case 0xf78: /* jng */
+ case 0xf83: /* mng */
+ case 0x695: /* gif */
+ case 0x69c: /* bmp */
+ case 0x132: /* ico */
+ case 0xb90: /* png */
+ case 0xff9: /* sprite */
+ return osfile_TYPE_SPRITE;
+ case 0xaad: /* svg */
+ case 0xaff: /* draw */
+ return osfile_TYPE_DRAW;
+ default:
+ break;
+ }
+
+ return osfile_TYPE_DATA;
+}
+
+/**
+ * Determine the RISC OS filetype for a MIME type
+ *
+ * \param mime_type MIME type to consider
+ * \return Corresponding RISC OS filetype
+ */
+int ro_content_filetype_from_mime_type(lwc_string *mime_type)
+{
+ int file_type;
+ os_error *error;
+
error = xmimemaptranslate_mime_type_to_filetype(
- content_get_mime_type(c), (bits *) &file_type);
+ lwc_string_data(mime_type), (bits *) &file_type);
if (error)
- return 0xffd;
+ file_type = 0xffd;
return file_type;
}
-
/**
* Determine the RISC OS filetype from a content type.
*
@@ -277,39 +324,10 @@
*/
int ro_content_filetype_from_type(content_type type) {
switch (type) {
- case CONTENT_HTML: return 0xfaf;
- case CONTENT_TEXTPLAIN: return 0xfff;
- case CONTENT_CSS: return 0xf79;
-#if defined(WITH_MNG) || defined(WITH_PNG)
- case CONTENT_PNG: return 0xb60;
-#endif
-#ifdef WITH_MNG
- case CONTENT_JNG: return 0xf78;
- case CONTENT_MNG: return 0xf84;
-#endif
-#ifdef WITH_JPEG
- case CONTENT_JPEG: return 0xc85;
-#endif
-#ifdef WITH_GIF
- case CONTENT_GIF: return 0x695;
-#endif
-#ifdef WITH_BMP
- case CONTENT_BMP: return 0x69c;
- case CONTENT_ICO: return 0x132;
-#endif
-#ifdef WITH_SPRITE
- case CONTENT_SPRITE: return 0xff9;
-#endif
-#ifdef WITH_DRAW
- case CONTENT_DRAW: return 0xaff;
-#endif
-#ifdef WITH_ARTWORKS
- case CONTENT_ARTWORKS: return 0xd94;
-#endif
-#ifdef WITH_NS_SVG
- case CONTENT_SVG: return 0xaad;
-#endif
- default: break;
+ case CONTENT_HTML: return 0xfaf;
+ case CONTENT_TEXTPLAIN: return 0xfff;
+ case CONTENT_CSS: return 0xf79;
+ default: break;
}
return 0;
}
Index: riscos/print.c
===================================================================
--- riscos/print.c (revision 12276)
+++ riscos/print.c (working copy)
@@ -33,10 +33,6 @@
#include "content/content.h"
#include "content/hlcache.h"
#include "desktop/plotters.h"
-#include "render/box.h"
-#include "render/font.h"
-#include "render/html.h"
-#include "render/layout.h"
#include "riscos/dialog.h"
#include "riscos/menus.h"
#include "riscos/print.h"
@@ -592,8 +588,7 @@
saved_width = content_get_width(h);
saved_height = content_get_height(h);
if (content_get_type(h) == CONTENT_HTML)
- /* TODO: Front end code shouldn't see contents */
- layout_document(hlcache_handle_get_content(h), width, height);
+ content_reformat(h, width, height);
/* open printer file */
error = xosfind_openoutw(osfind_NO_PATH | osfind_ERROR_IF_DIR |
@@ -763,9 +758,7 @@
/* restore document layout and redraw browser window */
if (content_get_type(h) == CONTENT_HTML)
- /* TODO: Front end code shouldn't see contents */
- layout_document(hlcache_handle_get_content(h),
- saved_width, saved_height);
+ content_reformat(h, saved_width, saved_height);
gui_window_redraw_window(g);
@@ -785,9 +778,7 @@
/* restore document layout */
if (content_get_type(h) == CONTENT_HTML)
- /* TODO: Front end code shouldn't see contents */
- layout_document(hlcache_handle_get_content(h),
- saved_width, saved_height);
+ content_reformat(h, saved_width, saved_height);
return false;
}
Index: monkey/utils.c
===================================================================
--- monkey/utils.c (revision 12276)
+++ monkey/utils.c (working copy)
@@ -132,7 +132,7 @@
bool
save_complete_gui_save(const char *path, const char *filename,
- size_t len, const char *sourcedata, content_type type)
+ size_t len, const char *sourcedata, lwc_string *mime_type)
{
return true;
}
Index: desktop/searchweb.c
===================================================================
--- desktop/searchweb.c (revision 12276)
+++ desktop/searchweb.c (working copy)
@@ -209,10 +209,7 @@
*/
return;
#else
- static const content_type accept[] = {
- CONTENT_ICO,
- CONTENT_UNKNOWN
- };
+ content_type accept = CONTENT_IMAGE;
char *url;
nserror error;
@@ -284,13 +281,7 @@
case CONTENT_MSG_DONE:
LOG(("got favicon '%s'", content_get_url(ico)));
- if (content_get_type(ico) == CONTENT_ICO) {
- gui_window_set_search_ico(search_ico);
- } else {
- hlcache_handle_release(ico);
- search_ico = NULL;
- search_web_retrieve_ico(true);
- }
+ gui_window_set_search_ico(search_ico);
break;
case CONTENT_MSG_ERROR:
Index: desktop/textinput.c
===================================================================
--- desktop/textinput.c (revision 12276)
+++ desktop/textinput.c (working copy)
@@ -2128,7 +2128,7 @@
assert(c != NULL);
if (!layout_inline_container(inline_container, width,
- textarea, 0, 0, c))
+ textarea, 0, 0, (struct html_content *) c))
warn_user("NoMemory", 0);
textarea->width = width;
textarea->height = height;
Index: desktop/browser.c
===================================================================
--- desktop/browser.c (revision 12276)
+++ desktop/browser.c (working copy)
@@ -454,7 +454,7 @@
fetch_is_post ? &post : NULL,
browser_window_callback, bw,
parent != NULL ? &child : NULL,
- NULL, &c);
+ CONTENT_ANY, &c);
if (error == NSERROR_NO_FETCH_HANDLER) {
gui_launch_url(url2);
free(url2);
Index: desktop/netsurf.c
===================================================================
--- desktop/netsurf.c (revision 12276)
+++ desktop/netsurf.c (working copy)
@@ -36,12 +36,15 @@
#include "content/hlcache.h"
#include "content/urldb.h"
#include "css/css.h"
+#include "image/image.h"
#include "desktop/netsurf.h"
#include "desktop/401login.h"
#include "desktop/browser.h"
#include "desktop/gui.h"
#include "desktop/options.h"
#include "desktop/searchweb.h"
+#include "render/html.h"
+#include "render/textplain.h"
#include "utils/log.h"
#include "utils/url.h"
#include "utils/utf8.h"
@@ -94,6 +97,7 @@
const char *options,
const char *messages)
{
+ nserror error;
struct utsname utsname;
nserror ret = NSERROR_OK;
@@ -134,6 +138,22 @@
messages_load(messages);
+ error = css_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ error = html_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ error = image_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ error = textplain_init();
+ if (error != NSERROR_OK)
+ return error;
+
url_init();
setlocale(LC_ALL, "C");
@@ -176,9 +196,6 @@
LOG(("Closing GUI"));
gui_quit();
- /* Clean up after CSS */
- css_cleanup();
-
LOG(("Closing search and related resources"));
search_web_cleanup();
@@ -191,6 +208,12 @@
LOG(("Closing fetches"));
fetch_quit();
+ /* Clean up after content handlers */
+ textplain_fini();
+ image_fini();
+ html_fini();
+ css_fini();
+
LOG(("Closing utf8"));
utf8_finalise();
Index: desktop/tree.c
===================================================================
--- desktop/tree.c (revision 12276)
+++ desktop/tree.c (working copy)
@@ -2771,7 +2771,8 @@
/* Fetch the icon */
err = hlcache_handle_retrieve(icon_url, 0, 0, 0,
- tree_icon_callback, 0, 0, 0, &c);
+ tree_icon_callback, 0, 0,
+ CONTENT_IMAGE, &c);
/* If we built the URL here, free it */
Index: desktop/save_complete.c
===================================================================
--- desktop/save_complete.c (revision 12276)
+++ desktop/save_complete.c (working copy)
@@ -138,6 +138,7 @@
int source_len;
struct nscss_import *imports;
uint32_t import_count;
+ lwc_string *type;
if (sheets[i].type == HTML_STYLESHEET_INTERNAL) {
if (save_imported_sheets(
@@ -176,9 +177,19 @@
warn_user("NoMemory", 0);
return false;
}
+
+ type = content_get_mime_type(css);
+ if (type == NULL) {
+ free(source);
+ return false;
+ }
+
res = save_complete_gui_save(path, filename, source_len,
- source, CONTENT_CSS);
+ source, type);
+
+ lwc_string_unref(type);
free(source);
+
if (res == false)
return false;
}
@@ -190,8 +201,9 @@
hlcache_handle *obj = object->content;
const char *obj_data;
unsigned long obj_size;
+ lwc_string *type;
- if (obj == NULL || content_get_type(obj) >= CONTENT_OTHER)
+ if (obj == NULL || content_get_type(obj) == CONTENT_NONE)
continue;
obj_data = content_get_source_data(obj, &obj_size);
@@ -214,8 +226,16 @@
}
snprintf(filename, sizeof filename, "%p", obj);
+
+ type = content_get_mime_type(obj);
+ if (type == NULL)
+ return false;
+
res = save_complete_gui_save(path, filename,
- obj_size, obj_data, content_get_type(obj));
+ obj_size, obj_data, type);
+
+ lwc_string_unref(type);
+
if(res == false)
return false;
}
@@ -282,6 +302,7 @@
unsigned long css_size;
struct nscss_import *child_imports;
uint32_t child_import_count;
+ lwc_string *type;
if (css == NULL)
continue;
@@ -310,9 +331,19 @@
return false;
}
+ if (lwc_intern_string("text/css", SLEN("text/css"), &type) !=
+ lwc_error_ok) {
+ free(source);
+ warn_user("NoMemory", 0);
+ return false;
+ }
+
res = save_complete_gui_save(path, filename, source_len,
- source, CONTENT_CSS);
+ source, type);
+
+ lwc_string_unref(type);
free(source);
+
if (res == false)
return false;
}
Index: desktop/tree_url_node.c
===================================================================
--- desktop/tree_url_node.c (revision 12276)
+++ desktop/tree_url_node.c (working copy)
@@ -61,42 +61,7 @@
{CONTENT_HTML, NULL},
{CONTENT_TEXTPLAIN, NULL},
{CONTENT_CSS, NULL},
-#if defined(WITH_MNG) || defined(WITH_PNG)
- {CONTENT_PNG, NULL},
-#endif
-#ifdef WITH_MNG
- {CONTENT_JNG, NULL},
- {CONTENT_MNG, NULL},
-#endif
-#ifdef WITH_JPEG
- {CONTENT_JPEG, NULL},
-#endif
-#ifdef WITH_GIF
- {CONTENT_GIF, NULL},
-#endif
-#ifdef WITH_BMP
- {CONTENT_BMP, NULL},
- {CONTENT_ICO, NULL},
-#endif
-#ifdef WITH_SPRITE
- {CONTENT_SPRITE, NULL},
-#endif
-#ifdef WITH_DRAW
- {CONTENT_DRAW, NULL},
-#endif
-#ifdef WITH_ARTWORKS
- {CONTENT_ARTWORKS, NULL},
-#endif
-#ifdef WITH_NS_SVG
- {CONTENT_SVG, NULL},
-#endif
-#ifdef WITH_WEBP
- {CONTENT_WEBP, NULL},
-#endif
-#ifdef WITH_AMIGA_ICON
- {CONTENT_AMIGA_ICON, NULL},
-#endif
- {CONTENT_UNKNOWN, NULL},
+ {CONTENT_IMAGE, NULL},
/* this serves as a sentinel */
{CONTENT_HTML, NULL}
Index: desktop/save_complete.h
===================================================================
--- desktop/save_complete.h (revision 12276)
+++ desktop/save_complete.h (working copy)
@@ -26,15 +26,16 @@
#include <stdbool.h>
#include <libxml/HTMLtree.h>
-#include "content/content.h"
+#include <libwapcaplet/libwapcaplet.h>
+
struct hlcache_handle;
void save_complete_init(void);
bool save_complete(struct hlcache_handle *c, const char *path);
bool save_complete_gui_save(const char *path, const char *filename,
- size_t len, const char *sourcedata, content_type type);
+ size_t len, const char *sourcedata, lwc_string *mime_type);
int save_complete_htmlSaveFileFormat(const char *path, const char *filename,
xmlDocPtr cur, const char *encoding, int format);
Index: content/content.c
===================================================================
--- content/content.c (revision 12276)
+++ content/content.c (working copy)
@@ -40,52 +40,6 @@
#include "desktop/options.h"
#include "render/html.h"
#include "render/textplain.h"
-#ifdef WITH_JPEG
-#include "image/jpeg.h"
-#endif
-#ifdef WITH_MNG
-#include "image/mng.h"
-#endif
-#ifdef WITH_GIF
-#include "image/gif.h"
-#endif
-#ifdef WITH_BMP
-#include "image/bmp.h"
-#include "image/ico.h"
-#endif
-#ifdef WITH_NS_SVG
-#include "image/svg.h"
-#endif
-#ifdef WITH_RSVG
-#include "image/rsvg.h"
-#endif
-#ifdef WITH_SPRITE
-#include "riscos/sprite.h"
-#endif
-#ifdef WITH_NSSPRITE
-#include "image/nssprite.h"
-#endif
-#ifdef WITH_DRAW
-#include "riscos/draw.h"
-#endif
-#ifdef WITH_PLUGIN
-#include "desktop/plugin.h"
-#endif
-#ifdef WITH_ARTWORKS
-#include "riscos/artworks.h"
-#endif
-#ifdef WITH_PNG
-#include "image/png.h"
-#endif
-#ifdef WITH_WEBP
-#include "image/webp.h"
-#endif
-#ifdef WITH_AMIGA_ICON
-#include "amiga/icon.h"
-#endif
-#ifdef WITH_APPLE_IMAGE
-#include "cocoa/apple_image.h"
-#endif
#include "utils/http.h"
#include "utils/log.h"
@@ -94,179 +48,6 @@
#include "utils/utils.h"
-/** An entry in mime_map. */
-struct mime_entry {
- char mime_type[40];
- content_type type;
-};
-/** A map from MIME type to ::content_type. Must be sorted by mime_type. */
-static const struct mime_entry mime_map[] = {
-#ifdef WITH_BMP
- {"application/bmp", CONTENT_BMP},
-#endif
-#ifdef WITH_DRAW
- {"application/drawfile", CONTENT_DRAW},
-#endif
-#ifdef WITH_BMP
- {"application/ico", CONTENT_ICO},
- {"application/preview", CONTENT_BMP},
- {"application/x-bmp", CONTENT_BMP},
-#endif
-#ifdef WITH_DRAW
- {"application/x-drawfile", CONTENT_DRAW},
-#endif
-#ifdef WITH_BMP
- {"application/x-ico", CONTENT_ICO},
-#endif
-#ifdef WITH_THEME_INSTALL
- {"application/x-netsurf-theme", CONTENT_THEME},
-#endif
-#ifdef WITH_BMP
- {"application/x-win-bitmap", CONTENT_BMP},
-#endif
- {"application/xhtml+xml", CONTENT_HTML},
-#ifdef WITH_BMP
- {"image/bmp", CONTENT_BMP},
-#endif
-#ifdef WITH_DRAW
- {"image/drawfile", CONTENT_DRAW},
-#endif
-#ifdef WITH_GIF
- {"image/gif", CONTENT_GIF},
-#endif
-#ifdef WITH_BMP
- {"image/ico", CONTENT_ICO},
-#endif
-#ifdef WITH_MNG
- {"image/jng", CONTENT_JNG},
-#endif
-#ifdef WITH_JPEG
- {"image/jpeg", CONTENT_JPEG},
- {"image/jpg", CONTENT_JPEG},
-#endif
-#ifdef WITH_APPLE_IMAGE
- {"image/jpeg", CONTENT_APPLE_IMAGE},
- {"image/jpg", CONTENT_APPLE_IMAGE},
-#endif
-#ifdef WITH_MNG
- {"image/mng", CONTENT_MNG},
-#endif
-#ifdef WITH_BMP
- {"image/ms-bmp", CONTENT_BMP},
-#endif
-#ifdef WITH_JPEG
- {"image/pjpeg", CONTENT_JPEG},
-#endif
-#ifdef WITH_APPLE_IMAGE
- {"image/pjpeg", CONTENT_APPLE_IMAGE},
-#endif
-#if defined(WITH_MNG) || defined(WITH_PNG)
- {"image/png", CONTENT_PNG},
-#endif
-#if defined(WITH_NS_SVG) || defined (WITH_RSVG)
- {"image/svg", CONTENT_SVG},
- {"image/svg+xml", CONTENT_SVG},
-#endif
-#ifdef WITH_BMP
- {"image/vnd.microsoft.icon", CONTENT_ICO},
-#endif
-#ifdef WITH_WEBP
- {"image/webp", CONTENT_WEBP},
-#endif
-#ifdef WITH_AMIGA_ICON
- {"image/x-amiga-icon", CONTENT_AMIGA_ICON},
-#endif
-#ifdef WITH_ARTWORKS
- {"image/x-artworks", CONTENT_ARTWORKS},
-#endif
-#ifdef WITH_BMP
- {"image/x-bitmap", CONTENT_BMP},
- {"image/x-bmp", CONTENT_BMP},
-#endif
-#ifdef WITH_DRAW
- {"image/x-drawfile", CONTENT_DRAW},
-#endif
-#ifdef WITH_BMP
- {"image/x-icon", CONTENT_ICO},
-#endif
-#ifdef WITH_MNG
- {"image/x-jng", CONTENT_JNG},
- {"image/x-mng", CONTENT_MNG},
-#endif
-#ifdef WITH_BMP
- {"image/x-ms-bmp", CONTENT_BMP},
-#endif
-#if defined(WITH_SPRITE) || defined(WITH_NSSPRITE)
- {"image/x-riscos-sprite", CONTENT_SPRITE},
-#endif
-#ifdef WITH_BMP
- {"image/x-win-bitmap", CONTENT_BMP},
- {"image/x-windows-bmp", CONTENT_BMP},
- {"image/x-xbitmap", CONTENT_BMP},
-#endif
- {"text/css", CONTENT_CSS},
- {"text/html", CONTENT_HTML},
- {"text/plain", CONTENT_TEXTPLAIN},
-#ifdef WITH_MNG
- {"video/mng", CONTENT_MNG},
- {"video/x-mng", CONTENT_MNG},
-#endif
-};
-#define MIME_MAP_COUNT (sizeof(mime_map) / sizeof(mime_map[0]))
-
-const char * const content_type_name[] = {
- "HTML",
- "TEXTPLAIN",
- "CSS",
-#ifdef WITH_JPEG
- "JPEG",
-#endif
-#ifdef WITH_GIF
- "GIF",
-#endif
-#ifdef WITH_BMP
- "BMP",
- "ICO",
-#endif
-#if defined(WITH_MNG) || defined(WITH_PNG)
- "PNG",
-#endif
-#ifdef WITH_MNG
- "JNG",
- "MNG",
-#endif
-#if defined(WITH_SPRITE) || defined(WITH_NSSPRITE)
- "SPRITE",
-#endif
-#ifdef WITH_DRAW
- "DRAW",
-#endif
-#ifdef WITH_PLUGIN
- "PLUGIN",
-#endif
- "DIRECTORY",
-#ifdef WITH_THEME_INSTALL
- "THEME",
-#endif
-#ifdef WITH_ARTWORKS
- "ARTWORKS",
-#endif
-#if defined(WITH_NS_SVG) || defined(WITH_RSVG)
- "SVG",
-#endif
-#ifdef WITH_WEBP
- "WEBP",
-#endif
-#ifdef WITH_AMIGA_ICON
- "AMIGA_ICON",
-#endif
-#ifdef WITH_APPLE_IMAGE
- "APPLE_IMAGE",
-#endif
- "OTHER",
- "UNKNOWN"
-};
-
const char * const content_status_name[] = {
"LOADING",
"READY",
@@ -274,139 +55,6 @@
"ERROR"
};
-/** An entry in handler_map. */
-struct handler_entry {
- bool (*create)(struct content *c, const http_parameter *params);
- bool (*process_data)(struct content *c,
- const char *data, unsigned int size);
- bool (*convert)(struct content *c);
- void (*reformat)(struct content *c, int width, int height);
- void (*destroy)(struct content *c);
- void (*stop)(struct content *c);
- void (*mouse_track)(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y);
- void (*mouse_action)(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y);
- bool (*redraw)(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
- bool (*redraw_tiled)(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y);
- void (*open)(struct content *c, struct browser_window *bw,
- struct content *page,
- struct box *box,
- struct object_params *params);
- void (*close)(struct content *c);
- bool (*clone)(const struct content *old, struct content *new_content);
- /** There must be one content per user for this type. */
- bool no_share;
-};
-/** A table of handler functions, indexed by ::content_type.
- * Must be ordered as enum ::content_type. */
-static const struct handler_entry handler_map[] = {
- {html_create, html_process_data, html_convert,
- html_reformat, html_destroy, html_stop, html_mouse_track,
- html_mouse_action, html_redraw, 0, html_open, html_close,
- html_clone, true},
- {textplain_create, textplain_process_data, textplain_convert,
- textplain_reformat, textplain_destroy, 0, textplain_mouse_track,
- textplain_mouse_action, textplain_redraw, 0, 0, 0,
- textplain_clone, true},
- {nscss_create, nscss_process_data, nscss_convert, 0, nscss_destroy,
- 0, 0, 0, 0, 0, 0, 0, nscss_clone, false},
-#ifdef WITH_JPEG
- {0, 0, nsjpeg_convert, 0, nsjpeg_destroy, 0, 0, 0,
- nsjpeg_redraw, nsjpeg_redraw_tiled, 0, 0, nsjpeg_clone, false},
-#endif
-#ifdef WITH_GIF
- {nsgif_create, 0, nsgif_convert, 0, nsgif_destroy, 0, 0, 0,
- nsgif_redraw, nsgif_redraw_tiled, 0, 0, nsgif_clone, false},
-#endif
-#ifdef WITH_BMP
- {nsbmp_create, 0, nsbmp_convert, 0, nsbmp_destroy, 0, 0, 0,
- nsbmp_redraw, nsbmp_redraw_tiled, 0, 0, nsbmp_clone, false},
- {nsico_create, 0, nsico_convert, 0, nsico_destroy, 0, 0, 0,
- nsico_redraw, nsico_redraw_tiled, 0, 0, nsico_clone, false},
-#endif
-
-#ifdef WITH_PNG
- {nspng_create, nspng_process_data, nspng_convert,
- 0, nspng_destroy, 0, 0, 0, nspng_redraw, nspng_redraw_tiled,
- 0, 0, nspng_clone, false},
-#else
-#ifdef WITH_MNG
- {nsmng_create, nsmng_process_data, nsmng_convert,
- 0, nsmng_destroy, 0, 0, 0, nsmng_redraw, nsmng_redraw_tiled,
- 0, 0, nsmng_clone, false},
-#endif
-#endif
-#ifdef WITH_MNG
- {nsmng_create, nsmng_process_data, nsmng_convert,
- 0, nsmng_destroy, 0, 0, 0, nsmng_redraw, nsmng_redraw_tiled,
- 0, 0, nsmng_clone, false},
- {nsmng_create, nsmng_process_data, nsmng_convert,
- 0, nsmng_destroy, 0, 0, 0, nsmng_redraw, nsmng_redraw_tiled,
- 0, 0, nsmng_clone, false},
-#endif
-#ifdef WITH_SPRITE
- {0, 0, sprite_convert,
- 0, sprite_destroy, 0, 0, 0, sprite_redraw, 0,
- 0, 0, sprite_clone, false},
-#endif
-#ifdef WITH_NSSPRITE
- {0, 0, nssprite_convert,
- 0, nssprite_destroy, 0, 0, 0, nssprite_redraw, 0,
- 0, 0, nssprite_clone, false},
-#endif
-#ifdef WITH_DRAW
- {0, 0, draw_convert,
- 0, draw_destroy, 0, 0, 0, draw_redraw, 0, 0, 0, draw_clone,
- false},
-#endif
-#ifdef WITH_PLUGIN
- {plugin_create, 0, plugin_convert,
- plugin_reformat, plugin_destroy, 0, 0, 0, plugin_redraw, 0,
- plugin_open, plugin_close, plugin_clone,
- true},
-#endif
-#ifdef WITH_THEME_INSTALL
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false},
-#endif
-#ifdef WITH_ARTWORKS
- {0, 0, artworks_convert,
- 0, artworks_destroy, 0, 0, 0, artworks_redraw, 0,
- 0, 0, artworks_clone, false},
-#endif
-#ifdef WITH_NS_SVG
- {svg_create, 0, svg_convert,
- svg_reformat, svg_destroy, 0, 0, 0, svg_redraw, 0,
- 0, 0, svg_clone, true},
-#endif
-#ifdef WITH_RSVG
- {rsvg_create, rsvg_process_data, rsvg_convert,
- 0, rsvg_destroy, 0, 0, 0, rsvg_redraw, 0, 0, 0, rsvg_clone,
- false},
-#endif
-#ifdef WITH_WEBP
- {0, 0, webp_convert,
- 0, webp_destroy, 0, 0, 0, webp_redraw, 0,
- 0, 0, webp_clone, false},
-#endif
-#ifdef WITH_AMIGA_ICON
- {0, 0, amiga_icon_convert,
- 0, amiga_icon_destroy, 0, 0, 0, amiga_icon_redraw, 0,
- 0, 0, amiga_icon_clone, false},
-#endif
-#ifdef WITH_APPLE_IMAGE
- {0, 0, apple_image_convert, 0, apple_image_destroy, 0, 0, 0,
- apple_image_redraw, apple_image_redraw_tiled, 0, 0, apple_image_clone, false},
-#endif
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false}
-};
-#define HANDLER_MAP_COUNT (sizeof(handler_map) / sizeof(handler_map[0]))
-
static nserror content_llcache_callback(llcache_handle *llcache,
const llcache_event *event, void *pw);
static void content_convert(struct content *c);
@@ -414,95 +62,41 @@
/**
- * Convert a MIME type to a content_type.
+ * Initialise a new content structure.
*
- * The returned ::content_type will always be suitable for content_create().
+ * \param c Content to initialise (allocated with talloc)
+ * \param handler Content handler
+ * \param imime_type MIME type of content
+ * \param params HTTP parameters
+ * \param llcache Source data handle
+ * \param fallback_charset Fallback charset
+ * \param quirks Quirkiness of content
+ * \return NSERROR_OK on success, appropriate error otherwise
*/
-content_type content_lookup(const char *mime_type)
+nserror content__init(struct content *c, const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks)
{
- struct mime_entry *m;
- m = bsearch(mime_type, mime_map, MIME_MAP_COUNT, sizeof(mime_map[0]),
- (int (*)(const void *, const void *)) strcasecmp);
- if (m == 0) {
-#ifdef WITH_PLUGIN
- if (plugin_handleable(mime_type))
- return CONTENT_PLUGIN;
-#endif
- return CONTENT_OTHER;
- }
- return m->type;
-}
-
-
-/**
- * Create a new content structure.
- *
- * \param url URL of content, copied
- * \return the new content structure, or 0 on memory exhaustion
- */
-
-struct content * content_create(llcache_handle *llcache,
- const char *fallback_charset, bool quirks)
-{
- struct content *c;
struct content_user *user_sentinel;
- const char *content_type_header;
- content_type type;
- char *mime_type;
- http_parameter *params;
nserror error;
- content_type_header =
- llcache_handle_get_header(llcache, "Content-Type");
- if (content_type_header == NULL)
- content_type_header = "text/plain";
-
- error = http_parse_content_type(content_type_header, &mime_type,
- ¶ms);
- if (error != NSERROR_OK)
- return NULL;
-
- type = content_lookup(mime_type);
-
- c = talloc_zero(0, struct content);
- if (c == NULL) {
- http_parameter_list_destroy(params);
- free(mime_type);
- return NULL;
- }
-
LOG(("url %s -> %p", llcache_handle_get_url(llcache), c));
user_sentinel = talloc(c, struct content_user);
if (user_sentinel == NULL) {
- talloc_free(c);
- http_parameter_list_destroy(params);
- free(mime_type);
- return NULL;
+ return NSERROR_NOMEM;
}
c->fallback_charset = talloc_strdup(c, fallback_charset);
if (fallback_charset != NULL && c->fallback_charset == NULL) {
- talloc_free(c);
- http_parameter_list_destroy(params);
- free(mime_type);
- return NULL;
+ return NSERROR_NOMEM;
}
- c->mime_type = talloc_strdup(c, mime_type);
- if (c->mime_type == NULL) {
- talloc_free(c);
- http_parameter_list_destroy(params);
- free(mime_type);
- return NULL;
- }
-
- /* No longer require mime_type */
- free(mime_type);
-
c->llcache = llcache;
- c->type = type;
+ c->mime_type = lwc_string_ref(imime_type);
+ c->handler = handler;
c->status = CONTENT_STATUS_LOADING;
c->width = 0;
c->height = 0;
@@ -526,24 +120,15 @@
content_set_status(c, messages_get("Loading"));
- if (handler_map[type].create) {
- if (handler_map[type].create(c, params) == false) {
- talloc_free(c);
- http_parameter_list_destroy(params);
- return NULL;
- }
- }
-
- http_parameter_list_destroy(params);
-
/* Finally, claim low-level cache events */
- if (llcache_handle_change_callback(llcache,
- content_llcache_callback, c) != NSERROR_OK) {
- talloc_free(c);
- return NULL;
+ error = llcache_handle_change_callback(llcache,
+ content_llcache_callback, c);
+ if (error != NSERROR_OK) {
+ lwc_string_unref(c->mime_type);
+ return error;
}
- return c;
+ return NSERROR_OK;
}
/**
@@ -566,8 +151,8 @@
/* Will never happen: handled in hlcache */
break;
case LLCACHE_EVENT_HAD_DATA:
- if (handler_map[c->type].process_data) {
- if (handler_map[c->type].process_data(c,
+ if (c->handler->process_data != NULL) {
+ if (c->handler->process_data(c,
(const char *) event->data.data.buf,
event->data.data.len) == false) {
llcache_handle_abort(c->llcache);
@@ -618,7 +203,7 @@
if (c == NULL)
return false;
- return (handler_map[c->type].reformat != NULL);
+ return (c->handler->reformat != NULL);
}
@@ -687,7 +272,6 @@
void content_convert(struct content *c)
{
assert(c);
- assert(c->type < HANDLER_MAP_COUNT);
assert(c->status == CONTENT_STATUS_LOADING ||
c->status == CONTENT_STATUS_ERROR);
@@ -699,9 +283,9 @@
LOG(("content %s (%p)", llcache_handle_get_url(c->llcache), c));
- if (handler_map[c->type].convert) {
+ if (c->handler->convert != NULL) {
c->locked = true;
- if (handler_map[c->type].convert(c) == false) {
+ if (c->handler->convert(c) == false) {
c->locked = false;
c->status = CONTENT_STATUS_ERROR;
}
@@ -766,8 +350,8 @@
LOG(("%p %s", c, llcache_handle_get_url(c->llcache)));
c->locked = true;
c->available_width = width;
- if (handler_map[c->type].reformat) {
- handler_map[c->type].reformat(c, width, height);
+ if (c->handler->reformat != NULL) {
+ c->handler->reformat(c, width, height);
content_broadcast(c, CONTENT_MSG_REFORMAT, data);
}
c->locked = false;
@@ -786,12 +370,14 @@
LOG(("content %p %s", c, llcache_handle_get_url(c->llcache)));
assert(c->locked == false);
- if (c->type < HANDLER_MAP_COUNT && handler_map[c->type].destroy)
- handler_map[c->type].destroy(c);
+ if (c->handler->destroy != NULL)
+ c->handler->destroy(c);
llcache_handle_release(c->llcache);
c->llcache = NULL;
+ lwc_string_unref(c->mime_type);
+
talloc_free(c);
}
@@ -812,8 +398,9 @@
struct content *c = hlcache_handle_get_content(h);
assert(c != NULL);
- if (handler_map[c->type].mouse_track)
- handler_map[c->type].mouse_track(c, bw, mouse, x, y);
+ if (c->handler->mouse_track != NULL)
+ c->handler->mouse_track(c, bw, mouse, x, y);
+
return;
}
@@ -840,8 +427,9 @@
struct content *c = hlcache_handle_get_content(h);
assert(c != NULL);
- if (handler_map[c->type].mouse_action)
- handler_map[c->type].mouse_action(c, bw, mouse, x, y);
+ if (c->handler->mouse_action != NULL)
+ c->handler->mouse_action(c, bw, mouse, x, y);
+
return;
}
@@ -925,11 +513,11 @@
return true;
}
- if (handler_map[c->type].redraw == NULL) {
+ if (c->handler->redraw == NULL) {
return true;
}
- return handler_map[c->type].redraw(c, x, y, width, height,
+ return c->handler->redraw(c, x, y, width, height,
clip, scale, background_colour);
}
@@ -956,18 +544,19 @@
if (c->locked)
/* not safe to attempt redraw */
return true;
- if (handler_map[c->type].redraw_tiled) {
- return handler_map[c->type].redraw_tiled(c, x, y, width, height,
+
+ if (c->handler->redraw_tiled != NULL) {
+ return c->handler->redraw_tiled(c, x, y, width, height,
clip, scale, background_colour,
repeat_x, repeat_y);
} else {
/* ensure we have a redrawable content */
- if ((!handler_map[c->type].redraw) || (width == 0) ||
+ if ((c->handler->redraw == NULL) || (width == 0) ||
(height == 0))
return true;
/* simple optimisation for no repeat (common for backgrounds) */
if ((!repeat_x) && (!repeat_y))
- return handler_map[c->type].redraw(c, x, y, width,
+ return c->handler->redraw(c, x, y, width,
height, clip, scale, background_colour);
/* find the redraw boundaries to loop within*/
x0 = x;
@@ -987,7 +576,7 @@
/* repeatedly plot our content */
for (y = y0; y < y1; y += height)
for (x = x0; x < x1; x += width)
- if (!handler_map[c->type].redraw(c, x, y,
+ if (!c->handler->redraw(c, x, y,
width, height, clip,
scale, background_colour))
return false;
@@ -1086,11 +675,10 @@
*/
bool content_matches_quirks(struct content *c, bool quirks)
{
- /* If the content isn't CSS, we don't care about quirks */
- if (c->type != CONTENT_CSS)
+ if (c->handler->matches_quirks == NULL)
return true;
- return c->quirks == quirks;
+ return c->handler->matches_quirks(c, quirks);
}
/**
@@ -1101,7 +689,7 @@
*/
bool content_is_shareable(struct content *c)
{
- return handler_map[c->type].no_share == false;
+ return c->handler->no_share == false;
}
/**
@@ -1141,10 +729,9 @@
{
struct content *c = hlcache_handle_get_content(h);
assert(c != 0);
- assert(c->type < CONTENT_UNKNOWN);
LOG(("content %p %s", c, llcache_handle_get_url(c->llcache)));
- if (handler_map[c->type].open)
- handler_map[c->type].open(c, bw, page, box, params);
+ if (c->handler->open != NULL)
+ c->handler->open(c, bw, page, box, params);
}
@@ -1158,10 +745,9 @@
{
struct content *c = hlcache_handle_get_content(h);
assert(c != 0);
- assert(c->type < CONTENT_UNKNOWN);
LOG(("content %p %s", c, llcache_handle_get_url(c->llcache)));
- if (handler_map[c->type].close)
- handler_map[c->type].close(c);
+ if (c->handler->close != NULL)
+ c->handler->close(c);
}
@@ -1185,41 +771,38 @@
}
/**
- * Retrieve type of content
+ * Retrieve computed type of content
*
* \param c Content to retrieve type of
- * \return Content type
+ * \return Computed content type
*/
content_type content_get_type(hlcache_handle *h)
{
- return content__get_type(hlcache_handle_get_content(h));
-}
+ struct content *c = hlcache_handle_get_content(h);
-content_type content__get_type(struct content *c)
-{
if (c == NULL)
- return CONTENT_UNKNOWN;
+ return CONTENT_NONE;
- return c->type;
+ return c->handler->type(c->mime_type);
}
/**
* Retrieve mime-type of content
*
* \param c Content to retrieve mime-type of
- * \return Pointer to mime-type, or NULL if not found.
+ * \return Pointer to referenced mime-type, or NULL if not found.
*/
-const char *content_get_mime_type(hlcache_handle *h)
+lwc_string *content_get_mime_type(hlcache_handle *h)
{
return content__get_mime_type(hlcache_handle_get_content(h));
}
-const char *content__get_mime_type(struct content *c)
+lwc_string *content__get_mime_type(struct content *c)
{
if (c == NULL)
return NULL;
- return c->mime_type;
+ return lwc_string_ref(c->mime_type);
}
/**
@@ -1501,29 +1084,37 @@
*/
struct content *content_clone(struct content *c)
{
- struct content *nc = talloc_zero(0, struct content);
+ struct content *nc;
+ nserror error;
- if (nc == NULL) {
+ error = c->handler->clone(c, &nc);
+ if (error != NSERROR_OK)
return NULL;
+
+ return nc;
+};
+
+/**
+ * Clone a content's data members
+ *
+ * \param c Content to clone
+ * \param nc Content to populate (allocated with talloc)
+ * \return NSERROR_OK on success, appropriate error otherwise
+ */
+nserror content__clone(const struct content *c, struct content *nc)
+{
+ nserror error;
+
+ error = llcache_handle_clone(c->llcache, &(nc->llcache));
+ if (error != NSERROR_OK) {
+ return error;
}
- if (llcache_handle_clone(c->llcache, &(nc->llcache)) != NSERROR_OK) {
- content_destroy(nc);
- return NULL;
- }
-
llcache_handle_change_callback(nc->llcache,
content_llcache_callback, nc);
-
- nc->type = c->type;
- if (c->mime_type != NULL) {
- nc->mime_type = talloc_strdup(nc, c->mime_type);
- if (nc->mime_type == NULL) {
- content_destroy(nc);
- return NULL;
- }
- }
+ nc->mime_type = lwc_string_ref(c->mime_type);
+ nc->handler = c->handler;
nc->status = c->status;
@@ -1535,16 +1126,14 @@
if (c->fallback_charset != NULL) {
nc->fallback_charset = talloc_strdup(nc, c->fallback_charset);
if (nc->fallback_charset == NULL) {
- content_destroy(nc);
- return NULL;
+ return NSERROR_NOMEM;
}
}
if (c->refresh != NULL) {
nc->refresh = talloc_strdup(nc, c->refresh);
if (nc->refresh == NULL) {
- content_destroy(nc);
- return NULL;
+ return NSERROR_NOMEM;
}
}
@@ -1556,8 +1145,7 @@
if (c->title != NULL) {
nc->title = talloc_strdup(nc, c->title);
if (nc->title == NULL) {
- content_destroy(nc);
- return NULL;
+ return NSERROR_NOMEM;
}
}
@@ -1570,15 +1158,7 @@
nc->total_size = c->total_size;
nc->http_code = c->http_code;
- /* Duplicate the data member (and bitmap, if appropriate) */
- if (handler_map[nc->type].clone != NULL) {
- if (handler_map[nc->type].clone(c, nc) == false) {
- content_destroy(nc);
- return NULL;
- }
- }
-
- return nc;
+ return NSERROR_OK;
}
/**
@@ -1592,13 +1172,8 @@
LOG(("Aborting %p", c));
if (c->status == CONTENT_STATUS_READY) {
- switch (c->type) {
- case CONTENT_HTML:
- html_stop(c);
- break;
- default:
- LOG(("Unable to abort sub-parts for type %d", c->type));
- }
+ if (c->handler->stop != NULL)
+ c->handler->stop(c);
}
/* And for now, abort our llcache object */
Index: content/content.h
===================================================================
--- content/content.h (revision 12276)
+++ content/content.h (working copy)
@@ -28,8 +28,12 @@
#include <stdbool.h>
+#include <libwapcaplet/libwapcaplet.h>
+
#include "utils/config.h"
#include "utils/errors.h"
+#include "utils/http.h"
+#include "content/content_factory.h"
#include "content/content_type.h"
#include "desktop/mouse.h"
#include "desktop/plot_style.h"
@@ -88,11 +92,7 @@
struct llcache_handle *download;
};
-
/* The following are for hlcache */
-content_type content_lookup(const char *mime_type);
-struct content *content_create(struct llcache_handle *llcache,
- const char *fallback_charset, bool quirks);
void content_destroy(struct content *c);
bool content_add_user(struct content *h,
@@ -138,7 +138,7 @@
/* Member accessors */
content_type content_get_type(struct hlcache_handle *c);
-const char *content_get_mime_type(struct hlcache_handle *c);
+lwc_string *content_get_mime_type(struct hlcache_handle *c);
const char *content_get_url(struct hlcache_handle *c);
const char *content_get_title(struct hlcache_handle *c);
content_status content_get_status(struct hlcache_handle *c);
Index: content/content_type.h
===================================================================
--- content/content_type.h (revision 12276)
+++ content/content_type.h (working copy)
@@ -30,56 +30,19 @@
/** The type of a content. */
typedef enum {
- CONTENT_HTML,
- CONTENT_TEXTPLAIN,
- CONTENT_CSS,
-#ifdef WITH_JPEG
- CONTENT_JPEG,
-#endif
-#ifdef WITH_GIF
- CONTENT_GIF,
-#endif
-#ifdef WITH_BMP
- CONTENT_BMP,
- CONTENT_ICO,
-#endif
-#if defined(WITH_MNG) || defined(WITH_PNG)
- CONTENT_PNG,
-#endif
-#ifdef WITH_MNG
- CONTENT_JNG,
- CONTENT_MNG,
-#endif
-#if defined(WITH_SPRITE) || defined(WITH_NSSPRITE)
- CONTENT_SPRITE,
-#endif
-#ifdef WITH_DRAW
- CONTENT_DRAW,
-#endif
-#ifdef WITH_PLUGIN
- CONTENT_PLUGIN,
-#endif
-#ifdef WITH_THEME_INSTALL
- CONTENT_THEME,
-#endif
-#ifdef WITH_ARTWORKS
- CONTENT_ARTWORKS,
-#endif
-#if defined(WITH_NS_SVG) || defined(WITH_RSVG)
- CONTENT_SVG,
-#endif
-#ifdef WITH_WEBP
- CONTENT_WEBP,
-#endif
-#ifdef WITH_AMIGA_ICON
- CONTENT_AMIGA_ICON,
-#endif
-#ifdef WITH_APPLE_IMAGE
- CONTENT_APPLE_IMAGE,
-#endif
- /* these must be the last two */
- CONTENT_OTHER,
- CONTENT_UNKNOWN /**< content-type not received yet */
+ CONTENT_NONE = 0x00,
+
+ CONTENT_HTML = 0x01,
+ CONTENT_TEXTPLAIN = 0x02,
+ CONTENT_CSS = 0x04,
+
+ CONTENT_IMAGE = 0x08,
+
+ CONTENT_PLUGIN = 0x10,
+
+ CONTENT_THEME = 0x20,
+
+ CONTENT_ANY = 0x3f
} content_type;
Index: content/hlcache.c
===================================================================
--- content/hlcache.c (revision 12276)
+++ content/hlcache.c (working copy)
@@ -48,7 +48,7 @@
uint32_t flags; /**< Retrieval flags */
- const content_type *accepted_types; /**< Accepted types, or NULL */
+ content_type accepted_types; /**< Accepted types */
hlcache_child_context child; /**< Child context */
};
@@ -80,8 +80,7 @@
static nserror hlcache_llcache_callback(llcache_handle *handle,
const llcache_event *event, void *pw);
static bool hlcache_type_is_acceptable(llcache_handle *llcache,
- const content_type *accepted_types,
- content_type *computed_type);
+ content_type accepted_types, content_type *computed_type);
static nserror hlcache_find_content(hlcache_retrieval_ctx *ctx);
static void hlcache_content_callback(struct content *c,
content_msg msg, union content_msg_data data, void *pw);
@@ -124,7 +123,7 @@
num_contents++;
}
- LOG(("%d contents to before cache drain", num_contents));
+ LOG(("%d contents remain before cache drain", num_contents));
/* Drain cache */
do {
@@ -189,7 +188,7 @@
const char *referer, llcache_post_data *post,
hlcache_handle_callback cb, void *pw,
hlcache_child_context *child,
- const content_type *accepted_types, hlcache_handle **result)
+ content_type accepted_types, hlcache_handle **result)
{
hlcache_retrieval_ctx *ctx;
nserror error;
@@ -449,7 +448,7 @@
switch (event->type) {
case LLCACHE_EVENT_HAD_HEADERS:
{
- content_type type = CONTENT_UNKNOWN;
+ content_type type = 0;
/* Unlink the context to prevent recursion */
RING_REMOVE(hlcache_retrieval_ctx_ring, ctx);
@@ -472,8 +471,8 @@
free(ctx);
return error;
}
- } else if (type == CONTENT_OTHER &&
- ctx->flags & HLCACHE_RETRIEVE_MAY_DOWNLOAD) {
+ } else if (type == CONTENT_NONE &&
+ (ctx->flags & HLCACHE_RETRIEVE_MAY_DOWNLOAD)) {
/* Unknown type, and we can download, so convert */
llcache_handle_force_stream(handle);
@@ -539,14 +538,13 @@
* \return True if the type is acceptable, false otherwise
*/
bool hlcache_type_is_acceptable(llcache_handle *llcache,
- const content_type *accepted_types, content_type *computed_type)
+ content_type accepted_types, content_type *computed_type)
{
const char *content_type_header;
char *mime_type;
http_parameter *params;
content_type type;
nserror error;
- bool acceptable;
content_type_header =
llcache_handle_get_header(llcache, "Content-Type");
@@ -558,27 +556,14 @@
if (error != NSERROR_OK)
return false;
- type = content_lookup(mime_type);
+ type = content_factory_type_from_mime_type(mime_type);
free(mime_type);
http_parameter_list_destroy(params);
- if (accepted_types == NULL) {
- acceptable = type != CONTENT_OTHER;
- } else {
- while (*accepted_types != CONTENT_UNKNOWN) {
- if (*accepted_types == type)
- break;
-
- accepted_types++;
- }
-
- acceptable = *accepted_types == type;
- }
-
*computed_type = type;
- return acceptable;
+ return ((accepted_types & type) != 0);
}
/**
@@ -614,7 +599,7 @@
continue;
/* Ensure that quirks mode is acceptable */
- if (content_matches_quirks(entry->content,
+ if (content_matches_quirks(entry->content,
ctx->child.quirks) == false)
continue;
@@ -634,7 +619,7 @@
return NSERROR_NOMEM;
/* Create content using llhandle */
- entry->content = content_create(ctx->llcache,
+ entry->content = content_factory_create_content(ctx->llcache,
ctx->child.charset, ctx->child.quirks);
if (entry->content == NULL) {
free(entry);
Index: content/content_protected.h
===================================================================
--- content/content_protected.h (revision 12276)
+++ content/content_protected.h (working copy)
@@ -26,68 +26,53 @@
#ifndef _NETSURF_CONTENT_CONTENT_PROTECTED_H_
#define _NETSURF_CONTENT_CONTENT_PROTECTED_H_
-/* Irritatingly this must come first, or odd include errors
- * will occur to do with setjmp.h.
- */
-#ifdef WITH_PNG
-#include "image/png.h"
-#endif
-
#include <stdint.h>
#include <time.h>
#include "utils/config.h"
#include "content/content.h"
+#include "content/content_factory.h"
#include "content/llcache.h"
-#include "css/css.h"
-#include "render/html.h"
-#include "render/textplain.h"
-#ifdef WITH_JPEG
-#include "image/jpeg.h"
-#endif
-#ifdef WITH_GIF
-#include "image/gif.h"
-#endif
-#ifdef WITH_BMP
-#include "image/bmp.h"
-#include "image/ico.h"
-#endif
-#ifdef WITH_PLUGIN
-#include "desktop/plugin.h"
-#endif
-#ifdef WITH_MNG
-#include "image/mng.h"
-#endif
-#ifdef WITH_SPRITE
-#include "riscos/sprite.h"
-#endif
-#ifdef WITH_NSSPRITE
-#include "image/nssprite.h"
-#endif
-#ifdef WITH_DRAW
-#include "riscos/draw.h"
-#endif
-#ifdef WITH_ARTWORKS
-#include "riscos/artworks.h"
-#endif
-#ifdef WITH_NS_SVG
-#include "image/svg.h"
-#endif
-#ifdef WITH_RSVG
-#include "image/rsvg.h"
-#endif
-#ifdef WITH_WEBP
-#include "image/webp.h"
-#endif
-#ifdef WITH_AMIGA_ICON
-#include "amiga/icon.h"
-#endif
-#ifdef WITH_APPLE_IMAGE
-#include "cocoa/apple_image.h"
-#endif
+#include "utils/errors.h"
struct bitmap;
struct content;
+struct content_handler {
+ nserror (*create)(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache,
+ const char *fallback_charset, bool quirks,
+ struct content **c);
+
+ bool (*process_data)(struct content *c,
+ const char *data, unsigned int size);
+ bool (*convert)(struct content *c);
+ void (*reformat)(struct content *c, int width, int height);
+ void (*destroy)(struct content *c);
+ void (*stop)(struct content *c);
+ void (*mouse_track)(struct content *c, struct browser_window *bw,
+ browser_mouse_state mouse, int x, int y);
+ void (*mouse_action)(struct content *c, struct browser_window *bw,
+ browser_mouse_state mouse, int x, int y);
+ bool (*redraw)(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+ bool (*redraw_tiled)(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+ void (*open)(struct content *c, struct browser_window *bw,
+ struct content *page,
+ struct box *box,
+ struct object_params *params);
+ void (*close)(struct content *c);
+ nserror (*clone)(const struct content *old, struct content **newc);
+ bool (*matches_quirks)(const struct content *c, bool quirks);
+ content_type (*type)(lwc_string *mime_type);
+ /** There must be one content per user for this type. */
+ bool no_share;
+};
+
/** Linked list of users of a content. */
struct content_user
{
@@ -102,9 +87,10 @@
struct content {
llcache_handle *llcache; /**< Low-level cache object */
- content_type type; /**< Type of content. */
- char *mime_type; /**< Original MIME type of data, or 0. */
+ lwc_string *mime_type; /**< Original MIME type of data */
+ const content_handler *handler; /**< Handler for content */
+
content_status status; /**< Current status. */
int width, height; /**< Dimensions, if applicable. */
@@ -113,59 +99,6 @@
bool quirks; /**< Content is in quirks mode */
char *fallback_charset; /**< Fallback charset, or NULL */
- /** Data dependent on type. */
- union {
- struct content_html_data html;
- struct content_textplain_data textplain;
- struct content_css_data css;
-#ifdef WITH_JPEG
- struct content_jpeg_data jpeg;
-#endif
-#ifdef WITH_GIF
- struct content_gif_data gif;
-#endif
-#ifdef WITH_BMP
- struct content_bmp_data bmp;
- struct content_ico_data ico;
-#endif
-#ifdef WITH_MNG
- struct content_mng_data mng;
-#endif
-#ifdef WITH_SPRITE
- struct content_sprite_data sprite;
-#endif
-#ifdef WITH_NSSPRITE
- struct content_nssprite_data nssprite;
-#endif
-#ifdef WITH_DRAW
- struct content_draw_data draw;
-#endif
-#ifdef WITH_PLUGIN
- struct content_plugin_data plugin;
-#endif
-#ifdef WITH_ARTWORKS
- struct content_artworks_data artworks;
-#endif
-#ifdef WITH_NS_SVG
- struct content_svg_data svg;
-#endif
-#ifdef WITH_RSVG
- struct content_rsvg_data rsvg;
-#endif
-#ifdef WITH_PNG
- struct content_png_data png;
-#endif
-#ifdef WITH_WEBP
- struct content_webp_data webp;
-#endif
-#ifdef WITH_AMIGA_ICON
- struct content_amiga_icon_data amiga_icon;
-#endif
-#ifdef WITH_APPLE_IMAGE
- struct content_apple_image_data apple_image;
-#endif
- } data;
-
/**< URL for refresh request, in standard form as from url_join. */
char *refresh;
@@ -208,6 +141,12 @@
extern const char * const content_type_name[];
extern const char * const content_status_name[];
+nserror content__init(struct content *c, const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ struct llcache_handle *llcache, const char *fallback_charset,
+ bool quirks);
+nserror content__clone(const struct content *c, struct content *nc);
+
void content_set_ready(struct content *c);
void content_set_done(struct content *c);
void content_set_status(struct content *c, const char *status_message, ...);
@@ -220,8 +159,7 @@
bool content__set_title(struct content *c, const char *title);
-content_type content__get_type(struct content *c);
-const char *content__get_mime_type(struct content *c);
+lwc_string *content__get_mime_type(struct content *c);
const char *content__get_url(struct content *c);
const char *content__get_title(struct content *c);
const char *content__get_status_message(struct content *c);
Index: content/hlcache.h
===================================================================
--- content/hlcache.h (revision 12276)
+++ content/hlcache.h (working copy)
@@ -101,7 +101,7 @@
* \param cb Callback to handle object events
* \param pw Pointer to client-specific data for callback
* \param child Child retrieval context, or NULL for top-level content
- * \param accepted_types Array of acceptable content types, or NULL for any
+ * \param accepted_types Bitmap of acceptable content types
* \param result Pointer to location to recieve cache handle
* \return NSERROR_OK on success, appropriate error otherwise
*
@@ -109,8 +109,6 @@
* The quirks field is ignored for child contents whose behaviour is not
* affected by quirks mode.
*
- * The \a accepted_types array must be terminated with CONTENT_UNKNOWN
- *
* \todo The above rules should be encoded in the handler_map.
*
* \todo Is there any way to sensibly reduce the number of parameters here?
@@ -119,7 +117,7 @@
const char *referer, llcache_post_data *post,
hlcache_handle_callback cb, void *pw,
hlcache_child_context *child,
- const content_type *accepted_types, hlcache_handle **result);
+ content_type accepted_types, hlcache_handle **result);
/**
* Release a high-level cache handle
Index: amiga/menu.c
===================================================================
--- amiga/menu.c (revision 12276)
+++ amiga/menu.c (working copy)
@@ -68,7 +68,6 @@
#include "desktop/save_complete.h"
#include "desktop/selection.h"
#include "desktop/textinput.h"
-#include "desktop/plugin.h"
#include "utils/messages.h"
#include "utils/url.h"
@@ -895,14 +894,10 @@
AddPart(fname,ap->ap_Info.fib_FileName,1024);
mt = fetch_mimetype(fname);
- ct = content_lookup(mt);
+ ct = content_factory_type_from_mime_type(mt);
- if(ct != CONTENT_OTHER) ret = TRUE;
+ if(ct != CONTENT_NONE) ret = TRUE;
-#ifdef WITH_PLUGIN
- if(ct == CONTENT_PLUGIN) ret = plugin_handleable(mt);
-#endif
-
free(mt);
return ret;
}
Index: amiga/Makefile.target
===================================================================
--- amiga/Makefile.target (revision 12276)
+++ amiga/Makefile.target (working copy)
@@ -23,7 +23,7 @@
$(eval $(call feature_enabled,NSSVG,-DWITH_NS_SVG,-lsvgtiny,SVG (libsvgtiny)))
$(eval $(call feature_enabled,MNG,,-llcms -ljpeg,PNG/JNG/MNG (libmng)))
$(eval $(call feature_enabled,WEBP,-DWITH_WEBP,-lwebp,WebP (libwebp)))
- $(eval $(call feature_enabled,AMIGA_ICON,-DWITH_AMIGA_ICON,,Amiga icon ))
+ $(eval $(call feature_enabled,AMIGA_ICON,-DWITH_AMIGA_ICON,,Amiga icon))
$(eval $(call feature_enabled,PLUGINS,-DWITH_PLUGIN,,DataTypes images))
CFLAGS += -I /SDK/local/common/include/libpng12
@@ -42,6 +42,8 @@
$(eval $(call pkg_config_find_and_add,GIF,libnsgif,GIF))
$(eval $(call pkg_config_find_and_add,PNG,libpng,PNG))
$(eval $(call pkg_config_find_and_add,NSSVG,libsvgtiny,NSSVG))
+ $(eval $(call feature_enabled,AMIGA_ICON,-DWITH_AMIGA_ICON,,Amiga icon))
+ $(eval $(call feature_enabled,PLUGINS,-DWITH_PLUGIN,,DataTypes images))
CFLAGS += -I$(GCCSDK_INSTALL_ENV)/include
CFLAGS += $(shell $(PKG_CONFIG) --cflags libxml-2.0 libcurl libcares openssl)
Index: amiga/gui.c
===================================================================
--- amiga/gui.c (revision 12276)
+++ amiga/gui.c (working copy)
@@ -50,12 +50,14 @@
#include "amiga/history.h"
#include "amiga/history_local.h"
#include "amiga/hotlist.h"
+#include "amiga/icon.h"
#include "amiga/launch.h"
#include "amiga/login.h"
#include "amiga/menu.h"
#include "amiga/misc.h"
#include "amiga/options.h"
#include "amiga/plotters.h"
+#include "amiga/plugin.h"
#include "amiga/print.h"
#include "amiga/schedule.h"
#include "amiga/search.h"
@@ -750,6 +752,9 @@
netsurf_init(&argc, &argv, "PROGDIR:Resources/Options", messages);
+ amiga_icon_init();
+ amiga_plugin_init();
+
gui_init(argc, argv);
gui_init2(argc, argv);
@@ -765,6 +770,9 @@
netsurf_exit();
+ amiga_plugin_fini();
+ amiga_icon_fini();
+
return 0;
}
@@ -3634,12 +3642,6 @@
if ((icon != NULL) &&
(content_get_status(icon) != CONTENT_STATUS_READY) &&
(content_get_status(icon) != CONTENT_STATUS_DONE)) return;
-#ifdef WITH_BMP
- if ((icon != NULL) && (content_get_type(icon) == CONTENT_ICO))
- {
- nsico_set_bitmap_from_size(icon, 16, 16);
- }
-#endif
if ((icon != NULL) && (content_get_bitmap(icon) != NULL))
{
bm = ami_getcachenativebm(content_get_bitmap(icon), 16, 16,
@@ -3691,12 +3693,6 @@
if(IsMinListEmpty(window_list)) return;
if(option_kiosk_mode == true) return;
if (ico == NULL) ico = search_web_ico();
-#ifdef WITH_BMP
- if ((ico != NULL) && (content_get_type(ico) == CONTENT_ICO))
- {
- nsico_set_bitmap_from_size(ico, 16, 16);
- }
-#endif
if ((ico != NULL) && (content_get_bitmap(ico) != NULL))
{
bm = ami_getcachenativebm(content_get_bitmap(ico), 16, 16, NULL);
Index: amiga/save_complete.c
===================================================================
--- amiga/save_complete.c (revision 12276)
+++ amiga/save_complete.c (working copy)
@@ -40,8 +40,10 @@
*/
bool save_complete_gui_save(const char *path, const char *filename, size_t len,
- const char *sourcedata, content_type type)
+ const char *sourcedata, lwc_string *mime_type)
{
+ content_type type = content_factory_type_from_mime_type(
+ lwc_string_data(mime_type));
int res;
int namelen;
char deftype[5];
Index: amiga/icon.c
===================================================================
--- amiga/icon.c (revision 12276)
+++ amiga/icon.c (working copy)
@@ -44,6 +44,7 @@
#include "content/content_protected.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
#include "utils/url.h"
@@ -52,6 +53,112 @@
#ifdef WITH_AMIGA_ICON
+typedef struct amiga_icon_content {
+ struct content base;
+} amiga_icon_content;
+
+static nserror amiga_icon_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool amiga_icon_convert(struct content *c);
+static void amiga_icon_destroy(struct content *c);
+static bool amiga_icon_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static nserror amiga_icon_clone(const struct content *old,
+ struct content **newc);
+static content_type amiga_icon_content_type(lwc_string *mime_type);
+
+static const content_handler amiga_icon_content_handler = {
+ amiga_icon_create,
+ NULL,
+ amiga_icon_convert,
+ NULL,
+ amiga_icon_destroy,
+ NULL,
+ NULL,
+ NULL,
+ amiga_icon_redraw,
+ NULL,
+ NULL,
+ NULL,
+ amiga_icon_clone,
+ NULL,
+ amiga_icon_content_type,
+ false
+};
+
+static const char *amiga_icon_types[] = {
+ "image/x-amiga_icon"
+};
+
+static lwc_string *amiga_icon_mime_types[NOF_ELEMENTS(amiga_icon_types)];
+
+nserror amiga_icon_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(amiga_icon_mime_types); i++) {
+ lerror = lwc_intern_string(amiga_icon_types[i],
+ strlen(amiga_icon_types[i]),
+ &amiga_icon_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(
+ amiga_icon_mime_types[i],
+ &amiga_icon_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ amiga_icon_fini();
+
+ return error;
+}
+
+void amiga_icon_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(amiga_icon_mime_types); i++) {
+ if (amiga_icon_mime_types[i] != NULL)
+ lwc_string_unref(amiga_icon_mime_types[i]);
+ }
+}
+
+nserror amiga_icon_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ amiga_icon_content *ai;
+ nserror error;
+
+ ai = talloc_zero(0, amiga_icon_content);
+ if (ai == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&ai->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(ai);
+ return error;
+ }
+
+ *c = (struct content *) ai;
+
+ return NSERROR_OK;
+}
+
/**
* Convert a CONTENT_AMIGA_ICON for display.
*
@@ -70,7 +177,7 @@
int err = 0;
uint8 r, g, b, a;
ULONG offset;
- char *url;
+ const char *url;
char *filename;
char *p;
ULONG trans, pals1;
@@ -119,7 +226,7 @@
if(dobj) FreeDiskObject(dobj);
return false;
}
- imagebuf = bitmap_get_buffer(c->bitmap);
+ imagebuf = (ULONG *) bitmap_get_buffer(c->bitmap);
if (!imagebuf) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
@@ -138,7 +245,7 @@
ICONCTRLA_GetPaletteSize1, &pals1,
TAG_DONE);
- imagebufptr = amiga_icon_convertcolouricon32((UBYTE *)imagebufptr,
+ imagebufptr = (unsigned char *) amiga_icon_convertcolouricon32((UBYTE *)imagebufptr,
width, height, trans, pals1, pal1, 0xff);
}
@@ -197,18 +304,40 @@
}
-bool amiga_icon_clone(const struct content *old, struct content *new_content)
+nserror amiga_icon_clone(const struct content *old, struct content **newc)
{
+ amiga_icon_content *ai;
+ nserror error;
+
+ ai = talloc_zero(0, amiga_icon_content);
+ if (ai == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &ai->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&ai->base);
+ return error;
+ }
+
/* Simply replay convert */
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (amiga_icon_convert(new_content) == false)
- return false;
+ if (amiga_icon_convert(&ai->base) == false) {
+ content_destroy(&ai->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) ai;
+
+ return NSERROR_OK;
}
+content_type amiga_icon_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
+
#endif /* WITH_AMIGA_ICON */
ULONG *amiga_icon_convertcolouricon32(UBYTE *icondata, ULONG width, ULONG height,
@@ -317,12 +446,6 @@
if((format == IDFMT_DIRECTMAPPED) || (format == IDFMT_PALETTEMAPPED))
{
-#ifdef WITH_BMP
- if ((icon != NULL) && (content_get_type(icon) == CONTENT_ICO))
- {
- nsico_set_bitmap_from_size(icon, 16, 16);
- }
-#endif
if ((icon != NULL) && (content_get_bitmap(icon) != NULL))
{
bm = ami_getcachenativebm(content_get_bitmap(icon), 16, 16, NULL);
Index: amiga/icon.h
===================================================================
--- amiga/icon.h (revision 12276)
+++ amiga/icon.h (working copy)
@@ -24,24 +24,18 @@
#define AMIGA_ICON_H
#include "utils/config.h"
+#include "utils/errors.h"
+
#ifdef WITH_AMIGA_ICON
-#include <stdbool.h>
-#include "content/hlcache.h"
+nserror amiga_icon_init(void);
+void amiga_icon_fini(void);
-struct rect;
+#else
-struct content_amiga_icon_data {
-/* empty */
-};
+#define amiga_icon_init() NSERROR_OK
+#define amiga_icon_fini() ((void) 0)
-bool amiga_icon_convert(struct content *c);
-void amiga_icon_destroy(struct content *c);
-bool amiga_icon_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool amiga_icon_clone(const struct content *old, struct content *new_content);
-
#endif /* WITH_AMIGA_ICON */
struct hlcache_handle;
Index: amiga/plugin.c
===================================================================
--- amiga/plugin.c (revision 12276)
+++ amiga/plugin.c (working copy)
@@ -26,25 +26,135 @@
#include "amiga/plugin.h"
#include "content/content_protected.h"
#include "desktop/plotters.h"
+#include "image/bitmap.h"
#include "render/box.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include <proto/datatypes.h>
#include <proto/intuition.h>
#include <datatypes/pictureclass.h>
+#include <intuition/classusr.h>
-bool plugin_create(struct content *c, const struct http_parameter *params)
+typedef struct plugin_content {
+ struct content base;
+
+ Object *dto;
+ int x;
+ int y;
+ int w;
+ int h;
+} plugin_content;
+
+static nserror plugin_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool plugin_convert(struct content *c);
+static void plugin_reformat(struct content *c, int width, int height);
+static void plugin_destroy(struct content *c);
+static bool plugin_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static void plugin_open(struct content *c, struct browser_window *bw,
+ struct content *page, struct box *box,
+ struct object_params *params);
+static void plugin_close(struct content *c);
+static nserror plugin_clone(const struct content *old, struct content **newc);
+static content_type plugin_content_type(lwc_string *mime_type);
+
+static const content_handler plugin_content_handler = {
+ plugin_create,
+ NULL,
+ plugin_convert,
+ plugin_reformat,
+ plugin_destroy,
+ NULL,
+ NULL,
+ NULL,
+ plugin_redraw,
+ NULL,
+ plugin_open,
+ plugin_close,
+ plugin_clone,
+ NULL,
+ plugin_content_type,
+ false
+};
+
+nserror plugin_init(void)
{
- LOG(("plugin_create"));
+ char dt_mime[50];
+ struct DataType *dt, *prevdt = NULL;
+ lwc_string *type;
+ lwc_error lerror;
+ nserror error;
- return true;
+ while((dt = ObtainDataType(DTST_RAM, NULL,
+ DTA_DataType, prevdt,
+ DTA_GroupID, GID_PICTURE, // we only support images for now
+ TAG_DONE)) != NULL)
+ {
+ ReleaseDataType(prevdt);
+ prevdt = dt;
+ ami_datatype_to_mimetype(dt, dt_mime);
+
+ LOG(("Guessed MIME from DT: %s", dt_mime));
+
+ lerror = lwc_intern_string(dt_mime, strlen(dt_mime), &type);
+ if (lerror != lwc_error_ok)
+ return NSERROR_NOMEM;
+
+ error = content_factory_register_handler(type,
+ &plugin_content_handler);
+
+ lwc_string_unref(type);
+
+ if (error != NSERROR_OK)
+ return error;
+
+ }
+
+ ReleaseDataType(prevdt);
+
+ return NSERROR_OK;
}
+void plugin_fini(void)
+{
+ /* Nothing to do */
+}
+
+nserror plugin_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ plugin_content *plugin;
+ nserror error;
+
+ plugin = talloc_zero(0, plugin_content);
+ if (plugin == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&plugin->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(plugin);
+ return error;
+ }
+
+ *c = (struct content *) plugin;
+
+ return NSERROR_OK;
+}
+
bool plugin_convert(struct content *c)
{
LOG(("plugin_convert"));
+ plugin_content *plugin = (plugin_content *) c;
union content_msg_data msg_data;
int width, height;
char title[100];
@@ -60,7 +170,7 @@
data = (uint8 *)content__get_source_data(c, &size);
- if(c->data.plugin.dto = NewDTObject(NULL,
+ if(plugin->dto = NewDTObject(NULL,
DTA_SourceType, DTST_MEMORY,
DTA_SourceAddress, data,
DTA_SourceSize, size,
@@ -68,7 +178,7 @@
PDTA_DestMode, PMODE_V43,
TAG_DONE))
{
- if(GetDTAttrs(c->data.plugin.dto, PDTA_BitMapHeader, &bmh, TAG_DONE))
+ if(GetDTAttrs(plugin->dto, PDTA_BitMapHeader, &bmh, TAG_DONE))
{
width = (int)bmh->bmh_Width;
height = (int)bmh->bmh_Height;
@@ -82,7 +192,7 @@
bm_buffer = bitmap_get_buffer(c->bitmap);
- IDoMethod(c->data.plugin.dto, PDTM_READPIXELARRAY,
+ IDoMethod(plugin->dto, PDTM_READPIXELARRAY,
bm_buffer, bm_format, bitmap_get_rowstride(c->bitmap),
0, 0, width, height);
}
@@ -110,12 +220,14 @@
void plugin_destroy(struct content *c)
{
+ plugin_content *plugin = (plugin_content *) c;
+
LOG(("plugin_destroy"));
if (c->bitmap != NULL)
bitmap_destroy(c->bitmap);
- DisposeDTObject(c->data.plugin.dto);
+ DisposeDTObject(plugin->dto);
return;
}
@@ -161,57 +273,40 @@
return;
}
-bool plugin_clone(const struct content *old, struct content *new_content)
+nserror plugin_clone(const struct content *old, struct content **newc)
{
+ plugin_content *plugin;
+ nserror error;
+
LOG(("plugin_clone"));
- /* We "clone" the old content by replaying creation and conversion */
- if (plugin_create(new_content, NULL) == false)
- return false;
+ plugin = talloc_zero(0, plugin_content);
+ if (plugin == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &plugin->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&plugin->base);
+ return error;
+ }
+
+ /* We "clone" the old content by replaying conversion */
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (plugin_convert(new_content) == false)
- return false;
+ if (plugin_convert(&plugin->base) == false) {
+ content_destroy(&plugin->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) plugin;
+
+ return NSERROR_OK;
}
-/**
- * Determines whether a content is handleable by a plugin
- *
- * \param mime_type The mime type of the content
- * \return true if the content is handleable, false otherwise
- */
-bool plugin_handleable(const char *mime_type)
+content_type plugin_content_type(lwc_string *mime_type)
{
- LOG(("plugin_handleable %s", mime_type));
-
- char dt_mime[50];
- struct DataType *dt, *prevdt = NULL;
- bool found = false;
-
- while((dt = ObtainDataType(DTST_RAM, NULL,
- DTA_DataType, prevdt,
- DTA_GroupID, GID_PICTURE, // we only support images for now
- TAG_DONE)) != NULL)
- {
- ReleaseDataType(prevdt);
- prevdt = dt;
- ami_datatype_to_mimetype(dt, &dt_mime);
-
- LOG(("Guessed MIME from DT: %s", dt_mime));
-
- if(strcmp(dt_mime, mime_type) == 0)
- {
- found = true;
- break;
- }
- }
-
- ReleaseDataType(prevdt);
-
- return found;
+ return CONTENT_PLUGIN;
}
#endif
Index: amiga/plugin.h
===================================================================
--- amiga/plugin.h (revision 12276)
+++ amiga/plugin.h (working copy)
@@ -19,19 +19,19 @@
#ifndef NETSURF_AMIGA_PLUGIN_H_
#define NETSURF_AMIGA_PLUGIN_H_
+#include "utils/config.h"
+#include "utils/errors.h"
+
#ifdef WITH_PLUGIN
-#include <intuition/classusr.h>
+nserror plugin_init(void);
+void plugin_fini(void);
-#include "desktop/plugin.h"
+#else
-struct content_plugin_data {
- Object *dto;
- int x;
- int y;
- int w;
- int h;
-};
+#define plugin_init() NSERROR_OK
+#define plugin_fini() ((void) 0)
#endif /* WITH_PLUGIN */
+
#endif
Index: amiga/filetype.c
===================================================================
--- amiga/filetype.c (revision 12276)
+++ amiga/filetype.c (working copy)
@@ -140,54 +140,6 @@
return "css";
break;
-#ifdef WITH_JPEG
- case CONTENT_JPEG:
- return "jpeg";
- break;
-#endif
-#ifdef WITH_GIF
- case CONTENT_GIF:
- return "gif";
- break;
-#endif
-#ifdef WITH_BMP
- case CONTENT_BMP:
- return "bmp";
- break;
-
- case CONTENT_ICO:
- return "ico";
- break;
-#endif
-#if defined(WITH_MNG) || defined(WITH_PNG)
- case CONTENT_PNG:
- return "png";
- break;
-#endif
-#ifdef WITH_MNG
- case CONTENT_JNG:
- return "jng";
- break;
-
- case CONTENT_MNG:
- return "mng";
- break;
-#endif
-#if defined(WITH_SPRITE) || defined(WITH_NSSPRITE)
- case CONTENT_SPRITE:
- return "rosprite";
- break;
-#endif
-#if defined(WITH_NS_SVG) || defined(WITH_RSVG)
- case CONTENT_SVG:
- return "svg";
- break;
-#endif
-#ifdef WITH_WEBP
- case CONTENT_WEBP:
- return "webp";
- break;
-#endif
default:
return "project";
break;
Conflicted files
Removed files
render/favicon.c
render/favicon.h
desktop/plugin.h
11 years, 9 months
[PATCH][RFC] Gopher support
by François Revol
I cleaned up the gopher support I wrote.
Still needs some more work but it's usable.
Comments ?
François.
11 years, 9 months