From 08177fa58119f9e67fdffb32ee20dbf05bd4fa78 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Thu, 10 Jun 2004 20:41:26 +0000 Subject: [project @ 2004-06-10 20:41:26 by bursa] Add global content list. Better error handling in content code. Improved code documentation. Remove some obsolete functions. Implement debug window listing contents. svn path=/import/netsurf/; revision=951 --- !NetSurf/Resources/en/Messages | 3 + !NetSurf/Resources/en/Templates,fec | Bin 6298 -> 6410 bytes !NetSurf/Resources/fr/Messages | 3 + !NetSurf/Resources/fr/Templates,fec | Bin 6404 -> 6516 bytes content/content.c | 292 +++++++++++++++++++++++++----------- content/content.h | 100 ++++++++++-- content/fetch.c | 8 +- content/fetchcache.c | 41 +++-- css/css.c | 119 ++++++++------- css/css.h | 4 +- debug/netsurfd.c | 10 +- desktop/browser.c | 1 + desktop/gui.h | 2 - desktop/netsurf.c | 12 +- makefile | 14 +- render/html.c | 111 ++++++-------- render/html.h | 15 +- render/textplain.c | 10 +- render/textplain.h | 4 +- riscos/dialog.c | 3 +- riscos/draw.c | 51 +++---- riscos/draw.h | 8 +- riscos/gif.c | 64 +++++--- riscos/gif.h | 11 +- riscos/gifread.c | 29 ++-- riscos/gui.c | 11 +- riscos/gui.h | 8 +- riscos/htmlredraw.c | 6 +- riscos/jpeg.c | 35 +++-- riscos/jpeg.h | 10 +- riscos/png.c | 72 +++++---- riscos/png.h | 13 +- riscos/sprite.c | 92 +++++++----- riscos/sprite.h | 15 +- riscos/wimp.c | 1 + utils/utils.h | 1 + 36 files changed, 743 insertions(+), 436 deletions(-) diff --git a/!NetSurf/Resources/en/Messages b/!NetSurf/Resources/en/Messages index 6d727b91d..25a7e3acb 100644 --- a/!NetSurf/Resources/en/Messages +++ b/!NetSurf/Resources/en/Messages @@ -117,6 +117,9 @@ FetchStyle2:Loading %u stylesheets: %s NotCSS:Warning: stylesheet is not CSS BadObject:Warning: bad object type ObjError:Error loading object: %s +ParsingFail:Parsing the document failed. +BadGIF:Reading GIF failed. +PNGError:PNG library error. DrawTitle:Draw image (%lux%lu, %lu bytes) GIFTitle:GIF image (%lux%lu) diff --git a/!NetSurf/Resources/en/Templates,fec b/!NetSurf/Resources/en/Templates,fec index 58f6c17c5..afad82c15 100644 Binary files a/!NetSurf/Resources/en/Templates,fec and b/!NetSurf/Resources/en/Templates,fec differ diff --git a/!NetSurf/Resources/fr/Messages b/!NetSurf/Resources/fr/Messages index 67cc4cc18..5077b78c9 100644 --- a/!NetSurf/Resources/fr/Messages +++ b/!NetSurf/Resources/fr/Messages @@ -115,6 +115,9 @@ FetchStyle2:Chargement de %u feuilles de styles: %s NotCSS:Attention: feuille de style non CSS BadObject:Attention: mauvais type d'objet ObjError:Erreur lors du chargement de: %s +ParsingFail:Parsing the document failed. +BadGIF:Reading GIF failed. +PNGError:PNG library error. DrawTitle:Image Draw (%lux%lu, %lu octets) GIFTitle:Image GIF (%lux%lu) diff --git a/!NetSurf/Resources/fr/Templates,fec b/!NetSurf/Resources/fr/Templates,fec index ec487e3d1..1f2934814 100644 Binary files a/!NetSurf/Resources/fr/Templates,fec and b/!NetSurf/Resources/fr/Templates,fec differ diff --git a/content/content.c b/content/content.c index a002c04fd..268b36433 100644 --- a/content/content.c +++ b/content/content.c @@ -45,6 +45,10 @@ #include "netsurf/utils/utils.h" +/** Linked list of all content structures. May include more than one content + * per URL. Doubly-linked. */ +struct content *content_list = 0; + /** An entry in mime_map. */ struct mime_entry { char mime_type[40]; @@ -79,17 +83,50 @@ static const struct mime_entry mime_map[] = { }; #define MIME_MAP_COUNT (sizeof(mime_map) / sizeof(mime_map[0])) +const char *content_type_name[] = { + "HTML", + "TEXTPLAIN", + "CSS", +#ifdef WITH_JPEG + "JPEG", +#endif +#ifdef WITH_GIF + "GIF", +#endif +#ifdef WITH_PNG + "PNG", +#endif +#ifdef WITH_SPRITE + "SPRITE", +#endif +#ifdef WITH_DRAW + "DRAW", +#endif +#ifdef WITH_PLUGIN + "PLUGIN", +#endif + "OTHER", + "UNKNOWN" +}; + +const char *content_status_name[] = { + "TYPE_UNKNOWN", + "LOADING", + "READY", + "DONE", + "ERROR" +}; + /** An entry in handler_map. */ struct handler_entry { - void (*create)(struct content *c, const char *params[]); - void (*process_data)(struct content *c, char *data, unsigned long size); - int (*convert)(struct content *c, unsigned int width, unsigned int height); - void (*revive)(struct content *c, unsigned int width, unsigned int height); - void (*reformat)(struct content *c, unsigned int width, unsigned int height); + bool (*create)(struct content *c, const char *params[]); + bool (*process_data)(struct content *c, char *data, unsigned int size); + bool (*convert)(struct content *c, int width, int height); + void (*reformat)(struct content *c, int width, int height); void (*destroy)(struct content *c); - void (*redraw)(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long clip_x0, long clip_y0, long clip_x1, long clip_y1, + void (*redraw)(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, float scale); void (*add_instance)(struct content *c, struct browser_window *bw, struct content *page, struct box *box, @@ -104,39 +141,39 @@ struct handler_entry { /** 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_revive, + {html_create, html_process_data, html_convert, html_reformat, html_destroy, html_redraw, html_add_instance, html_remove_instance, html_reshape_instance}, {textplain_create, html_process_data, textplain_convert, - 0, 0, 0, 0, 0, 0, 0}, - {0, 0, css_convert, css_revive, 0, css_destroy, 0, 0, 0, 0}, + 0, 0, 0, 0, 0, 0}, + {0, 0, css_convert, 0, css_destroy, 0, 0, 0, 0}, #ifdef WITH_JPEG - {nsjpeg_create, 0, nsjpeg_convert, 0, + {nsjpeg_create, 0, nsjpeg_convert, 0, nsjpeg_destroy, nsjpeg_redraw, 0, 0, 0}, #endif #ifdef WITH_GIF - {nsgif_create, 0, nsgif_convert, 0, + {nsgif_create, 0, nsgif_convert, 0, nsgif_destroy, nsgif_redraw, 0, 0, 0}, #endif #ifdef WITH_PNG - {nspng_create, nspng_process_data, nspng_convert, 0, + {nspng_create, nspng_process_data, nspng_convert, 0, nspng_destroy, nspng_redraw, 0, 0, 0}, #endif #ifdef WITH_SPRITE - {sprite_create, sprite_process_data, sprite_convert, sprite_revive, - sprite_reformat, sprite_destroy, sprite_redraw, 0, 0, 0}, + {sprite_create, sprite_process_data, sprite_convert, + 0, sprite_destroy, sprite_redraw, 0, 0, 0}, #endif #ifdef WITH_DRAW - {0, 0, draw_convert, 0, + {0, 0, draw_convert, 0, draw_destroy, draw_redraw, 0, 0, 0}, #endif #ifdef WITH_PLUGIN - {plugin_create, plugin_process_data, plugin_convert, plugin_revive, + {plugin_create, plugin_process_data, plugin_convert, plugin_reformat, plugin_destroy, plugin_redraw, plugin_add_instance, plugin_remove_instance, plugin_reshape_instance}, #endif - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + {0, 0, 0, 0, 0, 0, 0, 0, 0} }; #define HANDLER_MAP_COUNT (sizeof(handler_map) / sizeof(handler_map[0])) @@ -166,33 +203,62 @@ content_type content_lookup(const char *mime_type) /** * Create a new content structure. * + * \param url URL of content, copied + * \return the new content structure, or 0 on memory exhaustion + * * The type is initialised to CONTENT_UNKNOWN, and the status to * CONTENT_STATUS_TYPE_UNKNOWN. */ -struct content * content_create(char *url) +struct content * content_create(const char *url) { struct content *c; struct content_user *user_sentinel; LOG(("url %s", url)); - c = xcalloc(1, sizeof(struct content)); - c->url = xstrdup(url); + c = malloc(sizeof(struct content)); + if (!c) + return 0; + user_sentinel = malloc(sizeof *user_sentinel); + if (!user_sentinel) { + free(c); + return 0; + } + c->url = strdup(url); + if (!c->url) { + free(c); + free(user_sentinel); + return 0; + } c->type = CONTENT_UNKNOWN; + c->mime_type = 0; c->status = CONTENT_STATUS_TYPE_UNKNOWN; + c->width = 0; + c->height = 0; + c->available_width = 0; c->cache = 0; c->size = sizeof(struct content); - c->fetch = 0; - c->source_data = 0; - c->source_size = 0; - c->mime_type = 0; - content_set_status(c, messages_get("Loading")); - user_sentinel = xcalloc(1, sizeof(*user_sentinel)); + c->title = 0; + c->active = 0; user_sentinel->callback = 0; user_sentinel->p1 = user_sentinel->p2 = 0; user_sentinel->next = 0; c->user_list = user_sentinel; + content_set_status(c, messages_get("Loading")); + c->fetch = 0; + c->source_data = 0; + c->source_size = 0; + c->total_size = 0; c->lock = 0; c->destroy_pending = false; + c->no_error_pages = false; + c->error_count = 0; + + c->prev = 0; + c->next = content_list; + if (content_list) + content_list->prev = c; + content_list = c; + return c; } @@ -200,34 +266,51 @@ struct content * content_create(char *url) /** * Initialise the content for the specified type. * + * \param c content structure + * \param type content_type to initialise to + * \param mime_type MIME-type string for this content + * \param params array of strings, ordered attribute, value, attribute, ..., 0 + * \return true on success, false on error and error broadcast to users and + * possibly reported + * * The type is updated to the given type, and a copy of mime_type is taken. The * status is changed to CONTENT_STATUS_LOADING. CONTENT_MSG_LOADING is sent to * all users. The create function for the type is called to initialise the type * specific parts of the content structure. - * - * \param c content structure - * \param type content_type to initialise to - * \param mime_type MIME-type string for this content - * \param params array of strings, ordered attribute, value, attribute, ..., 0 */ -void content_set_type(struct content *c, content_type type, +bool content_set_type(struct content *c, content_type type, const char *mime_type, const char *params[]) { - union content_msg_data data; + union content_msg_data msg_data; + assert(c != 0); assert(c->status == CONTENT_STATUS_TYPE_UNKNOWN); assert(type < CONTENT_UNKNOWN); + LOG(("content %s, type %i", c->url, type)); + + c->mime_type = strdup(mime_type); + if (!c->mime_type) { + c->status = CONTENT_STATUS_ERROR; + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + return false; + } + c->type = type; - c->mime_type = xstrdup(mime_type); c->status = CONTENT_STATUS_LOADING; - c->source_data = xcalloc(0, 1); - if (handler_map[type].create) - handler_map[type].create(c, params); - content_broadcast(c, CONTENT_MSG_LOADING, data); - /* c may be destroyed at this point as a result of - * CONTENT_MSG_LOADING, so must not be accessed */ + + if (handler_map[type].create) { + if (!handler_map[type].create(c, params)) { + c->status = CONTENT_STATUS_ERROR; + return false; + } + } + + content_broadcast(c, CONTENT_MSG_LOADING, msg_data); + return true; } @@ -255,19 +338,44 @@ void content_set_status(struct content *c, const char *status_message, ...) * Process a block of source data. * * Calls the process_data function for the content. + * + * \param c content structure + * \param data new data to process + * \param size size of data + * \return true on success, false on error and error broadcast to users and + * possibly reported */ -void content_process_data(struct content *c, char *data, unsigned long size) +bool content_process_data(struct content *c, char *data, unsigned int size) { - assert(c != 0); + char *source_data; + union content_msg_data msg_data; + + assert(c); + assert(c->type < HANDLER_MAP_COUNT); assert(c->status == CONTENT_STATUS_LOADING); - LOG(("content %s, size %lu", c->url, size)); - c->source_data = xrealloc(c->source_data, c->source_size + size); + LOG(("content %s, size %u", c->url, size)); + + source_data = realloc(c->source_data, c->source_size + size); + if (!source_data) { + c->status = CONTENT_STATUS_ERROR; + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + return false; + } + c->source_data = source_data; memcpy(c->source_data + c->source_size, data, size); c->source_size += size; c->size += size; - if (handler_map[c->type].process_data) - handler_map[c->type].process_data(c, data, size); + + if (handler_map[c->type].process_data) { + if (!handler_map[c->type].process_data(c, data, size)) { + c->status = CONTENT_STATUS_ERROR; + return false; + } + } + return true; } @@ -281,54 +389,34 @@ void content_process_data(struct content *c, char *data, unsigned long size) * CONTENT_MSG_READY is sent to all users. * - If the conversion succeeds and is complete, the content gets status * CONTENT_STATUS_DONE, and CONTENT_MSG_READY then CONTENT_MSG_DONE are sent. - * - If the conversion fails, CONTENT_MSG_ERROR is sent. The content is then - * destroyed and must no longer be used. + * - If the conversion fails, CONTENT_MSG_ERROR is sent. The content will soon + * be destroyed and must no longer be used. */ -void content_convert(struct content *c, unsigned long width, unsigned long height) +void content_convert(struct content *c, int width, int height) { - union content_msg_data data; - assert(c != 0); + union content_msg_data msg_data; + + assert(c); assert(c->type < HANDLER_MAP_COUNT); assert(c->status == CONTENT_STATUS_LOADING); LOG(("content %s", c->url)); + c->available_width = width; if (handler_map[c->type].convert) { - if (handler_map[c->type].convert(c, width, height)) { - /* convert failed, destroy content */ - data.error = "Conversion failed"; - content_broadcast(c, CONTENT_MSG_ERROR, data); - if (c->cache) - cache_destroy(c); - content_destroy(c); + if (!handler_map[c->type].convert(c, width, height)) { + c->status = CONTENT_STATUS_ERROR; return; } } else { c->status = CONTENT_STATUS_DONE; } + assert(c->status == CONTENT_STATUS_READY || c->status == CONTENT_STATUS_DONE); - content_broadcast(c, CONTENT_MSG_READY, data); + content_broadcast(c, CONTENT_MSG_READY, msg_data); if (c->status == CONTENT_STATUS_DONE) - content_broadcast(c, CONTENT_MSG_DONE, data); -} - - -/** - * Fix content that has been loaded from the cache. - * - * Calls the revive function for the content. The content will be processed for - * display, for example dependencies loaded or reformated to current width. - */ - -void content_revive(struct content *c, unsigned long width, unsigned long height) -{ - assert(0); /* unmaintained */ - assert(c != 0); - if (c->status != CONTENT_STATUS_DONE) - return; - c->available_width = width; - handler_map[c->type].revive(c, width, height); + content_broadcast(c, CONTENT_MSG_DONE, msg_data); } @@ -338,7 +426,7 @@ void content_revive(struct content *c, unsigned long width, unsigned long height * Calls the reformat function for the content. */ -void content_reformat(struct content *c, unsigned long width, unsigned long height) +void content_reformat(struct content *c, int width, int height) { union content_msg_data data; assert(c != 0); @@ -352,6 +440,29 @@ void content_reformat(struct content *c, unsigned long width, unsigned long heig } +/** + * Destroys any contents in the content_list with no users or in + * CONTENT_STATUS_ERROR, and not with an active fetch or cached. + */ + +void content_clean(void) +{ + struct content *c, *next; + + for (c = content_list; c; c = next) { + next = c->next; + if (((!c->user_list->next && !c->cache) || + c->status == CONTENT_STATUS_ERROR) && + !c->fetch) { + LOG(("%p %s", c, c->url)); + if (c->cache) + cache_destroy(c); + content_destroy(c); + } + } +} + + /** * Destroy and free a content. * @@ -371,6 +482,13 @@ void content_destroy(struct content *c) return; } + if (c->next) + c->next->prev = c->prev; + if (c->prev) + c->prev->next = c->next; + else + content_list = c->next; + if (c->type < HANDLER_MAP_COUNT && handler_map[c->type].destroy) handler_map[c->type].destroy(c); for (user = c->user_list; user != 0; user = next) { @@ -411,9 +529,9 @@ void content_reset(struct content *c) * Calls the redraw function for the content, if it exists. */ -void content_redraw(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long clip_x0, long clip_y0, long clip_x1, long clip_y1, +void content_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, float scale) { assert(c != 0); @@ -570,3 +688,9 @@ void content_reshape_instance(struct content *c, struct browser_window *bw, handler_map[c->type].reshape_instance(c, bw, page, box, params, state); } + + +void content_add_error(struct content *c, const char *token, + unsigned int line) +{ +} diff --git a/content/content.h b/content/content.h index 13c4092ce..3fcbd39fe 100644 --- a/content/content.h +++ b/content/content.h @@ -14,12 +14,73 @@ * Each content has a type. The type is used to call a specific implementation * of functions such as content_process_data(). * + * The source data fetched from the URL is placed in the source_data buffer as + * it arrives. + * * Contents have an associated set of users, which are informed by a callback * when the state of the content changes or something interesting happens. * * Optionally, contents may have instances (depending on type). Instances * represent copies of the same URL, for example if a page is open in two * windows, or a page contains the same image twice. + * + * The status of a content follows a fixed order. Certain content functions + * change the state, and each change of state results in a message to all users + * of the content. The diagram below shows this: + * \dot + * digraph status { + * node [shape=plaintext, fontname=Helvetica, fontsize=9]; + * edge [fontname=Helvetica, fontsize=9]; + * + * content_create -> TYPE_UNKNOWN [style=bold]; + * TYPE_UNKNOWN -> content_set_type [style=bold]; + * content_set_type -> LOADING [label=MSG_LOADING, style=bold]; + * content_set_type -> ERROR [label=MSG_ERROR]; + * LOADING -> content_process_data [style=bold]; + * content_process_data -> LOADING [style=bold]; + * content_process_data -> ERROR [label=MSG_ERROR]; + * LOADING -> content_convert [style=bold]; + * content_convert -> READY [label=MSG_READY, style=bold]; + * content_convert -> DONE [label="MSG_READY\nMSG_DONE", style=bold]; + * content_convert -> ERROR [label=MSG_ERROR]; + * READY -> READY [style=bold]; + * READY -> DONE [label=MSG_DONE, style=bold]; + * + * TYPE_UNKNOWN [shape=ellipse]; + * LOADING [shape=ellipse]; + * READY [shape=ellipse]; + * DONE [shape=ellipse]; + * ERROR [shape=ellipse]; + * } + * \enddot + * + * To implement a new content type, implement the following functions: + * + * - type_create(): called to initialise type-specific fields in the + * content structure. Optional. + * + * - type_process_data(): called when some data arrives. Optional. + * + * - type_convert(): called when data has finished arriving. The + * content needs to be converted for display. Must set the status to one of + * CONTENT_STATUS_READY or CONTENT_STATUS_DONE if no error occurs. Optional, + * but probably required for non-trivial types. + * + * - type_reformat(): called when, for example, the window has been + * resized, and the content needs reformatting for the new size. Optional. + * + * - type_destroy(): called when the content is being destroyed. Free all + * resources. Optional. + * + * - type_redraw(): called to plot the content to screen. + * + * - type_(add|remove|reshape)_instance: ask James, this will probably + * be redesigned sometime. + * + * - type_create(), type_process_data(), type_convert(): + * if an error occurs, must broadcast CONTENT_MSG_ERROR and return false. + * Optionally use warn_user() for serious errors. The _destroy function will + * be called soon after. */ #ifndef _NETSURF_DESKTOP_CONTENT_H_ @@ -111,7 +172,9 @@ struct content { converted and is not safe to display. */ CONTENT_STATUS_READY, /**< Some parts of content still being loaded, but can be displayed. */ - CONTENT_STATUS_DONE /**< All finished. */ + CONTENT_STATUS_DONE, /**< All finished. */ + CONTENT_STATUS_ERROR /**< Error occurred, content will be + destroyed imminently. */ } status; /**< Current status. */ int width, height; /**< Dimensions, if applicable. */ @@ -147,7 +210,6 @@ struct content { char *title; /**< Title for browser window. */ unsigned int active; /**< Number of child fetches or conversions currently in progress. */ - int error; /**< Non-0 if an error has occurred. */ struct content_user *user_list; /**< List of users. */ char status_message[80]; /**< Text for status bar. */ @@ -159,26 +221,40 @@ struct content { int lock; /**< Content in use, do not destroy. */ bool destroy_pending; /**< Destroy when lock returns to 0. */ bool no_error_pages; /**< Used by fetchcache(). */ + + /** Array of first n rendering errors or warnings. */ + struct { + const char *token; + unsigned int line; /**< Line no, 0 if not applicable. */ + } error_list[40]; + unsigned int error_count; /**< Number of valid error entries. */ + + struct content *prev; /**< Previous in global content list. */ + struct content *next; /**< Next in global content list. */ }; +extern struct content *content_list; +extern const char *content_type_name[]; +extern const char *content_status_name[]; + struct browser_window; content_type content_lookup(const char *mime_type); -struct content * content_create(char *url); -void content_set_type(struct content *c, content_type type, +struct content * content_create(const char *url); +bool content_set_type(struct content *c, content_type type, const char *mime_type, const char *params[]); void content_set_status(struct content *c, const char *status_message, ...); -void content_process_data(struct content *c, char *data, unsigned long size); -void content_convert(struct content *c, unsigned long width, unsigned long height); -void content_revive(struct content *c, unsigned long width, unsigned long height); -void content_reformat(struct content *c, unsigned long width, unsigned long height); +bool content_process_data(struct content *c, char *data, unsigned int size); +void content_convert(struct content *c, int width, int height); +void content_reformat(struct content *c, int width, int height); +void content_clean(void); void content_destroy(struct content *c); void content_reset(struct content *c); -void content_redraw(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long clip_x0, long clip_y0, long clip_x1, long clip_y1, +void content_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, float scale); void content_add_user(struct content *c, void (*callback)(content_msg msg, struct content *c, void *p1, @@ -199,5 +275,7 @@ void content_remove_instance(struct content *c, struct browser_window *bw, void content_reshape_instance(struct content *c, struct browser_window *bw, struct content *page, struct box *box, struct object_params *params, void **state); +void content_add_error(struct content *c, const char *token, + unsigned int line); #endif diff --git a/content/fetch.c b/content/fetch.c index c8630f343..52d7effc5 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -31,9 +31,6 @@ #include "curl/curl.h" #include "netsurf/utils/config.h" #include "netsurf/content/fetch.h" -#ifdef riscos -#include "netsurf/desktop/gui.h" -#endif #include "netsurf/desktop/options.h" #ifdef WITH_AUTH #include "netsurf/desktop/401login.h" @@ -587,6 +584,11 @@ size_t fetch_curl_data(void * data, size_t size, size_t nmemb, struct fetch *f) /* send data to the caller */ LOG(("FETCH_DATA")); f->callback(FETCH_DATA, f->p, data, size * nmemb); + if (f->aborting) { + f->locked--; + f->stopped = true; + return 0; + } f->locked--; return size * nmemb; diff --git a/content/fetchcache.c b/content/fetchcache.c index 164a11231..359b59809 100644 --- a/content/fetchcache.c +++ b/content/fetchcache.c @@ -59,7 +59,7 @@ static void fetchcache_error_page(struct content *c, const char *error); * \param post_urlenc url encoded post data, or 0 if none * \param post_multipart multipart post data, or 0 if none * \param cookies send and accept cookies - * \return a new content, or 0 if an error occurred and no_error_pages is true + * \return a new content, or 0 if an error occurred */ struct content * fetchcache(const char *url, char *referer, @@ -77,12 +77,16 @@ struct content * fetchcache(const char *url, char *referer, ) { struct content *c; - char *url1 = xstrdup(url); - char *hash = strchr(url1, '#'); + char *url1; + char *hash; char error_message[500]; + url1 = strdup(url); + if (!url1) + return 0; + /* strip fragment identifier */ - if (hash != 0) + if ((hash = strchr(url1, '#'))) *hash = 0; LOG(("url %s", url1)); @@ -100,6 +104,10 @@ struct content * fetchcache(const char *url, char *referer, } c = content_create(url1); + if (!c) { + free(url1); + return 0; + } content_add_user(c, callback, p1, p2); #ifdef WITH_POST @@ -118,12 +126,10 @@ struct content * fetchcache(const char *url, char *referer, ,cookies #endif ); - if (c->fetch == 0) { + if (!c->fetch) { LOG(("warning: fetch_start failed")); - if (c->cache) - cache_destroy(c); + c->status = CONTENT_STATUS_ERROR; if (no_error_pages) { - content_destroy(c); free(url1); return 0; } @@ -144,6 +150,7 @@ struct content * fetchcache(const char *url, char *referer, void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size) { + bool res; struct content *c = p; content_type type; char *mime_type, *url; @@ -159,11 +166,13 @@ void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size) mime_type = fetchcache_parse_type(data, ¶ms); type = content_lookup(mime_type); LOG(("FETCH_TYPE, type %u", type)); - content_set_type(c, type, mime_type, (const char**)params); + res = content_set_type(c, type, mime_type, params); free(mime_type); for (i = 0; params[i]; i++) free(params[i]); free(params); + if (!res) + fetch_abort(c->fetch); if (c->cache && c->type == CONTENT_OTHER) cache_destroy(c); break; @@ -181,7 +190,8 @@ void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size) messages_get("Received"), human_friendly_bytesize(c->source_size + size)); content_broadcast(c, CONTENT_MSG_STATUS, msg_data); - content_process_data(c, data, size); + if (!content_process_data(c, data, size)) + fetch_abort(c->fetch); break; case FETCH_FINISHED: @@ -199,9 +209,10 @@ void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size) if (c->cache) cache_destroy(c); if (c->no_error_pages) { + c->status = CONTENT_STATUS_ERROR; msg_data.error = data; - content_broadcast(c, CONTENT_MSG_ERROR, msg_data); - content_destroy(c); + content_broadcast(c, CONTENT_MSG_ERROR, + msg_data); } else { content_reset(c); fetchcache_error_page(c, data); @@ -233,15 +244,15 @@ void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size) c->fetch = 0; msg_data.auth_realm = data; content_broadcast(c, CONTENT_MSG_AUTH, msg_data); - cache_destroy(c); + if (c->cache) + cache_destroy(c); break; #endif default: assert(0); } - if (--(c->lock) == 0 && c->destroy_pending) - content_destroy(c); + c->lock--; } diff --git a/css/css.c b/css/css.c index c42ad3d21..8239d77bf 100644 --- a/css/css.c +++ b/css/css.c @@ -87,6 +87,7 @@ #include "netsurf/desktop/gui.h" #endif #include "netsurf/utils/log.h" +#include "netsurf/utils/messages.h" #include "netsurf/utils/url.h" #include "netsurf/utils/utils.h" @@ -241,7 +242,7 @@ const struct css_style css_blank_style = { * Convert a CONTENT_CSS for use. */ -int css_convert(struct content *c, unsigned int width, unsigned int height) +bool css_convert(struct content *c, int width, int height) { unsigned char *source_data; unsigned char *current, *end, *token_text; @@ -250,6 +251,7 @@ int css_convert(struct content *c, unsigned int width, unsigned int height) void *parser; struct css_parser_params param = {false, c, 0, false, false}; struct css_parser_token token_data; + union content_msg_data msg_data; c->data.css.css = malloc(sizeof *c->data.css.css); parser = css_parser_Alloc(malloc); @@ -258,7 +260,11 @@ int css_convert(struct content *c, unsigned int width, unsigned int height) if (!c->data.css.css || !parser || !source_data) { free(c->data.css.css); css_parser_Free(parser, free); - return 1; + + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + return false; } for (i = 0; i != HASH_SIZE; i++) @@ -292,8 +298,12 @@ int css_convert(struct content *c, unsigned int width, unsigned int height) css_parser_(parser, 0, token_data, ¶m); css_parser_Free(parser, free); - if (param.memory_error) - return 1; + if (param.memory_error) { + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + return false; + } /*css_dump_stylesheet(c->data.css.css);*/ @@ -305,35 +315,7 @@ int css_convert(struct content *c, unsigned int width, unsigned int height) } c->status = CONTENT_STATUS_DONE; - return 0; -} - - -void css_revive(struct content *c, unsigned int width, unsigned int height) -{ - unsigned int i; - /* imported stylesheets */ - for (i = 0; i != c->data.css.import_count; i++) { - c->data.css.import_content[i] = fetchcache( - c->data.css.import_url[i], c->url, - css_atimport_callback, c, (void*)i, - c->width, c->height, true -#ifdef WITH_POST - , 0, 0 -#endif -#ifdef WITH_COOKIES - , false -#endif - ); - if (c->data.css.import_content[i] == 0) - continue; - if (c->data.css.import_content[i]->status != CONTENT_STATUS_DONE) - c->active++; - } - while (c->active != 0) { - fetch_poll(); - gui_multitask(); - } + return true; } @@ -371,6 +353,7 @@ void css_destroy(struct content *c) /** * Create a new struct css_node. * + * \param stylesheet content of type CONTENT_CSS * \param type type of node * \param data string for data, not copied * \param data_length length of data @@ -610,7 +593,7 @@ void css_atimport_callback(content_msg msg, struct content *css, content_remove_user(css, css_atimport_callback, c, (void*)i); c->data.css.import_content[i] = 0; c->active--; - c->error = 1; + content_add_error(c, "NotCSS", 0); } break; @@ -626,7 +609,7 @@ void css_atimport_callback(content_msg msg, struct content *css, case CONTENT_MSG_ERROR: c->data.css.import_content[i] = 0; c->active--; - c->error = 1; + content_add_error(c, "?", 0); break; case CONTENT_MSG_STATUS: @@ -638,7 +621,7 @@ void css_atimport_callback(content_msg msg, struct content *css, c->data.css.import_url[i] = strdup(data.redirect); if (!c->data.css.import_url[i]) { /** \todo report to user */ - c->error = 1; + /* c->error = 1; */ return; } c->data.css.import_content[i] = fetchcache( @@ -996,9 +979,41 @@ void css_dump_style(const struct css_style * const style) if (style->z != css_empty_style.z) \ fprintf(stderr, s ": %s; ", n[style->z]); - DUMP_KEYWORD(background_attachment, "background-attachment", css_background_attachment_name); DUMP_COLOR(background_color, "background-color"); - DUMP_KEYWORD(background_repeat, "background-repeat", css_background_repeat_name); + if (style->background_attachment != + css_empty_style.background_attachment || + style->background_image.type != + css_empty_style.background_image.type || + style->background_position.horz.pos != + css_empty_style.background_position.horz.pos || + style->background_position.vert.pos != + css_empty_style.background_position.vert.pos || + style->background_repeat != + css_empty_style.background_repeat) { + fprintf(stderr, "background: "); + switch (style->background_image.type) { + case CSS_BACKGROUND_IMAGE_NONE: + fprintf(stderr, "none"); + break; + case CSS_BACKGROUND_IMAGE_INHERIT: + fprintf(stderr, "inherit"); + break; + case CSS_BACKGROUND_IMAGE_URI: + fprintf(stderr, "(%p) \"%s\"", + style->background_image.uri, + style->background_image.uri); + break; + default: + fprintf(stderr, "UNKNOWN"); + break; + } + fprintf(stderr, " %s %s ", + css_background_attachment_name[ + style->background_attachment], + css_background_repeat_name[ + style->background_repeat]); + fprintf(stderr, "; "); + } DUMP_KEYWORD(clear, "clear", css_clear_name); DUMP_COLOR(color, "color"); DUMP_KEYWORD(cursor, "cursor", css_cursor_name); @@ -1078,7 +1093,7 @@ void css_dump_style(const struct css_style * const style) if (style->margin[0].margin != css_empty_style.margin[0].margin || style->margin[1].margin != css_empty_style.margin[1].margin || style->margin[2].margin != css_empty_style.margin[2].margin || - style->margin[3].margin != css_empty_style.margin[3].margin) { + style->margin[3].margin != css_empty_style.margin[3].margin) { fprintf(stderr, "margin:"); for (i = 0; i != 4; i++) { switch (style->margin[i].margin) { @@ -1152,19 +1167,19 @@ void css_dump_style(const struct css_style * const style) if (style->text_indent.size != css_empty_style.text_indent.size) { fprintf(stderr, "text-indent: "); switch (style->text_indent.size) { - case CSS_TEXT_INDENT_LENGTH: - css_dump_length(&style->text_indent.value.length); - break; - case CSS_TEXT_INDENT_PERCENT: - fprintf(stderr, "%g%%", - style->text_indent.value.percent); - break; - case CSS_TEXT_INDENT_INHERIT: - fprintf(stderr, "inherit"); - break; - default: - fprintf(stderr, "UNKNOWN"); - break; + case CSS_TEXT_INDENT_LENGTH: + css_dump_length(&style->text_indent.value.length); + break; + case CSS_TEXT_INDENT_PERCENT: + fprintf(stderr, "%g%%", + style->text_indent.value.percent); + break; + case CSS_TEXT_INDENT_INHERIT: + fprintf(stderr, "inherit"); + break; + default: + fprintf(stderr, "UNKNOWN"); + break; } fprintf(stderr, "; "); } diff --git a/css/css.h b/css/css.h index d80df9333..e3ebca02e 100644 --- a/css/css.h +++ b/css/css.h @@ -311,8 +311,7 @@ struct css_parser_token { struct content; -int css_convert(struct content *c, unsigned int width, unsigned int height); -void css_revive(struct content *c, unsigned int width, unsigned int height); +bool css_convert(struct content *c, int width, int height); void css_destroy(struct content *c); #ifdef CSS_INTERNALS @@ -340,6 +339,7 @@ void *css_parser_Alloc(void *(*mallocProc)(/*size_t*/ int)); void css_parser_Free(void *p, void (*freeProc)(void*)); void css_parser_(void *yyp, int yymajor, struct css_parser_token yyminor, struct css_parser_params *param); +const char *css_parser_TokenName(int tokenType); #endif diff --git a/debug/netsurfd.c b/debug/netsurfd.c index fefc5d483..417af1d50 100644 --- a/debug/netsurfd.c +++ b/debug/netsurfd.c @@ -119,9 +119,9 @@ void plugin_decode(void *a, void *b, void *c, void *d) } #endif -void html_redraw(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long x0, long y0, long x1, long y1, +void html_redraw(struct content *c, int x, int y, + int width, int height, + int x0, int y0, int x1, int y1, float scale) { } @@ -262,9 +262,9 @@ extern os_t os_read_monotonic_time(void) } #endif -void warn_user(const char *warn) +void warn_user(const char *warning, const char *detail) { - printf("WARNING: %s\n", warn); + printf("WARNING: %s %s\n", warning, detail); } void *ro_gui_current_redraw_gui = 0; diff --git a/desktop/browser.c b/desktop/browser.c index 8f1bb9a0c..2c8c28441 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -260,6 +260,7 @@ void browser_window_callback(content_msg msg, struct content *c, case CONTENT_MSG_ERROR: browser_window_set_status(bw, data.error); + warn_user(data.error, 0); if (c == bw->loading_content) bw->loading_content = 0; else if (c == bw->current_content) diff --git a/desktop/gui.h b/desktop/gui.h index d7f98609d..f388f2d7d 100644 --- a/desktop/gui.h +++ b/desktop/gui.h @@ -62,6 +62,4 @@ void gui_window_place_caret(gui_window *g, int x, int y, int height); void gui_launch_url(const char *url); -void warn_user(const char *warning, const char *detail); - #endif diff --git a/desktop/netsurf.c b/desktop/netsurf.c index 106a33193..21f01177e 100644 --- a/desktop/netsurf.c +++ b/desktop/netsurf.c @@ -54,6 +54,7 @@ void netsurf_init(int argc, char** argv) struct utsname utsname; stdout = stderr; + curl_memdebug("memdump"); if (uname(&utsname) != 0) LOG(("Failed to extract machine information\n")); else @@ -63,12 +64,6 @@ void netsurf_init(int argc, char** argv) fetch_init(); cache_init(); fetchcache_init(); -#ifdef WITH_PNG - nspng_init(); -#endif -#ifdef WITH_GIF - nsgif_init(); -#endif url_init(); } @@ -79,8 +74,9 @@ void netsurf_init(int argc, char** argv) void netsurf_poll(void) { - gui_poll(fetch_active); - fetch_poll(); + content_clean(); + gui_poll(fetch_active); + fetch_poll(); } diff --git a/makefile b/makefile index 93940fa2a..22573d354 100644 --- a/makefile +++ b/makefile @@ -24,13 +24,13 @@ OBJECTS_COMMON += imagemap.o loginlist.o options.o # desktop/ OBJECTS_RISCOS = $(OBJECTS_COMMON) OBJECTS_RISCOS += browser.o netsurf.o version.o # desktop/ -OBJECTS_RISCOS += 401login.o about.o constdata.o dialog.o download.o \ - draw.o filetype.o font.o gif.o gifread.o gui.o help.o \ - history.o htmlinstance.o htmlredraw.o jpeg.o menus.o \ - mouseactions.o plugin.o png.o save.o save_complete.o \ - save_draw.o save_text.o schedule.o sprite.o \ - textselection.o theme.o thumbnail.o toolbar.o uri.o \ - url_protocol.o wimp.o window.o # riscos/ +OBJECTS_RISCOS += 401login.o about.o constdata.o debugwin.o \ + dialog.o download.o draw.o filetype.o font.o gif.o \ + gifread.o gui.o help.o history.o htmlinstance.o \ + htmlredraw.o jpeg.o menus.o mouseactions.o plugin.o \ + png.o save.o save_complete.o save_draw.o save_text.o \ + schedule.o sprite.o textselection.o theme.o thumbnail.o \ + toolbar.o uri.o url_protocol.o wimp.o window.o # riscos/ OBJECTS_DEBUG = $(OBJECTS_COMMON) OBJECTS_DEBUG += filetyped.o fontd.o netsurfd.o # debug/ diff --git a/render/html.c b/render/html.c index f3d19a072..d39dd32da 100644 --- a/render/html.c +++ b/render/html.c @@ -51,10 +51,11 @@ static bool html_object_type_permitted(const content_type type, * created. */ -void html_create(struct content *c, const char *params[]) +bool html_create(struct content *c, const char *params[]) { unsigned int i; struct content_html_data *html = &c->data.html; + union content_msg_data msg_data; xmlCharEncoding encoding = XML_CHAR_ENCODING_NONE; html->encoding = NULL; @@ -74,7 +75,7 @@ void html_create(struct content *c, const char *params[]) } html->parser = htmlCreatePushParserCtxt(0, 0, "", 0, 0, encoding); - html->base_url = xstrdup(c->url); + html->base_url = strdup(c->url); html->layout = 0; html->background_colour = TRANSPARENT; html->stylesheet_count = 0; @@ -85,9 +86,24 @@ void html_create(struct content *c, const char *params[]) html->object = 0; html->imagemaps = 0; html->string_pool = pool_create(8000); - assert(html->string_pool); html->box_pool = pool_create(sizeof (struct box) * 100); - assert(html->box_pool); + + if (!html->parser || !html->base_url || !html->string_pool || + !html->box_pool) { + htmlFreeParserCtxt(html->parser); + free(html->base_url); + if (html->string_pool) + pool_destroy(html->string_pool); + if (html->box_pool) + pool_destroy(html->box_pool); + + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + return false; + } + + return true; } @@ -97,7 +113,7 @@ void html_create(struct content *c, const char *params[]) * The data is parsed in chunks of size CHUNK, multitasking in between. */ -void html_process_data(struct content *c, char *data, unsigned long size) +bool html_process_data(struct content *c, char *data, unsigned int size) { unsigned long x; @@ -120,6 +136,8 @@ void html_process_data(struct content *c, char *data, unsigned long size) gui_multitask(); } htmlParseChunk(c->data.html.parser, data + x, (int) (size - x), 0); + + return true; } @@ -138,11 +156,11 @@ void html_process_data(struct content *c, char *data, unsigned long size) * being fetched. */ -int html_convert(struct content *c, unsigned int width, unsigned int height) +bool html_convert(struct content *c, int width, int height) { xmlDoc *document; xmlNode *html, *head; - union content_msg_data data; + union content_msg_data msg_data; /* finish parsing */ htmlParseChunk(c->data.html.parser, "", 0, 1); @@ -150,9 +168,12 @@ int html_convert(struct content *c, unsigned int width, unsigned int height) /*xmlDebugDumpDocument(stderr, c->data.html.parser->myDoc);*/ htmlFreeParserCtxt(c->data.html.parser); c->data.html.parser = 0; - if (document == NULL) { + if (!document) { LOG(("Parsing failed")); - return 1; + msg_data.error = messages_get("ParsingFail"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("ParsingFail", 0); + return false; } /* Last change to pick the Content-Type charset information if the * server didn't send it (or we're reading the HTML from disk) @@ -168,7 +189,10 @@ int html_convert(struct content *c, unsigned int width, unsigned int height) if (html == 0 || strcmp((const char *) html->name, "html") != 0) { LOG(("html element not found")); xmlFreeDoc(document); - return 1; + msg_data.error = messages_get("ParsingFail"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("ParsingFail", 0); + return false; } for (head = html->children; head != 0 && head->type != XML_ELEMENT_NODE; @@ -188,7 +212,7 @@ int html_convert(struct content *c, unsigned int width, unsigned int height) /* convert xml tree to box tree */ LOG(("XML to box")); content_set_status(c, messages_get("Processing")); - content_broadcast(c, CONTENT_MSG_STATUS, data); + content_broadcast(c, CONTENT_MSG_STATUS, msg_data); xml_to_box(html, c); /*box_dump(c->data.html.layout->children, 0);*/ @@ -201,7 +225,7 @@ int html_convert(struct content *c, unsigned int width, unsigned int height) /* layout the box tree */ content_set_status(c, messages_get("Formatting")); - content_broadcast(c, CONTENT_MSG_STATUS, data); + content_broadcast(c, CONTENT_MSG_STATUS, msg_data); LOG(("Layout document")); layout_document(c->data.html.layout->children, width, c->data.html.box_pool); @@ -218,7 +242,7 @@ int html_convert(struct content *c, unsigned int width, unsigned int height) content_set_status(c, messages_get("FetchObjs"), c->active); } - return 0; + return true; } @@ -281,7 +305,6 @@ void html_find_stylesheets(struct content *c, xmlNode *head) c->data.html.stylesheet_content[1] = 0; c->data.html.stylesheet_count = 2; - c->error = 0; c->active = 0; c->data.html.stylesheet_content[0] = fetchcache( @@ -396,6 +419,8 @@ void html_find_stylesheets(struct content *c, xmlNode *head) const char *params[] = { 0 }; c->data.html.stylesheet_content[1] = content_create(c->data.html.base_url); + if (!c->data.html.stylesheet_content[1]) + return false; content_set_type(c->data.html.stylesheet_content[1], CONTENT_CSS, "text/css", params); } @@ -434,10 +459,10 @@ void html_find_stylesheets(struct content *c, xmlNode *head) gui_multitask(); } - if (c->error) { - content_set_status(c, "Warning: some stylesheets failed to load"); - content_broadcast(c, CONTENT_MSG_STATUS, msg_data); - } +/* if (c->error) { */ +/* content_set_status(c, "Warning: some stylesheets failed to load"); */ +/* content_broadcast(c, CONTENT_MSG_STATUS, msg_data); */ +/* } */ } @@ -457,7 +482,7 @@ void html_convert_css_callback(content_msg msg, struct content *css, if (css->type != CONTENT_CSS) { c->data.html.stylesheet_content[i] = 0; c->active--; - c->error = 1; + content_add_error(c, "NotCSS", 0); content_set_status(c, messages_get("NotCSS")); content_broadcast(c, CONTENT_MSG_STATUS, data); content_remove_user(css, html_convert_css_callback, c, (void*)i); @@ -475,7 +500,7 @@ void html_convert_css_callback(content_msg msg, struct content *css, case CONTENT_MSG_ERROR: c->data.html.stylesheet_content[i] = 0; c->active--; - c->error = 1; + content_add_error(c, "?", 0); break; case CONTENT_MSG_STATUS: @@ -506,7 +531,7 @@ void html_convert_css_callback(content_msg msg, struct content *css, case CONTENT_MSG_AUTH: c->data.html.stylesheet_content[i] = 0; c->active--; - c->error = 1; + content_add_error(c, "?", 0); break; #endif @@ -590,7 +615,7 @@ void html_object_callback(content_msg msg, struct content *object, /* not acceptable */ c->data.html.object[i].content = 0; c->active--; - c->error = 1; + content_add_error(c, "?", 0); content_set_status(c, messages_get("BadObject")); content_broadcast(c, CONTENT_MSG_STATUS, data); content_remove_user(object, html_object_callback, c, (void*)i); @@ -611,7 +636,7 @@ void html_object_callback(content_msg msg, struct content *object, case CONTENT_MSG_ERROR: c->data.html.object[i].content = 0; c->active--; - c->error = 1; + content_add_error(c, "?", 0); content_set_status(c, messages_get("ObjError"), data.error); content_broadcast(c, CONTENT_MSG_STATUS, data); @@ -674,7 +699,7 @@ void html_object_callback(content_msg msg, struct content *object, case CONTENT_MSG_AUTH: c->data.html.object[i].content = 0; c->active--; - c->error = 1; + content_add_error(c, "?", 0); break; #endif @@ -754,47 +779,11 @@ bool html_object_type_permitted(const content_type type, } -void html_revive(struct content *c, unsigned int width, unsigned int height) -{ - unsigned int i; - - assert(0); /* dead code, do not use as is */ - - /* reload objects and fix pointers */ - for (i = 0; i != c->data.html.object_count; i++) { - if (c->data.html.object[i].content != 0) { - c->data.html.object[i].content = fetchcache( - c->data.html.object[i].url, c->url, - html_object_callback, - c, (void*)i, 0, 0, true -#ifdef WITH_POST - , 0, 0 -#endif -#ifdef WITH_COOKIES - , false -#endif - ); - if (c->data.html.object[i].content && - c->data.html.object[i].content->status != CONTENT_STATUS_DONE) - c->active++; - } - } - - layout_document(c->data.html.layout->children, width, - c->data.html.box_pool); - c->width = c->data.html.layout->children->width; - c->height = c->data.html.layout->children->height; - - if (c->active != 0) - c->status = CONTENT_STATUS_READY; -} - - /** * Reformat a CONTENT_HTML to a new width. */ -void html_reformat(struct content *c, unsigned int width, unsigned int height) +void html_reformat(struct content *c, int width, int height) { layout_document(c->data.html.layout->children, width, c->data.html.box_pool); diff --git a/render/html.h b/render/html.h index 683c5dc73..9580beacb 100644 --- a/render/html.h +++ b/render/html.h @@ -83,11 +83,10 @@ struct content_html_data { }; -void html_create(struct content *c, const char *params[]); -void html_process_data(struct content *c, char *data, unsigned long size); -int html_convert(struct content *c, unsigned int width, unsigned int height); -void html_revive(struct content *c, unsigned int width, unsigned int height); -void html_reformat(struct content *c, unsigned int width, unsigned int height); +bool html_create(struct content *c, const char *params[]); +bool html_process_data(struct content *c, char *data, unsigned int size); +bool html_convert(struct content *c, int width, int height); +void html_reformat(struct content *c, int width, int height); void html_destroy(struct content *c); void html_fetch_object(struct content *c, char *url, struct box *box, const content_type *permitted_types, @@ -106,9 +105,9 @@ void html_remove_instance(struct content *c, struct browser_window *bw, struct object_params *params, void **state); /* in riscos/htmlredraw.c */ -void html_redraw(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long clip_x0, long clip_y0, long clip_x1, long clip_y1, +void html_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, float scale); #endif diff --git a/render/textplain.c b/render/textplain.c index 72ad98a4f..0a7f5db7c 100644 --- a/render/textplain.c +++ b/render/textplain.c @@ -15,14 +15,18 @@ static const char header[] = "
";
 static const char footer[] = "
