From e71691bae890040b83cfd54a2d9a1097d5026866 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Fri, 6 May 2011 20:40:09 +0000 Subject: Merge branches/jmb/content-factory to trunk svn path=/trunk/netsurf/; revision=12283 --- Makefile.defaults | 4 +- Makefile.sources | 9 +- amiga/Makefile.target | 4 +- amiga/clipboard.c | 2 +- amiga/context_menu.c | 4 +- amiga/drag.c | 4 +- amiga/filetype.c | 64 +--- amiga/filetype.h | 4 + amiga/gui.c | 21 +- amiga/icon.c | 149 +++++++- amiga/icon.h | 20 +- amiga/menu.c | 15 +- amiga/plugin.c | 191 +++++++--- amiga/plugin.h | 18 +- amiga/save_complete.c | 4 +- atari/gui.c | 2 +- atari/treeview.c | 30 +- beos/beos_save_complete.cpp | 2 +- beos/beos_treeview.cpp | 30 +- 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_factory.c | 195 +++++++++++ content/content_factory.h | 42 +++ 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/plugin.h | 59 ---- 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 | 28 +- image/ico.c | 222 +++++++++--- image/ico.h | 31 +- image/image.c | 100 ++++++ image/image.h | 31 ++ image/jpeg.c | 142 +++++++- image/jpeg.h | 27 +- image/mng.c | 430 +++++++++++++++++------ image/mng.h | 33 +- image/nssprite.c | 149 +++++++- image/nssprite.h | 20 +- image/png.c | 287 ++++++++++++---- image/png.h | 40 +-- image/rsvg.c | 189 ++++++++-- image/rsvg.h | 34 +- image/svg.c | 188 ++++++++-- image/svg.h | 33 +- image/webp.c | 136 +++++++- image/webp.h | 22 +- monkey/utils.c | 2 +- render/box.c | 16 +- render/box.h | 6 +- render/box_construct.c | 189 ++++------ render/box_normalise.c | 73 +++- render/favicon.c | 275 --------------- render/favicon.h | 28 -- render/form.c | 1 - render/html.c | 822 +++++++++++++++++++++++--------------------- render/html.h | 105 +----- render/html_interaction.c | 2 +- render/html_internal.h | 112 ++++++ 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 | 444 ++++++++++++++---------- riscos/plugin.h | 20 -- riscos/print.c | 15 +- riscos/save.c | 121 ++----- riscos/sprite.c | 148 +++++++- riscos/sprite.h | 25 +- riscos/treeview.c | 30 +- riscos/window.c | 56 +-- utils/errors.h | 5 +- windows/gui.c | 2 +- windows/tree.c | 30 +- 110 files changed, 5158 insertions(+), 3532 deletions(-) create mode 100644 content/content_factory.c create mode 100644 content/content_factory.h delete mode 100644 desktop/plugin.h create mode 100644 image/image.c create mode 100644 image/image.h delete mode 100644 render/favicon.c delete mode 100644 render/favicon.h create mode 100644 render/html_internal.h diff --git a/Makefile.defaults b/Makefile.defaults index adcc2f799..ee7b21d95 100644 --- a/Makefile.defaults +++ b/Makefile.defaults @@ -235,13 +235,13 @@ ifeq ($(TARGET),amiga) # Enable NetSurf's use of libsvgtiny for displaying SVGs # (NB: Requires NETSURF_AMIGA_USE_CAIRO) # Valid options: YES, NO - NETSURF_USE_NSSVG := NO + NETSURF_USE_NSSVG := YES # Enable NetSurf's use of libcairo for some plotter functions # This will also link NetSurf with shared objects, and # requires AmigaOS 4.1 or higher to run the resulting executable # Valid options: YES, NO - NETSURF_AMIGA_USE_CAIRO := NO + NETSURF_AMIGA_USE_CAIRO := YES # Optimisation levels CFLAGS += -O2 -Wuninitialized diff --git a/Makefile.sources b/Makefile.sources index ef4d83c23..a221b7002 100644 --- a/Makefile.sources +++ b/Makefile.sources @@ -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 @@ S_COMMON := $(addprefix content/,$(S_CONTENT)) \ $(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 diff --git a/amiga/Makefile.target b/amiga/Makefile.target index 551d12cf9..00b700551 100644 --- a/amiga/Makefile.target +++ b/amiga/Makefile.target @@ -23,7 +23,7 @@ ifeq ($(HOST),amiga) $(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 @@ else $(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) diff --git a/amiga/clipboard.c b/amiga/clipboard.c index ee9e692f5..0d1ba74ad 100755 --- a/amiga/clipboard.c +++ b/amiga/clipboard.c @@ -421,7 +421,7 @@ bool ami_easy_clipboard_svg(struct hlcache_handle *c) char *source_data; ULONG source_size; - if(content_get_type(c) != CONTENT_SVG) return false; + if(ami_mime_compare(c, "svg") == false) return false; if((source_data = content_get_source_data(c, &source_size)) == NULL) return false; if(!(OpenIFF(iffh,IFFF_WRITE))) diff --git a/amiga/context_menu.c b/amiga/context_menu.c index 81f81361e..12fed3160 100755 --- a/amiga/context_menu.c +++ b/amiga/context_menu.c @@ -469,7 +469,7 @@ static uint32 ami_context_menu_hook(struct Hook *hook,Object *item,APTR reserved ami_easy_clipboard_bitmap(bm); } #ifdef WITH_NS_SVG - else if(content_get_type(object) == CONTENT_SVG) + else if(ami_mime_compare(object, "svg") == true) { ami_easy_clipboard_svg(object); } @@ -529,7 +529,7 @@ static uint32 ami_context_menu_hook(struct Hook *hook,Object *item,APTR reserved SetComment(fname, content_get_url(object)); } #ifdef WITH_NS_SVG - else if(content_get_type(object) == CONTENT_SVG) + else if(ami_mime_compare(object, "svg") == true) { if(ami_save_svg(object,fname)) SetComment(fname, content_get_url(object)); diff --git a/amiga/drag.c b/amiga/drag.c index 37e0acd24..8f5625bcf 100644 --- a/amiga/drag.c +++ b/amiga/drag.c @@ -73,7 +73,7 @@ void gui_drag_save_object(gui_save_type type, hlcache_handle *c, break; case GUI_SAVE_OBJECT_NATIVE: #ifdef WITH_NS_SVG - if(content_get_type(c) == CONTENT_SVG) + if(ami_mime_compare(c, "svg") == true) { filetype = "dr2d"; } @@ -211,7 +211,7 @@ void ami_drag_save(struct Window *win) SetComment(path, content_get_url(c)); } #ifdef WITH_NS_SVG - else if(content_get_type(c) == CONTENT_SVG) + else if(ami_mime_compare(c, "svg") == true) { if(ami_save_svg(c, path)) SetComment(path, content_get_url(c)); diff --git a/amiga/filetype.c b/amiga/filetype.c index 61fe4a5c9..9d4414a13 100644 --- a/amiga/filetype.c +++ b/amiga/filetype.c @@ -20,7 +20,7 @@ #include #include "amiga/filetype.h" #include "content/fetch.h" -#include "content/content_type.h" +#include "content/content.h" #include "utils/log.h" #include "utils/utils.h" #include @@ -140,54 +140,6 @@ const char *ami_content_type_to_file_type(content_type type) 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; @@ -245,3 +197,17 @@ void ami_datatype_to_mimetype(struct DataType *dtn, char *mimetype) break; } } + +bool ami_mime_compare(struct hlcache_handle *c, const char *type) +{ + lwc_string *mime = content_get_mime_type(c); + const char *mime_string = lwc_string_data(mime); + size_t mime_length = lwc_string_length(mime); + + if(!strncmp("svg", type, 3)) + { + if(!strncmp(mime_string, "image/svg", mime_length)) return true; + if(!strncmp(mime_string, "image/svg+xml", mime_length)) return true; + } + else return false; +} diff --git a/amiga/filetype.h b/amiga/filetype.h index b7a1a54a9..a09a79a52 100644 --- a/amiga/filetype.h +++ b/amiga/filetype.h @@ -18,9 +18,13 @@ #ifndef AMIGA_FILETYPE_H #define AMIGA_FILETYPE_H +#include #include "content/content_type.h" #include +struct hlcache_handle; + const char *ami_content_type_to_file_type(content_type type); void ami_datatype_to_mimetype(struct DataType *dtn, char *mimetype); +bool ami_mime_compare(struct hlcache_handle *c, const char *type); #endif diff --git a/amiga/gui.c b/amiga/gui.c index 880901b9d..d3f05e576 100755 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -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" @@ -748,8 +750,12 @@ int main(int argc, char** argv) ami_schedule_open_timer(); ami_schedule_create(); + plugin_init(); + netsurf_init(&argc, &argv, "PROGDIR:Resources/Options", messages); + amiga_icon_init(); + gui_init(argc, argv); gui_init2(argc, argv); @@ -765,6 +771,9 @@ int main(int argc, char** argv) netsurf_exit(); + plugin_fini(); + amiga_icon_fini(); + return 0; } @@ -3634,12 +3643,6 @@ void gui_window_set_icon(struct gui_window *g, hlcache_handle *icon) 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 +3694,6 @@ void gui_window_set_search_ico(hlcache_handle *ico) 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); diff --git a/amiga/icon.c b/amiga/icon.c index 86d01bcd7..07dac8c0e 100644 --- a/amiga/icon.c +++ b/amiga/icon.c @@ -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 @@ ULONG *amiga_icon_convertcolouricon32(UBYTE *icondata, ULONG width, ULONG height #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 @@ bool amiga_icon_convert(struct content *c) 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 @@ bool amiga_icon_convert(struct content *c) 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 @@ bool amiga_icon_convert(struct content *c) 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,16 +304,38 @@ bool amiga_icon_redraw(struct content *c, int x, int y, } -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 */ @@ -317,12 +446,6 @@ void ami_superimpose_favicon(char *path, struct hlcache_handle *icon, char *type 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); diff --git a/amiga/icon.h b/amiga/icon.h index bd9fb501d..646c50653 100644 --- a/amiga/icon.h +++ b/amiga/icon.h @@ -24,23 +24,17 @@ #define AMIGA_ICON_H #include "utils/config.h" -#ifdef WITH_AMIGA_ICON +#include "utils/errors.h" -#include -#include "content/hlcache.h" +#ifdef WITH_AMIGA_ICON -struct rect; +nserror amiga_icon_init(void); +void amiga_icon_fini(void); -struct content_amiga_icon_data { -/* empty */ -}; +#else -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); +#define amiga_icon_init() NSERROR_OK +#define amiga_icon_fini() ((void) 0) #endif /* WITH_AMIGA_ICON */ diff --git a/amiga/menu.c b/amiga/menu.c index c39eb94bc..06820479b 100755 --- a/amiga/menu.c +++ b/amiga/menu.c @@ -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" @@ -635,7 +634,7 @@ void ami_menupick(ULONG code,struct gui_window_2 *gwin,struct MenuItem *item) SetComment(fname, content_get_url(gwin->bw->current_content)); } #ifdef WITH_NS_SVG - else if(content_get_type(gwin->bw->current_content) == CONTENT_SVG) + else if(ami_mime_compare(gwin->bw->current_content, "svg") == true) { if(ami_save_svg(gwin->bw->current_content,fname)) SetComment(fname, content_get_url(gwin->bw->current_content)); @@ -727,7 +726,7 @@ void ami_menupick(ULONG code,struct gui_window_2 *gwin,struct MenuItem *item) ami_easy_clipboard_bitmap(bm); } #ifdef WITH_NS_SVG - else if(content_get_type(gwin->bw->current_content) == CONTENT_SVG) + else if(ami_mime_compare(gwin->bw->current_content, "svg") == true) { ami_easy_clipboard_svg(gwin->bw->current_content); } @@ -895,13 +894,9 @@ static const ULONG ami_asl_mime_hook(struct Hook *mh,struct FileRequester *fr,st 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; - -#ifdef WITH_PLUGIN - if(ct == CONTENT_PLUGIN) ret = plugin_handleable(mt); -#endif + if(ct != CONTENT_NONE) ret = TRUE; free(mt); return ret; @@ -952,7 +947,7 @@ void ami_menu_update_disabled(struct gui_window *g, hlcache_handle *c) OffMenu(win,AMI_MENU_FIND); #ifdef WITH_NS_SVG - if(content_get_bitmap(c) || content_get_type(c) == CONTENT_SVG) + if(content_get_bitmap(c) || (ami_mime_compare(c, "svg") == true)) #else if(content_get_bitmap(c)) #endif diff --git a/amiga/plugin.c b/amiga/plugin.c index e21a7c2fc..e68930283 100644 --- a/amiga/plugin.c +++ b/amiga/plugin.c @@ -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 #include #include +#include -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 @@ bool plugin_convert(struct content *c) 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 @@ bool plugin_convert(struct content *c) 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 @@ bool plugin_convert(struct content *c) 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 @@ bool plugin_convert(struct content *c) 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 @@ void plugin_reformat(struct content *c, int width, int height) 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_IMAGE; } #endif diff --git a/amiga/plugin.h b/amiga/plugin.h index 669c5af5a..605d989d4 100644 --- a/amiga/plugin.h +++ b/amiga/plugin.h @@ -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 +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 diff --git a/amiga/save_complete.c b/amiga/save_complete.c index a1059b29a..592781ef8 100755 --- a/amiga/save_complete.c +++ b/amiga/save_complete.c @@ -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]; diff --git a/atari/gui.c b/atari/gui.c index 75664e5c1..1679a2226 100755 --- a/atari/gui.c +++ b/atari/gui.c @@ -637,7 +637,7 @@ save_complete_gui_save(const char *path, const char *filename, size_t len, const char *sourcedata, - content_type type) + lwc_string *mime_type) { TODO(); LOG(("%s", filename)); diff --git a/atari/treeview.c b/atari/treeview.c index b24e9aecb..9f1ddb65c 100755 --- a/atari/treeview.c +++ b/atari/treeview.c @@ -468,35 +468,7 @@ void tree_icon_name_from_content_type(char *buffer, content_type type) 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: strcpy( buffer, "content.png" ); break; diff --git a/beos/beos_save_complete.cpp b/beos/beos_save_complete.cpp index c922cd72f..19306dc21 100644 --- a/beos/beos_save_complete.cpp +++ b/beos/beos_save_complete.cpp @@ -39,7 +39,7 @@ extern "C" { */ 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; diff --git a/beos/beos_treeview.cpp b/beos/beos_treeview.cpp index 6763c25b8..4728995ad 100644 --- a/beos/beos_treeview.cpp +++ b/beos/beos_treeview.cpp @@ -48,35 +48,7 @@ void tree_icon_name_from_content_type(char *buffer, content_type type) 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; diff --git a/cocoa/NetsurfApp.m b/cocoa/NetsurfApp.m index 8897eb4b4..631d56b6c 100644 --- a/cocoa/NetsurfApp.m +++ b/cocoa/NetsurfApp.m @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +#import "cocoa/apple_image.h" #import "cocoa/NetsurfApp.h" #import "cocoa/gui.h" #import "cocoa/plotter.h" @@ -178,6 +179,8 @@ int main( int argc, char **argv ) 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 @@ int main( int argc, char **argv ) [app run]; netsurf_exit(); + + apple_image_fini(); return 0; } diff --git a/cocoa/apple_image.h b/cocoa/apple_image.h index 1611cf52a..5d329c1c5 100644 --- a/cocoa/apple_image.h +++ b/cocoa/apple_image.h @@ -20,34 +20,18 @@ #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" - -struct bitmap; -struct content; -struct rect; +#include "utils/errors.h" -struct content_apple_image_data { -}; +#ifdef WITH_APPLE_IMAGE -bool apple_image_convert(struct content *c); -void apple_image_destroy(struct content *c); +nserror apple_image_init(void); +void apple_image_fini(void); -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); +#else -bool apple_image_clone(const struct content *old, struct content *new_content); +#define apple_image_init() NSERROR_OK +#define apple_image_fini() ((void) 0) #endif /* WITH_APPLE_IMAGE */ diff --git a/cocoa/apple_image.m b/cocoa/apple_image.m index cdf3e537b..ab971667d 100644 --- a/cocoa/apple_image.m +++ b/cocoa/apple_image.m @@ -24,6 +24,119 @@ #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 @@ void apple_image_destroy(struct content *c) } -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. diff --git a/cocoa/gui.m b/cocoa/gui.m index f3a0b04a2..0ffc44543 100644 --- a/cocoa/gui.m +++ b/cocoa/gui.m @@ -258,11 +258,6 @@ void gui_window_stop_throbber(struct gui_window *g) 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; diff --git a/cocoa/save.m b/cocoa/save.m index a91a29810..9ee2f4cd8 100644 --- a/cocoa/save.m +++ b/cocoa/save.m @@ -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; diff --git a/content/content.c b/content/content.c index 95e5e049c..dd5c01ae7 100644 --- a/content/content.c +++ b/content/content.c @@ -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 @@ const char * const content_status_name[] = { "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 @@ static void content_update_status(struct content *c); /** - * Convert a MIME type to a content_type. + * Initialise a new content structure. * - * The returned ::content_type will always be suitable for content_create(). - */ - -content_type content_lookup(const char *mime_type) -{ - 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 + * \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 */ -struct content * content_create(llcache_handle *llcache, - const char *fallback_charset, bool quirks) +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 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; - } - - 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; + return NSERROR_NOMEM; } - /* 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 @@ struct content * content_create(llcache_handle *llcache, 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 @@ nserror content_llcache_callback(llcache_handle *llcache, /* 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 @@ bool content_can_reformat(hlcache_handle *h) if (c == NULL) return false; - return (handler_map[c->type].reformat != NULL); + return (c->handler->reformat != NULL); } @@ -687,7 +272,6 @@ void content_update_status(struct content *c) 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 @@ void content_convert(struct content *c) 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 @@ void content__reformat(struct content *c, int width, int height) 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 @@ void content_destroy(struct content *c) 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 @@ void content_mouse_track(hlcache_handle *h, struct browser_window *bw, 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 @@ void content_mouse_action(hlcache_handle *h, struct browser_window *bw, 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 @@ bool content_redraw(hlcache_handle *h, int x, int y, 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 @@ bool content_redraw_tiled(hlcache_handle *h, int x, int y, 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 @@ bool content_redraw_tiled(hlcache_handle *h, int x, int y, /* 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 @@ uint32_t content_count_users(struct content *c) */ 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_matches_quirks(struct content *c, bool quirks) */ 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 @@ void content_open(hlcache_handle *h, struct browser_window *bw, { 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 @@ void content_close(hlcache_handle *h) { 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 @@ bool content__set_title(struct content *c, const char *title) } /** - * 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 @@ const llcache_handle *content_get_llcache_handle(struct content *c) */ struct content *content_clone(struct content *c) { - struct content *nc = talloc_zero(0, struct content); + struct content *nc; + nserror error; - if (nc == NULL) { - return NULL; - } - - if (llcache_handle_clone(c->llcache, &(nc->llcache)) != NSERROR_OK) { - content_destroy(nc); + 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; } 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 @@ struct content *content_clone(struct content *c) 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 @@ struct content *content_clone(struct content *c) 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 @@ struct content *content_clone(struct content *c) 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 @@ nserror content_abort(struct content *c) 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 */ diff --git a/content/content.h b/content/content.h index 0bb40779f..b3e0b1ce2 100644 --- a/content/content.h +++ b/content/content.h @@ -28,8 +28,12 @@ #include +#include + #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 @@ union content_msg_data { 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 @@ void content_close(struct hlcache_handle *h); /* 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); diff --git a/content/content_factory.c b/content/content_factory.c new file mode 100644 index 000000000..95e7679ad --- /dev/null +++ b/content/content_factory.c @@ -0,0 +1,195 @@ +/* + * Copyright 2011 John-Mark Bell + * + * 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 . + */ + +/** \file + * Content factory (implementation) + */ + +#include +#include +#include + +#include "content/content.h" +#include "content/content_factory.h" +#include "content/content_protected.h" +#include "content/llcache.h" + +/** + * Entry in list of content handlers + */ +typedef struct content_handler_entry { + /** Next entry */ + struct content_handler_entry *next; + + /** MIME type handled by handler */ + lwc_string *mime_type; + /** Content handler object */ + const content_handler *handler; +} content_handler_entry; + +static content_handler_entry *content_handlers; + +/** + * Register a handler with the content factory + * + * \param mime_type MIME type to handle + * \param handler Content handler for MIME type + * \return NSERROR_OK on success, appropriate error otherwise + * + * \note Latest registration for a MIME type wins + */ +nserror content_factory_register_handler(lwc_string *mime_type, + const content_handler *handler) +{ + content_handler_entry *entry; + bool match; + + for (entry = content_handlers; entry != NULL; entry = entry->next) { + if (lwc_string_caseless_isequal(mime_type, entry->mime_type, + &match) == lwc_error_ok && match) + break; + } + + if (entry == NULL) { + entry = malloc(sizeof(content_handler_entry)); + if (entry == NULL) + return NSERROR_NOMEM; + + entry->next = content_handlers; + content_handlers = entry; + + entry->mime_type = lwc_string_ref(mime_type); + } + + entry->handler = handler; + + return NSERROR_OK; +} + +/** + * Find a handler for a MIME type. + * + * \param mime_type MIME type to search for + * \return Associated handler, or NULL if none + */ +static const content_handler *content_lookup(lwc_string *mime_type) +{ + content_handler_entry *entry; + bool match; + + for (entry = content_handlers; entry != NULL; entry = entry->next) { + if (lwc_string_caseless_isequal(mime_type, entry->mime_type, + &match) == lwc_error_ok && match) + break; + } + + if (entry != NULL) + return entry->handler; + + return NULL; +} + +/** + * Compute the generic content type for a MIME type + * + * \param mime_type MIME type to consider + * \return Generic content type + */ +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 = CONTENT_NONE; + + 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) { + type = handler->type(imime_type); + } + + lwc_string_unref(imime_type); + + return type; +} + +/** + * Create a content object + * + * \param llcache Underlying source data handle + * \param fallback_charset Character set to fall back to if none specified + * \param quirks Quirkiness of containing document + * \return Pointer to content object, or NULL on failure + */ +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; +} + diff --git a/content/content_factory.h b/content/content_factory.h new file mode 100644 index 000000000..330ce6812 --- /dev/null +++ b/content/content_factory.h @@ -0,0 +1,42 @@ +/* + * Copyright 2011 John-Mark Bell + * + * 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 . + */ + +#ifndef NETSURF_CONTENT_CONTENT_FACTORY_H_ +#define NETSURF_CONTENT_CONTENT_FACTORY_H_ + +#include + +#include + +#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 diff --git a/content/content_protected.h b/content/content_protected.h index a37d96c42..1d88de972 100644 --- a/content/content_protected.h +++ b/content/content_protected.h @@ -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 #include #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,8 +87,9 @@ struct content_user 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. */ @@ -113,59 +99,6 @@ struct content { 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 @@ struct content { 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 @@ void content__reformat(struct content *c, int width, int height); 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); diff --git a/content/content_type.h b/content/content_type.h index 0b086a599..8e24e4e8e 100644 --- a/content/content_type.h +++ b/content/content_type.h @@ -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; diff --git a/content/hlcache.c b/content/hlcache.c index a53db5d9f..b684ed01c 100644 --- a/content/hlcache.c +++ b/content/hlcache.c @@ -48,7 +48,7 @@ struct hlcache_retrieval_ctx { 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 void hlcache_clean(void *ignored); 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 @@ void hlcache_finalise(void) 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 @@ nserror hlcache_handle_retrieve(const char *url, uint32_t flags, 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 @@ nserror hlcache_llcache_callback(llcache_handle *handle, 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 @@ nserror hlcache_llcache_callback(llcache_handle *handle, 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 @@ nserror hlcache_llcache_callback(llcache_handle *handle, * \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 @@ bool hlcache_type_is_acceptable(llcache_handle *llcache, 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 @@ nserror hlcache_find_content(hlcache_retrieval_ctx *ctx) 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 @@ nserror hlcache_find_content(hlcache_retrieval_ctx *ctx) 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); diff --git a/content/hlcache.h b/content/hlcache.h index c4e10915a..2372158e1 100644 --- a/content/hlcache.h +++ b/content/hlcache.h @@ -101,7 +101,7 @@ nserror hlcache_poll(void); * \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 @@ nserror hlcache_poll(void); * 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 @@ nserror hlcache_handle_retrieve(const char *url, uint32_t flags, 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 diff --git a/css/css.c b/css/css.c index b03f2342b..b27debd5a 100644 --- a/css/css.c +++ b/css/css.c @@ -31,10 +31,21 @@ #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 */ @@ -44,6 +55,18 @@ typedef struct { * 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_imports(struct content_css_data *c); 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 @@ void css_cleanup(void) * \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 @@ nserror nscss_create_css_data(struct content_css_data *c, */ 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 @@ css_error nscss_process_css_data(struct content_css_data *c, const char *data, */ 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 @@ css_error nscss_convert_css_data(struct content_css_data *c) */ 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,32 +372,75 @@ void nscss_destroy_css_data(struct content_css_data *c) 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; } /** @@ -322,15 +452,25 @@ bool nscss_clone(const struct content *old, struct content *new_content) */ 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; } /***************************************************************************** @@ -394,7 +534,7 @@ void nscss_content_done(struct content_css_data *css, void *pw) 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 @@ nserror nscss_import(hlcache_handle *handle, 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 nscss_register_import(struct content_css_data *c, 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) { diff --git a/css/css.h b/css/css.h index d2f1191e2..28008664f 100644 --- a/css/css.h +++ b/css/css.h @@ -61,17 +61,8 @@ struct nscss_import { uint64_t media; /**< Media types that sheet applies to */ }; -void css_cleanup(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 css_init(void); +void css_fini(void); nserror nscss_create_css_data(struct content_css_data *c, const char *url, const char *charset, bool quirks, @@ -81,6 +72,7 @@ css_error nscss_process_css_data(struct content_css_data *c, const char *data, 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 diff --git a/css/select.c b/css/select.c index d4d6361b7..7e1af71d7 100644 --- a/css/select.c +++ b/css/select.c @@ -99,7 +99,7 @@ static bool parse_dimension(const char *data, bool strict, 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 @@ css_stylesheet *nscss_create_inline_style(const uint8_t *data, size_t len, /** * 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 @@ css_stylesheet *nscss_create_inline_style(const uint8_t *data, size_t len, * \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 @@ css_select_results *nscss_get_style(struct content *html, xmlNode *n, /** * 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 @@ css_computed_style *nscss_get_initial_style(struct content *html, /** * 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_name(void *pw, void *node, 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 @@ css_error node_has_class(void *pw, void *node, 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 @@ css_error node_is_visited(void *pw, void *node, bool *match) /** \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 @@ css_error node_is_visited(void *pw, void *node, bool *match) 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_is_lang(void *pw, void *node, 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 @@ css_error node_presentational_hint(void *pw, void *node, 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 node_presentational_hint(void *pw, void *node, 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 @@ css_error node_presentational_hint(void *pw, void *node, break; } - error = node_is_visited(html, n, &is_visited); + error = node_is_visited(ctx, n, &is_visited); if (error != CSS_OK) return error; diff --git a/css/select.h b/css/select.h index 21b53867d..c90e7f7a4 100644 --- a/css/select.h +++ b/css/select.h @@ -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); diff --git a/desktop/browser.c b/desktop/browser.c index fafdf7b82..1fb4de5f5 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -454,7 +454,7 @@ void browser_window_go_post(struct browser_window *bw, const char *url, 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); diff --git a/desktop/netsurf.c b/desktop/netsurf.c index 3707b1c72..9861e7e4a 100644 --- a/desktop/netsurf.c +++ b/desktop/netsurf.c @@ -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 @@ nserror netsurf_init(int *pargc, const char *options, const char *messages) { + nserror error; struct utsname utsname; nserror ret = NSERROR_OK; @@ -134,6 +138,22 @@ nserror netsurf_init(int *pargc, 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 @@ void netsurf_exit(void) LOG(("Closing GUI")); gui_quit(); - /* Clean up after CSS */ - css_cleanup(); - LOG(("Closing search and related resources")); search_web_cleanup(); @@ -191,6 +208,12 @@ void netsurf_exit(void) LOG(("Closing fetches")); fetch_quit(); + /* Clean up after content handlers */ + textplain_fini(); + image_fini(); + html_fini(); + css_fini(); + LOG(("Closing utf8")); utf8_finalise(); diff --git a/desktop/plugin.h b/desktop/plugin.h deleted file mode 100644 index b615c91af..000000000 --- a/desktop/plugin.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2011 Chris Young - * - * 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 . - */ - -/** - * \file Content handler for plugins (interface) - */ - -#ifndef NETSURF_DESKTOP_PLUGIN_H_ -#define NETSURF_DESKTOP_PLUGIN_H_ - -#ifdef WITH_PLUGIN - -#include - -#if defined(riscos) -#include "riscos/plugin.h" -#elif defined(nsamiga) -#include "amiga/plugin.h" -#endif - -struct box; -struct browser_window; -struct content; -struct object_params; -struct rect; -struct http_parameter; - -/* function definitions */ -bool plugin_handleable(const char *mime_type); -bool plugin_create(struct content *c, const struct http_parameter *params); -bool plugin_convert(struct content *c); -void plugin_reformat(struct content *c, int width, int height); -void plugin_destroy(struct content *c); -bool plugin_redraw(struct content *c, int x, int y, - int width, int height, const struct rect *clip, - float scale, colour background_colour); -void plugin_open(struct content *c, struct browser_window *bw, - struct content *page, struct box *box, - struct object_params *params); -void plugin_close(struct content *c); -bool plugin_clone(const struct content *old, struct content *new_content); - -#endif /* WITH_PLUGIN */ -#endif diff --git a/desktop/save_complete.c b/desktop/save_complete.c index 855ed247e..48e38e7f1 100644 --- a/desktop/save_complete.c +++ b/desktop/save_complete.c @@ -138,6 +138,7 @@ bool save_complete_html(hlcache_handle *c, const char *path, bool index, 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 @@ bool save_complete_html(hlcache_handle *c, const char *path, bool index, 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 @@ bool save_complete_html(hlcache_handle *c, const char *path, bool index, 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 @@ bool save_complete_html(hlcache_handle *c, const char *path, bool index, } 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 @@ bool save_imported_sheets(struct nscss_import *imports, uint32_t count, 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 @@ bool save_imported_sheets(struct nscss_import *imports, uint32_t count, 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; } diff --git a/desktop/save_complete.h b/desktop/save_complete.h index ad31fa486..6970ceaac 100644 --- a/desktop/save_complete.h +++ b/desktop/save_complete.h @@ -26,7 +26,8 @@ #include #include -#include "content/content.h" + +#include struct hlcache_handle; @@ -34,7 +35,7 @@ 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); diff --git a/desktop/searchweb.c b/desktop/searchweb.c index 23c0d5027..496ec14e1 100644 --- a/desktop/searchweb.c +++ b/desktop/searchweb.c @@ -209,10 +209,7 @@ void search_web_retrieve_ico(bool localdefault) */ return; #else - static const content_type accept[] = { - CONTENT_ICO, - CONTENT_UNKNOWN - }; + content_type accept = CONTENT_IMAGE; char *url; nserror error; @@ -284,13 +281,7 @@ nserror search_web_ico_callback(hlcache_handle *ico, 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: diff --git a/desktop/textinput.c b/desktop/textinput.c index 920d8fa99..708038d9a 100644 --- a/desktop/textinput.c +++ b/desktop/textinput.c @@ -2128,7 +2128,7 @@ void textarea_reflow(struct browser_window *bw, struct box *textarea, 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; diff --git a/desktop/tree.c b/desktop/tree.c index 9dc38c247..674bc1612 100644 --- a/desktop/tree.c +++ b/desktop/tree.c @@ -2771,7 +2771,8 @@ hlcache_handle *tree_load_icon(const char *name) /* 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 */ diff --git a/desktop/tree_url_node.c b/desktop/tree_url_node.c index 38fbdf3a6..a8a66dfbe 100644 --- a/desktop/tree_url_node.c +++ b/desktop/tree_url_node.c @@ -61,42 +61,7 @@ struct icon_entry icon_table[] = { {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} diff --git a/framebuffer/save.c b/framebuffer/save.c index 8be74b86d..601628ca0 100644 --- a/framebuffer/save.c +++ b/framebuffer/save.c @@ -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; } diff --git a/framebuffer/tree.c b/framebuffer/tree.c index 33e674704..c661edc55 100644 --- a/framebuffer/tree.c +++ b/framebuffer/tree.c @@ -37,35 +37,7 @@ void tree_icon_name_from_content_type(char *buffer, content_type type) 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; diff --git a/gtk/save.c b/gtk/save.c index a67a7e6d0..2efba7d3b 100644 --- a/gtk/save.c +++ b/gtk/save.c @@ -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; diff --git a/gtk/scaffolding.c b/gtk/scaffolding.c index 83b19ead1..a2b6c5460 100644 --- a/gtk/scaffolding.c +++ b/gtk/scaffolding.c @@ -1994,11 +1994,6 @@ void gui_window_set_icon(struct gui_window *_g, hlcache_handle *icon) 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 @@ void gui_window_set_search_ico(hlcache_handle *ico) 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; diff --git a/gtk/treeview.c b/gtk/treeview.c index b6c1c36bb..a56a28dfd 100644 --- a/gtk/treeview.c +++ b/gtk/treeview.c @@ -98,35 +98,7 @@ void tree_icon_name_from_content_type(char *buffer, content_type type) 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; diff --git a/image/bmp.c b/image/bmp.c index 1e8ec5be9..dbb4d9796 100644 --- a/image/bmp.c +++ b/image/bmp.c @@ -31,13 +31,40 @@ #include #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 @@ bmp_bitmap_callback_vt bmp_bitmap_callbacks = { .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 @@ bool nsbmp_convert(struct content *c) 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 @@ bool nsbmp_convert(struct content *c) } /* 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 @@ bool nsbmp_redraw(struct content *c, int x, int y, 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 @@ bool nsbmp_redraw_tiled(struct content *c, int x, int y, 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 @@ bool nsbmp_redraw_tiled(struct content *c, int x, int y, 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); +} -bool nsbmp_clone(const struct content *old, struct content *new_content) +nserror nsbmp_clone(const struct content *old, struct content **newc) { + nsbmp_content *new_bmp; + nserror error; + + 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() diff --git a/image/bmp.h b/image/bmp.h index cb386f6d1..885b94344 100644 --- a/image/bmp.h +++ b/image/bmp.h @@ -31,29 +31,15 @@ #include #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 */ diff --git a/image/gif.c b/image/gif.c index e449db345..20a67424e 100644 --- a/image/gif.c +++ b/image/gif.c @@ -38,6 +38,7 @@ #include #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 @@ gif_bitmap_callback_vt gif_bitmap_callbacks = { .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 +}; + +static const char *nsgif_types[] = { + "image/gif" +}; -bool nsgif_create(struct content *c, const struct http_parameter *params) +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 @@ bool nsgif_convert(struct content *c) } 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 @@ bool nsgif_redraw(struct content *c, int x, int y, 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 @@ bool nsgif_redraw_tiled(struct content *c, int x, int y, 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 @@ bool nsgif_redraw_tiled(struct content *c, int x, int y, 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 @@ bool nsgif_clone(const struct content *old, struct content *new_content) */ 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 @@ gif_result nsgif_get_frame(struct content *c) */ 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); } diff --git a/image/gif.h b/image/gif.h index a9f16d489..4ed06d09e 100644 --- a/image/gif.h +++ b/image/gif.h @@ -30,27 +30,13 @@ #include #include -struct content; -struct http_parameter; -struct rect; - -struct content_gif_data { - struct gif_animation *gif; /**< GIF animation data */ - int current_frame; /**< current frame to display [0...(max-1)] */ -}; - -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); +nserror nsgif_init(void); +void nsgif_fini(void); + +#else + +#define nsgif_init() NSERROR_OK +#define nsgif_fini() ((void) 0) #endif /* WITH_GIF */ diff --git a/image/ico.c b/image/ico.c index a753f470b..0397c5c7f 100644 --- a/image/ico.c +++ b/image/ico.c @@ -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 @@ bool nsico_convert(struct content *c) } /* 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 @@ bool nsico_redraw(struct content *c, int x, int y, 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 @@ bool nsico_redraw(struct content *c, int x, int y, 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 @@ bool nsico_redraw_tiled(struct content *c, int x, int y, 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 diff --git a/image/ico.h b/image/ico.h index 666c22371..5df3bca95 100644 --- a/image/ico.h +++ b/image/ico.h @@ -29,28 +29,15 @@ #include #include -struct content; -struct hlcache_handle; -struct http_parameter; -struct rect; - -struct content_ico_data { - struct ico_collection *ico; /** ICO collection data */ -}; - -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); +#include "utils/errors.h" + +nserror nsico_init(void); +void nsico_fini(void); + +#else + +#define nsico_init() NSERROR_OK +#define nsico_fini() ((void) 0) #endif /* WITH_BMP */ diff --git a/image/image.c b/image/image.c new file mode 100644 index 000000000..23853f133 --- /dev/null +++ b/image/image.c @@ -0,0 +1,100 @@ +/* + * Copyright 2011 John-Mark Bell + * + * 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 . + */ + +#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" + +/** + * Initialise image content handlers + * + * \return NSERROR_OK on success, appropriate error otherwise. + */ +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; +} + +/** + * Finalise image content handlers + */ +void image_fini(void) +{ + nsbmp_fini(); + nsgif_fini(); + nsico_fini(); + nsjpeg_fini(); + nsmng_fini(); + nssprite_fini(); + nspng_fini(); + nsrsvg_fini(); + svg_fini(); + webp_fini(); +} + diff --git a/image/image.h b/image/image.h new file mode 100644 index 000000000..44ea148a8 --- /dev/null +++ b/image/image.h @@ -0,0 +1,31 @@ +/* + * Copyright 2011 John-Mark Bell + * + * 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 . + */ + +/** \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 diff --git a/image/jpeg.c b/image/jpeg.c index 7ef621121..05519d63f 100644 --- a/image/jpeg.c +++ b/image/jpeg.c @@ -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 #include #include #include #include +#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,6 +87,95 @@ static boolean nsjpeg_fill_input_buffer(j_decompress_ptr cinfo); 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 @@ void nsjpeg_destroy(struct content *c) } -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 */ diff --git a/image/jpeg.h b/image/jpeg.h index 70bae4a6b..57b82bdc1 100644 --- a/image/jpeg.h +++ b/image/jpeg.h @@ -28,24 +28,15 @@ #include -struct bitmap; -struct content; -struct rect; - -struct content_jpeg_data { - int dummy; /* NOT USED but to satisfy Norcroft */ -}; - -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); +#include "utils/errors.h" + +nserror nsjpeg_init(void); +void nsjpeg_fini(void); + +#else + +#define nsjpeg_init() NSERROR_OK +#define nsjpeg_fini() ((void) 0) #endif /* WITH_JPEG */ diff --git a/image/mng.c b/image/mng.c index 6067aa8e8..a6b0377c4 100644 --- a/image/mng.c +++ b/image/mng.c @@ -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 #include #include @@ -33,6 +30,7 @@ #include #include #include +#include "content/content_protected.h" #include "desktop/options.h" #include "desktop/plotters.h" #include "image/bitmap.h" @@ -40,12 +38,44 @@ #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, @@ -59,7 +89,7 @@ static mng_bool nsmng_refresh(mng_handle mng, mng_uint32 x, mng_uint32 y, 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,8 +98,131 @@ static mng_ptr nsmng_alloc(mng_size_t n); 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 +}; + +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; -bool nsmng_create(struct content *c, const struct http_parameter *params) + return NSERROR_OK; +} + +nserror nsmng_create_mng_data(nsmng_content *c) { mng_retcode code; union content_msg_data msg_data; @@ -79,20 +232,20 @@ bool nsmng_create(struct content *c, const struct http_parameter *params) /* 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 @@ bool nsmng_create(struct content *c, const struct http_parameter *params) /* 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 @@ bool nsmng_create(struct content *c, const struct http_parameter *params) /* 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 @@ bool nsmng_create(struct content *c, const struct http_parameter *params) /* 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_openstream(mng_handle mng) 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 @@ mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer, mng_uint32 size, /* 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_closestream(mng_handle mng) 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 @@ mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width, /* 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 @@ mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width, 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 @@ bool nsmng_process_data(struct content *c, const char *data, unsigned int size) /* 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_process_data(struct content *c, const char *data, unsigned int size) 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 @@ bool nsmng_convert(struct content *c) /* 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 @@ bool nsmng_convert(struct content *c) } 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 @@ bool nsmng_convert(struct content *c) */ /* 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 @@ bool nsmng_convert(struct content *c) 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_bool nsmng_refresh(mng_handle mng, mng_uint32 x, mng_uint32 y, 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 @@ mng_bool nsmng_refresh(mng_handle mng, mng_uint32 x, mng_uint32 y, /* 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 @@ mng_bool nsmng_refresh(mng_handle mng, mng_uint32 x, mng_uint32 y, * 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 @@ mng_bool nsmng_settimer(mng_handle mng, mng_uint32 msecs) 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 @@ bool nsmng_redraw(struct content *c, int x, int y, 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 @@ bool nsmng_redraw(struct content *c, int x, int y, /* 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 @@ bool nsmng_redraw_tiled(struct content *c, int x, int y, 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,35 +753,61 @@ bool nsmng_redraw_tiled(struct content *c, int x, int y, /* 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; } /** @@ -613,22 +815,22 @@ bool nsmng_clone(const struct content *old, struct content *new_content) */ 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 @@ void nsmng_animate(void *p) * 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 @@ bool nsmng_broadcast_error(struct content *c, mng_retcode code) 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_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) { - 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 @@ mng_bool nsmng_errorproc(mng_handle mng, mng_int32 code, 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); } diff --git a/image/mng.h b/image/mng.h index 5835fef96..a3318615b 100644 --- a/image/mng.h +++ b/image/mng.h @@ -28,32 +28,13 @@ #include -struct content; -struct http_parameter; -struct rect; - -struct content_mng_data { - bool opaque_test_pending; - bool read_start; - bool read_resume; - int read_size; - bool waiting; - bool displayed; - void *handle; -}; - -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); +nserror nsmng_init(void); +void nsmng_fini(void); + +#else + +#define nsmng_init() NSERROR_OK +#define nsmng_fini() ((void) 0) #endif /* WITH_MNG */ diff --git a/image/nssprite.c b/image/nssprite.c index a0ad8678c..961188c84 100644 --- a/image/nssprite.c +++ b/image/nssprite.c @@ -29,13 +29,33 @@ #include #include #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 @@ bool nssprite_convert(struct content *c) 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 @@ bool nssprite_convert(struct content *c) 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_redraw(struct content *c, int x, int y, } -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 diff --git a/image/nssprite.h b/image/nssprite.h index 3b69108cd..1f25896b3 100644 --- a/image/nssprite.h +++ b/image/nssprite.h @@ -28,19 +28,13 @@ #include -struct content; -struct rect; - -struct content_nssprite_data { - struct rosprite_area* sprite_area; -}; - -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); +nserror nssprite_init(void); +void nssprite_fini(void); + +#else + +#define nssprite_init() NSERROR_OK +#define nssprite_fini() ((void) 0) #endif /* WITH_NSSPRITE */ diff --git a/image/png.c b/image/png.c index 159019996..5469e6923 100644 --- a/image/png.c +++ b/image/png.c @@ -23,8 +23,7 @@ #include #include -/* Ugh -- setjmp.h weirdness ensues if this isn't first... */ -#include "image/png.h" +#include #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 +}; + +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]); + } +} -bool nspng_create(struct content *c, const struct http_parameter *params) +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 @@ bool nspng_process_data(struct content *c, const char *data, unsigned int size) 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 @@ void info_callback(png_structp png, png_infop info) 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 @@ void info_callback(png_structp png, png_infop info) 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 @@ static unsigned int interlace_row_step[8] = {8, 8, 8, 4, 4, 2, 2}; 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 @@ void row_callback(png_structp png, png_bytep new_row, 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 @@ void row_callback(png_structp png, png_bytep new_row, /* 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 @@ void end_callback(png_structp png, png_infop info) 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 @@ bool nspng_convert(struct content *c) 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 @@ bool nspng_convert(struct content *c) 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 @@ bool nspng_convert(struct content *c) 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 @@ bool nspng_redraw_tiled(struct content *c, int x, int y, 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 diff --git a/image/png.h b/image/png.h index fb9efcfd4..1119b6a43 100644 --- a/image/png.h +++ b/image/png.h @@ -24,37 +24,17 @@ #ifdef WITH_PNG -#include "desktop/plot_style.h" - #include -#include - -struct content; -struct bitmap; -struct http_parameter; -struct rect; - -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 */ -}; - -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); + +#include "utils/errors.h" + +nserror nspng_init(void); +void nspng_fini(void); + +#else + +#define nspng_init() NSERROR_OK +#define nspng_fini() ((void) 0) #endif diff --git a/image/rsvg.c b/image/rsvg.c index cf3d5cea6..26370de57 100644 --- a/image/rsvg.c +++ b/image/rsvg.c @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -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) +{ + 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) { - struct content_rsvg_data *d = &c->data.rsvg; 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 @@ static inline void rsvg_argb_to_abgr(uint8_t *pixels, 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 @@ bool rsvg_redraw(struct content *c, int x, int y, 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 @@ void rsvg_destroy(struct content *c) 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 */ diff --git a/image/rsvg.h b/image/rsvg.h index 90b4ba8f3..4d4e65fea 100644 --- a/image/rsvg.h +++ b/image/rsvg.h @@ -27,30 +27,16 @@ #ifdef WITH_RSVG #include -#include -#include -#include "desktop/plot_style.h" -#include "image/bitmap.h" - -struct content; -struct http_parameter; -struct rect; - -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 */ -}; - -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); + +#include "utils/errors.h" + +nserror nsrsvg_init(void); +void nsrsvg_fini(void); + +#else + +#define nsrsvg_init() NSERROR_OK +#define nsrsvg_fini() ((void) 0) #endif /* WITH_RSVG */ diff --git a/image/svg.c b/image/svg.c index d77c8e03a..781a9af48 100644 --- a/image/svg.c +++ b/image/svg.c @@ -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 @@ bool svg_convert(struct content *c) 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 @@ bool svg_redraw(struct content *c, int x, int y, 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 @@ bool svg_redraw(struct content *c, int x, int y, 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 */ diff --git a/image/svg.h b/image/svg.h index d836cb310..0e8ad8559 100644 --- a/image/svg.h +++ b/image/svg.h @@ -23,25 +23,22 @@ #ifndef _NETSURF_IMAGE_SVG_H_ #define _NETSURF_IMAGE_SVG_H_ +#include "utils/config.h" + +#ifdef WITH_NS_SVG + #include -struct content; -struct http_parameter; -struct svgtiny_diagram; -struct rect; - -struct content_svg_data { - struct svgtiny_diagram *diagram; - bool done_parse; -}; - -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); +#include "utils/errors.h" + +nserror svg_init(void); +void svg_fini(void); + +#else + +#define svg_init() NSERROR_OK +#define svg_fini() ((void) 0) + +#endif #endif diff --git a/image/webp.c b/image/webp.c index 439bdfc9b..a76c0918c 100644 --- a/image/webp.c +++ b/image/webp.c @@ -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, + NULL, + 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: + webp_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_redraw(struct content *c, int x, int y, } -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 diff --git a/image/webp.h b/image/webp.h index a89713ac3..3d976d13e 100644 --- a/image/webp.h +++ b/image/webp.h @@ -28,19 +28,15 @@ #include -struct content; -struct rect; - -struct content_webp_data { -/* empty */ -}; - -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); +#include "utils/errors.h" + +nserror webp_init(void); +void webp_fini(void); + +#else + +#define webp_init() NSERROR_OK +#define webp_fini() ((void) 0) #endif /* WITH_WEBP */ diff --git a/monkey/utils.c b/monkey/utils.c index fba79184f..5b262a2a7 100644 --- a/monkey/utils.c +++ b/monkey/utils.c @@ -132,7 +132,7 @@ utf8_to_local_encoding(const char *string, size_t len, 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; } diff --git a/render/box.c b/render/box.c index e54ca2fb7..537ea3674 100644 --- a/render/box.c +++ b/render/box.c @@ -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,16 +563,12 @@ bool box_contains_point(struct box *box, int x, int y, bool *physically) 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 = c->data.html.layout; + box = html_get_box_tree(h); while ((box = box_at_point(box, x, y, &box_x, &box_y, &content))) { if (box->style && css_computed_visibility(box->style) == @@ -597,16 +593,12 @@ struct box *box_object_at_point(hlcache_handle *h, int x, int y) 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 = c->data.html.layout; + box = html_get_box_tree(h); while ((box = box_at_point(box, x, y, &box_x, &box_y, &content))) { if (box->style && css_computed_visibility(box->style) == @@ -804,7 +796,7 @@ struct box *box_pick_text_box(hlcache_handle *h, { 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]; diff --git a/render/box.h b/render/box.h index e7c19ad6d..b5092728f 100644 --- a/render/box.h +++ b/render/box.h @@ -99,7 +99,7 @@ struct box; 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_handle_scrollbars(struct browser_window *bw, struct box *box, 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 diff --git a/render/box_construct.c b/render/box_construct.c index f780d0714..f73a8322c 100644 --- a/render/box_construct.c +++ b/render/box_construct.c @@ -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_PARENT = "_parent"; 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_input_text(BOX_SPECIAL_PARAMS, bool password); 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 @@ static const struct element_entry element_table[] = { * \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 @@ bool xml_to_box(xmlNode *n, struct content *c) 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 @@ static const box_type box_map[] = { * \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 @@ bool convert_xml_to_box(xmlNode *n, struct content *content, * \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 @@ bool box_construct_element(xmlNode *n, struct content *content, 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 @@ bool box_construct_element(xmlNode *n, struct content *content, 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 @@ bool box_construct_element(xmlNode *n, struct content *content, * 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 @@ void box_construct_generate(xmlNode *n, struct content *content, * \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 @@ bool box_construct_text(xmlNode *n, struct content *content, * \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_select_results *box_get_style(struct content *c, 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 @@ css_select_results *box_get_style(struct content *c, 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 @@ bool box_body(BOX_SPECIAL_PARAMS) 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 @@ bool box_a(BOX_SPECIAL_PARAMS) 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 @@ bool box_image(BOX_SPECIAL_PARAMS) /* 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 @@ bool box_image(BOX_SPECIAL_PARAMS) /* 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 @@ bool box_object(BOX_SPECIAL_PARAMS) * (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 @@ bool box_object(BOX_SPECIAL_PARAMS) 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 @@ bool box_object(BOX_SPECIAL_PARAMS) * !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 @@ bool box_object(BOX_SPECIAL_PARAMS) /* 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 box_frameset(BOX_SPECIAL_PARAMS) { 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 @@ bool box_frameset(BOX_SPECIAL_PARAMS) 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_frameset(BOX_SPECIAL_PARAMS) } 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 @@ bool box_create_frameset(struct content_html_frames *f, xmlNode *n, 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 @@ bool box_iframe(BOX_SPECIAL_PARAMS) 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 @@ bool box_iframe(BOX_SPECIAL_PARAMS) 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 @@ bool box_iframe(BOX_SPECIAL_PARAMS) 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 @@ bool box_iframe(BOX_SPECIAL_PARAMS) 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 @@ bool box_input(BOX_SPECIAL_PARAMS) 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 @@ bool box_input(BOX_SPECIAL_PARAMS) 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 @@ bool box_input(BOX_SPECIAL_PARAMS) */ 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 @@ bool box_button(BOX_SPECIAL_PARAMS) { 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 @@ bool box_select(BOX_SPECIAL_PARAMS) 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 @@ bool box_textarea(BOX_SPECIAL_PARAMS) 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 @@ bool box_embed(BOX_SPECIAL_PARAMS) /* 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 @@ bool box_embed(BOX_SPECIAL_PARAMS) 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); } /** diff --git a/render/box_normalise.c b/render/box_normalise.c index 21ede6dd4..f7154c5f3 100644 --- a/render/box_normalise.c +++ b/render/box_normalise.c @@ -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 @@ struct columns { }; -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 @@ static bool box_normalise_inline_container(struct box *cont, struct content *c); * \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 @@ bool box_normalise_block(struct box *block, struct content *c) /* 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_block(struct box *block, struct content *c) } -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 @@ bool box_normalise_table(struct box *table, struct content * c) /* 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 @@ bool box_normalise_table(struct box *table, struct content * c) 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 @@ bool box_normalise_table(struct box *table, struct content * c) } 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(struct box *table, struct content * c) */ 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 @@ bool box_normalise_table_spans(struct box *table, struct span_info *spans, 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_spans(struct box *table, struct span_info *spans, 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 @@ bool box_normalise_table_row_group(struct box *row_group, /* 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 @@ bool box_normalise_table_row_group(struct box *row_group, 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_group(struct box *row_group, 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 @@ bool box_normalise_table_row(struct box *row, /* 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 calculate_table_row(struct columns *col_info, } -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; diff --git a/render/favicon.c b/render/favicon.c deleted file mode 100644 index 6bc654e29..000000000 --- a/render/favicon.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright 2007 James Bursa - * Copyright 2009 Mark Benjamin - * - * 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 . - */ - -#include -#include "content/content_protected.h" -#include "content/hlcache.h" -#include "desktop/shape.h" -#include "render/favicon.h" -#include "render/html.h" -#include "utils/log.h" -#include "utils/messages.h" -#include "utils/talloc.h" -#include "utils/url.h" -#include "utils/utils.h" - -static char *favicon_get_icon_ref(struct content *c, xmlNode *html); -static nserror favicon_callback(hlcache_handle *icon, - const hlcache_event *event, void *pw); - -/** - * retrieve 1 url reference to 1 favicon - * \param html xml node of html element - * \return pointer to url; NULL for no icon; caller owns returned pointer - */ -char *favicon_get_icon_ref(struct content *c, xmlNode *html) -{ - xmlNode *node = html; - char *rel, *href, *url, *url2 = NULL; - url_func_result res; - - while (node) { - if (node->children != NULL) { /* children */ - node = node->children; - } else if (node->next != NULL) { /* siblings */ - node = node->next; - } else { /* ancestor siblings */ - while (node != NULL && node->next == NULL) - node = node->parent; - - if (node == NULL) - break; - - node = node->next; - } - - assert(node != NULL); - - if (node->type != XML_ELEMENT_NODE) - continue; - - if (strcmp((const char *) node->name, "link") == 0) { - /* rel= */ - if ((rel = (char *) xmlGetProp(node, - (const xmlChar *) "rel")) == NULL) - continue; - - if (strcasestr(rel, "icon") == 0) { - xmlFree(rel); - continue; - } - - if (strcasecmp(rel, "apple-touch-icon") == 0) { - xmlFree(rel); - continue; - } - - xmlFree(rel); - - if ((href = (char *) xmlGetProp(node, - (const xmlChar *) "href")) == NULL) - continue; - - res = url_join(href, c->data.html.base_url, &url); - - xmlFree(href); - - if (res != URL_FUNC_OK) - continue; - - if (url2 != NULL) { - free(url2); - url2 = NULL; - } - - res = url_normalize(url, &url2); - - free(url); - - if (res != URL_FUNC_OK) { - url2 = NULL; - - if (res == URL_FUNC_NOMEM) - return NULL; - - continue; - } - - } - } - - if (url2 == NULL) { - char *scheme; - - /* There was no icon link defined in the HTML source data. - * If the HTML document's base URL uses either the HTTP or - * HTTPS schemes, then try using "://host/favicon.ico" - */ - if (url_scheme(c->data.html.base_url, &scheme) != URL_FUNC_OK) - return NULL; - - if (strcasecmp(scheme, "http") != 0 && - strcasecmp(scheme, "https") != 0) { - free(scheme); - return NULL; - } - - free(scheme); - - if (url_join("/favicon.ico", c->data.html.base_url, &url2) - != URL_FUNC_OK) - return NULL; - } - - return url2; -} - -/** - * retrieve 1 favicon - * \param c content structure - * \param html xml node of html element - * \return true for success, false for error - */ - -bool favicon_get_icon(struct content *c, xmlNode *html) -{ - static const content_type permitted_types[] = { -#ifdef WITH_BMP - CONTENT_ICO, -#endif -#if defined(WITH_MNG) || defined(WITH_PNG) - CONTENT_PNG, -#endif -#ifdef WITH_GIF - CONTENT_GIF, -#endif - CONTENT_UNKNOWN - }; - char *url; - nserror error; - - url = favicon_get_icon_ref(c, html); - if (url == NULL) - return false; - - error = hlcache_handle_retrieve(url, LLCACHE_RETRIEVE_NO_ERROR_PAGES, - content__get_url(c), NULL, favicon_callback, c, NULL, - permitted_types, &c->data.html.favicon); - - if (error == NSERROR_OK) { - c->active += 1; - } - - free(url); - - return error == NSERROR_OK; -} - -/** - * Callback for fetchcache() for linked favicon - */ - -nserror favicon_callback(hlcache_handle *icon, - const hlcache_event *event, void *pw) -{ - struct content *c = pw; - bool consider_done = false, consider_redraw = false; - - switch (event->type) { - case CONTENT_MSG_LOADING: - /* check that the favicon is really a correct image type */ - if (content_get_type(icon) == CONTENT_UNKNOWN) { - union content_msg_data msg_data; - - LOG(("%s is not a favicon", content_get_url(icon))); - - hlcache_handle_abort(icon); - hlcache_handle_release(icon); - c->data.html.favicon = NULL; - c->active -= 1; - consider_done = true; - - content_add_error(c, "NotFavIco", 0); - - msg_data.error = messages_get("NotFavIco"); - content_broadcast(c, CONTENT_MSG_STATUS, msg_data); - } - break; - - case CONTENT_MSG_READY: - break; - case CONTENT_MSG_DONE: - c->active -= 1; - consider_done = true; - break; - - case CONTENT_MSG_ERROR: - LOG(("favicon %s failed: %s", - content_get_url(icon), event->data.error)); - hlcache_handle_release(c->data.html.favicon); - c->data.html.favicon = NULL; - - content_add_error(c, "?", 0); - - c->active -= 1; - consider_done = true; - break; - - case CONTENT_MSG_STATUS: - content_broadcast(c, CONTENT_MSG_STATUS, event->data); - break; - - case CONTENT_MSG_REDRAW: - /* Fall through */ - case CONTENT_MSG_REFRESH: - /* Fall through */ - case CONTENT_MSG_REFORMAT: - consider_redraw = true; - break; - - default: - assert(0); - } - -#ifdef WITH_GIF - if (consider_redraw && (c->data.html.favicon != NULL) && - (content_get_type(c->data.html.favicon) == - CONTENT_GIF)) { - union content_msg_data msg_data; - struct rect clip; - /* This is needed in order to cause animated GIFs to update - * their bitmap */ - clip.x0 = clip.y0 = 0; - clip.x1 = clip.y1 = 0; - content_redraw(c->data.html.favicon, 0, 0, -1, -1, &clip, - 1.0, 0); - content_broadcast(c, CONTENT_MSG_FAVICON_REFRESH, msg_data); - } -#endif - - if (consider_done && (c->active == 0)) { - /* all objects have arrived */ - content__reformat(c, c->available_width, c->height); - html_set_status(c, ""); - content_set_done(c); - } - - - return NSERROR_OK; -} diff --git a/render/favicon.h b/render/favicon.h deleted file mode 100644 index 428655ecd..000000000 --- a/render/favicon.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2009 Mark Benjamin - * - * 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 . - */ - -#ifndef _NETSURF_RENDER_FAVICON_H_ -#define _NETSURF_RENDER_FAVICON_H_ - -#include - -struct content; - -bool favicon_get_icon(struct content *c, xmlNode *html); - -#endif diff --git a/render/form.c b/render/form.c index 8a52a4fdb..955c208e8 100644 --- a/render/form.c +++ b/render/form.c @@ -1466,7 +1466,6 @@ void form_submit(hlcache_handle *h, struct browser_window *target, 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); diff --git a/render/html.c b/render/html.c index cf9fdea81..aa905802e 100644 --- a/render/html.c +++ b/render/html.c @@ -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 @@ static nserror html_object_callback(hlcache_handle *object, const hlcache_event *event, void *pw); static void html_object_done(struct box *box, hlcache_handle *object, bool background); -static void html_object_failed(struct box *box, struct content *content, +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 @@ static void html_dump_frameset(struct content_html_frames *frame, 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[] = "" @@ -98,6 +133,52 @@ static const char empty_document[] = "" ""; +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,104 @@ static const char empty_document[] = * 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) +{ + 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) { - struct content_html_data *html = &c->data.html; 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 + nerror = NSERROR_BAD_ENCODING; + } else { msg_data.error = messages_get("NoMemory"); + nerror = NSERROR_NOMEM; + } - content_broadcast(c, CONTENT_MSG_ERROR, msg_data); - return false; + content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data); + + return nerror; } @@ -182,12 +295,13 @@ error: 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 +317,7 @@ bool html_process_data(struct content *c, const char *data, unsigned int size) 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 +336,14 @@ encoding_change: /* 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 +352,16 @@ encoding_change: } /* 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 +369,16 @@ encoding_change: 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 +406,6 @@ encoding_change: * * - 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 +415,7 @@ encoding_change: 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 +426,22 @@ bool html_convert(struct content *c) 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 +455,7 @@ bool html_convert(struct content *c) 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 +465,24 @@ bool html_convert(struct content *c) 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 +490,7 @@ bool html_convert(struct content *c) } /* 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 +507,20 @@ bool html_convert(struct content *c) } 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 +528,9 @@ bool html_convert(struct content *c) 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 +544,7 @@ bool html_convert(struct content *c) /* 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 +555,7 @@ bool html_convert(struct content *c) } /* get stylesheets */ - if (!html_find_stylesheets(c, html)) + if (!html_find_stylesheets(htmlc, html)) return false; return true; @@ -456,37 +566,36 @@ bool html_convert(struct content *c) * * \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 +604,7 @@ void html_finish_conversion(struct content *c) 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 +613,54 @@ void html_finish_conversion(struct content *c) 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 +676,7 @@ void html_finish_conversion(struct content *c) * 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 +685,7 @@ bool html_head(struct content *c, xmlNode *head) 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 +695,7 @@ bool html_head(struct content *c, xmlNode *head) 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 +710,7 @@ bool html_head(struct content *c, xmlNode *head) 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 +726,9 @@ bool html_head(struct content *c, xmlNode *head) "_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 +751,7 @@ bool html_head(struct content *c, xmlNode *head) * \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 +768,7 @@ bool html_meta_refresh(struct content *c, xmlNode *head) 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 +838,17 @@ bool html_meta_refresh(struct content *c, xmlNode *head) /* 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 +911,32 @@ bool html_meta_refresh(struct content *c, xmlNode *head) 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 +953,9 @@ bool html_meta_refresh(struct content *c, xmlNode *head) * \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 +965,57 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) 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->active = 0; + 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->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 +1085,7 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) * 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 +1104,28 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) /* 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 +1134,13 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) } } - 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 +1155,7 @@ no_memory: * \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 +1185,29 @@ bool html_process_style_element(struct content *c, unsigned int *index, } /* 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 +1221,7 @@ bool html_process_style_element(struct content *c, unsigned int *index, 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 +1229,26 @@ bool html_process_style_element(struct content *c, unsigned int *index, 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 +1260,9 @@ no_memory: */ 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 +1273,22 @@ void html_inline_style_done(struct content_css_data *css, void *pw) 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 +1296,7 @@ nserror html_convert_css_callback(hlcache_handle *css, case CONTENT_MSG_DONE: LOG(("got stylesheet '%s'", content_get_url(css))); - parent->active--; + parent->base.active--; break; case CONTENT_MSG_ERROR: @@ -1211,20 +1304,21 @@ nserror html_convert_css_callback(hlcache_handle *css, 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 +1331,15 @@ nserror html_convert_css_callback(hlcache_handle *css, * \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 +1349,8 @@ bool html_fetch_object(struct content *c, const char *url, struct box *box, 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 +1365,16 @@ bool html_fetch_object(struct content *c, const char *url, struct box *box, 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 +1385,11 @@ bool html_fetch_object(struct content *c, const char *url, struct box *box, } /* 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 +1405,24 @@ bool html_fetch_object(struct content *c, const char *url, struct box *box, 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 +1435,8 @@ bool html_replace_object(struct content_html_object *object, const char *url) 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 +1445,9 @@ bool html_replace_object(struct content_html_object *object, const char *url) 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 +1462,7 @@ nserror html_object_callback(hlcache_handle *object, 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,50 +1470,31 @@ nserror html_object_callback(hlcache_handle *object, 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: + c->base.active--; + html_object_done(box, object, o->background); if (box->flags & REPLACE_DIM) { union content_msg_data data; - c->active--; - html_object_done(box, object, o->background); - if (!box_visible(box)) break; @@ -1433,10 +1506,7 @@ nserror html_object_callback(hlcache_handle *object, data.redraw.height = box->height; data.redraw.full_redraw = true; - content_broadcast(c, CONTENT_MSG_REDRAW, data); - } else { - c->active--; - html_object_done(box, object, o->background); + content_broadcast(&c->base, CONTENT_MSG_REDRAW, data); } break; @@ -1445,17 +1515,17 @@ nserror html_object_callback(hlcache_handle *object, 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 @@ nserror html_object_callback(hlcache_handle *object, 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 @@ nserror html_object_callback(hlcache_handle *object, 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 @@ nserror html_object_callback(hlcache_handle *object, 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 @@ void html_object_done(struct box *box, hlcache_handle *object, * \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 */ @@ -1585,29 +1657,6 @@ void html_object_failed(struct box *box, struct content *content, } -/** - * 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_object_refresh(void *p) 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_stop(struct content *c) 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_redraw_a_box(hlcache_handle *h, struct box *box) 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,12 +1786,7 @@ void html_destroy(struct content *c) form_free(f); } - if (html->favicon != NULL) { - hlcache_handle_release(html->favicon); - html->favicon = NULL; - } - - imagemap_destroy(c); + imagemap_destroy(html); if (html->parser_binding != NULL) binding_destroy_tree(html->parser_binding); @@ -1849,7 +1893,7 @@ void html_destroy_iframe(struct content_html_iframe *iframe) { } } -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 @@ bool html_clone(const struct content *old, struct content *new_content) * 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 @@ void html_open(struct content *c, struct browser_window *bw, 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_open(struct content *c, struct browser_window *bw, 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 @@ void html_dump_frameset(struct content_html_frames *frame, */ 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 @@ xmlDoc *html_get_document(hlcache_handle *h) */ 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 @@ struct box *html_get_box_tree(hlcache_handle *h) */ 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 @@ const char *html_get_encoding(hlcache_handle *h) */ 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 @@ binding_encoding_source html_get_encoding_source(hlcache_handle *h) */ 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_frames *html_get_frameset(hlcache_handle *h) */ 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 @@ struct content_html_iframe *html_get_iframe(hlcache_handle *h) */ 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_url(hlcache_handle *h) */ 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 @@ const char *html_get_base_target(hlcache_handle *h) */ 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 html_stylesheet *html_get_stylesheets(hlcache_handle *h, unsigned int *n) */ 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 @@ struct content_html_object *html_get_objects(hlcache_handle *h, unsigned int *n) */ 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 @@ bool html_get_id_offset(hlcache_handle *h, const char *frag_id, int *x, int *y) } 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; +} + diff --git a/render/html.h b/render/html.h index 8789f30e6..a321f5d48 100644 --- a/render/html.h +++ b/render/html.h @@ -45,16 +45,6 @@ struct plotters; 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 content_html_object { 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 { 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 */ - - 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; - - 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; -}; +/* 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; /** Render padding and margin box outlines in html_redraw(). */ extern bool html_redraw_debug; - -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); +nserror html_init(void); +void html_fini(void); 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, diff --git a/render/html_interaction.c b/render/html_interaction.c index 8cbd2c143..6670a1a90 100644 --- a/render/html_interaction.c +++ b/render/html_interaction.c @@ -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" diff --git a/render/html_internal.h b/render/html_internal.h new file mode 100644 index 000000000..ae1851e1e --- /dev/null +++ b/render/html_internal.h @@ -0,0 +1,112 @@ +/* + * Copyright 2004 James Bursa + * + * 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 . + */ + +/** \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; + + /** Parser object handle */ + void *parser_binding; + /** Document tree */ + xmlDoc *document; + /** Quirkyness of document */ + binding_quirks_mode quirks; + + /** Encoding of source, NULL if unknown. */ + char *encoding; + /** Source of encoding information. */ + binding_encoding_source encoding_source; + + /** Base URL (may be a copy of content->url). */ + char *base_url; + /** Base target */ + char *base_target; + + /** Box tree, or NULL. */ + struct box *layout; + /** Document background colour. */ + colour background_colour; + /** Font callback table */ + const struct font_functions *font_func; + + /** Number of entries in stylesheet_content. */ + unsigned int stylesheet_count; + /** Stylesheets. Each may be NULL. */ + 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 NULL 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 NULL if not an + * object within a page. */ + struct html_content *page; + /** Box containing this, or NULL 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 + + diff --git a/render/html_redraw.c b/render/html_redraw.c index c5d20b26f..fbe09f744 100644 --- a/render/html_redraw.c +++ b/render/html_redraw.c @@ -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 @@ bool html_redraw(struct content *c, int x, int y, 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 @@ bool html_redraw(struct content *c, int x, int y, .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 @@ bool html_redraw(struct content *c, int x, int y, /* 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); diff --git a/render/imagemap.c b/render/imagemap.c index 07a46d404..e8d61384f 100644 --- a/render/imagemap.c +++ b/render/imagemap.c @@ -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 { 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 @@ static int imagemap_point_in_poly(int num, float *xpt, float *ypt, * \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 @@ bool imagemap_add(struct content *c, const char *key, struct mapentry *list) 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 @@ bool imagemap_add(struct content *c, const char *key, struct mapentry *list) * \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 @@ bool imagemap_create(struct content *c) * * \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 @@ void imagemap_destroy(struct content *c) } } - free(c->data.html.imagemaps); + free(c->imagemaps); } /** @@ -184,23 +181,22 @@ void imagemap_destroy(struct content *c) * * \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 @@ void imagemap_dump(struct content *c) * \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 @@ bool imagemap_extract(xmlNode *node, struct content *c) * \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 @@ bool imagemap_extract_map(xmlNode *node, struct content *c, */ 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 @@ const char *imagemap_get(hlcache_handle *h, const char *key, 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; } diff --git a/render/imagemap.h b/render/imagemap.h index 87a84c3dd..60d73653c 100644 --- a/render/imagemap.h +++ b/render/imagemap.h @@ -21,12 +21,12 @@ #include -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, diff --git a/render/layout.c b/render/layout.c index ca3f84853..b46930b21 100644 --- a/render/layout.c +++ b/render/layout.c @@ -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 int line_height(const css_computed_style *style); 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 void layout_compute_relative_offset(struct box *box, int *x, int *y); 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,13 +140,11 @@ static void layout_compute_offsets(struct box *box, * \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; - - assert(content->type == CONTENT_HTML); + struct box *doc = content->layout; + const struct font_functions *font_func = content->font_func; layout_minmax_block(doc, font_func); @@ -202,7 +201,7 @@ bool layout_document(struct content *content, int width, int height) */ 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 @@ void layout_block_add_scrollbar(struct box *box, int which) 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 @@ void find_sides(struct box *fl, int y0, int y1, */ 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 @@ int line_height(const css_computed_style *style) * 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 @@ static bool layout_text_box_split(struct content *content, 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 @@ bool layout_line(struct box *first, int *width, int *y, 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 @@ int layout_text_indent(const css_computed_style *style, int width) * \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 @@ void place_float_below(struct box *c, int width, int cx, int y, */ 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 @@ void layout_compute_relative_offset(struct box *box, int *x, int *y) 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_position_absolute(struct box *box, 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; diff --git a/render/layout.h b/render/layout.h index 30d9757f6..f4117e286 100644 --- a/render/layout.h +++ b/render/layout.h @@ -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); diff --git a/render/textplain.c b/render/textplain.c index 9601e25ab..a394b8251 100644 --- a/render/textplain.c +++ b/render/textplain.c @@ -50,6 +50,24 @@ #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 plot_font_style_t textplain_style = { 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) { - const char *encoding; + textplain_content *text; nserror error; + const char *encoding; - 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 @@ parserutils_error textplain_charset_hack(const uint8_t *data, size_t len, 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 @@ bool textplain_create_internal(struct content *c, const char *encoding) 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 @@ bool textplain_drain_input(struct content *c, parserutils_inputstream *stream, 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_copy_utf8_data(struct content *c, const uint8_t *buf, size_t len) 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 @@ bool textplain_process_data(struct content *c, 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 @@ no_memory: 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 @@ bool textplain_convert(struct content *c) 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 @@ bool textplain_convert(struct content *c) 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 @@ void textplain_reformat(struct content *c, int width, int height) 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 @@ void textplain_reformat(struct content *c, int width, int height) 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 @@ void textplain_reformat(struct content *c, int width, int height) 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 @@ no_memory: 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 @@ bool textplain_redraw(struct content *c, int x, int y, 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 @@ bool textplain_redraw(struct content *c, int x, int y, */ 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 @@ unsigned long textplain_line_count(hlcache_handle *h) */ 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_size(hlcache_handle *h) 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 @@ size_t textplain_offset_from_coords(hlcache_handle *h, int x, int y, int dir) 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 @@ size_t textplain_offset_from_coords(hlcache_handle *h, int x, int y, int dir) 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 @@ size_t textplain_offset_from_coords(hlcache_handle *h, int x, int y, int dir) 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 @@ int textplain_coord_from_offset(const char *text, size_t offset, size_t length) 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 @@ void textplain_coords_from_range(hlcache_handle *h, unsigned start, 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 @@ void textplain_coords_from_range(hlcache_handle *h, unsigned start, 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 @@ void textplain_coords_from_range(hlcache_handle *h, unsigned start, 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_line(hlcache_handle *h, unsigned lineno, 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 @@ char *textplain_get_raw_data(hlcache_handle *h, unsigned start, unsigned end, *plen = end - start; - return c->data.textplain.utf8_data + start; + return c->utf8_data + start; } /** diff --git a/render/textplain.h b/render/textplain.h index c338220d1..66e4e83ee 100644 --- a/render/textplain.h +++ b/render/textplain.h @@ -32,36 +32,8 @@ struct hlcache_handle; struct http_parameter; struct rect; -struct textplain_line { - size_t start; - size_t length; -}; - -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); +nserror textplain_init(void); +void textplain_fini(void); /* access to lines for text selection and searching */ unsigned long textplain_line_count(struct hlcache_handle *h); diff --git a/riscos/artworks.c b/riscos/artworks.c index 45bba1a13..2be64a633 100644 --- a/riscos/artworks.c +++ b/riscos/artworks.c @@ -32,14 +32,15 @@ #include "oslib/os.h" #include "oslib/wimp.h" #include "utils/config.h" -#include "desktop/plotters.h" #include "content/content_protected.h" +#include "desktop/plotters.h" #include "riscos/artworks.h" #include "riscos/gui.h" #include "riscos/wimputils.h" -#include "utils/utils.h" -#include "utils/messages.h" #include "utils/log.h" +#include "utils/messages.h" +#include "utils/talloc.h" +#include "utils/utils.h" #define AWRender_FileInitAddress 0x46080 #define AWRender_RenderAddress 0x46081 @@ -53,6 +54,20 @@ #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; @@ -72,12 +87,12 @@ struct awinfo_block { /* 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,7 +104,105 @@ os_error *awrender_render(const char *doc, 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 @@ os_error *awrender_render(const char *doc, 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 @@ bool artworks_convert(struct content *c) } 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 @@ bool artworks_convert(struct content *c) 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 @@ bool artworks_convert(struct content *c) 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 @@ bool artworks_convert(struct content *c) void artworks_destroy(struct content *c) { - free(c->data.artworks.block); + artworks_content *aw = (artworks_content *) c; + + free(aw->block); } @@ -236,6 +351,7 @@ bool artworks_redraw(struct content *c, int x, int y, 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 @@ bool artworks_redraw(struct content *c, int x, int y, /* 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 @@ bool artworks_redraw(struct content *c, int x, int y, 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 @@ bool artworks_redraw(struct content *c, int x, int y, 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 @@ bool artworks_redraw(struct content *c, int x, int y, &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 @@ bool artworks_redraw(struct content *c, int x, int y, 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 diff --git a/riscos/artworks.h b/riscos/artworks.h index 5acd463ee..4a339cc84 100644 --- a/riscos/artworks.h +++ b/riscos/artworks.h @@ -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 diff --git a/riscos/draw.c b/riscos/draw.c index 76bda452f..d2773439a 100644 --- a/riscos/draw.c +++ b/riscos/draw.c @@ -29,13 +29,123 @@ #include #include "oslib/drawfile.h" #include "utils/config.h" -#include "desktop/plotters.h" #include "content/content_protected.h" +#include "desktop/plotters.h" #include "riscos/draw.h" #include "riscos/gui.h" -#include "utils/utils.h" -#include "utils/messages.h" #include "utils/log.h" +#include "utils/messages.h" +#include "utils/talloc.h" +#include "utils/utils.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 @@ bool draw_convert(struct content *c) /* 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 @@ bool draw_redraw(struct content *c, int x, int y, 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 @@ bool draw_redraw(struct content *c, int x, int y, 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 @@ bool draw_redraw(struct content *c, int x, int y, * 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 diff --git a/riscos/draw.h b/riscos/draw.h index f7a014844..a0843202a 100644 --- a/riscos/draw.h +++ b/riscos/draw.h @@ -24,23 +24,17 @@ #define _NETSURF_RISCOS_DRAW_H_ #include "utils/config.h" -#ifdef WITH_DRAW +#include "utils/errors.h" -#include +#ifdef WITH_DRAW -struct content; -struct rect; +nserror draw_init(void); +void draw_fini(void); -struct content_draw_data { - int x0, y0; -}; +#else -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); +#define draw_init() NSERROR_OK +#define draw_fini() ((void) 0) #endif /* WITH_DRAW */ diff --git a/riscos/filetype.c b/riscos/filetype.c index 2c8ac76d9..5c539a1d6 100644 --- a/riscos/filetype.c +++ b/riscos/filetype.c @@ -253,22 +253,69 @@ int cmp_type(const void *x, const void *y) */ 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(hlcache_handle *c) */ 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; } diff --git a/riscos/gui.c b/riscos/gui.c index 230d30db2..9d162f6f5 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -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 @@ int main(int argc, char** argv) 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 @@ int main(int argc, char** argv) netsurf_exit(); + sprite_fini(); + draw_fini(); + artworks_fini(); + return 0; } diff --git a/riscos/gui.h b/riscos/gui.h index dcfb6a0ce..d64764c2d 100644 --- a/riscos/gui.h +++ b/riscos/gui.h @@ -171,6 +171,8 @@ void ro_gui_history_mouse_at(wimp_pointer *pointer); /* 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); diff --git a/riscos/gui/url_bar.c b/riscos/gui/url_bar.c index 4a3b4b232..aadc0e36f 100644 --- a/riscos/gui/url_bar.c +++ b/riscos/gui/url_bar.c @@ -875,7 +875,7 @@ bool ro_gui_url_bar_test_for_text_field_keypress(struct url_bar *url_bar, 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 @@ bool ro_gui_url_bar_set_site_favicon(struct url_bar *url_bar, // \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 @@ bool ro_gui_url_bar_set_content_favicon(struct url_bar *url_bar, 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, diff --git a/riscos/plugin.c b/riscos/plugin.c index b70083831..d39944d07 100644 --- a/riscos/plugin.c +++ b/riscos/plugin.c @@ -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,9 +65,31 @@ #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, @@ -96,8 +117,8 @@ struct plugin_param_item { 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 @@ struct plugin_stream { #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_stream_as_file_callback(void *p); 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_stream_callback(content_msg msg, struct content *c, 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; - - return true; + 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 NSERROR_OK; } /** @@ -229,11 +296,13 @@ bool plugin_convert(struct content *c) */ 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 @@ void plugin_open(struct content *c, struct browser_window *bw, 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 @@ void plugin_open(struct content *c, struct browser_window *bw, 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 @@ void plugin_open(struct content *c, struct browser_window *bw, 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 @@ void plugin_open(struct content *c, struct browser_window *bw, /* 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 @@ void plugin_open(struct content *c, struct browser_window *bw, 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 @@ void plugin_open(struct content *c, struct browser_window *bw, } /* 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 @@ void plugin_open(struct content *c, struct browser_window *bw, 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 @@ void plugin_open(struct content *c, struct browser_window *bw, 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 @@ error: free(params); } + lwc_string_unref(mime_type); + LOG(("done")); } @@ -412,17 +489,18 @@ error: */ 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 @@ void plugin_close(struct content *c) 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 @@ void plugin_close(struct content *c) } /* paranoia */ - c->data.plugin.streams = 0; + plugin->streams = 0; } /** @@ -470,6 +548,7 @@ void plugin_close(struct content *c) */ 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 @@ void plugin_reformat(struct content *c, int width, int height) 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 @@ void plugin_reformat(struct content *c, int width, int height) 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 @@ void plugin_reformat(struct content *c, int width, int height) 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 @@ bool plugin_clone(const struct content *old, struct content *new_content) * \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; } @@ -575,34 +674,6 @@ bool plugin_create_sysvar(const char *mime_type, char* sysvar, bool helper) return true; } -/** - * 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 * @@ -610,31 +681,31 @@ bool plugin_handleable(const char *mime_type) */ 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_open_msg(wimp_message *message) */ 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 @@ void plugin_opening(wimp_message *message) 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_close_msg(wimp_message *message) */ 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_closed(wimp_message *message) */ 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 @@ void plugin_reshape_request(wimp_message *message) * 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_reshape_request(wimp_message *message) */ 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 @@ void plugin_stream_new(wimp_message *message) 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 @@ void plugin_stream_written(wimp_message *message) 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_stream_written(wimp_message *message) */ 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 @@ void plugin_url_access(wimp_message *message) 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 @@ void plugin_url_access(wimp_message *message) */ 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 @@ void plugin_url_access(wimp_message *message) * 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 @@ void plugin_url_access(wimp_message *message) * \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 @@ void plugin_create_stream(struct content *plugin, struct content *c, 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 @@ bool plugin_send_stream_new(struct plugin_stream *p) 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 @@ bool plugin_send_stream_new(struct plugin_stream *p) 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 @@ void plugin_write_stream(struct plugin_stream *p, unsigned int consumed) 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 @@ void plugin_write_stream(struct plugin_stream *p, unsigned int consumed) 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 @@ void plugin_stream_as_file_callback(void *p) 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 @@ void plugin_write_stream_as_file(struct plugin_stream *p) 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 @@ void plugin_write_stream_as_file(struct plugin_stream *p) 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 @@ void plugin_destroy_stream(struct plugin_stream *p, 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 @@ void plugin_destroy_stream(struct plugin_stream *p, 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 @@ void plugin_destroy_stream(struct plugin_stream *p, * \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 @@ bool plugin_write_parameters_file(struct content *c, xosfile_create_dir(".WWW", 77); xosfile_create_dir(".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 @@ bool plugin_write_parameters_file(struct content *c, 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 @@ bool plugin_write_parameters_file(struct content *c, 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 @@ error: ppi = 0; } - free(c->data.plugin.filename); - c->data.plugin.filename = 0; + free(c->filename); + c->filename = 0; return false; } @@ -1634,14 +1700,14 @@ void plugin_stream_free(struct plugin_stream *p) /* 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); } diff --git a/riscos/plugin.h b/riscos/plugin.h index a3586b284..87b59edca 100644 --- a/riscos/plugin.h +++ b/riscos/plugin.h @@ -22,30 +22,10 @@ #include "utils/config.h" #ifdef WITH_PLUGIN -#include "desktop/plugin.h" #include #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); diff --git a/riscos/print.c b/riscos/print.c index a1e940f4d..486742c64 100644 --- a/riscos/print.c +++ b/riscos/print.c @@ -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 @@ bool print_document(struct gui_window *g, const char *filename) 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 @@ bool print_document(struct gui_window *g, const char *filename) /* 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 @@ error: /* 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; } diff --git a/riscos/save.c b/riscos/save.c index a47de318f..b1b743e59 100644 --- a/riscos/save.c +++ b/riscos/save.c @@ -1013,7 +1013,7 @@ void ro_gui_save_done(void) */ 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 @@ bool save_complete_gui_save(const char *path, const char *filename, size_t len, 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_complete(hlcache_handle *h, char *path) 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 @@ void ro_gui_save_set_state(hlcache_handle *h, gui_save_type save_type, 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) diff --git a/riscos/sprite.c b/riscos/sprite.c index 55afa6f98..e14f8b19a 100644 --- a/riscos/sprite.c +++ b/riscos/sprite.c @@ -21,27 +21,130 @@ * * 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 #include #include "oslib/osspriteop.h" #include "utils/config.h" -#include "desktop/plotters.h" #include "content/content_protected.h" +#include "desktop/plotters.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 @@ bool sprite_convert(struct content *c) 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 @@ bool sprite_redraw(struct content *c, int x, int y, 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,16 +236,38 @@ bool sprite_redraw(struct content *c, int x, int y, 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 diff --git a/riscos/sprite.h b/riscos/sprite.h index a0b071425..79e02f44b 100644 --- a/riscos/sprite.h +++ b/riscos/sprite.h @@ -23,24 +23,19 @@ #ifndef _NETSURF_RISCOS_SPRITE_H_ #define _NETSURF_RISCOS_SPRITE_H_ -#include -#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; -}; - -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); + +nserror sprite_init(void); +void sprite_fini(void); + +#else + +#define sprite_init() NSERROR_OK +#define sprite_fini() ((void) 0) + #endif byte sprite_bpp(const osspriteop_header *s); diff --git a/riscos/treeview.c b/riscos/treeview.c index 8cc3ea12b..0206a7c29 100644 --- a/riscos/treeview.c +++ b/riscos/treeview.c @@ -1241,35 +1241,7 @@ void tree_icon_name_from_content_type(char *buffer, content_type type) 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; diff --git a/riscos/window.c b/riscos/window.c index 7c2cfd8f1..5ad6db981 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -3893,46 +3893,20 @@ bool ro_gui_window_content_export_types(hlcache_handle *h, 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 @@ void ro_gui_window_prepare_pageinfo(struct gui_window *g) 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 @@ void ro_gui_window_prepare_pageinfo(struct gui_window *g) 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 @@ void ro_gui_window_prepare_pageinfo(struct gui_window *g) 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_pageinfo(struct gui_window *g) 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 @@ void ro_gui_window_prepare_objectinfo(hlcache_handle *object, const char *href) if (url == NULL) url = "-"; mime = content_get_mime_type(object); - if (mime == NULL) - mime = "-"; if (href) target = href; @@ -4067,7 +4041,9 @@ void ro_gui_window_prepare_objectinfo(hlcache_handle *object, const char *href) 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); } diff --git a/utils/errors.h b/utils/errors.h index 8bca2819a..fcfb3cc49 100644 --- a/utils/errors.h +++ b/utils/errors.h @@ -39,8 +39,11 @@ typedef enum { 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_BAD_ENCODING /**< The character set is unknown */ } nserror; #endif diff --git a/windows/gui.c b/windows/gui.c index 4e87c0739..5c5fed48a 100644 --- a/windows/gui.c +++ b/windows/gui.c @@ -1733,7 +1733,7 @@ save_complete_gui_save(const char *path, const char *filename, size_t len, const char *sourcedata, - content_type type) + lwc_string *mime_type) { return false; } diff --git a/windows/tree.c b/windows/tree.c index c67e50bc4..ec0750be4 100644 --- a/windows/tree.c +++ b/windows/tree.c @@ -37,35 +37,7 @@ void tree_icon_name_from_content_type(char *buffer, content_type type) 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; -- cgit v1.2.3