diff options
Diffstat (limited to 'riscos')
-rw-r--r-- | riscos/filetype.c | 8 | ||||
-rw-r--r-- | riscos/gui.c | 2 | ||||
-rw-r--r-- | riscos/help.c | 18 | ||||
-rw-r--r-- | riscos/mng.c | 371 | ||||
-rw-r--r-- | riscos/mng.h | 9 | ||||
-rw-r--r-- | riscos/window.c | 17 |
6 files changed, 406 insertions, 19 deletions
diff --git a/riscos/filetype.c b/riscos/filetype.c index f0c9fa71d..837151521 100644 --- a/riscos/filetype.c +++ b/riscos/filetype.c @@ -23,13 +23,13 @@ struct type_entry { }; static const struct type_entry type_map[] = { {0x188, "application/x-shockwave-flash"}, - {0x251, "image/jng"}, /* currently in user space */ - {0x252, "image/mng"}, /* currently in user space */ {0x695, "image/gif"}, {0xaff, "image/x-drawfile"}, {0xb60, "image/png"}, {0xc85, "image/jpeg"}, + {0xf78, "image/jng"}, {0xf79, "text/css"}, + {0xf83, "image/mng"}, {0xfaf, "text/html"}, {0xff9, "image/x-riscos-sprite"}, {0xfff, "text/plain"}, @@ -124,11 +124,11 @@ int ro_content_filetype(struct content *content) switch (content->type) { case CONTENT_HTML: return 0xfaf; case CONTENT_TEXTPLAIN: return 0xfff; + case CONTENT_MNG: return 0xf84; case CONTENT_CSS: return 0xf79; + case CONTENT_JNG: return 0xf78; case CONTENT_JPEG: return 0xc85; case CONTENT_PNG: return 0xb60; - case CONTENT_JNG: return 0x251; /* currently in user space */ - case CONTENT_MNG: return 0x252; /* currently in user space */ case CONTENT_GIF: return 0x695; case CONTENT_SPRITE: return 0xff9; case CONTENT_DRAW: return 0xaff; diff --git a/riscos/gui.c b/riscos/gui.c index afd4d97a3..90e73096a 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -994,6 +994,8 @@ void ro_msg_dataload(wimp_message *message) else if (file_type == 0xb28) /* ANT URL file */ url = ro_gui_url_file_parse(message->data.data_xfer.file_name); else if (file_type == 0xfaf || + file_type == 0xf78 || + file_type == 0xf83 || file_type == 0x695 || file_type == 0xaff || file_type == 0xb60 || diff --git a/riscos/help.c b/riscos/help.c index d247f51b4..1ba514f95 100644 --- a/riscos/help.c +++ b/riscos/help.c @@ -213,15 +213,18 @@ static void ro_gui_interactive_help_broadcast(wimp_message *message, char *token help_full_message_reply *reply; char *base_token; + /* Start off with an empty reply + */ + reply = (help_full_message_reply *)message; + reply->reply[0] = '\0'; + /* Check if the message exists */ translated_token = messages_get(token); if (translated_token == token) { /* We must never provide default help for a 'g' suffix. */ - if (token[strlen(token) - 1] == 'g') { - token[0] = '\0'; - } else { + if (token[strlen(token) - 1] != 'g') { /* Find the key from the token. */ base_token = token; @@ -237,15 +240,16 @@ static void ro_gui_interactive_help_broadcast(wimp_message *message, char *token /* Check if the base key exists and use an empty string if not */ translated_token = messages_get(token); - if (translated_token == token) token[0] = '\0'; } } + /* Copy our message string */ - reply = (help_full_message_reply *)message; - reply->reply[235] = 0; - strncpy(reply->reply, translated_token, 235); + if (translated_token != token) { + reply->reply[235] = 0; + strncpy(reply->reply, translated_token, 235); + } /* Broadcast the help reply */ diff --git a/riscos/mng.c b/riscos/mng.c index 1f25f9e1b..e02811359 100644 --- a/riscos/mng.c +++ b/riscos/mng.c @@ -10,6 +10,8 @@ #include <string.h> #include <stdlib.h> #include <swis.h> +#include "libmng/libmng.h" +#include "oslib/os.h" #include "oslib/osspriteop.h" #include "netsurf/utils/config.h" #include "netsurf/content/content.h" @@ -17,28 +19,350 @@ #include "netsurf/riscos/options.h" #include "netsurf/riscos/mng.h" #include "netsurf/riscos/tinct.h" +#include "netsurf/riscos/wimp.h" #include "netsurf/utils/log.h" #include "netsurf/utils/messages.h" #include "netsurf/utils/utils.h" #ifdef WITH_MNG +/* We do not currently support any form of colour/gamma correction, nor do + we support dynamic MNGs. +*/ + + +static mng_bool nsmng_openstream(mng_handle mng); +static mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread); +static mng_bool nsmng_closestream(mng_handle mng); +static mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width, mng_uint32 height); +static mng_ptr nsmng_getcanvasline(mng_handle mng, mng_uint32 line); +static mng_uint32 nsmng_gettickcount(mng_handle mng); +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); + bool nsmng_create(struct content *c, const char *params[]) { - return false; + + /* Initialise the library (libmng is compiled with MNG_INTERNAL_MEMMNGMT) + */ + c->data.mng.sprite_area = NULL; + c->data.mng.handle = mng_initialize(c, MNG_NULL, MNG_NULL, MNG_NULL); + if (c->data.mng.handle == MNG_NULL) { + LOG(("Unable to initialise MNG library.")); + return nsmng_broadcast_error(c); + } + + /* We need to decode in suspension mode + */ + if (mng_set_suspensionmode(c->data.mng.handle, MNG_TRUE) != MNG_NOERROR) { + LOG(("Unable to set suspension mode.")); + return nsmng_broadcast_error(c); + } + + /* We need to register our callbacks + */ + if (mng_setcb_openstream(c->data.mng.handle, nsmng_openstream) != MNG_NOERROR) { + LOG(("Unable to set openstream callback.")); + return nsmng_broadcast_error(c); + } + if (mng_setcb_readdata(c->data.mng.handle, nsmng_readdata) != MNG_NOERROR) { + LOG(("Unable to set readdata callback.")); + return nsmng_broadcast_error(c); + } + if (mng_setcb_closestream(c->data.mng.handle, nsmng_closestream) != MNG_NOERROR) { + LOG(("Unable to set closestream callback.")); + return nsmng_broadcast_error(c); + } + if (mng_setcb_processheader(c->data.mng.handle, nsmng_processheader) != MNG_NOERROR) { + LOG(("Unable to set processheader callback.")); + return nsmng_broadcast_error(c); + } + + /* Register our callbacks for displaying + */ + if (mng_setcb_getcanvasline(c->data.mng.handle, nsmng_getcanvasline) != MNG_NOERROR) { + LOG(("Unable to set getcanvasline callback.")); + return nsmng_broadcast_error(c); + } + if (mng_setcb_refresh(c->data.mng.handle, nsmng_refresh) != MNG_NOERROR) { + LOG(("Unable to set refresh callback.")); + return nsmng_broadcast_error(c); + } + if (mng_setcb_gettickcount(c->data.mng.handle, nsmng_gettickcount) != MNG_NOERROR) { + LOG(("Unable to set gettickcount callback.")); + return nsmng_broadcast_error(c); + } + if (mng_setcb_settimer(c->data.mng.handle, nsmng_settimer) != MNG_NOERROR) { + LOG(("Unable to set settimer callback.")); + return nsmng_broadcast_error(c); + } + + /* 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; + return true; } +/* START OF CALLBACKS REQUIRED FOR READING +*/ + + +mng_bool nsmng_openstream(mng_handle mng) { + return MNG_TRUE; +} + +mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread) { + struct content *c; + + /* Get our content back + */ + c = (struct content *)mng_get_userdata(mng); + LOG(("Reading data")); + + /* Copy any data we have (maximum of 'size') + */ + *bytesread = ((c->source_size - c->data.mng.read_size) < size) ? + (c->source_size - c->data.mng.read_size) : size; + if ((*bytesread) > 0) { + memcpy(buffer, c->source_data + c->data.mng.read_size, *bytesread); + c->data.mng.read_size += *bytesread; + } + LOG(("Read data (%i bytes, %i total)", *bytesread, c->data.mng.read_size)); + + /* Return success + */ + return MNG_TRUE; +} + +mng_bool nsmng_closestream(mng_handle mng) { + return MNG_TRUE; +} + +mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width, mng_uint32 height) { + struct content *c; + int sprite_size; + osspriteop_area *sprite_area; + osspriteop_header *sprite_header; + union content_msg_data msg_data; + + /* 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); + sprite_size = width * height * 4 + sizeof(osspriteop_header) + sizeof(osspriteop_area); + c->data.mng.sprite_area = (osspriteop_area *)malloc(sprite_size); + if (!(c->data.mng.sprite_area)) { + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + LOG(("Insufficient memory to create canvas.")); + return MNG_FALSE; + } + + /* Initialise the content size + */ + c->width = width; + c->height = height; + + /* Initialise the sprite area + */ + sprite_area = c->data.mng.sprite_area; + sprite_area->size = sprite_size; + sprite_area->sprite_count = 1; + sprite_area->first = sizeof(osspriteop_area); + sprite_area->used = sprite_size; + + /* Initialise the sprite header + */ + sprite_header = (osspriteop_header *)(sprite_area + 1); + sprite_header->size = sprite_size - sizeof(osspriteop_area); + strcpy(sprite_header->name, "mng"); + sprite_header->width = width - 1; + sprite_header->height = height - 1; + sprite_header->left_bit = 0; + sprite_header->right_bit = 31; + sprite_header->mask = sprite_header->image = sizeof(osspriteop_header); + sprite_header->mode = (os_mode) 0x301680b5; + + /* Set the canvas style + */ + if (mng_set_canvasstyle(mng, MNG_CANVAS_RGBA8) != MNG_NOERROR) { + LOG(("Error setting canvas style.")); + } + + LOG(("Created canvas (%ix%i)", c->width, c->height)); + + /* Return success + */ + return MNG_TRUE; +} + + +/* END OF CALLBACKS REQUIRED FOR READING +*/ + + bool nsmng_process_data(struct content *c, char *data, unsigned int size) { + mng_retcode status; + + /* We only need to do any processing if we're starting/resuming reading. + */ + if ((!c->data.mng.read_resume) && (!c->data.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; + } else { + status = mng_read_resume(c->data.mng.handle); + } + c->data.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); + } + + /* Continue onwards + */ return true; } bool nsmng_convert(struct content *c, int width, int height) { + mng_retcode status; + + LOG(("Converting")); + + /* Set the title + */ + c->title = malloc(100); + if (c->title) { + if (c->type == CONTENT_MNG) { + snprintf(c->title, 100, messages_get("MNGTitle"), + c->width, c->height, c->source_size); + } else if (c->type == CONTENT_PNG) { + snprintf(c->title, 100, messages_get("PNGTitle"), + c->width, c->height, c->source_size); + } else { + snprintf(c->title, 100, messages_get("JNGTitle"), + c->width, c->height, c->source_size); + } + } + c->size += (c->width * c->height * 4) + sizeof(osspriteop_header) + sizeof(osspriteop_area) + 100; + c->status = CONTENT_STATUS_DONE; + + + /* Start displaying + */ + status = mng_display(c->data.mng.handle); + if ((status != MNG_NOERROR) && (status != MNG_NEEDTIMERWAIT)) { + LOG(("Unable to start display (%i)", status)); + return nsmng_broadcast_error(c); + } return true; } +/* START OF CALLBACKS REQUIRED FOR DISPLAYING +*/ + + +mng_ptr nsmng_getcanvasline(mng_handle mng, mng_uint32 line) { + char *base; + struct content *c; + + /* Get our content back + */ + c = (struct content *)mng_get_userdata(mng); + + /* Calculate the address + */ + base = ((char *) c->data.mng.sprite_area + c->data.mng.sprite_area->first); + base += sizeof(osspriteop_header); + return base + (c->width * 4) * line; +} + + +mng_uint32 nsmng_gettickcount(mng_handle mng) { + os_t time; + + /* Get the time in centiseconds and return in milliseconds + */ + xos_read_monotonic_time(&time); + return (time * 10); +} + +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; + + /* Get our content back + */ + c = (struct content *)mng_get_userdata(mng); + + /* Set the minimum redraw area + */ + data.redraw.x = x; + data.redraw.y = y; + data.redraw.width = w; + data.redraw.height = h; + + /* Set the redraw area to the whole canvas to ensure that if we can redraw something + to trigger animation later then we do + */ +/* data.redraw.x = 0; + data.redraw.y = 0; + data.redraw.width = c->width; + data.redraw.height = c->height; +*/ + /* Always redraw everything + */ + data.redraw.full_redraw = true; + + /* Set the object characteristics + */ + data.redraw.object = c; + data.redraw.object_x = 0; + data.redraw.object_y = 0; + data.redraw.object_width = c->width; + data.redraw.object_height = c->height; + + content_broadcast(c, CONTENT_MSG_REDRAW, data); + return MNG_TRUE; +} + +mng_bool nsmng_settimer(mng_handle mng, mng_uint32 msecs) { + struct content *c; + + /* Get our content back + */ + c = (struct content *)mng_get_userdata(mng); + + /* Perform the scheduling + */ + schedule(msecs / 10, nsmng_animate, c); + return MNG_TRUE; +} + + +/* END OF CALLBACKS REQUIRED FOR DISPLAYING +*/ + + void nsmng_destroy(struct content *c) { + /* Cleanup the MNG structure and release the canvas memory + */ + schedule_remove(nsmng_animate, c); + mng_cleanup(&c->data.mng.handle); + if (c->data.mng.sprite_area) { + free(c->data.mng.sprite_area); + c->data.mng.sprite_area = NULL; + } } @@ -63,11 +387,52 @@ void nsmng_redraw(struct content *c, int x, int y, sprites not matching the required specifications are ignored. See the Tinct documentation for further information. */ -/* _swix(Tinct_PlotScaledAlpha, _IN(2) | _IN(3) | _IN(4) | _IN(5) | _IN(6) | _IN(7), + _swix(Tinct_PlotScaledAlpha, _IN(2) | _IN(3) | _IN(4) | _IN(5) | _IN(6) | _IN(7), ((char *) c->data.mng.sprite_area + c->data.mng.sprite_area->first), x, y - height, width, height, tinct_options); -*/ + + /* Check if we need to restart the animation + */ + if (c->data.mng.waiting) nsmng_animate(c); +} + +/** + * Animates to the next frame + */ +void nsmng_animate(void *p) { + struct content *c = 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; + } else { + c->data.mng.waiting = false; + mng_display_resume(c->data.mng.handle); + } +} + + + +/** + * Broadcasts an error message and returns false + * + * \param c the content to broadcast for + * \return false + */ +bool nsmng_broadcast_error(struct content *c) { + union content_msg_data msg_data; + if (c->type == CONTENT_MNG) { + msg_data.error = messages_get("MNGError"); + } else if (c->type == CONTENT_PNG) { + msg_data.error = messages_get("PNGError"); + } else { + msg_data.error = messages_get("JNGError"); + } + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } #endif diff --git a/riscos/mng.h b/riscos/mng.h index 41a09403a..661a9822b 100644 --- a/riscos/mng.h +++ b/riscos/mng.h @@ -1,20 +1,25 @@ /* * This file is part of NetSurf, http://netsurf.sourceforge.net/ * Licensed under the GNU General Public License, - * http://www.opensource.org/licenses/gpl-license + * http://www.opensource.org/licenses/gpl-license * Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net> */ #ifndef _NETSURF_RISCOS_MNG_H_ #define _NETSURF_RISCOS_MNG_H_ +#include "libmng/libmng.h" #include "oslib/osspriteop.h" struct content; struct content_mng_data { + bool read_start; + bool read_resume; + int read_size; + bool waiting; + mng_handle handle; osspriteop_area *sprite_area; - char *sprite_image; }; bool nsmng_create(struct content *c, const char *params[]); diff --git a/riscos/window.c b/riscos/window.c index 06e4d9c0b..0c451934e 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -245,6 +245,7 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw, */ state.next = wimp_TOP; ro_gui_window_open(g, (wimp_open*)&state); + ro_gui_prepare_navigate(g); /* Set the caret position to the URL bar */ @@ -555,10 +556,19 @@ void gui_window_update_box(struct gui_window *g, (ro_gui_current_redraw_gui->option.buffer_everything)) ro_gui_buffer_close(); error = xwimp_get_rectangle(&update, &more); + if (error) { - LOG(("xwimp_get_rectangle: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); + /* RISC OS 3.7 returns the following error is enough buffer + is claimed to cause a new dynamic area to be created. It + doesn't actually stop anything working, so we mask it out + for now until a better fix is found. + */ + if ((!ro_gui_current_redraw_gui->option.buffer_everything) || + (error->errnum != 0x286)) { + LOG(("xwimp_get_rectangle: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } ro_gui_current_redraw_gui = NULL; return; } @@ -1750,5 +1760,6 @@ void gui_window_set_pointer(gui_pointer_shape shape) void gui_window_new_content(struct gui_window *g) { + ro_gui_prepare_navigate(g); ro_gui_dialog_close_persistant(g->window); } |