"; -void textplain_create(struct content *c, const char *params[]) +bool textplain_create(struct content *c, const char *params[]) { - html_create(c, params); + if (!html_create(c, params)) + /* html_create() must have broadcast MSG_ERROR already, so we + * don't need to. */ + return false; htmlParseChunk(c->data.html.parser, header, sizeof(header) - 1, 0); + return true; } -int textplain_convert(struct content *c, unsigned int width, unsigned int height) +bool textplain_convert(struct content *c, int width, int height) { htmlParseChunk(c->data.html.parser, footer, sizeof(footer) - 1, 0); c->type = CONTENT_HTML; diff --git a/render/textplain.h b/render/textplain.h index 859ff9e62..63550e181 100644 --- a/render/textplain.h +++ b/render/textplain.h @@ -10,7 +10,7 @@ struct content; -void textplain_create(struct content *c, const char *params[]); -int textplain_convert(struct content *c, unsigned int width, unsigned int height); +bool textplain_create(struct content *c, const char *params[]); +bool textplain_convert(struct content *c, int width, int height); #endif diff --git a/riscos/dialog.c b/riscos/dialog.c index e59b3ba02..47c279515 100644 --- a/riscos/dialog.c +++ b/riscos/dialog.c @@ -33,7 +33,7 @@ wimp_w dialog_info, dialog_saveas, dialog_config, dialog_config_br, dialog_401li, #endif dialog_zoom, dialog_pageinfo, dialog_objinfo, dialog_tooltip, - dialog_warning, dialog_config_th_pane; + dialog_warning, dialog_config_th_pane, dialog_debug; static int font_size; static int font_min_size; @@ -83,6 +83,7 @@ void ro_gui_dialog_init(void) dialog_objinfo = ro_gui_dialog_create("objectinfo"); dialog_tooltip = ro_gui_dialog_create("tooltip"); dialog_warning = ro_gui_dialog_create("warning"); + dialog_debug = ro_gui_dialog_create("debug"); set_browser_choices(); set_proxy_choices(); diff --git a/riscos/draw.c b/riscos/draw.c index b59a96261..fbe4251cf 100644 --- a/riscos/draw.c +++ b/riscos/draw.c @@ -18,56 +18,47 @@ #ifdef WITH_DRAW -int draw_convert(struct content *c, unsigned int width, unsigned int height) +bool draw_convert(struct content *c, int width, int height) { + union content_msg_data msg_data; + os_box bbox; os_error *error; - os_trfm *matrix = xcalloc(1, sizeof(os_trfm)); - os_box *bbox = xcalloc(1, sizeof(os_box)); - - /* Full size image (1:1) */ - matrix->entries[0][0] = 1 << 16; - matrix->entries[0][1] = 0; - matrix->entries[1][0] = 0; - matrix->entries[1][1] = 1 << 16; - matrix->entries[2][0] = 0; - matrix->entries[2][1] = 0; /* BBox contents in Draw units (256*OS unit) */ error = xdrawfile_bbox(0, (drawfile_diagram*)(c->source_data), - (int)c->source_size, matrix, bbox); - + (int) c->source_size, 0, &bbox); if (error) { - LOG(("error: %s", error->errmess)); - xfree(matrix); - xfree(bbox); - return 1; + LOG(("xdrawfile_bbox: 0x%x: %s", + error->errnum, error->errmess)); + msg_data.error = error->errmess; + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; } /* c->width & c->height stored as (OS units/2) => divide by 512 to convert from draw units */ - c->width = ((bbox->x1 - bbox->x0) / 512); - c->height = ((bbox->y1 - bbox->y0) / 512); - c->data.draw.x0 = bbox->x0 / 2; - c->data.draw.y0 = bbox->y0 / 2; - c->title = xcalloc(100, 1); - sprintf(c->title, messages_get("DrawTitle"), c->width, + c->width = ((bbox.x1 - bbox.x0) / 512); + c->height = ((bbox.y1 - bbox.y0) / 512); + c->data.draw.x0 = bbox.x0 / 2; + c->data.draw.y0 = bbox.y0 / 2; + c->title = malloc(100); + if (c->title) + snprintf(c->title, 100, messages_get("DrawTitle"), c->width, c->height, c->source_size); c->status = CONTENT_STATUS_DONE; - xfree(matrix); - xfree(bbox); - return 0; + return true; } void draw_destroy(struct content *c) { - xfree(c->title); + free(c->title); } -void draw_redraw(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long clip_x0, long clip_y0, long clip_x1, long clip_y1, +void draw_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, float scale) { os_trfm matrix; diff --git a/riscos/draw.h b/riscos/draw.h index bb1f88d3f..67752a3dd 100644 --- a/riscos/draw.h +++ b/riscos/draw.h @@ -14,10 +14,10 @@ struct content_draw_data { int x0, y0; }; -int draw_convert(struct content *c, unsigned int width, unsigned int height); +bool draw_convert(struct content *c, int width, int height); void draw_destroy(struct content *c); -void draw_redraw(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long clip_x0, long clip_y0, long clip_x1, long clip_y1, +void draw_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, float scale); #endif diff --git a/riscos/gif.c b/riscos/gif.c index e15c5ebe4..9cd50829a 100644 --- a/riscos/gif.c +++ b/riscos/gif.c @@ -21,6 +21,7 @@ #include "netsurf/riscos/options.h" #include "netsurf/riscos/tinct.h" #include "netsurf/utils/log.h" +#include "netsurf/utils/messages.h" #include "netsurf/utils/utils.h" @@ -38,19 +39,27 @@ static void nsgif_animate(void *p); -void nsgif_init(void) { -} -void nsgif_create(struct content *c, const char *params[]) { +bool nsgif_create(struct content *c, const char *params[]) { + union content_msg_data msg_data; /* Initialise our data structure */ - c->data.gif.gif = (gif_animation *)xcalloc(sizeof(gif_animation), 1); + c->data.gif.gif = calloc(sizeof(gif_animation), 1); + if (!c->data.gif.gif) { + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + return false; + } c->data.gif.current_frame = 0; + return true; } -int nsgif_convert(struct content *c, unsigned int iwidth, unsigned int iheight) { +bool nsgif_convert(struct content *c, int iwidth, int iheight) { + int res; struct gif_animation *gif; + union content_msg_data msg_data; /* Create our animation */ @@ -61,38 +70,59 @@ int nsgif_convert(struct content *c, unsigned int iwidth, unsigned int iheight) /* Initialise the GIF */ - gif_initialise(gif); + res = gif_initialise(gif); + if (res < 0) { + if (res == GIF_INSUFFICIENT_MEMORY) { + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + } else { + msg_data.error = messages_get("BadGIF"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + } + return false; + } /* Abort on bad GIFs */ - if ((gif->frame_count_partial == 0) || (gif->width == 0) || (gif->height == 0)) return 1; + if ((gif->frame_count_partial == 0) || (gif->width == 0) || + (gif->height == 0)) { + msg_data.error = messages_get("BadGIF"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } /* Store our content width */ c->width = gif->width; c->height = gif->height; + /* Initialise the first frame so if we try to use the image data directly prior to + a plot we get some sensible data + */ + res = gif_decode_frame(c->data.gif.gif, 0); + if (res < 0 && res != GIF_INSUFFICIENT_FRAME_DATA) { + msg_data.error = messages_get("BadGIF"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } + /* Schedule the animation if we have one */ if (gif->frame_count > 1) { schedule(gif->frames[0].frame_delay, nsgif_animate, c); } - /* Initialise the first frame so if we try to use the image data directly prior to - a plot we get some sensible data - */ - gif_decode_frame(c->data.gif.gif, 0); - /* Exit as a success */ c->status = CONTENT_STATUS_DONE; - return 0; + return true; } -void nsgif_redraw(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long clip_x0, long clip_y0, long clip_x1, long clip_y1, +void nsgif_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, float scale) { int previous_frame; @@ -152,7 +182,7 @@ void nsgif_destroy(struct content *c) */ schedule_remove(nsgif_animate, c); gif_finalise(c->data.gif.gif); - xfree(c->data.gif.gif); + free(c->data.gif.gif); } diff --git a/riscos/gif.h b/riscos/gif.h index 526716dec..f6365071a 100644 --- a/riscos/gif.h +++ b/riscos/gif.h @@ -25,13 +25,12 @@ struct content_gif_data { unsigned int current_frame; }; -void nsgif_init(void); -void nsgif_create(struct content *c, const char *params[]); -int nsgif_convert(struct content *c, unsigned int width, unsigned int height); +bool nsgif_create(struct content *c, const char *params[]); +bool nsgif_convert(struct content *c, int width, int height); void nsgif_destroy(struct content *c); -void nsgif_redraw(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long clip_x0, long clip_y0, long clip_x1, long clip_y1, +void nsgif_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, float scale); #endif diff --git a/riscos/gifread.c b/riscos/gifread.c index 3f4306374..3e9d39b69 100644 --- a/riscos/gifread.c +++ b/riscos/gifread.c @@ -96,11 +96,12 @@ static int clear_image = FALSE; any information that hasn't already been decoded. If an error occurs, all previously decoded frames are retained. - @return -5 for GIF frame data error - -4 for insufficient data to process any more frames - -3 for memory error - -2 for GIF error - -1 for insufficient data to do anything + @return GIF_FRAME_DATA_ERROR for GIF frame data error + GIF_INSUFFICIENT_FRAME_DATA for insufficient data to process + any more frames + GIF_INSUFFICIENT_MEMORY for memory error + GIF_DATA_ERROR for GIF error + GIF_INSUFFICIENT_DATA for insufficient data to do anything 0 for successful decoding 1 for successful decoding (all frames completely read) */ @@ -112,7 +113,7 @@ int gif_initialise(struct gif_animation *gif) { /* Check for sufficient data to be a GIF */ - if (gif->buffer_size < 13) return -1; + if (gif->buffer_size < 13) return GIF_INSUFFICIENT_DATA; /* Get our current processing position */ @@ -244,12 +245,12 @@ int gif_initialise(struct gif_animation *gif) { if (gif->frame_count_partial > 0) { /* Set the redraw for the first frame to the maximum frame size */ - gif->frames[0].redraw_required = 0; + gif->frames[0].redraw_required = 0; gif->frames[0].redraw_x = 0; gif->frames[0].redraw_y = 0; gif->frames[0].redraw_width = gif->width; gif->frames[0].redraw_height = gif->height; - + /* We now work backwards to update the redraw characteristics of frames with clear codes to stop a snowball effect of the redraw areas. It doesn't really make much difference for most images, and will not work as well @@ -282,7 +283,7 @@ int gif_initialise(struct gif_animation *gif) { } } } - + } /* If there was a memory error tell the caller @@ -512,7 +513,7 @@ int gif_initialise_frame(struct gif_animation *gif) { gif->frames[frame].redraw_width = width; gif->frames[frame].redraw_height = height; } - + /* if we are clearing the background then we need to redraw enough to cover the previous frame too */ @@ -584,10 +585,10 @@ int gif_initialise_frame(struct gif_animation *gif) { /** Decodes a GIF frame. - @return -5 for GIF frame data error - -4 for insufficient data to complete the frame - -2 for GIF error (invalid frame header) - -1 for insufficient data to do anything + @return GIF_FRAME_DATA_ERROR for GIF frame data error + GIF_INSUFFICIENT_FRAME_DATA for insufficient data to complete the frame + GIF_DATA_ERROR for GIF error (invalid frame header) + GIF_INSUFFICIENT_DATA for insufficient data to do anything 0 for successful decoding */ int gif_decode_frame(struct gif_animation *gif, unsigned int frame) { diff --git a/riscos/gui.c b/riscos/gui.c index 3f33e0581..dc36dd1bf 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -374,7 +374,7 @@ void ro_gui_check_resolvers(void) if (resolvers) { LOG(("Inet$Resolvers '%s'", resolvers)); } else { - LOG(("Inet$Resolvers not set", resolvers)); + LOG(("Inet$Resolvers not set")); warn_user("Resolvers", 0); } } @@ -613,6 +613,8 @@ void ro_gui_redraw_window_request(wimp_draw *redraw) ro_gui_redraw_config_th_pane(redraw); else if (redraw->w == history_window) ro_gui_history_redraw(redraw); + else if (redraw->w == dialog_debug) + ro_gui_debugwin_redraw(redraw); else { g = ro_lookup_gui_from_w(redraw->w); if (g != NULL) @@ -660,6 +662,11 @@ void ro_gui_close_window_request(wimp_close *close) { gui_window *g; + if (close->w == dialog_debug) { + ro_gui_debugwin_close(); + return; + } + g = ro_lookup_gui_from_w(close->w); if (g) { @@ -719,6 +726,8 @@ void ro_gui_icon_bar_click(wimp_pointer *pointer) "file:///%%3CNetSurf$Dir%%3E/Docs/intro_%s", option_language)) >= 0 && length < sizeof(url)) browser_window_create(url, NULL); + } else if (pointer->buttons == wimp_CLICK_ADJUST) { + ro_gui_debugwin_open(); } } diff --git a/riscos/gui.h b/riscos/gui.h index db56bbc77..91839cc76 100644 --- a/riscos/gui.h +++ b/riscos/gui.h @@ -23,7 +23,8 @@ extern wimp_w dialog_info, dialog_saveas, dialog_config, dialog_config_br, dialog_config_prox, dialog_config_th, dialog_zoom, dialog_pageinfo, - dialog_objinfo, dialog_tooltip, dialog_warning, dialog_config_th_pane; + dialog_objinfo, dialog_tooltip, dialog_warning, dialog_config_th_pane, + dialog_debug; extern wimp_w history_window; extern wimp_menu *iconbar_menu, *browser_menu, *combo_menu; extern int iconbar_menu_height; @@ -195,6 +196,11 @@ void schedule(int t, void (*callback)(void *p), void *p); void schedule_remove(void (*callback)(void *p), void *p); void schedule_run(void); +/* in debugwin.c */ +void ro_gui_debugwin_open(void); +void ro_gui_debugwin_close(void); +void ro_gui_debugwin_redraw(wimp_draw *redraw); + /* icon numbers */ #define ICON_TOOLBAR_BACK 0 #define ICON_TOOLBAR_FORWARD 1 diff --git a/riscos/htmlredraw.c b/riscos/htmlredraw.c index 3e40aa6ac..d39acc1f4 100644 --- a/riscos/htmlredraw.c +++ b/riscos/htmlredraw.c @@ -60,9 +60,9 @@ static os_trfm trfm = { { { 0, 0 } } }; -void html_redraw(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long clip_x0, long clip_y0, long clip_x1, long clip_y1, +void html_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, float scale) { bool select_on = false; diff --git a/riscos/jpeg.c b/riscos/jpeg.c index 14128192d..ea8cb120b 100644 --- a/riscos/jpeg.c +++ b/riscos/jpeg.c @@ -40,6 +40,9 @@ #endif +static char nsjpeg_error_buffer[JMSG_LENGTH_MAX]; + + struct nsjpeg_error_mgr { struct jpeg_error_mgr pub; jmp_buf setjmp_buffer; @@ -57,9 +60,10 @@ static void nsjpeg_term_source(j_decompress_ptr cinfo); * Create a CONTENT_JPEG. */ -void nsjpeg_create(struct content *c, const char *params[]) +bool nsjpeg_create(struct content *c, const char *params[]) { c->data.jpeg.sprite_area = 0; + return true; } @@ -67,7 +71,7 @@ void nsjpeg_create(struct content *c, const char *params[]) * Convert a CONTENT_JPEG for display. */ -int nsjpeg_convert(struct content *c, unsigned int w, unsigned int h) +bool nsjpeg_convert(struct content *c, int w, int h) { struct jpeg_decompress_struct cinfo; struct nsjpeg_error_mgr jerr; @@ -80,13 +84,17 @@ int nsjpeg_convert(struct content *c, unsigned int w, unsigned int h) unsigned int area_size; osspriteop_area *sprite_area = 0; osspriteop_header *sprite; + union content_msg_data msg_data; cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = nsjpeg_error_exit; if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); free(sprite_area); - return 1; + + msg_data.error = nsjpeg_error_buffer; + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; } jpeg_create_decompress(&cinfo); source_mgr.next_input_byte = c->source_data; @@ -104,7 +112,12 @@ int nsjpeg_convert(struct content *c, unsigned int w, unsigned int h) sprite_area = malloc(area_size); if (!sprite_area) { LOG(("malloc failed")); - return 1; + jpeg_destroy_decompress(&cinfo); + + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + return false; } /* area control block */ @@ -142,10 +155,10 @@ int nsjpeg_convert(struct content *c, unsigned int w, unsigned int h) c->data.jpeg.sprite_area = sprite_area; c->title = malloc(100); if (c->title) - sprintf(c->title, messages_get("JPEGTitle"), + snprintf(c->title, 100, messages_get("JPEGTitle"), width, height, c->source_size); c->status = CONTENT_STATUS_DONE; - return 0; + return true; } @@ -158,7 +171,7 @@ int nsjpeg_convert(struct content *c, unsigned int w, unsigned int h) void nsjpeg_error_exit(j_common_ptr cinfo) { struct nsjpeg_error_mgr *err = (struct nsjpeg_error_mgr *) cinfo->err; - (*cinfo->err->output_message) (cinfo); + err->pub.format_message(cinfo, nsjpeg_error_buffer); longjmp(err->setjmp_buffer, 1); } @@ -229,9 +242,9 @@ void nsjpeg_destroy(struct content *c) * Redraw a CONTENT_JPEG. */ -void nsjpeg_redraw(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long clip_x0, long clip_y0, long clip_x1, long clip_y1, +void nsjpeg_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, float scale) { unsigned int tinct_options; @@ -255,7 +268,7 @@ void nsjpeg_redraw(struct content *c, long x, long y, _IN(2) | _IN(3) | _IN(4) | _IN(5) | _IN(6) | _IN(7), (char *) c->data.jpeg.sprite_area + c->data.jpeg.sprite_area->first, - x, (int) (y - height), + x, y - height, width, height, tinct_options); } diff --git a/riscos/jpeg.h b/riscos/jpeg.h index 928ec252f..8db1ba502 100644 --- a/riscos/jpeg.h +++ b/riscos/jpeg.h @@ -16,12 +16,12 @@ struct content_jpeg_data { osspriteop_area *sprite_area; }; -void nsjpeg_create(struct content *c, const char *params[]); -int nsjpeg_convert(struct content *c, unsigned int width, unsigned int height); +bool nsjpeg_create(struct content *c, const char *params[]); +bool nsjpeg_convert(struct content *c, int width, int height); void nsjpeg_destroy(struct content *c); -void nsjpeg_redraw(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long clip_x0, long clip_y0, long clip_x1, long clip_y1, +void nsjpeg_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, float scale); #endif diff --git a/riscos/png.c b/riscos/png.c index 2c269c839..b31c992d3 100644 --- a/riscos/png.c +++ b/riscos/png.c @@ -32,19 +32,29 @@ static void row_callback(png_structp png, png_bytep new_row, static void end_callback(png_structp png, png_infop info); -void nspng_init(void) +bool nspng_create(struct content *c, const char *params[]) { -} - + union content_msg_data msg_data; -void nspng_create(struct content *c, const char *params[]) -{ c->data.png.sprite_area = 0; c->data.png.png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); - assert(c->data.png.png != 0); + if (!c->data.png.png) { + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + return false; + } c->data.png.info = png_create_info_struct(c->data.png.png); - assert(c->data.png.info != 0); + if (!c->data.png.info) { + png_destroy_read_struct(&c->data.png.png, + &c->data.png.info, 0); + + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + return false; + } if (setjmp(png_jmpbuf(c->data.png.png))) { png_destroy_read_struct(&c->data.png.png, @@ -52,30 +62,38 @@ void nspng_create(struct content *c, const char *params[]) LOG(("Failed to set callbacks")); c->data.png.png = NULL; c->data.png.info = NULL; - return; + + msg_data.error = messages_get("PNGError"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; } png_set_progressive_read_fn(c->data.png.png, c, info_callback, row_callback, end_callback); + + return true; } -void nspng_process_data(struct content *c, char *data, unsigned long size) +bool nspng_process_data(struct content *c, char *data, unsigned int size) { + 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); LOG(("Failed to process data")); c->data.png.png = NULL; c->data.png.info = NULL; - return; + + msg_data.error = messages_get("PNGError"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; } - LOG(("data %p, size %li", data, size)); - png_process_data(c->data.png.png, c->data.png.info, - data, size); + png_process_data(c->data.png.png, c->data.png.info, data, size); - c->size += size; + return true; } @@ -224,30 +242,32 @@ void end_callback(png_structp png, png_infop info) -int nspng_convert(struct content *c, unsigned int width, unsigned int height) +bool nspng_convert(struct content *c, int width, int height) { - if (c->data.png.png == NULL || c->data.png.info == NULL) - return 1; + assert(c->data.png.png); + assert(c->data.png.info); png_destroy_read_struct(&c->data.png.png, &c->data.png.info, 0); - c->title = xcalloc(100, 1); - sprintf(c->title, messages_get("PNGTitle"), c->width, c->height); + c->title = malloc(100); + if (c->title) + snprintf(c->title, 100, messages_get("PNGTitle"), + c->width, c->height); c->status = CONTENT_STATUS_DONE; - return 0; + return true; } void nspng_destroy(struct content *c) { - xfree(c->title); - xfree(c->data.png.sprite_area); + free(c->title); + free(c->data.png.sprite_area); } -void nspng_redraw(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long clip_x0, long clip_y0, long clip_x1, long clip_y1, +void nspng_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, float scale) { unsigned int tinct_options; @@ -269,7 +289,7 @@ void nspng_redraw(struct content *c, long x, long y, */ _swix(Tinct_PlotScaledAlpha, _IN(2) | _IN(3) | _IN(4) | _IN(5) | _IN(6) | _IN(7), ((char *) c->data.png.sprite_area + c->data.png.sprite_area->first), - x, (int)(y - height), + x, y - height, width, height, tinct_options); } diff --git a/riscos/png.h b/riscos/png.h index ead45d290..49d311efd 100644 --- a/riscos/png.h +++ b/riscos/png.h @@ -22,13 +22,12 @@ struct content_png_data { char *sprite_image; }; -void nspng_init(void); -void nspng_create(struct content *c, const char *params[]); -void nspng_process_data(struct content *c, char *data, unsigned long size); -int nspng_convert(struct content *c, unsigned int width, unsigned int height); +bool nspng_create(struct content *c, const char *params[]); +bool nspng_process_data(struct content *c, char *data, unsigned int size); +bool nspng_convert(struct content *c, int width, int height); void nspng_destroy(struct content *c); -void nspng_redraw(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long clip_x0, long clip_y0, long clip_x1, long clip_y1, +void nspng_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, float scale); #endif diff --git a/riscos/sprite.c b/riscos/sprite.c index b7d2bf068..b5c5f64bb 100644 --- a/riscos/sprite.c +++ b/riscos/sprite.c @@ -19,74 +19,90 @@ #ifdef WITH_SPRITE -void sprite_create(struct content *c, const char *params[]) +bool sprite_create(struct content *c, const char *params[]) { - c->data.sprite.data = xcalloc(4, 1); + union content_msg_data msg_data; + + c->data.sprite.data = malloc(4); + if (!c->data.sprite.data) { + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + return false; + } c->data.sprite.length = 4; + return true; } -void sprite_process_data(struct content *c, char *data, unsigned long size) +bool sprite_process_data(struct content *c, char *data, unsigned int size) { - c->data.sprite.data = xrealloc(c->data.sprite.data, c->data.sprite.length + size); - memcpy((char*)(c->data.sprite.data) + c->data.sprite.length, data, size); + char *sprite_data; + union content_msg_data msg_data; + + sprite_data = realloc(c->data.sprite.data, + c->data.sprite.length + size); + if (!sprite_data) { + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + return false; + } + c->data.sprite.data = sprite_data; + memcpy((char*)(c->data.sprite.data) + c->data.sprite.length, + data, size); c->data.sprite.length += size; c->size += size; + return true; } -int sprite_convert(struct content *c, unsigned int width, unsigned int height) +bool sprite_convert(struct content *c, int width, int height) { os_error *error; int w, h; + union content_msg_data msg_data; osspriteop_area *area = (osspriteop_area*)c->data.sprite.data; - /* fill in the size (first word) of the area */ + /* fill in the size (first word) of the area */ area->size = c->data.sprite.length; error = xosspriteop_read_sprite_info(osspriteop_PTR, - area, - (osspriteop_id)((char*)(c->data.sprite.data) + area->first), - &w, &h, NULL, NULL); - - if (error) { - LOG(("error: %s", error->errmess)); - return 1; - } + area, + (osspriteop_id)((char*)(c->data.sprite.data) + area->first), + &w, &h, NULL, NULL); + if (error) { + LOG(("xosspriteop_read_sprite_info: 0x%x: %s", + error->errnum, error->errmess)); + msg_data.error = error->errmess; + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } c->width = w; c->height = h; - c->title = xcalloc(100, 1); - sprintf(c->title, messages_get("SpriteTitle"), c->width, - c->height, c->data.sprite.length); + c->title = malloc(100); + if (c->title) + snprintf(c->title, 100, messages_get("SpriteTitle"), c->width, + c->height, c->data.sprite.length); c->status = CONTENT_STATUS_DONE; - return 0; -} - - -void sprite_revive(struct content *c, unsigned int width, unsigned int height) -{ -} - - -void sprite_reformat(struct content *c, unsigned int width, unsigned int height) -{ + return true; } void sprite_destroy(struct content *c) { - xfree(c->data.sprite.data); - xfree(c->title); + free(c->data.sprite.data); + free(c->title); } -void sprite_redraw(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long clip_x0, long clip_y0, long clip_x1, long clip_y1, +void sprite_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, float scale) { - unsigned int size; + unsigned int size; osspriteop_area *area = (osspriteop_area*)c->data.sprite.data; osspriteop_trans_tab *table; os_factors factors; @@ -94,14 +110,14 @@ void sprite_redraw(struct content *c, long x, long y, xcolourtrans_generate_table_for_sprite( area, (osspriteop_id)((char*)(c->data.sprite.data) + - area->first), + area->first), colourtrans_CURRENT_MODE, colourtrans_CURRENT_PALETTE, 0, colourtrans_GIVEN_SPRITE, 0, 0, &size); table = xcalloc(size, 1); xcolourtrans_generate_table_for_sprite( area, (osspriteop_id)((char*)(c->data.sprite.data) + - area->first), + area->first), colourtrans_CURRENT_MODE, colourtrans_CURRENT_PALETTE, table, colourtrans_GIVEN_SPRITE, 0, 0, 0); @@ -113,7 +129,7 @@ void sprite_redraw(struct content *c, long x, long y, xosspriteop_put_sprite_scaled(osspriteop_PTR, area, (osspriteop_id)((char*)(c->data.sprite.data) + - area->first), + area->first), x, (int)(y - height), osspriteop_USE_MASK | osspriteop_USE_PALETTE, &factors, table); diff --git a/riscos/sprite.h b/riscos/sprite.h index 183a5494f..39cf23eb1 100644 --- a/riscos/sprite.h +++ b/riscos/sprite.h @@ -17,15 +17,12 @@ struct content_sprite_data { unsigned long length; }; -void sprite_init(void); -void sprite_create(struct content *c, const char *params[]); -void sprite_process_data(struct content *c, char *data, unsigned long size); -int sprite_convert(struct content *c, unsigned int width, unsigned int height); -void sprite_revive(struct content *c, unsigned int width, unsigned int height); -void sprite_reformat(struct content *c, unsigned int width, unsigned int height); +bool sprite_create(struct content *c, const char *params[]); +bool sprite_process_data(struct content *c, char *data, unsigned int size); +bool sprite_convert(struct content *c, int width, int height); void sprite_destroy(struct content *c); -void sprite_redraw(struct content *c, long x, long y, - unsigned long width, unsigned long height, - long clip_x0, long clip_y0, long clip_x1, long clip_y1, +void sprite_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, float scale); #endif diff --git a/riscos/wimp.c b/riscos/wimp.c index b5f16e69b..8880232c9 100644 --- a/riscos/wimp.c +++ b/riscos/wimp.c @@ -21,6 +21,7 @@ #include "netsurf/desktop/gui.h" #include "netsurf/riscos/wimp.h" #include "netsurf/utils/log.h" +#include "netsurf/utils/utils.h" /* Wimp_Extend,11 block */ diff --git a/utils/utils.h b/utils/utils.h index b727b7ca8..e606baa6c 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -31,5 +31,6 @@ void regcomp_wrapper(regex_t *preg, const char *regex, int cflags); void clean_cookiejar(void); void unicode_transliterate(unsigned int c, char **r); char *human_friendly_bytesize(unsigned long bytesize); +void warn_user(const char *warning, const char *detail); #endif -- cgit v1.2.3