diff options
author | Vincent Sanders <vince@kyllikki.org> | 2016-05-05 22:28:51 +0100 |
---|---|---|
committer | Vincent Sanders <vince@kyllikki.org> | 2016-05-15 13:44:34 +0100 |
commit | d21447d096a320a08b3efb2b8768fad0dcdcfd64 (patch) | |
tree | 1a83814b7c9e94b2f13c473261f23dd3a17dee64 /frontends/riscos | |
parent | 2cbb337756d9af5bda4d594964d446439f602551 (diff) | |
download | netsurf-d21447d096a320a08b3efb2b8768fad0dcdcfd64.tar.gz netsurf-d21447d096a320a08b3efb2b8768fad0dcdcfd64.tar.bz2 |
move frontends into sub directory
Diffstat (limited to 'frontends/riscos')
228 files changed, 63025 insertions, 0 deletions
diff --git a/frontends/riscos/401login.c b/frontends/riscos/401login.c new file mode 100644 index 000000000..e95a74809 --- /dev/null +++ b/frontends/riscos/401login.c @@ -0,0 +1,236 @@ +/* + * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "utils/config.h" + +#include <assert.h> +#include <stdbool.h> +#include <string.h> +#include <oslib/wimp.h> + +#include "utils/log.h" +#include "utils/messages.h" +#include "content/content.h" +#include "content/hlcache.h" +#include "content/urldb.h" +#include "desktop/browser.h" + +#include "riscos/gui.h" +#include "riscos/dialog.h" +#include "riscos/wimp_event.h" + +#define ICON_401LOGIN_LOGIN 0 +#define ICON_401LOGIN_CANCEL 1 +#define ICON_401LOGIN_HOST 2 +#define ICON_401LOGIN_REALM 3 +#define ICON_401LOGIN_USERNAME 4 +#define ICON_401LOGIN_PASSWORD 5 + +static void ro_gui_401login_close(wimp_w w); +static bool ro_gui_401login_apply(wimp_w w); +static void ro_gui_401login_open(nsurl *url, lwc_string *host, + const char *realm, + nserror (*cb)(bool proceed, void *pw), void *cbpw); + +static wimp_window *dialog_401_template; + +struct session_401 { + lwc_string *host; /**< Host for user display */ + char *realm; /**< Authentication realm */ + char uname[256]; /**< Buffer for username */ + nsurl *url; /**< URL being fetched */ + char pwd[256]; /**< Buffer for password */ + nserror (*cb)(bool proceed, void *pw); /**< Continuation callback */ + void *cbpw; /**< Continuation callback data */ +}; + + +/** + * Load the 401 login window template. + */ + +void ro_gui_401login_init(void) +{ + dialog_401_template = ro_gui_dialog_load_template("login"); +} + + +/** + * Open the login dialog + */ +void gui_401login_open(nsurl *url, const char *realm, + nserror (*cb)(bool proceed, void *pw), void *cbpw) +{ + lwc_string *host = nsurl_get_component(url, NSURL_HOST); + assert(host != NULL); + + ro_gui_401login_open(url, host, realm, cb, cbpw); + + lwc_string_unref(host); +} + + +/** + * Open a 401 login window. + */ + +void ro_gui_401login_open(nsurl *url, lwc_string *host, const char *realm, + nserror (*cb)(bool proceed, void *pw), void *cbpw) +{ + struct session_401 *session; + wimp_w w; + const char *auth; + + session = calloc(1, sizeof(struct session_401)); + if (!session) { + ro_warn_user("NoMemory", 0); + return; + } + + session->url = nsurl_ref(url); + if (realm == NULL) + realm = "Secure Area"; + auth = urldb_get_auth_details(session->url, realm); + if (auth == NULL) { + session->uname[0] = '\0'; + session->pwd[0] = '\0'; + } else { + const char *pwd; + size_t pwd_len; + + pwd = strchr(auth, ':'); + assert(pwd && pwd < auth + sizeof(session->uname)); + memcpy(session->uname, auth, pwd - auth); + session->uname[pwd - auth] = '\0'; + ++pwd; + pwd_len = strlen(pwd); + assert(pwd_len < sizeof(session->pwd)); + memcpy(session->pwd, pwd, pwd_len); + session->pwd[pwd_len] = '\0'; + } + session->host = lwc_string_ref(host); + session->realm = strdup(realm); + session->cb = cb; + session->cbpw = cbpw; + + if (!session->realm) { + nsurl_unref(session->url); + lwc_string_unref(session->host); + free(session); + ro_warn_user("NoMemory", 0); + return; + } + + /* fill in download window icons */ + dialog_401_template->icons[ICON_401LOGIN_HOST].data. + indirected_text.text = + (char *)lwc_string_data(session->host); + dialog_401_template->icons[ICON_401LOGIN_HOST].data. + indirected_text.size = + lwc_string_length(session->host) + 1; + dialog_401_template->icons[ICON_401LOGIN_REALM].data. + indirected_text.text = session->realm; + dialog_401_template->icons[ICON_401LOGIN_REALM].data. + indirected_text.size = strlen(session->realm) + 1; + dialog_401_template->icons[ICON_401LOGIN_USERNAME].data. + indirected_text.text = session->uname; + dialog_401_template->icons[ICON_401LOGIN_USERNAME].data. + indirected_text.size = sizeof(session->uname); + dialog_401_template->icons[ICON_401LOGIN_PASSWORD].data. + indirected_text.text = session->pwd; + dialog_401_template->icons[ICON_401LOGIN_PASSWORD].data. + indirected_text.size = sizeof(session->pwd); + + /* create and open the window */ + w = wimp_create_window(dialog_401_template); + + ro_gui_wimp_event_register_text_field(w, ICON_401LOGIN_USERNAME); + ro_gui_wimp_event_register_text_field(w, ICON_401LOGIN_PASSWORD); + ro_gui_wimp_event_register_cancel(w, ICON_401LOGIN_CANCEL); + ro_gui_wimp_event_register_ok(w, ICON_401LOGIN_LOGIN, + ro_gui_401login_apply); + ro_gui_wimp_event_register_close_window(w, ro_gui_401login_close); + ro_gui_wimp_event_set_user_data(w, session); + + ro_gui_dialog_open_persistent(NULL, w, false); +} + +/** + * Handle closing of login dialog + */ +void ro_gui_401login_close(wimp_w w) +{ + os_error *error; + struct session_401 *session; + + session = (struct session_401 *)ro_gui_wimp_event_get_user_data(w); + + assert(session); + + /* If ok didn't happen, send failure response */ + if (session->cb != NULL) + session->cb(false, session->cbpw); + + nsurl_unref(session->url); + lwc_string_unref(session->host); + free(session->realm); + free(session); + + error = xwimp_delete_window(w); + if (error) { + LOG("xwimp_delete_window: 0x%x:%s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + ro_gui_wimp_event_finalise(w); +} + + +/* Login Clicked -> create a new fetch request, specifying uname & pwd + * CURLOPT_USERPWD takes a string "username:password" + */ +bool ro_gui_401login_apply(wimp_w w) +{ + struct session_401 *session; + char *auth; + + session = (struct session_401 *)ro_gui_wimp_event_get_user_data(w); + + assert(session); + + auth = malloc(strlen(session->uname) + strlen(session->pwd) + 2); + if (!auth) { + LOG("calloc failed"); + ro_warn_user("NoMemory", 0); + return false; + } + + sprintf(auth, "%s:%s", session->uname, session->pwd); + + urldb_set_auth_details(session->url, session->realm, auth); + + free(auth); + + session->cb(true, session->cbpw); + + /* Flag that we sent response by invalidating callback details */ + session->cb = NULL; + session->cbpw = NULL; + + return true; +} + diff --git a/frontends/riscos/Makefile b/frontends/riscos/Makefile new file mode 100644 index 000000000..6ed076800 --- /dev/null +++ b/frontends/riscos/Makefile @@ -0,0 +1,153 @@ +# +# Makefile for NetSurf RISC OS target +# +# This file is part of NetSurf + +# ---------------------------------------------------------------------------- +# RISC OS target setup +# ---------------------------------------------------------------------------- + +$(eval $(call pkg_config_find_and_add,libcares,Cares)) + +$(eval $(call feature_enabled,DRAW,-DWITH_DRAW,,Drawfile rendering)) +$(eval $(call feature_enabled,SPRITE,-DWITH_SPRITE,,Sprite rendering)) +$(eval $(call feature_enabled,ARTWORKS,-DWITH_ARTWORKS,,ArtWorks rendering)) +$(eval $(call feature_enabled,DRAW_EXPORT,-DWITH_DRAW_EXPORT,-lpencil,Drawfile export)) + + +TPD_RISCOS = $(foreach TPL,$(notdir $(TPL_RISCOS)), \ + !NetSurf/Resources/$(TPL)/Templates$(TPLEXT)) + +RESOURCES = $(TPD_RISCOS) + +CFLAGS += -Driscos -std=c99 -D_BSD_SOURCE -D_POSIX_C_SOURCE \ + -mpoke-function-name -fno-strict-aliasing + +CFLAGS += -I$(GCCSDK_INSTALL_ENV)/include +ifeq ($(HOST),riscos) + CFLAGS += -I<OSLib$$Dir> -mthrowback +endif +ASFLAGS += -xassembler-with-cpp -I. -I$(GCCSDK_INSTALL_ENV)/include +LDFLAGS += -L$(GCCSDK_INSTALL_ENV)/lib -lrufl +ifeq ($(HOST),riscos) + LDFLAGS += -LOSLib: -lOSLib32 +else + LDFLAGS += -lOSLib32 + ifeq ($(SUBTARGET),-elf) + # Go for static builds & AIF binary at the moment: + CFLAGS += -static + LDFLAGS += -static + EXEEXT := ,ff8 + endif +endif + +# ---------------------------------------------------------------------------- +# Source file setup +# ---------------------------------------------------------------------------- + +# S_RISCOS are sources purely for the RISC OS build +S_FRONTEND := 401login.c assert.c bitmap.c buffer.c cookies.c configure.c \ + dialog.c download.c filetype.c font.c \ + global_history.c gui.c help.c history.c hotlist.c iconbar.c \ + image.c menus.c message.c mouse.c palettes.c plotters.c \ + print.c query.c save.c save_draw.c save_pdf.c schedule.c \ + search.c searchweb.c sslcert.c textarea.c \ + textselection.c theme.c theme_install.c toolbar.c \ + treeview.c ucstables.c uri.c url_complete.c url_protocol.c \ + url_suggest.c wimp.c wimp_event.c window.c \ + $(addprefix content-handlers/,artworks.c awrender.s draw.c \ + sprite.c) \ + $(addprefix gui/,button_bar.c progress_bar.c status_bar.c \ + throbber.c url_bar.c) \ + $(addprefix configure/,con_cache.c con_connect.c con_content.c \ + con_fonts.c con_home.c con_image.c con_inter.c con_language.c \ + con_secure.c con_theme.c) + +# This is the final source build list +# Note this is deliberately *not* expanded here as common and image +# are not yet available +SOURCES = $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_FRONTEND) + +EXETARGET := !NetSurf/!RunImage$(EXEEXT) + +# The filter and target for split messages +MESSAGES_FILTER=ro + +!NetSurf/!Run$(RUNEXT): $(FRONTEND_SOURCE_DIR)/scripts/Run $(EXETARGET) + $(VQ)echo " MAKERUN: $@" + $(Q)$(MAKERUN) $(EXETARGET) $< $@ + +!NetSurf/!Help$(RUNEXT): $(FRONTEND_SOURCE_DIR)/scripts/Help + $(VQ)echo " CP: $@" + $(Q)cp $< $@ + +$(DEPROOT)/squeeze.d: $(EXETARGET) + $(VQ)echo " SQUEEZE: $<" + $(Q)$(SQUEEZE) -f -v $(EXETARGET) + $(Q)$(TOUCH) $@ + +POSTEXES += !NetSurf/!Run$(RUNEXT) !NetSurf/!Help$(RUNEXT) $(DEPROOT)/squeeze.d + + +clean-run: + $(VQ)echo " CLEAN: !NetSurf/!Run$(RUNEXT)" + $(Q) $(RM) !NetSurf/!Run$(RUNEXT) + +clean-help: + $(VQ)echo " CLEAN: !NetSurf/!Help$(RUNEXT)" + $(Q) $(RM) !NetSurf/!Help$(RUNEXT) + +CLEANS += clean-run clean-help + +# ---------------------------------------------------------------------------- +# Template targets +# ---------------------------------------------------------------------------- + +# Template objects +TPL_RISCOS := de en fr nl # TODO: It'd be nice to auto-detect these +TPL_RISCOS := $(addprefix $(FRONTEND_SOURCE_DIR)/templates/,$(TPL_RISCOS)) + +# Template target creation macro +define compile_template +!NetSurf/Resources/$(1)/Templates$$(TPLEXT): $(2) + $$(VQ)echo "TEMPLATE: $(2)" + $$(Q)mkdir -p !NetSurf/Resources/$(1) + $$(Q)$$(CC) -x c -E -P $$(CFLAGS) $(2) | $$(CCRES) - $$@ + +CLEAN_TEMPLATES += !NetSurf/Resources/$(1)/Templates$$(TPLEXT) + +endef + +$(eval $(foreach TPL,$(TPL_RISCOS), \ + $(call compile_template,$(notdir $(TPL)),$(TPL)))) + +clean-templates: + $(VQ)echo " CLEAN: $(CLEAN_TEMPLATES)" + $(Q)$(RM) $(CLEAN_TEMPLATES) +CLEANS += clean-templates + + +# ---------------------------------------------------------------------------- +# Install target +# ---------------------------------------------------------------------------- + +install-riscos: + +# ---------------------------------------------------------------------------- +# Package target +# ---------------------------------------------------------------------------- + +package-riscos: netsurf.zip + +netsurf.zip: $(EXETARGET) + $(eval $@_TMPDIR := $(shell mktemp -d)) + $(Q) $(RM) $@ + $(Q) rsync --archive --verbose $(CURDIR)/!NetSurf $($@_TMPDIR) + $(Q) $(CURDIR)/utils/git-date.sh $(FRONTEND_SOURCE_DIR)/distribution + $(Q) rsync --archive --verbose $(FRONTEND_SOURCE_DIR)/distribution/!Boot $($@_TMPDIR) + $(Q) rsync --archive --verbose $(FRONTEND_SOURCE_DIR)/distribution/!System $($@_TMPDIR) + $(Q) rsync --archive --verbose $(FRONTEND_SOURCE_DIR)/distribution/3rdParty $($@_TMPDIR) + $(Q) cp $(FRONTEND_SOURCE_DIR)/distribution/ReadMe $($@_TMPDIR) + $(Q) cp $(FRONTEND_SOURCE_DIR)/distribution/LeesMij $($@_TMPDIR) + $(Q) cd $($@_TMPDIR) && /opt/netsurf/arm-unknown-riscos/env/bin/zip -9vr\, $(CURDIR)/$@ * + $(Q) $(RM) -rf $($@_TMPDIR) diff --git a/frontends/riscos/Makefile.defaults b/frontends/riscos/Makefile.defaults new file mode 100644 index 000000000..aed361631 --- /dev/null +++ b/frontends/riscos/Makefile.defaults @@ -0,0 +1,37 @@ +# ---------------------------------------------------------------------------- +# RISC OS-specific options +# ---------------------------------------------------------------------------- + +# Enable NetSurf's use of libsvgtiny for displaying SVGs +# Valid options: YES, NO +NETSURF_USE_NSSVG := YES + +# Enable NetSurf's support for displaying RISC OS Draw files +# Valid options: YES, NO +NETSURF_USE_DRAW := YES + +# Enable NetSurf's support for displaying RISC OS Sprites +# Valid options: YES, NO +NETSURF_USE_SPRITE := YES + +# Enable NetSurf's use of librosprite for displaying RISC OS Sprites +# Valid options: YES, NO, AUTO +NETSURF_USE_ROSPRITE := NO + +# Enable NetSurf's use of AWRender for displaying ArtWorks files +# Valid options: YES, NO +NETSURF_USE_ARTWORKS := YES + +# Enable NetSurf's support for the Acorn plugin protocol +# Valid options: YES, NO +NETSURF_USE_PLUGINS := NO + +# Enable NetSurf's use of pencil for Drawfile export +# Valid options: YES, NO +NETSURF_USE_DRAW_EXPORT := YES + +# Enable building the source object cache filesystem based backing store. +NETSURF_FS_BACKING_STORE := YES + +# Optimisation levels +CFLAGS += -O2 diff --git a/frontends/riscos/assert.c b/frontends/riscos/assert.c new file mode 100644 index 000000000..50b8f5d54 --- /dev/null +++ b/frontends/riscos/assert.c @@ -0,0 +1,44 @@ +/* + * Copyright 2005 James Bursa <bursa@users.sourceforge.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * Assert reporting (RISC OS implementation). + */ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include "oslib/wimp.h" + + +/** + * Report an assert() failure and exit. + */ + +void __assert2(const char *expr, const char *function, const char *file, + int line) +{ + fprintf(stderr, "\n\"%s\", line %d: %s%sAssertion failed: %s\n", + file, line, + function ? function : "", + function ? ": " : "", + expr); + fflush(stderr); + + abort(); +} diff --git a/frontends/riscos/bitmap.c b/frontends/riscos/bitmap.c new file mode 100644 index 000000000..cc4be590c --- /dev/null +++ b/frontends/riscos/bitmap.c @@ -0,0 +1,876 @@ +/* + * Copyright 2004 James Bursa <bursa@users.sourceforge.net> + * Copyright 2005 Richard Wilson <info@tinct.net> + * Copyright 2008 Adrian Lees <adrianl@users.sourceforge.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * \file + * RISC OS implementation of bitmap operations. + * + * This implements the interface given by image/bitmap.h using RISC OS + * sprites. + */ + +#include <assert.h> +#include <stdbool.h> +#include <string.h> +#include <swis.h> +#include <rufl.h> +#include <unixlib/local.h> +#include <oslib/colourtrans.h> +#include <oslib/osfile.h> +#include <oslib/osfind.h> +#include <oslib/osgbpb.h> +#include <oslib/osspriteop.h> +#include <oslib/wimp.h> + +#include "utils/nsoption.h" +#include "utils/filename.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "desktop/plotters.h" +#include "content/content.h" +#include "image/bitmap.h" + +#include "riscos/gui.h" +#include "riscos/image.h" +#include "riscos/palettes.h" +#include "riscos/content-handlers/sprite.h" +#include "riscos/tinct.h" +#include "riscos/bitmap.h" + +/** Colour in the overlay sprite that allows the bitmap to show through */ +#define OVERLAY_INDEX 0xfe + +/** Size of buffer used when constructing mask data to be saved */ +#define SAVE_CHUNK_SIZE 4096 + +/** + * Whether we can use 32bpp sprites + */ +static int thumbnail_32bpp_available = -1; + +/** + * Sprite output context saving + */ +struct thumbnail_save_area { + osspriteop_save_area *save_area; + int context1; + int context2; + int context3; +}; + +/** + * Initialise a bitmaps sprite area. + * + * \param bitmap the bitmap to initialise + * \return true if bitmap initialised else false. + */ + +static bool bitmap_initialise(struct bitmap *bitmap) +{ + unsigned int area_size; + osspriteop_area *sprite_area; + osspriteop_header *sprite; + + assert(!bitmap->sprite_area); + + area_size = 16 + 44 + bitmap->width * bitmap->height * 4; + if (bitmap->state & BITMAP_CLEAR_MEMORY) + bitmap->sprite_area = calloc(1, area_size); + else + bitmap->sprite_area = malloc(area_size); + + if (!bitmap->sprite_area) + return false; + + /* area control block */ + sprite_area = bitmap->sprite_area; + sprite_area->size = area_size; + sprite_area->sprite_count = 1; + sprite_area->first = 16; + sprite_area->used = area_size; + + /* sprite control block */ + sprite = (osspriteop_header *) (sprite_area + 1); + sprite->size = area_size - 16; + memset(sprite->name, 0x00, 12); + strncpy(sprite->name, "bitmap", 12); + sprite->width = bitmap->width - 1; + sprite->height = bitmap->height - 1; + sprite->left_bit = 0; + sprite->right_bit = 31; + sprite->image = sprite->mask = 44; + sprite->mode = tinct_SPRITE_MODE; + + return true; +} + + +/* exported interface documented in riscos/bitmap.h */ +void *riscos_bitmap_create(int width, int height, unsigned int state) +{ + struct bitmap *bitmap; + + if (width == 0 || height == 0) + return NULL; + + bitmap = calloc(1, sizeof(struct bitmap)); + if (!bitmap) + return NULL; + bitmap->width = width; + bitmap->height = height; + bitmap->state = state; + + return bitmap; +} + + +/* exported interface documented in riscos/bitmap.h */ +unsigned char *riscos_bitmap_get_buffer(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *) vbitmap; + assert(bitmap); + + /* dynamically create the buffer */ + if (bitmap->sprite_area == NULL) { + if (!bitmap_initialise(bitmap)) + return NULL; + } + + /* image data area should exist */ + if (bitmap->sprite_area) + return ((unsigned char *) (bitmap->sprite_area)) + 16 + 44; + + return NULL; +} + + +/** + * Sets whether a bitmap should be plotted opaque + * + * \param vbitmap a bitmap, as returned by bitmap_create() + * \param opaque whether the bitmap should be plotted opaque + */ +static void bitmap_set_opaque(void *vbitmap, bool opaque) +{ + struct bitmap *bitmap = (struct bitmap *) vbitmap; + assert(bitmap); + + if (opaque) + bitmap->state |= BITMAP_OPAQUE; + else + bitmap->state &= ~BITMAP_OPAQUE; +} + + +/** + * Find the width of a pixel row in bytes. + * + * \param vbitmap A bitmap, as returned by riscos_bitmap_create() + * \return width of a pixel row in the bitmap + */ +static size_t bitmap_get_rowstride(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *) vbitmap; + return bitmap->width * 4; +} + + +/** + * Tests whether a bitmap has an opaque alpha channel + * + * \param vbitmap a bitmap, as returned by bitmap_create() + * \return whether the bitmap is opaque + */ +static bool bitmap_test_opaque(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *) vbitmap; + unsigned char *sprite; + unsigned int width, height, size; + osspriteop_header *sprite_header; + unsigned *p, *ep; + + assert(bitmap); + + sprite = riscos_bitmap_get_buffer(bitmap); + if (!sprite) + return false; + + width = bitmap_get_rowstride(bitmap); + + sprite_header = (osspriteop_header *) (bitmap->sprite_area + 1); + + height = (sprite_header->height + 1); + + size = width * height; + + p = (void *) sprite; + + ep = (void *) (sprite + (size & ~31)); + while (p < ep) { + /* \todo prefetch(p, 128)? */ + if (((p[0] & p[1] & p[2] & p[3] & p[4] & p[5] & p[6] & p[7]) + & 0xff000000U) != 0xff000000U) + return false; + p += 8; + } + + ep = (void *) (sprite + size); + while (p < ep) { + if ((*p & 0xff000000U) != 0xff000000U) return false; + p++; + } + + return true; +} + + +/* exported interface documented in riscos/bitmap.h */ +bool riscos_bitmap_get_opaque(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *) vbitmap; + assert(bitmap); + return (bitmap->state & BITMAP_OPAQUE); +} + + +/* exported interface documented in riscos/bitmap.h */ +void riscos_bitmap_destroy(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *) vbitmap; + + assert(bitmap); + + /* destroy bitmap */ + if (bitmap->sprite_area) { + free(bitmap->sprite_area); + } + + free(bitmap); +} + + +/* exported interface documented in riscos/bitmap.h */ +bool riscos_bitmap_save(void *vbitmap, const char *path, unsigned flags) +{ + struct bitmap *bitmap = (struct bitmap *) vbitmap; + os_error *error; + + if (bitmap == NULL) { + ro_warn_user("SaveError", messages_get("SprIsNull")); + return false; + } + + if (!bitmap->sprite_area) { + riscos_bitmap_get_buffer(bitmap); + } + if (!bitmap->sprite_area) + return false; + + if (riscos_bitmap_get_opaque(bitmap)) { + error = xosspriteop_save_sprite_file(osspriteop_USER_AREA, + (bitmap->sprite_area), path); + if (error) { + LOG("xosspriteop_save_sprite_file: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("SaveError", error->errmess); + return false; + } + return true; + } else { + /* to make the saved sprite useful we must convert from 'Tinct' + * format to either a bi-level mask or a Select-style full + * alpha channel */ + osspriteop_area *area = bitmap->sprite_area; + osspriteop_header *hdr = (void *) ((char *) area + area->first); + unsigned width = hdr->width + 1, height = hdr->height + 1; + unsigned image_size = height * width * 4; + unsigned char *chunk_buf; + unsigned *p, *elp, *eip; + unsigned mask_size; + size_t chunk_pix; + struct { + osspriteop_area area; + osspriteop_header hdr; + } file_hdr; + os_fw fw; + + /* we only support 32bpp sprites */ + if ((((unsigned)hdr->mode >> 27)&15) != 6) { + assert(!"Unsupported sprite format in bitmap_save"); + return false; + } + + chunk_buf = malloc(SAVE_CHUNK_SIZE); + if (!chunk_buf) { + ro_warn_user("NoMemory", NULL); + return false; + } + + file_hdr.area = *area; + file_hdr.hdr = *hdr; + + if (flags & BITMAP_SAVE_FULL_ALPHA) { + mask_size = ((width + 3) & ~3) * height; + chunk_pix = SAVE_CHUNK_SIZE; + file_hdr.hdr.mode = (os_mode)((unsigned)file_hdr.hdr.mode + | (1U<<31)); + } else { + mask_size = (((width + 31) & ~31)/8) * height; + chunk_pix = SAVE_CHUNK_SIZE<<3; + file_hdr.hdr.mode = (os_mode)((unsigned)file_hdr.hdr.mode + & ~(1U<<31)); + } + + file_hdr.area.sprite_count = 1; + file_hdr.area.first = sizeof(file_hdr.area); + file_hdr.area.used = sizeof(file_hdr) + image_size + mask_size; + + file_hdr.hdr.image = sizeof(file_hdr.hdr); + file_hdr.hdr.mask = file_hdr.hdr.image + image_size; + file_hdr.hdr.size = file_hdr.hdr.mask + mask_size; + + error = xosfind_openoutw(0, path, NULL, &fw); + if (error) { + LOG("xosfind_openoutw: 0x%x: %s", error->errnum, error->errmess); + free(chunk_buf); + ro_warn_user("SaveError", error->errmess); + return false; + } + + p = (void *) ((char *) hdr + hdr->image); + + /* write out the area header, sprite header and image data */ + error = xosgbpb_writew(fw, (byte*)&file_hdr + 4, + sizeof(file_hdr)-4, NULL); + if (!error) + error = xosgbpb_writew(fw, (byte*)p, image_size, NULL); + if (error) { + LOG("xosgbpb_writew: 0x%x: %s", error->errnum, error->errmess); + free(chunk_buf); + xosfind_closew(fw); + ro_warn_user("SaveError", error->errmess); + return false; + } + + /* then write out the mask data in chunks */ + eip = p + (width * height); /* end of image */ + elp = p + width; /* end of line */ + + while (p < eip) { + unsigned char *dp = chunk_buf; + unsigned *ep = p + chunk_pix; + if (ep > elp) ep = elp; + + if (flags & BITMAP_SAVE_FULL_ALPHA) { + while (p < ep) { + *dp++ = ((unsigned char*)p)[3]; + p++; + } + } + else { + unsigned char mb = 0; + int msh = 0; + while (p < ep) { + if (((unsigned char*)p)[3]) mb |= (1 << msh); + if (++msh >= 8) { + *dp++ = mb; + msh = 0; + mb = 0; + } + p++; + } + if (msh > 0) *dp++ = mb; + } + + if (p >= elp) { /* end of line yet? */ + /* align to word boundary */ + while ((int)dp & 3) *dp++ = 0; + /* advance end of line pointer */ + elp += width; + } + error = xosgbpb_writew(fw, (byte*)chunk_buf, dp-chunk_buf, NULL); + if (error) { + LOG("xosgbpb_writew: 0x%x: %s", error->errnum, error->errmess); + free(chunk_buf); + xosfind_closew(fw); + ro_warn_user("SaveError", error->errmess); + return false; + } + } + + error = xosfind_closew(fw); + if (error) { + LOG("xosfind_closew: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("SaveError", error->errmess); + } + + error = xosfile_set_type(path, osfile_TYPE_SPRITE); + if (error) { + LOG("xosfile_set_type: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("SaveError", error->errmess); + } + + free(chunk_buf); + return true; + } +} + + +/** + * The bitmap image has changed, so flush any persistent cache. + * + * \param vbitmap a bitmap, as returned by bitmap_create() + */ +static void bitmap_modified(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *) vbitmap; + bitmap->state |= BITMAP_MODIFIED; +} + + +/** + * Get the width of a bitmap. + * + * \param vbitmap A bitmap, as returned by bitmap_create() + * \return The bitmaps width in pixels. + */ +static int bitmap_get_width(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *) vbitmap; + return bitmap->width; +} + + +/** + * Get the height of a bitmap. + * + * \param vbitmap A bitmap, as returned by bitmap_create() + * \return The bitmaps height in pixels. + */ +static int bitmap_get_height(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *) vbitmap; + return bitmap->height; +} + + +/** + * Find the bytes per pixel of a bitmap + * + * \param vbitmap a bitmap, as returned by bitmap_create() + * \return bytes per pixel + */ +static size_t bitmap_get_bpp(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *)vbitmap; + assert(bitmap); + return 4; +} + + +/* exported interface documented in riscos/bitmap.h */ +void riscos_bitmap_overlay_sprite(struct bitmap *bitmap, + const osspriteop_header *s) +{ + const os_colour *palette; + const byte *sp, *mp; + bool masked = false; + bool alpha = false; + os_error *error; + int dp_offset; + int sp_offset; + unsigned *dp; + int x, y; + int w, h; + + assert(sprite_bpp(s) == 8); + + if ((unsigned)s->mode & 0x80000000U) + alpha = true; + + error = xosspriteop_read_sprite_info(osspriteop_PTR, + (osspriteop_area *)0x100, + (osspriteop_id)s, + &w, &h, NULL, NULL); + if (error) { + LOG("xosspriteop_read_sprite_info: 0x%x:%s", error->errnum, error->errmess); + return; + } + sp_offset = ((s->width + 1) * 4) - w; + + if (w > bitmap->width) + w = bitmap->width; + if (h > bitmap->height) + h = bitmap->height; + + dp_offset = bitmap_get_rowstride(bitmap) / 4; + + dp = (void*)riscos_bitmap_get_buffer(bitmap); + if (!dp) + return; + sp = (byte*)s + s->image; + mp = (byte*)s + s->mask; + + sp += s->left_bit / 8; + mp += s->left_bit / 8; + + if (s->image > (int)sizeof(*s)) + palette = (os_colour*)(s + 1); + else + palette = default_palette8; + + if (s->mask != s->image) { + masked = true; + bitmap_set_opaque(bitmap, false); + } + + /* (partially-)transparent pixels in the overlayed sprite retain + * their transparency in the output bitmap; opaque sprite pixels + * are also propagated to the bitmap, except those which are the + * OVERLAY_INDEX colour which allow the original bitmap contents to + * show through */ + for (y = 0; y < h; y++) { + unsigned *sdp = dp; + for(x = 0; x < w; x++) { + os_colour d = ((unsigned)palette[(*sp) << 1]) >> 8; + if (*sp++ == OVERLAY_INDEX) + d = *dp; + if (masked) { + if (alpha) + d |= ((*mp << 24) ^ 0xff000000U); + else if (*mp) + d |= 0xff000000U; + } + *dp++ = d; + mp++; + } + dp = sdp + dp_offset; + sp += sp_offset; + mp += sp_offset; + } +} + + +/** + * Creates an 8bpp canvas. + * + * \param bitmap the bitmap to clone the size of + * \return a sprite area containing an 8bpp sprite + */ +static osspriteop_area *thumbnail_create_8bpp(struct bitmap *bitmap) +{ + unsigned image_size = ((bitmap->width + 3) & ~3) * bitmap->height; + bool opaque = riscos_bitmap_get_opaque(bitmap); + osspriteop_header *sprite_header = NULL; + osspriteop_area *sprite_area = NULL; + unsigned area_size; + + /* clone the sprite */ + area_size = sizeof(osspriteop_area) + + sizeof(osspriteop_header) + + image_size + + 2048; + + if (!opaque) area_size += image_size; + + sprite_area = (osspriteop_area *)malloc(area_size); + if (!sprite_area) { + LOG("no memory for malloc()"); + return NULL; + } + sprite_area->size = area_size; + sprite_area->sprite_count = 1; + sprite_area->first = 16; + sprite_area->used = area_size; + sprite_header = (osspriteop_header *)(sprite_area + 1); + sprite_header->size = area_size - sizeof(osspriteop_area); + memset(sprite_header->name, 0x00, 12); + strcpy(sprite_header->name, "bitmap"); + sprite_header->left_bit = 0; + sprite_header->height = bitmap->height - 1; + sprite_header->mode = os_MODE8BPP90X90; + sprite_header->right_bit = ((bitmap->width << 3) - 1) & 31; + sprite_header->width = ((bitmap->width + 3) >> 2) - 1; + sprite_header->image = sizeof(osspriteop_header) + 2048; + sprite_header->mask = sizeof(osspriteop_header) + 2048; + if (!opaque) sprite_header->mask += image_size; + + /* create the palette. we don't read the necessary size like + * we really should as we know it's going to have 256 entries + * of 8 bytes = 2048. */ + xcolourtrans_read_palette((osspriteop_area *)os_MODE8BPP90X90, + (osspriteop_id)0, + (os_palette *)(sprite_header + 1), 2048, + (colourtrans_palette_flags)(1 << 1), 0); + return sprite_area; +} + + +/** + * Switches output to the specified sprite and returns the previous context. + */ +static struct thumbnail_save_area* +thumbnail_switch_output(osspriteop_area *sprite_area, + osspriteop_header *sprite_header) +{ + struct thumbnail_save_area *save_area; + int size; + + /* create a save area */ + save_area = calloc(sizeof(struct thumbnail_save_area), 1); + if (save_area == NULL) return NULL; + + /* allocate OS_SpriteOp save area */ + if (xosspriteop_read_save_area_size(osspriteop_PTR, sprite_area, + (osspriteop_id)sprite_header, &size)) { + free(save_area); + return NULL; + } + + /* create the save area */ + save_area->save_area = malloc((unsigned)size); + if (save_area->save_area == NULL) { + free(save_area); + return NULL; + } + save_area->save_area->a[0] = 0; + + /* switch output to sprite */ + if (xosspriteop_switch_output_to_sprite(osspriteop_PTR, sprite_area, + (osspriteop_id)sprite_header, save_area->save_area, + 0, &save_area->context1, &save_area->context2, + &save_area->context3)) { + free(save_area->save_area); + free(save_area); + return NULL; + } + return save_area; +} + + +/** + * Restores output to the specified context, and destroys it. + */ +static void thumbnail_restore_output(struct thumbnail_save_area *save_area) +{ + /* we don't care if we err, as there's nothing we can do about it */ + xosspriteop_switch_output_to_sprite(osspriteop_PTR, + (osspriteop_area *)save_area->context1, + (osspriteop_id)save_area->context2, + (osspriteop_save_area *)save_area->context3, + 0, 0, 0, 0); + free(save_area->save_area); + free(save_area); +} + + +/** + * Convert a bitmap to 8bpp. + * + * \param bitmap the bitmap to convert + * \return a sprite area containing an 8bpp sprite + */ +osspriteop_area *riscos_bitmap_convert_8bpp(struct bitmap *bitmap) +{ + struct thumbnail_save_area *save_area; + osspriteop_area *sprite_area = NULL; + osspriteop_header *sprite_header = NULL; + + sprite_area = thumbnail_create_8bpp(bitmap); + if (!sprite_area) + return NULL; + sprite_header = (osspriteop_header *)(sprite_area + 1); + + + /* switch output and redraw */ + save_area = thumbnail_switch_output(sprite_area, sprite_header); + if (save_area == NULL) { + if (thumbnail_32bpp_available != 1) + free(sprite_area); + return false; + } + _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7), + (osspriteop_header *)(bitmap->sprite_area + 1), + 0, 0, + tinct_ERROR_DIFFUSE); + thumbnail_restore_output(save_area); + + if (sprite_header->image != sprite_header->mask) { + /* build the sprite mask from the alpha channel */ + void *buf = riscos_bitmap_get_buffer(bitmap); + unsigned *dp = (unsigned *) buf; + if (!dp) + return sprite_area; + int w = bitmap_get_width(bitmap); + int h = bitmap_get_height(bitmap); + int dp_offset = bitmap_get_rowstride(bitmap) / 4 - w; + int mp_offset = ((sprite_header->width + 1) * 4) - w; + byte *mp = (byte*)sprite_header + sprite_header->mask; + bool alpha = ((unsigned)sprite_header->mode & 0x80000000U) != 0; + + while (h-- > 0) { + int x = 0; + for(x = 0; x < w; x++) { + unsigned d = *dp++; + if (alpha) + *mp++ = (d >> 24) ^ 0xff; + else + *mp++ = (d < 0xff000000U) ? 0 : 0xff; + } + dp += dp_offset; + mp += mp_offset; + } + } + + return sprite_area; +} + + + + +/** + * Check to see whether 32bpp sprites are available. + * + * Rather than using Wimp_ReadSysInfo we test if 32bpp sprites are available + * in case the user has a 3rd party patch to enable them. + */ +static void thumbnail_test(void) +{ + unsigned int area_size; + osspriteop_area *sprite_area; + + /* try to create a 1x1 32bpp sprite */ + area_size = sizeof(osspriteop_area) + + sizeof(osspriteop_header) + sizeof(int); + if ((sprite_area = (osspriteop_area *)malloc(area_size)) == NULL) { + LOG("Insufficient memory to perform sprite test."); + return; + } + sprite_area->size = area_size + 1; + sprite_area->sprite_count = 0; + sprite_area->first = 16; + sprite_area->used = 16; + if (xosspriteop_create_sprite(osspriteop_NAME, sprite_area, + "test", false, 1, 1, (os_mode)tinct_SPRITE_MODE)) + thumbnail_32bpp_available = 0; + else + thumbnail_32bpp_available = 1; + free(sprite_area); +} + + +/* exported interface documented in riscos/bitmap.h */ +nserror riscos_bitmap_render(struct bitmap *bitmap, + struct hlcache_handle *content) +{ + struct thumbnail_save_area *save_area; + osspriteop_area *sprite_area = NULL; + osspriteop_header *sprite_header = NULL; + struct redraw_context ctx = { + .interactive = false, + .background_images = true, + .plot = &ro_plotters + }; + + assert(content); + assert(bitmap); + + LOG("content %p in bitmap %p", content, bitmap); + + /* check if we have access to 32bpp sprites natively */ + if (thumbnail_32bpp_available == -1) { + thumbnail_test(); + } + + /* if we don't support 32bpp sprites then we redirect to an 8bpp + * image and then convert back. + */ + if (thumbnail_32bpp_available != 1) { + sprite_area = thumbnail_create_8bpp(bitmap); + if (!sprite_area) + return false; + sprite_header = (osspriteop_header *)(sprite_area + 1); + } else { + const uint8_t *pixbufp = riscos_bitmap_get_buffer(bitmap); + if (!pixbufp || !bitmap->sprite_area) + return false; + sprite_area = bitmap->sprite_area; + sprite_header = (osspriteop_header *)(sprite_area + 1); + } + + /* set up the plotters */ + ro_plot_origin_x = 0; + ro_plot_origin_y = bitmap->height * 2; + + /* switch output and redraw */ + save_area = thumbnail_switch_output(sprite_area, sprite_header); + if (!save_area) { + if (thumbnail_32bpp_available != 1) + free(sprite_area); + return false; + } + rufl_invalidate_cache(); + colourtrans_set_gcol(os_COLOUR_WHITE, colourtrans_SET_BG_GCOL, + os_ACTION_OVERWRITE, 0); + + /* render the content */ + content_scaled_redraw(content, bitmap->width, bitmap->height, &ctx); + + thumbnail_restore_output(save_area); + rufl_invalidate_cache(); + + /* if we changed to 8bpp then go back to 32bpp */ + if (thumbnail_32bpp_available != 1) { + const uint8_t *pixbufp = riscos_bitmap_get_buffer(bitmap); + _kernel_oserror *error; + + if (!pixbufp || !bitmap->sprite_area) { + free(sprite_area); + return false; + } + error = _swix(Tinct_ConvertSprite, _INR(2,3), + sprite_header, + (osspriteop_header *)(bitmap->sprite_area + 1)); + free(sprite_area); + if (error) + return false; + } + + bitmap_modified(bitmap); + + return NSERROR_OK; +} + +static struct gui_bitmap_table bitmap_table = { + .create = riscos_bitmap_create, + .destroy = riscos_bitmap_destroy, + .set_opaque = bitmap_set_opaque, + .get_opaque = riscos_bitmap_get_opaque, + .test_opaque = bitmap_test_opaque, + .get_buffer = riscos_bitmap_get_buffer, + .get_rowstride = bitmap_get_rowstride, + .get_width = bitmap_get_width, + .get_height = bitmap_get_height, + .get_bpp = bitmap_get_bpp, + .save = riscos_bitmap_save, + .modified = bitmap_modified, + .render = riscos_bitmap_render, +}; + +struct gui_bitmap_table *riscos_bitmap_table = &bitmap_table; diff --git a/frontends/riscos/bitmap.h b/frontends/riscos/bitmap.h new file mode 100644 index 000000000..3aca30de6 --- /dev/null +++ b/frontends/riscos/bitmap.h @@ -0,0 +1,116 @@ +/* + * Copyright 2004 James Bursa <bursa@users.sourceforge.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _NETSURF_RISCOS_BITMAP_H_ +#define _NETSURF_RISCOS_BITMAP_H_ + +struct osspriteop_area; +struct osspriteop_header; +struct hlcache_handle; +struct bitmap; + +/** bitmap operations table */ +struct gui_bitmap_table *riscos_bitmap_table; + +/** save with full alpha channel (if not opaque) */ +#define BITMAP_SAVE_FULL_ALPHA (1 << 0) + +/** + * RISC OS wimp toolkit bitmap. + */ +struct bitmap { + int width; /**< width of bitmap */ + int height; /**< height of bitmap */ + + unsigned int state; /**< The bitmap attributes (opaque/dirty etc.) */ + + struct osspriteop_area *sprite_area; /**< Uncompressed data, or NULL */ +}; + +/** + * Convert bitmap to 8bpp sprite. + * + * \param bitmap the bitmap to convert. + * \return The converted sprite. + */ +struct osspriteop_area *riscos_bitmap_convert_8bpp(struct bitmap *bitmap); + +/** + * Render content into bitmap. + * + * \param bitmap the bitmap to draw to + * \param content content structure to render + * \return true on success and bitmap updated else false + */ +nserror riscos_bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content); + +/** + * Overlay a sprite onto the given bitmap + * + * \param bitmap bitmap object + * \param s 8bpp sprite to be overlayed onto bitmap + */ +void riscos_bitmap_overlay_sprite(struct bitmap *bitmap, const struct osspriteop_header *s); + +/** + * Create a bitmap. + * + * \param width width of image in pixels + * \param height width of image in pixels + * \param state the state to create the bitmap in. + * \return an opaque struct bitmap, or NULL on memory exhaustion + */ +void *riscos_bitmap_create(int width, int height, unsigned int state); + +/** + * Free a bitmap. + * + * \param vbitmap a bitmap, as returned by bitmap_create() + */ +void riscos_bitmap_destroy(void *vbitmap); + +/** + * Return a pointer to the pixel data in a bitmap. + * + * The pixel data is packed as BITMAP_FORMAT, possibly with padding at + * the end of rows. The width of a row in bytes is given by + * riscos_bitmap_get_rowstride(). + * + * \param vbitmap A bitmap as returned by riscos_bitmap_create() + * \return pointer to the pixel buffer + */ +unsigned char *riscos_bitmap_get_buffer(void *vbitmap); + +/** + * Gets whether a bitmap should be plotted opaque + * + * \param vbitmap A bitmap, as returned by riscos_bitmap_create() + */ +bool riscos_bitmap_get_opaque(void *vbitmap); + +/** + * Save a bitmap in the platform's native format. + * + * \param vbitmap a bitmap, as returned by bitmap_create() + * \param path pathname for file + * \param flags modify the behaviour of the save + * \return true on success, false on error and error reported + */ +bool riscos_bitmap_save(void *vbitmap, const char *path, unsigned flags); + +#endif diff --git a/frontends/riscos/buffer.c b/frontends/riscos/buffer.c new file mode 100644 index 000000000..7176c1c1c --- /dev/null +++ b/frontends/riscos/buffer.c @@ -0,0 +1,396 @@ +/* + * Copyright 2004, 2005 Richard Wilson <info@tinct.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <swis.h> +#include <oslib/colourtrans.h> +#include <oslib/os.h> +#include <oslib/osspriteop.h> +#include <oslib/wimp.h> +#include <oslib/wimpreadsysinfo.h> + +#include "utils/nsoption.h" +#include "utils/log.h" + +#include "riscos/buffer.h" +#include "riscos/gui.h" +#include "riscos/tinct.h" +#include "riscos/wimp.h" +#include "riscos/wimputils.h" + +#define BUFFER_EXCLUSIVE_USER_REDRAW "Only support pure user redraw (faster)" +//#define BUFFER_EMULATE_32BPP "Redirect to a 32bpp sprite and plot with Tinct" + +/** Absent from OSLib +*/ +#ifndef osspriteop_TYPEEXPANSION +#define osspriteop_TYPEEXPANSION ((osspriteop_mode_word) 0xFu) +#endif +#ifndef osspriteop_TYPE16BPP4K +#define osspriteop_TYPE16BPP4K ((osspriteop_mode_word) 0x10u) +#endif + +static void ro_gui_buffer_free(void); + + +/** The buffer characteristics +*/ +static osspriteop_area *buffer = NULL; +static char buffer_name[12] = "scr_buffer"; + +/** The current clip area +*/ +static os_box clipping; + +/** The current save area +*/ +static osspriteop_save_area *save_area; +static int context0; +static int context1; +static int context2; +static int context3; + +/** The current sprite mode +*/ +static os_mode mode; + + +/** + * Opens a buffer for writing to. + * + * The ro_plot_origin_ variables are updated to reflect the new screen origin, + * so the variables should be set before calling this function, and not + * changed until after ro_gui_buffer_close() has been called. + * + * \param redraw the current WIMP redraw area to buffer + */ +void ro_gui_buffer_open(wimp_draw *redraw) +{ + int size; + int total_size; + os_coord sprite_size; + int bpp, word_width; + bool palette; + os_error *error; + int palette_size = 0; +#ifdef BUFFER_EXCLUSIVE_USER_REDRAW + osspriteop_header *header; +#endif + + /* Close any open buffer + */ + if (buffer) + ro_gui_buffer_close(); + + /* Store our clipping region + */ + clipping = redraw->clip; + + /* Stop bad rectangles + */ + if ((clipping.x1 < clipping.x0) || + (clipping.y1 < clipping.y0)) { + LOG("Invalid clipping rectangle (%i, %i) to (%i,%i)", clipping.x0, clipping.y0, clipping.x1, clipping.y1); + return; + } + + /* Work out how much buffer we need + */ + sprite_size.x = clipping.x1 - clipping.x0 + 1; + sprite_size.y = clipping.y1 - clipping.y0 + 1; + ro_convert_os_units_to_pixels(&sprite_size, (os_mode)-1); + if (sprite_size.y == 1) /* work around SpriteExtend bug */ + sprite_size.y = 2; + +#ifdef BUFFER_EMULATE_32BPP + bpp = 5; + palette = false; +#else + /* Get the screen depth as we can't use palettes for >8bpp + */ + xos_read_mode_variable((os_mode)-1, os_MODEVAR_LOG2_BPP, &bpp, 0); + palette = (bpp < 4); +#endif + + /* Get our required buffer size + */ + word_width = ((sprite_size.x << bpp) + 31) >> 5; + if (palette) + palette_size = ((1 << (1 << bpp)) << 3); + total_size = sizeof(osspriteop_area) + sizeof(osspriteop_header) + + (word_width * sprite_size.y * 4) + palette_size; + buffer = (osspriteop_area *)malloc(total_size); + if (!buffer) { + LOG("Failed to allocate memory"); + ro_gui_buffer_free(); + return; + } + buffer->size = total_size; + buffer->first = 16; + +#ifdef BUFFER_EMULATE_32BPP + mode = tinct_SPRITE_MODE; +#else + if ((error = xwimpreadsysinfo_wimp_mode(&mode)) != NULL) { + LOG("Error reading mode '%s'", error->errmess); + ro_gui_buffer_free(); + return; + } + + /* if we're not in a numbered screen mode then we need + to build a suitable sprite mode word */ + if (mode >= (os_mode)0x100) { + static const ns_os_vdu_var_list vars = { + os_MODEVAR_LOG2_BPP, + { + os_MODEVAR_MODE_FLAGS, + os_MODEVAR_NCOLOUR, + os_MODEVAR_XEIG_FACTOR, + os_MODEVAR_YEIG_FACTOR, + os_VDUVAR_END_LIST + } + }; + struct { + int log2bpp; + int flags; + int ncolour; + int xeig, yeig; + } vals; + int type; + + error = xos_read_vdu_variables(PTR_OS_VDU_VAR_LIST(&vars), (int *)&vals); + if (error) { + LOG("Error reading mode properties '%s'", error->errmess); + ro_gui_buffer_free(); + return; + } + + switch (vals.ncolour) { + case 1: + case 3: + case 15: + case 63: + case 255: + /* Paletted modes are pixel packing order agnostic */ + type = 1 + vals.log2bpp; + mode = (os_mode)((type << osspriteop_TYPE_SHIFT) | + osspriteop_NEW_STYLE | + ((180 >> vals.yeig) << osspriteop_YRES_SHIFT) | + ((180 >> vals.xeig) << osspriteop_XRES_SHIFT)); + break; + case 4095: + /* 16bpp 4k colours */ + type = osspriteop_TYPE16BPP4K; + mode = (os_mode)((osspriteop_TYPEEXPANSION << osspriteop_TYPE_SHIFT) | + osspriteop_NEW_STYLE | + (vals.yeig << 6) | + (vals.xeig << 4) | + (type << 20) | + (vals.flags & 0xFF00)); + break; + case 65535: + switch ((vals.flags & 0x3000) >> os_MODE_FLAG_DATA_FORMAT_SHIFT) { + case os_MODE_FLAG_DATA_FORMAT_RGB: + if (vals.flags & 0xC000) { + /* Non VIDC packing order */ + if (vals.flags & os_MODE_FLAG_FULL_PALETTE) + type = osspriteop_TYPE16BPP64K; + else + type = osspriteop_TYPE16BPP; + mode = (os_mode)((osspriteop_TYPEEXPANSION << osspriteop_TYPE_SHIFT) | + osspriteop_NEW_STYLE | + (vals.yeig << 6) | + (vals.xeig << 4) | + (type << 20) | + (vals.flags & 0xFF00)); + } else { + /* VIDC packing order */ + if (vals.flags & os_MODE_FLAG_FULL_PALETTE) + type = osspriteop_TYPE16BPP64K; + else + type = osspriteop_TYPE16BPP; + mode = (os_mode)((type << osspriteop_TYPE_SHIFT) | + osspriteop_NEW_STYLE | + ((180 >> vals.yeig) << osspriteop_YRES_SHIFT) | + ((180 >> vals.xeig) << osspriteop_XRES_SHIFT)); + } + break; + default: + LOG("Unhandled 16bpp format from flags %d", vals.flags); + ro_gui_buffer_free(); + return; + } + break; + case -1: + /* 16M colours */ + switch ((vals.flags & 0x3000) >> os_MODE_FLAG_DATA_FORMAT_SHIFT) { + case os_MODE_FLAG_DATA_FORMAT_RGB: + if (vals.flags & 0xC000) { + /* Non VIDC packing order */ + type = osspriteop_TYPE32BPP; + mode = (os_mode)((osspriteop_TYPEEXPANSION << osspriteop_TYPE_SHIFT) | + osspriteop_NEW_STYLE | + (vals.yeig << 6) | + (vals.xeig << 4) | + (type << 20) | + (vals.flags & 0xFF00)); + } else { + /* VIDC packing order */ + type = osspriteop_TYPE32BPP; + mode = (os_mode)((type << osspriteop_TYPE_SHIFT) | + osspriteop_NEW_STYLE | + ((180 >> vals.yeig) << osspriteop_YRES_SHIFT) | + ((180 >> vals.xeig) << osspriteop_XRES_SHIFT)); + } + break; + default: + LOG("Unhandled 32bpp data format from flags %d", vals.flags); + ro_gui_buffer_free(); + return; + } + break; + default: + LOG("Unhandled NCOLOUR value %d", vals.ncolour); + ro_gui_buffer_free(); + return; + } + } +#endif + +#ifdef BUFFER_EXCLUSIVE_USER_REDRAW + /* Create the sprite manually so we don't waste time clearing the + background. + */ + buffer->sprite_count = 1; + buffer->used = total_size; + header = (osspriteop_header *)(buffer + 1); + header->size = total_size - sizeof(osspriteop_area); + memcpy(header->name, buffer_name, 12); + header->width = word_width - 1; + header->height = sprite_size.y - 1; + header->left_bit = 0; + header->right_bit = ((sprite_size.x << bpp) - 1) & 31; + header->image = sizeof(osspriteop_header) + palette_size; + header->mask = header->image; + header->mode = mode; + if (palette) + xcolourtrans_read_palette((osspriteop_area *)mode, + (osspriteop_id)os_CURRENT_MODE, + (os_palette *)(header + 1), palette_size, + (colourtrans_palette_flags) + colourtrans_FLASHING_PALETTE, 0); +#else + /* Read the current contents of the screen + */ + buffer->sprite_count = 0; + buffer->used = 16; + if ((error = xosspriteop_get_sprite_user_coords(osspriteop_NAME, + buffer, buffer_name, palette, + clipping.x0, clipping.y0, + clipping.x1, clipping.y1)) != NULL) { + LOG("Grab error '%s'", error->errmess); + ro_gui_buffer_free(); + return; + } +#endif + /* Allocate OS_SpriteOp save area + */ + if ((error = xosspriteop_read_save_area_size(osspriteop_PTR, + buffer, (osspriteop_id)(buffer + 1), &size)) != NULL) { + LOG("Save area error '%s'", error->errmess); + ro_gui_buffer_free(); + return; + } + if ((save_area = malloc((size_t)size)) == NULL) { + ro_gui_buffer_free(); + return; + } + save_area->a[0] = 0; + + /* Switch output to sprite + */ + if ((error = xosspriteop_switch_output_to_sprite(osspriteop_PTR, + buffer, (osspriteop_id)(buffer + 1), save_area, + &context0, &context1, &context2, &context3)) != NULL) { + LOG("Switching error '%s'", error->errmess); + free(save_area); + ro_gui_buffer_free(); + return; + } + + /* Emulate an origin as the FontManager doesn't respect it in + most cases. + */ + ro_plot_origin_x -= clipping.x0; + ro_plot_origin_y -= clipping.y0; + + /* Update the ECF origin + */ + if ((error = xos_set_ecf_origin(-ro_plot_origin_x, + -ro_plot_origin_y)) != NULL) { + LOG("Invalid ECF origin: '%s'", error->errmess); + } +} + + +/** + * Closes any open buffer and flushes the contents to screen + */ +void ro_gui_buffer_close(void) +{ + /* Check we have an open buffer + */ + if (!buffer) + return; + + /* Remove any previous redirection + */ + ro_plot_origin_x += clipping.x0; + ro_plot_origin_y += clipping.y0; + xosspriteop_unswitch_output(context0, context1, context2, context3); + free(save_area); + + /* Plot the contents to screen + */ + if (mode == tinct_SPRITE_MODE) + _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7), + (char *)(buffer + 1), + clipping.x0, clipping.y0, + nsoption_int(plot_fg_quality)); + else + xosspriteop_put_sprite_user_coords(osspriteop_PTR, + buffer, (osspriteop_id)(buffer + 1), + clipping.x0, clipping.y0, (os_action)0); + ro_gui_buffer_free(); + + /* Update the ECF origin + */ + os_set_ecf_origin(0, 0); +} + + +/** + * Releases any buffer memory depending on cache constraints. + */ +static void ro_gui_buffer_free(void) +{ + free(buffer); + buffer = NULL; +} diff --git a/frontends/riscos/buffer.h b/frontends/riscos/buffer.h new file mode 100644 index 000000000..a683c324c --- /dev/null +++ b/frontends/riscos/buffer.h @@ -0,0 +1,31 @@ +/* + * Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * Screen buffering (interface). + */ + +#ifndef _NETSURF_RISCOS_BUFFER_H_ +#define _NETSURF_RISCOS_BUFFER_H_ + +#include "oslib/wimp.h" + +void ro_gui_buffer_open(wimp_draw *redraw); +void ro_gui_buffer_close(void); + +#endif diff --git a/frontends/riscos/configure.c b/frontends/riscos/configure.c new file mode 100644 index 000000000..9d28616ec --- /dev/null +++ b/frontends/riscos/configure.c @@ -0,0 +1,410 @@ +/* + * Copyright 2005 Richard Wilson <info@tinct.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * \file + * RISC OS option setting (implementation). + */ + +#include <assert.h> +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <oslib/os.h> +#include <oslib/osbyte.h> +#include <oslib/territory.h> +#include <oslib/wimp.h> + +#include "utils/log.h" +#include "utils/messages.h" + +#include "riscos/gui.h" +#include "riscos/dialog.h" +#include "riscos/configure.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" +#include "riscos/configure/configure.h" + +#define CONFIGURE_ICON_PADDING_H 32 +#define CONFIGURE_ICON_PADDING_V 32 +#define CONFIGURE_DEFAULT_ICON_WIDTH (68 + CONFIGURE_ICON_PADDING_H) +#define CONFIGURE_DEFAULT_ICON_HEIGHT (128 + CONFIGURE_ICON_PADDING_V) + +struct configure_tool { + const char *name; +#define CONFIGURE_TOOL_TRANSLATED_SIZE 64 + char translated[CONFIGURE_TOOL_TRANSLATED_SIZE]; + char *validation; + bool (*initialise)(wimp_w w); + void (*finalise)(wimp_w w); + wimp_w w; + wimp_i i; + bool open; + struct configure_tool *next; +}; + +static wimp_w configure_window; +static int configure_current_encoding; +static int configure_icons = 0; +static struct configure_tool *configure_tools = NULL; +static int configure_icon_width = CONFIGURE_DEFAULT_ICON_WIDTH; +static int configure_icon_height = CONFIGURE_DEFAULT_ICON_HEIGHT; +static int configure_icons_per_line = 0; +static int configure_width; +static int configure_height; + +static bool ro_gui_configure_click(wimp_pointer *pointer); +static void ro_gui_configure_open_window(wimp_open *open); +static void ro_gui_configure_close(wimp_w w); +static bool ro_gui_configure_translate(void); +static void ro_gui_configure_register(const char *window, + bool (*initialise)(wimp_w w), void (*finalise)(wimp_w w)); + +void ro_gui_configure_initialise(void) +{ + /* create our window */ + configure_window = ro_gui_dialog_create("configure"); + ro_gui_wimp_event_register_open_window(configure_window, + ro_gui_configure_open_window); + ro_gui_wimp_event_register_mouse_click(configure_window, + ro_gui_configure_click); + ro_gui_wimp_event_set_help_prefix(configure_window, "HelpConfigure"); + + /* add in our option windows */ + ro_gui_configure_register("con_cache", + ro_gui_options_cache_initialise, + ro_gui_wimp_event_finalise); + ro_gui_configure_register("con_connect", + ro_gui_options_connection_initialise, + ro_gui_wimp_event_finalise); + ro_gui_configure_register("con_content", + ro_gui_options_content_initialise, + ro_gui_wimp_event_finalise); + ro_gui_configure_register("con_fonts", + ro_gui_options_fonts_initialise, + ro_gui_wimp_event_finalise); + ro_gui_configure_register("con_home", + ro_gui_options_home_initialise, + ro_gui_wimp_event_finalise); + ro_gui_configure_register("con_image", + ro_gui_options_image_initialise, + ro_gui_options_image_finalise); + ro_gui_configure_register("con_inter", + ro_gui_options_interface_initialise, + ro_gui_wimp_event_finalise); + ro_gui_configure_register("con_lang", + ro_gui_options_language_initialise, + ro_gui_wimp_event_finalise); + ro_gui_configure_register("con_theme", + ro_gui_options_theme_initialise, + ro_gui_options_theme_finalise); + ro_gui_configure_register("con_secure", + ro_gui_options_security_initialise, + ro_gui_wimp_event_finalise); + + /* translate the icons */ + if (!ro_gui_configure_translate()) + die("ro_gui_configure_translate failed"); +} + +void ro_gui_configure_show(void) +{ + int width, height; + + width = configure_icon_width << 2; + height = ((configure_icons + 3) >> 2) * configure_icon_height; + ro_gui_dialog_open_top(configure_window, NULL, width, height); +} + +bool ro_gui_configure_click(wimp_pointer *pointer) +{ + struct configure_tool *tool; + + if (pointer->buttons == wimp_CLICK_MENU) + return true; + + for (tool = configure_tools; tool; tool = tool->next) { + if (tool->i == pointer->i) { + if (!tool->open) { + tool->open = true; + if (!tool->initialise(tool->w)) + return false; + ro_gui_dialog_open_persistent( + configure_window, + tool->w, true); + ro_gui_wimp_event_register_close_window( + tool->w, + ro_gui_configure_close); + } else { + ro_gui_dialog_open_top(tool->w, NULL, 0, 0); + } + break; + } + } + return true; +} + +void ro_gui_configure_close(wimp_w w) +{ + struct configure_tool *tool; + + for (tool = configure_tools; tool; tool = tool->next) { + if (tool->w == w) { + tool->open = false; + if (tool->finalise) + tool->finalise(w); + break; + } + } +} + +void ro_gui_configure_open_window(wimp_open *open) +{ + os_error *error; + int screen_width, screen_height; + int height, width; + int icons_per_line, icon_lines; + int max_height; + os_box extent = { 0, 0, 0, 0 }; + struct configure_tool *tool; + + if (!ro_gui_configure_translate()) { + ro_warn_user("ro_gui_configure_translate failed", 0); + return; + } + + width = open->visible.x1 - open->visible.x0; + height = open->visible.y1 - open->visible.y0; + icons_per_line = width / configure_icon_width; + if (icons_per_line < 1) + icons_per_line = 1; + + /* move our icons */ + if (icons_per_line != configure_icons_per_line) { + int x, y, l; + configure_icons_per_line = icons_per_line; + x = CONFIGURE_ICON_PADDING_H / 2; + y = -configure_icon_height + (CONFIGURE_ICON_PADDING_V / 2); + l = 0; + for (tool = configure_tools; tool; tool = tool->next) { + error = xwimp_resize_icon(configure_window, + tool->i, + x, + y, + x + configure_icon_width - + CONFIGURE_ICON_PADDING_H, + y + configure_icon_height - + CONFIGURE_ICON_PADDING_V); + if (error) { + LOG("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess); + } + x += configure_icon_width; + l++; + if (l >= icons_per_line) { + x = CONFIGURE_ICON_PADDING_H / 2; + l = 0; + y -= configure_icon_height; + } + } + error = xwimp_force_redraw(configure_window, + 0, -16384, 16384, 0); + if (error) { + LOG("xwimp_force_redraw: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + } + + /* restrict our height */ + icon_lines = (configure_icons + icons_per_line - 1) / + icons_per_line; + max_height = (icon_lines * configure_icon_height); + if (height > max_height) + open->visible.y0 = open->visible.y1 - max_height; + + /* set the extent */ + if ((configure_height != height) || (configure_width != width)) { + int max_icons_per_line; + ro_gui_screen_size(&screen_width, &screen_height); + max_icons_per_line = screen_width / configure_icon_width; + if (max_icons_per_line > configure_icons) + max_icons_per_line = configure_icons; + extent.x1 = configure_icon_width * max_icons_per_line; + extent.y0 = -max_height; + error = xwimp_set_extent(open->w, &extent); + if (error) { + LOG("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + return; + } + configure_height = height; + configure_width = width; + } + + /* open the window */ + error = xwimp_open_window(open); + if (error) { + LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + return; + } +} + +void ro_gui_configure_register(const char *window, + bool (*initialise)(wimp_w w), void (*finalise)(wimp_w w)) +{ + wimp_icon_create new_icon; + struct configure_tool *tool; + struct configure_tool *link; + os_error *error; + + /* create our tool */ + tool = calloc(sizeof(struct configure_tool), 1); + if (!tool) { + LOG("Insufficient memory for calloc()"); + die("Insufficient memory"); + return; /* For the benefit of scan-build */ + } + tool->name = window; + tool->translated[0] = '\0'; + tool->validation = malloc(strlen(window) + 2); + if (!tool->validation) { + LOG("Insufficient memory for malloc()"); + die("Insufficient memory"); + } + sprintf(tool->validation, "S%s", window); + tool->initialise = initialise; + tool->finalise = finalise; + tool->w = ro_gui_dialog_create(tool->name); + + /* create the icon */ + new_icon.w = configure_window; + new_icon.icon.extent.x0 = 0; + new_icon.icon.extent.x1 = configure_icon_width; + new_icon.icon.extent.y1 = 0; + new_icon.icon.extent.y0 = -configure_icon_height; + new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE | + wimp_ICON_INDIRECTED | wimp_ICON_HCENTRED | + (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT) | + (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | + (wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT); + new_icon.icon.data.indirected_text_and_sprite.text = + tool->translated; + new_icon.icon.data.indirected_text_and_sprite.validation = + tool->validation; + new_icon.icon.data.indirected_text_and_sprite.size = + CONFIGURE_TOOL_TRANSLATED_SIZE; + error = xwimp_create_icon(&new_icon, &tool->i); + if (error) { + LOG("xwimp_create_icon: 0x%x: %s", error->errnum, error->errmess); + die(error->errmess); + } + + /* Set the icon's text in current local encoding */ + ro_gui_set_icon_string(configure_window, tool->i, + messages_get(tool->name), true); + + /* link into our list alphabetically */ + if ((!configure_tools) || + (strcmp(configure_tools->translated, + tool->translated) > 0)) { + tool->next = configure_tools; + configure_tools = tool; + } else { + for (link = configure_tools; link; link = link->next) { + if (link->next) { + if (strcmp(link->next->translated, + tool->translated) > 0) { + tool->next = link->next; + link->next = tool; + break; + } + } else { + link->next = tool; + break; + } + } + } + configure_icons++; +} + +/** + * Translate tool icons into the system local encoding. + * This will also recalculate the minimum required icon width. + * + * \return true on success, false on memory exhaustion + */ +bool ro_gui_configure_translate(void) +{ + int alphabet; + struct configure_tool *tool; + int icon_width; + os_error *error; + + /* read current alphabet */ + error = xosbyte1(osbyte_ALPHABET_NUMBER, 127, 0, + &alphabet); + if (error) { + LOG("failed reading alphabet: 0x%x: %s", error->errnum, error->errmess); + /* assume Latin1 */ + alphabet = territory_ALPHABET_LATIN1; + } + + if (alphabet == configure_current_encoding) + /* text is already in the correct encoding */ + return true; + + /* reset icon width */ + configure_icon_width = CONFIGURE_DEFAULT_ICON_WIDTH; + + for (tool = configure_tools; tool; tool = tool->next) { + /* re-translate the text */ + ro_gui_set_icon_string(configure_window, tool->i, + messages_get(tool->name), true); + + /* update the width */ + error = xwimptextop_string_width(tool->translated, + strlen(tool->translated), &icon_width); + if (error) { + LOG("xwimptextop_string_width: 0x%x: %s", error->errnum, error->errmess); + return false; + } + icon_width += CONFIGURE_ICON_PADDING_H; + if (icon_width > configure_icon_width) + configure_icon_width = icon_width; + + error = xwimp_resize_icon(configure_window, + tool->i, + 0, + -configure_icon_height, + configure_icon_width, + 0); + if (error) { + LOG("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess); + } + } + + /* invalidate our global icons_per_line setting + * so the icons get reflowed */ + configure_icons_per_line = 0; + + /* finally, set the current encoding */ + configure_current_encoding = alphabet; + + return true; +} diff --git a/frontends/riscos/configure.h b/frontends/riscos/configure.h new file mode 100644 index 000000000..c190a6d0c --- /dev/null +++ b/frontends/riscos/configure.h @@ -0,0 +1,34 @@ +/* + * Copyright 2005 Richard Wilson <info@tinct.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * RISC OS option setting (interface). + */ + + +#ifndef _NETSURF_RISCOS_CONFIGURE_H_ +#define _NETSURF_RISCOS_CONFIGURE_H_ + +#include <stdbool.h> +#include "oslib/os.h" +#include "oslib/wimp.h" + +void ro_gui_configure_initialise(void); +void ro_gui_configure_show(void); + +#endif diff --git a/frontends/riscos/configure/con_cache.c b/frontends/riscos/configure/con_cache.c new file mode 100644 index 000000000..730d6f82f --- /dev/null +++ b/frontends/riscos/configure/con_cache.c @@ -0,0 +1,107 @@ +/* + * Copyright 2005 Richard Wilson <info@tinct.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include <oslib/hourglass.h> + +#include "utils/nsoption.h" +#include "utils/filename.h" +#include "utils/messages.h" + +#include "riscos/gui.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" +#include "riscos/configure.h" +#include "riscos/configure/configure.h" +#include "riscos/dialog.h" + + +#define CACHE_MEMORY_SIZE 3 +#define CACHE_MEMORY_DEC 4 +#define CACHE_MEMORY_INC 5 +#define CACHE_DISC_SIZE 10 +#define CACHE_DISC_DEC 11 +#define CACHE_DISC_INC 12 +#define CACHE_DISC_EXPIRE 15 +#define CACHE_DISC_EXPIRE_DEC 16 +#define CACHE_DISC_EXPIRE_INC 17 +#define CACHE_DEFAULT_BUTTON 19 +#define CACHE_CANCEL_BUTTON 20 +#define CACHE_OK_BUTTON 21 + +static bool ro_gui_options_cache_click(wimp_pointer *pointer); +static bool ro_gui_options_cache_ok(wimp_w w); + +bool ro_gui_options_cache_initialise(wimp_w w) +{ + /* set the current values */ + ro_gui_set_icon_decimal(w, CACHE_MEMORY_SIZE, + (nsoption_int(memory_cache_size) * 10) >> 20, 1); + ro_gui_set_icon_decimal(w, CACHE_DISC_SIZE, + (int) ((nsoption_uint(disc_cache_size)) >> 20), 0); + ro_gui_set_icon_decimal(w, CACHE_DISC_EXPIRE, + (nsoption_int(disc_cache_age)), 0); + + /* initialise all functions for a newly created window */ + ro_gui_wimp_event_register_numeric_field(w, CACHE_MEMORY_SIZE, + CACHE_MEMORY_INC, CACHE_MEMORY_DEC, 0, 640, 1, 1); + ro_gui_wimp_event_register_numeric_field(w, CACHE_DISC_SIZE, + CACHE_DISC_INC, CACHE_DISC_DEC, 0, 4095, 1, 0); + ro_gui_wimp_event_register_numeric_field(w, CACHE_DISC_EXPIRE, + CACHE_DISC_EXPIRE_INC, CACHE_DISC_EXPIRE_DEC, 1, 3650, + 1, 0); + ro_gui_wimp_event_register_mouse_click(w, ro_gui_options_cache_click); + ro_gui_wimp_event_register_cancel(w, CACHE_CANCEL_BUTTON); + ro_gui_wimp_event_register_ok(w, CACHE_OK_BUTTON, + ro_gui_options_cache_ok); + ro_gui_wimp_event_set_help_prefix(w, "HelpCacheConfig"); + ro_gui_wimp_event_memorise(w); + return true; + +} + +bool ro_gui_options_cache_click(wimp_pointer *pointer) +{ + switch (pointer->i) { + case CACHE_DEFAULT_BUTTON: + /* set the default values */ + ro_gui_set_icon_decimal(pointer->w, CACHE_MEMORY_SIZE, + 120, 1); + ro_gui_set_icon_decimal(pointer->w, CACHE_DISC_SIZE, + 1024, 0); + ro_gui_set_icon_decimal(pointer->w, CACHE_DISC_EXPIRE, + 28, 0); + return true; + } + return false; +} + +bool ro_gui_options_cache_ok(wimp_w w) +{ + nsoption_set_int(memory_cache_size, + (((ro_gui_get_icon_decimal(w, + CACHE_MEMORY_SIZE, 1) + 1) << 20) - 1) / 10); + nsoption_set_uint(disc_cache_size, + (uint) (ro_gui_get_icon_decimal(w, + CACHE_DISC_SIZE, 0) << 20)); + nsoption_set_int(disc_cache_age, + ro_gui_get_icon_decimal(w, CACHE_DISC_EXPIRE, 0)); + + ro_gui_save_options(); + return true; +} diff --git a/frontends/riscos/configure/con_connect.c b/frontends/riscos/configure/con_connect.c new file mode 100644 index 000000000..9515c5d6f --- /dev/null +++ b/frontends/riscos/configure/con_connect.c @@ -0,0 +1,220 @@ +/* + * Copyright 2006 Richard Wilson <info@tinct.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include "swis.h" +#include "oslib/osspriteop.h" +#include "oslib/wimp.h" + +#include "utils/nsoption.h" +#include "utils/log.h" + +#include "riscos/configure/configure.h" +#include "riscos/dialog.h" +#include "riscos/menus.h" +#include "riscos/tinct.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" + + +#define CONNECTION_PROXY_FIELD 3 +#define CONNECTION_PROXY_MENU 4 +#define CONNECTION_PROXY_HOST_LABEL 5 +#define CONNECTION_PROXY_HOST 6 +#define CONNECTION_PROXY_PORT_LABEL 7 +#define CONNECTION_PROXY_PORT 8 +#define CONNECTION_PROXY_USERNAME_LABEL 9 +#define CONNECTION_PROXY_USERNAME 10 +#define CONNECTION_PROXY_PASSWORD_LABEL 11 +#define CONNECTION_PROXY_PASSWORD 12 +#define CONNECTION_MAX_FETCH_FIELD 16 +#define CONNECTION_MAX_FETCH_DEC 17 +#define CONNECTION_MAX_FETCH_INC 18 +#define CONNECTION_HOST_FETCH_FIELD 20 +#define CONNECTION_HOST_FETCH_DEC 21 +#define CONNECTION_HOST_FETCH_INC 22 +#define CONNECTION_CACHE_FETCH_FIELD 24 +#define CONNECTION_CACHE_FETCH_DEC 25 +#define CONNECTION_CACHE_FETCH_INC 26 +#define CONNECTION_DEFAULT_BUTTON 27 +#define CONNECTION_CANCEL_BUTTON 28 +#define CONNECTION_OK_BUTTON 29 + +#define http_proxy_type (nsoption_bool(http_proxy) ? (nsoption_int(http_proxy_auth) + 1) : 0) + +static int ro_gui_options_connection_proxy_type(wimp_w w); +static void ro_gui_options_connection_default(wimp_pointer *pointer); +static bool ro_gui_options_connection_ok(wimp_w w); +static bool ro_gui_options_connection_update(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a); + +bool ro_gui_options_connection_initialise(wimp_w w) +{ + int proxy_type; + + /* set the current values */ + proxy_type = (nsoption_bool(http_proxy) ? (nsoption_int(http_proxy_auth) + 1) : 0); + ro_gui_set_icon_string(w, CONNECTION_PROXY_FIELD, + proxy_type_menu->entries[proxy_type]. + data.indirected_text.text, true); + ro_gui_set_icon_string(w, CONNECTION_PROXY_HOST, + nsoption_charp(http_proxy_host) ? + nsoption_charp(http_proxy_host) : "", true); + ro_gui_set_icon_integer(w, CONNECTION_PROXY_PORT, + nsoption_int(http_proxy_port)); + ro_gui_set_icon_string(w, CONNECTION_PROXY_USERNAME, + nsoption_charp(http_proxy_auth_user) ? + nsoption_charp(http_proxy_auth_user) : "", true); + ro_gui_set_icon_string(w, CONNECTION_PROXY_PASSWORD, + nsoption_charp(http_proxy_auth_pass) ? + nsoption_charp(http_proxy_auth_pass) : "", true); + ro_gui_set_icon_integer(w, CONNECTION_MAX_FETCH_FIELD, + nsoption_int(max_fetchers)); + ro_gui_set_icon_integer(w, CONNECTION_HOST_FETCH_FIELD, + nsoption_int(max_fetchers_per_host)); + ro_gui_set_icon_integer(w, CONNECTION_CACHE_FETCH_FIELD, + nsoption_int(max_cached_fetch_handles)); + ro_gui_options_connection_update(w, -1, NULL, NULL, NO_ACTION); + + /* register icons */ + ro_gui_wimp_event_register_menu_gright(w, CONNECTION_PROXY_FIELD, + CONNECTION_PROXY_MENU, proxy_type_menu); + ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_HOST_LABEL); + ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_HOST); + ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_PORT_LABEL); + ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_PORT); + ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_USERNAME_LABEL); + ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_USERNAME); + ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_PASSWORD_LABEL); + ro_gui_wimp_event_register_text_field(w, CONNECTION_PROXY_PASSWORD); + ro_gui_wimp_event_register_numeric_field(w, CONNECTION_MAX_FETCH_FIELD, + CONNECTION_MAX_FETCH_INC, CONNECTION_MAX_FETCH_DEC, + 1, 99, 1, 0); + ro_gui_wimp_event_register_numeric_field(w, CONNECTION_HOST_FETCH_FIELD, + CONNECTION_HOST_FETCH_INC, CONNECTION_HOST_FETCH_DEC, + 1, 99, 1, 0); + ro_gui_wimp_event_register_numeric_field(w, CONNECTION_CACHE_FETCH_FIELD, + CONNECTION_CACHE_FETCH_INC, CONNECTION_CACHE_FETCH_DEC, + 1, 99, 1, 0); + ro_gui_wimp_event_register_menu_selection(w, + ro_gui_options_connection_update); + ro_gui_wimp_event_register_button(w, CONNECTION_DEFAULT_BUTTON, + ro_gui_options_connection_default); + ro_gui_wimp_event_register_cancel(w, CONNECTION_CANCEL_BUTTON); + ro_gui_wimp_event_register_ok(w, CONNECTION_OK_BUTTON, + ro_gui_options_connection_ok); + + ro_gui_wimp_event_set_help_prefix(w, "HelpConnectConfig"); + ro_gui_wimp_event_memorise(w); + return true; + +} + +bool ro_gui_options_connection_update(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a) +{ + int proxy_type; + bool host, user; + + /* update the shaded state */ + proxy_type = ro_gui_options_connection_proxy_type(w); + host = (proxy_type > 0); + user = (proxy_type > 1); + + ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_HOST_LABEL, !host); + ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_HOST, !host); + ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_PORT_LABEL, !host); + ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_PORT, !host); + ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_USERNAME_LABEL, !user); + ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_USERNAME, !user); + ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_PASSWORD_LABEL, !user); + ro_gui_set_icon_shaded_state(w, CONNECTION_PROXY_PASSWORD, !user); + + return true; +} + +int ro_gui_options_connection_proxy_type(wimp_w w) +{ + const char *text; + int i; + + text = ro_gui_get_icon_string(w, CONNECTION_PROXY_FIELD); + for (i = 0; (i < 4); i++) + if (!strcmp(text, proxy_type_menu->entries[i]. + data.indirected_text.text)) + return i; + assert(false); +} + +void ro_gui_options_connection_default(wimp_pointer *pointer) +{ + ro_gui_set_icon_string(pointer->w, CONNECTION_PROXY_FIELD, + proxy_type_menu->entries[0]. + data.indirected_text.text, true); + ro_gui_set_icon_string(pointer->w, CONNECTION_PROXY_HOST, "", true); + ro_gui_set_icon_integer(pointer->w, CONNECTION_PROXY_PORT, 8080); + ro_gui_set_icon_string(pointer->w, CONNECTION_PROXY_USERNAME, "", true); + ro_gui_set_icon_string(pointer->w, CONNECTION_PROXY_PASSWORD, "", true); + ro_gui_set_icon_integer(pointer->w, CONNECTION_MAX_FETCH_FIELD, 24); + ro_gui_set_icon_integer(pointer->w, CONNECTION_HOST_FETCH_FIELD, 5); + ro_gui_set_icon_integer(pointer->w, CONNECTION_CACHE_FETCH_FIELD, 6); + ro_gui_options_connection_update(pointer->w, -1, NULL, NULL, NO_ACTION); +} + +bool ro_gui_options_connection_ok(wimp_w w) +{ + int proxy_type; + + proxy_type = ro_gui_options_connection_proxy_type(w); + if (proxy_type == 0) { + nsoption_set_bool(http_proxy, false); + } else { + nsoption_set_bool(http_proxy, true); + nsoption_set_int(http_proxy_auth, proxy_type - 1); + } + + nsoption_set_charp(http_proxy_host, + strdup(ro_gui_get_icon_string(w, + CONNECTION_PROXY_HOST))); + + nsoption_set_int(http_proxy_port, + ro_gui_get_icon_decimal(w, CONNECTION_PROXY_PORT, 0)); + + nsoption_set_charp(http_proxy_auth_user, + strdup(ro_gui_get_icon_string(w, + CONNECTION_PROXY_USERNAME))); + + nsoption_set_charp(http_proxy_auth_pass, + strdup(ro_gui_get_icon_string(w, + CONNECTION_PROXY_PASSWORD))); + + nsoption_set_int(max_fetchers, + ro_gui_get_icon_decimal(w, + CONNECTION_MAX_FETCH_FIELD, 0)); + + nsoption_set_int(max_fetchers_per_host, + ro_gui_get_icon_decimal(w, + CONNECTION_HOST_FETCH_FIELD, 0)); + + nsoption_set_int(max_cached_fetch_handles, + ro_gui_get_icon_decimal(w, + CONNECTION_CACHE_FETCH_FIELD, 0)); + + ro_gui_save_options(); + return true; +} diff --git a/frontends/riscos/configure/con_content.c b/frontends/riscos/configure/con_content.c new file mode 100644 index 000000000..50bbd15ef --- /dev/null +++ b/frontends/riscos/configure/con_content.c @@ -0,0 +1,107 @@ +/* + * Copyright 2006 Richard Wilson <info@tinct.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> + +#include "utils/nsoption.h" +#include "utils/messages.h" + +#include "riscos/gui.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" +#include "riscos/configure.h" +#include "riscos/configure/configure.h" +#include "riscos/dialog.h" + +#define CONTENT_BLOCK_ADVERTISEMENTS 2 +#define CONTENT_BLOCK_POPUPS 3 +#define CONTENT_NO_PLUGINS 4 +#define CONTENT_TARGET_BLANK 7 +#define CONTENT_DEFAULT_BUTTON 8 +#define CONTENT_CANCEL_BUTTON 9 +#define CONTENT_OK_BUTTON 10 +#define CONTENT_NO_JAVASCRIPT 11 + +static void ro_gui_options_content_default(wimp_pointer *pointer); +static bool ro_gui_options_content_ok(wimp_w w); + +bool ro_gui_options_content_initialise(wimp_w w) +{ + /* set the current values */ + ro_gui_set_icon_selected_state(w, CONTENT_BLOCK_ADVERTISEMENTS, + nsoption_bool(block_advertisements)); + ro_gui_set_icon_selected_state(w, CONTENT_BLOCK_POPUPS, + nsoption_bool(block_popups)); + ro_gui_set_icon_selected_state(w, CONTENT_NO_PLUGINS, + nsoption_bool(no_plugins)); + ro_gui_set_icon_selected_state(w, CONTENT_TARGET_BLANK, + nsoption_bool(target_blank)); + ro_gui_set_icon_selected_state(w, CONTENT_NO_JAVASCRIPT, + !nsoption_bool(enable_javascript)); + + /* initialise all functions for a newly created window */ + ro_gui_wimp_event_register_checkbox(w, CONTENT_BLOCK_ADVERTISEMENTS); + ro_gui_wimp_event_register_checkbox(w, CONTENT_BLOCK_POPUPS); + ro_gui_wimp_event_register_checkbox(w, CONTENT_NO_PLUGINS); + ro_gui_wimp_event_register_checkbox(w, CONTENT_TARGET_BLANK); + ro_gui_wimp_event_register_checkbox(w, CONTENT_NO_JAVASCRIPT); + ro_gui_wimp_event_register_button(w, CONTENT_DEFAULT_BUTTON, + ro_gui_options_content_default); + ro_gui_wimp_event_register_cancel(w, CONTENT_CANCEL_BUTTON); + ro_gui_wimp_event_register_ok(w, CONTENT_OK_BUTTON, + ro_gui_options_content_ok); + ro_gui_wimp_event_set_help_prefix(w, "HelpContentConfig"); + ro_gui_wimp_event_memorise(w); + return true; + +} + +void ro_gui_options_content_default(wimp_pointer *pointer) +{ + /* set the default values */ + ro_gui_set_icon_selected_state(pointer->w, CONTENT_BLOCK_ADVERTISEMENTS, + false); + ro_gui_set_icon_selected_state(pointer->w, CONTENT_BLOCK_POPUPS, + false); + ro_gui_set_icon_selected_state(pointer->w, CONTENT_NO_PLUGINS, + false); + ro_gui_set_icon_selected_state(pointer->w, CONTENT_TARGET_BLANK, + true); + ro_gui_set_icon_selected_state(pointer->w, CONTENT_NO_JAVASCRIPT, + false); +} + +bool ro_gui_options_content_ok(wimp_w w) +{ + nsoption_set_bool(block_advertisements, + ro_gui_get_icon_selected_state(w, CONTENT_BLOCK_ADVERTISEMENTS)); + + nsoption_set_bool(block_popups, + ro_gui_get_icon_selected_state(w, CONTENT_BLOCK_POPUPS)); + nsoption_set_bool(no_plugins, + ro_gui_get_icon_selected_state(w, CONTENT_NO_PLUGINS)); + + nsoption_set_bool(target_blank, + ro_gui_get_icon_selected_state(w, CONTENT_TARGET_BLANK)); + + nsoption_set_bool(enable_javascript, + !ro_gui_get_icon_selected_state(w, CONTENT_NO_JAVASCRIPT)); + + ro_gui_save_options(); + return true; +} diff --git a/frontends/riscos/configure/con_fonts.c b/frontends/riscos/configure/con_fonts.c new file mode 100644 index 000000000..280312843 --- /dev/null +++ b/frontends/riscos/configure/con_fonts.c @@ -0,0 +1,209 @@ +/* + * Copyright 2005 Richard Wilson <info@tinct.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include <stddef.h> + +#include "utils/nsoption.h" +#include "utils/messages.h" +#include "desktop/plot_style.h" + +#include "riscos/gui.h" +#include "riscos/font.h" +#include "riscos/menus.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" +#include "riscos/configure.h" +#include "riscos/configure/configure.h" +#include "riscos/dialog.h" + + +#define FONT_SANS_FIELD 3 +#define FONT_SANS_MENU 4 +#define FONT_SERIF_FIELD 6 +#define FONT_SERIF_MENU 7 +#define FONT_MONOSPACE_FIELD 9 +#define FONT_MONOSPACE_MENU 10 +#define FONT_CURSIVE_FIELD 12 +#define FONT_CURSIVE_MENU 13 +#define FONT_FANTASY_FIELD 15 +#define FONT_FANTASY_MENU 16 +#define FONT_DEFAULT_FIELD 18 +#define FONT_DEFAULT_MENU 19 +#define FONT_DEFAULT_SIZE 23 +#define FONT_DEFAULT_DEC 24 +#define FONT_DEFAULT_INC 25 +#define FONT_MINIMUM_SIZE 28 +#define FONT_MINIMUM_DEC 29 +#define FONT_MINIMUM_INC 30 +#define FONT_DEFAULT_BUTTON 32 +#define FONT_CANCEL_BUTTON 33 +#define FONT_OK_BUTTON 34 + +/* This menu only ever gets created once */ +/** \todo The memory claimed for this menu should + * probably be released at some point */ +static wimp_menu *default_menu; + +static const char *font_names[PLOT_FONT_FAMILY_COUNT] = { + "Sans-serif", + "Serif", + "Monospace", + "Cursive", + "Fantasy" +}; + +static void ro_gui_options_fonts_default(wimp_pointer *pointer); +static bool ro_gui_options_fonts_ok(wimp_w w); +static bool ro_gui_options_fonts_init_menu(void); + +bool ro_gui_options_fonts_initialise(wimp_w w) +{ + /* set the current values */ + ro_gui_set_icon_decimal(w, FONT_DEFAULT_SIZE, nsoption_int(font_size), 1); + ro_gui_set_icon_decimal(w, FONT_MINIMUM_SIZE, nsoption_int(font_min_size), 1); + ro_gui_set_icon_string(w, FONT_SANS_FIELD, nsoption_charp(font_sans), true); + ro_gui_set_icon_string(w, FONT_SERIF_FIELD, nsoption_charp(font_serif), true); + ro_gui_set_icon_string(w, FONT_MONOSPACE_FIELD, nsoption_charp(font_mono), true); + ro_gui_set_icon_string(w, FONT_CURSIVE_FIELD, nsoption_charp(font_cursive), true); + ro_gui_set_icon_string(w, FONT_FANTASY_FIELD, nsoption_charp(font_fantasy), true); + ro_gui_set_icon_string(w, FONT_DEFAULT_FIELD, + font_names[nsoption_int(font_default)], true); + + if (!ro_gui_options_fonts_init_menu()) + return false; + + /* initialise all functions for a newly created window */ + ro_gui_wimp_event_register_menu_gright(w, FONT_SANS_FIELD, + FONT_SANS_MENU, rufl_family_menu); + ro_gui_wimp_event_register_menu_gright(w, FONT_SERIF_FIELD, + FONT_SERIF_MENU, rufl_family_menu); + ro_gui_wimp_event_register_menu_gright(w, FONT_MONOSPACE_FIELD, + FONT_MONOSPACE_MENU, rufl_family_menu); + ro_gui_wimp_event_register_menu_gright(w, FONT_CURSIVE_FIELD, + FONT_CURSIVE_MENU, rufl_family_menu); + ro_gui_wimp_event_register_menu_gright(w, FONT_FANTASY_FIELD, + FONT_FANTASY_MENU, rufl_family_menu); + ro_gui_wimp_event_register_menu_gright(w, FONT_DEFAULT_FIELD, + FONT_DEFAULT_MENU, default_menu); + ro_gui_wimp_event_register_numeric_field(w, FONT_DEFAULT_SIZE, + FONT_DEFAULT_INC, FONT_DEFAULT_DEC, 50, 1000, 1, 1); + ro_gui_wimp_event_register_numeric_field(w, FONT_MINIMUM_SIZE, + FONT_MINIMUM_INC, FONT_MINIMUM_DEC, 10, 500, 1, 1); + ro_gui_wimp_event_register_button(w, FONT_DEFAULT_BUTTON, + ro_gui_options_fonts_default); + ro_gui_wimp_event_register_cancel(w, FONT_CANCEL_BUTTON); + ro_gui_wimp_event_register_ok(w, FONT_OK_BUTTON, + ro_gui_options_fonts_ok); + ro_gui_wimp_event_set_help_prefix(w, "HelpFontConfig"); + ro_gui_wimp_event_memorise(w); + return true; + +} + +void ro_gui_options_fonts_default(wimp_pointer *pointer) +{ + const char *fallback = nsfont_fallback_font(); + + /* set the default values */ + ro_gui_set_icon_decimal(pointer->w, FONT_DEFAULT_SIZE, 128, 1); + ro_gui_set_icon_decimal(pointer->w, FONT_MINIMUM_SIZE, 85, 1); + ro_gui_set_icon_string(pointer->w, FONT_SANS_FIELD, + nsfont_exists("Homerton") ? "Homerton" : fallback, true); + ro_gui_set_icon_string(pointer->w, FONT_SERIF_FIELD, + nsfont_exists("Trinity") ? "Trinity" : fallback, true); + ro_gui_set_icon_string(pointer->w, FONT_MONOSPACE_FIELD, + nsfont_exists("Corpus") ? "Corpus" : fallback, true); + ro_gui_set_icon_string(pointer->w, FONT_CURSIVE_FIELD, + nsfont_exists("Churchill") ? "Churchill" : fallback, true); + ro_gui_set_icon_string(pointer->w, FONT_FANTASY_FIELD, + nsfont_exists("Sassoon") ? "Sassoon" : fallback, true); + ro_gui_set_icon_string(pointer->w, FONT_DEFAULT_FIELD, + font_names[0], true); +} + +bool ro_gui_options_fonts_ok(wimp_w w) +{ + unsigned int i; + + nsoption_set_int(font_size, + ro_gui_get_icon_decimal(w, FONT_DEFAULT_SIZE, 1)); + + nsoption_set_int(font_min_size, + ro_gui_get_icon_decimal(w, FONT_MINIMUM_SIZE, 1)); + + if (nsoption_int(font_size) < nsoption_int(font_min_size)) { + nsoption_set_int(font_size, nsoption_int(font_min_size)); + ro_gui_set_icon_decimal(w, FONT_DEFAULT_SIZE, nsoption_int(font_size), 1); + +} + + nsoption_set_charp(font_sans, + strdup(ro_gui_get_icon_string(w, FONT_SANS_FIELD))); + + nsoption_set_charp(font_serif, + strdup(ro_gui_get_icon_string(w, FONT_SERIF_FIELD))); + + nsoption_set_charp(font_mono, + strdup(ro_gui_get_icon_string(w, FONT_MONOSPACE_FIELD))); + + nsoption_set_charp(font_cursive, + strdup(ro_gui_get_icon_string(w, FONT_CURSIVE_FIELD))); + + nsoption_set_charp(font_fantasy, + strdup(ro_gui_get_icon_string(w, FONT_FANTASY_FIELD))); + + for (i = 0; i != 5; i++) { + if (!strcmp(font_names[i], ro_gui_get_icon_string(w, + FONT_DEFAULT_FIELD))) + break; + } + if (i == 5) + /* this should never happen, but still */ + i = 0; + + nsoption_set_int(font_default, i); + + ro_gui_save_options(); + return true; +} + +bool ro_gui_options_fonts_init_menu(void) +{ + unsigned int i; + + if (default_menu) + /* Already exists */ + return true; + + default_menu = malloc(wimp_SIZEOF_MENU(5)); + if (!default_menu) { + ro_warn_user("NoMemory", 0); + return false; + } + default_menu->title_data.indirected_text.text = + (char *) messages_get("DefaultFonts"); + ro_gui_menu_init_structure(default_menu, 5); + for (i = 0; i < 5; i++) { + default_menu->entries[i].data.indirected_text.text = + (char *) font_names[i]; + default_menu->entries[i].data.indirected_text.size = + strlen(font_names[i]); + } + return true; +} diff --git a/frontends/riscos/configure/con_home.c b/frontends/riscos/configure/con_home.c new file mode 100644 index 000000000..ea8e243ed --- /dev/null +++ b/frontends/riscos/configure/con_home.c @@ -0,0 +1,118 @@ +/* + * Copyright 2005 Richard Wilson <info@tinct.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include <stdlib.h> + +#include "utils/messages.h" +#include "utils/nsoption.h" + +#include "riscos/gui.h" +#include "riscos/menus.h" +#include "riscos/url_suggest.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" +#include "riscos/configure.h" +#include "riscos/configure/configure.h" +#include "riscos/dialog.h" + +#define HOME_URL_FIELD 3 +#define HOME_URL_GRIGHT 4 +#define HOME_OPEN_STARTUP 5 +#define HOME_DEFAULT_BUTTON 6 +#define HOME_CANCEL_BUTTON 7 +#define HOME_OK_BUTTON 8 + +static void ro_gui_options_home_default(wimp_pointer *pointer); +static bool ro_gui_options_home_ok(wimp_w w); +static bool ro_gui_options_home_menu_prepare(wimp_w w, wimp_i i, + wimp_menu *menu, wimp_pointer *pointer); + +bool ro_gui_options_home_initialise(wimp_w w) +{ + /* set the current values */ + ro_gui_set_icon_string(w, HOME_URL_FIELD, + nsoption_charp(homepage_url) ? + nsoption_charp(homepage_url) : "", true); + + ro_gui_set_icon_selected_state(w, HOME_OPEN_STARTUP, + nsoption_bool(open_browser_at_startup)); + + ro_gui_set_icon_shaded_state(w, + HOME_URL_GRIGHT, !ro_gui_url_suggest_prepare_menu()); + + /* initialise all functions for a newly created window */ + ro_gui_wimp_event_register_menu_gright(w, HOME_URL_FIELD, + HOME_URL_GRIGHT, ro_gui_url_suggest_menu); + ro_gui_wimp_event_register_checkbox(w, HOME_OPEN_STARTUP); + ro_gui_wimp_event_register_button(w, HOME_DEFAULT_BUTTON, + ro_gui_options_home_default); + ro_gui_wimp_event_register_cancel(w, HOME_CANCEL_BUTTON); + ro_gui_wimp_event_register_ok(w, HOME_OK_BUTTON, + ro_gui_options_home_ok); + ro_gui_wimp_event_register_menu_prepare(w, + ro_gui_options_home_menu_prepare); + ro_gui_wimp_event_set_help_prefix(w, "HelpHomeConfig"); + ro_gui_wimp_event_memorise(w); + return true; + +} + +void ro_gui_options_home_default(wimp_pointer *pointer) +{ + /* set the default values */ + ro_gui_set_icon_string(pointer->w, HOME_URL_FIELD, "", true); + ro_gui_set_icon_selected_state(pointer->w, HOME_OPEN_STARTUP, false); +} + +bool ro_gui_options_home_ok(wimp_w w) +{ + nsoption_set_charp(homepage_url, + strdup(ro_gui_get_icon_string(w, HOME_URL_FIELD))); + + nsoption_set_bool(open_browser_at_startup, + ro_gui_get_icon_selected_state(w, HOME_OPEN_STARTUP)); + + ro_gui_save_options(); + return true; +} + + +/** + * Callback to prepare menus in the Configure Home dialog. At present, this + * only has to handle the URL Suggestion pop-up. + * + * \param w The window handle owning the menu. + * \param i The icon handle owning the menu. + * \param *menu The menu to be prepared. + * \param *pointer The associated mouse click event block, or NULL + * on an Adjust-click re-opening. + * \return true if the event was handled; false if not. + */ + +bool ro_gui_options_home_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer) +{ + if (menu != ro_gui_url_suggest_menu || i != HOME_URL_GRIGHT) + return false; + + if (pointer != NULL) + ro_gui_url_suggest_prepare_menu(); + + return true; +} diff --git a/frontends/riscos/configure/con_image.c b/frontends/riscos/configure/con_image.c new file mode 100644 index 000000000..49dd4f76d --- /dev/null +++ b/frontends/riscos/configure/con_image.c @@ -0,0 +1,269 @@ +/* + * Copyright 2006 Richard Wilson <info@tinct.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include <swis.h> +#include <oslib/osspriteop.h> +#include <oslib/wimp.h> + +#include "utils/nsoption.h" +#include "utils/log.h" + +#include "riscos/gui.h" +#include "riscos/configure/configure.h" +#include "riscos/dialog.h" +#include "riscos/menus.h" +#include "riscos/tinct.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" + + +#define IMAGE_FOREGROUND_FIELD 3 +#define IMAGE_FOREGROUND_MENU 4 +#define IMAGE_BACKGROUND_FIELD 6 +#define IMAGE_BACKGROUND_MENU 7 +#define IMAGE_CURRENT_DISPLAY 8 +#define IMAGE_SPEED_TEXT 11 +#define IMAGE_SPEED_FIELD 12 +#define IMAGE_SPEED_DEC 13 +#define IMAGE_SPEED_INC 14 +#define IMAGE_SPEED_CS 15 +#define IMAGE_DISABLE_ANIMATION 16 +#define IMAGE_DEFAULT_BUTTON 17 +#define IMAGE_CANCEL_BUTTON 18 +#define IMAGE_OK_BUTTON 19 + +static bool ro_gui_options_image_click(wimp_pointer *pointer); +static bool ro_gui_options_image_ok(wimp_w w); +static void ro_gui_options_image_redraw(wimp_draw *redraw); +static bool ro_gui_options_image_update(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a); +static void ro_gui_options_image_read(wimp_w w, unsigned int *bg, + unsigned int *fg); +static void ro_gui_options_update_shading(wimp_w w); + +static osspriteop_area *example_images; +int example_users = 0; +unsigned int tinct_options[] = {tinct_USE_OS_SPRITE_OP, 0, tinct_DITHER, + tinct_ERROR_DIFFUSE}; + +bool ro_gui_options_image_initialise(wimp_w w) +{ + int i; + + /* load the sprite file */ + if (example_users == 0) { + char pathname[256]; + snprintf(pathname, 256, "%s.Resources.Image", NETSURF_DIR); + pathname[255] = '\0'; + example_images = ro_gui_load_sprite_file(pathname); + if (!example_images) + return false; + } + example_users++; + + /* set the current values */ + for (i = 0; (i < 4); i++) { + if ((unsigned int)nsoption_int(plot_fg_quality) == tinct_options[i]) + ro_gui_set_icon_string(w, IMAGE_FOREGROUND_FIELD, + image_quality_menu->entries[i]. + data.indirected_text.text, true); + if ((unsigned int)nsoption_int(plot_bg_quality) == tinct_options[i]) + ro_gui_set_icon_string(w, IMAGE_BACKGROUND_FIELD, + image_quality_menu->entries[i]. + data.indirected_text.text, true); + } + ro_gui_set_icon_decimal(w, IMAGE_SPEED_FIELD, + nsoption_int(minimum_gif_delay), 2); + ro_gui_set_icon_selected_state(w, IMAGE_DISABLE_ANIMATION, + !nsoption_bool(animate_images)); + ro_gui_options_update_shading(w); + + /* register icons */ + ro_gui_wimp_event_register_menu_gright(w, IMAGE_FOREGROUND_FIELD, + IMAGE_FOREGROUND_MENU, image_quality_menu); + ro_gui_wimp_event_register_menu_gright(w, IMAGE_BACKGROUND_FIELD, + IMAGE_BACKGROUND_MENU, image_quality_menu); + ro_gui_wimp_event_register_text_field(w, IMAGE_SPEED_TEXT); + ro_gui_wimp_event_register_numeric_field(w, IMAGE_SPEED_FIELD, + IMAGE_SPEED_INC, IMAGE_SPEED_DEC, 0, 6000, 10, 2); + ro_gui_wimp_event_register_checkbox(w, IMAGE_DISABLE_ANIMATION); + ro_gui_wimp_event_register_text_field(w, IMAGE_SPEED_CS); + ro_gui_wimp_event_register_redraw_window(w, + ro_gui_options_image_redraw); + ro_gui_wimp_event_register_mouse_click(w, + ro_gui_options_image_click); + ro_gui_wimp_event_register_menu_selection(w, + ro_gui_options_image_update); + ro_gui_wimp_event_register_cancel(w, IMAGE_CANCEL_BUTTON); + ro_gui_wimp_event_register_ok(w, IMAGE_OK_BUTTON, + ro_gui_options_image_ok); + ro_gui_wimp_event_set_help_prefix(w, "HelpImageConfig"); + ro_gui_wimp_event_memorise(w); + + return true; +} + +void ro_gui_options_image_finalise(wimp_w w) +{ + example_users--; + if (example_users == 0) { + free(example_images); + example_images = NULL; + } + ro_gui_wimp_event_finalise(w); +} + +bool ro_gui_options_image_update(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a) +{ + ro_gui_redraw_icon(w, IMAGE_CURRENT_DISPLAY); + + return true; +} + +void ro_gui_options_image_redraw(wimp_draw *redraw) +{ + osbool more; + os_error *error; + wimp_icon_state icon_state; + osspriteop_header *bg = NULL, *fg = NULL; + unsigned int bg_tinct = 0, fg_tinct = 0; + + /* get the icon location */ + icon_state.w = redraw->w; + icon_state.i = IMAGE_CURRENT_DISPLAY; + error = xwimp_get_icon_state(&icon_state); + if (error) { + LOG("xwimp_get_icon_state: 0x%x: %s", + error->errnum, error->errmess); + ro_warn_user("MenuError", error->errmess); + return; + } + + /* find the sprites */ + if (example_images) { + ro_gui_options_image_read(redraw->w, &bg_tinct, &fg_tinct); + fg_tinct |= 0xeeeeee00; + xosspriteop_select_sprite(osspriteop_USER_AREA, + example_images, (osspriteop_id)"img_bg", &bg); + xosspriteop_select_sprite(osspriteop_USER_AREA, + example_images, (osspriteop_id)"img_fg", &fg); + } + + /* perform the redraw */ + more = wimp_redraw_window(redraw); + while (more) { + int origin_x, origin_y; + origin_x = redraw->box.x0 - redraw->xscroll + + icon_state.icon.extent.x0 + 2; + origin_y = redraw->box.y1 - redraw->yscroll + + icon_state.icon.extent.y0 + 2; + if (bg) + _swix(Tinct_Plot, _INR(2,4) | _IN(7), + bg, origin_x, origin_y, bg_tinct); + if (fg) + _swix(Tinct_PlotAlpha, _INR(2,4) | _IN(7), + fg, origin_x, origin_y, fg_tinct); + more = wimp_get_rectangle(redraw); + } +} + +void ro_gui_options_image_read(wimp_w w, unsigned int *bg, unsigned int *fg) +{ + const char *text; + int i; + + text = ro_gui_get_icon_string(w, IMAGE_FOREGROUND_FIELD); + for (i = 0; i < 4; i++) + if (!strcmp(text, image_quality_menu->entries[i]. + data.indirected_text.text)) + *fg = tinct_options[i]; + + text = ro_gui_get_icon_string(w, IMAGE_BACKGROUND_FIELD); + for (i = 0; i < 4; i++) + if (!strcmp(text, image_quality_menu->entries[i]. + data.indirected_text.text)) + *bg = tinct_options[i]; +} + +bool ro_gui_options_image_click(wimp_pointer *pointer) +{ + unsigned int old_fg, old_bg, bg, fg; + + ro_gui_options_image_read(pointer->w, &old_bg, &old_fg); + switch (pointer->i) { + case IMAGE_DEFAULT_BUTTON: + ro_gui_set_icon_string(pointer->w, + IMAGE_FOREGROUND_FIELD, + image_quality_menu->entries[3]. + data.indirected_text.text, true); + ro_gui_set_icon_string(pointer->w, + IMAGE_BACKGROUND_FIELD, + image_quality_menu->entries[2]. + data.indirected_text.text, true); + ro_gui_set_icon_decimal(pointer->w, IMAGE_SPEED_FIELD, + 10, 2); + ro_gui_set_icon_selected_state(pointer->w, + IMAGE_DISABLE_ANIMATION, false); + case IMAGE_DISABLE_ANIMATION: + ro_gui_options_update_shading(pointer->w); + break; + case IMAGE_CANCEL_BUTTON: + ro_gui_wimp_event_restore(pointer->w); + break; + default: + return false; + } + + ro_gui_options_image_read(pointer->w, &bg, &fg); + if ((bg != old_bg) || (fg != old_fg)) + ro_gui_options_image_update(pointer->w, pointer->i, + NULL, NULL, NO_ACTION); + + return false; +} + +void ro_gui_options_update_shading(wimp_w w) +{ + bool shaded; + + shaded = ro_gui_get_icon_selected_state(w, IMAGE_DISABLE_ANIMATION); + ro_gui_set_icon_shaded_state(w, IMAGE_SPEED_TEXT, shaded); + ro_gui_set_icon_shaded_state(w, IMAGE_SPEED_FIELD, shaded); + ro_gui_set_icon_shaded_state(w, IMAGE_SPEED_DEC, shaded); + ro_gui_set_icon_shaded_state(w, IMAGE_SPEED_INC, shaded); + ro_gui_set_icon_shaded_state(w, IMAGE_SPEED_CS, shaded); +} + +bool ro_gui_options_image_ok(wimp_w w) +{ + ro_gui_options_image_read(w, + (unsigned int *)&nsoption_int(plot_bg_quality), + (unsigned int *)&nsoption_int(plot_fg_quality)); + + nsoption_set_int(minimum_gif_delay, + ro_gui_get_icon_decimal(w, IMAGE_SPEED_FIELD, 2)); + + nsoption_set_bool(animate_images, + !ro_gui_get_icon_selected_state(w, + IMAGE_DISABLE_ANIMATION)); + ro_gui_save_options(); + + return true; +} diff --git a/frontends/riscos/configure/con_inter.c b/frontends/riscos/configure/con_inter.c new file mode 100644 index 000000000..7ab912c54 --- /dev/null +++ b/frontends/riscos/configure/con_inter.c @@ -0,0 +1,145 @@ +/* + * Copyright 2006 Adrian Lees <adrianl@users.sourceforge.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> + +#include "utils/nsoption.h" + +#include "riscos/gui.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" +#include "riscos/configure.h" +#include "riscos/configure/configure.h" +#include "riscos/dialog.h" + +#define INTERFACE_STRIP_EXTNS_OPTION 2 +#define INTERFACE_CONFIRM_OVWR_OPTION 3 +#define INTERFACE_URL_COMPLETE_OPTION 6 +#define INTERFACE_HISTORY_TOOLTIP_OPTION 7 +#define INTERFACE_THUMBNAIL_ICONISE_OPTION 10 +#define INTERFACE_DEFAULT_BUTTON 11 +#define INTERFACE_CANCEL_BUTTON 12 +#define INTERFACE_OK_BUTTON 13 +#define INTERFACE_USE_EXTERNAL_HOTLIST 16 +#define INTERFACE_EXTERNAL_HOTLIST_APP 18 + + +static bool ro_gui_options_interface_click(wimp_pointer *pointer); +static void ro_gui_options_interface_default(wimp_pointer *pointer); +static bool ro_gui_options_interface_ok(wimp_w w); + +bool ro_gui_options_interface_initialise(wimp_w w) +{ + /* set the current values */ + ro_gui_set_icon_selected_state(w, INTERFACE_STRIP_EXTNS_OPTION, + nsoption_bool(strip_extensions)); + ro_gui_set_icon_selected_state(w, INTERFACE_CONFIRM_OVWR_OPTION, + nsoption_bool(confirm_overwrite)); + ro_gui_set_icon_selected_state(w, INTERFACE_URL_COMPLETE_OPTION, + nsoption_bool(url_suggestion)); + ro_gui_set_icon_selected_state(w, INTERFACE_HISTORY_TOOLTIP_OPTION, + nsoption_bool(history_tooltip)); + ro_gui_set_icon_selected_state(w, INTERFACE_THUMBNAIL_ICONISE_OPTION, + nsoption_bool(thumbnail_iconise)); + ro_gui_set_icon_selected_state(w, INTERFACE_USE_EXTERNAL_HOTLIST, + nsoption_bool(external_hotlists)); + ro_gui_set_icon_string(w, INTERFACE_EXTERNAL_HOTLIST_APP, + (nsoption_charp(external_hotlist_app)) ? + nsoption_charp(external_hotlist_app) : "", false); + + ro_gui_set_icon_shaded_state(w, INTERFACE_EXTERNAL_HOTLIST_APP, + !nsoption_bool(external_hotlists)); + + /* initialise all functions for a newly created window */ + ro_gui_wimp_event_register_mouse_click(w, + ro_gui_options_interface_click); + ro_gui_wimp_event_register_button(w, INTERFACE_DEFAULT_BUTTON, + ro_gui_options_interface_default); + ro_gui_wimp_event_register_cancel(w, INTERFACE_CANCEL_BUTTON); + ro_gui_wimp_event_register_ok(w, INTERFACE_OK_BUTTON, + ro_gui_options_interface_ok); + ro_gui_wimp_event_set_help_prefix(w, "HelpInterfaceConfig"); + ro_gui_wimp_event_memorise(w); + return true; + +} + + +bool ro_gui_options_interface_click(wimp_pointer *pointer) +{ + bool shaded; + + switch (pointer->i) { + case INTERFACE_USE_EXTERNAL_HOTLIST: + shaded = !ro_gui_get_icon_selected_state(pointer->w, + INTERFACE_USE_EXTERNAL_HOTLIST); + ro_gui_set_icon_shaded_state(pointer->w, + INTERFACE_EXTERNAL_HOTLIST_APP, shaded); + return false; + break; + } + return false; +} + + + +void ro_gui_options_interface_default(wimp_pointer *pointer) +{ + ro_gui_set_icon_selected_state(pointer->w, + INTERFACE_STRIP_EXTNS_OPTION, true); + ro_gui_set_icon_selected_state(pointer->w, + INTERFACE_CONFIRM_OVWR_OPTION, true); + ro_gui_set_icon_selected_state(pointer->w, + INTERFACE_URL_COMPLETE_OPTION, true); + ro_gui_set_icon_selected_state(pointer->w, + INTERFACE_HISTORY_TOOLTIP_OPTION, true); + ro_gui_set_icon_selected_state(pointer->w, + INTERFACE_THUMBNAIL_ICONISE_OPTION, true); + ro_gui_set_icon_selected_state(pointer->w, + INTERFACE_USE_EXTERNAL_HOTLIST, false); + ro_gui_set_icon_string(pointer->w, INTERFACE_EXTERNAL_HOTLIST_APP, + "", false); +} + +bool ro_gui_options_interface_ok(wimp_w w) +{ + nsoption_set_bool(strip_extensions, + ro_gui_get_icon_selected_state(w, + INTERFACE_STRIP_EXTNS_OPTION)); + nsoption_set_bool(confirm_overwrite, + ro_gui_get_icon_selected_state(w, + INTERFACE_CONFIRM_OVWR_OPTION)); + nsoption_set_bool(url_suggestion, + ro_gui_get_icon_selected_state(w, + INTERFACE_URL_COMPLETE_OPTION)); + nsoption_set_bool(history_tooltip, + ro_gui_get_icon_selected_state(w, + INTERFACE_HISTORY_TOOLTIP_OPTION)); + nsoption_set_bool(thumbnail_iconise, + ro_gui_get_icon_selected_state(w, + INTERFACE_THUMBNAIL_ICONISE_OPTION)); + nsoption_set_bool(external_hotlists, + ro_gui_get_icon_selected_state(w, + INTERFACE_USE_EXTERNAL_HOTLIST)); + nsoption_set_charp(external_hotlist_app, + strdup(ro_gui_get_icon_string(w, + INTERFACE_EXTERNAL_HOTLIST_APP))); + + ro_gui_save_options(); + return true; +} diff --git a/frontends/riscos/configure/con_language.c b/frontends/riscos/configure/con_language.c new file mode 100644 index 000000000..2030c65c0 --- /dev/null +++ b/frontends/riscos/configure/con_language.c @@ -0,0 +1,139 @@ +/* + * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk> + * Copyright 2006 Richard Wilson <info@tinct.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> + +#include "utils/nsoption.h" +#include "utils/log.h" +#include "utils/messages.h" + +#include "riscos/gui.h" +#include "riscos/menus.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" +#include "riscos/configure.h" +#include "riscos/configure/configure.h" +#include "riscos/dialog.h" + + +#define LANGUAGE_INTERFACE_FIELD 3 +#define LANGUAGE_INTERFACE_GRIGHT 4 +#define LANGUAGE_WEB_PAGES_FIELD 6 +#define LANGUAGE_WEB_PAGES_GRIGHT 7 +#define LANGUAGE_DEFAULT_BUTTON 8 +#define LANGUAGE_CANCEL_BUTTON 9 +#define LANGUAGE_OK_BUTTON 10 + +static void ro_gui_options_language_default(wimp_pointer *pointer); +static bool ro_gui_options_language_ok(wimp_w w); +static const char *ro_gui_options_language_name(const char *code); + +bool ro_gui_options_language_initialise(wimp_w w) +{ + /* set the current values */ + ro_gui_set_icon_string(w, LANGUAGE_INTERFACE_FIELD, + ro_gui_options_language_name(nsoption_charp(language) ? + nsoption_charp(language) : "en"), true); + ro_gui_set_icon_string(w, LANGUAGE_WEB_PAGES_FIELD, + ro_gui_options_language_name(nsoption_charp(accept_language) ? + nsoption_charp(accept_language) : "en"), true); + + /* initialise all functions for a newly created window */ + ro_gui_wimp_event_register_menu_gright(w, LANGUAGE_INTERFACE_FIELD, + LANGUAGE_INTERFACE_GRIGHT, languages_menu); + ro_gui_wimp_event_register_menu_gright(w, LANGUAGE_WEB_PAGES_FIELD, + LANGUAGE_WEB_PAGES_GRIGHT, languages_menu); + ro_gui_wimp_event_register_button(w, LANGUAGE_DEFAULT_BUTTON, + ro_gui_options_language_default); + ro_gui_wimp_event_register_cancel(w, LANGUAGE_CANCEL_BUTTON); + ro_gui_wimp_event_register_ok(w, LANGUAGE_OK_BUTTON, + ro_gui_options_language_ok); + ro_gui_wimp_event_set_help_prefix(w, "HelpLanguageConfig"); + ro_gui_wimp_event_memorise(w); + return true; + +} + +void ro_gui_options_language_default(wimp_pointer *pointer) +{ + const char *code; + + code = ro_gui_default_language(); + ro_gui_set_icon_string(pointer->w, LANGUAGE_INTERFACE_FIELD, + ro_gui_options_language_name(code ? + code : "en"), true); + ro_gui_set_icon_string(pointer->w, LANGUAGE_WEB_PAGES_FIELD, + ro_gui_options_language_name(code ? + code : "en"), true); +} + +bool ro_gui_options_language_ok(wimp_w w) +{ + const char *code; + char *temp; + + code = ro_gui_menu_find_menu_entry_key(languages_menu, + ro_gui_get_icon_string(w, LANGUAGE_INTERFACE_FIELD)); + if (code) { + code += 5; /* skip 'lang_' */ + if ((!nsoption_charp(language)) || + (strcmp(nsoption_charp(language), code))) { + temp = strdup(code); + if (temp) { + nsoption_set_charp(language, temp); + } else { + LOG("No memory to duplicate language code"); + ro_warn_user("NoMemory", 0); + } + } + } + code = ro_gui_menu_find_menu_entry_key(languages_menu, + ro_gui_get_icon_string(w, LANGUAGE_WEB_PAGES_FIELD)); + if (code) { + code += 5; /* skip 'lang_' */ + if ((!nsoption_charp(accept_language)) || + (strcmp(nsoption_charp(accept_language), code))) { + temp = strdup(code); + if (temp) { + nsoption_set_charp(accept_language,temp); + } else { + LOG("No memory to duplicate language code"); + ro_warn_user("NoMemory", 0); + } + } + } + ro_gui_save_options(); + return true; +} + + +/** + * Convert a 2-letter ISO language code to the language name. + * + * \param code 2-letter ISO language code + * \return language name, or code if unknown + */ +const char *ro_gui_options_language_name(const char *code) +{ + char key[] = "lang_xx"; + key[5] = code[0]; + key[6] = code[1]; + + return messages_get(key); +} diff --git a/frontends/riscos/configure/con_secure.c b/frontends/riscos/configure/con_secure.c new file mode 100644 index 000000000..9c8a846c3 --- /dev/null +++ b/frontends/riscos/configure/con_secure.c @@ -0,0 +1,83 @@ +/* + * Copyright 2006 Richard Wilson <info@tinct.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> + +#include "utils/nsoption.h" +#include "utils/messages.h" + +#include "riscos/gui.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" +#include "riscos/configure.h" +#include "riscos/configure/configure.h" +#include "riscos/dialog.h" + +#define SECURITY_REFERRER 2 +#define SECURITY_DURATION_FIELD 6 +#define SECURITY_DURATION_INC 7 +#define SECURITY_DURATION_DEC 8 +#define SECURITY_DEFAULT_BUTTON 10 +#define SECURITY_CANCEL_BUTTON 11 +#define SECURITY_OK_BUTTON 12 + +static void ro_gui_options_security_default(wimp_pointer *pointer); +static bool ro_gui_options_security_ok(wimp_w w); + +bool ro_gui_options_security_initialise(wimp_w w) +{ + /* set the current values */ + ro_gui_set_icon_selected_state(w, SECURITY_REFERRER, + nsoption_bool(send_referer)); + ro_gui_set_icon_integer(w, SECURITY_DURATION_FIELD, + nsoption_int(expire_url)); + + /* initialise all functions for a newly created window */ + ro_gui_wimp_event_register_checkbox(w, SECURITY_REFERRER); + ro_gui_wimp_event_register_numeric_field(w, SECURITY_DURATION_FIELD, + SECURITY_DURATION_DEC, SECURITY_DURATION_INC, + 0, 365, 1, 0); + ro_gui_wimp_event_register_button(w, SECURITY_DEFAULT_BUTTON, + ro_gui_options_security_default); + ro_gui_wimp_event_register_cancel(w, SECURITY_CANCEL_BUTTON); + ro_gui_wimp_event_register_ok(w, SECURITY_OK_BUTTON, + ro_gui_options_security_ok); + ro_gui_wimp_event_set_help_prefix(w, "HelpSecurityConfig"); + ro_gui_wimp_event_memorise(w); + return true; + +} + +void ro_gui_options_security_default(wimp_pointer *pointer) +{ + /* set the default values */ + ro_gui_set_icon_integer(pointer->w, SECURITY_DURATION_FIELD, 28); + ro_gui_set_icon_selected_state(pointer->w, SECURITY_REFERRER, true); +} + +bool ro_gui_options_security_ok(wimp_w w) +{ + nsoption_set_bool(send_referer, + ro_gui_get_icon_selected_state(w, SECURITY_REFERRER)); + + nsoption_set_int(expire_url, + ro_gui_get_icon_decimal(w,SECURITY_DURATION_FIELD, 0)); + + ro_gui_save_options(); + return true; +} diff --git a/frontends/riscos/configure/con_theme.c b/frontends/riscos/configure/con_theme.c new file mode 100644 index 000000000..fb0d3dfb0 --- /dev/null +++ b/frontends/riscos/configure/con_theme.c @@ -0,0 +1,420 @@ +/* + * Copyright 2006 Richard Wilson <info@tinct.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <oslib/osspriteop.h> +#include <oslib/wimp.h> +#include <oslib/wimpspriteop.h> + +#include "utils/config.h" +#include "utils/nsoption.h" +#include "utils/log.h" +#include "utils/messages.h" + +#include "riscos/gui.h" +#include "riscos/configure/configure.h" +#include "riscos/configure.h" +#include "riscos/dialog.h" +#include "riscos/menus.h" +#include "riscos/theme.h" +#include "riscos/toolbar.h" +#include "riscos/url_complete.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" +#include "riscos/wimputils.h" + + +#define THEME_PANE_AREA 0 +#define THEME_DEFAULT_BUTTON 2 +#define THEME_CANCEL_BUTTON 3 +#define THEME_OK_BUTTON 4 + +struct toolbar_display { + struct toolbar *toolbar; + struct theme_descriptor *descriptor; + int icon_number; + struct toolbar_display *next; +}; + +static wimp_window theme_pane_definition = { + {0, 0, 16, 16}, + 0, + 0, + wimp_TOP, + wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_VSCROLL | wimp_WINDOW_AUTO_REDRAW, + wimp_COLOUR_BLACK, + wimp_COLOUR_LIGHT_GREY, + wimp_COLOUR_LIGHT_GREY, + wimp_COLOUR_VERY_LIGHT_GREY, + wimp_COLOUR_DARK_GREY, + wimp_COLOUR_MID_LIGHT_GREY, + wimp_COLOUR_CREAM, + 0, + {0, -16384, 16384, 0}, + wimp_ICON_TEXT | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED, + wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT, + wimpspriteop_AREA, + 1, + 1, + {""}, + 0, + {} +}; + + +static wimp_w theme_pane; +static struct theme_descriptor *theme_list = NULL; +static struct toolbar_display *toolbars = NULL; +static char theme_radio_validation[] = "Sradiooff,radioon"; +static char theme_null_validation[] = ""; +static char theme_line_validation[] = "R2"; + +static bool ro_gui_options_theme_ok(wimp_w w); +static bool ro_gui_options_theme_click(wimp_pointer *pointer); +static void ro_gui_options_theme_load(void); +static void ro_gui_options_theme_free(void); + +bool ro_gui_options_theme_initialise(wimp_w w) +{ + wimp_window_state state; + wimp_icon_state icon_state; + os_error *error; + struct theme_descriptor *theme_choice; + struct toolbar_display *toolbar; + + /* only allow one instance for now*/ + if (theme_pane) + return false; + error = xwimp_create_window(&theme_pane_definition, &theme_pane); + if (error) { + LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess); + return false; + } + state.w = w; + error = xwimp_get_window_state(&state); + if (error) { + LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess); + return false; + } + icon_state.w = w; + icon_state.i = THEME_PANE_AREA; + error = xwimp_get_icon_state(&icon_state); + if (error) { + LOG("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess); + return false; + } + state.w = theme_pane; + state.visible.x1 = state.visible.x0 + icon_state.icon.extent.x1 - 16 - + ro_get_vscroll_width(theme_pane); + state.visible.x0 += icon_state.icon.extent.x0 + 16; + state.visible.y0 = state.visible.y1 + icon_state.icon.extent.y0 + 16; + state.visible.y1 += icon_state.icon.extent.y1 - 28; + LOG("Y0 = %i, y1 = %i", icon_state.icon.extent.y0, icon_state.icon.extent.y1); + error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), w, + wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT + << wimp_CHILD_XORIGIN_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT + << wimp_CHILD_YORIGIN_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT + << wimp_CHILD_LS_EDGE_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT + << wimp_CHILD_BS_EDGE_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT + << wimp_CHILD_RS_EDGE_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT + << wimp_CHILD_TS_EDGE_SHIFT); + if (error) { + LOG("xwimp_open_window_nested: 0x%x: %s", error->errnum, error->errmess); + return false; + } + + /* load themes */ + ro_gui_options_theme_load(); + + /* set the current selection */ + theme_choice = ro_gui_theme_find(nsoption_charp(theme)); + if (!theme_choice) + theme_choice = ro_gui_theme_find("Aletheia"); + for (toolbar = toolbars; toolbar; toolbar = toolbar->next) + ro_gui_set_icon_selected_state(theme_pane, toolbar->icon_number, + (toolbar->descriptor == theme_choice)); + ro_gui_wimp_event_memorise(theme_pane); + ro_gui_wimp_event_set_help_prefix(theme_pane, "HelpThemePConfig"); + + ro_gui_wimp_event_register_mouse_click(w, ro_gui_options_theme_click); + ro_gui_wimp_event_register_cancel(w, THEME_CANCEL_BUTTON); + ro_gui_wimp_event_register_ok(w, THEME_OK_BUTTON, + ro_gui_options_theme_ok); + ro_gui_wimp_event_set_help_prefix(w, "HelpThemeConfig"); + ro_gui_wimp_event_memorise(w); + + return true; +} + +void ro_gui_options_theme_finalise(wimp_w w) +{ + ro_gui_options_theme_free(); + if (theme_pane) { + os_error *error; + ro_gui_wimp_event_finalise(theme_pane); + error = xwimp_delete_window(theme_pane); + if (error) { + LOG("xwimp_delete_window: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + theme_pane = 0; + } + ro_gui_wimp_event_finalise(w); +} + +bool ro_gui_options_theme_ok(wimp_w w) +{ + struct toolbar_display *toolbar; + struct theme_descriptor *theme_new = NULL; + + /* find the current selection */ + for (toolbar = toolbars; toolbar; toolbar = toolbar->next) { + if (ro_gui_get_icon_selected_state(theme_pane, toolbar->icon_number)) { + theme_new = toolbar->descriptor; + break; + } + } + + /* set the options */ + if (theme_new) { + nsoption_set_charp(theme, strdup(theme_new->leafname)); + ro_gui_theme_apply(theme_new); + } else { + nsoption_set_charp(theme, NULL); + } + ro_gui_save_options(); + + /* store the pane status */ + ro_gui_wimp_event_memorise(theme_pane); + return true; +} + +bool ro_gui_options_theme_click(wimp_pointer *pointer) +{ + struct theme_descriptor *theme_default; + struct toolbar_display *toolbar; + + switch (pointer->i) { + case THEME_DEFAULT_BUTTON: + theme_default = ro_gui_theme_find("Aletheia"); + for (toolbar = toolbars; toolbar; toolbar = toolbar->next) + ro_gui_set_icon_selected_state(theme_pane, + toolbar->icon_number, + (toolbar->descriptor == theme_default)); + break; + case THEME_CANCEL_BUTTON: + ro_gui_wimp_event_restore(theme_pane); + break; + case THEME_OK_BUTTON: + ro_gui_wimp_event_memorise(theme_pane); + break; + } + return false; +} + +void ro_gui_options_theme_load(void) +{ + os_error *error; + os_box extent = { 0, 0, 0, 0 }; + struct theme_descriptor *descriptor; + struct toolbar_display *link; + struct toolbar_display *toolbar_display; + struct toolbar *toolbar; + wimp_icon_create new_icon; + wimp_window_state state; + int parent_width, nested_y, min_extent, base_extent; + int *radio_icons, *radio_set; + int theme_count; + + /* delete our old list and get/open a new one */ + ro_gui_options_theme_free(); + theme_list = ro_gui_theme_get_available(); + ro_gui_theme_open(theme_list, true); + + /* create toolbars for each theme */ + theme_count = 0; + descriptor = theme_list; + while (descriptor != NULL) { + /* try to create a toolbar */ + toolbar = ro_toolbar_create(descriptor, NULL, + THEME_STYLE_BROWSER_TOOLBAR, + TOOLBAR_FLAGS_DISPLAY, NULL, NULL, NULL); + if (toolbar != NULL) { + ro_toolbar_add_buttons(toolbar, brower_toolbar_buttons, + nsoption_charp(toolbar_browser)); + ro_toolbar_add_url(toolbar); + ro_toolbar_add_throbber(toolbar); + ro_toolbar_rebuild(toolbar); + toolbar_display = calloc(sizeof(struct toolbar_display), 1); + if (!toolbar_display) { + LOG("No memory for calloc()"); + ro_warn_user("NoMemory", 0); + return; + } + toolbar_display->toolbar = toolbar; + toolbar_display->descriptor = descriptor; + if (!toolbars) { + toolbars = toolbar_display; + } else { + link = toolbars; + while (link->next) link = link->next; + link->next = toolbar_display; + } + theme_count++; + } + descriptor = descriptor->next; + } + + /* nest the toolbars */ + state.w = theme_pane; + error = xwimp_get_window_state(&state); + if (error) { + LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + return; + } + + parent_width = state.visible.x1 - state.visible.x0; + min_extent = state.visible.y0 - state.visible.y1; + nested_y = 0; + base_extent = state.visible.y1 - state.yscroll; + extent.x1 = parent_width; + link = toolbars; + new_icon.w = theme_pane; + new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED | + wimp_ICON_VCENTRED | + (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | + (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT); + while (link) { + /* update the toolbar */ + int item_height = 44 + 44 + 16; + if (link->next) item_height += 16; + ro_toolbar_process(link->toolbar, parent_width, false); + extent.y0 = nested_y - + ro_toolbar_height(link->toolbar) - + item_height; + if (link->next) extent.y0 -= 16; + if (extent.y0 > min_extent) extent.y0 = min_extent; + xwimp_set_extent(theme_pane, &extent); + + /* create the descriptor icons and separator line */ + new_icon.icon.extent.x0 = 8; + new_icon.icon.extent.x1 = parent_width - 8; + new_icon.icon.flags &= ~wimp_ICON_BORDER; + new_icon.icon.flags |= wimp_ICON_SPRITE; + new_icon.icon.extent.y1 = nested_y - + ro_toolbar_height(link->toolbar) - 8; + new_icon.icon.extent.y0 = nested_y - + ro_toolbar_height(link->toolbar) - 52; + new_icon.icon.data.indirected_text_and_sprite.text = + (char *)&link->descriptor->name; + new_icon.icon.data.indirected_text_and_sprite.size = + strlen(link->descriptor->name) + 1; + new_icon.icon.data.indirected_text_and_sprite.validation = + theme_radio_validation; + new_icon.icon.flags |= (wimp_BUTTON_RADIO << + wimp_ICON_BUTTON_TYPE_SHIFT); + xwimp_create_icon(&new_icon, &link->icon_number); + new_icon.icon.flags &= ~wimp_ICON_SPRITE; + new_icon.icon.extent.x0 = 52; + new_icon.icon.extent.y1 -= 44; + new_icon.icon.extent.y0 -= 44; + new_icon.icon.data.indirected_text.text = + (char *)&link->descriptor->author; + new_icon.icon.data.indirected_text.size = + strlen(link->descriptor->author) + 1; + new_icon.icon.data.indirected_text.validation = + theme_null_validation; + new_icon.icon.flags &= ~(wimp_BUTTON_RADIO << + wimp_ICON_BUTTON_TYPE_SHIFT); + xwimp_create_icon(&new_icon, 0); + if (link->next) { + new_icon.icon.flags |= wimp_ICON_BORDER; + new_icon.icon.extent.x0 = -8; + new_icon.icon.extent.x1 = parent_width + 8; + new_icon.icon.extent.y1 -= 52; + new_icon.icon.extent.y0 = new_icon.icon.extent.y1 - 8; + new_icon.icon.data.indirected_text.text = + theme_null_validation; + new_icon.icon.data.indirected_text.validation = + theme_line_validation; + new_icon.icon.data.indirected_text.size = 1; + xwimp_create_icon(&new_icon, 0); + } + + /* nest the toolbar window */ + state.w = ro_toolbar_get_window(link->toolbar); + state.yscroll = 0; + state.visible.y1 = nested_y + base_extent; + state.visible.y0 = state.visible.y1 - + ro_toolbar_height(link->toolbar) + 2; + xwimp_open_window_nested(PTR_WIMP_OPEN(&state), theme_pane, + wimp_CHILD_LINKS_PARENT_WORK_AREA + << wimp_CHILD_BS_EDGE_SHIFT | + wimp_CHILD_LINKS_PARENT_WORK_AREA + << wimp_CHILD_TS_EDGE_SHIFT); + + /* continue processing */ + nested_y -= ro_toolbar_height(link->toolbar) + + item_height; + link = link->next; + } + + /* set the icons as radios */ + radio_icons = (int *)calloc(theme_count + 1, sizeof(int)); + radio_set = radio_icons; + for (link = toolbars; link; link = link->next) + *radio_set++ = link->icon_number; + *radio_set = -1; + ro_gui_wimp_event_register_radio(theme_pane, radio_icons); + + /* update our display */ + xwimp_force_redraw(theme_pane, 0, -16384, 16384, 16384); +} + +void ro_gui_options_theme_free(void) +{ + struct toolbar_display *toolbar; + struct toolbar_display *next_toolbar; + + /* free all our toolbars */ + next_toolbar = toolbars; + while ((toolbar = next_toolbar) != NULL) { + next_toolbar = toolbar->next; + xwimp_delete_icon(theme_pane, toolbar->icon_number); + xwimp_delete_icon(theme_pane, toolbar->icon_number + 1); + if (next_toolbar) + xwimp_delete_icon(theme_pane, + toolbar->icon_number + 2); + ro_toolbar_destroy(toolbar->toolbar); + free(toolbar); + } + toolbars = NULL; + + /* close all our themes */ + if (theme_list) + ro_gui_theme_close(theme_list, true); + theme_list = NULL; +} diff --git a/frontends/riscos/configure/configure.h b/frontends/riscos/configure/configure.h new file mode 100644 index 000000000..e5cdb392e --- /dev/null +++ b/frontends/riscos/configure/configure.h @@ -0,0 +1,43 @@ +/* + * Copyright 2005 Richard Wilson <info@tinct.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * Automated RISC OS WIMP event handling (interface). + */ + + +#ifndef _NETSURF_RISCOS_OPTIONS_CONFIGURE_H_ +#define _NETSURF_RISCOS_OPTIONS_CONFIGURE_H_ + +#include <stdbool.h> +#include "oslib/wimp.h" + +bool ro_gui_options_cache_initialise(wimp_w w); +bool ro_gui_options_connection_initialise(wimp_w w); +bool ro_gui_options_content_initialise(wimp_w w); +bool ro_gui_options_fonts_initialise(wimp_w w); +bool ro_gui_options_home_initialise(wimp_w w); +bool ro_gui_options_image_initialise(wimp_w w); +void ro_gui_options_image_finalise(wimp_w w); +bool ro_gui_options_interface_initialise(wimp_w w); +bool ro_gui_options_language_initialise(wimp_w w); +bool ro_gui_options_security_initialise(wimp_w w); +bool ro_gui_options_theme_initialise(wimp_w w); +void ro_gui_options_theme_finalise(wimp_w w); + +#endif diff --git a/frontends/riscos/content-handlers/artworks.c b/frontends/riscos/content-handlers/artworks.c new file mode 100644 index 000000000..b6f7a0d08 --- /dev/null +++ b/frontends/riscos/content-handlers/artworks.c @@ -0,0 +1,435 @@ +/* + * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * Content for image/x-artworks (RISC OS implementation). + * + * Uses the ArtworksRenderer module + */ + +#include "utils/config.h" +#ifdef WITH_ARTWORKS + +#include <assert.h> +#include <limits.h> +#include <stdlib.h> +#include "swis.h" +#include "oslib/os.h" +#include "oslib/wimp.h" + +#include "utils/config.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/utils.h" +#include "content/content_protected.h" +#include "desktop/plotters.h" + +#include "riscos/content-handlers/artworks.h" +#include "riscos/gui.h" +#include "riscos/wimputils.h" + +#define AWRender_FileInitAddress 0x46080 +#define AWRender_RenderAddress 0x46081 +#define AWRender_DocBounds 0x46082 +#define AWRender_SendDefs 0x46083 +#define AWRender_ClaimVectors 0x46084 +#define AWRender_ReleaseVectors 0x46085 +#define AWRender_FindFirstFont 0x46086 +#define AWRender_FindNextFont 0x46087 + + +#define INITIAL_BLOCK_SIZE 0x1000 + +typedef struct artworks_content { + struct content base; + + int x0, y0, x1, y1; + + void *render_routine; + void *render_workspace; + + /* dynamically-resizable block required by + ArtWorksRenderer rendering routine */ + + void *block; + size_t size; +} artworks_content; + +struct awinfo_block { + int ditherx; + int dithery; + int clip_x0; + int clip_y0; + int clip_x1; + int clip_y1; + int print_lowx; + int print_lowy; + int print_handle; + int print_x1; + int print_y1; + int bgcolour; +}; + + +/* Assembler routines for interfacing with the ArtworksRenderer module */ + +extern os_error *awrender_init(const char **doc, + unsigned long *doc_size, + void *routine, + void *workspace); + +extern os_error *awrender_render(const char *doc, + const struct awinfo_block *info, + const os_trfm *trans, + const int *vdu_vars, + void **rsz_block, + size_t *rsz_size, + int wysiwyg_setting, + int output_dest, + size_t doc_size, + void *routine, + void *workspace); + +static nserror artworks_create(const content_handler *handler, + lwc_string *imime_type, const struct http_parameter *params, + llcache_handle *llcache, const char *fallback_charset, + bool quirks, struct content **c); +static bool artworks_convert(struct content *c); +static void artworks_destroy(struct content *c); +static bool artworks_redraw(struct content *c, struct content_redraw_data *data, + const struct rect *clip, const struct redraw_context *ctx); +static nserror artworks_clone(const struct content *old, struct content **newc); +static content_type artworks_content_type(void); + +static const content_handler artworks_content_handler = { + .create = artworks_create, + .data_complete = artworks_convert, + .destroy = artworks_destroy, + .redraw = artworks_redraw, + .clone = artworks_clone, + .type = artworks_content_type, + .no_share = false, +}; + +static const char *artworks_types[] = { + "image/x-artworks" +}; + +CONTENT_FACTORY_REGISTER_TYPES(artworks, artworks_types, + artworks_content_handler) + +nserror artworks_create(const content_handler *handler, + lwc_string *imime_type, const struct http_parameter *params, + llcache_handle *llcache, const char *fallback_charset, + bool quirks, struct content **c) +{ + artworks_content *aw; + nserror error; + + aw = calloc(1, sizeof(artworks_content)); + if (aw == NULL) + return NSERROR_NOMEM; + + error = content__init(&aw->base, handler, imime_type, params, + llcache, fallback_charset, quirks); + if (error != NSERROR_OK) { + free(aw); + return error; + } + + *c = (struct content *) aw; + + return NSERROR_OK; +} + +/** + * Convert a CONTENT_ARTWORKS for display. + * + * No conversion is necessary. We merely read the ArtWorks + * bounding box bottom-left. + */ + +bool artworks_convert(struct content *c) +{ + artworks_content *aw = (artworks_content *) c; + union content_msg_data msg_data; + const char *source_data; + unsigned long source_size; + void *init_workspace; + void *init_routine; + os_error *error; + int used = -1; /* slightly better with older OSLib versions */ + char *title; + + /* check whether AWViewer has been seen and we can therefore + locate the ArtWorks rendering modules */ + xos_read_var_val_size("Alias$LoadArtWorksModules", 0, os_VARTYPE_STRING, + &used, NULL, NULL); + if (used >= 0) { + LOG("Alias$LoadArtWorksModules not defined"); + msg_data.error = messages_get("AWNotSeen"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } + + /* load the modules, or do nothing if they're already loaded */ + error = xos_cli("LoadArtWorksModules"); + if (error) { + LOG("xos_cli: 0x%x: %s", error->errnum, error->errmess); + msg_data.error = error->errmess; + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } + + /* lookup the addresses of the init and render routines */ + error = (os_error*)_swix(AWRender_FileInitAddress, _OUT(0) | _OUT(1), + &init_routine, &init_workspace); + if (error) { + LOG("AWRender_FileInitAddress: 0x%x: %s", error->errnum, error->errmess); + msg_data.error = error->errmess; + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } + + error = (os_error*)_swix(AWRender_RenderAddress, _OUT(0) | _OUT(1), + &aw->render_routine, + &aw->render_workspace); + if (error) { + LOG("AWRender_RenderAddress: 0x%x: %s", error->errnum, error->errmess); + msg_data.error = error->errmess; + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } + + source_data = content__get_source_data(c, &source_size); + + /* initialise (convert file to new format if required) */ + error = awrender_init(&source_data, &source_size, + init_routine, init_workspace); + if (error) { + LOG("awrender_init: 0x%x : %s", error->errnum, error->errmess); + msg_data.error = error->errmess; + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } + + error = (os_error*)_swix(AWRender_DocBounds, + _IN(0) | _OUT(2) | _OUT(3) | _OUT(4) | _OUT(5), + source_data, + &aw->x0, + &aw->y0, + &aw->x1, + &aw->y1); + + if (error) { + LOG("AWRender_DocBounds: 0x%x: %s", error->errnum, error->errmess); + msg_data.error = error->errmess; + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } + + LOG("bounding box: %d,%d,%d,%d", aw->x0, aw->y0, aw->x1, aw->y1); + + /* create the resizable workspace required by the + ArtWorksRenderer rendering routine */ + + aw->size = INITIAL_BLOCK_SIZE; + aw->block = malloc(INITIAL_BLOCK_SIZE); + if (!aw->block) { + LOG("failed to create block for ArtworksRenderer"); + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } + + c->width = (aw->x1 - aw->x0) / 512; + c->height = (aw->y1 - aw->y0) / 512; + + title = messages_get_buff("ArtWorksTitle", + nsurl_access_leaf(llcache_handle_get_url(c->llcache)), + c->width, c->height); + if (title != NULL) { + content__set_title(c, title); + free(title); + } + content_set_ready(c); + content_set_done(c); + /* Done: update status bar */ + content_set_status(c, ""); + return true; +} + + +/** + * Destroy a CONTENT_ARTWORKS and free all resources it owns. + */ + +void artworks_destroy(struct content *c) +{ + artworks_content *aw = (artworks_content *) c; + + free(aw->block); +} + + +/** + * Redraw a CONTENT_ARTWORKS. + */ + +bool artworks_redraw(struct content *c, struct content_redraw_data *data, + const struct rect *clip, const struct redraw_context *ctx) +{ + static const ns_os_vdu_var_list vars = { + os_MODEVAR_XEIG_FACTOR, + { + os_MODEVAR_YEIG_FACTOR, + os_MODEVAR_LOG2_BPP, + os_VDUVAR_END_LIST + } + }; + artworks_content *aw = (artworks_content *) c; + struct awinfo_block info; + const char *source_data; + unsigned long source_size; + os_error *error; + os_trfm matrix; + int vals[24]; + + int clip_x0 = clip->x0; + int clip_y0 = clip->y0; + int clip_x1 = clip->x1; + int clip_y1 = clip->y1; + + if (ctx->plot->flush && !ctx->plot->flush()) + return false; + + /* pick up render addresses again in case they've changed + (eg. newer AWRender module loaded since we first loaded this file) */ + (void)_swix(AWRender_RenderAddress, _OUT(0) | _OUT(1), + &aw->render_routine, + &aw->render_workspace); + + /* Scaled image. Transform units (65536*OS units) */ + matrix.entries[0][0] = data->width * 65536 / c->width; + matrix.entries[0][1] = 0; + matrix.entries[1][0] = 0; + matrix.entries[1][1] = data->height * 65536 / c->height; + /* Draw units. (x,y) = bottom left */ + matrix.entries[2][0] = ro_plot_origin_x * 256 + data->x * 512 - + aw->x0 * data->width / c->width; + matrix.entries[2][1] = ro_plot_origin_y * 256 - + (data->y + data->height) * 512 - + aw->y0 * data->height / c->height; + + info.ditherx = ro_plot_origin_x; + info.dithery = ro_plot_origin_y; + + clip_x0 -= data->x; + clip_y0 -= data->y; + clip_x1 -= data->x; + clip_y1 -= data->y; + + if (data->scale == 1.0) { + info.clip_x0 = (clip_x0 * 512) + aw->x0 - 511; + info.clip_y0 = ((c->height - clip_y1) * 512) + aw->y0 - 511; + info.clip_x1 = (clip_x1 * 512) + aw->x0 + 511; + info.clip_y1 = ((c->height - clip_y0) * 512) + aw->y0 + 511; + } + else { + info.clip_x0 = (clip_x0 * 512 / data->scale) + aw->x0 - 511; + info.clip_y0 = ((c->height - (clip_y1 / data->scale)) * 512) + + aw->y0 - 511; + info.clip_x1 = (clip_x1 * 512 / data->scale) + aw->x0 + 511; + info.clip_y1 = ((c->height - (clip_y0 / data->scale)) * 512) + + aw->y0 + 511; + } + + info.print_lowx = 0; + info.print_lowy = 0; + info.print_handle = 0; + info.bgcolour = 0x20000000 | data->background_colour; + + error = xos_read_vdu_variables(PTR_OS_VDU_VAR_LIST(&vars), vals); + if (error) { + LOG("xos_read_vdu_variables: 0x%x: %s", error->errnum, error->errmess); + return false; + } + + error = xwimp_read_palette((os_palette*)&vals[3]); + if (error) { + LOG("xwimp_read_palette: 0x%x: %s", error->errnum, error->errmess); + return false; + } + + source_data = content__get_source_data(c, &source_size); + + error = awrender_render(source_data, + &info, + &matrix, + vals, + &aw->block, + &aw->size, + 110, /* fully anti-aliased */ + 0, + source_size, + aw->render_routine, + aw->render_workspace); + + if (error) { + LOG("awrender_render: 0x%x: %s", error->errnum, error->errmess); + return false; + } + + return true; +} + +nserror artworks_clone(const struct content *old, struct content **newc) +{ + artworks_content *aw; + nserror error; + + aw = calloc(1, sizeof(artworks_content)); + if (aw == NULL) + return NSERROR_NOMEM; + + error = content__clone(old, &aw->base); + if (error != NSERROR_OK) { + content_destroy(&aw->base); + return error; + } + + /* Simply re-run convert */ + if (old->status == CONTENT_STATUS_READY || + old->status == CONTENT_STATUS_DONE) { + if (artworks_convert(&aw->base) == false) { + content_destroy(&aw->base); + return NSERROR_CLONE_FAILED; + } + } + + *newc = (struct content *) aw; + + return NSERROR_OK; +} + +content_type artworks_content_type(void) +{ + return CONTENT_IMAGE; +} + +#endif diff --git a/frontends/riscos/content-handlers/artworks.h b/frontends/riscos/content-handlers/artworks.h new file mode 100644 index 000000000..67832cc54 --- /dev/null +++ b/frontends/riscos/content-handlers/artworks.h @@ -0,0 +1,42 @@ +/* + * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * Content for image/x-artworks (RISC OS interface). + */ + +#ifndef _NETSURF_RISCOS_ARTWORKS_H_ +#define _NETSURF_RISCOS_ARTWORKS_H_ + +#include "utils/config.h" +#include "utils/errors.h" + +#ifdef WITH_ARTWORKS + +nserror artworks_init(void); + +#else + +static inline nserror artworks_init(void) +{ + return NSERROR_OK; +} + +#endif + +#endif diff --git a/frontends/riscos/content-handlers/awrender.s b/frontends/riscos/content-handlers/awrender.s new file mode 100644 index 000000000..5bcafe520 --- /dev/null +++ b/frontends/riscos/content-handlers/awrender.s @@ -0,0 +1,390 @@ +#if defined(__aof__) + AREA |ARM$$code|,CODE,READONLY + + IMPORT messages_get + IMPORT realloc + IMPORT strcpy + IMPORT |__rt_stkovf_split_big| + + EXPORT awrender_init + EXPORT awrender_render + + +aw_rsz_block * 0 +aw_rsz_size * 4 +aw_fixed_block * 8 +aw_fixed_size * 12 +aw_sl * 16 +aw_fp * 20 +sizeof_aw * 24 + + +; os_error *awrender_init(byte **doc, size_t *doc_size, void *init_routine, void *init_workspace); + +awrender_init MOV ip,sp + STMFD sp!,{a1,a2,v1,v2,fp,ip,lr,pc} + SUB fp,ip,#4 + SUB ip,sp,#512 + CMP ip,sl + BLMI |__rt_stkovf_split_big| + + LDR v2,=aw_temp + LDR a1,[a1] + MOV v1,a3 + LDR a3,[a2] + MOV ip,a4 + STR a1,[v2,#aw_rsz_block] + STR a3,[v2,#aw_rsz_size] + MOV a2,#-1 + STR a2,[v2,#aw_fixed_block] + STR a3,[v2,#aw_fixed_size] + STR sl,[v2,#aw_sl] + STR fp,[v2,#aw_fp] + ADR a2,aw_callback + MOV lr,pc + MOV pc,v1 + MOVVC a1,#0 + + ;return updated block ptr & size to caller + + LDR a2,[fp,#-28] + LDR a3,[fp,#-24] + LDR ip,[v2,#aw_rsz_block] + LDR lr,[v2,#aw_rsz_size] + STR ip,[a2] + STR lr,[a3] + + LDMEA fp,{v1,v2,fp,sp,pc} + + +; os_error *awrender_render(const char *doc, +; const struct awinfo_block *info, +; const os_trfm *trans, +; const int *vdu_vars, +; char **rsz_block, +; size_t *rsz_size, +; int wysiwyg_setting, +; int output_dest, +; size_t doc_size, +; void *routine, +; void *workspace); + +awrender_render MOV ip,sp + STMFD sp!,{v1-v4,fp,ip,lr,pc} + SUB fp,ip,#4 + SUB ip,sp,#512 + CMP ip,sl + BLMI |__rt_stkovf_split_big| + + LDR R12,[fp,#20] + LDR R14,=aw_temp + LDR R5,[fp,#4] + LDR R6,[fp,#12] + LDR R4,[R5] ;resizable block + LDR R7,[fp,#16] + STR R4,[R14,#aw_rsz_block] + STR R0,[R14,#aw_fixed_block] ;document ptr + STR R12,[R14,#aw_fixed_size] ;document size + LDR R12,[fp,#8] + + STR R5,[sp,#-4]! ;ptr to receive block + STR R12,[sp,#-4]! ;ptr to receive size + + LDR R12,[R12] + ADR R5,aw_callback + STR R12,[R14,#aw_rsz_size] + + STR sl,[R14,#aw_sl] + STR fp,[R14,#aw_fp] + + LDR R12,[fp,#28] + MOV lr,pc + LDR pc,[fp,#24] + MOVVC a1,#0 + + ;return updated block ptr & size to caller + + LDR R7,=aw_temp + LDR R12,[sp],#4 + LDR R4,[sp],#4 + LDR R5,[R7,#aw_rsz_size] + LDR R6,[R7,#aw_rsz_block] + STR R5,[R12] + STR R6,[R4] + + LDMEA fp,{v1-v4,fp,sp,pc} + + +; Callback routine for block resizing +; (passed to AWRender init and render routines) +; +; entry R11 = reason code +; 0 = CallBackReason_Memory +; 3 = CallBackReason_Interface +; (0 => return capabilities) +; exit R0 => base of resizable block +; R1 = size of resizable block +; R2 => base of fixed block (or -1 if no fixed block) +; R3 = size of fixed block (or document in resizable block) +; VC if resize successful, VS and R0 => error otherwise + +aw_callback TEQ R11,#3 + TEQEQ R0,#0 + MOVEQ R0,#1<<10 ;background colour supplied + TEQ R11,#0 + LDREQ R11,=aw_temp + MOVNE PC,R14 + + CMP R0,#-1 ;read block size? + LDRNE R2,[R11,#aw_rsz_size] + MOVNE R1,R0 ;new block size + LDR R0,[R11,#aw_rsz_block] + BEQ aw_read + + ; Note: because ArtworksRenderer seems to call + ; this routine for every scanline rendered + ; we never call realloc unless we have to in + ; order to expand the block. Also it calls + ; us with a size request of 0 which we must + ; safely ignore otherwise rendering will stop. + + CMP R1,R2 + BLS aw_read + + STMFD R13!,{R1,R10-R12,R14} + LDR sl,[R11,#aw_sl] + LDR fp,[R11,#aw_fp] + BL realloc + LDMFD R13!,{R1,R10-R12,R14} + + CMP R0,#0 ;did it work? + BEQ aw_nomem + + STR R0,[R11] + STR R1,[R11,#aw_rsz_size] + +aw_read ; return details of fixed block + + LDR R2,[R11,#aw_fixed_block] + LDR R3,[R11,#aw_fixed_size] + SUBS R11,R11,R11 ;clear V + MOV PC,R14 + +aw_nomem STMFD R13!,{R10,R12,R14} + LDR sl,[R11,#aw_sl] + LDR fp,[R11,#aw_fp] + ADR R0,tok_nomem + BL messages_get + MOV a2,a1 + LDR a1,=errblk + 4 + BL strcpy + SUB R0,R0,#4 ;error number already 0 + MOV R11,#0 ;restore reason code + CMP PC,#1<<31 ;set V + LDMFD R13!,{R10,R12,PC} + +tok_nomem = "NoMemory",0 + ALIGN + + + AREA |ARM$$zidata|,DATA,NOINIT + +aw_temp % sizeof_aw +errblk % 256 + + END + +#elif defined(__ELF__) + + .text + +.set aw_rsz_block, 0 +.set aw_rsz_size, 4 +.set aw_fixed_block, 8 +.set aw_fixed_size, 12 +.set aw_sl, 16 +.set aw_fp, 20 +.set sizeof_aw, 24 + +@ os_error *awrender_init(byte **doc, size_t *doc_size, void *init_routine, void *init_workspace); + + .global awrender_init +awrender_init: MOV ip,sp + STMFD sp!,{a1,a2,v1,v2,fp,ip,lr,pc} + SUB fp,ip,#4 + SUB ip,sp,#512 + CMP ip,sl + BLMI __rt_stkovf_split_big + + LDR v2,=aw_temp + LDR a1,[a1] + MOV v1,a3 + LDR a3,[a2] + MOV ip,a4 + STR a1,[v2,#aw_rsz_block] + STR a3,[v2,#aw_rsz_size] + MOV a2,#-1 + STR a2,[v2,#aw_fixed_block] + STR a3,[v2,#aw_fixed_size] + STR sl,[v2,#aw_sl] + STR fp,[v2,#aw_fp] + ADR a2,aw_callback + MOV lr,pc + MOV pc,v1 + MOVVC a1,#0 + + @ return updated block ptr & size to caller + + LDR a2,[fp,#-28] + LDR a3,[fp,#-24] + LDR ip,[v2,#aw_rsz_block] + LDR lr,[v2,#aw_rsz_size] + STR ip,[a2] + STR lr,[a3] + + LDMEA fp,{v1,v2,fp,sp,pc} + + +@ os_error *awrender_render(const char *doc, +@ const struct awinfo_block *info, +@ const os_trfm *trans, +@ const int *vdu_vars, +@ char **rsz_block, +@ size_t *rsz_size, +@ int wysiwyg_setting, +@ int output_dest, +@ size_t doc_size, +@ void *routine, +@ void *workspace); + + .global awrender_render +awrender_render: MOV ip,sp + STMFD sp!,{v1-v4,fp,ip,lr,pc} + SUB fp,ip,#4 + SUB ip,sp,#512 + CMP ip,sl + BLMI __rt_stkovf_split_big + + LDR R12,[fp,#20] + LDR R14,=aw_temp + LDR R5,[fp,#4] + LDR R6,[fp,#12] + LDR R4,[R5] @ resizable block + LDR R7,[fp,#16] + STR R4,[R14,#aw_rsz_block] + STR R0,[R14,#aw_fixed_block] @ document ptr + STR R12,[R14,#aw_fixed_size] @ document size + LDR R12,[fp,#8] + + STR R5,[sp,#-4]! @ ptr to receive block + STR R12,[sp,#-4]! @ ptr to receive size + + LDR R12,[R12] + ADR R5,aw_callback + STR R12,[R14,#aw_rsz_size] + + STR sl,[R14,#aw_sl] + STR fp,[R14,#aw_fp] + + LDR R12,[fp,#28] + MOV lr,pc + LDR pc,[fp,#24] + MOVVC a1,#0 + + @ return updated block ptr & size to caller + + LDR R7,=aw_temp + LDR R12,[sp],#4 + LDR R4,[sp],#4 + LDR R5,[R7,#aw_rsz_size] + LDR R6,[R7,#aw_rsz_block] + STR R5,[R12] + STR R6,[R4] + + LDMEA fp,{v1-v4,fp,sp,pc} + + +@ Callback routine for block resizing +@ (passed to AWRender init and render routines) +@ +@ entry R11 = reason code +@ 0 = CallBackReason_Memory +@ 3 = CallBackReason_Interface +@ (0 => return capabilities) +@ exit R0 => base of resizable block +@ R1 = size of resizable block +@ R2 => base of fixed block (or -1 if no fixed block) +@ R3 = size of fixed block (or document in resizable block) +@ VC if resize successful, VS and R0 => error otherwise + +aw_callback: TEQ R11,#3 + TEQEQ R0,#0 + MOVEQ R0,#1<<10 @ background colour supplied + TEQ R11,#0 + LDREQ R11,=aw_temp + MOVNE PC,R14 + + CMP R0,#-1 @ read block size? + LDRNE R2,[R11,#aw_rsz_size] + MOVNE R1,R0 @ new block size + LDR R0,[R11,#aw_rsz_block] + BEQ aw_read + + @ Note: because ArtworksRenderer seems to call + @ this routine for every scanline rendered + @ we never call realloc unless we have to in + @ order to expand the block. Also it calls + @ us with a size request of 0 which we must + @ safely ignore otherwise rendering will stop. + + CMP R1,R2 + BLS aw_read + + STMFD R13!,{R1,R10-R12,R14} + LDR sl,[R11,#aw_sl] + LDR fp,[R11,#aw_fp] + BL realloc + LDMFD R13!,{R1,R10-R12,R14} + + CMP R0,#0 @ did it work? + BEQ aw_nomem + + STR R0,[R11] + STR R1,[R11,#aw_rsz_size] + +aw_read: @ return details of fixed block + + LDR R2,[R11,#aw_fixed_block] + LDR R3,[R11,#aw_fixed_size] + SUBS R11,R11,R11 @ clear V + MOV PC,R14 + +aw_nomem: STMFD R13!,{R10,R12,R14} + LDR sl,[R11,#aw_sl] + LDR fp,[R11,#aw_fp] + ADR R0,tok_nomem + BL messages_get + MOV a2,a1 + LDR a1,=errblk + 4 + BL strcpy + SUB R0,R0,#4 @ error number already 0 + MOV R11,#0 @ restore reason code + CMP PC,#1<<31 @ set V + LDMFD R13!,{R10,R12,PC} + +tok_nomem: .asciz "NoMemory" + .align + + .bss + +aw_temp: .space sizeof_aw + .type aw_temp, %object + .size aw_temp, . - aw_temp + +errblk: .space 256 + .type errblk, %object + .size errblk, . - errblk + + .end +#endif + diff --git a/frontends/riscos/content-handlers/draw.c b/frontends/riscos/content-handlers/draw.c new file mode 100644 index 000000000..f2bee16dc --- /dev/null +++ b/frontends/riscos/content-handlers/draw.c @@ -0,0 +1,254 @@ +/* + * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * Content for image/x-drawfile (RISC OS implementation). + * + * The DrawFile module is used to plot the DrawFile. + */ + +#include "utils/config.h" +#ifdef WITH_DRAW + +#include <string.h> +#include <stdlib.h> +#include "oslib/drawfile.h" + +#include "utils/config.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/utils.h" +#include "content/content_protected.h" +#include "desktop/plotters.h" + +#include "riscos/content-handlers/draw.h" +#include "riscos/gui.h" + +typedef struct draw_content { + struct content base; + + int x0, y0; +} draw_content; + +static nserror draw_create(const content_handler *handler, + lwc_string *imime_type, const struct http_parameter *params, + llcache_handle *llcache, const char *fallback_charset, + bool quirks, struct content **c); +static bool draw_convert(struct content *c); +static void draw_destroy(struct content *c); +static bool draw_redraw(struct content *c, struct content_redraw_data *data, + const struct rect *clip, const struct redraw_context *ctx); +static nserror draw_clone(const struct content *old, struct content **newc); +static content_type draw_content_type(void); + +static const content_handler draw_content_handler = { + .create = draw_create, + .data_complete = draw_convert, + .destroy = draw_destroy, + .redraw = draw_redraw, + .clone = draw_clone, + .type = draw_content_type, + .no_share = false, +}; + +static const char *draw_types[] = { + "application/drawfile", + "application/x-drawfile", + "image/drawfile", + "image/x-drawfile" +}; + +CONTENT_FACTORY_REGISTER_TYPES(draw, draw_types, draw_content_handler) + +nserror draw_create(const content_handler *handler, + lwc_string *imime_type, const struct http_parameter *params, + llcache_handle *llcache, const char *fallback_charset, + bool quirks, struct content **c) +{ + draw_content *draw; + nserror error; + + draw = calloc(1, sizeof(draw_content)); + if (draw == NULL) + return NSERROR_NOMEM; + + error = content__init(&draw->base, handler, imime_type, params, + llcache, fallback_charset, quirks); + if (error != NSERROR_OK) { + free(draw); + return error; + } + + *c = (struct content *) draw; + + return NSERROR_OK; +} + +/** + * Convert a CONTENT_DRAW for display. + * + * No conversion is necessary. We merely read the DrawFile dimensions and + * bounding box bottom-left. + */ + +bool draw_convert(struct content *c) +{ + draw_content *draw = (draw_content *) c; + union content_msg_data msg_data; + const char *source_data; + unsigned long source_size; + const void *data; + os_box bbox; + os_error *error; + char *title; + + source_data = content__get_source_data(c, &source_size); + data = source_data; + + /* BBox contents in Draw units (256*OS unit) */ + error = xdrawfile_bbox(0, (drawfile_diagram *) data, + (int) source_size, 0, &bbox); + if (error) { + 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; + } + + if (bbox.x1 > bbox.x0 && bbox.y1 > bbox.y0) { + /* 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); + } + else + /* invalid/undefined bounding box */ + c->height = c->width = 0; + + draw->x0 = bbox.x0; + draw->y0 = bbox.y0; + + title = messages_get_buff("DrawTitle", + nsurl_access_leaf(llcache_handle_get_url(c->llcache)), + c->width, c->height); + if (title != NULL) { + content__set_title(c, title); + free(title); + } + + content_set_ready(c); + content_set_done(c); + /* Done: update status bar */ + content_set_status(c, ""); + return true; +} + + +/** + * Destroy a CONTENT_DRAW and free all resources it owns. + */ + +void draw_destroy(struct content *c) +{ +} + + +/** + * Redraw a CONTENT_DRAW. + */ + +bool draw_redraw(struct content *c, struct content_redraw_data *data, + const struct rect *clip, const struct redraw_context *ctx) +{ + draw_content *draw = (draw_content *) c; + os_trfm matrix; + const char *source_data; + unsigned long source_size; + const void *src_data; + os_error *error; + + if (ctx->plot->flush && !ctx->plot->flush()) + return false; + + if (!c->width || !c->height) + return false; + + source_data = content__get_source_data(c, &source_size); + src_data = source_data; + + /* Scaled image. Transform units (65536*OS units) */ + matrix.entries[0][0] = data->width * 65536 / c->width; + matrix.entries[0][1] = 0; + matrix.entries[1][0] = 0; + matrix.entries[1][1] = data->height * 65536 / c->height; + /* Draw units. (x,y) = bottom left */ + matrix.entries[2][0] = ro_plot_origin_x * 256 + data->x * 512 - + draw->x0 * data->width / c->width; + matrix.entries[2][1] = ro_plot_origin_y * 256 - + (data->y + data->height) * 512 - + draw->y0 * data->height / c->height; + + error = xdrawfile_render(0, (drawfile_diagram *) src_data, + (int) source_size, &matrix, 0, 0); + if (error) { + LOG("xdrawfile_render: 0x%x: %s", error->errnum, error->errmess); + return false; + } + + return true; +} + +/** + * Clone a CONTENT_DRAW + */ + +nserror draw_clone(const struct content *old, struct content **newc) +{ + draw_content *draw; + nserror error; + + draw = calloc(1, sizeof(draw_content)); + if (draw == NULL) + return NSERROR_NOMEM; + + error = content__clone(old, &draw->base); + if (error != NSERROR_OK) { + content_destroy(&draw->base); + return error; + } + + /* Simply rerun convert */ + if (old->status == CONTENT_STATUS_READY || + old->status == CONTENT_STATUS_DONE) { + if (draw_convert(&draw->base) == false) { + content_destroy(&draw->base); + return NSERROR_CLONE_FAILED; + } + } + + *newc = (struct content *) draw; + + return NSERROR_OK; +} + +content_type draw_content_type(void) +{ + return CONTENT_IMAGE; +} + +#endif diff --git a/frontends/riscos/content-handlers/draw.h b/frontends/riscos/content-handlers/draw.h new file mode 100644 index 000000000..9f5baf6dc --- /dev/null +++ b/frontends/riscos/content-handlers/draw.h @@ -0,0 +1,42 @@ +/* + * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * Content for image/x-drawfile (RISC OS interface). + */ + +#ifndef _NETSURF_RISCOS_DRAW_H_ +#define _NETSURF_RISCOS_DRAW_H_ + +#include "utils/config.h" +#include "utils/errors.h" + +#ifdef WITH_DRAW + +nserror draw_init(void); + +#else + +static inline nserror draw_init(void) +{ + return NSERROR_OK; +} + +#endif /* WITH_DRAW */ + +#endif diff --git a/frontends/riscos/content-handlers/sprite.c b/frontends/riscos/content-handlers/sprite.c new file mode 100644 index 000000000..12fed4931 --- /dev/null +++ b/frontends/riscos/content-handlers/sprite.c @@ -0,0 +1,266 @@ +/* + * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * Content for image/x-riscos-sprite (RISC OS implementation). + * + * No conversion is necessary: we can render RISC OS sprites directly under + * RISC OS. + */ + +#include <string.h> +#include <stdlib.h> +#include "oslib/osspriteop.h" + +#include "utils/config.h" +#include "utils/config.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/utils.h" +#include "content/content_protected.h" +#include "desktop/plotters.h" + +#include "riscos/gui.h" +#include "riscos/image.h" +#include "riscos/content-handlers/sprite.h" + +#ifdef WITH_SPRITE + +typedef struct sprite_content { + struct content base; + + void *data; +} sprite_content; + +static nserror sprite_create(const content_handler *handler, + lwc_string *imime_type, const struct http_parameter *params, + llcache_handle *llcache, const char *fallback_charset, + bool quirks, struct content **c); +static bool sprite_convert(struct content *c); +static void sprite_destroy(struct content *c); +static bool sprite_redraw(struct content *c, struct content_redraw_data *data, + const struct rect *clip, const struct redraw_context *ctx); +static nserror sprite_clone(const struct content *old, struct content **newc); +static content_type sprite_content_type(void); + +static const content_handler sprite_content_handler = { + .create = sprite_create, + .data_complete = sprite_convert, + .destroy = sprite_destroy, + .redraw = sprite_redraw, + .clone = sprite_clone, + .type = sprite_content_type, + .no_share = false, +}; + +static const char *sprite_types[] = { + "image/x-riscos-sprite" +}; + +CONTENT_FACTORY_REGISTER_TYPES(sprite, sprite_types, sprite_content_handler) + +nserror sprite_create(const content_handler *handler, + lwc_string *imime_type, const struct http_parameter *params, + llcache_handle *llcache, const char *fallback_charset, + bool quirks, struct content **c) +{ + sprite_content *sprite; + nserror error; + + sprite = calloc(1, sizeof(sprite_content)); + if (sprite == NULL) + return NSERROR_NOMEM; + + error = content__init(&sprite->base, handler, imime_type, params, + llcache, fallback_charset, quirks); + if (error != NSERROR_OK) { + free(sprite); + return error; + } + + *c = (struct content *) sprite; + + return NSERROR_OK; +} + +/** + * Convert a CONTENT_SPRITE for display. + * + * No conversion is necessary. We merely read the sprite dimensions. + */ + +bool sprite_convert(struct content *c) +{ + sprite_content *sprite = (sprite_content *) c; + os_error *error; + int w, h; + union content_msg_data msg_data; + const char *source_data; + unsigned long source_size; + const void *sprite_data; + char *title; + + source_data = content__get_source_data(c, &source_size); + + sprite_data = source_data - 4; + osspriteop_area *area = (osspriteop_area*) sprite_data; + sprite->data = area; + + /* check for bad data */ + if ((int)source_size + 4 != area->used) { + msg_data.error = messages_get("BadSprite"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } + + error = xosspriteop_read_sprite_info(osspriteop_PTR, + (osspriteop_area *)0x100, + (osspriteop_id) ((char *) area + 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; + + /* set title text */ + title = messages_get_buff("SpriteTitle", + nsurl_access_leaf(llcache_handle_get_url(c->llcache)), + c->width, c->height); + if (title != NULL) { + content__set_title(c, title); + free(title); + } + content_set_ready(c); + content_set_done(c); + /* Done: update status bar */ + content_set_status(c, ""); + return true; +} + + +/** + * Destroy a CONTENT_SPRITE and free all resources it owns. + */ + +void sprite_destroy(struct content *c) +{ + /* do not free c->data.sprite.data at it is simply a pointer to + * 4 bytes beforec->source_data. */ +} + + +/** + * Redraw a CONTENT_SPRITE. + */ + +bool sprite_redraw(struct content *c, struct content_redraw_data *data, + const struct rect *clip, const struct redraw_context *ctx) +{ + sprite_content *sprite = (sprite_content *) c; + + if (ctx->plot->flush && !ctx->plot->flush()) + return false; + + return image_redraw(sprite->data, + ro_plot_origin_x + data->x * 2, + ro_plot_origin_y - data->y * 2, + data->width, data->height, + c->width, + c->height, + data->background_colour, + false, false, false, + IMAGE_PLOT_OS); +} + +nserror sprite_clone(const struct content *old, struct content **newc) +{ + sprite_content *sprite; + nserror error; + + sprite = calloc(1, sizeof(sprite_content)); + if (sprite == NULL) + return NSERROR_NOMEM; + + error = content__clone(old, &sprite->base); + if (error != NSERROR_OK) { + content_destroy(&sprite->base); + return error; + } + + /* Simply rerun convert */ + if (old->status == CONTENT_STATUS_READY || + old->status == CONTENT_STATUS_DONE) { + if (sprite_convert(&sprite->base) == false) { + content_destroy(&sprite->base); + return NSERROR_CLONE_FAILED; + } + } + + *newc = (struct content *) sprite; + + return NSERROR_OK; +} + +content_type sprite_content_type(void) +{ + return CONTENT_IMAGE; +} + +#endif + + +/** + * Returns the bit depth of a sprite + * + * \param s sprite + * \return depth in bpp + */ + +byte sprite_bpp(const osspriteop_header *s) +{ + /* bit 31 indicates the presence of a full alpha channel + * rather than a binary mask */ + int type = ((unsigned)s->mode >> osspriteop_TYPE_SHIFT) & 15; + byte bpp = 0; + + switch (type) { + case osspriteop_TYPE_OLD: + { + bits psr; + int val; + if (!xos_read_mode_variable(s->mode, + os_MODEVAR_LOG2_BPP, &val, &psr) && + !(psr & _C)) + bpp = 1 << val; + } + break; + case osspriteop_TYPE1BPP: bpp = 1; break; + case osspriteop_TYPE2BPP: bpp = 2; break; + case osspriteop_TYPE4BPP: bpp = 4; break; + case osspriteop_TYPE8BPP: bpp = 8; break; + case osspriteop_TYPE16BPP: bpp = 16; break; + case osspriteop_TYPE32BPP: bpp = 32; break; + case osspriteop_TYPE_CMYK: bpp = 32; break; + } + return bpp; +} diff --git a/frontends/riscos/content-handlers/sprite.h b/frontends/riscos/content-handlers/sprite.h new file mode 100644 index 000000000..ab6d312a5 --- /dev/null +++ b/frontends/riscos/content-handlers/sprite.h @@ -0,0 +1,44 @@ +/* + * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * Content for image/x-riscos-sprite (RISC OS interface). + */ + +#ifndef _NETSURF_RISCOS_SPRITE_H_ +#define _NETSURF_RISCOS_SPRITE_H_ + +#include "utils/config.h" +#include "utils/errors.h" + +#ifdef WITH_SPRITE + +nserror sprite_init(void); + +#else + +static inline nserror sprite_init(void) +{ + return NSERROR_OK; +} + +#endif + +byte sprite_bpp(const osspriteop_header *s); + +#endif diff --git a/frontends/riscos/cookies.c b/frontends/riscos/cookies.c new file mode 100644 index 000000000..93c9f39cf --- /dev/null +++ b/frontends/riscos/cookies.c @@ -0,0 +1,385 @@ +/* + * Copyright 2006 Richard Wilson <info@tinct.net> + * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * Cookies (implementation). + */ + +#include <assert.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "oslib/wimp.h" +#include "oslib/wimpspriteop.h" + +#include "utils/nsoption.h" +#include "utils/messages.h" +#include "utils/log.h" +#include "content/urldb.h" +#include "desktop/cookie_manager.h" +#include "desktop/tree.h" +#include "desktop/textinput.h" + +#include "riscos/cookies.h" +#include "riscos/dialog.h" +#include "riscos/menus.h" +#include "riscos/toolbar.h" +#include "riscos/treeview.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" + +static void ro_gui_cookies_toolbar_update_buttons(void); +static void ro_gui_cookies_toolbar_save_buttons(char *config); +static bool ro_gui_cookies_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer); +static void ro_gui_cookies_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action); +static bool ro_gui_cookies_menu_select(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action); +static void ro_gui_cookies_toolbar_click(button_bar_action action); + +struct ro_treeview_callbacks ro_cookies_treeview_callbacks = { + ro_gui_cookies_toolbar_click, + ro_gui_cookies_toolbar_update_buttons, + ro_gui_cookies_toolbar_save_buttons +}; + +/* The RISC OS cookie window, toolbar and treeview data. */ + +static struct ro_cookies_window { + wimp_w window; + struct toolbar *toolbar; + ro_treeview *tv; + wimp_menu *menu; +} cookies_window; + +/** + * Pre-Initialise the cookies tree. This is called for things that + * need to be done at the gui_init() stage, such as loading templates. + */ + +void ro_gui_cookies_preinitialise(void) +{ + /* Create our window. */ + + cookies_window.window = ro_gui_dialog_create("tree"); + ro_gui_set_window_title(cookies_window.window, + messages_get("Cookies")); +} + +/** + * Initialise cookies tree, at the gui_init2() stage. + */ + +void ro_gui_cookies_postinitialise(void) +{ + /* Create our toolbar. */ + + cookies_window.toolbar = ro_toolbar_create(NULL, cookies_window.window, + THEME_STYLE_COOKIES_TOOLBAR, TOOLBAR_FLAGS_NONE, + ro_treeview_get_toolbar_callbacks(), NULL, + "HelpCookiesToolbar"); + if (cookies_window.toolbar != NULL) { + ro_toolbar_add_buttons(cookies_window.toolbar, + cookies_toolbar_buttons, + nsoption_charp(toolbar_cookies)); + ro_toolbar_rebuild(cookies_window.toolbar); + } + + /* Create the treeview with the window and toolbar. */ + + cookies_window.tv = ro_treeview_create(cookies_window.window, + cookies_window.toolbar, &ro_cookies_treeview_callbacks, + TREE_COOKIES); + if (cookies_window.tv == NULL) { + LOG("Failed to allocate treeview"); + return; + } + + ro_toolbar_update_client_data(cookies_window.toolbar, + cookies_window.tv); + + /* Build the cookies window menu. */ + + static const struct ns_menu cookies_definition = { + "Cookies", { + { "Cookies", NO_ACTION, 0 }, + { "Cookies.Expand", TREE_EXPAND_ALL, 0 }, + { "Cookies.Expand.All", TREE_EXPAND_ALL, 0 }, + { "Cookies.Expand.Folders", TREE_EXPAND_FOLDERS, 0 }, + { "Cookies.Expand.Links", TREE_EXPAND_LINKS, 0 }, + { "Cookies.Collapse", TREE_COLLAPSE_ALL, 0 }, + { "Cookies.Collapse.All", TREE_COLLAPSE_ALL, 0 }, + { "Cookies.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 }, + { "Cookies.Collapse.Links", TREE_COLLAPSE_LINKS, 0 }, + { "Cookies.Toolbars", NO_ACTION, 0 }, + { "_Cookies.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 }, + { "Cookies.Toolbars.EditToolbar",TOOLBAR_EDIT, 0 }, + { "Selection", TREE_SELECTION, 0 }, + { "Selection.Delete", TREE_SELECTION_DELETE, 0 }, + { "SelectAll", TREE_SELECT_ALL, 0 }, + { "Clear", TREE_CLEAR_SELECTION, 0 }, + {NULL, 0, 0} + } + }; + cookies_window.menu = ro_gui_menu_define_menu(&cookies_definition); + + ro_gui_wimp_event_register_menu(cookies_window.window, + cookies_window.menu, false, false); + ro_gui_wimp_event_register_menu_prepare(cookies_window.window, + ro_gui_cookies_menu_prepare); + ro_gui_wimp_event_register_menu_selection(cookies_window.window, + ro_gui_cookies_menu_select); + ro_gui_wimp_event_register_menu_warning(cookies_window.window, + ro_gui_cookies_menu_warning); +} + +/** + * Destroy the cookies window. + */ + +void ro_gui_cookies_destroy(void) +{ + if (cookies_window.tv == NULL) + return; + + ro_treeview_destroy(cookies_window.tv); +} + +/** + * Open the cookies window. + * + */ + +void ro_gui_cookies_open(void) +{ + ro_gui_cookies_toolbar_update_buttons(); + + if (!ro_gui_dialog_open_top(cookies_window.window, + cookies_window.toolbar, 600, 800)) { + ro_treeview_set_origin(cookies_window.tv, 0, + -(ro_toolbar_height(cookies_window.toolbar))); + } +} + + +/** + * Handle toolbar button clicks. + * + * \param action The action to handle + */ + +void ro_gui_cookies_toolbar_click(button_bar_action action) +{ + switch (action) { + case TOOLBAR_BUTTON_DELETE: + cookie_manager_keypress(NS_KEY_DELETE_LEFT); + break; + + case TOOLBAR_BUTTON_EXPAND: + cookie_manager_expand(false); + break; + + case TOOLBAR_BUTTON_COLLAPSE: + cookie_manager_contract(false); + break; + + case TOOLBAR_BUTTON_OPEN: + cookie_manager_expand(true); + break; + + case TOOLBAR_BUTTON_CLOSE: + cookie_manager_contract(true); + break; + + default: + break; + } +} + + +/** + * Update the button state in the cookies toolbar. + */ + +void ro_gui_cookies_toolbar_update_buttons(void) +{ + ro_toolbar_set_button_shaded_state(cookies_window.toolbar, + TOOLBAR_BUTTON_DELETE, + !cookie_manager_has_selection()); +} + + +/** + * Save a new button arrangement in the cookies toolbar. + * + * \param *config The new button configuration string. + */ + +void ro_gui_cookies_toolbar_save_buttons(char *config) +{ + nsoption_set_charp(toolbar_cookies, config); + ro_gui_save_options(); +} + + +/** + * Prepare the cookies menu for opening + * + * \param w The window owning the menu. + * \param i The icon owning the menu. + * \param *menu The menu about to be opened. + * \param *pointer Pointer to the relevant wimp event block, or + * NULL for an Adjust click. + * \return true if the event was handled; else false. + */ + +bool ro_gui_cookies_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer) +{ + bool selection; + + if (menu != cookies_window.menu) + return false; + + selection = cookie_manager_has_selection(); + + ro_gui_menu_set_entry_shaded(cookies_window.menu, + TREE_SELECTION, !selection); + ro_gui_menu_set_entry_shaded(cookies_window.menu, + TREE_CLEAR_SELECTION, !selection); + + ro_gui_menu_set_entry_shaded(menu, TOOLBAR_BUTTONS, + ro_toolbar_menu_option_shade(cookies_window.toolbar)); + ro_gui_menu_set_entry_ticked(menu, TOOLBAR_BUTTONS, + ro_toolbar_menu_buttons_tick(cookies_window.toolbar)); + + ro_gui_menu_set_entry_shaded(menu, TOOLBAR_EDIT, + ro_toolbar_menu_edit_shade(cookies_window.toolbar)); + ro_gui_menu_set_entry_ticked(menu, TOOLBAR_EDIT, + ro_toolbar_menu_edit_tick(cookies_window.toolbar)); + + return true; +} + +/** + * Handle submenu warnings for the cookies menu + * + * \param w The window owning the menu. + * \param i The icon owning the menu. + * \param *menu The menu to which the warning applies. + * \param *selection The wimp menu selection data. + * \param action The selected menu action. + */ + +void ro_gui_cookies_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action) +{ + /* Do nothing */ +} + +/** + * Handle selections from the cookies menu + * + * \param w The window owning the menu. + * \param i The icon owning the menu. + * \param *menu The menu from which the selection was made. + * \param *selection The wimp menu selection data. + * \param action The selected menu action. + * \return true if action accepted; else false. + */ + +bool ro_gui_cookies_menu_select(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action) +{ + switch (action) { + case TREE_EXPAND_ALL: + cookie_manager_expand(false); + return true; + case TREE_EXPAND_FOLDERS: + cookie_manager_expand(true); + return true; + case TREE_EXPAND_LINKS: + cookie_manager_expand(false); + return true; + case TREE_COLLAPSE_ALL: + cookie_manager_contract(true); + return true; + case TREE_COLLAPSE_FOLDERS: + cookie_manager_contract(true); + return true; + case TREE_COLLAPSE_LINKS: + cookie_manager_contract(false); + return true; + case TREE_SELECTION_DELETE: + cookie_manager_keypress(NS_KEY_DELETE_LEFT); + return true; + case TREE_SELECT_ALL: + cookie_manager_keypress(NS_KEY_SELECT_ALL); + return true; + case TREE_CLEAR_SELECTION: + cookie_manager_keypress(NS_KEY_CLEAR_SELECTION); + return true; + case TOOLBAR_BUTTONS: + ro_toolbar_set_display_buttons(cookies_window.toolbar, + !ro_toolbar_get_display_buttons( + cookies_window.toolbar)); + return true; + case TOOLBAR_EDIT: + ro_toolbar_toggle_edit(cookies_window.toolbar); + return true; + default: + return false; + } + + return false; +} + +/** + * Check if a particular window handle is the cookies window + * + * \param window the window in question + * \return true if this window is the cookies + */ + +bool ro_gui_cookies_check_window(wimp_w window) +{ + if (cookies_window.window == window) + return true; + else + return false; +} + +/** + * Check if a particular menu handle is the cookies menu + * + * \param *menu The menu in question. + * \return true if this menu is the cookies menu + */ + +bool ro_gui_cookies_check_menu(wimp_menu *menu) +{ + if (cookies_window.menu == menu) + return true; + else + return false; +} + diff --git a/frontends/riscos/cookies.h b/frontends/riscos/cookies.h new file mode 100644 index 000000000..b7313393e --- /dev/null +++ b/frontends/riscos/cookies.h @@ -0,0 +1,38 @@ +/* + * Copyright 2006 Richard Wilson <info@tinct.net> + * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * Cookies (interface). + */ + +#ifndef _NETSURF_RISCOS_COOKIES_H_ +#define _NETSURF_RISCOS_COOKIES_H_ + +#include "riscos/menus.h" + +void ro_gui_cookies_preinitialise(void); +void ro_gui_cookies_postinitialise(void); +void ro_gui_cookies_destroy(void); +bool ro_gui_cookies_check_window(wimp_w window); +bool ro_gui_cookies_check_menu(wimp_menu *menu); + +void ro_gui_cookies_open(void); + +#endif + diff --git a/frontends/riscos/dialog.c b/frontends/riscos/dialog.c new file mode 100644 index 000000000..d4356086d --- /dev/null +++ b/frontends/riscos/dialog.c @@ -0,0 +1,816 @@ +/* + * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net> + * Copyright 2005 James Bursa <bursa@users.sourceforge.net> + * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk> + * Copyright 2005 Richard Wilson <info@tinct.net> + * Copyright 2004 Andrew Timmins <atimmins@blueyonder.co.uk> + * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net> + * Copyright 2014 Stephen Fryatt <stevef@netsurf-browser.org> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "utils/config.h" + +#include <assert.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <oslib/colourtrans.h> +#include <oslib/osfile.h> +#include <oslib/osgbpb.h> +#include <oslib/osspriteop.h> +#include <oslib/wimp.h> + +#include "utils/nsoption.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/nsurl.h" +#include "desktop/version.h" +#include "desktop/browser.h" + +#include "riscos/configure.h" +#include "riscos/cookies.h" +#include "riscos/dialog.h" +#include "riscos/global_history.h" +#include "riscos/gui.h" +#include "riscos/hotlist.h" +#include "riscos/menus.h" +#include "riscos/save.h" +#include "riscos/sslcert.h" +#include "riscos/toolbar.h" +#include "riscos/url_complete.h" +#include "riscos/url_suggest.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" +#include "riscos/wimputils.h" + +#define ICON_ZOOM_VALUE 1 +#define ICON_ZOOM_DEC 2 +#define ICON_ZOOM_INC 3 +#define ICON_ZOOM_FRAMES 5 +#define ICON_ZOOM_CANCEL 7 +#define ICON_ZOOM_OK 8 + +/* The maximum number of persistent dialogues +*/ +#define MAX_PERSISTENT 64 + + +wimp_w dialog_info, dialog_saveas, + dialog_401li, + dialog_zoom, dialog_pageinfo, dialog_objinfo, dialog_tooltip, + dialog_warning, + dialog_folder, dialog_entry, dialog_search, dialog_print, + dialog_url_complete, dialog_openurl; + +struct gui_window *ro_gui_current_zoom_gui; + + +/* A simple mapping of parent and child +*/ +static struct { + wimp_w dialog; + wimp_w parent; +} persistent_dialog[MAX_PERSISTENT]; + + +static bool ro_gui_dialog_open_url_init(void); +static bool ro_gui_dialog_openurl_apply(wimp_w w); +static bool ro_gui_dialog_open_url_menu_prepare(wimp_w w, wimp_i i, + wimp_menu *menu, wimp_pointer *pointer); + +static bool ro_gui_dialog_zoom_apply(wimp_w w); + +/** + * Load and create dialogs from template file. + */ + +void ro_gui_dialog_init(void) +{ + /* warning dialog */ + dialog_warning = ro_gui_dialog_create("warning"); + ro_gui_wimp_event_register_ok(dialog_warning, ICON_WARNING_CONTINUE, + NULL); + ro_gui_wimp_event_set_help_prefix(dialog_warning, "HelpWarning"); + + /* tooltip for history */ + dialog_tooltip = ro_gui_dialog_create("tooltip"); + + /* configure window */ + ro_gui_configure_initialise(); + + /* 401 login window */ + ro_gui_401login_init(); + + /* theme installation */ + dialog_theme_install = ro_gui_dialog_create("theme_inst"); + ro_gui_wimp_event_register_cancel(dialog_theme_install, + ICON_THEME_INSTALL_CANCEL); + ro_gui_wimp_event_register_ok(dialog_theme_install, + ICON_THEME_INSTALL_INSTALL, + ro_gui_theme_install_apply); + ro_gui_wimp_event_set_help_prefix(dialog_theme_install, "HelpThemeInst"); + + /* search */ + ro_gui_search_init(); + + /* print */ + ro_gui_print_init(); + + /* about us */ + dialog_info = ro_gui_dialog_create("info"); + ro_gui_set_icon_string(dialog_info, 4, netsurf_version, true); + ro_gui_wimp_event_set_help_prefix(dialog_info, "HelpAppInfo"); + + /* page info */ + dialog_pageinfo = ro_gui_dialog_create("pageinfo"); + ro_gui_wimp_event_set_help_prefix(dialog_pageinfo, "HelpPageInfo"); + + /* object info */ + dialog_objinfo = ro_gui_dialog_create("objectinfo"); + ro_gui_wimp_event_set_help_prefix(dialog_objinfo, "HelpObjInfo"); + + /* save as */ + dialog_saveas = ro_gui_saveas_create("saveas"); + ro_gui_wimp_event_register_button(dialog_saveas, ICON_SAVE_ICON, + ro_gui_save_start_drag); + ro_gui_wimp_event_register_text_field(dialog_saveas, ICON_SAVE_PATH); + ro_gui_wimp_event_register_cancel(dialog_saveas, ICON_SAVE_CANCEL); + ro_gui_wimp_event_register_ok(dialog_saveas, ICON_SAVE_OK, + ro_gui_save_ok); + ro_gui_wimp_event_set_help_prefix(dialog_saveas, "HelpSaveAs"); + + /* url suggestion */ + dialog_url_complete = ro_gui_dialog_create("url_suggest"); + ro_gui_wimp_event_register_mouse_click(dialog_url_complete, + ro_gui_url_complete_click); + ro_gui_wimp_event_register_pointer_entering_window(dialog_url_complete, + ro_gui_url_complete_entering); + ro_gui_wimp_event_register_redraw_window(dialog_url_complete, + ro_gui_url_complete_redraw); + ro_gui_wimp_event_set_help_prefix(dialog_url_complete, "HelpAutoURL"); + + /* open URL */ + ro_gui_dialog_open_url_init(); + + /* scale view */ + dialog_zoom = ro_gui_dialog_create("zoom"); + ro_gui_wimp_event_register_numeric_field(dialog_zoom, ICON_ZOOM_VALUE, + ICON_ZOOM_INC, ICON_ZOOM_DEC, 10, 1600, 10, 0); + ro_gui_wimp_event_register_checkbox(dialog_zoom, ICON_ZOOM_FRAMES); + ro_gui_wimp_event_register_cancel(dialog_zoom, ICON_ZOOM_CANCEL); + ro_gui_wimp_event_register_ok(dialog_zoom, ICON_ZOOM_OK, + ro_gui_dialog_zoom_apply); + ro_gui_wimp_event_set_help_prefix(dialog_zoom, "HelpScaleView"); + + /* Treeview initialisation has moved to the end, to allow any + * associated dialogues to be set up first. + */ + + /* certificate verification window */ + ro_gui_cert_preinitialise(); + + /* hotlist window */ + ro_gui_hotlist_preinitialise(); + + /* global history window */ + ro_gui_global_history_preinitialise(); + + /* cookies window */ + ro_gui_cookies_preinitialise(); +} + + +/** + * Create a window from a template. + * + * \param template_name name of template to load + * \return window handle + * + * Exits through die() on error. + */ + +wimp_w ro_gui_dialog_create(const char *template_name) +{ + wimp_window *window; + wimp_w w; + os_error *error; + + window = ro_gui_dialog_load_template(template_name); + + /* create window */ + window->sprite_area = gui_sprites; + error = xwimp_create_window(window, &w); + if (error) { + LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess); + xwimp_close_template(); + die(error->errmess); + } + + /* the window definition is copied by the wimp and may be freed */ + free(window); + + return w; +} + + +/** + * Load a template without creating a window. + * + * \param template_name name of template to load + * \return window block + * + * Exits through die() on error. + */ + +wimp_window * ro_gui_dialog_load_template(const char *template_name) +{ + char name[20]; + int context, window_size, data_size; + char *data; + wimp_window *window; + os_error *error; + + /* Template names must be <= 11 chars long */ + assert(strlen(template_name) <= 11); + + /* wimp_load_template won't accept a const char * */ + strncpy(name, template_name, sizeof name); + + /* find required buffer sizes */ + error = xwimp_load_template(wimp_GET_SIZE, 0, 0, wimp_NO_FONTS, + name, 0, &window_size, &data_size, &context); + if (error) { + LOG("xwimp_load_template: 0x%x: %s", error->errnum, error->errmess); + xwimp_close_template(); + die(error->errmess); + } + if (!context) { + LOG("template '%s' missing", template_name); + xwimp_close_template(); + die("Template"); + } + + /* allocate space for indirected data and temporary window buffer */ + data = malloc(data_size); + window = malloc(window_size); + if (!data || !window) { + xwimp_close_template(); + die("NoMemory"); + } + + /* load template */ + error = xwimp_load_template(window, data, data + data_size, + wimp_NO_FONTS, name, 0, 0, 0, 0); + if (error) { + LOG("xwimp_load_template: 0x%x: %s", error->errnum, error->errmess); + xwimp_close_template(); + die(error->errmess); + } + + return window; +} + + +/** + * Open a dialog box, centred on the screen. + */ + +void ro_gui_dialog_open(wimp_w w) +{ + int screen_x, screen_y, dx, dy; + wimp_window_state state; + os_error *error; + + /* find screen centre in os units */ + ro_gui_screen_size(&screen_x, &screen_y); + screen_x /= 2; + screen_y /= 2; + + /* centre and open */ + state.w = w; + error = xwimp_get_window_state(&state); + if (error) { + LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + return; + } + dx = (state.visible.x1 - state.visible.x0) / 2; + dy = (state.visible.y1 - state.visible.y0) / 2; + state.visible.x0 = screen_x - dx; + state.visible.x1 = screen_x + dx; + state.visible.y0 = screen_y - dy; + state.visible.y1 = screen_y + dy; + state.next = wimp_TOP; + ro_gui_open_window_request(PTR_WIMP_OPEN(&state)); + + /* Set the caret position */ + ro_gui_set_caret_first(w); +} + + +/** + * Close a dialog box. + */ + +void ro_gui_dialog_close(wimp_w close) +{ + int i; + wimp_caret caret; + os_error *error; + + /* Check if we're a persistent window */ + for (i = 0; i < MAX_PERSISTENT; i++) { + if (persistent_dialog[i].dialog == close) { + /* We are => invalidate record */ + persistent_dialog[i].parent = NULL; + persistent_dialog[i].dialog = NULL; + break; + } + } + + /* Close any child windows */ + ro_gui_dialog_close_persistent(close); + + /* Give the caret back to the parent window. This code relies on + the fact that only tree windows and browser windows open + persistent dialogues, as the caret gets placed to no icon. + */ + error = xwimp_get_caret_position(&caret); + if (error) { + LOG("xwimp_get_caret_position: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } else if (caret.w == close) { + /* Check if we are a persistent window */ + if (i < MAX_PERSISTENT) { + error = xwimp_set_caret_position( + persistent_dialog[i].parent, + wimp_ICON_WINDOW, -100, -100, + 32, -1); + /* parent may have been closed first */ + if ((error) && (error->errnum != 0x287)) { + LOG("xwimp_set_caret_position: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + } + } + + error = xwimp_close_window(close); + if (error) { + LOG("xwimp_close_window: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } +} + + +/** + * Moves a window to the top of the stack. + * + * If the window is currently closed then: + * + * * The window is opened in the centre of the screen (at the supplied size) + * * Any toolbar editing session is stopped + * * The scroll position is set to the top of the window + * + * If the window is currently open then: + * + * * The window is brought to the top of the stack + * + * \param w the window to show + * \param toolbar the toolbar to consider + * \param width the window width if it is currently closed (or 0 to retain) + * \param height the window height if it is currently closed (or 0 to retain) + * \return true if the window was previously open + */ +bool ro_gui_dialog_open_top(wimp_w w, struct toolbar *toolbar, + int width, int height) { + os_error *error; + int screen_width, screen_height; + wimp_window_state state; + bool open; + + state.w = w; + error = xwimp_get_window_state(&state); + if (error) { + ro_warn_user("WimpError", error->errmess); + return false; + } + + /* if we're open we jump to the top of the stack, if not then we + * open in the centre of the screen. */ + open = state.flags & wimp_WINDOW_OPEN; + if (!open) { + int dimension; + int scroll_width; + /* cancel any editing */ + if (ro_toolbar_get_editing(toolbar)) + ro_toolbar_toggle_edit(toolbar); + + /* move to the centre */ + ro_gui_screen_size(&screen_width, &screen_height); + dimension = ((width == 0) ? + (state.visible.x1 - state.visible.x0) : width); + scroll_width = ro_get_vscroll_width(w); + state.visible.x0 = (screen_width - (dimension + scroll_width)) / 2; + state.visible.x1 = state.visible.x0 + dimension; + dimension = ((height == 0) ? + (state.visible.y1 - state.visible.y0) : height); + state.visible.y0 = (screen_height - dimension) / 2; + state.visible.y1 = state.visible.y0 + dimension; + state.xscroll = 0; + state.yscroll = 0; + if (toolbar) + state.yscroll = ro_toolbar_height(toolbar); + } + + /* open the window at the top of the stack */ + state.next = wimp_TOP; + ro_gui_open_window_request(PTR_WIMP_OPEN(&state)); + return open; +} + + +/** + * Open window at the location of the pointer. + */ + +void ro_gui_dialog_open_at_pointer(wimp_w w) +{ + wimp_pointer ptr; + os_error *error; + + /* get the pointer position */ + error = xwimp_get_pointer_info(&ptr); + if (error) { + LOG("xwimp_get_pointer_info: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + return; + } + + ro_gui_dialog_open_xy(w, ptr.pos.x - 64, ptr.pos.y); +} + + +/** + * Open window at a specified location. + */ + +void ro_gui_dialog_open_xy(wimp_w w, int x, int y) +{ + wimp_window_state state; + os_error *error; + int dx, dy; + + /* move the window */ + state.w = w; + error = xwimp_get_window_state(&state); + if (error) { + LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + return; + } + dx = (state.visible.x1 - state.visible.x0); + dy = (state.visible.y1 - state.visible.y0); + state.visible.x0 = x; + state.visible.x1 = x + dx; + state.visible.y0 = y - dy; + state.visible.y1 = y; + + /* if the window is already open, close it first so that it opens fully + * on screen */ + error = xwimp_close_window(w); + if (error) { + LOG("xwimp_close_window: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + return; + } + + /* open the window at the top of the stack */ + state.next = wimp_TOP; + ro_gui_open_window_request(PTR_WIMP_OPEN(&state)); +} + + +/** + * Opens a window at the centre of either another window or the screen + * + * /param parent the parent window (NULL for centre of screen) + * /param child the child window + */ +void ro_gui_dialog_open_centre_parent(wimp_w parent, wimp_w child) { + os_error *error; + wimp_window_state state; + int mid_x, mid_y; + int dimension, scroll_width; + + /* get the parent window state */ + if (parent) { + state.w = parent; + error = xwimp_get_window_state(&state); + if (error) { + LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + return; + } + scroll_width = ro_get_vscroll_width(parent); + mid_x = (state.visible.x0 + state.visible.x1 + scroll_width); + mid_y = (state.visible.y0 + state.visible.y1); + } else { + ro_gui_screen_size(&mid_x, &mid_y); + } + mid_x /= 2; + mid_y /= 2; + + /* get the child window state */ + state.w = child; + error = xwimp_get_window_state(&state); + if (error) { + LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + return; + } + + /* move to the centre of the parent at the top of the stack */ + dimension = state.visible.x1 - state.visible.x0; + scroll_width = ro_get_vscroll_width(history_window); + state.visible.x0 = mid_x - (dimension + scroll_width) / 2; + state.visible.x1 = state.visible.x0 + dimension; + dimension = state.visible.y1 - state.visible.y0; + state.visible.y0 = mid_y - dimension / 2; + state.visible.y1 = state.visible.y0 + dimension; + state.next = wimp_TOP; + ro_gui_open_window_request(PTR_WIMP_OPEN(&state)); +} + + +/** + * Open a persistent dialog box relative to the pointer. + * + * \param parent the owning window (NULL for no owner) + * \param w the dialog window + * \param pointer open the window at the pointer (centre of the parent + * otherwise) + */ + +void ro_gui_dialog_open_persistent(wimp_w parent, wimp_w w, bool pointer) { + + if (pointer) + ro_gui_dialog_open_at_pointer(w); + else + ro_gui_dialog_open_centre_parent(parent, w); + + /* todo: use wimp_event definitions rather than special cases */ + if ((w == dialog_pageinfo) || (w == dialog_objinfo)) + ro_gui_wimp_update_window_furniture(w, wimp_WINDOW_CLOSE_ICON, + wimp_WINDOW_CLOSE_ICON); + ro_gui_dialog_add_persistent(parent, w); + ro_gui_set_caret_first(w); +} + + +void ro_gui_dialog_add_persistent(wimp_w parent, wimp_w w) { + int i; + + /* all persistant windows have a back icon */ + ro_gui_wimp_update_window_furniture(w, wimp_WINDOW_BACK_ICON, + wimp_WINDOW_BACK_ICON); + + /* Add a mapping + */ + if ((parent == NULL) || (parent == wimp_ICON_BAR)) + return; + for (i = 0; i < MAX_PERSISTENT; i++) { + if (persistent_dialog[i].dialog == NULL || + persistent_dialog[i].dialog == w) { + persistent_dialog[i].dialog = w; + persistent_dialog[i].parent = parent; + return; + } + } + LOG("Unable to map persistent dialog to parent."); + return; +} + + +/** + * Close persistent dialogs associated with a window. + * + * \param parent the window to close children of + */ + +void ro_gui_dialog_close_persistent(wimp_w parent) { + int i; + wimp_w w; + + /* Check our mappings. + * + * The window handle is copied into w before proceeding, as + * ro_gui_dialog_close() will NULL persistent_dialog[i].dialog as + * part of the closing process. This would mean that the subsequent + * event dispatch would fail. (These events are logged to allow + * side effects to be investigated -- this code hasn't worked before). + */ + for (i = 0; i < MAX_PERSISTENT; i++) { + if (persistent_dialog[i].parent == parent && + persistent_dialog[i].dialog != NULL) { + w = persistent_dialog[i].dialog; + ro_gui_dialog_close(w); + if (ro_gui_wimp_event_close_window(w)) + LOG("Persistent dialog close event: 0x%x", (unsigned)w); + persistent_dialog[i].parent = NULL; + persistent_dialog[i].dialog = NULL; + } + } +} + + +/** + * Save the current options. + */ + +void ro_gui_save_options(void) +{ + nsoption_write("<NetSurf$ChoicesSave>", NULL, NULL); +} + +bool ro_gui_dialog_zoom_apply(wimp_w w) { + unsigned int scale; + bool all; + + scale = atoi(ro_gui_get_icon_string(w, ICON_ZOOM_VALUE)); + all = ro_gui_get_icon_selected_state(w, ICON_ZOOM_FRAMES); + ro_gui_window_set_scale(ro_gui_current_zoom_gui, scale * 0.01); + return true; +} + + +/** + * Prepares the Scale view dialog. + */ + +void ro_gui_dialog_prepare_zoom(struct gui_window *g) +{ + char scale_buffer[8]; + sprintf(scale_buffer, "%.0f", browser_window_get_scale(g->bw) * 100); + ro_gui_set_icon_string(dialog_zoom, ICON_ZOOM_VALUE, scale_buffer, true); + ro_gui_set_icon_selected_state(dialog_zoom, ICON_ZOOM_FRAMES, true); + ro_gui_set_icon_shaded_state(dialog_zoom, ICON_ZOOM_FRAMES, true); + ro_gui_current_zoom_gui = g; + ro_gui_wimp_event_memorise(dialog_zoom); +} + +/** + * Update the Scale View dialog to reflect the current window settings + * + * \param g the gui_window to update for + */ +void ro_gui_dialog_update_zoom(struct gui_window *g) { + if (g == ro_gui_current_zoom_gui) + ro_gui_dialog_prepare_zoom(g); +} + + +/** + * Create the Open URL dialogue, allocating storage for the URL field icon + * as we go. + * + * \return true on success; false on failure (although errors with + * the templates or memory allocation will exit via die()). + */ + +static bool ro_gui_dialog_open_url_init(void) +{ + wimp_window *definition; + char *buffer; + os_error *error; + + definition = ro_gui_dialog_load_template("open_url"); + + /* _load_template() should die on any error, so we trust its data. */ + + assert(definition != NULL); + + /* Create the dialogue, with modifications. */ + + if ((definition->icons[ICON_OPENURL_URL].flags & wimp_ICON_INDIRECTED) + == 0) { + LOG("open_url URL icon not indirected"); + xwimp_close_template(); + die("Template"); + } + + buffer = malloc(RO_GUI_MAX_URL_SIZE); + if (buffer == NULL) { + xwimp_close_template(); + die("NoMemory"); + } + + definition->icons[ICON_OPENURL_URL].data.indirected_text.text = buffer; + definition->icons[ICON_OPENURL_URL].data.indirected_text.size = + RO_GUI_MAX_URL_SIZE; + definition->sprite_area = gui_sprites; + + error = xwimp_create_window(definition, &dialog_openurl); + if (error != NULL) { + LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess); + xwimp_close_template(); + die(error->errmess); + } + + free(definition); + + ro_gui_wimp_event_register_menu_gright(dialog_openurl, ICON_OPENURL_URL, + ICON_OPENURL_MENU, ro_gui_url_suggest_menu); + ro_gui_wimp_event_register_cancel(dialog_openurl, ICON_OPENURL_CANCEL); + ro_gui_wimp_event_register_ok(dialog_openurl, ICON_OPENURL_OPEN, + ro_gui_dialog_openurl_apply); + ro_gui_wimp_event_register_menu_prepare(dialog_openurl, + ro_gui_dialog_open_url_menu_prepare); + ro_gui_wimp_event_set_help_prefix(dialog_openurl, "HelpOpenURL"); + + return true; +} + + + +bool ro_gui_dialog_openurl_apply(wimp_w w) { + const char *urltxt; + char *url2; + nsurl *url; + nserror error; + + urltxt = ro_gui_get_icon_string(w, ICON_OPENURL_URL); + url2 = strdup(urltxt); /** @todo why is this copied */ + if (url2 == NULL) { + return false; + } + + error = nsurl_create(url2, &url); + free(url2); + if (error == NSERROR_OK) { + error = browser_window_create(BW_CREATE_HISTORY, + url, + NULL, + NULL, + NULL); + nsurl_unref(url); + } + if (error != NSERROR_OK) { + ro_warn_user(messages_get_errorcode(error), 0); + return false; + } + + return true; + +} + + +/** + * Prepares the Open URL dialog. + */ + +void ro_gui_dialog_prepare_open_url(void) +{ + ro_gui_set_icon_string(dialog_openurl, ICON_OPENURL_URL, "", true); + ro_gui_set_icon_shaded_state(dialog_openurl, + ICON_OPENURL_MENU, !ro_gui_url_suggest_prepare_menu()); + ro_gui_wimp_event_memorise(dialog_openurl); +} + + +/** + * Callback to prepare menus in the Open URL dialog. At present, this + * only has to handle the URL Suggestion pop-up. + * + * \param w The window handle owning the menu. + * \param i The icon handle owning the menu. + * \param *menu The menu to be prepared. + * \param *pointer The associated mouse click event block, or NULL + * on an Adjust-click re-opening. + * \return true if the event was handled; false if not. + */ + +bool ro_gui_dialog_open_url_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer) +{ + if (menu != ro_gui_url_suggest_menu || i != ICON_OPENURL_MENU) + return false; + + if (pointer != NULL) + return ro_gui_url_suggest_prepare_menu(); + + return true; +} diff --git a/frontends/riscos/dialog.h b/frontends/riscos/dialog.h new file mode 100644 index 000000000..463048436 --- /dev/null +++ b/frontends/riscos/dialog.h @@ -0,0 +1,55 @@ +/* + * Copyright 2005 Richard Wilson <info@tinct.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _NETSURF_RISCOS_DIALOG_H_ +#define _NETSURF_RISCOS_DIALOG_H_ + +struct toolbar; +struct gui_window; + +void ro_gui_dialog_init(void); +wimp_w ro_gui_dialog_create(const char *template_name); +wimp_window * ro_gui_dialog_load_template(const char *template_name); + +void ro_gui_dialog_open(wimp_w w); +void ro_gui_dialog_close(wimp_w close); + +bool ro_gui_dialog_open_top(wimp_w w, struct toolbar *toolbar, + int width, int height); +void ro_gui_dialog_open_at_pointer(wimp_w w); +void ro_gui_dialog_open_xy(wimp_w, int x, int y); +void ro_gui_dialog_open_centre_parent(wimp_w parent, wimp_w w); + +void ro_gui_dialog_open_persistent(wimp_w parent, wimp_w w, bool pointer); +void ro_gui_dialog_add_persistent(wimp_w parent, wimp_w w); +void ro_gui_dialog_close_persistent(wimp_w parent); + + + + +void ro_gui_dialog_click(wimp_pointer *pointer); +void ro_gui_dialog_prepare_zoom(struct gui_window *g); +void ro_gui_dialog_update_zoom(struct gui_window *g); +void ro_gui_dialog_prepare_open_url(void); +void ro_gui_save_options(void); +void ro_gui_dialog_open_config(void); +void ro_gui_dialog_proxyauth_menu_selection(int item); +void ro_gui_dialog_image_menu_selection(int item); +void ro_gui_dialog_languages_menu_selection(const char *lang); +void ro_gui_dialog_font_menu_selection(int item); +#endif diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/!Boot,feb b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Boot,feb new file mode 100644 index 000000000..485bd521d --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Boot,feb @@ -0,0 +1,17 @@ +If (("<Cache$AppDir>" = "") OR ("<Cache$ForceVars>" = "1")) Then Set Cache$AppDir <Obey$Dir> + +IconSprites <Cache$AppDir>.!Sprites + +| Find and set up resource paths +WimpSlot -min 64k -max 64k +Run <Cache$AppDir>.Resources.ResFind CacheApp +If (("<Cache$Meta>" = "") OR ("<Cache$ForceVars>" = "1")) Then Set Cache$Meta CacheAppRes:!Meta + +| Work out where the cache directory should be -- use Choices$User if set or Default, otherwise. +Set Cache$Suffix "<Choices$User>" +If "<Cache$Suffix>" = "" Then Set Cache$Suffix "Default" +If (("<Cache$Dir>" = "") OR ("<Cache$ForceVars>" = "1")) Then Set Cache$Dir "<Cache$AppDir>.Caches.<Cache$Suffix>" +Unset Cache$Suffix + +| Ensure cache directory exists (sadly, unavoidable) +CDir <Cache$Dir> diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/!Help,feb b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Help,feb new file mode 100644 index 000000000..35eeeb31b --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Help,feb @@ -0,0 +1,2 @@ +If "<CacheAppRes$Path>" = "" Then Run <Cache$AppDir>.Resources.ResFind CacheApp +Filer_Run CacheAppRes:Help
\ No newline at end of file diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/!Run,feb b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Run,feb new file mode 100644 index 000000000..8aead9733 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Run,feb @@ -0,0 +1,9 @@ +Set Cache$ForceVars 1 +Run <Obey$Dir>.!Boot +Unset Cache$ForceVars + +RMEnsure SysLog 0.17 IfThere <SysLog$Dir>.!Run Then Run <SysLog$Dir>.!Run +RMEnsure SysLog 0.17 Set Cache$SysLogMissing "True" + +Wimpslot -min 128k -max 128k +Run <Cache$AppDir>.!RunImage diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/!RunImage,ffb b/frontends/riscos/distribution/!Boot/Resources/!Cache/!RunImage,ffb Binary files differnew file mode 100644 index 000000000..61752af99 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/!RunImage,ffb diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites,ff9 Binary files differnew file mode 100644 index 000000000..b71a51cf3 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites,ff9 diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites22,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites22,ff9 Binary files differnew file mode 100644 index 000000000..e43f88c89 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites22,ff9 diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/Caches/Blank b/frontends/riscos/distribution/!Boot/Resources/!Cache/Caches/Blank new file mode 100644 index 000000000..898dc5872 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/Caches/Blank @@ -0,0 +1 @@ +This is here just to stop the directory structure getting lost when unzipping.
\ No newline at end of file diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/MultiError,ffb b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/MultiError,ffb Binary files differnew file mode 100644 index 000000000..ec348b0e9 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/MultiError,ffb diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/ResFind,ffb b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/ResFind,ffb Binary files differnew file mode 100644 index 000000000..7766cc928 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/ResFind,ffb diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/!Meta b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/!Meta new file mode 100644 index 000000000..2de40bd7c --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/!Meta @@ -0,0 +1,9 @@ +# Meta file for Cache +Help:<CacheAppRes$Dir>.Help +Version:1.13 +Web:http://www.snowstone.org.uk/riscos/ +Title:Cache +Publisher:Adam Richardson +Description:Cache provides a central location for semi-permanent data on your system. +Email:riscos@snowstone.org.uk + diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Help b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Help new file mode 100644 index 000000000..aad9bf0b1 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Help @@ -0,0 +1,60 @@ +Cache +----- + +Cache provides a shared location for cached data. This location can be +used by application authors to store semi-permanent data. Cache can be +placed anywhere on your computer where it will be "seen" by the Filer +during start up. (For instance, the "Resources" directory inside !Boot.) + +Once "seen" it will set up a cache location, which can be shown by +double-clicking on !Cache. + + +Application Authors +----------- ------- + +Use Cache in a similar way to using Scrap. You *must not* assume that +Cache is present on the user's system however, as Cache is not an +official part of the system (like Scrap). + +To use Cache you should: + * Check for the presence of "<Cache$Dir>" before proceeding + * Read from and write data to "<Cache$Dir>.APPNAME" where APPNAME has + been allocated to you by the allocations service. See: + http://www.riscosopen.com/content/allocate + * If the APPNAME directory does not exist, you should create it. + +This version of Cache is published by Adam Richardson who can be +contacted at riscos@snowstone.org.uk. + +The website for Cache is: http://www.snowstone.org.uk/riscos/ + + +Credits +------- + +Cache is (c) Adam Richardson, 2007. +Thanks to Rob Kendrick for the initial idea and input. + + +License +------- + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Messages b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Messages new file mode 100644 index 000000000..366122292 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Messages @@ -0,0 +1,8 @@ +# Messages for Cache + +multiuser:Multi-user system present. +singleuser:No multi-user system present. +location:Cache directory set to: +opendir:Opening cache location... +fatalerror:Cache has suffered a fatal error and has quit. + diff --git a/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Templates,fec b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Templates,fec Binary files differnew file mode 100644 index 000000000..22f910ad9 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Templates,fec diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Boot,feb b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Boot,feb new file mode 100644 index 000000000..7c0c46241 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Boot,feb @@ -0,0 +1,5 @@ +| Unicode Boot file +| +Set Unicode$Dir <Obey$Dir> +SetMacro Unicode$Path <Unicode$Dir>.,Resources:$.Resources.Unicode. +IconSprites Unicode:!Sprites diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Help b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Help new file mode 100644 index 000000000..8c0488185 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Help @@ -0,0 +1 @@ +This application contains resources for Unicode support in applications. diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Run,feb b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Run,feb new file mode 100644 index 000000000..bd70e96ac --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Run,feb @@ -0,0 +1,5 @@ +| Unicode Run file +| +Set Unicode$Dir <Obey$Dir> +SetMacro Unicode$Path <Unicode$Dir>.,Resources:$.Resources.Unicode. +IconSprites Unicode:!Sprites diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites,ff9 Binary files differnew file mode 100644 index 000000000..3eb5b44b7 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites,ff9 diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites11,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites11,ff9 Binary files differnew file mode 100644 index 000000000..48986b41e --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites11,ff9 diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites22,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites22,ff9 Binary files differnew file mode 100644 index 000000000..63a6e6122 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites22,ff9 diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Acorn/Latin1 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Acorn/Latin1 Binary files differnew file mode 100644 index 000000000..bdf5d3b67 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Acorn/Latin1 diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/CentEuro b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/CentEuro Binary files differnew file mode 100644 index 000000000..5ab69ff2e --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/CentEuro diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Cyrillic b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Cyrillic Binary files differnew file mode 100644 index 000000000..670fd6cdc --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Cyrillic diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Roman b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Roman Binary files differnew file mode 100644 index 000000000..254579e2c --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Roman diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Ukrainian b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Ukrainian Binary files differnew file mode 100644 index 000000000..a220587ba --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Ukrainian diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/BigFive b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/BigFive Binary files differnew file mode 100644 index 000000000..c659cef19 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/BigFive diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C0/40[ISO646] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C0/40[ISO646] Binary files differnew file mode 100644 index 000000000..cd92b5486 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C0/40[ISO646] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C1/43[IS6429] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C1/43[IS6429] Binary files differnew file mode 100644 index 000000000..74002a168 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C1/43[IS6429] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/40[646old] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/40[646old] Binary files differnew file mode 100644 index 000000000..00e2d1096 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/40[646old] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/41[646-GB] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/41[646-GB] Binary files differnew file mode 100644 index 000000000..c293f93d6 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/41[646-GB] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/42[646IRV] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/42[646IRV] Binary files differnew file mode 100644 index 000000000..e0b4bcadb --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/42[646IRV] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/43[FinSwe] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/43[FinSwe] Binary files differnew file mode 100644 index 000000000..7d4646905 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/43[FinSwe] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/47[646-SE] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/47[646-SE] Binary files differnew file mode 100644 index 000000000..a6b091a22 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/47[646-SE] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/48[646-SE] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/48[646-SE] Binary files differnew file mode 100644 index 000000000..9bd24ab29 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/48[646-SE] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/49[JS201K] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/49[JS201K] new file mode 100644 index 000000000..20ce8d498 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/49[JS201K] @@ -0,0 +1 @@ +aÿbÿcÿdÿeÿfÿgÿhÿiÿjÿkÿlÿmÿnÿoÿpÿqÿrÿsÿtÿuÿvÿwÿxÿyÿzÿ{ÿ|ÿ}ÿ~ÿÿ€ÿÿ‚ÿƒÿ„ÿ…ÿ†ÿ‡ÿˆÿ‰ÿŠÿ‹ÿŒÿÿŽÿÿÿ‘ÿ’ÿ“ÿ”ÿ•ÿ–ÿ—ÿ˜ÿ™ÿšÿ›ÿœÿÿžÿŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
\ No newline at end of file diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4A[JS201R] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4A[JS201R] Binary files differnew file mode 100644 index 000000000..21d2a479b --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4A[JS201R] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4B[646-DE] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4B[646-DE] Binary files differnew file mode 100644 index 000000000..a2e284e1b --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4B[646-DE] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4C[646-PT] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4C[646-PT] Binary files differnew file mode 100644 index 000000000..e076e2517 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4C[646-PT] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/54[GB1988] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/54[GB1988] Binary files differnew file mode 100644 index 000000000..3b43719ce --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/54[GB1988] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/56[Teltxt] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/56[Teltxt] Binary files differnew file mode 100644 index 000000000..73ce49e17 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/56[Teltxt] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/59[646-IT] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/59[646-IT] Binary files differnew file mode 100644 index 000000000..f1ae81962 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/59[646-IT] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/5A[646-ES] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/5A[646-ES] Binary files differnew file mode 100644 index 000000000..674fc2d70 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/5A[646-ES] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/60[646-NO] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/60[646-NO] Binary files differnew file mode 100644 index 000000000..fc92892ee --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/60[646-NO] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/66[646-FR] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/66[646-FR] Binary files differnew file mode 100644 index 000000000..8dd604679 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/66[646-FR] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/69[646-HU] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/69[646-HU] Binary files differnew file mode 100644 index 000000000..65300b2c5 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/69[646-HU] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6B[Arabic] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6B[Arabic] Binary files differnew file mode 100644 index 000000000..c47689914 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6B[Arabic] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6C[IS6937] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6C[IS6937] Binary files differnew file mode 100644 index 000000000..93453f5de --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6C[IS6937] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/7A[SerbCr] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/7A[SerbCr] Binary files differnew file mode 100644 index 000000000..9740e784e --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/7A[SerbCr] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/40[JS6226] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/40[JS6226] Binary files differnew file mode 100644 index 000000000..a677dfc3d --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/40[JS6226] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/41[GB2312] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/41[GB2312] Binary files differnew file mode 100644 index 000000000..679608ad2 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/41[GB2312] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/42[JIS208] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/42[JIS208] Binary files differnew file mode 100644 index 000000000..532b1f4f3 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/42[JIS208] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/43[KS1001] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/43[KS1001] Binary files differnew file mode 100644 index 000000000..36186c864 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/43[KS1001] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/44[JIS212] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/44[JIS212] Binary files differnew file mode 100644 index 000000000..f5343a30e --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/44[JIS212] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/47[CNS1] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/47[CNS1] Binary files differnew file mode 100644 index 000000000..da07f45d3 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/47[CNS1] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/48[CNS2] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/48[CNS2] Binary files differnew file mode 100644 index 000000000..44ee24c91 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/48[CNS2] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/49[CNS3] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/49[CNS3] Binary files differnew file mode 100644 index 000000000..a8464e5aa --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/49[CNS3] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4A[CNS4] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4A[CNS4] Binary files differnew file mode 100644 index 000000000..a8f3e3270 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4A[CNS4] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4B[CNS5] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4B[CNS5] Binary files differnew file mode 100644 index 000000000..535b0f4b5 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4B[CNS5] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4C[CNS6] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4C[CNS6] Binary files differnew file mode 100644 index 000000000..7bfb2b1d4 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4C[CNS6] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4D[CNS7] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4D[CNS7] new file mode 100644 index 000000000..be14c7279 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4D[CNS7] @@ -0,0 +1,2 @@ +ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿö5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿUVÿÿÿÿÿÿÿÿÿÿÿÿg6ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿaÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿE:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉ;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿU=ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿè>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¶?ÿÿÿÿÿÿ½?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖ@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿqAÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ˜BÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿzGÿÿÿÿÿÿÿÿÿÿÿÿ¸GÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿHÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ/Iÿÿÿÿÿÿÿÿÿÿ1IÿÿÿÿÿÿÿÿÿÿÿÿÿÿœIÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæIÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ8Kÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ:Lÿÿÿÿ±LÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGMÿÿQMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ£8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ×qÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿš>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÂ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜ@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³Aÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿf†ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙEÿÿÝEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿIÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ=“ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¨IÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÊJÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿKÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀLÿÿÿÿÿÿÿÿÿÿÿÿÊLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ%MÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿJMÿÿSMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ6ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ>ÿÿÿÿÿÿÿÿÿÿÿÿ#>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿCÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ]EÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿZFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ…GÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿIÿÿÿÿÿÿÿÿÿÿÿÿ9Iÿÿÿÿÿÿ7IÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿkJÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍJÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ{6ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõdÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ';ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏ?ÿÿÿÿÿÿÍ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚AÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRBÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿQDÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿZEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿeFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯HÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿAIÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ)Jÿÿÿÿÿÿÿÿÿÿÿÿÿÿ*Jÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–JÿÿÿÿÿÿÿÿÿÿÿÿKÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~6áXÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ Cÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé|ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿeEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿdGÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ#HÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙ•ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¹4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿK<ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñ@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿgFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‰HÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿLÿÿÿÿÿÿLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿmLÿÿpLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿgÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿZ>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯BÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿkEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿcIÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€J„JJÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñJÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGšÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¨4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‹Aÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ+CÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿzEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ FÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿmFÿÿÿÿÿÿÿÿÿÿGÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿjIlIÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²KÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿLÿÿÿÿÿÿ-LÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿEMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ +FÿÿÿÿÿÿÿÿFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ.HÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ1Cÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¼K»KÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ6ÿÿÿÿÿÿÿÿÿÿr7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿtvÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìKÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿyBÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
\ No newline at end of file diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/41[Lat1] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/41[Lat1] Binary files differnew file mode 100644 index 000000000..97e6b1106 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/41[Lat1] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/42[Lat2] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/42[Lat2] Binary files differnew file mode 100644 index 000000000..b753c40fe --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/42[Lat2] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/43[Lat3] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/43[Lat3] Binary files differnew file mode 100644 index 000000000..88d477886 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/43[Lat3] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/44[Lat4] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/44[Lat4] Binary files differnew file mode 100644 index 000000000..a40662d45 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/44[Lat4] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/46[Greek] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/46[Greek] Binary files differnew file mode 100644 index 000000000..c42397388 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/46[Greek] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/47[Arabic] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/47[Arabic] Binary files differnew file mode 100644 index 000000000..4507f467a --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/47[Arabic] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/48[Hebrew] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/48[Hebrew] Binary files differnew file mode 100644 index 000000000..70f39cca6 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/48[Hebrew] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4C[Cyrill] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4C[Cyrill] Binary files differnew file mode 100644 index 000000000..8ff0115e4 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4C[Cyrill] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4D[Lat5] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4D[Lat5] Binary files differnew file mode 100644 index 000000000..6381e607e --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4D[Lat5] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/50[LatSup] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/50[LatSup] Binary files differnew file mode 100644 index 000000000..a320c7fe8 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/50[LatSup] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/52[IS6937] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/52[IS6937] Binary files differnew file mode 100644 index 000000000..dff6ccba4 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/52[IS6937] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/54[Thai] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/54[Thai] Binary files differnew file mode 100644 index 000000000..d74377759 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/54[Thai] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/56[Lat6] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/56[Lat6] Binary files differnew file mode 100644 index 000000000..4e3e4f313 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/56[Lat6] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/58[L6Sami] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/58[L6Sami] Binary files differnew file mode 100644 index 000000000..4dfd9188c --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/58[L6Sami] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/59[Lat7] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/59[Lat7] Binary files differnew file mode 100644 index 000000000..256a88e76 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/59[Lat7] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5C[Welsh] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5C[Welsh] Binary files differnew file mode 100644 index 000000000..b5e00509f --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5C[Welsh] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5D[Sami] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5D[Sami] Binary files differnew file mode 100644 index 000000000..15734c036 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5D[Sami] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5E[Hebrew] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5E[Hebrew] Binary files differnew file mode 100644 index 000000000..a6593b071 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5E[Hebrew] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5F[Lat8] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5F[Lat8] Binary files differnew file mode 100644 index 000000000..c15713e82 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5F[Lat8] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/62[Lat9] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/62[Lat9] Binary files differnew file mode 100644 index 000000000..5bf449d58 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/62[Lat9] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/66[Lat10] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/66[Lat10] Binary files differnew file mode 100644 index 000000000..e8ba925d3 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/66[Lat10] diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/KOI8-R b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/KOI8-R Binary files differnew file mode 100644 index 000000000..8063cd4bc --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/KOI8-R diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1250 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1250 Binary files differnew file mode 100644 index 000000000..7a0d35ceb --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1250 diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1251 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1251 Binary files differnew file mode 100644 index 000000000..3d6009cab --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1251 diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1252 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1252 Binary files differnew file mode 100644 index 000000000..6d3bf293d --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1252 diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1253 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1253 Binary files differnew file mode 100644 index 000000000..50a48be13 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1253 diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1254 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1254 Binary files differnew file mode 100644 index 000000000..45ecfe907 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1254 diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1256 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1256 Binary files differnew file mode 100644 index 000000000..7fc95a92f --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1256 diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP866 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP866 Binary files differnew file mode 100644 index 000000000..cd214d24b --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP866 diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP874 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP874 Binary files differnew file mode 100644 index 000000000..26a6fc8c3 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP874 diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP932 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP932 Binary files differnew file mode 100644 index 000000000..2c0c111f9 --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP932 diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Files/Aliases b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Files/Aliases new file mode 100644 index 000000000..8978ede4c --- /dev/null +++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Files/Aliases @@ -0,0 +1,303 @@ +# > Unicode:Files.Aliases +# Mapping of character set encoding names to their canonical form +# +# Lines starting with a '#' are comments, blank lines are ignored. +# +# Based on http://www.iana.org/assignments/character-sets and +# http://www.iana.org/assignments/ianacharset-mib +# +# Canonical Form MIBenum Aliases... +# +US-ASCII 3 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII ISO646-US ANSI_X3.4-1968 us IBM367 cp367 csASCII +ISO-10646-UTF-1 27 csISO10646UTF1 +ISO_646.basic:1983 28 ref csISO646basic1983 +INVARIANT 29 csINVARIANT +ISO_646.irv:1983 30 iso-ir-2 irv csISO2IntlRefVersion +BS_4730 20 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom +NATS-SEFI 31 iso-ir-8-1 csNATSSEFI +NATS-SEFI-ADD 32 iso-ir-8-2 csNATSSEFIADD +NATS-DANO 33 iso-ir-9-1 csNATSDANO +NATS-DANO-ADD 34 iso-ir-9-2 csNATSDANOADD +SEN_850200_B 35 iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish +SEN_850200_C 21 iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames +KS_C_5601-1987 36 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 +ISO-2022-KR 37 csISO2022KR +EUC-KR 38 csEUCKR EUCKR +ISO-2022-JP 39 csISO2022JP +ISO-2022-JP-2 40 csISO2022JP2 +ISO-2022-CN 104 +ISO-2022-CN-EXT 105 +JIS_C6220-1969-jp 41 JIS_C6220-1969 iso-ir-13 katakana x0201-7 csISO13JISC6220jp +JIS_C6220-1969-ro 42 iso-ir-14 jp ISO646-JP csISO14JISC6220ro +IT 22 iso-ir-15 ISO646-IT csISO15Italian +PT 43 iso-ir-16 ISO646-PT csISO16Portuguese +ES 23 iso-ir-17 ISO646-ES csISO17Spanish +greek7-old 44 iso-ir-18 csISO18Greek7Old +latin-greek 45 iso-ir-19 csISO19LatinGreek +DIN_66003 24 iso-ir-21 de ISO646-DE csISO21German +NF_Z_62-010_(1973) 46 iso-ir-25 ISO646-FR1 csISO25French +Latin-greek-1 47 iso-ir-27 csISO27LatinGreek1 +ISO_5427 48 iso-ir-37 csISO5427Cyrillic +JIS_C6226-1978 49 iso-ir-42 csISO42JISC62261978 +BS_viewdata 50 iso-ir-47 csISO47BSViewdata +INIS 51 iso-ir-49 csISO49INIS +INIS-8 52 iso-ir-50 csISO50INIS8 +INIS-cyrillic 53 iso-ir-51 csISO51INISCyrillic +ISO_5427:1981 54 iso-ir-54 ISO5427Cyrillic1981 +ISO_5428:1980 55 iso-ir-55 csISO5428Greek +GB_1988-80 56 iso-ir-57 cn ISO646-CN csISO57GB1988 +GB_2312-80 57 iso-ir-58 chinese csISO58GB231280 +NS_4551-1 25 iso-ir-60 ISO646-NO no csISO60DanishNorwegian csISO60Norwegian1 +NS_4551-2 58 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 +NF_Z_62-010 26 iso-ir-69 ISO646-FR fr csISO69French +videotex-suppl 59 iso-ir-70 csISO70VideotexSupp1 +PT2 60 iso-ir-84 ISO646-PT2 csISO84Portuguese2 +ES2 61 iso-ir-85 ISO646-ES2 csISO85Spanish2 +MSZ_7795.3 62 iso-ir-86 ISO646-HU hu csISO86Hungarian +JIS_C6226-1983 63 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 +greek7 64 iso-ir-88 csISO88Greek7 +ASMO_449 65 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 +iso-ir-90 66 csISO90 +JIS_C6229-1984-a 67 iso-ir-91 jp-ocr-a csISO91JISC62291984a +JIS_C6229-1984-b 68 iso-ir-92 ISO646-JP-OCR-B jp-ocr-b csISO92JISC62991984b +JIS_C6229-1984-b-add 69 iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd +JIS_C6229-1984-hand 70 iso-ir-94 jp-ocr-hand csISO94JIS62291984hand +JIS_C6229-1984-hand-add 71 iso-ir-95 jp-ocr-hand-add csISO95JIS62291984handadd +JIS_C6229-1984-kana 72 iso-ir-96 csISO96JISC62291984kana +ISO_2033-1983 73 iso-ir-98 e13b csISO2033 +ANSI_X3.110-1983 74 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS +ISO-8859-1 4 iso-ir-100 ISO_8859-1 ISO_8859-1:1987 latin1 l1 IBM819 CP819 csISOLatin1 8859_1 ISO8859-1 +ISO-8859-2 5 iso-ir-101 ISO_8859-2 ISO_8859-2:1987 latin2 l2 csISOLatin2 8859_2 ISO8859-2 +T.61-7bit 75 iso-ir-102 csISO102T617bit +T.61-8bit 76 T.61 iso-ir-103 csISO103T618bit +ISO-8859-3 6 iso-ir-109 ISO_8859-3 ISO_8859-3:1988 latin3 l3 csISOLatin3 8859_3 ISO8859-3 +ISO-8859-4 7 iso-ir-110 ISO_8859-4 ISO_8859-4:1988 latin4 l4 csISOLatin4 8859_4 ISO8859-4 +ECMA-cyrillic 77 iso-ir-111 KOI8-E csISO111ECMACyrillic +CSA_Z243.4-1985-1 78 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 +CSA_Z243.4-1985-2 79 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 +CSA_Z243.4-1985-gr 80 iso-ir-123 csISO123CSAZ24341985gr +ISO-8859-6 9 iso-ir-127 ISO_8859-6 ISO_8859-6:1987 ECMA-114 ASMO-708 arabic csISOLatinArabic +ISO-8859-6-E 81 csISO88596E ISO_8859-6-E +ISO-8859-6-I 82 csISO88596I ISO_8859-6-I +ISO-8859-7 10 iso-ir-126 ISO_8859-7 ISO_8859-7:1987 ELOT_928 ECMA-118 greek greek8 csISOLatinGreek 8859_7 ISO8859-7 +T.101-G2 83 iso-ir-128 csISO128T101G2 +ISO-8859-8 11 iso-ir-138 ISO_8859-8 ISO_8859-8:1988 hebrew csISOLatinHebrew 8859_8 ISO8859-8 +ISO-8859-8-E 84 csISO88598E ISO_8859-8-E +ISO-8859-8-I 85 csISO88598I ISO_8859-8-I +CSN_369103 86 iso-ir-139 csISO139CSN369103 +JUS_I.B1.002 87 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 +ISO_6937-2-add 14 iso-ir-142 csISOTextComm +IEC_P27-1 88 iso-ir-143 csISO143IECP271 +ISO-8859-5 8 iso-ir-144 ISO_8859-5 ISO_8859-5:1988 cyrillic csISOLatinCyrillic 8859_5 ISO8859-5 +JUS_I.B1.003-serb 89 iso-ir-146 serbian csISO146Serbian +JUS_I.B1.003-mac 90 macedonian iso-ir-147 csISO147Macedonian +ISO-8859-9 12 iso-ir-148 ISO_8859-9 ISO_8859-9:1989 latin5 l5 csISOLatin5 8859_9 ISO8859-9 +greek-ccitt 91 iso-ir-150 csISO150 csISO150GreekCCITT +NC_NC00-10:81 92 cuba iso-ir-151 ISO646-CU csISO151Cuba +ISO_6937-2-25 93 iso-ir-152 csISO6937Add +GOST_19768-74 94 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 +ISO_8859-supp 95 iso-ir-154 latin1-2-5 csISO8859Supp +ISO_10367-box 96 iso-ir-155 csISO10367Box +ISO-8859-10 13 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 8859_10 ISO8859-10 +latin-lap 97 lap iso-ir-158 csISO158Lap +JIS_X0212-1990 98 x0212 iso-ir-159 csISO159JISX02121990 +DS_2089 99 DS2089 ISO646-DK dk csISO646Danish +us-dk 100 csUSDK +dk-us 101 csDKUS +JIS_X0201 15 X0201 csHalfWidthKatakana +KSC5636 102 ISO646-KR csKSC5636 +ISO-10646-UCS-2 1000 csUnicode UCS-2 UCS2 +ISO-10646-UCS-4 1001 csUCS4 UCS-4 UCS4 +DEC-MCS 2008 dec csDECMCS +hp-roman8 2004 roman8 r8 csHPRoman8 +macintosh 2027 mac csMacintosh MACROMAN MAC-ROMAN X-MAC-ROMAN +IBM037 2028 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl csIBM037 +IBM038 2029 EBCDIC-INT cp038 csIBM038 +IBM273 2030 CP273 csIBM273 +IBM274 2031 EBCDIC-BE CP274 csIBM274 +IBM275 2032 EBCDIC-BR cp275 csIBM275 +IBM277 2033 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 +IBM278 2034 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 +IBM280 2035 CP280 ebcdic-cp-it csIBM280 +IBM281 2036 EBCDIC-JP-E cp281 csIBM281 +IBM284 2037 CP284 ebcdic-cp-es csIBM284 +IBM285 2038 CP285 ebcdic-cp-gb csIBM285 +IBM290 2039 cp290 EBCDIC-JP-kana csIBM290 +IBM297 2040 cp297 ebcdic-cp-fr csIBM297 +IBM420 2041 cp420 ebcdic-cp-ar1 csIBM420 +IBM423 2042 cp423 ebcdic-cp-gr csIBM423 +IBM424 2043 cp424 ebcdic-cp-he csIBM424 +IBM437 2011 cp437 437 csPC8CodePage437 +IBM500 2044 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 +IBM775 2087 cp775 csPC775Baltic +IBM850 2009 cp850 850 csPC850Multilingual +IBM851 2045 cp851 851 csIBM851 +IBM852 2010 cp852 852 csPCp852 +IBM855 2046 cp855 855 csIBM855 +IBM857 2047 cp857 857 csIBM857 +IBM860 2048 cp860 860 csIBM860 +IBM861 2049 cp861 861 cp-is csIBM861 +IBM862 2013 cp862 862 csPC862LatinHebrew +IBM863 2050 cp863 863 csIBM863 +IBM864 2051 cp864 csIBM864 +IBM865 2052 cp865 865 csIBM865 +IBM866 2086 cp866 866 csIBM866 +IBM868 2053 CP868 cp-ar csIBM868 +IBM869 2054 cp869 869 cp-gr csIBM869 +IBM870 2055 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 +IBM871 2056 CP871 ebcdic-cp-is csIBM871 +IBM880 2057 cp880 EBCDIC-Cyrillic csIBM880 +IBM891 2058 cp891 csIBM891 +IBM903 2059 cp903 csIBM903 +IBM904 2060 cp904 904 csIBBM904 +IBM905 2061 CP905 ebcdic-cp-tr csIBM905 +IBM918 2062 CP918 ebcdic-cp-ar2 csIBM918 +IBM1026 2063 CP1026 csIBM1026 +EBCDIC-AT-DE 2064 csIBMEBCDICATDE +EBCDIC-AT-DE-A 2065 csEBCDICATDEA +EBCDIC-CA-FR 2066 csEBCDICCAFR +EBCDIC-DK-NO 2067 csEBCDICDKNO +EBCDIC-DK-NO-A 2068 csEBCDICDKNOA +EBCDIC-FI-SE 2069 csEBCDICFISE +EBCDIC-FI-SE-A 2070 csEBCDICFISEA +EBCDIC-FR 2071 csEBCDICFR +EBCDIC-IT 2072 csEBCDICIT +EBCDIC-PT 2073 csEBCDICPT +EBCDIC-ES 2074 csEBCDICES +EBCDIC-ES-A 2075 csEBCDICESA +EBCDIC-ES-S 2076 csEBCDICESS +EBCDIC-UK 2077 csEBCDICUK +EBCDIC-US 2078 csEBCDICUS +UNKNOWN-8BIT 2079 csUnknown8BiT +MNEMONIC 2080 csMnemonic +MNEM 2081 csMnem +VISCII 2082 csVISCII +VIQR 2083 csVIQR +KOI8-R 2084 csKOI8R +KOI8-U 2088 +IBM00858 2089 CCSID00858 CP00858 PC-Multilingual-850+euro +IBM00924 2090 CCSID00924 CP00924 ebcdic-Latin9--euro +IBM01140 2091 CCSID01140 CP01140 ebcdic-us-37+euro +IBM01141 2092 CCSID01141 CP01141 ebcdic-de-273+euro +IBM01142 2093 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro +IBM01143 2094 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro +IBM01144 2095 CCSID01144 CP01144 ebcdic-it-280+euro +IBM01145 2096 CCSID01145 CP01145 ebcdic-es-284+euro +IBM01146 2097 CCSID01146 CP01146 ebcdic-gb-285+euro +IBM01147 2098 CCSID01147 CP01147 ebcdic-fr-297+euro +IBM01148 2099 CCSID01148 CP01148 ebcdic-international-500+euro +IBM01149 2100 CCSID01149 CP01149 ebcdic-is-871+euro +Big5-HKSCS 2101 +IBM1047 2102 IBM-1047 +PTCP154 2103 csPTCP154 PT154 CP154 Cyrillic-Asian +Amiga-1251 2104 Ami1251 Amiga1251 Ami-1251 +KOI7-switched 2105 +UNICODE-1-1 1010 csUnicode11 +SCSU 1011 +UTF-7 1012 +UTF-16BE 1013 +UTF-16LE 1014 +UTF-16 1015 +CESU-8 1016 csCESU-8 +UTF-32 1017 +UTF-32BE 1018 +UTF-32LE 1019 +BOCU-1 1020 csBOCU-1 +UNICODE-1-1-UTF-7 103 csUnicode11UTF7 +UTF-8 106 UNICODE-1-1-UTF-8 UNICODE-2-0-UTF-8 utf8 +ISO-8859-13 109 8859_13 ISO8859-13 +ISO-8859-14 110 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic l8 8859_14 ISO8859-14 +ISO-8859-15 111 ISO_8859-15 Latin-9 8859_15 ISO8859-15 +ISO-8859-16 112 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 +GBK 113 CP936 MS936 windows-936 +GB18030 114 +OSD_EBCDIC_DF04_15 115 +OSD_EBCDIC_DF03_IRV 116 +OSD_EBCDIC_DF04_1 117 +JIS_Encoding 16 csJISEncoding +Shift_JIS 17 MS_Kanji csShiftJIS X-SJIS Shift-JIS +EUC-JP 18 csEUCPkdFmtJapanese Extended_UNIX_Code_Packed_Format_for_Japanese EUCJP +Extended_UNIX_Code_Fixed_Width_for_Japanese 19 csEUCFixWidJapanese +ISO-10646-UCS-Basic 1002 csUnicodeASCII +ISO-10646-Unicode-Latin1 1003 csUnicodeLatin1 ISO-10646 +ISO-Unicode-IBM-1261 1005 csUnicodeIBM1261 +ISO-Unicode-IBM-1268 1006 csUnicodeIBM1268 +ISO-Unicode-IBM-1276 1007 csUnicodeIBM1276 +ISO-Unicode-IBM-1264 1008 csUnicodeIBM1264 +ISO-Unicode-IBM-1265 1009 csUnicodeIBM1265 +ISO-8859-1-Windows-3.0-Latin-1 2000 csWindows30Latin1 +ISO-8859-1-Windows-3.1-Latin-1 2001 csWindows31Latin1 +ISO-8859-2-Windows-Latin-2 2002 csWindows31Latin2 +ISO-8859-9-Windows-Latin-5 2003 csWindows31Latin5 +Adobe-Standard-Encoding 2005 csAdobeStandardEncoding +Ventura-US 2006 csVenturaUS +Ventura-International 2007 csVenturaInternational +PC8-Danish-Norwegian 2012 csPC8DanishNorwegian +PC8-Turkish 2014 csPC8Turkish +IBM-Symbols 2015 csIBMSymbols +IBM-Thai 2016 csIBMThai +HP-Legal 2017 csHPLegal +HP-Pi-font 2018 csHPPiFont +HP-Math8 2019 csHPMath8 +Adobe-Symbol-Encoding 2020 csHPPSMath +HP-DeskTop 2021 csHPDesktop +Ventura-Math 2022 csVenturaMath +Microsoft-Publishing 2023 csMicrosoftPublishing +Windows-31J 2024 csWindows31J +GB2312 2025 csGB2312 EUC-CN EUCCN CN-GB +Big5 2026 csBig5 BIG-FIVE BIG-5 CN-BIG5 BIG_FIVE x-x-big5 +windows-1250 2250 CP1250 MS-EE +windows-1251 2251 CP1251 MS-CYRL +windows-1252 2252 CP1252 MS-ANSI +windows-1253 2253 CP1253 MS-GREEK +windows-1254 2254 CP1254 MS-TURK +windows-1255 2255 +windows-1256 2256 CP1256 MS-ARAB +windows-1257 2257 CP1257 WINBALTRIM +windows-1258 2258 +TIS-620 2259 +HZ-GB-2312 2085 + +# Additional encodings not defined by IANA + +# Arbitrary allocations +#CP737 3001 +#CP853 3002 +#CP856 3003 +CP874 3004 WINDOWS-874 +#CP922 3005 +#CP1046 3006 +#CP1124 3007 +#CP1125 3008 WINDOWS-1125 +#CP1129 3009 +#CP1133 3010 IBM-CP1133 +#CP1161 3011 IBM-1161 IBM1161 CSIBM1161 +#CP1162 3012 IBM-1162 IBM1162 CSIBM1162 +#CP1163 3013 IBM-1163 IBM1163 CSIBM1163 +#GEORGIAN-ACADEMY 3014 +#GEORGIAN-PS 3015 +#KOI8-RU 3016 +#KOI8-T 3017 +#MACARABIC 3018 X-MAC-ARABIC MAC-ARABIC +#MACCROATIAN 3019 X-MAC-CROATIAN MAC-CROATIAN +#MACGREEK 3020 X-MAC-GREEK MAC-GREEK +#MACHEBREW 3021 X-MAC-HEBREW MAC-HEBREW +#MACICELAND 3022 X-MAC-ICELAND MAC-ICELAND +#MACROMANIA 3023 X-MAC-ROMANIA MAC-ROMANIA +#MACTHAI 3024 X-MAC-THAI MAC-THAI +#MACTURKISH 3025 X-MAC-TURKISH MAC-TURKISH +#MULELAO-1 3026 +CP949 3027 WINDOWS-949 + +# From Unicode Lib +ISO-IR-182 4000 +ISO-IR-197 4002 +ISO-2022-JP-1 4008 +MACCYRILLIC 4009 X-MAC-CYRILLIC MAC-CYRILLIC +MACUKRAINE 4010 X-MAC-UKRAINIAN MAC-UKRAINIAN +MACCENTRALEUROPE 4011 X-MAC-CENTRALEURROMAN MAC-CENTRALEURROMAN +JOHAB 4012 +ISO-8859-11 4014 iso-ir-166 ISO_8859-11 ISO8859-11 8859_11 +X-CURRENT 4999 X-SYSTEM +X-ACORN-LATIN1 5001 +X-ACORN-FUZZY 5002 diff --git a/frontends/riscos/distribution/!System/310/Modules/CryptRand,ffa b/frontends/riscos/distribution/!System/310/Modules/CryptRand,ffa Binary files differnew file mode 100644 index 000000000..f403843b3 --- /dev/null +++ b/frontends/riscos/distribution/!System/310/Modules/CryptRand,ffa diff --git a/frontends/riscos/distribution/!System/310/Modules/Iconv,ffa b/frontends/riscos/distribution/!System/310/Modules/Iconv,ffa Binary files differnew file mode 100644 index 000000000..8a9cc3adb --- /dev/null +++ b/frontends/riscos/distribution/!System/310/Modules/Iconv,ffa diff --git a/frontends/riscos/distribution/!System/310/Modules/Network/URI,ffa b/frontends/riscos/distribution/!System/310/Modules/Network/URI,ffa Binary files differnew file mode 100644 index 000000000..431535e21 --- /dev/null +++ b/frontends/riscos/distribution/!System/310/Modules/Network/URI,ffa diff --git a/frontends/riscos/distribution/!System/310/Modules/SharedULib,ffa b/frontends/riscos/distribution/!System/310/Modules/SharedULib,ffa Binary files differnew file mode 100755 index 000000000..8dd0dd2c9 --- /dev/null +++ b/frontends/riscos/distribution/!System/310/Modules/SharedULib,ffa diff --git a/frontends/riscos/distribution/!System/310/Modules/Tinct,ffa b/frontends/riscos/distribution/!System/310/Modules/Tinct,ffa Binary files differnew file mode 100644 index 000000000..b8fda27b8 --- /dev/null +++ b/frontends/riscos/distribution/!System/310/Modules/Tinct,ffa diff --git a/frontends/riscos/distribution/3rdParty/AcornURI/!ReadMe b/frontends/riscos/distribution/3rdParty/AcornURI/!ReadMe new file mode 100644 index 000000000..4f4ca1e24 --- /dev/null +++ b/frontends/riscos/distribution/3rdParty/AcornURI/!ReadMe @@ -0,0 +1,34 @@ +AcornURI 1.04 +------------- + +Hi. This is a complete reimplementation of Acorn's URI module such that it +works on Iyonix. This allows simple URI / URL launching from applications. +Merge this !System with your own, then (re)launch your favourite browser to +ensure it's running. + +This has a few advantages over the official offering: it's smaller, +compatible with more browsers and more tolerant of errors. + +This is released under the terms of the LGPL, which is included in this +archive as the file Copying. Previous versions of this module were released +under the GPL, and are still available from sudden.recoil.org. + +Source is available from the same place you downloaded this archive, ie +<http://sudden.recoil.org/others/acornuri/acornuri104src.zip> + + +Changelog +--------- + +v1.04 20-May-06 Relicensed under the LGPL (rather than GPL) + +v1.03 11-May-04 Changed the order of things to try, so it now + always prefers browsers which are already loaded + +v1.02 19-Feb-04 Fixed claiming of URIs where I'd misread the spec + Added automatic fall-back to the ANT protocol + Removed some service calls to improve reliability + +-- +Christian Ludlam +chris@recoil.org
\ No newline at end of file diff --git a/frontends/riscos/distribution/3rdParty/AcornURI/Copying b/frontends/riscos/distribution/3rdParty/AcornURI/Copying new file mode 100644 index 000000000..5ab7695ab --- /dev/null +++ b/frontends/riscos/distribution/3rdParty/AcornURI/Copying @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/frontends/riscos/distribution/3rdParty/CryptRand/Copyright b/frontends/riscos/distribution/3rdParty/CryptRand/Copyright new file mode 100644 index 000000000..abb4a9b80 --- /dev/null +++ b/frontends/riscos/distribution/3rdParty/CryptRand/Copyright @@ -0,0 +1,46 @@ +CryptRandom + +Upstream sources were downloaded and built by +the GCCSDK Autobuilder. + +For information on the autobuilder see the URL: + +http://www.riscos.info/index.php/GCCSDK#GCCSDK_Autobuilder + +The source used for this build can be found at + +http://www.riscos.info/packages/src/System + +Upstream source fetched by CVS with + +CVS root theom@chiark.greenend.org.uk:/u3/theom/cvs-pub +Module cryptrandom +Upstream source fetched using SVN from + + +# For AOF builds needing another branch (if this is not defined AB_SVN is + +Copyright +--------- + +Copyright 2000-11 Theo Markettos <theo@markettos.org.uk> +Portions copyright Simon Tatham, Gary S. Brown and Eric Young + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including without +limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +SIMON TATHAM OR THEO MARKETTOS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/frontends/riscos/distribution/3rdParty/Iconv/ReadMe b/frontends/riscos/distribution/3rdParty/Iconv/ReadMe new file mode 100644 index 000000000..907c2c7c8 --- /dev/null +++ b/frontends/riscos/distribution/3rdParty/Iconv/ReadMe @@ -0,0 +1,45 @@ +What is Iconv? +============== + +Iconv is a module which provides character set conversion akin to that provided +by the C iconv() function. + +Iconv Installation instructions +=============================== + +To install the Iconv module, simply use the System merge utility provided by +Configure to merge the !System directory provided with the one on your system. + +Use the Boot merge facility in Configure to merge the provided !Boot directory +with the one on your system. If there is no !Boot merge facility provided on +your system, simply drag the !Boot directory over your existing boot structure. + +Further documentation can be found in the "doc" directory. + +Note for developers: +~~~~~~~~~~~~~~~~~~~~ +The "stubs" directory contains source for a set of C stubs. +See the ReadMe file in that directory for further information. + +Licence +======= + +Iconv is Copyright © 2004-13 J-M Bell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/frontends/riscos/distribution/3rdParty/Iconv/doc/API b/frontends/riscos/distribution/3rdParty/Iconv/doc/API new file mode 100644 index 000000000..13fa22fce --- /dev/null +++ b/frontends/riscos/distribution/3rdParty/Iconv/doc/API @@ -0,0 +1,132 @@ +Iconv Module API +================ + +If using C, then you really should be using the libiconv stubs provided +(or UnixLib, if appropriate). See the iconv.h header file for further +documentation of these calls. + +Iconv_Open (&57540) +------------------- + + Create a conversion descriptor + + On Entry: r0 -> string containing name of destination encoding (eg "UTF-8") + r1 -> string containing name of source encoding (eg "CP1252") + + On Exit: r0 = conversion descriptor + All others preserved + + Either encoding name may have a number of parameters appended to them. + Parameters are separated by a pair of forward-slashes ("//"). + Currently defined parameters are: + + Parameter: Destination: Source: + + TRANSLIT Transliterate unrepresentable None + output. + + The conversion descriptor is an opaque value. The user should not, + therefore, assume anything about its meaning, nor modify it in any way. + Doing so is guaranteed to result in undefined behaviour. + + +Iconv_Iconv (&57541) +-------------------- + + This SWI is deprecated and Iconv_Convert should be used instead. + + +Iconv_Close (&57542) +-------------------- + + Destroy a conversion descriptor + + On Entry: r0 = conversion descriptor to destroy + + On Exit: r0 = 0 + All others preserved + + +Iconv_Convert (&57543) +--------------------- + + Convert a byte sequence to another encoding + + On Entry: r0 = conversion descriptor returned by Iconv_Open + r1 -> input buffer (or NULL to reset encoding context) + r2 = length of buffer pointed to by r1 + r3 -> output buffer + r4 = length of buffer pointed to by r3 + + On Exit: r0 = number of non-reversible conversions performed (always 0) + r1 -> updated input buffer pointer (after last input read) + r2 = number of bytes remaining in input buffer + r3 -> updated output buffer pointer (i.e. end of output) + r4 = number of free bytes in the output buffer + All others preserved + + Note that all strings should be NUL-terminated so, if calling from BASIC, + some terminating character munging may be needed. + + +Errors: + +Should an error occur, the SWI will return with V set and r0 -> error buffer. +Note that only the error number will be filled in and may be one of: + + ICONV_NOMEM (&81b900) + ICONV_INVAL (&81b901) + ICONV_2BIG (&81b902) + ICONV_ILSEQ (&81b903) + +These map directly to the corresponding C errno values. + + +Iconv_CreateMenu (&57544) +------------------------- + + Create a menu data structure containing all available encodings. + + On Entry: r0 = flags. All bits reserved, must be 0 + r1 -> buffer, or 0 to read required length + r2 = length of buffer in r1 + r3 -> currently selected encoding name, or 0 if none selected + r4 -> buffer for indirected data, or 0 to read length + r5 = length of buffer in r4 + + On Exit: r2 = required size of buffer in r1 if r1 = 0 on entry, + or length of data placed in buffer + r5 = required size of buffer in r4 if r4 = 0 on entry, + or length of data placed in buffer + + Menu titles are direct form text buffers. Menu entries are indirect text. + Entry text is stored in the buffer pointed to by R4 on entry to this call. + + +Iconv_DecodeMenu (&57545) +------------------------- + + Decode a selection in a menu generated by Iconv_CreateMenu. + Places the corresponding encoding name in the result buffer. + + On Entry: r0 = flags. All bits reserved, must be 0 + r1 -> menu definition + r2 -> menu selections, as per Wimp_Poll + r3 -> buffer for result or 0 to read required length + r4 = buffer length + + On Exit: r4 = required size of buffer if r3 = 0 on entry, + or length of data placed in buffer (0 if no selected + encoding) + + The menu selections block pointed to by r2 on entry should be based at + the root of the encodings menu structure (i.e. index 0 in the block + should correspond to the selection in the main encoding menu). + + This call will update the selection status of the menu(s) appropriately. + + +Example Code: +============= + +Example code may be found in the IconvEg BASIC file. diff --git a/frontends/riscos/distribution/3rdParty/Iconv/doc/ChangeLog b/frontends/riscos/distribution/3rdParty/Iconv/doc/ChangeLog new file mode 100644 index 000000000..3a22a45fa --- /dev/null +++ b/frontends/riscos/distribution/3rdParty/Iconv/doc/ChangeLog @@ -0,0 +1,114 @@ +Iconv Changelog +=============== + +0.01 10-Sep-2004 +---------------- + + - Initial version - unreleased. + +0.02 27-Sep-2004 +---------------- + + - Use allocated SWI & error chunks. + - Fix issues in 8bit encoding handling. + - First public release. + +0.03 22-Jan-2005 +---------------- + + - Add Iconv_Convert SWI with improved interface. + - Deprecate Iconv_Iconv SWI. + - Add encoding name alias handling. + - Bundle !Unicode resource. + +0.04 08-Apr-2005 +---------------- + + - Improve parameter checking. + - Fix potential memory leaks. + - Add encoding menu creation and selection handling. + +0.05 27-Jun-2005 +---------------- + + - Improve encoding alias support, using external data file. + - Add StubsG build for A9home users. + +0.06 05-Nov-2005 +---------------- + + - Modified menu creation API to store indirected text in a + user-provided buffer. This change is backwards incompatible. + +0.07 11-Feb-2006 +---------------- + + - Corrected output values for E2BIG errors. + - Fixed input pointer update after successful conversion. + +0.08 11-Mar-2007 +---------------- + + - Tightened up parameter checking in various places. + - Improve aliases hash function. + - Make 8bit write function's return values match encoding_write + with encoding_WRITE_STRICT set. + - Fix bug in 8bit writing which resulted in the remaining buffer + size being reduced even if nothing was written. + - Improve support for endian-specific Unicode variants. + - Work around issue in UnicodeLib where remaining buffer size is + reduced if an attempt is made to write an unrepresentable character. + - Add rudimentary //TRANSLIT support - simply replaces with '?' for now. + - Make UnicodeLib handle raw ISO-8859-{1,2,9,10,15} and not attempt + ISO-6937-2-25 shift sequences. + - Remove StubsG build as A9home now has a C99 capable C library. + - Overhaul documentation. + +0.09 20-Nov-2008 +---------------- + + - Restructured source tree into cross-platform and RO-specific parts. + - New build system to go with this. + - Fixes for compiling with GCC4. + - Introduce *Iconv command which performs command line conversion. + - Fixes/improvements to the handlers for: + + US-ASCII + + UTF-8 + + ISO-8859-7 + + ISO-8859-8 + + ISO-8859-11 + + Windows-1256 + + MacRoman + + JIS X 0208 + + JIS X 0212 + + KS X 1001 + + EUC-JP + + Any ISO-2022 based charset that uses a 94x94 table in GR + + Johab + + ShiftJIS + - Add support for ISO-8859-16 (Latin 10) + - Significantly improve detection and reporting of error conditions + +0.10 29-Nov-2008 +---------------- + + - Fixes to the *Iconv command parameter parsing + - Ensure *Iconv outputs all converted data when the input is invalid + - Fix handling of illegal UTF-8 byte sequences + - Fix handling of incomplete multibyte input sequences. + +0.11 04-Jan-2011 +---------------- + + - Detect missing mapping file when using 8bit codecs. This prevents spurious + memory exhaustion errors. + - Toolchain used to build 0.10 turns out to have produced broken code. + - Minor additions to the charset alias mapping file. + +0.12 20-Jan-2013 +--------------- + + - Master alias mapping file now lives in ROOL repository. + - Correct handling of trailing valid shift sequences. Previously would + erroneously report EINVAL, instead of silently accepting them. + - Add proper transliteration behaviour when requested using //TRANSLIT. diff --git a/frontends/riscos/distribution/3rdParty/Iconv/doc/Uni-iconv b/frontends/riscos/distribution/3rdParty/Iconv/doc/Uni-iconv new file mode 100644 index 000000000..caea2d0f1 --- /dev/null +++ b/frontends/riscos/distribution/3rdParty/Iconv/doc/Uni-iconv @@ -0,0 +1,204 @@ +Introduction: +============= + +This file documents an approximate correlation between the data files +provided in the !Unicode distribution and the encoding headers in GNU +libiconv 1.9.1. + +Those with '?' in the iconv column either are not represented in iconv +or I've missed the relevant header file ;) + +A number of encodings are present in the iconv distribution but not +in !Unicode. These are documented at the end of this file. + +Changelog: +========== + +v 0.01 (09-Sep-2004) +~~~~~~~~~~~~~~~~~~~~ +Initial Incarnation + +v 0.02 (11-Sep-2004) +~~~~~~~~~~~~~~~~~~~~ +Documented additional encodings supported by the Iconv module. +Corrected list of !Unicode deficiencies. + + +!Unicode->iconv: +================ + +Unicode: iconv: notes: + +Acorn.Latin1 riscos1.h + +Apple.CentEuro mac_centraleurope.h +Apple.Cyrillic mac_cyrillic.h +Apple.Roman mac_roman.h +Apple.Ukrainian mac_ukraine.h + +BigFive big5.h + +ISO2022.C0.40[ISO646] ? + +ISO2022.C1.43[IS6429] ? + +ISO2022.G94.40[646old] iso646_cn.h +ISO2022.G94.41[646-GB] ? +ISO2022.G94.42[646IRV] ? +ISO2022.G94.43[FinSwe] ? +ISO2022.G94.47[646-SE] ? +ISO2022.G94.48[646-SE] ? +ISO2022.G94.49[JS201K] jisx0201.h top of JIS range +ISO2022.G94.4A[JS201R] jisx0201.h iso646_jp.h bottom of JIS range +ISO2022.G94.4B[646-DE] ? +ISO2022.G94.4C[646-PT] ? +ISO2022.G94.54[GB1988] ? +ISO2022.G94.56[Teltxt] ? +ISO2022.G94.59[646-IT] ? +ISO2022.G94.5A[646-ES] ? +ISO2022.G94.60[646-NO] ? +ISO2022.G94.66[646-FR] ? +ISO2022.G94.69[646-HU] ? +ISO2022.G94.6B[Arabic] ? +ISO2022.G94.6C[IS6397] ? +ISO2022.G94.7A[SerbCr] ? + +ISO2022.G94x94.40[JS6226] ? +ISO2022.G94x94.41[GB2312] gb2312.h +ISO2022.G94x94.42[JIS208] jis0x208.h +ISO2022.G94x94.43[KS1001] ksc5601.h +ISO2022.G94x94.44[JIS212] jis0x212.h +ISO2022.G94x94.47[CNS1] cns11643_1.h the tables differ +ISO2022.G94x94.48[CNS2] cns11643_2.h +ISO2022.G94x94.49[CNS3] cns11643_3.h +ISO2022.G94x94.4A[CNS4] cns11643_4.h +ISO2022.G94x94.4B[CNS5] cns11643_5.h +ISO2022.G94x94.4C[CNS6] cns11643_6.h +ISO2022.G94x94.4D[CNS7] cns11643_7.h + +ISO2022.G96.41[Lat1] iso8859_1.h +ISO2022.G96.42[Lat2] iso8859_2.h +ISO2022.G96.43[Lat3] iso8859_3.h +ISO2022.G96.44[Lat4] iso8859_4.h +ISO2022.G96.46[Greek] ? +ISO2022.G96.47[Arabic] iso8859_6.h ISO-8859-6 ignored +ISO2022.G96.48[Hebrew] ? +ISO2022.G96.4C[Cyrill] ? +ISO2022.G96.4D[Lat5] iso8859_5.h +ISO2022.G96.50[LatSup] ? +ISO2022.G96.52[IS6397] ? +ISO2022.G96.54[Thai] tis620.h +ISO2022.G96.56[Lat6] iso8859_6.h +ISO2022.G96.58[L6Sami] ? +ISO2022.G96.59[Lat7] iso8859_7.h +ISO2022.G96.5C[Welsh] ? +ISO2022.G96.5D[Sami] ? +ISO2022.G96.5E[Hebrew] ? +ISO2022.G96.5F[Lat8] iso8859_8.h +ISO2022.G96.62[Lat9] iso8859_9.h + +KOI8-R koi8_r.h + +Microsoft.CP1250 cp1250.h +Microsoft.CP1251 cp1251.h +Microsoft.CP1252 cp1252.h +Microsoft.CP1254 cp1254.h +Microsoft.CP866 cp866.h +Microsoft.CP932 cp932.h cp932ext.h + +iconv->!Unicode: +================ + +Iconv has the following encodings, which are not present in !Unicode. +Providing a suitable data file for !Unicode is trivial. Whether UnicodeLib +will then act upon the addition of these is unknown. +This list is ordered as per libiconv's NOTES file. + +European & Semitic languages: + + ISO-8859-16 (iso8859_16.h) + KOI8-{U,RU,T} (koi8_xx.h) + CP125{3,5,6,7} (cp125n.h) + CP850 (cp850.h) + CP862 (cp862.h) + Mac{Croatian,Romania,Greek,Turkish,Hebrew,Arabic} (mac_foo.h) + +Japanese: + + None afaikt. + +Simplified Chinese: + + GB18030 (gb18030.h, gb18030ext.h) + HZ-GB-2312 (hz.h) + +Traditional Chinese: + + CP950 (cp950.h) + BIG5-HKSCS (big5hkscs.h) + +Korean: + + CP949 (cp949.h) + +Armenian: + + ARMSCII-8 (armscii_8.h) + +Georgian: + + Georgian-Academy, Georgian-PS (georgian_academy.h, georgian_ps.h) + +Thai: + + CP874 (cp874.h) + MacThai (mac_thai.h) + +Laotian: + + MuleLao-1, CP1133 (mulelao.h, cp1133.h) + +Vietnamese: + + VISCII, TCVN (viscii.h, tcvn.h) + CP1258 (cp1258.h) + +Unicode: + + BE/LE variants of normal encodings. I assume UnicodeLib handles + these, but can't be sure. + C99 / JAVA - well, yes. + + +Iconv Module: +============= + +The iconv module is effectively a thin veneer around UnicodeLib. However, +8bit encodings are implemented within the module rather than using the +support in UnicodeLib. The rationale for this is simply that, although +UnicodeLib will understand (and act upon - reportedly...) additions to +the ISO2022 Unicode resource, other encodings are ignored. As the vast +majority of outstanding encodings fall into this category, and the code +is fairly simple, it made sense to implement it within the module. + +With use of the iconv module, the list of outstanding encodings is +reduced to: + + CP1255 (requires state-based transcoding) + + GB18030 (not 8bit - reportedly a requirement of PRC) + HZ-GB-2312 (not 8bit - supported by IE4) + + CP950 (not 8bit - a (MS) variant of Big5) + BIG5-HKSCS (not 8bit - again, a Big5 variant) + + CP949 (not 8bit) + + ARMSCII-8 (easily implemented, if required) + + VISCII (easily implemented, if required) + CP1258, TCVN (requires state-based transcoding) + +Additionally, the rest of the CodePage encodings implemented in iconv +but not listed above (due to omissions from the iconv documentation) +are implemented by the iconv module. diff --git a/frontends/riscos/distribution/3rdParty/SharedULib/Copyright b/frontends/riscos/distribution/3rdParty/SharedULib/Copyright new file mode 100644 index 000000000..b6784ed06 --- /dev/null +++ b/frontends/riscos/distribution/3rdParty/SharedULib/Copyright @@ -0,0 +1,761 @@ +UnixLib Copyright +----------------- + +UnixLib is Copyright (c) 1995-1999 Simon Callan, Nick Burrett, +Nicholas Clark and Peter Burwood. + +These contributors have expressed "no interest" in any further licensing or +copyright in regards to UnixLib. + +Other sections are (c) 1999-2006 Nick Burrett, John Tytgat, Peter Naulls, +Peter Teichmann, Alex Waugh, Christian Ludlam, Theo Markettos, Graham Shaw, +James Bursa and John-Mark Bell. + +In January 2005, permission was obtained from all relevant contributors +by Peter Naulls to license all past and present contributions to UnixLib +(where possible) under the revised BSD license. The license is included +in the next section and is applicable to all code in UnixLib that does not +have an explicit license in its source. + +Prior to 4th January 2005 and after May 2001, UnixLib contained code licensed +under the GNU General Public License, and versions of UnixLib produced +between these dates are subject to the provisions of the GPL. We realised +that this might cause potential problems with the wider use of UnixLib in +RISC OS, and along with the desire to clarify the overall licensing status of +UnixLib, GPL code was removed from UnixLib and the above permission from all +copyright holders allowed UnixLib contributions to be relicensed as per the +revised BSD license. The GPL is therefore not included in this notice +as it is no longer relevant to UnixLib. + + +Practical notes on using UnixLib in your own programs: + +This is a plain English version of guidelines for use of UnixLib in +your programs. It does not override any of the licenses included +below, but is intended to state instances when it may be used in +free and non-free software. Where there is contradiction or +ambiguity in this wording, please refer to the specifics of the licence +in question. These recommendations are based upon our understading +of the GPL/LGPL and BSD licenses and are subject to change should +our understanding of the topics improve. + + - Because UnixLib contains code that is subject to the Lesser GNU + Public License, the LGPL is the overriding consideration when + linking UnixLib to programs (unless the program itself is GPL). + + - You are free to use sections of UnixLib in your own programs + subject to the conditions of that code. If the entirety of + that code is under a BSD license, then you can generally use + that code as you see fit, and there is no further obligation + from you as long as the copyright notice remains. If you + use LGPL code in your program, then your program must also be + distributed under the LGPL (or GPL). + + - If you use UnixLib in its intended original form - that is as a + supporting library for ported programs to RISC OS - then your program + is subject to the LGPL; or the GPL if the program is covered by that. + Note that you must make the source and any modifications available to for + both if requested. This is of course equally true if you write an original + GPL program using UnixLib. In most cases, no additional action is + required of you, especially since source is usually readibly available. + + - If you use UnixLib for a non-free program - whether that's commercial or + otherwise, then you should carefully read section 6 of the LGPL. This + applies, because at the present time, there is no practical method of + dynamic linking on RISC OS. At such time that UnixLib is available as a + shared library, then programs dynamically linking to it will no longer be + subject to the LPGL as applied to UnixLib. + + - Section 6 means that in practice, you must supply, or offer to + supply either source or object code for your program. + This is mainly to allow rebuilding of the executable program + with later or modified versions of UnixLib. You must of course + supply (or better, contribute to the GCCSDK project) any + modifications you make to UnixLib upon request. + + +Recommended reading: + +Frequently Asked Questions about the GNU GPL +http://www.fsf.org/licenses/gpl-faq.html (has some sections on LGPL) + +About the justifications for using LGPL +http://www.fsf.org/licenses/why-not-lgpl.html + + + +=========================================================================== + + Copyright (c) 1995-2005 UnixLib Developers + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=========================================================================== + +Portions of UnixLib are copyright The Regents of the University of +California. + +Portions of this library are copyright Sun Microsystems, Inc. The + +Portions of this library are derived from the GNU C Library and fall under +the GNU Library General Public License. + +Portions of this library are copyright Henry Spencer. + +Portions of this library are copyright The Regents of the University of +California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState +Corporation and other parties. + +Portions of this library are copyright PostgreSQL Global Development Group. + +The licenses for the above are duplicated below. + + +=========================================================================== + + Copyright (c) The Regents of the University of California. + All rights reserved. + + This code is derived from software contributed to Berkeley by + Chris Torek. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by the University of + California, Berkeley and its contributors. + 4. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +=========================================================================== + + Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + + Developed at SunPro, a Sun Microsystems, Inc. business. + Permission to use, copy, modify, and distribute this + software is freely granted, provided that this notice + is preserved. + +=========================================================================== + + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + +=========================================================================== + +Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. + +Development of this software was funded, in part, by Cray Research Inc., +UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics +Corporation, none of whom are responsible for the results. The author +thanks all of them. + +Redistribution and use in source and binary forms -- with or without +modification -- are permitted for any purpose, provided that +redistributions in source form retain this entire copyright notice and +indicate the origin and nature of any modifications. + +I'd appreciate being given credit for this package in the documentation +of software which uses it, but that is not a requirement. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=========================================================================== + +This software is copyrighted by the Regents of the University of +California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState +Corporation and other parties. The following terms apply to all files +associated with the software unless explicitly disclaimed in +individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" +in the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you +are acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. + +=========================================================================== + +PostgreSQL Database Management System +(formerly known as Postgres, then as Postgres95) + +Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group + +Portions Copyright (c) 1994, The Regents of the University of California + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose, without fee, and without a written agreement +is hereby granted, provided that the above copyright notice and this +paragraph and the following two paragraphs appear in all copies. + +IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING +LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS +DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO +PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. diff --git a/frontends/riscos/distribution/3rdParty/Tinct/!Help b/frontends/riscos/distribution/3rdParty/Tinct/!Help new file mode 100644 index 000000000..2e27e354f --- /dev/null +++ b/frontends/riscos/distribution/3rdParty/Tinct/!Help @@ -0,0 +1,304 @@ +Tinct +===== +This module provides the necessary functionality to display alpha-blended +sprites both scaled and otherwise. It also provides functions for dithering, +error diffusion and performing bi-linear filtering to improve their appearance. + + +Technical information +¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ +To ensure future compatibility, this module does not patch the OS in any way +and works in a totally legal way. It also does not write to itself in any +way, so is suitable for running from ROM. + Redirection to sprites is supported, although due to the overheads involved +with caching the colour translation tables it is not recommended that this is +done frequently. There are some exceptions to this, however, as redirecting to +a 16bpp or 32bpp mode sprite does not require any translation tables, and +redirecting to a sprite that has the same mode and palette as the previous +destination that Tinct was used for causes a minimum overhead as the +translation tables are checked and cached values are used if possible. + +Format of a sprite with 8-bit alpha channel +¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +The sprite format used by Tinct differs from those used by RISC OS Select, +and whilst facilities are supplied to convert sprites into the required format, +no facilities are provided to manipulate them. + All sprites used by Tinct must be 32bpp, and cannot have a standard RISC OS +mask specified. The basic format of the sprite is shown below, with the +restrictions to the standard sprite format marked with an asterisk (*): + + [+0] Offset to next sprite + [+4] Sprite name, up to 12 characters with trailing zeroes + [+16] Width in words - 1 + [+20] Height in scan lines - 1 + [+24] First bit used + [+28] Last bit used + [+32] Offset to sprite image + [+36] * Offset to sprite image (no mask allowed) + [+40] * Sprite type (must be 0x301680B5) + +Whereas for normal sprites the sprite image would be a series of colour words +of the format RrGgBb00, alpha-blended sprites use the empty byte to specify +the alpha value, ie RrGgBbAa. + The alpha values represent the blending level on a linear scale where 0x00 +represents that the source pixel is totally transparent and 0xff that it is +totally opaque. It should be noted that as a standard 32bpp sprite (eg as +created with !Paint) will have the alpha channel set to 0x00 by default no +output will be visible when plotting as an alpha-blended sprite. + +Error handling +¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +If an incorrect sprite is attempted to be used, Tinct currently always returns +error number 0x700 (SBadSpriteFile) rather than the specific cause of the +problem (eg. BadDPI, BadMSFlags or BadPixelDepth) as OS_SpriteOp would do. +There are several technical reasons for this behaviour, and future versions of +Tinct may return more descriptive errors depending on the cause. + + +SWIs provided +¯¯¯¯¯¯¯¯¯¯¯¯¯ +Tinct provides four SWIs to plot sprites and one to convert sprites to their +32bpp equivalent. All values supplied to Tinct must be in OS units, and the +current OS clipping rectangle is used. + The sprite pointers provided are equivalent to calling OS_SpriteOp with +bit 9 of the reason code set. To plot a sprite by name, the sprite should +first be found by using OS_SpriteOp with reason code 0x18 and using the +returned sprite address. + +Tinct_PlotAlpha (0x57240) +¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +Plots an alpha-blended sprite at the specified coordinates. + +-> R2 Sprite pointer + R3 X coordinate + R4 Y coordinate + R7 Flag word + + +Tinct_PlotScaledAlpha (0x57241) +¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +Plots a scaled alpha-blended sprite at the specified coordinates. + +-> R2 Sprite pointer + R3 X coordinate + R4 Y coordinate + R5 Scaled sprite width + R6 Scaled sprite height + R7 Flag word + + +Tinct_Plot (0x57242) +¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +Plots a sprite at the specified coordinates with a constant 0xff value for +the alpha channel, ie without a mask. + +-> R2 Sprite pointer + R3 X coordinate + R4 Y coordinate + R7 Flag word + + +Tinct_PlotScaled (0x57243) +¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +Plots a scaled sprite at the specified coordinates with a constant 0xff value +for the alpha channel, ie without a mask. + +-> R2 Sprite pointer + R3 X coordinate + R4 Y coordinate + R5 Scaled sprite width + R6 Scaled sprite height + R7 Flag word + + +Tinct_ConvertSprite (0x57244) +¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +Converts a paletted sprite into its 32bpp equivalent. Sufficient memory must +have previously been allocated for the sprite (44 + width * height * 4). + As sprites with 16bpp or 32bpp do not have palettes, conversion cannot be +performed on these variants. All sprites must be supplied with a full palette, +eg 8bpp must have 256 palette entries. + +-> R2 Source sprite pointer + R3 Destination sprite pointer + + +Tinct_AvailableFeatures (0x57245) +¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +Returns the features available to the caller by specifying bits in the flag +word. The features available are unique for each mode, although the current +version of Tinct supports the same subset of features for all modes. + +-> R0 Feature to test for, or 0 for all features +<- R0 Features available + + +Tinct_Compress (0x57246) +¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +Compresses an image using a fast algorithm. Sufficient memory must have been +previously allocated for the maximum possible compressed size. This value is +equal to 28 + (width * height * 4) * 33 / 32. + +-> R0 Source sprite pointer + R2 Output data buffer + R3 Output bytes available + R7 Flag word +<- R0 Size of compressed data + + +Tinct_Decompress (0x57247) +¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +Decompresses an image previously compressed. Sufficient memory must have been +previously allocated for the decompressed data (44 + width * height * 4) where +width and height are available at +0 and +4 of the compressed data respectively. + +-> R0 Input data buffer + R2 Output data buffer + R7 Flag word (currently 0) +<- R0 Size of decompressed data + + +Flag word (plotting) +¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ +All the SWIs provided by Tinct for plotting use a common flag word to +describe the manner in which the plot is performed. Each bit controls a +particular characteristic of the plotting: + + 0 Forcibly read the screen base (only use if hardware scrolling) + 1 Use bi-linear filtering when scaling sprites + 2 Dither colours in 16bpp and below + 3 Perform error diffusion if bit 2 clear, invert dither pattern if set + 4 Horizontally fill the current graphics window with the sprite + 5 Vertically fill the current graphics window with the sprite + 6 Forcibly read the palette (only use if changing palette outside of + the WIMP) + 7 Use OS_SpriteOp to perform final plotting (see note) + 8+ Reserved (must be 0) if bit 7 is clear, background colour to + blend the alpha channel to otherwise + +If a bit is set in the flag word that cannot be honoured by the current +version of Tinct then it is ignored. Tinct_AvailableFeatures can be used +to test in advance what flags will be honoured. + +Bi-linear filtering +¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +Although bi-linear filtering is only relevant during scaled plotting, this +situation occurs when the EigFactors of the mode are not equal. As such, an +application should always set their preferred flags to ensure consistency. The +case of XEig * 2 = YEig (rectangular pixel modes) for even height sprites is a +special case and has optimised code implemented. + There is an upper limit to the size of sprite that can be bi-linear filtered. +The checks that are currently made are: + + scaled_width / sprite_width < 256 + scaled_height / sprite_height < 256 + scaled_width * max(sprite_height, scaled_height) < 32,768 + + It should be noted that as bi-linear filtering is performed as a pre-filter, +it carries a sizable overhead. However, as all scaling calculations are +performed during this filter, tiled plotting (bits 4 and 5) are affected by +a smaller margin (in certain cases a speed gain can be achieved). + As bi-linear filtering is performed using a pre-filter, it can be used in +association with OS_SpriteOp rendering. + +Error diffusion and dithering +¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +If both error diffusion and dithering are enabled then the image is plotted +using only dithering, but with the dither pattern inverted. This enables an +application to provide the user with what appears to be a higher quality image +by redrawing every frame with the flag toggled. + There is a significant speed difference between dithering and error diffusion, +and Tinct does not support error diffusion in all colour depths. If error +diffusion is requested, but cannot be performed by Tinct then dithering with +an inverted pattern is used (as if bits 2 and 3 were set). + There is an upper limit to the size of sprite that Tinct can perform error +diffusion on. This is currently set to a display width of 2047 pixels wide with +an unlimited height. Any attempt to use a higher resolution will result in +dithered rendering with an inverted pattern (ie bits 2 and 3 set). + As error diffusion and dithering are implemented during the plot cycle, it is +not possible to use them in association with OS_SpriteOp rendering. However, +the bits should be set as future versions of Tinct may respect them for users +of RISC OS 3.1 where true colour sprites are not supported. + +Sprite filling +¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +If filling is specified, then the supplied co-ordinate is the offset of the +pattern relative to (0, 0) used for the fill. For example, a 64x64 sprite that +is plotted with bits 4 and 5 set and a position of (32, 16) would fill the +current graphics window with multiple copies of the image stating with the +first image plotted at (-32, -48). + The caller should not concern itself with the size of the image being tiled +as small images are internally optimised where possible to maximise the +plotting speed. + +Rendering using OS_SpriteOp +¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +It can be useful to use Tinct to perform the rendering to using OS_SpriteOp. +There are two general situations where this may be useful: + + 1) To output to a printer driver + 2) To allow hardware acceleraton (such as a ViewFinder card) + +By using Tinct rather than a direct OS_SpriteOp call, it allows the caller to +retain certain features Tinct provides (such as sprite filling and a limited +version of the standard alpha blending) and allows the caller to have a common +plotting interface. + When using this feature for alpha-blended sprites, the background colour +specified in the top 24-bits of the flag word is used for blending with any +pixels that are not transparent. This requires that Tinct requires a second +copy of the sprite in memory to modify which may present a significant overhead +in some situations. Plotting opaquely does not have any such overheads. + Using OS_SpriteOp rendering does not currently work on RISC OS 3.1 or earlier +due to the lack of support for true colour sprites. Future versions of Tinct +may remove this restriction. + + +Flag word (compression) +¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ +The flag word used by Tinct_Compress can be used to improve the compression +ratio by performing pre-filtering on the data. The flags below relate only to +compression and should not be passed to Tinct_Decompress. + + 0 Image is opaque, remove the alpha channel prior to compression + +All unspecified bits are reserved for future expansion and as such should be +set to 0. + +Compressed data format +¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +Certain aspects of the compressed data format are guaranteed to remain constant, +so may be used by applications. + + +0 Sprite width + +4 Sprite height + +8 Sprite name (12 chars) + +20 Compression flags + +24 Number of bytes of data following + +The method of compression is not guaranteed to remain constant over future +revisions of Tinct, but subsequent versions will decompress data compressed +with previous versions. + + +Contact details +¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ +If you would like to report a problem relating to Tinct, provide feedback, or +request a licence for a commercial product, please use the details below: + +Address: 5 Queens Close, East Markham, Newark, Nottinghamshire, NG22 0QY. UK +E-mail: info@tinct.net +Website: www.tinct.net + + +Copyright and licence details +¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ +Tinct is © copyright Richard Wilson, 2004. + +Distribution and usage +¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ +Unrestricted use of Tinct is hereby granted for any non-commercial product. Any +use as part of a commercial product requires written consent from the author. +No charge may be made relating to the distribution of this software, and this +copyright information should be included in all copies of the software. + Modified versions of this program may not be distributed without the authors +consent, nor may modified versions of the source code or relating files.
\ No newline at end of file diff --git a/frontends/riscos/distribution/LeesMij b/frontends/riscos/distribution/LeesMij new file mode 100644 index 000000000..a0d3ff41f --- /dev/null +++ b/frontends/riscos/distribution/LeesMij @@ -0,0 +1,73 @@ +NetSurf +======= + +Dit is een ontwikkelversie van NetSurf, een webbrowser met open +broncode. + +De nieuwste versie van NetSurf is verkrijgbaar via: + + http://www.netsurf-browser.org/ + + +Installatie +----------- + +De installatie gaat in drie stappen: + + 1. Gebruik de samenvoegfaciliteit van !Boot (te openen via de + besturingssysteeminstellingen -> !Boot) om de meegeleverde + !Boot-map samen te voegen met die van het systeem. + + Als het besturingssysteem geen !Boot-samenvoegfaciliteit + ondersteund, sleep dan de meegeleverde !Boot-map in de map + waarin de bestaande !Boot-structuur staat. + + 2. Gebruik de samenvoegfaciliteit van !System (te openen via de + besturingssysteeminstellingen -> !System) om de meegeleverde + !System-map samen te voegen met die van het systeem. + + 3. Sleep de !NetSurf-programmamap naar de gewenste map op de + harde schijf. + +Dubbelklik op het programma !NetSurf in de gekozen locatie om de +NetSurf-browser te starten. + + +Opmerking NetSurf vereist de WindowManager-module 3.80 of een + recentere versie. Deze is standaard aanwezig in RISC OS 4 + of een recentere versie. Voor RISC OS 3-gebruikers zijn + er twee mogelijkheden om NetSurf te kunnen gebruiken: + + - De 'Universal !Boot Sequence' van Acorn: + http://www.riscos.com/ftp_space/generic/uniboot/ + - HardDisc4-schijfstructuur van RISC OS Open: + https://www.riscosopen.org/content/downloads/common/ + + +Opmerking RISC OS 3.1 of oudere versies worden niet ondersteund. + + +Licenties +--------- + +NetSurf wordt geleverd onder de GPL, evenals verschillende andere +licenties voor de verschillende componenten die het programma +gebruikt. Bezoek in de NetSurf-browser het URL-adres 'about:licence' +voor meer informatie. + + +De meegeleverde !Boot- en !System-mappen bevatten items die door +derden zijn geproduceerd. De bijbehorende licenties zijn meegeleverd +in de map '3rdParty'. + +AcornURI + http://sudden.recoil.org/others/ + +Iconv + http://www.netsurf-browser.org/iconv/ + +SharedUnixLibrary + http://www.riscos.info/downloads/gccsdk/sharedunixlib/system.zip + +Tinct + http://www.tinct.net/tinct.asp diff --git a/frontends/riscos/distribution/ReadMe b/frontends/riscos/distribution/ReadMe new file mode 100644 index 000000000..eec39d6ab --- /dev/null +++ b/frontends/riscos/distribution/ReadMe @@ -0,0 +1,61 @@ +NetSurf +======= + +This is a development build of NetSurf, an open source web browser. + +The latest version of NetSurf is available from: + + http://www.netsurf-browser.org/ + + +Installation +------------ + +Installation is a three step process: + + 1. Use the Boot Merge facility provided by Configure to merge + the supplied !Boot directory with the one on your system. + + If there is no !Boot merge facility on your system, simply + drag the supplied !Boot over your existing boot structure. + + 2. Use the System Merge facility provided by Configure to merge + the supplied !System directory with the one on your system. + + 3. Drag the !NetSurf application directory to a place on your + hard disc. + +Double click on !NetSurf in your chosen location to launch NetSurf. + + +Note NetSurf requires WindowManager 3.80 or later. This comes + with RISC OS 4 and above. RISC OS 3 users should install + the Universal Boot Sequence from: + http://acorn.riscos.com/riscos/releases/UniBoot/ + +Note RISC OS 3.1 and earlier are not supported. + + +Licences +-------- + +NetSurf is provided under the GPL, as well as several other licences +for different components it uses. Visit NetSurf's about:licence URL +for details. + + +The !Boot and !System directories contain items provided produced +by third parties. Their licences are provided in the 3rd Party +directory. + +AcornURI + http://sudden.recoil.org/others/ + +Iconv + http://www.netsurf-browser.org/iconv/ + +SharedUnixLibrary + http://www.riscos.info/downloads/gccsdk/sharedunixlib/system.zip + +Tinct + http://www.tinct.net/tinct.asp diff --git a/frontends/riscos/download.c b/frontends/riscos/download.c new file mode 100644 index 000000000..cddb449de --- /dev/null +++ b/frontends/riscos/download.c @@ -0,0 +1,1629 @@ +/* + * Copyright 2004 James Bursa <bursa@users.sourceforge.net> + * Copyright 2003 Rob Jackson <jacko@xms.ms> + * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * \file + * RISC OS download windows implementation. + * + * This file implements the interface given by desktop/gui_download.h + * for download windows. Each download window has an associated + * fetch. Downloads start by writing received data to a temporary + * file. At some point the user chooses a destination (by drag & + * drop), and the temporary file is then moved to the destination and + * the download continues until complete. + */ + +#include <assert.h> +#include <string.h> +#include <time.h> +#include <curl/curl.h> +#include <libwapcaplet/libwapcaplet.h> + +#include "oslib/mimemap.h" +#include "oslib/osargs.h" +#include "oslib/osfile.h" +#include "oslib/osfind.h" +#include "oslib/osfscontrol.h" +#include "oslib/osgbpb.h" +#include "oslib/wimp.h" +#include "oslib/wimpspriteop.h" + +#include "utils/sys_time.h" +#include "utils/nsoption.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/nsurl.h" +#include "utils/utf8.h" +#include "utils/utils.h" +#include "utils/string.h" +#include "utils/corestrings.h" +#include "desktop/gui_download.h" +#include "desktop/download.h" + +#include "riscos/gui.h" +#include "riscos/dialog.h" +#include "riscos/mouse.h" +#include "riscos/save.h" +#include "riscos/query.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" +#include "riscos/ucstables.h" +#include "riscos/filetype.h" + +#define ICON_DOWNLOAD_ICON 0 +#define ICON_DOWNLOAD_URL 1 +#define ICON_DOWNLOAD_PATH 2 +#define ICON_DOWNLOAD_DESTINATION 3 +#define ICON_DOWNLOAD_PROGRESS 5 +#define ICON_DOWNLOAD_STATUS 6 + +#define RO_DOWNLOAD_MAX_PATH_LEN 255 + +typedef enum +{ + QueryRsn_Quit, + QueryRsn_Abort, + QueryRsn_Overwrite +} query_reason; + + +/** Data for a download window. */ +struct gui_download_window { + /** Associated context, or 0 if the fetch has completed or aborted. */ + download_context *ctx; + unsigned int received; /**< Amount of data received so far. */ + unsigned int total_size; /**< Size of resource, or 0 if unknown. */ + + wimp_w window; /**< RISC OS window handle. */ + bits file_type; /**< RISC OS file type. */ + + char url[256]; /**< Buffer for URL icon. */ + char sprite_name[20]; /**< Buffer for sprite icon. */ + char path[RO_DOWNLOAD_MAX_PATH_LEN]; /**< Buffer for pathname icon. */ + char status[256]; /**< Buffer for status icon. */ + + /** User has chosen the destination, and it is being written. */ + bool saved; + bool close_confirmed; + bool error; /**< Error occurred, aborted. */ + + /** RISC OS file handle, of temporary file when !saved, and of + * destination when saved. */ + os_fw file; + + query_id query; + query_reason query_rsn; + + struct timeval start_time; /**< Time download started. */ + struct timeval last_time; /**< Time status was last updated. */ + unsigned int last_received; /**< Value of received at last_time. */ + float average_rate; /**< Moving average download rate. */ + unsigned int average_points; /**< Number of points in the average. */ + + bool send_dataload; /**< Should send DataLoad message when finished */ + wimp_message save_message; /**< Copy of wimp DataSaveAck message */ + + struct gui_download_window *prev; /**< Previous in linked list. */ + struct gui_download_window *next; /**< Next in linked list. */ +}; + + +/** List of all download windows. */ +static struct gui_download_window *download_window_list = 0; +/** Download window with current save operation. */ +static struct gui_download_window *download_window_current = 0; + +/** Template for a download window. */ +static wimp_window *download_template; + +/** Width of progress bar at 100%. */ +static int download_progress_width; +/** Coordinates of progress bar. */ +static int download_progress_x0; +static int download_progress_y0; +static int download_progress_y1; + +/** Current download directory. */ +static char *download_dir = NULL; +static size_t download_dir_len; + +static void ro_gui_download_drag_end(wimp_dragged *drag, void *data); +static const char *ro_gui_download_temp_name(struct gui_download_window *dw); +static void ro_gui_download_update_status(struct gui_download_window *dw); +static void ro_gui_download_update_status_wrapper(void *p); +static void ro_gui_download_window_hide_caret(struct gui_download_window *dw); +static char *ro_gui_download_canonicalise(const char *path); +static bool ro_gui_download_check_space(struct gui_download_window *dw, + const char *dest_file, const char *orig_file); +static os_error *ro_gui_download_move(struct gui_download_window *dw, + const char *dest_file, const char *src_file); +static void ro_gui_download_remember_dir(const char *path); +static bool ro_gui_download_save(struct gui_download_window *dw, + const char *file_name, bool force_overwrite); +static void ro_gui_download_send_dataload(struct gui_download_window *dw); +static void ro_gui_download_window_destroy_wrapper(void *p); +static bool ro_gui_download_window_destroy(struct gui_download_window *dw, bool quit); +static void ro_gui_download_close_confirmed(query_id, enum query_response res, void *p); +static void ro_gui_download_close_cancelled(query_id, enum query_response res, void *p); +static void ro_gui_download_overwrite_confirmed(query_id, enum query_response res, void *p); +static void ro_gui_download_overwrite_cancelled(query_id, enum query_response res, void *p); + +static bool ro_gui_download_click(wimp_pointer *pointer); +static bool ro_gui_download_keypress(wimp_key *key); +static void ro_gui_download_close(wimp_w w); + +static const query_callback close_funcs = +{ + ro_gui_download_close_confirmed, + ro_gui_download_close_cancelled +}; + +static const query_callback overwrite_funcs = +{ + ro_gui_download_overwrite_confirmed, + ro_gui_download_overwrite_cancelled +}; + + +/** + * Load the download window template. + */ + +void ro_gui_download_init(void) +{ + download_template = ro_gui_dialog_load_template("download"); + download_progress_width = + download_template->icons[ICON_DOWNLOAD_STATUS].extent.x1 - + download_template->icons[ICON_DOWNLOAD_STATUS].extent.x0; + download_progress_x0 = + download_template->icons[ICON_DOWNLOAD_PROGRESS].extent.x0; + download_progress_y0 = + download_template->icons[ICON_DOWNLOAD_PROGRESS].extent.y0; + download_progress_y1 = + download_template->icons[ICON_DOWNLOAD_PROGRESS].extent.y1; +} + + +/** + * Returns the pathname of a temporary file for this download. + * + * \param dw download window + * \return ptr to pathname + */ + +const char *ro_gui_download_temp_name(struct gui_download_window *dw) +{ + static char temp_name[40]; + snprintf(temp_name, sizeof temp_name, "<Wimp$ScrapDir>.ns%x", + (unsigned int) dw); + return temp_name; +} + +/** + * Try and find the correct RISC OS filetype from a download context. + */ +static nserror download_ro_filetype(download_context *ctx, bits *ftype_out) +{ + nsurl *url = download_context_get_url(ctx); + bits ftype = 0; + lwc_string *scheme; + + /* If the file is local try and read its filetype */ + scheme = nsurl_get_component(url, NSURL_SCHEME); + if (scheme != NULL) { + bool filescheme; + if (lwc_string_isequal(scheme, + corestring_lwc_file, + &filescheme) != lwc_error_ok) { + filescheme = false; + } + + if (filescheme) { + lwc_string *path = nsurl_get_component(url, NSURL_PATH); + if (path != NULL && lwc_string_length(path) != 0) { + char *raw_path; + raw_path = curl_unescape(lwc_string_data(path), + lwc_string_length(path)); + if (raw_path != NULL) { + ftype = ro_filetype_from_unix_path(raw_path); + curl_free(raw_path); + } + } + } + } + + /* If we still don't have a filetype (i.e. failed reading local + * one or fetching a remote object), then use the MIME type. + */ + if (ftype == 0) { + /* convert MIME type to RISC OS file type */ + os_error *error; + const char *mime_type; + + mime_type = download_context_get_mime_type(ctx); + error = xmimemaptranslate_mime_type_to_filetype(mime_type, &ftype); + if (error) { + LOG("xmimemaptranslate_mime_type_to_filetype: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("MiscError", error->errmess); + ftype = 0xffd; + } + } + + *ftype_out = ftype; + return NSERROR_OK; +} + +/** + * Create and open a download progress window. + * + * \param ctx Download context + * \param gui The RISCOS gui window to download for. + * \return A new gui_download_window structure, or NULL on error and error + * reported + */ + +static struct gui_download_window * +gui_download_window_create(download_context *ctx, struct gui_window *gui) +{ + nsurl *url = download_context_get_url(ctx); + const char *temp_name; + char *filename = NULL; + struct gui_download_window *dw; + bool space_warning = false; + os_error *error; + char *local_path; + nserror err; + size_t i, last_dot; + + dw = malloc(sizeof *dw); + if (!dw) { + ro_warn_user("NoMemory", 0); + return 0; + } + + dw->ctx = ctx; + dw->saved = false; + dw->close_confirmed = false; + dw->error = false; + dw->query = QUERY_INVALID; + dw->received = 0; + dw->total_size = download_context_get_total_length(ctx); + + /** @todo change this to take a reference to the nsurl and use + * that value directly rather than using a fixed buffer. + */ + strncpy(dw->url, nsurl_access(url), sizeof dw->url); + dw->url[sizeof dw->url - 1] = 0; + + dw->status[0] = 0; + gettimeofday(&dw->start_time, 0); + dw->last_time = dw->start_time; + dw->last_received = 0; + dw->file_type = 0; + dw->average_rate = 0; + dw->average_points = 0; + + /* get filetype */ + err = download_ro_filetype(ctx, &dw->file_type); + if (err != NSERROR_OK) { + ro_warn_user(messages_get_errorcode(err), 0); + free(dw); + return 0; + } + + /* open temporary output file */ + temp_name = ro_gui_download_temp_name(dw); + if (!ro_gui_download_check_space(dw, temp_name, NULL)) { + /* issue a warning but continue with the download because the + user can save it to another medium whilst it's downloading */ + space_warning = true; + } + error = xosfind_openoutw(osfind_NO_PATH | osfind_ERROR_IF_DIR, + temp_name, 0, &dw->file); + if (error) { + LOG("xosfind_openoutw: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("SaveError", error->errmess); + free(dw); + return 0; + } + + /* fill in download window icons */ + download_template->icons[ICON_DOWNLOAD_URL].data.indirected_text.text = + dw->url; + download_template->icons[ICON_DOWNLOAD_URL].data.indirected_text.size = + sizeof dw->url; + + download_template->icons[ICON_DOWNLOAD_STATUS].data.indirected_text. + text = dw->status; + download_template->icons[ICON_DOWNLOAD_STATUS].data.indirected_text. + size = sizeof dw->status; + + sprintf(dw->sprite_name, "file_%.3x", dw->file_type); + if (!ro_gui_wimp_sprite_exists(dw->sprite_name)) + strcpy(dw->sprite_name, "file_xxx"); + download_template->icons[ICON_DOWNLOAD_ICON].data.indirected_sprite.id = + (osspriteop_id) dw->sprite_name; + + /* Get a suitable path- and leafname for the download. */ + temp_name = download_context_get_filename(dw->ctx); + + if (temp_name == NULL) + temp_name = messages_get("SaveObject"); + + if (temp_name != NULL) + filename = strdup(temp_name); + + if (filename == NULL) { + LOG("Failed to establish download filename."); + ro_warn_user("SaveError", error->errmess); + free(dw); + return 0; + } + + for (i = 0, last_dot = (size_t) -1; filename[i] != '\0'; i++) { + const char c = filename[i]; + + if (c == '.') { + last_dot = i; + filename[i] = '/'; + } else if (c <= ' ' || strchr(":*#$&@^%\\", c) != NULL) + filename[i] = '_'; + } + + if (nsoption_bool(strip_extensions) && last_dot != (size_t) -1) + filename[last_dot] = '\0'; + + if (download_dir != NULL && strlen(download_dir) > 0) + snprintf(dw->path, RO_DOWNLOAD_MAX_PATH_LEN, "%s.%s", + download_dir, filename); + else + snprintf(dw->path, RO_DOWNLOAD_MAX_PATH_LEN, "%s", + filename); + + free(filename); + + err = utf8_to_local_encoding(dw->path, 0, &local_path); + if (err != NSERROR_OK) { + /* badenc should never happen */ + assert(err !=NSERROR_BAD_ENCODING); + LOG("utf8_to_local_encoding failed"); + ro_warn_user("NoMemory", 0); + free(dw); + return 0; + } + else { + strncpy(dw->path, local_path, sizeof dw->path); + free(local_path); + } + + download_template->icons[ICON_DOWNLOAD_PATH].data.indirected_text.text = + dw->path; + download_template->icons[ICON_DOWNLOAD_PATH].data.indirected_text.size = + sizeof dw->path; + + download_template->icons[ICON_DOWNLOAD_DESTINATION].data. + indirected_text.text = dw->path; + download_template->icons[ICON_DOWNLOAD_DESTINATION].data. + indirected_text.size = sizeof dw->path; + + download_template->icons[ICON_DOWNLOAD_DESTINATION].flags |= + wimp_ICON_DELETED; + + /* create and open the download window */ + error = xwimp_create_window(download_template, &dw->window); + if (error) { + LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + free(dw); + return 0; + } + + dw->prev = 0; + dw->next = download_window_list; + if (download_window_list) + download_window_list->prev = dw; + download_window_list = dw; + + ro_gui_download_update_status(dw); + + ro_gui_dialog_open(dw->window); + + ro_gui_wimp_event_set_user_data(dw->window, dw); + ro_gui_wimp_event_register_mouse_click(dw->window, ro_gui_download_click); + ro_gui_wimp_event_register_keypress(dw->window, ro_gui_download_keypress); + ro_gui_wimp_event_register_close_window(dw->window, ro_gui_download_close); + + /* issue the warning now, so that it appears in front of the download + * window! */ + if (space_warning) + ro_warn_user("DownloadWarn", messages_get("NoDiscSpace")); + + return dw; +} + +/** + * Handle failed downloads. + * + * \param dw download window + * \param error_msg error message + */ + +static void gui_download_window_error(struct gui_download_window *dw, + const char *error_msg) +{ + os_error *error; + + if (dw->ctx != NULL) + download_context_destroy(dw->ctx); + dw->ctx = NULL; + dw->error = true; + + riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw); + + /* place error message in status icon in red */ + strncpy(dw->status, error_msg, sizeof dw->status); + error = xwimp_set_icon_state(dw->window, + ICON_DOWNLOAD_STATUS, + wimp_COLOUR_RED << wimp_ICON_FG_COLOUR_SHIFT, + wimp_ICON_FG_COLOUR); + if (error) { + LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + + /* grey out pathname icon */ + error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_PATH, + wimp_ICON_SHADED, 0); + if (error) { + LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + + /* grey out file icon */ + error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_ICON, + wimp_ICON_SHADED, wimp_ICON_SHADED); + if (error) { + LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + + ro_gui_download_window_hide_caret(dw); +} + +/** + * Handle received download data. + * + * \param dw download window + * \param data pointer to block of data received + * \param size size of data + * \return NSERROR_OK on success, appropriate error otherwise + */ + +static nserror gui_download_window_data(struct gui_download_window *dw, + const char *data, unsigned int size) +{ + while (true) { + const char *msg; + int unwritten; + os_error *error; + + error = xosgbpb_writew(dw->file, (const byte *) data, size, + &unwritten); + if (error) { + LOG("xosgbpb_writew: 0x%x: %s", error->errnum, error->errmess); + msg = error->errmess; + + } else if (unwritten) { + LOG("xosgbpb_writew: unwritten %i", unwritten); + msg = messages_get("Unwritten"); + } + else { + dw->received += size; + return NSERROR_OK; + } + + ro_warn_user("SaveError", msg); + + if (dw->saved) { + /* try to continue with the temporary file */ + const char *temp_name = ro_gui_download_temp_name(dw); + + error = ro_gui_download_move(dw, temp_name, dw->path); + if (!error) { + + /* re-allow saving */ + dw->saved = false; + + error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_ICON, + wimp_ICON_SHADED, 0); + if (error) { + LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + + error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_DESTINATION, + wimp_ICON_DELETED, wimp_ICON_DELETED); + if (error) { + LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + error = xwimp_set_icon_state(dw->window, + ICON_DOWNLOAD_PATH, wimp_ICON_DELETED, 0); + if (error) { + LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + + continue; + } + } + + /* give up then */ + assert(dw->ctx); + download_context_abort(dw->ctx); + gui_download_window_error(dw, msg); + + return NSERROR_SAVE_FAILED; + } +} + + +/** + * Update the status text and progress bar. + * + * \param dw download window + */ + +void ro_gui_download_update_status(struct gui_download_window *dw) +{ + char *total_size; + char *speed; + char time[20] = "?"; + struct timeval t; + float dt; + unsigned int left; + float rate; + os_error *error; + int width; + char *local_status; + nserror err; + + gettimeofday(&t, 0); + dt = (t.tv_sec + 0.000001 * t.tv_usec) - (dw->last_time.tv_sec + + 0.000001 * dw->last_time.tv_usec); + if (dt == 0) + dt = 0.001; + + total_size = human_friendly_bytesize(max(dw->received, dw->total_size)); + + if (dw->ctx) { + char *received; + rate = (dw->received - dw->last_received) / dt; + received = human_friendly_bytesize(dw->received); + /* A simple 'modified moving average' download rate calculation + * to smooth out rate fluctuations: chosen for simplicity. + */ + dw->average_points++; + dw->average_rate = + ((dw->average_points - 1) * + dw->average_rate + rate) / + dw->average_points; + speed = human_friendly_bytesize(dw->average_rate); + if (dw->total_size) { + float f; + + if (dw->average_rate > 0) { + left = (dw->total_size - dw->received) / + dw->average_rate; + sprintf(time, "%u:%.2u", left / 60, left % 60); + } + + /* convert to local encoding */ + err = utf8_to_local_encoding( + messages_get("Download"), 0, &local_status); + if (err != NSERROR_OK) { + /* badenc should never happen */ + assert(err != NSERROR_BAD_ENCODING); + /* hide nomem error */ + snprintf(dw->status, sizeof dw->status, + messages_get("Download"), + received, total_size, speed, time); + } + else { + snprintf(dw->status, sizeof dw->status, + local_status, + received, total_size, speed, time); + free(local_status); + } + + f = (float) dw->received / (float) dw->total_size; + width = download_progress_width * f; + } else { + left = t.tv_sec - dw->start_time.tv_sec; + sprintf(time, "%u:%.2u", left / 60, left % 60); + + err = utf8_to_local_encoding( + messages_get("DownloadU"), 0, &local_status); + if (err != NSERROR_OK) { + /* badenc should never happen */ + assert(err != NSERROR_BAD_ENCODING); + /* hide nomem error */ + snprintf(dw->status, sizeof dw->status, + messages_get("DownloadU"), + received, speed, time); + } + else { + snprintf(dw->status, sizeof dw->status, + local_status, + received, speed, time); + free(local_status); + } + + /* length unknown, stay at 0 til finished */ + width = 0; + } + } else { + left = dw->last_time.tv_sec - dw->start_time.tv_sec; + if (left == 0) + left = 1; + rate = (float) dw->received / (float) left; + sprintf(time, "%u:%.2u", left / 60, left % 60); + speed = human_friendly_bytesize(rate); + + err = utf8_to_local_encoding(messages_get("Downloaded"), 0, + &local_status); + if (err != NSERROR_OK) { + /* badenc should never happen */ + assert(err != NSERROR_BAD_ENCODING); + /* hide nomem error */ + snprintf(dw->status, sizeof dw->status, + messages_get("Downloaded"), + total_size, speed, time); + } + else { + snprintf(dw->status, sizeof dw->status, local_status, + total_size, speed, time); + free(local_status); + } + + /* all done */ + width = download_progress_width; + } + + dw->last_time = t; + dw->last_received = dw->received; + + error = xwimp_resize_icon(dw->window, ICON_DOWNLOAD_PROGRESS, + download_progress_x0, + download_progress_y0, + download_progress_x0 + width, + download_progress_y1); + if (error) { + LOG("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + + error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_STATUS, 0, 0); + if (error) { + LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + + if (dw->ctx) { + riscos_schedule(1000, ro_gui_download_update_status_wrapper, dw); + } else { + riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw); + } +} + + +/** + * Wrapper for ro_gui_download_update_status(), suitable for riscos_schedule(). + */ + +void ro_gui_download_update_status_wrapper(void *p) +{ + ro_gui_download_update_status((struct gui_download_window *) p); +} + + + +/** + * Hide the caret but preserve input focus. + * + * \param dw download window + */ + +void ro_gui_download_window_hide_caret(struct gui_download_window *dw) +{ + wimp_caret caret; + os_error *error; + + error = xwimp_get_caret_position(&caret); + if (error) { + LOG("xwimp_get_caret_position: 0x%x : %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + else if (caret.w == dw->window) { + error = xwimp_set_caret_position(dw->window, (wimp_i)-1, 0, 0, 1 << 25, -1); + if (error) { + LOG("xwimp_get_caret_position: 0x%x : %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + } +} + + + + +/** + * Handle completed downloads. + * + * \param dw download window + */ + +static void gui_download_window_done(struct gui_download_window *dw) +{ + os_error *error; + + if (dw->ctx != NULL) + download_context_destroy(dw->ctx); + dw->ctx = NULL; + ro_gui_download_update_status(dw); + + error = xosfind_closew(dw->file); + if (error) { + LOG("xosfind_closew: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("SaveError", error->errmess); + } + dw->file = 0; + + if (dw->saved) { + error = xosfile_set_type(dw->path, + dw->file_type); + if (error) { + LOG("xosfile_set_type: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("SaveError", error->errmess); + } + + if (dw->send_dataload) { + ro_gui_download_send_dataload(dw); + } + + riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw); + } +} + + +/** + * Handle Mouse_Click events in a download window. + * + * \param pointer block returned by Wimp_Poll + */ + +bool ro_gui_download_click(wimp_pointer *pointer) +{ + struct gui_download_window *dw; + + dw = (struct gui_download_window *)ro_gui_wimp_event_get_user_data(pointer->w); + if ((pointer->buttons & (wimp_DRAG_SELECT | wimp_DRAG_ADJUST)) && + pointer->i == ICON_DOWNLOAD_ICON && + !dw->error && !dw->saved) { + const char *sprite = ro_gui_get_icon_string(pointer->w, pointer->i); + int x = pointer->pos.x, y = pointer->pos.y; + wimp_window_state wstate; + wimp_icon_state istate; + /* start the drag from the icon's exact location, rather than the pointer */ + istate.w = wstate.w = pointer->w; + istate.i = pointer->i; + if (!xwimp_get_window_state(&wstate) && !xwimp_get_icon_state(&istate)) { + x = (istate.icon.extent.x1 + istate.icon.extent.x0)/2 + + wstate.visible.x0 - wstate.xscroll; + y = (istate.icon.extent.y1 + istate.icon.extent.y0)/2 + + wstate.visible.y1 - wstate.yscroll; + } + ro_mouse_drag_start(ro_gui_download_drag_end, NULL, NULL, NULL); + download_window_current = dw; + ro_gui_drag_icon(x, y, sprite); + + } else if (pointer->i == ICON_DOWNLOAD_DESTINATION) { + char command[256] = "Filer_OpenDir "; + char *dot; + + strncpy(command + 14, dw->path, 242); + command[255] = 0; + dot = strrchr(command, '.'); + if (dot) { + os_error *error; + *dot = 0; + error = xos_cli(command); + if (error) { + LOG("xos_cli: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("MiscError", error->errmess); + } + } + } + return true; +} + + +/** + * Handler Key_Press events in a download window. + * + * \param key key press returned by Wimp_Poll + * \return true iff key press handled + */ + +bool ro_gui_download_keypress(wimp_key *key) +{ + struct gui_download_window *dw; + + dw = (struct gui_download_window *)ro_gui_wimp_event_get_user_data(key->w); + switch (key->c) + { + case wimp_KEY_ESCAPE: + ro_gui_download_window_destroy(dw, false); + return true; + + case wimp_KEY_RETURN: { + const char *name = ro_gui_get_icon_string(dw->window, + ICON_DOWNLOAD_PATH); + if (!strrchr(name, '.')) { + ro_warn_user("NoPathError", NULL); + return true; + } + ro_gui_convert_save_path(dw->path, sizeof dw->path, name); + + dw->send_dataload = false; + if (ro_gui_download_save(dw, dw->path, + !nsoption_bool(confirm_overwrite)) && !dw->ctx) + { + /* finished already */ + riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw); + } + return true; + } + break; + } + + /* ignore all other keypresses (F12 etc) */ + return false; +} + + +/** + * Handle User_Drag_Box event for a drag from a download window. + * + * \param *drag block returned by Wimp_Poll + * \param *data NULL data to allow use as callback from ro_mouse. + */ + +static void ro_gui_download_drag_end(wimp_dragged *drag, void *data) +{ + wimp_pointer pointer; + wimp_message message; + struct gui_download_window *dw = download_window_current; + const char *leaf; + os_error *error; + + if (dw->saved || dw->error) + return; + + error = xwimp_get_pointer_info(&pointer); + if (error) { + LOG("xwimp_get_pointer_info: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + return; + } + + /* ignore drags to the download window itself */ + if (pointer.w == dw->window) return; + + leaf = strrchr(dw->path, '.'); + if (leaf) + leaf++; + else + leaf = dw->path; + ro_gui_convert_save_path(message.data.data_xfer.file_name, 212, leaf); + + message.your_ref = 0; + message.action = message_DATA_SAVE; + message.data.data_xfer.w = pointer.w; + message.data.data_xfer.i = pointer.i; + message.data.data_xfer.pos.x = pointer.pos.x; + message.data.data_xfer.pos.y = pointer.pos.y; + message.data.data_xfer.est_size = dw->total_size ? dw->total_size : + dw->received; + message.data.data_xfer.file_type = dw->file_type; + message.size = 44 + ((strlen(message.data.data_xfer.file_name) + 4) & + (~3u)); + + error = xwimp_send_message_to_window(wimp_USER_MESSAGE, &message, + pointer.w, pointer.i, 0); + if (error) { + LOG("xwimp_send_message_to_window: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + + gui_current_drag_type = GUI_DRAG_DOWNLOAD_SAVE; +} + + +/** + * Handle Message_DataSaveAck for a drag from a download window. + * + * \param message block returned by Wimp_Poll + */ + +void ro_gui_download_datasave_ack(wimp_message *message) +{ + struct gui_download_window *dw = download_window_current; + + dw->send_dataload = true; + memcpy(&dw->save_message, message, sizeof(wimp_message)); + + if (!ro_gui_download_save(dw, message->data.data_xfer.file_name, + !nsoption_bool(confirm_overwrite))) + return; + + if (!dw->ctx) { + /* Ack successful completed save with message_DATA_LOAD immediately + to reduce the chance of the target app getting confused by it + being delayed */ + + ro_gui_download_send_dataload(dw); + + riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw); + } +} + + +/** + * Return a pathname in canonical form + * + * \param path pathnamee to be canonicalised + * \return ptr to pathname in malloc block, or NULL + */ + +char *ro_gui_download_canonicalise(const char *path) +{ + os_error *error; + int spare = 0; + char *buf; + + error = xosfscontrol_canonicalise_path(path, NULL, NULL, NULL, 0, &spare); + if (error) { + LOG("xosfscontrol_canonicalise_path: 0x%x: %s", error->errnum, error->errmess); + return NULL; + } + + buf = malloc(1 - spare); + if (buf) { + error = xosfscontrol_canonicalise_path(path, buf, NULL, NULL, + 1 - spare, NULL); + if (error) { + LOG("xosfscontrol_canonicalise_path: 0x%x: %s", error->errnum, error->errmess); + + free(buf); + return NULL; + } + } + + return buf; +} + + +/** + * Check the available space on the medium containing the destination file, + * taking into account any space currently occupied by the file at its + * original location. + * + * \param dw download window + * \param dest_file destination pathname + * \param orig_file current pathname, NULL if no existing file + * \return true iff there's enough space + */ + +bool ro_gui_download_check_space(struct gui_download_window *dw, + const char *dest_file, const char *orig_file) +{ + /* is there enough free space for this file? */ + int dest_len = strlen(dest_file); + os_error *error; + int max_file; + bits free_lo; + int free_hi; + char *dir; + + dir = malloc(dest_len + 1); + if (!dir) return true; + + while (dest_len > 0 && dest_file[--dest_len] != '.'); + + memcpy(dir, dest_file, dest_len); + dir[dest_len] = '\0'; + + /* try the 64-bit variant first (RO 3.6+) */ + error = xosfscontrol_free_space64(dir, &free_lo, &free_hi, + &max_file, NULL, NULL); + if (error) { + LOG("xosfscontrol_free_space64: 0x%x: %s", error->errnum, error->errmess); + + free_hi = 0; + error = xosfscontrol_free_space(dir, (int*)&free_lo, + &max_file, NULL); + if (error) { + LOG("xosfscontrol_free_space: 0x%x: %s", error->errnum, error->errmess); + /* close our eyes and hope */ + free(dir); + return true; + } + } + + free(dir); + + if ((bits)max_file < dw->total_size || (!free_hi && free_lo < dw->total_size)) { + char *dest_canon, *orig_canon; + bits space; + + if (!orig_file || !dw->file) { + /* no original file to take into account */ + return false; + } + + space = min((bits)max_file, free_lo); + + dest_canon = ro_gui_download_canonicalise(dest_file); + if (!dest_canon) dest_canon = (char*)dest_file; + + orig_canon = ro_gui_download_canonicalise(orig_file); + if (!orig_canon) orig_canon = (char*)orig_file; + + /* not enough space; allow for the file's original location + when space is tight by comparing the first part of the two + pathnames (and assuming the FS isn't brain damaged!) */ + + char *dot = strchr(orig_canon, '.'); + if (dot && !strncasecmp(dest_canon, orig_canon, (dot + 1) - orig_canon)) { + int allocation; + + error = xosargs_read_allocation(dw->file, + &allocation); + if (error) { + LOG("xosargs_read_allocation: 0x%x : %s", error->errnum, error->errmess); + } + else { + space += allocation; + } + } + + if (dest_canon != dest_file) free(dest_canon); + if (orig_canon != orig_file) free(orig_canon); + + if (space >= dw->total_size) { + /* OK, renaming should work */ + return true; + } + + return false; + } + return true; +} + +/** + * Move the downloading file to a new location and continue downloading there. + * + * \param dw download window + * \param dest_file new location + * \param src_file old location + * \return error iff failed to move file + */ + +os_error *ro_gui_download_move(struct gui_download_window *dw, + const char *dest_file, const char *src_file) +{ + os_error *error; + + /* close temporary file */ + if (dw->file) { + error = xosfind_closew(dw->file); + dw->file = 0; + if (error) { + LOG("xosfind_closew: 0x%x: %s", error->errnum, error->errmess); + return error; + } + } + + /* move or copy temporary file to destination file */ + error = xosfscontrol_rename(src_file, dest_file); + /* Errors from a filing system have number 0x1XXnn, where XX is the FS + * number, and nn the error number. 0x9F is "Not same disc". */ + if (error && (error->errnum == error_BAD_RENAME || + (error->errnum & 0xFF00FFu) == 0x1009Fu)) { + /* rename failed: copy with delete */ + error = xosfscontrol_copy(src_file, dest_file, + osfscontrol_COPY_FORCE | + osfscontrol_COPY_DELETE | + osfscontrol_COPY_LOOK, + 0, 0, 0, 0, 0); + if (error) { + LOG("xosfscontrol_copy: 0x%x: %s", error->errnum, error->errmess); + return error; + } + } else if (error) { + LOG("xosfscontrol_rename: 0x%x: %s", error->errnum, error->errmess); + return error; + } + + if (dw->ctx) { + /* open new destination file if still fetching */ + error = xosfile_write(dest_file, 0xdeaddead, 0xdeaddead, + fileswitch_ATTR_OWNER_READ | + fileswitch_ATTR_OWNER_WRITE); + if (error) { + LOG("xosfile_write: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("SaveError", error->errmess); + } + + error = xosfind_openupw(osfind_NO_PATH | osfind_ERROR_IF_DIR, + dest_file, 0, &dw->file); + if (error) { + LOG("xosfind_openupw: 0x%x: %s", error->errnum, error->errmess); + return error; + } + + error = xosargs_set_ptrw(dw->file, dw->received); + if (error) { + LOG("xosargs_set_ptrw: 0x%x: %s", error->errnum, error->errmess); + return error; + } + + } else { + /* otherwise just set the file type */ + error = xosfile_set_type(dest_file, + dw->file_type); + if (error) { + LOG("xosfile_set_type: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("SaveError", error->errmess); + } + } + + /* success */ + return NULL; +} + + +/** + * Remember the directory containing the given file, + * for use in further downloads. + * + * \param path pathname of downloaded file + * \return none + */ + +void ro_gui_download_remember_dir(const char *path) +{ + const char *lastdot = NULL; + const char *p = path; + + while (*p >= 0x20) { + if (*p == '.') { + /* don't remember the directory if it's a temporary file */ + if (!lastdot && p == path + 12 && + !memcmp(path, "<Wimp$Scrap>", 12)) break; + lastdot = p; + } + p++; + } + + if (lastdot) { + /* remember the directory */ + char *new_dir = realloc(download_dir, (lastdot+1)-path); + if (new_dir) { + download_dir_len = lastdot - path; + memcpy(new_dir, path, download_dir_len); + new_dir[download_dir_len] = '\0'; + download_dir = new_dir; + } + } +} + +/** + * Start of save operation, user has specified where the file should be saved. + * + * \param dw download window + * \param file_name pathname of destination file + & \param force_overwrite true iff required to overwrite without prompting + * \return true iff save successfully initiated + */ + +bool ro_gui_download_save(struct gui_download_window *dw, + const char *file_name, bool force_overwrite) +{ + fileswitch_object_type obj_type; + const char *temp_name; + os_error *error; + + if (dw->saved || dw->error) + return true; + + temp_name = ro_gui_download_temp_name(dw); + + /* does the user want to check for collisions when saving? */ + if (!force_overwrite) { + /* check whether the destination file/dir already exists */ + error = xosfile_read_stamped(file_name, &obj_type, + NULL, NULL, NULL, NULL, NULL); + if (error) { + LOG("xosfile_read_stamped: 0x%x:%s", error->errnum, error->errmess); + return false; + } + + switch (obj_type) { + case osfile_NOT_FOUND: + break; + + case osfile_IS_FILE: + dw->query = query_user("OverwriteFile", NULL, &overwrite_funcs, dw, + messages_get("Replace"), messages_get("DontReplace")); + dw->query_rsn = QueryRsn_Overwrite; + return false; + + default: + error = xosfile_make_error(file_name, obj_type); + assert(error); + ro_warn_user("SaveError", error->errmess); + return false; + } + } + + if (!ro_gui_download_check_space(dw, file_name, temp_name)) { + ro_warn_user("SaveError", messages_get("NoDiscSpace")); + return false; + } + + error = ro_gui_download_move(dw, file_name, temp_name); + if (error) { + ro_warn_user("SaveError", error->errmess); + + /* try to reopen at old location so that the download can continue + to the temporary file */ + error = xosfind_openupw(osfind_NO_PATH | osfind_ERROR_IF_DIR, + temp_name, 0, &dw->file); + if (error) { + LOG("xosfind_openupw: 0x%x: %s", error->errnum, error->errmess); + + } else { + error = xosargs_set_ptrw(dw->file, dw->received); + if (error) { + LOG("xosargs_set_ptrw: 0x%x: %s", error->errnum, error->errmess); + } + } + + if (error) { + if (dw->ctx) + download_context_abort(dw->ctx); + gui_download_window_error(dw, error->errmess); + } + return false; + } + + dw->saved = true; + strncpy(dw->path, file_name, sizeof dw->path); + + if (!dw->send_dataload || dw->save_message.data.data_xfer.est_size != -1) + ro_gui_download_remember_dir(file_name); + + /* grey out file icon */ + error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_ICON, + wimp_ICON_SHADED, wimp_ICON_SHADED); + if (error) { + LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + + /* hide writeable path icon and show destination icon + Note: must redraw icon bounding box because the destination icon + has rounded edges on RISC OS Select/Adjust and doesn't + completely cover the writeable icon */ + + ro_gui_force_redraw_icon(dw->window, ICON_DOWNLOAD_PATH); + error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_PATH, + wimp_ICON_DELETED, wimp_ICON_DELETED); + if (error) { + LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + error = xwimp_set_icon_state(dw->window, + ICON_DOWNLOAD_DESTINATION, wimp_ICON_DELETED, 0); + if (error) { + LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + + ro_gui_download_window_hide_caret(dw); + + return true; +} + + +/** + * Send DataLoad message in response to DataSaveAck, informing the + * target application that the transfer is complete. + * + * \param dw download window + */ + +void ro_gui_download_send_dataload(struct gui_download_window *dw) +{ + /* Ack successful save with message_DATA_LOAD */ + wimp_message *message = &dw->save_message; + os_error *error; + + assert(dw->send_dataload); + dw->send_dataload = false; + + message->action = message_DATA_LOAD; + message->your_ref = message->my_ref; + error = xwimp_send_message_to_window(wimp_USER_MESSAGE, message, + message->data.data_xfer.w, + message->data.data_xfer.i, 0); + /* The window we just attempted to send a message to may + * have been closed before the message was sent. As we've + * no clean way of detecting this, we'll just detect the + * error return from the message send attempt and judiciously + * ignore it. + * + * Ideally, we would have registered to receive Message_WindowClosed + * and then cleared dw->send_dataload flag for the appropriate + * window. Unfortunately, however, a long-standing bug in the + * Pinboard module prevents this from being a viable solution. + * + * See http://groups.google.co.uk/group/comp.sys.acorn.tech/msg/e3fbf70d8393e6cf?dmode=source&hl=en + * for the rather depressing details. + */ + if (error && error->errnum != error_WIMP_BAD_HANDLE) { + LOG("xwimp_set_icon_state: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + + riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw); +} + + +/** + * Handle closing of download window + */ +void ro_gui_download_close(wimp_w w) +{ + struct gui_download_window *dw; + + dw = (struct gui_download_window *)ro_gui_wimp_event_get_user_data(w); + ro_gui_download_window_destroy(dw, false); +} + + +/** + * Close a download window and free any related resources. + * + * \param dw download window + * \param quit destroying because we're quitting the whole app + * \return true if window destroyed, not waiting for user confirmation + */ + +bool ro_gui_download_window_destroy(struct gui_download_window *dw, bool quit) +{ + bool safe = dw->saved && !dw->ctx; + os_error *error; + + if (!safe && !dw->close_confirmed) + { + query_reason rsn = quit ? QueryRsn_Quit : QueryRsn_Abort; + + if (dw->query != QUERY_INVALID) { + + /* can we just reuse the existing query? */ + if (rsn == dw->query_rsn) { + ro_gui_query_window_bring_to_front(dw->query); + return false; + } + + query_close(dw->query); + dw->query = QUERY_INVALID; + } + + if (quit) { + /* bring all download windows to the front of the desktop as + a convenience if there are lots of windows open */ + + struct gui_download_window *d = download_window_list; + while (d) { + ro_gui_dialog_open_top(d->window, NULL, 0, 0); + d = d->next; + } + } + + dw->query_rsn = rsn; + dw->query = query_user(quit ? "QuitDownload" : "AbortDownload", + NULL, &close_funcs, dw, NULL, NULL); + + return false; + } + + riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw); + riscos_schedule(-1, ro_gui_download_window_destroy_wrapper, dw); + + /* remove from list */ + if (dw->prev) + dw->prev->next = dw->next; + else + download_window_list = dw->next; + if (dw->next) + dw->next->prev = dw->prev; + + /* delete window */ + error = xwimp_delete_window(dw->window); + if (error) { + LOG("xwimp_delete_window: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + ro_gui_wimp_event_finalise(dw->window); + + /* close download file */ + if (dw->file) { + error = xosfind_closew(dw->file); + if (error) { + LOG("xosfind_closew: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("SaveError", error->errmess); + } + } + + /* delete temporary file */ + if (!dw->saved) { + const char *temp_name = ro_gui_download_temp_name(dw); + + error = xosfile_delete(temp_name, 0, 0, 0, 0, 0); + if (error) { + LOG("xosfile_delete: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("SaveError", error->errmess); + } + } + + if (dw->ctx) { + download_context_abort(dw->ctx); + download_context_destroy(dw->ctx); + } + + free(dw); + + return true; +} + + +/** + * Wrapper for ro_gui_download_window_destroy(), suitable for riscos_schedule(). + */ + +void ro_gui_download_window_destroy_wrapper(void *p) +{ + struct gui_download_window *dw = p; + if (dw->query != QUERY_INVALID) + query_close(dw->query); + dw->query = QUERY_INVALID; + dw->close_confirmed = true; + ro_gui_download_window_destroy(dw, false); +} + + +/** + * User has opted to cancel the close, leaving the download to continue. + */ + +void ro_gui_download_close_cancelled(query_id id, enum query_response res, void *p) +{ + struct gui_download_window *dw = p; + dw->query = QUERY_INVALID; +} + + +/** + * Download aborted, close window and tidy up. + */ + +void ro_gui_download_close_confirmed(query_id id, enum query_response res, void *p) +{ + struct gui_download_window *dw = p; + dw->query = QUERY_INVALID; + dw->close_confirmed = true; + if (dw->query_rsn == QueryRsn_Quit) { + + /* destroy all our downloads */ + while (download_window_list) + ro_gui_download_window_destroy_wrapper(download_window_list); + + /* and restart the shutdown */ + if (ro_gui_prequit()) + riscos_done = true; + } + else + ro_gui_download_window_destroy(dw, false); +} + + +/** + * User has opted not to overwrite the existing file. + */ + +void ro_gui_download_overwrite_cancelled(query_id id, enum query_response res, void *p) +{ + struct gui_download_window *dw = p; + dw->query = QUERY_INVALID; +} + + +/** + * Overwrite of existing file confirmed, proceed with the save. + */ + +void ro_gui_download_overwrite_confirmed(query_id id, enum query_response res, void *p) +{ + struct gui_download_window *dw = p; + dw->query = QUERY_INVALID; + + if (!ro_gui_download_save(dw, dw->save_message.data.data_xfer.file_name, true)) + return; + + if (!dw->ctx) { + /* Ack successful completed save with message_DATA_LOAD immediately + to reduce the chance of the target app getting confused by it + being delayed */ + + ro_gui_download_send_dataload(dw); + + riscos_schedule(2000, ro_gui_download_window_destroy_wrapper, dw); + } +} + + +/** + * Respond to PreQuit message, displaying a prompt message if we need + * the user to confirm the shutdown. + * + * \return true if we can shutdown straightaway + */ + +bool ro_gui_download_prequit(void) +{ + while (download_window_list) + { + if (!ro_gui_download_window_destroy(download_window_list, true)) + return false; /* awaiting user confirmation */ + } + return true; +} + +static struct gui_download_table download_table = { + .create = gui_download_window_create, + .data = gui_download_window_data, + .error = gui_download_window_error, + .done = gui_download_window_done, +}; + +struct gui_download_table *riscos_download_table = &download_table; diff --git a/frontends/riscos/filetype.c b/frontends/riscos/filetype.c new file mode 100644 index 000000000..99a44ae30 --- /dev/null +++ b/frontends/riscos/filetype.c @@ -0,0 +1,352 @@ +/* + * Copyright 2004 James Bursa <bursa@users.sourceforge.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <string.h> +#include <unixlib/local.h> +#include "oslib/mimemap.h" +#include "oslib/osfile.h" + +#include "utils/config.h" +#include "utils/log.h" +#include "content/content.h" +#include "content/fetch.h" +#include "content/hlcache.h" + +#include "riscos/filetype.h" +#include "riscos/gui.h" + +/* type_map must be in sorted order by file_type */ +struct type_entry { + bits file_type; + char mime_type[40]; +}; +static const struct type_entry type_map[] = { + {0x132, "image/ico"}, + {0x188, "application/x-shockwave-flash"}, + {0x695, "image/gif"}, + {0x69c, "image/x-ms-bmp"}, + {0xaad, "image/svg+xml"}, + {0xaff, "image/x-drawfile"}, + {0xb60, "image/png"}, + {0xc85, "image/jpeg"}, + {0xd94, "image/x-artworks"}, + {0xf78, "image/jng"}, + {0xf79, "text/css"}, + {0xf81, "application/javascript"}, + {0xf83, "image/mng"}, + {0xfaf, "text/html"}, + {0xff9, "image/x-riscos-sprite"}, + {0xfff, "text/plain"}, +}; +#define TYPE_MAP_COUNT (sizeof(type_map) / sizeof(type_map[0])) + +#define BUF_SIZE (256) +static char type_buf[BUF_SIZE]; + + +static int cmp_type(const void *x, const void *y); + +/* exported interface documented in riscos/filetype.h */ +const char *fetch_filetype(const char *unix_path) +{ + struct type_entry *t; + unsigned int len = strlen(unix_path) + 100; + char *path = calloc(len, 1); + char *r; + os_error *error; + bits file_type, temp; + int objtype; + + if (!path) { + LOG("Insufficient memory for calloc"); + ro_warn_user("NoMemory", 0); + return "application/riscos"; + } + + /* convert path to RISC OS format and read file type */ + r = __riscosify(unix_path, 0, __RISCOSIFY_NO_SUFFIX, path, len, 0); + if (r == 0) { + LOG("__riscosify failed"); + free(path); + return "application/riscos"; + } + + error = xosfile_read_stamped_no_path(path, &objtype, 0, 0, 0, 0, + &file_type); + if (error) { + LOG("xosfile_read_stamped_no_path failed: %s", error->errmess); + free(path); + return "application/riscos"; + } + + if (objtype == osfile_IS_DIR) { + sprintf(type_buf, "application/x-netsurf-directory"); + free(path); + return (const char *)type_buf; + } + + /* If filetype is text or data, and the file has an extension, try to + * map the extension to a filetype via the MimeMap file. */ + if (file_type == osfile_TYPE_TEXT || file_type == osfile_TYPE_DATA) { + char *slash = strrchr(path, '/'); + if (slash) { + error = xmimemaptranslate_extension_to_filetype( + slash+1, &temp); + if (error) + /* ignore error and leave file_type alone */ + LOG("xmimemaptranslate_extension_to_filetype: ""0x%x %s", error->errnum, error->errmess); + else + file_type = temp; + } + } + + /* search for MIME type in our internal table */ + t = bsearch(&file_type, type_map, TYPE_MAP_COUNT, + sizeof(type_map[0]), cmp_type); + if (t) { + /* found, so return it */ + free(path); + return t->mime_type; + } + + /* not in internal table, so ask MimeMap */ + error = xmimemaptranslate_filetype_to_mime_type(file_type, type_buf); + if (error) { + LOG("0x%x %s", error->errnum, error->errmess); + free(path); + return "application/riscos"; + } + /* make sure we're NULL terminated. If we're not, the MimeMap + * module's probably written past the end of the buffer from + * SVC mode. Short of rewriting MimeMap with an incompatible API, + * there's nothing we can do about it. + */ + type_buf[BUF_SIZE - 1] = '\0'; + + free(path); + + LOG("mime type '%s'", type_buf); + return (const char *)type_buf; + +} + +/* exported interface documented in riscos/filetype.h */ +char *fetch_mimetype(const char *ro_path) +{ + os_error *e; + bits filetype = 0, load; + int objtype; + char *mime = calloc(BUF_SIZE, sizeof(char)); + char *slash; + struct type_entry *t; + + if (!mime) { + LOG("Insufficient memory for calloc"); + ro_warn_user("NoMemory", 0); + return 0; + } + + e = xosfile_read_no_path(ro_path, &objtype, &load, 0, 0, 0); + if (e) { + LOG("xosfile_read_no_path: 0x%x: %s", e->errnum, e->errmess); + free(mime); + return 0; + } + + if (objtype == osfile_IS_DIR) { + free(mime); + return 0; /* directories are pointless */ + } + + if ((load >> 20) & 0xFFF) { + filetype = (load>>8) & 0x000FFF; + } + else { + free(mime); + return 0; /* no idea */ + } + + /* If filetype is text and the file has an extension, try to map the + * extension to a filetype via the MimeMap file. */ + slash = strrchr(ro_path, '/'); + if (slash && filetype == osfile_TYPE_TEXT) { + e = xmimemaptranslate_extension_to_filetype(slash+1, &load); + if (e) + /* if we get an error here, simply ignore it and + * leave filetype unchanged */ + LOG("0x%x %s", e->errnum, e->errmess); + else + filetype = load; + } + + /* search for MIME type in our internal table */ + t = bsearch(&filetype, type_map, TYPE_MAP_COUNT, + sizeof(type_map[0]), cmp_type); + if (t) { + /* found, so return it */ + strncpy(mime, t->mime_type, BUF_SIZE); + return mime; + } + + /* not in internal table, so ask MimeMap */ + e = xmimemaptranslate_filetype_to_mime_type(filetype, mime); + if (e) { + LOG("xmimemaptranslate_filetype_to_mime_type: 0x%x: %s", e->errnum, e->errmess); + free(mime); + return 0; + } + /* make sure we're NULL terminated. If we're not, the MimeMap + * module's probably written past the end of the buffer from + * SVC mode. Short of rewriting MimeMap with an incompatible API, + * there's nothing we can do about it. + */ + mime[BUF_SIZE - 1] = '\0'; + + return mime; +} + +/** + * Comparison function for bsearch + */ +int cmp_type(const void *x, const void *y) +{ + const bits *p = x; + const struct type_entry *q = y; + return *p < q->file_type ? -1 : (*p == q->file_type ? 0 : +1); +} + +/* exported interface documented in riscos/filetype.h */ +int ro_content_filetype(hlcache_handle *c) +{ + lwc_string *mime_type; + int file_type; + + file_type = ro_content_filetype_from_type(content_get_type(c)); + if (file_type != 0) + return file_type; + + mime_type = content_get_mime_type(c); + + file_type = ro_content_filetype_from_mime_type(mime_type); + + lwc_string_unref(mime_type); + + return file_type; +} + + +/* exported interface documented in riscos/filetype.h */ +int ro_content_native_type(hlcache_handle *c) +{ + switch (ro_content_filetype(c)) { + case FILETYPE_JPEG: /* jpeg */ + case FILETYPE_JNG: /* jng */ + case FILETYPE_MNG: /* mng */ + case FILETYPE_GIF: /* gif */ + case FILETYPE_BMP: /* bmp */ + case FILETYPE_ICO: /* ico */ + case FILETYPE_PNG: /* png */ + case 0xff9: /* sprite */ + return osfile_TYPE_SPRITE; + case FILETYPE_SVG: /* svg */ + case 0xaff: /* draw */ + return osfile_TYPE_DRAW; + default: + break; + } + + return osfile_TYPE_DATA; +} + + +/* exported interface documented in riscos/filetype.h */ +int ro_content_filetype_from_mime_type(lwc_string *mime_type) +{ + int file_type, index; + os_error *error; + + /* Search internal type map */ + for (index = TYPE_MAP_COUNT; index > 0; index--) { + const struct type_entry *e = &type_map[index - 1]; + + if (strlen(e->mime_type) == lwc_string_length(mime_type) && + strncasecmp(e->mime_type, + lwc_string_data(mime_type), + lwc_string_length(mime_type)) == 0) + return e->file_type; + } + + /* Ask MimeMap module */ + error = xmimemaptranslate_mime_type_to_filetype( + lwc_string_data(mime_type), (bits *) &file_type); + if (error) + file_type = 0xffd; + + return file_type; +} + + +/* exported interface documented in riscos/filetype.h */ +int ro_content_filetype_from_type(content_type type) { + switch (type) { + case CONTENT_HTML: return FILETYPE_HTML; + case CONTENT_TEXTPLAIN: return 0xfff; + case CONTENT_CSS: return 0xf79; + default: break; + } + return 0; +} + + +/* exported interface documented in riscos/filetype.h */ +bits ro_filetype_from_unix_path(const char *unix_path) +{ + unsigned int len = strlen(unix_path) + 100; + char *path = calloc(len, 1); + char *r; + os_error *error; + bits file_type; + + if (!path) { + LOG("Insufficient memory for calloc"); + ro_warn_user("NoMemory", 0); + return osfile_TYPE_DATA; + } + + /* convert path to RISC OS format and read file type */ + r = __riscosify(unix_path, 0, __RISCOSIFY_NO_SUFFIX, path, len, 0); + if (r == 0) { + LOG("__riscosify failed"); + free(path); + return osfile_TYPE_DATA; + } + + error = xosfile_read_stamped_no_path(path, 0, 0, 0, 0, 0, + &file_type); + if (error) { + LOG("xosfile_read_stamped_no_path failed: %s", error->errmess); + free(path); + return osfile_TYPE_DATA; + } + + free(path); + + return file_type; +} + diff --git a/frontends/riscos/filetype.h b/frontends/riscos/filetype.h new file mode 100644 index 000000000..3ba613033 --- /dev/null +++ b/frontends/riscos/filetype.h @@ -0,0 +1,128 @@ +/* + * Copyright 2014 Vincent Sanders <vince@netsurf-browser.org> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file riscos/filetype.h + * RISC OS filetpe interface. + */ + +#ifndef _NETSURF_RISCOS_FILETYPE_H_ +#define _NETSURF_RISCOS_FILETYPE_H_ + +#include "content/content_type.h" + +#ifndef FILETYPE_ACORN_URI +#define FILETYPE_ACORN_URI 0xf91 +#endif +#ifndef FILETYPE_ANT_URL +#define FILETYPE_ANT_URL 0xb28 +#endif +#ifndef FILETYPE_IEURL +#define FILETYPE_IEURL 0x1ba +#endif +#ifndef FILETYPE_HTML +#define FILETYPE_HTML 0xfaf +#endif +#ifndef FILETYPE_JNG +#define FILETYPE_JNG 0xf78 +#endif +#ifndef FILETYPE_CSS +#define FILETYPE_CSS 0xf79 +#endif +#ifndef FILETYPE_MNG +#define FILETYPE_MNG 0xf83 +#endif +#ifndef FILETYPE_GIF +#define FILETYPE_GIF 0x695 +#endif +#ifndef FILETYPE_BMP +#define FILETYPE_BMP 0x69c +#endif +#ifndef FILETYPE_ICO +#define FILETYPE_ICO 0x132 +#endif +#ifndef FILETYPE_PNG +#define FILETYPE_PNG 0xb60 +#endif +#ifndef FILETYPE_JPEG +#define FILETYPE_JPEG 0xc85 +#endif +#ifndef FILETYPE_ARTWORKS +#define FILETYPE_ARTWORKS 0xd94 +#endif +#ifndef FILETYPE_SVG +#define FILETYPE_SVG 0xaad +#endif + +/** + * Determine the MIME type of a local file. + * + * \param unix_path Unix style path to file on disk + * \return Pointer to MIME type string (should not be freed) - invalidated + * on next call to fetch_filetype. + */ +const char *fetch_filetype(const char *unix_path); + +/** + * Find a MIME type for a local file + * + * \param ro_path RISC OS style path to file on disk + * \return MIME type string (on heap, caller should free), or NULL + */ +char *fetch_mimetype(const char *ro_path); + +/** + * Determine the RISC OS filetype for a content. + * + * \param h The handle of the content to examine. + * \return The RISC OS filetype corresponding to the content + */ +int ro_content_filetype(struct hlcache_handle *h); + +/** + * Determine the native RISC OS filetype to export a content as + * + * \param c The content to examine + * \return Native RISC OS filetype for export + */ +int ro_content_native_type(struct hlcache_handle *c); + +/** + * Determine the RISC OS filetype for a MIME type + * + * \param mime_type MIME type to consider + * \return Corresponding RISC OS filetype + */ +int ro_content_filetype_from_mime_type(lwc_string *mime_type); + +/** + * Determine the RISC OS filetype from a content type. + * + * \param type The content type to examine. + * \return The RISC OS filetype corresponding to the content, or 0 for unknown + */ +int ro_content_filetype_from_type(content_type type); + +/** + * Determine the type of a local file. + * + * \param unix_path Unix style path to file on disk + * \return File type + */ +bits ro_filetype_from_unix_path(const char *unix_path); + +#endif diff --git a/frontends/riscos/font.c b/frontends/riscos/font.c new file mode 100644 index 000000000..2f2ba9a35 --- /dev/null +++ b/frontends/riscos/font.c @@ -0,0 +1,598 @@ +/* + * Copyright 2006 James Bursa <bursa@users.sourceforge.net> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * \file + * RISC OS implementation of Font handling. + * + * The RUfl is used to handle and render fonts. + */ + +#include "utils/config.h" + +#include <assert.h> +#include <string.h> +#include <oslib/wimp.h> +#include <oslib/wimpreadsysinfo.h> + +#include "utils/nsoption.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/utils.h" +#include "desktop/gui_layout.h" + +#include "riscos/gui.h" +#include "riscos/font.h" + + +/** desktop font, size and style being used */ +char ro_gui_desktop_font_family[80]; +int ro_gui_desktop_font_size = 12; +rufl_style ro_gui_desktop_font_style = rufl_WEIGHT_400; +bool no_font_blending = false; + + +/** + * Check that at least Homerton.Medium is available. + */ +static void nsfont_check_fonts(void) +{ + char s[252]; + font_f font; + os_error *error; + + error = xfont_find_font("Homerton.Medium\\ELatin1", + 160, 160, 0, 0, &font, 0, 0); + if (error) { + if (error->errnum == error_FILE_NOT_FOUND) { + xwimp_start_task("TaskWindow -wimpslot 200K -quit " + "<NetSurf$Dir>.FixFonts", 0); + die("FontBadInst"); + } else { + LOG("xfont_find_font: 0x%x: %s", error->errnum, error->errmess); + snprintf(s, sizeof s, messages_get("FontError"), + error->errmess); + die(s); + } + } + + error = xfont_lose_font(font); + if (error) { + LOG("xfont_lose_font: 0x%x: %s", error->errnum, error->errmess); + snprintf(s, sizeof s, messages_get("FontError"), + error->errmess); + die(s); + } +} + + +/** + * Check that a font option is valid, and fix it if not. + * + * \param option pointer to option, as used by options.[ch] + * \param family font family to use if option is not set, or the set + * family is not available + * \param fallback font family to use if family is not available either + */ +static void nsfont_check_option(char **option, const char *family, + const char *fallback) +{ + if (*option && !nsfont_exists(*option)) { + free(*option); + *option = 0; + } + if (!*option) { + if (nsfont_exists(family)) + *option = strdup(family); + else + *option = strdup(fallback); + } +} + + +/** + * Initialize font handling. + * + * Exits through die() on error. + */ +void nsfont_init(void) +{ + const char *fallback; + rufl_code code; + + nsfont_check_fonts(); + + LOG("Initialise RUfl"); + code = rufl_init(); + if (code != rufl_OK) { + if (code == rufl_FONT_MANAGER_ERROR) + LOG("rufl_init: rufl_FONT_MANAGER_ERROR: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); + else + LOG("rufl_init: 0x%x", code); + die("The Unicode font library could not be initialized. " + "Please report this to the developers."); + } + LOG("RUfl initialised"); + + if (rufl_family_list_entries == 0) + die("No fonts could be found. At least one font must be " + "installed."); + + fallback = nsfont_fallback_font(); + + nsfont_check_option(&nsoption_charp(font_sans), "Homerton", fallback); + nsfont_check_option(&nsoption_charp(font_serif), "Trinity", fallback); + nsfont_check_option(&nsoption_charp(font_mono), "Corpus", fallback); + nsfont_check_option(&nsoption_charp(font_cursive), "Churchill", fallback); + nsfont_check_option(&nsoption_charp(font_fantasy), "Sassoon", fallback); + + if (nsoption_int(font_default) != PLOT_FONT_FAMILY_SANS_SERIF && + nsoption_int(font_default) != PLOT_FONT_FAMILY_SERIF && + nsoption_int(font_default) != PLOT_FONT_FAMILY_MONOSPACE && + nsoption_int(font_default) != PLOT_FONT_FAMILY_CURSIVE && + nsoption_int(font_default) != PLOT_FONT_FAMILY_FANTASY) { + nsoption_set_int(font_default, PLOT_FONT_FAMILY_SANS_SERIF); + } +} + + +/** + * Retrieve the fallback font name + * + * \return Fallback font name + */ +const char *nsfont_fallback_font(void) +{ + const char *fallback = "Homerton"; + + if (!nsfont_exists(fallback)) { + LOG("Homerton not found, dumping RUfl family list"); + for (unsigned int i = 0; i < rufl_family_list_entries; i++) { + LOG("'%s'", rufl_family_list[i]); + } + fallback = rufl_family_list[0]; + } + + return fallback; +} + + +/** + * bsearch comparison routine + */ +static int nsfont_list_cmp(const void *keyval, const void *datum) +{ + const char *key = keyval; + const char * const *entry = datum; + return strcasecmp(key, *entry); +} + + +/** + * Check if a font family is available. + * + * \param font_family name of font family + * \return true if the family is available + */ +bool nsfont_exists(const char *font_family) +{ + if (bsearch(font_family, rufl_family_list, + rufl_family_list_entries, sizeof rufl_family_list[0], + nsfont_list_cmp)) + return true; + return false; +} + + +/** + * Measure the width of a string. + * + * \param fstyle plot style for this text + * \param string UTF-8 string to measure + * \param length length of string + * \param width updated to width of string[0..length) + * \return true on success, false on error and error reported + */ +static nserror +ro_font_width(const plot_font_style_t *fstyle, + const char *string, size_t length, + int *width) +{ + const char *font_family; + unsigned int font_size; + rufl_style font_style; + rufl_code code; + + nsfont_read_style(fstyle, &font_family, &font_size, &font_style); + if (font_size == 0) { + *width = 0; + return NSERROR_OK; + } + + code = rufl_width(font_family, font_style, font_size, + string, length, + width); + if (code != rufl_OK) { + if (code == rufl_FONT_MANAGER_ERROR) + LOG("rufl_width: rufl_FONT_MANAGER_ERROR: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); + else + LOG("rufl_width: 0x%x", code); +/* ro_warn_user("MiscError", "font error"); */ + *width = 0; + return NSERROR_INVALID; + } + + *width /= 2; + return NSERROR_OK; +} + + +/** + * Find the position in a string where an x coordinate falls. + * + * \param fstyle style for this text + * \param string UTF-8 string to measure + * \param length length of string + * \param x x coordinate to search for + * \param char_offset updated to offset in string of actual_x, [0..length] + * \param actual_x updated to x coordinate of character closest to x + * \return true on success, false on error and error reported + */ +static nserror +ro_font_position(const plot_font_style_t *fstyle, + const char *string, size_t length, + int x, size_t *char_offset, int *actual_x) +{ + const char *font_family; + unsigned int font_size; + rufl_style font_style; + rufl_code code; + + nsfont_read_style(fstyle, &font_family, &font_size, &font_style); + if (font_size == 0) { + *char_offset = 0; + *actual_x = 0; + return NSERROR_OK; + } + + code = rufl_x_to_offset(font_family, font_style, font_size, + string, length, + x * 2, char_offset, actual_x); + if (code != rufl_OK) { + if (code == rufl_FONT_MANAGER_ERROR) + LOG("rufl_x_to_offset: rufl_FONT_MANAGER_ERROR: ""0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); + else + LOG("rufl_x_to_offset: 0x%x", code); +/* ro_warn_user("MiscError", "font error"); */ + *char_offset = 0; + *actual_x = 0; + return NSERROR_INVALID; + } + + *actual_x /= 2; + + return NSERROR_OK; +} + + +/** + * Find where to split a string to make it fit a width. + * + * \param fstyle style for this text + * \param string UTF-8 string to measure + * \param length length of string, in bytes + * \param x width available + * \param char_offset updated to offset in string of actual_x, [1..length] + * \param actual_x updated to x coordinate of character closest to x + * \return true on success, false on error and error reported + * + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible + */ +static nserror +ro_font_split(const plot_font_style_t *fstyle, + const char *string, size_t length, + int x, size_t *char_offset, int *actual_x) +{ + const char *font_family; + unsigned int font_size; + rufl_style font_style; + rufl_code code; + + nsfont_read_style(fstyle, &font_family, &font_size, &font_style); + if (font_size == 0) { + *char_offset = 0; + *actual_x = 0; + return NSERROR_OK; + } + + code = rufl_split(font_family, font_style, font_size, + string, length, + x * 2, char_offset, actual_x); + if (code != rufl_OK) { + if (code == rufl_FONT_MANAGER_ERROR) { + LOG("rufl_split: rufl_FONT_MANAGER_ERROR: ""0x%x: %s", + rufl_fm_error->errnum, rufl_fm_error->errmess); + } else { + LOG("rufl_split: 0x%x", code); + } +/* ro_warn_user("MiscError", "font error"); */ + *char_offset = 0; + *actual_x = 0; + return NSERROR_INVALID; + } + + if (*char_offset != length) { + /* we found something to split at */ + size_t orig = *char_offset; + + /* ensure a space at <= the split point we found */ + while (*char_offset && string[*char_offset] != ' ') { + (*char_offset)--; + } + + /* nothing valid found <= split point, advance to next space */ + if (*char_offset == 0) { + *char_offset = orig; + while ((*char_offset != length) && + (string[*char_offset] != ' ')) { + (*char_offset)++; + } + } + } + + code = rufl_width(font_family, font_style, font_size, + string, *char_offset, + actual_x); + if (code != rufl_OK) { + if (code == rufl_FONT_MANAGER_ERROR) { + LOG("rufl_width: rufl_FONT_MANAGER_ERROR: 0x%x: %s", + rufl_fm_error->errnum, rufl_fm_error->errmess); + } else { + LOG("rufl_width: 0x%x", code); + } +/* ro_warn_user("MiscError", "font error"); */ + *char_offset = 0; + *actual_x = 0; + return NSERROR_INVALID; + } + + *actual_x /= 2; + return NSERROR_OK; +} + + +/** + * Paint a string. + * + * \param fstyle plot style for this text + * \param string UTF-8 string to measure + * \param length length of string + * \param x x coordinate + * \param y y coordinate + * \return true on success, false on error and error reported + */ +bool nsfont_paint(const plot_font_style_t *fstyle, const char *string, + size_t length, int x, int y) +{ + const char *font_family; + unsigned int font_size; + unsigned int flags = rufl_BLEND_FONT; + rufl_style font_style; + rufl_code code; + + nsfont_read_style(fstyle, &font_family, &font_size, &font_style); + if (font_size == 0) + return true; + + if (no_font_blending || print_active) + flags = 0; + + code = rufl_paint(font_family, font_style, font_size, + string, length, x, y, flags); + if (code != rufl_OK) { + if (code == rufl_FONT_MANAGER_ERROR) { + LOG("rufl_paint: rufl_FONT_MANAGER_ERROR: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); + } else { + LOG("rufl_paint: 0x%x", code); + } + } + + return true; +} + + +/** + * Convert a font style to a font family, size and rufl_style. + * + * \param fstyle plot style for this text + * \param font_family updated to font family + * \param font_size updated to font size + * \param font_style updated to font style + */ +void nsfont_read_style(const plot_font_style_t *fstyle, + const char **font_family, unsigned int *font_size, + rufl_style *font_style) +{ + static const rufl_style weight_table[] = { + rufl_WEIGHT_100, + rufl_WEIGHT_200, + rufl_WEIGHT_300, + rufl_WEIGHT_400, + rufl_WEIGHT_500, + rufl_WEIGHT_600, + rufl_WEIGHT_700, + rufl_WEIGHT_800, + rufl_WEIGHT_900 + }; + + *font_size = (fstyle->size * 16) / FONT_SIZE_SCALE; + if (1600 < *font_size) + *font_size = 1600; + + switch (fstyle->family) { + case PLOT_FONT_FAMILY_SANS_SERIF: + *font_family = nsoption_charp(font_sans); + break; + case PLOT_FONT_FAMILY_SERIF: + *font_family = nsoption_charp(font_serif); + break; + case PLOT_FONT_FAMILY_MONOSPACE: + *font_family = nsoption_charp(font_mono); + break; + case PLOT_FONT_FAMILY_CURSIVE: + *font_family = nsoption_charp(font_cursive); + break; + case PLOT_FONT_FAMILY_FANTASY: + *font_family = nsoption_charp(font_fantasy); + break; + default: + *font_family = nsoption_charp(font_sans); + break; + } + + if ((fstyle->flags & FONTF_ITALIC) || (fstyle->flags & FONTF_OBLIQUE)) { + *font_style = rufl_SLANTED; + } else { + *font_style = 0; + } + + *font_style |= weight_table[(fstyle->weight / 100) - 1]; +} + + +/** + * Looks up the current desktop font and converts that to a family name, + * font size and style flags suitable for passing directly to rufl + * + * \param family buffer to receive font family + * \param family_size buffer size + * \param psize receives the font size in 1/16 points + * \param pstyle receives the style settings to be passed to rufl + */ +static void +ro_gui_wimp_desktop_font(char *family, + size_t family_size, + int *psize, + rufl_style *pstyle) +{ + rufl_style style = rufl_WEIGHT_400; + os_error *error; + int ptx, pty; + font_f font_handle; + int used; + + assert(family); + assert(20 < family_size); + assert(psize); + assert(pstyle); + + error = xwimpreadsysinfo_font(&font_handle, NULL); + if (error) { + LOG("xwimpreadsysinfo_font: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + goto failsafe; + } + + if (font_handle == font_SYSTEM) { + /* Er, yeah; like that's ever gonna work with RUfl */ + goto failsafe; + } + + error = xfont_read_identifier(font_handle, NULL, &used); + if (error) { + LOG("xfont_read_identifier: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("MiscError", error->errmess); + goto failsafe; + } + + if (family_size < (size_t) used + 1) { + LOG("desktop font name too long"); + goto failsafe; + } + + error = xfont_read_defn(font_handle, (byte *) family, + &ptx, &pty, NULL, NULL, NULL, NULL); + if (error) { + LOG("xfont_read_defn: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("MiscError", error->errmess); + goto failsafe; + } + + for (size_t i = 0; i != (size_t) used; i++) { + if (family[i] < ' ') { + family[i] = 0; + break; + } + } + + LOG("desktop font \"%s\"", family); + + if (strcasestr(family, ".Medium")) + style = rufl_WEIGHT_500; + else if (strcasestr(family, ".Bold")) + style = rufl_WEIGHT_700; + if (strcasestr(family, ".Italic") || strcasestr(family, ".Oblique")) + style |= rufl_SLANTED; + + char *dot = strchr(family, '.'); + if (dot) + *dot = 0; + + *psize = max(ptx, pty); + *pstyle = style; + + LOG("family \"%s\", size %i, style %i", family, *psize, style); + + return; + +failsafe: + strcpy(family, "Homerton"); + *psize = 12*16; + *pstyle = rufl_WEIGHT_400; +} + + +/** + * Retrieve the current desktop font family, size and style from + * the WindowManager in a form suitable for passing to rufl + */ +void ro_gui_wimp_get_desktop_font(void) +{ + ro_gui_wimp_desktop_font(ro_gui_desktop_font_family, + sizeof(ro_gui_desktop_font_family), + &ro_gui_desktop_font_size, + &ro_gui_desktop_font_style); +} + + +static struct gui_layout_table layout_table = { + .width = ro_font_width, + .position = ro_font_position, + .split = ro_font_split, +}; + +struct gui_layout_table *riscos_layout_table = &layout_table; diff --git a/frontends/riscos/font.h b/frontends/riscos/font.h new file mode 100644 index 000000000..0319a7ee3 --- /dev/null +++ b/frontends/riscos/font.h @@ -0,0 +1,45 @@ +/* + * Copyright 2014 Vincent Sanders <vince@netsurf-browser.org> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file riscos/font.h + * RISC OS font interface. + */ + +#ifndef _NETSURF_RISCOS_FONT_H_ +#define _NETSURF_RISCOS_FONT_H_ + +#include <rufl.h> + +struct gui_layout_table *riscos_layout_table; + +/** desktop font, size and style being used */ +extern char ro_gui_desktop_font_family[]; +extern int ro_gui_desktop_font_size; +extern rufl_style ro_gui_desktop_font_style; + +void nsfont_init(void); +bool nsfont_exists(const char *font_family); +const char *nsfont_fallback_font(void); +bool nsfont_paint(const plot_font_style_t *fstyle, const char *string, + size_t length, int x, int y); +void nsfont_read_style(const plot_font_style_t *fstyle, + const char **font_family, unsigned int *font_size, + rufl_style *font_style); +void ro_gui_wimp_get_desktop_font(void); + +#endif diff --git a/frontends/riscos/global_history.c b/frontends/riscos/global_history.c new file mode 100644 index 000000000..c469847e0 --- /dev/null +++ b/frontends/riscos/global_history.c @@ -0,0 +1,413 @@ +/* + * Copyright 2005 Richard Wilson <info@tinct.net> + * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * Global history (implementation). + */ + +#include <assert.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "oslib/wimp.h" +#include "oslib/wimpspriteop.h" + +#include "content/urldb.h" +#include "utils/nsoption.h" +#include "utils/messages.h" +#include "utils/log.h" +#include "desktop/global_history.h" +#include "desktop/tree.h" +#include "desktop/gui_window.h" + +#include "riscos/dialog.h" +#include "riscos/global_history.h" +#include "riscos/gui.h" +#include "riscos/menus.h" +#include "riscos/save.h" +#include "riscos/toolbar.h" +#include "riscos/treeview.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" + +static void ro_gui_global_history_toolbar_update_buttons(void); +static void ro_gui_global_history_toolbar_save_buttons(char *config); +static bool ro_gui_global_history_menu_prepare(wimp_w w, wimp_i i, + wimp_menu *menu, wimp_pointer *pointer); +static void ro_gui_global_history_menu_warning(wimp_w w, wimp_i i, + wimp_menu *menu, wimp_selection *selection, menu_action action); +static bool ro_gui_global_history_menu_select(wimp_w w, wimp_i i, + wimp_menu *menu, wimp_selection *selection, menu_action action); +static void ro_gui_global_history_toolbar_click(button_bar_action action); + +struct ro_treeview_callbacks ro_global_history_treeview_callbacks = { + ro_gui_global_history_toolbar_click, + ro_gui_global_history_toolbar_update_buttons, + ro_gui_global_history_toolbar_save_buttons +}; + +/* The RISC OS global history window, toolbar and treeview data */ + +static struct ro_global_history_window { + wimp_w window; + struct toolbar *toolbar; + ro_treeview *tv; + wimp_menu *menu; +} global_history_window; + +/** + * Pre-Initialise the global history tree. This is called for things that + * need to be done at the gui_init() stage, such as loading templates. + */ + +void ro_gui_global_history_preinitialise(void) +{ + /* Create our window. */ + + global_history_window.window = ro_gui_dialog_create("tree"); + ro_gui_set_window_title(global_history_window.window, + messages_get("GlobalHistory")); +} + +/** + * Initialise global history tree, at the gui_init2() stage. + */ + +void ro_gui_global_history_postinitialise(void) +{ + /* Create our toolbar. */ + + global_history_window.toolbar = ro_toolbar_create(NULL, + global_history_window.window, + THEME_STYLE_GLOBAL_HISTORY_TOOLBAR, TOOLBAR_FLAGS_NONE, + ro_treeview_get_toolbar_callbacks(), NULL, + "HelpGHistoryToolbar"); + if (global_history_window.toolbar != NULL) { + ro_toolbar_add_buttons(global_history_window.toolbar, + global_history_toolbar_buttons, + nsoption_charp(toolbar_history)); + ro_toolbar_rebuild(global_history_window.toolbar); + } + + /* Create the treeview with the window and toolbar. */ + + global_history_window.tv = + ro_treeview_create(global_history_window.window, + global_history_window.toolbar, + &ro_global_history_treeview_callbacks, + TREE_HISTORY); + if (global_history_window.tv == NULL) { + LOG("Failed to allocate treeview"); + return; + } + + ro_toolbar_update_client_data(global_history_window.toolbar, + global_history_window.tv); + + /* Build the global history window menu. */ + + static const struct ns_menu global_history_definition = { + "History", { + { "History", NO_ACTION, 0 }, + { "_History.Export", HISTORY_EXPORT, &dialog_saveas }, + { "History.Expand", TREE_EXPAND_ALL, 0 }, + { "History.Expand.All", TREE_EXPAND_ALL, 0 }, + { "History.Expand.Folders", TREE_EXPAND_FOLDERS, 0 }, + { "History.Expand.Links", TREE_EXPAND_LINKS, 0 }, + { "History.Collapse", TREE_COLLAPSE_ALL, 0 }, + { "History.Collapse.All", TREE_COLLAPSE_ALL, 0 }, + { "History.Collapse.Folders", TREE_COLLAPSE_FOLDERS, 0 }, + { "History.Collapse.Links", TREE_COLLAPSE_LINKS, 0 }, + { "History.Toolbars", NO_ACTION, 0 }, + { "_History.Toolbars.ToolButtons", TOOLBAR_BUTTONS, 0 }, + { "History.Toolbars.EditToolbar",TOOLBAR_EDIT, 0 }, + { "Selection", TREE_SELECTION, 0 }, + { "Selection.Launch", TREE_SELECTION_LAUNCH, 0 }, + { "Selection.Delete", TREE_SELECTION_DELETE, 0 }, + { "SelectAll", TREE_SELECT_ALL, 0 }, + { "Clear", TREE_CLEAR_SELECTION, 0 }, + {NULL, 0, 0} + } + }; + global_history_window.menu = ro_gui_menu_define_menu( + &global_history_definition); + + ro_gui_wimp_event_register_menu(global_history_window.window, + global_history_window.menu, false, false); + ro_gui_wimp_event_register_menu_prepare(global_history_window.window, + ro_gui_global_history_menu_prepare); + ro_gui_wimp_event_register_menu_selection(global_history_window.window, + ro_gui_global_history_menu_select); + ro_gui_wimp_event_register_menu_warning(global_history_window.window, + ro_gui_global_history_menu_warning); +} + +/** + * Destroy the global history window. + */ + +void ro_gui_global_history_destroy(void) +{ + if (global_history_window.tv == NULL) + return; + + ro_treeview_destroy(global_history_window.tv); +} + +/** + * Open the global history window. + */ + +void ro_gui_global_history_open(void) +{ + ro_gui_global_history_toolbar_update_buttons(); + + if (!ro_gui_dialog_open_top(global_history_window.window, + global_history_window.toolbar, 600, 800)) { + ro_treeview_set_origin(global_history_window.tv, 0, + -(ro_toolbar_height( + global_history_window.toolbar))); + } +} + +/** + * Handle toolbar button clicks. + * + * \param action The action to handle + */ + +void ro_gui_global_history_toolbar_click(button_bar_action action) +{ + switch (action) { + case TOOLBAR_BUTTON_DELETE: + global_history_keypress(NS_KEY_DELETE_LEFT); + break; + + case TOOLBAR_BUTTON_EXPAND: + global_history_expand(false); + break; + + case TOOLBAR_BUTTON_COLLAPSE: + global_history_contract(false); + break; + + case TOOLBAR_BUTTON_OPEN: + global_history_expand(true); + break; + + case TOOLBAR_BUTTON_CLOSE: + global_history_contract(true); + break; + + case TOOLBAR_BUTTON_LAUNCH: + global_history_keypress(NS_KEY_CR); + break; + + default: + break; + } +} + + +/** + * Update the button state in the global history toolbar. + */ + +void ro_gui_global_history_toolbar_update_buttons(void) +{ + ro_toolbar_set_button_shaded_state(global_history_window.toolbar, + TOOLBAR_BUTTON_DELETE, + !global_history_has_selection()); + + ro_toolbar_set_button_shaded_state(global_history_window.toolbar, + TOOLBAR_BUTTON_LAUNCH, + !global_history_has_selection()); +} + + +/** + * Save a new button arrangement in the global history toolbar. + * + * \param *config The new button configuration string. + */ + +void ro_gui_global_history_toolbar_save_buttons(char *config) +{ + nsoption_set_charp(toolbar_history, config); + ro_gui_save_options(); +} + + +/** + * Prepare the global history menu for opening + * + * \param w The window owning the menu. + * \param i The icon owning the menu. + * \param *menu The menu about to be opened. + * \param *pointer Pointer to the relevant wimp event block, or + * NULL for an Adjust click. + * \return true if the event was handled; else false. + */ + +bool ro_gui_global_history_menu_prepare(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_pointer *pointer) +{ + bool selection; + + if (menu != global_history_window.menu) + return false; + + selection = global_history_has_selection(); + + ro_gui_menu_set_entry_shaded(global_history_window.menu, + TREE_SELECTION, !selection); + ro_gui_menu_set_entry_shaded(global_history_window.menu, + TREE_CLEAR_SELECTION, !selection); + + ro_gui_save_prepare(GUI_SAVE_HISTORY_EXPORT_HTML, + NULL, NULL, NULL, NULL); + + ro_gui_menu_set_entry_shaded(menu, TOOLBAR_BUTTONS, + ro_toolbar_menu_option_shade( + global_history_window.toolbar)); + ro_gui_menu_set_entry_ticked(menu, TOOLBAR_BUTTONS, + ro_toolbar_menu_buttons_tick( + global_history_window.toolbar)); + + ro_gui_menu_set_entry_shaded(menu, TOOLBAR_EDIT, + ro_toolbar_menu_edit_shade( + global_history_window.toolbar)); + ro_gui_menu_set_entry_ticked(menu, TOOLBAR_EDIT, + ro_toolbar_menu_edit_tick( + global_history_window.toolbar)); + + return true; +} + +/** + * Handle submenu warnings for the global_hostory menu + * + * \param w The window owning the menu. + * \param i The icon owning the menu. + * \param *menu The menu to which the warning applies. + * \param *selection The wimp menu selection data. + * \param action The selected menu action. + */ + +void ro_gui_global_history_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action) +{ + /* Do nothing */ +} + +/** + * Handle selections from the global history menu + * + * \param w The window owning the menu. + * \param i The icon owning the menu. + * \param *menu The menu from which the selection was made. + * \param *selection The wimp menu selection data. + * \param action The selected menu action. + * \return true if action accepted; else false. + */ + +bool ro_gui_global_history_menu_select(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection, menu_action action) +{ + switch (action) { + case HISTORY_EXPORT: + ro_gui_dialog_open_persistent(w, dialog_saveas, true); + return true; + case TREE_EXPAND_ALL: + global_history_expand(false); + return true; + case TREE_EXPAND_FOLDERS: + global_history_expand(true); + return true; + case TREE_EXPAND_LINKS: + global_history_expand(false); + return true; + case TREE_COLLAPSE_ALL: + global_history_contract(true); + return true; + case TREE_COLLAPSE_FOLDERS: + global_history_contract(true); + return true; + case TREE_COLLAPSE_LINKS: + global_history_contract(false); + return true; + case TREE_SELECTION_LAUNCH: + global_history_keypress(NS_KEY_CR); + return true; + case TREE_SELECTION_DELETE: + global_history_keypress(NS_KEY_DELETE_LEFT); + return true; + case TREE_SELECT_ALL: + global_history_keypress(NS_KEY_SELECT_ALL); + return true; + case TREE_CLEAR_SELECTION: + global_history_keypress(NS_KEY_CLEAR_SELECTION); + return true; + case TOOLBAR_BUTTONS: + ro_toolbar_set_display_buttons(global_history_window.toolbar, + !ro_toolbar_get_display_buttons( + global_history_window.toolbar)); + return true; + case TOOLBAR_EDIT: + ro_toolbar_toggle_edit(global_history_window.toolbar); + return true; + default: + return false; + } + + return false; +} + +/** + * Check if a particular window handle is the global history window + * + * \param window the window in question + * \return true if this window is the global history + */ + +bool ro_gui_global_history_check_window(wimp_w window) +{ + if (global_history_window.window == window) + return true; + else + return false; +} + +/** + * Check if a particular menu handle is the global history menu + * + * \param *menu The menu in question. + * \return true if this menu is the global history menu + */ + +bool ro_gui_global_history_check_menu(wimp_menu *menu) +{ + if (global_history_window.menu == menu) + return true; + else + return false; +} + diff --git a/frontends/riscos/global_history.h b/frontends/riscos/global_history.h new file mode 100644 index 000000000..6f5ba11eb --- /dev/null +++ b/frontends/riscos/global_history.h @@ -0,0 +1,38 @@ +/* + * Copyright 2005 Richard Wilson <info@tinct.net> + * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * Global history (interface). + */ + +#ifndef _NETSURF_RISCOS_GLOBALHISTORY_H_ +#define _NETSURF_RISCOS_GLOBALHISTORY_H_ + +#include "riscos/menus.h" + +void ro_gui_global_history_preinitialise(void); +void ro_gui_global_history_postinitialise(void); +void ro_gui_global_history_destroy(void); +void ro_gui_global_history_open(void); +void ro_gui_global_history_save(void); +bool ro_gui_global_history_check_window(wimp_w window); +bool ro_gui_global_history_check_menu(wimp_menu *menu); + +#endif + diff --git a/frontends/riscos/gui.c b/frontends/riscos/gui.c new file mode 100644 index 000000000..309f27bdb --- /dev/null +++ b/frontends/riscos/gui.c @@ -0,0 +1,2522 @@ +/* + * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net> + * Copyright 2004-2008 James Bursa <bursa@users.sourceforge.net> + * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk> + * Copyright 2005 Richard Wilson <info@tinct.net> + * Copyright 2004 Andrew Timmins <atimmins@blueyonder.co.uk> + * Copyright 2004-2009 John Tytgat <joty@netsurf-browser.org> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include <string.h> +#include <assert.h> +#include <errno.h> +#include <signal.h> +#include <unixlib/local.h> +#include <fpu_control.h> +#include <oslib/help.h> +#include <oslib/uri.h> +#include <oslib/inetsuite.h> +#include <oslib/pdriver.h> +#include <oslib/osfile.h> +#include <oslib/hourglass.h> +#include <oslib/osgbpb.h> +#include <oslib/osbyte.h> +#include <oslib/osmodule.h> +#include <oslib/osfscontrol.h> + +#include "utils/utils.h" +#include "utils/nsoption.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/file.h" +#include "utils/filename.h" +#include "utils/url.h" +#include "utils/corestrings.h" +#include "desktop/gui_fetch.h" +#include "desktop/gui_misc.h" +#include "desktop/save_complete.h" +#include "desktop/treeview.h" +#include "desktop/netsurf.h" +#include "desktop/browser.h" +#include "content/urldb.h" +#include "content/hlcache.h" +#include "content/backing_store.h" + +#include "riscos/gui.h" +#include "riscos/bitmap.h" +#include "riscos/wimputils.h" +#include "riscos/hotlist.h" +#include "riscos/buffer.h" +#include "riscos/textselection.h" +#include "riscos/print.h" +#include "riscos/save.h" +#include "riscos/dialog.h" +#include "riscos/wimp.h" +#include "riscos/message.h" +#include "riscos/help.h" +#include "riscos/query.h" +#include "riscos/window.h" +#include "riscos/iconbar.h" +#include "riscos/sslcert.h" +#include "riscos/global_history.h" +#include "riscos/cookies.h" +#include "riscos/wimp_event.h" +#include "riscos/uri.h" +#include "riscos/url_protocol.h" +#include "riscos/mouse.h" +#include "riscos/ucstables.h" +#include "riscos/filetype.h" +#include "riscos/font.h" +#include "riscos/toolbar.h" +#include "riscos/content-handlers/artworks.h" +#include "riscos/content-handlers/draw.h" +#include "riscos/content-handlers/sprite.h" + +bool riscos_done = false; + +extern bool ro_plot_patterned_lines; + +int os_version = 0; + +const char * const __dynamic_da_name = "NetSurf"; /**< For UnixLib. */ +int __dynamic_da_max_size = 128 * 1024 * 1024; /**< For UnixLib. */ +int __feature_imagefs_is_file = 1; /**< For UnixLib. */ +/* default filename handling */ +int __riscosify_control = __RISCOSIFY_NO_SUFFIX | + __RISCOSIFY_NO_REVERSE_SUFFIX; +#ifndef __ELF__ +extern int __dynamic_num; +#endif + +const char * NETSURF_DIR; + +static const char *task_name = "NetSurf"; +#define CHOICES_PREFIX "<Choices$Write>.WWW.NetSurf." + +ro_gui_drag_type gui_current_drag_type; +wimp_t task_handle; /**< RISC OS wimp task handle. */ +static clock_t gui_last_poll; /**< Time of last wimp_poll. */ +osspriteop_area *gui_sprites; /**< Sprite area containing pointer and hotlist sprites */ + +#define DIR_SEP ('.') + +/** + * Accepted wimp user messages. + */ +static ns_wimp_message_list task_messages = { + message_HELP_REQUEST, + { + message_DATA_SAVE, + message_DATA_SAVE_ACK, + message_DATA_LOAD, + message_DATA_LOAD_ACK, + message_DATA_OPEN, + message_PRE_QUIT, + message_SAVE_DESKTOP, + message_MENU_WARNING, + message_MENUS_DELETED, + message_WINDOW_INFO, + message_CLAIM_ENTITY, + message_DATA_REQUEST, + message_DRAGGING, + message_DRAG_CLAIM, + message_MODE_CHANGE, + message_PALETTE_CHANGE, + message_FONT_CHANGED, + message_URI_PROCESS, + message_URI_RETURN_RESULT, + message_INET_SUITE_OPEN_URL, +#ifdef WITH_PLUGIN + message_PLUG_IN_OPENING, + message_PLUG_IN_CLOSED, + message_PLUG_IN_RESHAPE_REQUEST, + message_PLUG_IN_FOCUS, + message_PLUG_IN_URL_ACCESS, + message_PLUG_IN_STATUS, + message_PLUG_IN_BUSY, + message_PLUG_IN_STREAM_NEW, + message_PLUG_IN_STREAM_WRITE, + message_PLUG_IN_STREAM_WRITTEN, + message_PLUG_IN_STREAM_DESTROY, + message_PLUG_IN_OPEN, + message_PLUG_IN_CLOSE, + message_PLUG_IN_RESHAPE, + message_PLUG_IN_STREAM_AS_FILE, + message_PLUG_IN_NOTIFY, + message_PLUG_IN_ABORT, + message_PLUG_IN_ACTION, + /* message_PLUG_IN_INFORMED, (not provided by oslib) */ +#endif + message_PRINT_SAVE, + message_PRINT_ERROR, + message_PRINT_TYPE_ODD, + message_HOTLIST_ADD_URL, + message_HOTLIST_CHANGED, + 0 + } +}; + + +static struct +{ + int width; /* in OS units */ + int height; +} screen_info; + + +/** + * Callback to translate resource to full url for RISC OS. + * + * Transforms a resource: path into a full URL. The returned URL is + * used as the target for a redirect. The caller takes ownership of + * the returned nsurl including unrefing it when finished with it. + * + * \param path The path of the resource to locate. + * \return A string containing the full URL of the target object or + * NULL if no suitable resource can be found. + */ +static nsurl *gui_get_resource_url(const char *path) +{ + static const char base_url[] = "file:///NetSurf:/Resources/"; + size_t path_len, length; + char *raw; + nsurl *url = NULL; + + /* Map paths first */ + if (strcmp(path, "adblock.css") == 0) { + path = "AdBlock"; + + } else if (strcmp(path, "default.css") == 0) { + path = "CSS"; + + } else if (strcmp(path, "quirks.css") == 0) { + path = "Quirks"; + + } else if (strcmp(path, "favicon.ico") == 0) { + path = "Icons/content.png"; + + } else if (strcmp(path, "user.css") == 0) { + /* Special case; this file comes from Choices: */ + nsurl_create("file:///Choices:WWW/NetSurf/User", &url); + return url; + } + + path_len = strlen(path); + + /* Find max URL length */ + length = SLEN(base_url) + SLEN("xx/") + path_len + 1; + + raw = malloc(length); + if (raw != NULL) { + /* Insert base URL */ + char *ptr = memcpy(raw, base_url, SLEN(base_url)); + ptr += SLEN(base_url); + + /* Add language directory to URL, for translated files */ + /* TODO: handle non-en langauages + * handle non-html translated files */ + if (path_len > SLEN(".html") && + strncmp(path + path_len - SLEN(".html"), + ".html", SLEN(".html")) == 0) { + memcpy(ptr, "en/", SLEN("en/")); + ptr += SLEN("en/"); + } + + /* Add filename to URL */ + memcpy(ptr, path, path_len); + ptr += path_len; + + /* Terminate string */ + *ptr = '\0'; + + nsurl_create(raw, &url); + free(raw); + } + + return url; +} + + +/** + * Set colour option from wimp. + * + * \param opts The netsurf options. + * \param wimp wimp colour value + * \param option the netsurf option enum. + * \param def_colour The default colour value to use. + * \return NSERROR_OK on success or error code. + */ +static nserror +set_colour_from_wimp(struct nsoption_s *opts, + wimp_colour wimp, + enum nsoption_e option, + colour def_colour) +{ + os_error *error; + os_PALETTE(20) palette; + + error = xwimp_read_true_palette((os_palette *) &palette); + if (error != NULL) { + LOG("xwimp_read_palette: 0x%x: %s", + error->errnum, error->errmess); + } else { + /* entries are in B0G0R0LL */ + def_colour = palette.entries[wimp] >> 8; + } + + opts[option].value.c = def_colour; + + return NSERROR_OK; +} + + +/** + * Set option defaults for riscos frontend + * + * @param defaults The option table to update. + * @return error status. + * + * @todo The wimp_COLOUR_... values here map the colour definitions to + * parts of the RISC OS desktop palette. In places this is fairly + * arbitrary, and could probably do with re-checking. + */ +static nserror set_defaults(struct nsoption_s *defaults) +{ + /* Set defaults for absent option strings */ + nsoption_setnull_charp(ca_bundle, strdup("NetSurf:Resources.ca-bundle")); + nsoption_setnull_charp(cookie_file, strdup("NetSurf:Cookies")); + nsoption_setnull_charp(cookie_jar, strdup(CHOICES_PREFIX "Cookies")); + + if (nsoption_charp(ca_bundle) == NULL || + nsoption_charp(cookie_file) == NULL || + nsoption_charp(cookie_jar) == NULL) { + LOG("Failed initialising default options"); + return NSERROR_BAD_PARAMETER; + } + + /* RISC OS platform does not generally benefit from disc cache + * so the default should be off. + */ + nsoption_set_uint(disc_cache_size, 0); + + /* set default system colours for riscos ui */ + set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_ActiveBorder, 0x00000000); + set_colour_from_wimp(defaults, wimp_COLOUR_CREAM, NSOPTION_sys_colour_ActiveCaption, 0x00dddddd); + set_colour_from_wimp(defaults, wimp_COLOUR_VERY_LIGHT_GREY, NSOPTION_sys_colour_AppWorkspace, 0x00eeeeee); + set_colour_from_wimp(defaults, wimp_COLOUR_VERY_LIGHT_GREY, NSOPTION_sys_colour_Background, 0x00aa0000);/* \TODO -- Check */ + set_colour_from_wimp(defaults, wimp_COLOUR_VERY_LIGHT_GREY, NSOPTION_sys_colour_ButtonFace, 0x00aaaaaa); + set_colour_from_wimp(defaults, wimp_COLOUR_DARK_GREY, NSOPTION_sys_colour_ButtonHighlight, 0x00cccccc);/* \TODO -- Check */ + set_colour_from_wimp(defaults, wimp_COLOUR_MID_DARK_GREY, NSOPTION_sys_colour_ButtonShadow, 0x00bbbbbb); + set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_ButtonText, 0x00000000); + set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_CaptionText, 0x00000000); + set_colour_from_wimp(defaults, wimp_COLOUR_MID_LIGHT_GREY, NSOPTION_sys_colour_GrayText, 0x00777777);/* \TODO -- Check */ + set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_Highlight, 0x00ee0000); + set_colour_from_wimp(defaults, wimp_COLOUR_WHITE, NSOPTION_sys_colour_HighlightText, 0x00000000); + set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_InactiveBorder, 0x00000000); + set_colour_from_wimp(defaults, wimp_COLOUR_LIGHT_GREY, NSOPTION_sys_colour_InactiveCaption, 0x00ffffff); + set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_InactiveCaptionText, 0x00cccccc); + set_colour_from_wimp(defaults, wimp_COLOUR_CREAM, NSOPTION_sys_colour_InfoBackground, 0x00aaaaaa); + set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_InfoText, 0x00000000); + set_colour_from_wimp(defaults, wimp_COLOUR_WHITE, NSOPTION_sys_colour_Menu, 0x00aaaaaa); + set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_MenuText, 0x00000000); + set_colour_from_wimp(defaults, wimp_COLOUR_LIGHT_GREY, NSOPTION_sys_colour_Scrollbar, 0x00aaaaaa);/* \TODO -- Check */ + set_colour_from_wimp(defaults, wimp_COLOUR_MID_DARK_GREY, NSOPTION_sys_colour_ThreeDDarkShadow, 0x00555555); + set_colour_from_wimp(defaults, wimp_COLOUR_VERY_LIGHT_GREY, NSOPTION_sys_colour_ThreeDFace, 0x00dddddd); + set_colour_from_wimp(defaults, wimp_COLOUR_WHITE, NSOPTION_sys_colour_ThreeDHighlight, 0x00aaaaaa); + set_colour_from_wimp(defaults, wimp_COLOUR_WHITE, NSOPTION_sys_colour_ThreeDLightShadow, 0x00999999); + set_colour_from_wimp(defaults, wimp_COLOUR_MID_DARK_GREY, NSOPTION_sys_colour_ThreeDShadow, 0x00777777); + set_colour_from_wimp(defaults, wimp_COLOUR_VERY_LIGHT_GREY, NSOPTION_sys_colour_Window, 0x00aaaaaa); + set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_WindowFrame, 0x00000000); + set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_WindowText, 0x00000000); + + return NSERROR_OK; +} + + + + +/** + * Create intermediate directories for Choices and User Data files + */ +static void ro_gui_create_dirs(void) +{ + char buf[256]; + char *path; + + /* Choices */ + path = getenv("NetSurf$ChoicesSave"); + if (!path) + die("Failed to find NetSurf Choices save path"); + + snprintf(buf, sizeof(buf), "%s", path); + netsurf_mkdir_all(buf); + + /* URL */ + snprintf(buf, sizeof(buf), "%s", nsoption_charp(url_save)); + netsurf_mkdir_all(buf); + + /* Hotlist */ + snprintf(buf, sizeof(buf), "%s", nsoption_charp(hotlist_save)); + netsurf_mkdir_all(buf); + + /* Recent */ + snprintf(buf, sizeof(buf), "%s", nsoption_charp(recent_save)); + netsurf_mkdir_all(buf); + + /* Theme */ + snprintf(buf, sizeof(buf), "%s", nsoption_charp(theme_save)); + netsurf_mkdir_all(buf); + /* and the final directory part (as theme_save is a directory) */ + xosfile_create_dir(buf, 0); +} + + +/** + * Ensures the gui exits cleanly. + */ +static void ro_gui_cleanup(void) +{ + ro_gui_buffer_close(); + xhourglass_off(); + /* Uninstall NetSurf-specific fonts */ + xos_cli("FontRemove NetSurf:Resources.Fonts."); +} + + +/** + * Handles a signal + */ +static void ro_gui_signal(int sig) +{ + static const os_error error = { 1, "NetSurf has detected a serious " + "error and must exit. Please submit a bug report, " + "attaching the browser log file." }; + os_colour old_sand, old_glass; + + ro_gui_cleanup(); + + xhourglass_on(); + xhourglass_colours(0x0000ffff, 0x000000ff, &old_sand, &old_glass); + nsoption_dump(stderr, NULL); + /*rufl_dump_state();*/ + +#ifndef __ELF__ + /* save WimpSlot and DA to files if NetSurf$CoreDump exists */ + int used; + xos_read_var_val_size("NetSurf$CoreDump", 0, 0, &used, 0, 0); + if (used) { + int curr_slot; + xwimp_slot_size(-1, -1, &curr_slot, 0, 0); + LOG("saving WimpSlot, size 0x%x", curr_slot); + xosfile_save("$.NetSurf_Slot", 0x8000, 0, + (byte *) 0x8000, + (byte *) 0x8000 + curr_slot); + + if (__dynamic_num != -1) { + int size; + byte *base_address; + xosdynamicarea_read(__dynamic_num, &size, + &base_address, 0, 0, 0, 0, 0); + LOG("saving DA %i, base %p, size 0x%x", __dynamic_num, base_address, size); + xosfile_save("$.NetSurf_DA", + (bits) base_address, 0, + base_address, + base_address + size); + } + } +#else + /* Save WimpSlot and UnixLib managed DAs when UnixEnv$coredump + * defines a coredump directory. */ + const _kernel_oserror *err = __unixlib_write_coredump (NULL); + if (err != NULL) + LOG("Coredump failed: %s", err->errmess); +#endif + + xhourglass_colours(old_sand, old_glass, 0, 0); + xhourglass_off(); + + __write_backtrace(sig); + + xwimp_report_error_by_category(&error, + wimp_ERROR_BOX_GIVEN_CATEGORY | + wimp_ERROR_BOX_CATEGORY_ERROR << + wimp_ERROR_BOX_CATEGORY_SHIFT, + "NetSurf", "!netsurf", + (osspriteop_area *) 1, "Quit", 0); + xos_cli("Filer_Run <Wimp$ScrapDir>.WWW.NetSurf.Log"); + + _Exit(sig); +} + + +/** + * Read a "line" from an Acorn URI file. + * + * \param fp file pointer to read from + * \param b buffer for line, size 400 bytes + * \return true on success, false on EOF + */ +static bool ro_gui_uri_file_parse_line(FILE *fp, char *b) +{ + int c; + unsigned int i = 0; + + c = getc(fp); + if (c == EOF) + return false; + + /* skip comment lines */ + while (c == '#') { + do { c = getc(fp); } while (c != EOF && 32 <= c); + if (c == EOF) + return false; + do { c = getc(fp); } while (c != EOF && c < 32); + if (c == EOF) + return false; + } + + /* read "line" */ + do { + if (i == 399) + return false; + b[i++] = c; + c = getc(fp); + } while (c != EOF && 32 <= c); + + /* skip line ending control characters */ + while (c != EOF && c < 32) + c = getc(fp); + + if (c != EOF) + ungetc(c, fp); + + b[i] = 0; + return true; +} + + +/** + * Parse an Acorn URI file. + * + * \param file_name file to read + * \param uri_title pointer to receive title data, or NULL for no data + * \return URL from file, or 0 on error and error reported + */ +static char *ro_gui_uri_file_parse(const char *file_name, char **uri_title) +{ + /* See the "Acorn URI Handler Functional Specification" for the + * definition of the URI file format. */ + char line[400]; + char *url = NULL; + FILE *fp; + + *uri_title = NULL; + fp = fopen(file_name, "rb"); + if (!fp) { + LOG("fopen(\"%s\", \"rb\"): %i: %s", file_name, errno, strerror(errno)); + ro_warn_user("LoadError", strerror(errno)); + return 0; + } + + /* "URI" */ + if (!ro_gui_uri_file_parse_line(fp, line) || strcmp(line, "URI") != 0) + goto uri_syntax_error; + + /* version */ + if (!ro_gui_uri_file_parse_line(fp, line) || + strspn(line, "0123456789") != strlen(line)) + goto uri_syntax_error; + + /* URI */ + if (!ro_gui_uri_file_parse_line(fp, line)) + goto uri_syntax_error; + + url = strdup(line); + if (!url) { + ro_warn_user("NoMemory", 0); + fclose(fp); + return 0; + } + + /* title */ + if (!ro_gui_uri_file_parse_line(fp, line)) + goto uri_free; + if (uri_title && line[0] && ((line[0] != '*') || line[1])) { + *uri_title = strdup(line); + if (!*uri_title) /* non-fatal */ + ro_warn_user("NoMemory", 0); + } + fclose(fp); + + return url; + +uri_free: + free(url); + +uri_syntax_error: + fclose(fp); + ro_warn_user("URIError", 0); + return 0; +} + + +/** + * Parse an ANT URL file. + * + * \param file_name file to read + * \return URL from file, or 0 on error and error reported + */ +static char *ro_gui_url_file_parse(const char *file_name) +{ + char line[400]; + char *url; + FILE *fp; + + fp = fopen(file_name, "r"); + if (!fp) { + LOG("fopen(\"%s\", \"r\"): %i: %s", file_name, errno, strerror(errno)); + ro_warn_user("LoadError", strerror(errno)); + return 0; + } + + if (!fgets(line, sizeof line, fp)) { + if (ferror(fp)) { + LOG("fgets: %i: %s", errno, strerror(errno)); + ro_warn_user("LoadError", strerror(errno)); + } else + ro_warn_user("LoadError", messages_get("EmptyError")); + fclose(fp); + return 0; + } + + fclose(fp); + + if (line[strlen(line) - 1] == '\n') + line[strlen(line) - 1] = '\0'; + + url = strdup(line); + if (!url) { + ro_warn_user("NoMemory", 0); + return 0; + } + + return url; +} + + +/** + * Parse an IEURL file. + * + * \param file_name file to read + * \return URL from file, or 0 on error and error reported + */ +static char *ro_gui_ieurl_file_parse(const char *file_name) +{ + char line[400]; + char *url = 0; + FILE *fp; + + fp = fopen(file_name, "r"); + if (!fp) { + LOG("fopen(\"%s\", \"r\"): %i: %s", file_name, errno, strerror(errno)); + ro_warn_user("LoadError", strerror(errno)); + return 0; + } + + while (fgets(line, sizeof line, fp)) { + if (strncmp(line, "URL=", 4) == 0) { + if (line[strlen(line) - 1] == '\n') + line[strlen(line) - 1] = '\0'; + url = strdup(line + 4); + if (!url) { + fclose(fp); + ro_warn_user("NoMemory", 0); + return 0; + } + break; + } + } + if (ferror(fp)) { + LOG("fgets: %i: %s", errno, strerror(errno)); + ro_warn_user("LoadError", strerror(errno)); + fclose(fp); + return 0; + } + + fclose(fp); + + if (!url) + ro_warn_user("URIError", 0); + + return url; +} + + +/** + * Handle Message_DataOpen (double-click on file in the Filer). + * + * \param message The wimp message to open. + */ +static void ro_msg_dataopen(wimp_message *message) +{ + int file_type = message->data.data_xfer.file_type; + char *url = 0; + os_error *oserror; + nsurl *urlns; + nserror error; + size_t len; + + switch (file_type) { + case 0xb28: /* ANT URL file */ + url = ro_gui_url_file_parse(message->data.data_xfer.file_name); + error = nsurl_create(url, &urlns); + free(url); + break; + + case 0xfaf: /* HTML file */ + error = netsurf_path_to_nsurl(message->data.data_xfer.file_name, + &urlns); + break; + + case 0x1ba: /* IEURL file */ + url = ro_gui_ieurl_file_parse(message-> + data.data_xfer.file_name); + error = nsurl_create(url, &urlns); + free(url); + break; + + case 0x2000: /* application */ + len = strlen(message->data.data_xfer.file_name); + if (len < 9 || strcmp(".!NetSurf", + message->data.data_xfer.file_name + len - 9)) + return; + + if (nsoption_charp(homepage_url) && + nsoption_charp(homepage_url)[0]) { + error = nsurl_create(nsoption_charp(homepage_url), + &urlns); + } else { + error = nsurl_create(NETSURF_HOMEPAGE, &urlns); + } + break; + + default: + return; + } + + /* send DataLoadAck */ + message->action = message_DATA_LOAD_ACK; + message->your_ref = message->my_ref; + oserror = xwimp_send_message(wimp_USER_MESSAGE, message, message->sender); + if (oserror) { + LOG("xwimp_send_message: 0x%x: %s", oserror->errnum, oserror->errmess); + ro_warn_user("WimpError", oserror->errmess); + return; + } + + if (error != NSERROR_OK) { + ro_warn_user(messages_get_errorcode(error), 0); + return; + } + + /* create a new window with the file */ + error = browser_window_create(BW_CREATE_HISTORY, + urlns, + NULL, + NULL, + NULL); + nsurl_unref(urlns); + if (error != NSERROR_OK) { + ro_warn_user(messages_get_errorcode(error), 0); + } +} + + +/** + * Handle Message_DataLoad (file dragged in). + */ +static void ro_msg_dataload(wimp_message *message) +{ + int file_type = message->data.data_xfer.file_type; + char *urltxt = NULL; + char *title = NULL; + struct gui_window *g; + os_error *oserror; + nsurl *url; + nserror error; + + g = ro_gui_window_lookup(message->data.data_xfer.w); + if (g) { + if (ro_gui_window_dataload(g, message)) + return; + } + else { + g = ro_gui_toolbar_lookup(message->data.data_xfer.w); + if (g && ro_gui_toolbar_dataload(g, message)) + return; + } + + switch (file_type) { + case FILETYPE_ACORN_URI: + urltxt = ro_gui_uri_file_parse(message->data.data_xfer.file_name, + &title); + error = nsurl_create(urltxt, &url); + free(urltxt); + break; + + case FILETYPE_ANT_URL: + urltxt = ro_gui_url_file_parse(message->data.data_xfer.file_name); + error = nsurl_create(urltxt, &url); + free(urltxt); + break; + + case FILETYPE_IEURL: + urltxt = ro_gui_ieurl_file_parse(message->data.data_xfer.file_name); + error = nsurl_create(urltxt, &url); + free(urltxt); + break; + + case FILETYPE_HTML: + case FILETYPE_JNG: + case FILETYPE_CSS: + case FILETYPE_MNG: + case FILETYPE_GIF: + case FILETYPE_BMP: + case FILETYPE_ICO: + case osfile_TYPE_DRAW: + case FILETYPE_PNG: + case FILETYPE_JPEG: + case osfile_TYPE_SPRITE: + case osfile_TYPE_TEXT: + case FILETYPE_ARTWORKS: + case FILETYPE_SVG: + /* display the actual file */ + error = netsurf_path_to_nsurl(message->data.data_xfer.file_name, &url); + break; + + default: + return; + } + + /* report error to user */ + if (error != NSERROR_OK) { + ro_warn_user(messages_get_errorcode(error), 0); + return; + } + + + if (g) { + error = browser_window_navigate(g->bw, + url, + NULL, + BW_NAVIGATE_HISTORY, + NULL, + NULL, + NULL); + } else { + error = browser_window_create(BW_CREATE_HISTORY, + url, + NULL, + NULL, + NULL); + } + nsurl_unref(url); + if (error != NSERROR_OK) { + ro_warn_user(messages_get_errorcode(error), 0); + } + + + /* send DataLoadAck */ + message->action = message_DATA_LOAD_ACK; + message->your_ref = message->my_ref; + oserror = xwimp_send_message(wimp_USER_MESSAGE, message, + message->sender); + if (oserror) { + LOG("xwimp_send_message: 0x%x: %s", oserror->errnum, oserror->errmess); + ro_warn_user("WimpError", oserror->errmess); + return; + } + +} + + +/** + * Ensure that the filename in a data transfer message is NULL terminated + * (some applications, especially BASIC programs use CR) + * + * \param message message to be corrected + */ +static void ro_msg_terminate_filename(wimp_full_message_data_xfer *message) +{ + const char *ep = (char*)message + message->size; + char *p = message->file_name; + + if ((size_t)message->size >= sizeof(*message)) + ep = (char*)message + sizeof(*message) - 1; + + while (p < ep && *p >= ' ') p++; + *p = '\0'; +} + + +/** + * Handle Message_DataSave + */ +static void ro_msg_datasave(wimp_message *message) +{ + wimp_full_message_data_xfer *dataxfer = (wimp_full_message_data_xfer*)message; + + /* remove ghost caret if drag-and-drop protocol was used */ +// ro_gui_selection_drag_reset(); + + ro_msg_terminate_filename(dataxfer); + + if (ro_gui_selection_prepare_paste_datasave(dataxfer)) + return; + + switch (dataxfer->file_type) { + case FILETYPE_ACORN_URI: + case FILETYPE_ANT_URL: + case FILETYPE_IEURL: + case FILETYPE_HTML: + case FILETYPE_JNG: + case FILETYPE_CSS: + case FILETYPE_MNG: + case FILETYPE_GIF: + case FILETYPE_BMP: + case FILETYPE_ICO: + case osfile_TYPE_DRAW: + case FILETYPE_PNG: + case FILETYPE_JPEG: + case osfile_TYPE_SPRITE: + case osfile_TYPE_TEXT: + case FILETYPE_ARTWORKS: + case FILETYPE_SVG: { + os_error *error; + + dataxfer->your_ref = dataxfer->my_ref; + dataxfer->size = offsetof(wimp_full_message_data_xfer, file_name) + 16; + dataxfer->action = message_DATA_SAVE_ACK; + dataxfer->est_size = -1; + memcpy(dataxfer->file_name, "<Wimp$Scrap>", 13); + + error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message*)dataxfer, message->sender); + if (error) { + LOG("xwimp_send_message: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + } + break; + } +} + + +/** + * Handle Message_DataSaveAck. + */ +static void ro_msg_datasave_ack(wimp_message *message) +{ + ro_msg_terminate_filename((wimp_full_message_data_xfer*)message); + + if (ro_print_ack(message)) + return; + + switch (gui_current_drag_type) { + case GUI_DRAG_DOWNLOAD_SAVE: + ro_gui_download_datasave_ack(message); + break; + + case GUI_DRAG_SAVE: + ro_gui_save_datasave_ack(message); + gui_current_drag_type = GUI_DRAG_NONE; + break; + + default: + break; + } + + gui_current_drag_type = GUI_DRAG_NONE; +} + + +/** + * Handle PreQuit message + * + * \param message PreQuit message from Wimp + */ +static void ro_msg_prequit(wimp_message *message) +{ + if (!ro_gui_prequit()) { + os_error *error; + + /* we're objecting to the close down */ + message->your_ref = message->my_ref; + error = xwimp_send_message(wimp_USER_MESSAGE_ACKNOWLEDGE, + message, message->sender); + if (error) { + LOG("xwimp_send_message: 0x%x:%s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + } +} + + +/** + * Handle SaveDesktop message. + * + * \param message SaveDesktop message from Wimp. + */ +static void ro_msg_save_desktop(wimp_message *message) +{ + os_error *error; + + error = xosgbpb_writew(message->data.save_desktopw.file, + (const byte*)"Run ", 4, NULL); + if (!error) { + error = xosgbpb_writew(message->data.save_desktopw.file, + (const byte*)NETSURF_DIR, strlen(NETSURF_DIR), NULL); + if (!error) + error = xos_bputw('\n', message->data.save_desktopw.file); + } + + if (error) { + LOG("xosgbpb_writew/xos_bputw: 0x%x:%s", error->errnum, error->errmess); + ro_warn_user("SaveError", error->errmess); + + /* we must cancel the save by acknowledging the message */ + message->your_ref = message->my_ref; + error = xwimp_send_message(wimp_USER_MESSAGE_ACKNOWLEDGE, + message, message->sender); + if (error) { + LOG("xwimp_send_message: 0x%x:%s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + } +} + + +/** + * Handle WindowInfo message (part of the iconising protocol) + * + * \param message WindowInfo message from the Iconiser + */ +static void ro_msg_window_info(wimp_message *message) +{ + wimp_full_message_window_info *wi; + struct gui_window *g; + + /* allow the user to turn off thumbnail icons */ + if (!nsoption_bool(thumbnail_iconise)) + return; + + wi = (wimp_full_message_window_info*)message; + g = ro_gui_window_lookup(wi->w); + + /* ic_<task name> will suffice for our other windows */ + if (g) { + ro_gui_window_iconise(g, wi); + ro_gui_dialog_close_persistent(wi->w); + } +} + + +/** + * Get screen properties following a mode change. + */ +static void ro_gui_get_screen_properties(void) +{ + static const ns_os_vdu_var_list vars = { + os_MODEVAR_XWIND_LIMIT, + { + os_MODEVAR_YWIND_LIMIT, + os_MODEVAR_XEIG_FACTOR, + os_MODEVAR_YEIG_FACTOR, + os_VDUVAR_END_LIST + } + }; + os_error *error; + int vals[4]; + + error = xos_read_vdu_variables(PTR_OS_VDU_VAR_LIST(&vars), vals); + if (error) { + LOG("xos_read_vdu_variables: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("MiscError", error->errmess); + return; + } + screen_info.width = (vals[0] + 1) << vals[2]; + screen_info.height = (vals[1] + 1) << vals[3]; +} + + +/** + * Warn the user if Inet$Resolvers is not set. + */ +static void ro_gui_check_resolvers(void) +{ + char *resolvers; + resolvers = getenv("Inet$Resolvers"); + if (resolvers && resolvers[0]) { + LOG("Inet$Resolvers '%s'", resolvers); + } else { + LOG("Inet$Resolvers not set or empty"); + ro_warn_user("Resolvers", 0); + } +} + + +/** + * Initialise the RISC OS specific GUI. + * + * \param argc The number of command line arguments. + * \param argv The string vector of command line arguments. + */ +static nserror gui_init(int argc, char** argv) +{ + struct { + void (*sigabrt)(int); + void (*sigfpe)(int); + void (*sigill)(int); + void (*sigint)(int); + void (*sigsegv)(int); + void (*sigterm)(int); + void (*sigoserror)(int); + } prev_sigs; + char path[40]; + os_error *error; + int length; + char *nsdir_temp; + byte *base; + nsurl *url; + nserror ret; + bool open_window; + + /* re-enable all FPU exceptions/traps except inexact operations, + * which we're not interested in, and underflow which is incorrectly + * raised when converting an exact value of 0 from double-precision + * to single-precision on FPEmulator v4.09-4.11 (MVFD F0,#0:MVFS F0,F0) + * - UnixLib disables all FP exceptions by default */ + + _FPU_SETCW(_FPU_IEEE & ~(_FPU_MASK_PM | _FPU_MASK_UM)); + + xhourglass_start(1); + + /* read OS version for code that adapts to conform to the OS + * (remember that it's preferable to check for specific features + * being present) */ + xos_byte(osbyte_IN_KEY, 0, 0xff, &os_version, NULL); + + /* the first release version of the A9home OS is incapable of + plotting patterned lines (presumably a fault in the hw acceleration) */ + if (!xosmodule_lookup("VideoHWSMI", NULL, NULL, &base, NULL, NULL)) { +#if 0 // this fault still hasn't been fixed, so disable patterned lines for all versions until it has + const char *help = (char*)base + ((int*)base)[5]; + while (*help > 9) help++; + while (*help == 9) help++; + if (!memcmp(help, "0.55", 4)) +#endif + ro_plot_patterned_lines = false; + } + + /* Create our choices directories */ + ro_gui_create_dirs(); + + /* Register exit and signal handlers */ + atexit(ro_gui_cleanup); + prev_sigs.sigabrt = signal(SIGABRT, ro_gui_signal); + prev_sigs.sigfpe = signal(SIGFPE, ro_gui_signal); + prev_sigs.sigill = signal(SIGILL, ro_gui_signal); + prev_sigs.sigint = signal(SIGINT, ro_gui_signal); + prev_sigs.sigsegv = signal(SIGSEGV, ro_gui_signal); + prev_sigs.sigterm = signal(SIGTERM, ro_gui_signal); + prev_sigs.sigoserror = signal(SIGOSERROR, ro_gui_signal); + + if (prev_sigs.sigabrt == SIG_ERR || prev_sigs.sigfpe == SIG_ERR || + prev_sigs.sigill == SIG_ERR || + prev_sigs.sigint == SIG_ERR || + prev_sigs.sigsegv == SIG_ERR || + prev_sigs.sigterm == SIG_ERR || + prev_sigs.sigoserror == SIG_ERR) + die("Failed registering signal handlers"); + + /* Load in UI sprites */ + gui_sprites = ro_gui_load_sprite_file("NetSurf:Resources.Sprites"); + if (!gui_sprites) + die("Unable to load Sprites."); + + /* Find NetSurf directory */ + nsdir_temp = getenv("NetSurf$Dir"); + if (!nsdir_temp) + die("Failed to locate NetSurf directory"); + NETSURF_DIR = strdup(nsdir_temp); + if (!NETSURF_DIR) + die("Failed duplicating NetSurf directory string"); + + /* Initialise filename allocator */ + filename_initialise(); + + /* Initialise save complete functionality */ + save_complete_init(); + + /* Load in visited URLs and Cookies */ + urldb_load(nsoption_charp(url_path)); + urldb_load_cookies(nsoption_charp(cookie_file)); + + /* Initialise with the wimp */ + error = xwimp_initialise(wimp_VERSION_RO38, task_name, + PTR_WIMP_MESSAGE_LIST(&task_messages), 0, + &task_handle); + if (error) { + LOG("xwimp_initialise: 0x%x: %s", error->errnum, error->errmess); + die(error->errmess); + } + /* Register message handlers */ + ro_message_register_route(message_HELP_REQUEST, + ro_gui_interactive_help_request); + ro_message_register_route(message_DATA_OPEN, + ro_msg_dataopen); + ro_message_register_route(message_DATA_SAVE, + ro_msg_datasave); + ro_message_register_route(message_DATA_SAVE_ACK, + ro_msg_datasave_ack); + ro_message_register_route(message_PRE_QUIT, + ro_msg_prequit); + ro_message_register_route(message_SAVE_DESKTOP, + ro_msg_save_desktop); + ro_message_register_route(message_DRAGGING, + ro_gui_selection_dragging); + ro_message_register_route(message_DRAG_CLAIM, + ro_gui_selection_drag_claim); + ro_message_register_route(message_WINDOW_INFO, + ro_msg_window_info); + + /* Initialise the font subsystem */ + nsfont_init(); + + /* Initialise global information */ + ro_gui_get_screen_properties(); + ro_gui_wimp_get_desktop_font(); + + /* Issue a *Desktop to poke AcornURI into life */ + if (getenv("NetSurf$Start_URI_Handler")) + xwimp_start_task("Desktop", 0); + + /* Open the templates */ + if ((length = snprintf(path, sizeof(path), + "NetSurf:Resources.%s.Templates", + nsoption_charp(language))) < 0 || length >= (int)sizeof(path)) + die("Failed to locate Templates resource."); + error = xwimp_open_template(path); + if (error) { + LOG("xwimp_open_template failed: 0x%x: %s", error->errnum, error->errmess); + die(error->errmess); + } + + ret = treeview_init(12); + if (ret != NSERROR_OK) { + die("Failed to initialise treeview"); + } + + /* Initialise themes before dialogs */ + ro_gui_theme_initialise(); + + /* Initialise dialog windows (must be after UI sprites are loaded) */ + ro_gui_dialog_init(); + + /* Initialise download window */ + ro_gui_download_init(); + + /* Initialise menus */ + ro_gui_menu_init(); + + /* Initialise query windows */ + ro_gui_query_init(); + + /* Initialise the history subsystem */ + ro_gui_history_init(); + + /* Initialise toolbars */ + ro_toolbar_init(); + + /* Initialise url bar module */ + ro_gui_url_bar_init(); + + /* Initialise browser windows */ + ro_gui_window_initialise(); + + /* Done with the templates file */ + wimp_close_template(); + + /* Create Iconbar icon and menus */ + ro_gui_iconbar_initialise(); + + /* Finally, check Inet$Resolvers for sanity */ + ro_gui_check_resolvers(); + + /* certificate verification window */ + ro_gui_cert_postinitialise(); + + /* hotlist window */ + ro_gui_hotlist_postinitialise(); + + /* global history window */ + ro_gui_global_history_postinitialise(); + + /* cookies window */ + ro_gui_cookies_postinitialise(); + + open_window = nsoption_bool(open_browser_at_startup); + + /* parse command-line arguments */ + if (argc == 2) { + LOG("parameters: '%s'", argv[1]); + /* this is needed for launching URI files */ + if (strcasecmp(argv[1], "-nowin") == 0) { + return NSERROR_OK; + } + ret = nsurl_create(NETSURF_HOMEPAGE, &url); + } + else if (argc == 3) { + LOG("parameters: '%s' '%s'", argv[1], argv[2]); + open_window = true; + + /* HTML files */ + if (strcasecmp(argv[1], "-html") == 0) { + ret = netsurf_path_to_nsurl(argv[2], &url); + } + /* URL files */ + else if (strcasecmp(argv[1], "-urlf") == 0) { + char *urlf = ro_gui_url_file_parse(argv[2]); + if (!urlf) { + LOG("allocation failed"); + die("Insufficient memory for URL"); + } + ret = nsurl_create(urlf, &url); + free(urlf); + } + /* ANT URL Load */ + else if (strcasecmp(argv[1], "-url") == 0) { + ret = nsurl_create(argv[2], &url); + } + /* Unknown => exit here. */ + else { + LOG("Unknown parameters: '%s' '%s'", argv[1], argv[2]); + return NSERROR_BAD_PARAMETER; + } + } + /* get user's homepage (if configured) */ + else if (nsoption_charp(homepage_url) && + nsoption_charp(homepage_url)[0]) { + ret = nsurl_create(nsoption_charp(homepage_url), &url); + } + /* default homepage */ + else { + ret = nsurl_create(NETSURF_HOMEPAGE, &url); + } + + /* check for url creation error */ + if (ret != NSERROR_OK) { + return ret; + } + + if (open_window) { + ret = browser_window_create(BW_CREATE_HISTORY, + url, + NULL, + NULL, + NULL); + } + nsurl_unref(url); + + return ret; +} + + +/** + * Determine the default language to use. + * + * RISC OS has no standard way of determining which language the user prefers. + * We have to guess from the 'Country' setting. + */ +const char *ro_gui_default_language(void) +{ + char path[40]; + const char *lang; + int country; + os_error *error; + + /* choose a language from the configured country number */ + error = xosbyte_read(osbyte_VAR_COUNTRY_NUMBER, &country); + if (error) { + LOG("xosbyte_read failed: 0x%x: %s", error->errnum, error->errmess); + country = 1; + } + switch (country) { + case 7: /* Germany */ + case 30: /* Austria */ + case 35: /* Switzerland (70% German-speaking) */ + lang = "de"; + break; + case 6: /* France */ + case 18: /* Canada2 (French Canada?) */ + lang = "fr"; + break; + case 34: /* Netherlands */ + lang = "nl"; + break; + default: + lang = "en"; + break; + } + sprintf(path, "NetSurf:Resources.%s", lang); + if (is_dir(path)) + return lang; + return "en"; +} + + +/** + * Create a nsurl from a RISC OS pathname. + * + * Perform the necessary operations on a path to generate a nsurl. + * + * @param[in] path The RISC OS pathname to convert. + * @param[out] url_out pointer to recive the nsurl, The returned url must be + * unreferenced by the caller. + * @return NSERROR_OK and the url is placed in \a url or error code on faliure. + */ +static nserror ro_path_to_nsurl(const char *path, struct nsurl **url_out) +{ + int spare; + char *canonical_path; /* canonicalised RISC OS path */ + char *unix_path; /* unix path */ + char *escurl; + os_error *error; + nserror ret; + int urllen; + char *url; /* resulting url */ + + /* calculate the canonical risc os path */ + error = xosfscontrol_canonicalise_path(path, 0, 0, 0, 0, &spare); + if (error) { + LOG("xosfscontrol_canonicalise_path failed: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("PathToURL", error->errmess); + return NSERROR_NOT_FOUND; + } + + canonical_path = malloc(1 - spare); + if (canonical_path == NULL) { + free(canonical_path); + return NSERROR_NOMEM; + } + + error = xosfscontrol_canonicalise_path(path, canonical_path, 0, 0, 1 - spare, 0); + if (error) { + LOG("xosfscontrol_canonicalise_path failed: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("PathToURL", error->errmess); + free(canonical_path); + return NSERROR_NOT_FOUND; + } + + /* create a unix path from the cananocal risc os one */ + unix_path = __unixify(canonical_path, __RISCOSIFY_NO_REVERSE_SUFFIX, NULL, 0, 0); + + if (unix_path == NULL) { + LOG("__unixify failed: %s", canonical_path); + free(canonical_path); + return NSERROR_BAD_PARAMETER; + } + free(canonical_path); + + /* convert the unix path into a url */ + urllen = strlen(unix_path) + FILE_SCHEME_PREFIX_LEN + 1; + url = malloc(urllen); + if (url == NULL) { + LOG("Unable to allocate url"); + free(unix_path); + return NSERROR_NOMEM; + } + + if (*unix_path == '/') { + snprintf(url, urllen, "%s%s", FILE_SCHEME_PREFIX, unix_path + 1); + } else { + snprintf(url, urllen, "%s%s", FILE_SCHEME_PREFIX, unix_path); + } + free(unix_path); + + /* We don't want '/' to be escaped. */ + ret = url_escape(url, FILE_SCHEME_PREFIX_LEN, false, "/", &escurl); + free(url); + if (ret != NSERROR_OK) { + return ret; + } + + ret = nsurl_create(escurl, url_out); + free(escurl); + + return ret; +} + + +/** + * Create a path from a nsurl using posix file handling. + * + * @param[in] url The url to encode. + * @param[out] path_out A string containing the result path which should + * be freed by the caller. + * @return NSERROR_OK and the path is written to \a path or error code + * on faliure. + */ +static nserror ro_nsurl_to_path(struct nsurl *url, char **path_out) +{ + lwc_string *urlpath; + char *unpath; + char *path; + bool match; + lwc_string *scheme; + nserror res; + char *r; + + if ((url == NULL) || (path_out == NULL)) { + return NSERROR_BAD_PARAMETER; + } + + scheme = nsurl_get_component(url, NSURL_SCHEME); + + if (lwc_string_caseless_isequal(scheme, corestring_lwc_file, + &match) != lwc_error_ok) + { + return NSERROR_BAD_PARAMETER; + } + lwc_string_unref(scheme); + if (match == false) { + return NSERROR_BAD_PARAMETER; + } + + urlpath = nsurl_get_component(url, NSURL_PATH); + if (urlpath == NULL) { + return NSERROR_BAD_PARAMETER; + } + + res = url_unescape(lwc_string_data(urlpath), &unpath); + lwc_string_unref(urlpath); + if (res != NSERROR_OK) { + return res; + } + + /* RISC OS path should not be more than 100 characters longer */ + path = malloc(strlen(unpath) + 100); + if (path == NULL) { + free(unpath); + return NSERROR_NOMEM; + } + + r = __riscosify(unpath, 0, __RISCOSIFY_NO_SUFFIX, + path, strlen(unpath) + 100, 0); + free(unpath); + if (r == NULL) { + free(path); + return NSERROR_NOMEM; + } + + *path_out = path; + + return NSERROR_OK; +} + + +/** + * Ensures output logging stream is correctly configured. + */ +static bool nslog_stream_configure(FILE *fptr) +{ + /* set log stream to be non-buffering */ + setbuf(fptr, NULL); + + return true; +} + + +/** + * Close down the gui (RISC OS). + */ +static void gui_quit(void) +{ + urldb_save_cookies(nsoption_charp(cookie_jar)); + urldb_save(nsoption_charp(url_save)); + ro_gui_window_quit(); + ro_gui_global_history_destroy(); + ro_gui_hotlist_destroy(); + ro_gui_cookies_destroy(); + ro_gui_saveas_quit(); + ro_gui_url_bar_fini(); + rufl_quit(); + free(gui_sprites); + xwimp_close_down(task_handle); + xhourglass_off(); +} + + +/** + * Handle Close_Window_Request events. + */ +static void ro_gui_close_window_request(wimp_close *close) +{ + if (ro_gui_alt_pressed()) + ro_gui_window_close_all(); + else { + if (ro_gui_wimp_event_close_window(close->w)) + return; + ro_gui_dialog_close(close->w); + } +} + + +/** + * Handle key press paste callback. + */ +static void ro_gui_keypress_cb(void *pw) +{ + wimp_key *key = (wimp_key *) pw; + + if (ro_gui_wimp_event_keypress(key) == false) { + os_error *error = xwimp_process_key(key->c); + if (error) { + LOG("xwimp_process_key: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + } + + free(key); +} + + +/** + * Handle gui keypress. + */ +static void ro_gui_keypress(wimp_key *key) +{ + if (key->c == wimp_KEY_ESCAPE && + (gui_current_drag_type == GUI_DRAG_SAVE || + gui_current_drag_type == GUI_DRAG_DOWNLOAD_SAVE)) { + + /* Allow Escape key to be used for cancelling a drag + * save (easier than finding somewhere safe to abort + * the drag) + */ + ro_gui_drag_box_cancel(); + gui_current_drag_type = GUI_DRAG_NONE; + } else if (key->c == 22 /* Ctrl-V */) { + wimp_key *copy; + + /* Must copy the keypress as it's on the stack */ + copy = malloc(sizeof(wimp_key)); + if (copy == NULL) + return; + memcpy(copy, key, sizeof(wimp_key)); + + ro_gui_selection_prepare_paste(key->w, ro_gui_keypress_cb, copy); + } else if (ro_gui_wimp_event_keypress(key) == false) { + os_error *error = xwimp_process_key(key->c); + if (error) { + LOG("xwimp_process_key: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } + } +} + + +/** + * Handle the three User_Message events. + */ +static void ro_gui_user_message(wimp_event_no event, wimp_message *message) +{ + /* attempt automatic routing */ + if (ro_message_handle_message(event, message)) + return; + + switch (message->action) { + case message_DATA_LOAD: + ro_msg_terminate_filename((wimp_full_message_data_xfer*)message); + + if (event == wimp_USER_MESSAGE_ACKNOWLEDGE) { + if (ro_print_current_window) + ro_print_dataload_bounce(message); + } else if (ro_gui_selection_prepare_paste_dataload( + (wimp_full_message_data_xfer *) message) == false) { + ro_msg_dataload(message); + } + break; + + case message_DATA_LOAD_ACK: + if (ro_print_current_window) + ro_print_cleanup(); + break; + + case message_MENU_WARNING: + ro_gui_menu_warning((wimp_message_menu_warning *) + &message->data); + break; + + case message_MENUS_DELETED: + ro_gui_menu_message_deleted((wimp_message_menus_deleted *) + &message->data); + break; + + case message_CLAIM_ENTITY: + ro_gui_selection_claim_entity((wimp_full_message_claim_entity*)message); + break; + + case message_DATA_REQUEST: + ro_gui_selection_data_request((wimp_full_message_data_request*)message); + break; + + case message_MODE_CHANGE: + ro_gui_get_screen_properties(); + rufl_invalidate_cache(); + break; + + case message_PALETTE_CHANGE: + break; + + case message_FONT_CHANGED: + ro_gui_wimp_get_desktop_font(); + break; + + case message_URI_PROCESS: + if (event != wimp_USER_MESSAGE_ACKNOWLEDGE) + ro_uri_message_received(message); + break; + case message_URI_RETURN_RESULT: + ro_uri_bounce(message); + break; + case message_INET_SUITE_OPEN_URL: + if (event == wimp_USER_MESSAGE_ACKNOWLEDGE) { + ro_url_bounce(message); + } + else { + ro_url_message_received(message); + } + break; +#ifdef WITH_PLUGIN + case message_PLUG_IN_OPENING: + plugin_opening(message); + break; + case message_PLUG_IN_CLOSED: + plugin_closed(message); + break; + case message_PLUG_IN_RESHAPE_REQUEST: + plugin_reshape_request(message); + break; + case message_PLUG_IN_FOCUS: + break; + case message_PLUG_IN_URL_ACCESS: + plugin_url_access(message); + break; + case message_PLUG_IN_STATUS: + plugin_status(message); + break; + case message_PLUG_IN_BUSY: + break; + case message_PLUG_IN_STREAM_NEW: + plugin_stream_new(message); + break; + case message_PLUG_IN_STREAM_WRITE: + break; + case message_PLUG_IN_STREAM_WRITTEN: + plugin_stream_written(message); + break; + case message_PLUG_IN_STREAM_DESTROY: + break; + case message_PLUG_IN_OPEN: + if (event == wimp_USER_MESSAGE_ACKNOWLEDGE) + plugin_open_msg(message); + break; + case message_PLUG_IN_CLOSE: + if (event == wimp_USER_MESSAGE_ACKNOWLEDGE) + plugin_close_msg(message); + break; + case message_PLUG_IN_RESHAPE: + case message_PLUG_IN_STREAM_AS_FILE: + case message_PLUG_IN_NOTIFY: + case message_PLUG_IN_ABORT: + case message_PLUG_IN_ACTION: + break; +#endif + case message_PRINT_SAVE: + if (event == wimp_USER_MESSAGE_ACKNOWLEDGE) + ro_print_save_bounce(message); + break; + case message_PRINT_ERROR: + ro_print_error(message); + break; + case message_PRINT_TYPE_ODD: + ro_print_type_odd(message); + break; + case message_HOTLIST_CHANGED: + ro_gui_hotlist_add_cleanup(); + break; + case message_QUIT: + riscos_done = true; + break; + } +} + + +/** + * Process a Wimp_Poll event. + * + * \param event wimp event number + * \param block parameter block + */ +static void ro_gui_handle_event(wimp_event_no event, wimp_block *block) +{ + switch (event) { + case wimp_NULL_REASON_CODE: + ro_gui_throb(); + ro_mouse_poll(); + break; + + case wimp_REDRAW_WINDOW_REQUEST: + ro_gui_wimp_event_redraw_window(&block->redraw); + break; + + case wimp_OPEN_WINDOW_REQUEST: + ro_gui_open_window_request(&block->open); + break; + + case wimp_CLOSE_WINDOW_REQUEST: + ro_gui_close_window_request(&block->close); + break; + + case wimp_POINTER_LEAVING_WINDOW: + ro_mouse_pointer_leaving_window(&block->leaving); + break; + + case wimp_POINTER_ENTERING_WINDOW: + ro_gui_wimp_event_pointer_entering_window(&block->entering); + break; + + case wimp_MOUSE_CLICK: + ro_gui_wimp_event_mouse_click(&block->pointer); + break; + + case wimp_USER_DRAG_BOX: + ro_mouse_drag_end(&block->dragged); + break; + + case wimp_KEY_PRESSED: + ro_gui_keypress(&(block->key)); + break; + + case wimp_MENU_SELECTION: + ro_gui_menu_selection(&(block->selection)); + break; + + /* Scroll requests fall back to a generic handler because we + * might get these events for any window from a scroll-wheel. + */ + + case wimp_SCROLL_REQUEST: + if (!ro_gui_wimp_event_scroll_window(&(block->scroll))) + ro_gui_scroll(&(block->scroll)); + break; + + case wimp_USER_MESSAGE: + case wimp_USER_MESSAGE_RECORDED: + case wimp_USER_MESSAGE_ACKNOWLEDGE: + ro_gui_user_message(event, &(block->message)); + break; + } +} + + +/** + * Poll the RISC OS wimp for events. + */ +static void riscos_poll(void) +{ + wimp_event_no event; + wimp_block block; + const wimp_poll_flags mask = wimp_MASK_LOSE | wimp_MASK_GAIN | wimp_SAVE_FP; + os_t track_poll_offset; + + /* Poll wimp. */ + xhourglass_off(); + track_poll_offset = ro_mouse_poll_interval(); + if (sched_active || (track_poll_offset > 0)) { + os_t t = os_read_monotonic_time(); + + if (track_poll_offset > 0) { + t += track_poll_offset; + } else { + t += 10; + } + + if (sched_active && (sched_time - t) < 0) { + t = sched_time; + } + + event = wimp_poll_idle(mask, &block, t, 0); + } else { + event = wimp_poll(wimp_MASK_NULL | mask, &block, 0); + } + + xhourglass_on(); + gui_last_poll = clock(); + ro_gui_handle_event(event, &block); + + /* Only run scheduled callbacks on a null poll + * We cannot do this in the null event handler, as that may be called + * from gui_multitask(). Scheduled callbacks must only be run from the + * top-level. + */ + if (event == wimp_NULL_REASON_CODE) { + schedule_run(); + } + + ro_gui_window_update_boxes(); +} + + +/** + * Handle Open_Window_Request events. + */ +void ro_gui_open_window_request(wimp_open *open) +{ + os_error *error; + + if (ro_gui_wimp_event_open_window(open)) + return; + + error = xwimp_open_window(open); + if (error) { + LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + return; + } +} + + +/** + * source bounce callback. + */ +static void ro_gui_view_source_bounce(wimp_message *message) +{ + char *filename; + os_error *error; + char command[256]; + + /* run the file as text */ + filename = ((wimp_full_message_data_xfer *)message)->file_name; + sprintf(command, "@RunType_FFF %s", filename); + error = xwimp_start_task(command, 0); + if (error) { + LOG("xwimp_start_task failed: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } +} + + +/** + * Send the source of a content to a text editor. + */ +void ro_gui_view_source(hlcache_handle *c) +{ + os_error *error; + char *temp_name; + wimp_full_message_data_xfer message; + int objtype; + bool done = false; + + const char *source_data; + unsigned long source_size; + + if (!c) { + ro_warn_user("MiscError", "No document source"); + return; + } + + source_data = content_get_source_data(c, &source_size); + + if (!source_data) { + ro_warn_user("MiscError", "No document source"); + return; + } + + /* try to load local files directly. */ + if (netsurf_nsurl_to_path(hlcache_handle_get_url(c), &temp_name) == NSERROR_OK) { + error = xosfile_read_no_path(temp_name, &objtype, 0, 0, 0, 0); + if ((!error) && (objtype == osfile_IS_FILE)) { + snprintf(message.file_name, 212, "%s", temp_name); + message.file_name[211] = '\0'; + done = true; + } + free(temp_name); + } + if (!done) { + /* We cannot release the requested filename until after it + * has finished being used. As we can't easily find out when + * this is, we simply don't bother releasing it and simply + * allow it to be re-used next time NetSurf is started. The + * memory overhead from doing this is under 1 byte per + * filename. */ + char *r; + char full_name[256]; + const char *filename = filename_request(); + if (!filename) { + ro_warn_user("NoMemory", 0); + return; + } + + snprintf(full_name, 256, "%s/%s", TEMP_FILENAME_PREFIX, + filename); + full_name[255] = '\0'; + r = __riscosify(full_name, 0, __RISCOSIFY_NO_SUFFIX, + message.file_name, 212, 0); + if (r == 0) { + LOG("__riscosify failed"); + return; + } + message.file_name[211] = '\0'; + + error = xosfile_save_stamped(message.file_name, + ro_content_filetype(c), + (byte *) source_data, + (byte *) source_data + source_size); + if (error) { + LOG("xosfile_save_stamped failed: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("MiscError", error->errmess); + return; + } + } + + /* begin the DataOpen protocol */ + message.your_ref = 0; + message.size = 44 + ((strlen(message.file_name) + 4) & (~3u)); + message.action = message_DATA_OPEN; + message.w = 0; + message.i = 0; + message.pos.x = 0; + message.pos.y = 0; + message.est_size = 0; + message.file_type = 0xfff; + ro_message_send_message(wimp_USER_MESSAGE_RECORDED, + (wimp_message*)&message, 0, + ro_gui_view_source_bounce); +} + + +/** + * Broadcast an URL that we can't handle. + */ +static nserror gui_launch_url(struct nsurl *url) +{ + /* Try ant broadcast */ + ro_url_broadcast(nsurl_access(url)); + return NSERROR_OK; +} + + +/** + * Choose the language to use. + */ +static void ro_gui_choose_language(void) +{ + /* if option_language exists and is valid, use that */ + if (nsoption_charp(language)) { + char path[40]; + if (2 < strlen(nsoption_charp(language))) + nsoption_charp(language)[2] = 0; + sprintf(path, "NetSurf:Resources.%s", nsoption_charp(language)); + + if (is_dir(path)) { + nsoption_setnull_charp(accept_language, + strdup(nsoption_charp(language))); + return; + } + nsoption_set_charp(language, NULL); + } + + nsoption_set_charp(language, strdup(ro_gui_default_language())); + if (nsoption_charp(language) == NULL) + die("Out of memory"); + nsoption_set_charp(accept_language, strdup(nsoption_charp(language))); + if (nsoption_charp(accept_language) == NULL) + die("Out of memory"); +} + + +/** + * Display a warning for a serious problem (eg memory exhaustion). + * + * \param warning message key for warning message + * \param detail additional message, or 0 + */ +nserror ro_warn_user(const char *warning, const char *detail) +{ + LOG("%s %s", warning, detail); + + if (dialog_warning) { + char warn_buffer[300]; + snprintf(warn_buffer, sizeof warn_buffer, "%s %s", + messages_get(warning), + detail ? detail : ""); + warn_buffer[sizeof warn_buffer - 1] = 0; + ro_gui_set_icon_string(dialog_warning, ICON_WARNING_MESSAGE, + warn_buffer, true); + xwimp_set_icon_state(dialog_warning, ICON_WARNING_HELP, + wimp_ICON_DELETED, wimp_ICON_DELETED); + ro_gui_dialog_open(dialog_warning); + xos_bell(); + } else { + /* probably haven't initialised (properly), use a + non-multitasking error box */ + os_error error; + snprintf(error.errmess, sizeof error.errmess, "%s %s", + messages_get(warning), + detail ? detail : ""); + error.errmess[sizeof error.errmess - 1] = 0; + xwimp_report_error_by_category(&error, + wimp_ERROR_BOX_OK_ICON | + wimp_ERROR_BOX_GIVEN_CATEGORY | + wimp_ERROR_BOX_CATEGORY_ERROR << + wimp_ERROR_BOX_CATEGORY_SHIFT, + "NetSurf", "!netsurf", + (osspriteop_area *) 1, 0, 0); + } + + return NSERROR_OK; +} + + +/** + * Display an error and exit. + * + * Should only be used during initialisation. + */ +void die(const char * const error) +{ + os_error warn_error; + + LOG("%s", error); + + warn_error.errnum = 1; /* \todo: reasonable ? */ + strncpy(warn_error.errmess, messages_get(error), + sizeof(warn_error.errmess)-1); + warn_error.errmess[sizeof(warn_error.errmess)-1] = '\0'; + xwimp_report_error_by_category(&warn_error, + wimp_ERROR_BOX_OK_ICON | + wimp_ERROR_BOX_GIVEN_CATEGORY | + wimp_ERROR_BOX_CATEGORY_ERROR << + wimp_ERROR_BOX_CATEGORY_SHIFT, + "NetSurf", "!netsurf", + (osspriteop_area *) 1, 0, 0); + exit(EXIT_FAILURE); +} + + +/** + * Test whether it's okay to shutdown, prompting the user if not. + * + * \return true iff it's okay to shutdown immediately + */ +bool ro_gui_prequit(void) +{ + return ro_gui_download_prequit(); +} + + +/** + * Generate a riscos path from one or more component elemnts. + * + * Constructs a complete path element from passed components. The + * second (and subsequent) components have a slash substituted for all + * riscos directory separators. + * + * If a string is allocated it must be freed by the caller. + * + * @param[in,out] str pointer to string pointer if this is NULL enough + * storage will be allocated for the complete path. + * @param[in,out] size The size of the space available if \a str not + * NULL on input and if not NULL set to the total + * output length on output. + * @param[in] nelm The number of elements. + * @param[in] ap The elements of the path as string pointers. + * @return NSERROR_OK and the complete path is written to str + * or error code on faliure. + */ +static nserror riscos_mkpath(char **str, size_t *size, size_t nelm, va_list ap) +{ + const char *elm[16]; + size_t elm_len[16]; + size_t elm_idx; + char *fname; + size_t fname_len = 0; + char *curp; + size_t idx; + + /* check the parameters are all sensible */ + if ((nelm == 0) || (nelm > 16)) { + return NSERROR_BAD_PARAMETER; + } + if ((*str != NULL) && (size == NULL)) { + /* if the caller is providing the buffer they must say + * how much space is available. + */ + return NSERROR_BAD_PARAMETER; + } + + /* calculate how much storage we need for the complete path + * with all the elements. + */ + for (elm_idx = 0; elm_idx < nelm; elm_idx++) { + elm[elm_idx] = va_arg(ap, const char *); + /* check the argument is not NULL */ + if (elm[elm_idx] == NULL) { + return NSERROR_BAD_PARAMETER; + } + elm_len[elm_idx] = strlen(elm[elm_idx]); + fname_len += elm_len[elm_idx]; + } + fname_len += nelm; /* allow for separators and terminator */ + + /* ensure there is enough space */ + fname = *str; + if (fname != NULL) { + if (fname_len > *size) { + return NSERROR_NOSPACE; + } + } else { + fname = malloc(fname_len); + if (fname == NULL) { + return NSERROR_NOMEM; + } + } + + /* copy the elements in with directory separator */ + curp = fname; + + /* first element is not altered */ + memmove(curp, elm[0], elm_len[0]); + curp += elm_len[0]; + /* ensure there is a delimiter */ + if (curp[-1] != DIR_SEP) { + *curp = DIR_SEP; + curp++; + } + + /* subsequent elemnts have slashes substituted with directory + * separators. + */ + for (elm_idx = 1; elm_idx < nelm; elm_idx++) { + for (idx = 0; idx < elm_len[elm_idx]; idx++) { + if (elm[elm_idx][idx] == DIR_SEP) { + *curp = '/'; + } else { + *curp = elm[elm_idx][idx]; + } + curp++; + } + *curp = DIR_SEP; + curp++; + } + curp[-1] = 0; /* NULL terminate */ + + assert((curp - fname) <= (int)fname_len); + + *str = fname; + if (size != NULL) { + *size = fname_len; + } + + return NSERROR_OK; + +} + + +/** + * Get the basename of a file using posix path handling. + * + * This gets the last element of a path and returns it. The returned + * element has all forward slashes translated into riscos directory + * separators. + * + * @param[in] path The path to extract the name from. + * @param[in,out] str Pointer to string pointer if this is NULL enough + * storage will be allocated for the path element. + * @param[in,out] size The size of the space available if \a + * str not NULL on input and set to the total + * output length on output. + * @return NSERROR_OK and the complete path is written to str + * or error code on faliure. + */ +static nserror riscos_basename(const char *path, char **str, size_t *size) +{ + const char *leafname; + char *fname; + char *temp; + + if (path == NULL) { + return NSERROR_BAD_PARAMETER; + } + + leafname = strrchr(path, DIR_SEP); + if (!leafname) { + leafname = path; + } else { + leafname += 1; + } + + fname = strdup(leafname); + if (fname == NULL) { + return NSERROR_NOMEM; + } + + /** @todo check this leafname translation is actually required */ + /* and s/\//\./g */ + for (temp = fname; *temp != 0; temp++) { + if (*temp == '/') { + *temp = DIR_SEP; + } + } + + *str = fname; + if (size != NULL) { + *size = strlen(fname); + } + return NSERROR_OK; +} + + +/** + * Ensure that all directory elements needed to store a filename exist. + * + * Given a path of x.y.z directories x and x.y will be created. + * + * @param fname The filename to ensure the path to exists. + * @return NSERROR_OK on success or error code on failure. + */ +static nserror riscos_mkdir_all(const char *fname) +{ + char *dname; + char *cur; + + dname = strdup(fname); + + cur = dname; + while ((cur = strchr(cur, '.'))) { + *cur = '\0'; + xosfile_create_dir(dname, 0); + *cur++ = '.'; + } + + free(dname); + + return NSERROR_OK; +} + +/** + * Find screen size in OS units. + */ +void ro_gui_screen_size(int *width, int *height) +{ + *width = screen_info.width; + *height = screen_info.height; +} + + +/** + * Send the debug dump of a content to a text editor. + */ +void ro_gui_dump_browser_window(struct browser_window *bw) +{ + os_error *error; + + /* open file for dump */ + FILE *stream = fopen("<Wimp$ScrapDir>.WWW.NetSurf.dump", "w"); + if (!stream) { + LOG("fopen: errno %i", errno); + ro_warn_user("SaveError", strerror(errno)); + return; + } + + browser_window_debug_dump(bw, stream, CONTENT_DEBUG_RENDER); + + fclose(stream); + + /* launch file in editor */ + error = xwimp_start_task("Filer_Run <Wimp$ScrapDir>.WWW.NetSurf.dump", + 0); + if (error) { + LOG("xwimp_start_task failed: 0x%x: %s", error->errnum, error->errmess); + ro_warn_user("WimpError", error->errmess); + } +} + + +static struct gui_file_table riscos_file_table = { + .mkpath = riscos_mkpath, + .basename = riscos_basename, + .nsurl_to_path = ro_nsurl_to_path, + .path_to_nsurl = ro_path_to_nsurl, + .mkdir_all = riscos_mkdir_all, +}; + +static struct gui_fetch_table riscos_fetch_table = { + .filetype = fetch_filetype, + + .get_resource_url = gui_get_resource_url, + .mimetype = fetch_mimetype, +}; + +static struct gui_misc_table riscos_misc_table = { + .schedule = riscos_schedule, + .warning = ro_warn_user, + + .quit = gui_quit, + .launch_url = gui_launch_url, + .cert_verify = gui_cert_verify, + .login = gui_401login_open, +}; + + +static char *get_cachepath(void) +{ + char *cachedir; + char *cachepath = NULL; + nserror ret; + + cachedir = getenv("Cache$Dir"); + if ((cachedir == NULL) || (cachedir[0] == 0)) { + LOG("cachedir was null"); + return NULL; + } + ret = netsurf_mkpath(&cachepath, NULL, 2, cachedir, "NetSurf"); + if (ret != NSERROR_OK) { + return NULL; + } + return cachepath; +} + +/** + * Normal entry point from RISC OS. + */ +int main(int argc, char** argv) +{ + char *cachepath; + char path[40]; + int length; + os_var_type type; + int used = -1; /* slightly better with older OSLib versions */ + os_error *error; + nserror ret; + struct netsurf_table riscos_table = { + .misc = &riscos_misc_table, + .window = riscos_window_table, + .clipboard = riscos_clipboard_table, + .download = riscos_download_table, + .fetch = &riscos_fetch_table, + .file = &riscos_file_table, + .utf8 = riscos_utf8_table, + .search = riscos_search_table, + .llcache = filesystem_llcache_table, + .bitmap = riscos_bitmap_table, + .layout = riscos_layout_table, + }; + + ret = netsurf_register(&riscos_table); + if (ret != NSERROR_OK) { + die("NetSurf operation table failed registration"); + } + + /* Consult NetSurf$Logging environment variable to decide if logging + * is required. */ + error = xos_read_var_val_size("NetSurf$Logging", 0, os_VARTYPE_STRING, + &used, NULL, &type); + if (error != NULL || type != os_VARTYPE_STRING || used != -2) { + verbose_log = true; + } else { + char logging_env[2]; + error = xos_read_var_val("NetSurf$Logging", logging_env, + sizeof(logging_env), 0, os_VARTYPE_STRING, + &used, NULL, &type); + if (error != NULL || logging_env[0] != '0') { + verbose_log = true; + } else { + verbose_log = false; + } + } + + /* initialise logging. Not fatal if it fails but not much we + * can do about it either. + */ + nslog_init(nslog_stream_configure, &argc, argv); + + /* user options setup */ + ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default); + if (ret != NSERROR_OK) { + die("Options failed to initialise"); + } + nsoption_read("NetSurf:Choices", NULL); + nsoption_commandline(&argc, argv, NULL); + + /* Choose the interface language to use */ + ro_gui_choose_language(); + + /* select language-specific Messages */ + if (((length = snprintf(path, + sizeof(path), + "NetSurf:Resources.%s.Messages", + nsoption_charp(language))) < 0) || + (length >= (int)sizeof(path))) { + die("Failed to locate Messages resource."); + } + + /* initialise messages */ + messages_add_from_file(path); + + /* obtain cache path */ + cachepath = get_cachepath(); + + /* common initialisation */ + ret = netsurf_init(cachepath); + free(cachepath); + if (ret != NSERROR_OK) { + die("NetSurf failed to initialise core"); + } + + artworks_init(); + draw_init(); + sprite_init(); + + /* Load some extra RISC OS specific Messages */ + messages_add_from_file("NetSurf:Resources.LangNames"); + + ret = gui_init(argc, argv); + if (ret != NSERROR_OK) { + ro_warn_user(messages_get_errorcode(ret), 0); + } + + while (!riscos_done) { + riscos_poll(); + } + + netsurf_exit(); + + return 0; +} diff --git a/frontends/riscos/gui.h b/frontends/riscos/gui.h new file mode 100644 index 000000000..624f9e2fb --- /dev/null +++ b/frontends/riscos/gui.h @@ -0,0 +1,271 @@ +/* + * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net> + * Copyright 2004 James Bursa <bursa@users.sourceforge.net> + * Copyright 2004 Andrew Timmins <atimmins@blueyonder.co.uk> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _NETSURF_RISCOS_GUI_H_ +#define _NETSURF_RISCOS_GUI_H_ + +#include <oslib/wimp.h> + +#define RISCOS5 0xAA + +#define THUMBNAIL_WIDTH 100 +#define THUMBNAIL_HEIGHT 86 + +/* The maximum size for user-editable URLs in the RISC OS GUI. */ + +#define RO_GUI_MAX_URL_SIZE 2048 + +extern int os_version; + +extern const char * NETSURF_DIR; + +struct toolbar; +struct status_bar; +struct plotter_table; +struct gui_window; +struct tree; +struct node; +struct history; +struct css_style; +struct ssl_cert_info; +struct nsurl; +struct hlcache_handle; + +enum gui_pointer_shape; + +extern wimp_t task_handle; /**< RISC OS wimp task handle. */ + +extern wimp_w dialog_info, dialog_saveas, dialog_zoom, dialog_pageinfo, + dialog_objinfo, dialog_tooltip, dialog_warning, dialog_openurl, + dialog_folder, dialog_entry, dialog_url_complete, + dialog_search, dialog_print, dialog_theme_install; +extern wimp_w current_menu_window; +extern bool current_menu_open; +extern wimp_menu *recent_search_menu; /* search.c */ +extern wimp_w history_window; +extern bool gui_redraw_debug; +extern osspriteop_area *gui_sprites; +extern bool dialog_folder_add, dialog_entry_add, hotlist_insert; +extern bool print_active, print_text_black; +extern bool no_font_blending; + +typedef enum { GUI_DRAG_NONE, GUI_DRAG_DOWNLOAD_SAVE, GUI_DRAG_SAVE } + ro_gui_drag_type; + +extern ro_gui_drag_type gui_current_drag_type; + +extern bool riscos_done; + +/** RISC OS data for a browser window. */ +struct gui_window { + /** Associated platform-independent browser window data. */ + struct browser_window *bw; + + struct toolbar *toolbar; /**< Toolbar, or 0 if not present. */ + struct status_bar *status_bar; /**< Status bar, or 0 if not present. */ + + wimp_w window; /**< RISC OS window handle. */ + + int old_width; /**< Width when last opened / os units. */ + int old_height; /**< Height when last opened / os units. */ + bool update_extent; /**< Update the extent on next opening */ + bool active; /**< Whether the throbber should be active */ + + char title[256]; /**< Buffer for window title. */ + + int iconise_icon; /**< ID number of icon when window is iconised */ + + char validation[12]; /**< Validation string for colours */ + + float scale; /**< Browser window scale */ + + /** Options. */ + struct { + bool buffer_animations; /**< Use screen buffering for animations. */ + bool buffer_everything; /**< Use screen buffering for everything. */ + } option; + + struct gui_window *prev; /**< Previous in linked list. */ + struct gui_window *next; /**< Next in linked list. */ +}; + + +extern struct gui_window *ro_gui_current_redraw_gui; + + +/* in gui.c */ +void ro_gui_open_window_request(wimp_open *open); +void ro_gui_screen_size(int *width, int *height); +void ro_gui_view_source(struct hlcache_handle *c); +void ro_gui_dump_browser_window(struct browser_window *bw); +void ro_gui_drag_box_start(wimp_pointer *pointer); +bool ro_gui_prequit(void); +const char *ro_gui_default_language(void); +nserror ro_warn_user(const char *warning, const char *detail); + +/** + * Cause an abnormal program termination. + * + * \note This never returns and is intended to terminate without any cleanup. + * + * \param error The message to display to the user. + */ +void die(const char * const error) __attribute__ ((noreturn)); + +/* in download.c */ +void ro_gui_download_init(void); +void ro_gui_download_datasave_ack(wimp_message *message); +bool ro_gui_download_prequit(void); +extern struct gui_download_table *riscos_download_table; + +/* in 401login.c */ +void ro_gui_401login_init(void); +void gui_401login_open(struct nsurl *url, const char *realm, + nserror (*cb)(bool proceed, void *pw), void *cbpw); + +/* in window.c */ +void ro_gui_window_set_scale(struct gui_window *g, float scale); +bool ro_gui_window_dataload(struct gui_window *g, wimp_message *message); +void ro_gui_window_mouse_at(wimp_pointer *pointer, void *data); +void ro_gui_window_iconise(struct gui_window *g, + wimp_full_message_window_info *wi); +bool ro_gui_toolbar_dataload(struct gui_window *g, wimp_message *message); +void ro_gui_window_redraw_all(void); +void ro_gui_window_update_boxes(void); +void ro_gui_window_quit(void); +/* void ro_gui_window_close_all(void); */ +#define ro_gui_window_close_all ro_gui_window_quit /* no need for a separate fn */ +void ro_gui_throb(void); +void ro_gui_window_default_options(struct gui_window *gui); +struct gui_window *ro_gui_window_lookup(wimp_w window); +struct gui_window *ro_gui_toolbar_lookup(wimp_w window); +bool ro_gui_window_to_window_pos(struct gui_window *g, int x, int y, + os_coord *pos); +bool ro_gui_window_to_screen_pos(struct gui_window *g, int x, int y, + os_coord *pos); +enum browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons, + wimp_icon_flags type); +enum browser_mouse_state ro_gui_mouse_drag_state(wimp_mouse_state buttons, + wimp_icon_flags type); +bool ro_gui_shift_pressed(void); +bool ro_gui_ctrl_pressed(void); +bool ro_gui_alt_pressed(void); +void gui_window_set_pointer(struct gui_window *g, enum gui_pointer_shape shape); + +/* in history.c */ +void ro_gui_history_init(void); +void ro_gui_history_open(struct gui_window *g, bool pointer); + +/* in schedule.c */ +extern bool sched_active; +extern os_t sched_time; + +/** + * Process events up to current time. + */ +bool schedule_run(void); + +/** + * Schedule a callback. + * + * \param t interval before the callback should be made in ms + * \param callback callback function + * \param p user parameter, passed to callback function + * + * The callback function will be called as soon as possible after t ms have + * passed. + */ +nserror riscos_schedule(int t, void (*callback)(void *p), void *p); + +/* in search.c */ +void ro_gui_search_init(void); +void ro_gui_search_prepare(struct browser_window *g); +struct gui_search_table *riscos_search_table; + +/* in print.c */ +void ro_gui_print_init(void); +void ro_gui_print_prepare(struct gui_window *g); + +/* in plotters.c */ +extern const struct plotter_table ro_plotters; +extern int ro_plot_origin_x; +extern int ro_plot_origin_y; + +/* in theme_install.c */ +bool ro_gui_theme_install_apply(wimp_w w); + +/* in sslcert.c */ +void gui_cert_verify(struct nsurl *url, + const struct ssl_cert_info *certs, unsigned long num, + nserror (*cb)(bool proceed, void *pw), void *cbpw); + +/* icon numbers */ +#define ICON_STATUS_RESIZE 0 +#define ICON_STATUS_TEXT 1 + +#define ICON_SAVE_ICON 0 +#define ICON_SAVE_PATH 1 +#define ICON_SAVE_OK 2 +#define ICON_SAVE_CANCEL 3 + +#define ICON_PAGEINFO_TITLE 0 +#define ICON_PAGEINFO_URL 1 +#define ICON_PAGEINFO_ENC 2 +#define ICON_PAGEINFO_TYPE 3 +#define ICON_PAGEINFO_ICON 4 + +#define ICON_OBJINFO_URL 0 +#define ICON_OBJINFO_TARGET 1 +#define ICON_OBJINFO_TYPE 2 +#define ICON_OBJINFO_ICON 3 + +#define ICON_WARNING_MESSAGE 0 +#define ICON_WARNING_CONTINUE 1 +#define ICON_WARNING_HELP 2 + +#define ICON_SEARCH_TEXT 0 +#define ICON_SEARCH_CASE_SENSITIVE 1 +#define ICON_SEARCH_FIND_NEXT 2 +#define ICON_SEARCH_FIND_PREV 3 +#define ICON_SEARCH_CANCEL 4 +#define ICON_SEARCH_STATUS 5 +#define ICON_SEARCH_MENU 8 +#define ICON_SEARCH_SHOW_ALL 9 + +#define ICON_THEME_INSTALL_MESSAGE 0 +#define ICON_THEME_INSTALL_INSTALL 1 +#define ICON_THEME_INSTALL_CANCEL 2 + +#define ICON_OPENURL_URL 1 +#define ICON_OPENURL_CANCEL 2 +#define ICON_OPENURL_OPEN 3 +#define ICON_OPENURL_MENU 4 + +#define ICON_ENTRY_NAME 1 +#define ICON_ENTRY_URL 3 +#define ICON_ENTRY_CANCEL 4 +#define ICON_ENTRY_OK 5 +#define ICON_ENTRY_RECENT 6 + +#define ICON_FOLDER_NAME 1 +#define ICON_FOLDER_CANCEL 2 +#define ICON_FOLDER_OK 3 + +#endif diff --git a/frontends/riscos/gui/button_bar.c b/frontends/riscos/gui/button_bar.c new file mode 100644 index 000000000..6ecd7cffa --- /dev/null +++ b/frontends/riscos/gui/button_bar.c @@ -0,0 +1,1229 @@ +/* + * Copyright 2004, 2005 Richard Wilson <info@tinct.net> + * Copyright 2011 Stephen Fryatt <stevef@netsurf-browser.org> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * Button bars (implementation). + */ + +#include <assert.h> +#include <stdio.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <oslib/dragasprite.h> +#include <oslib/os.h> +#include <oslib/osspriteop.h> +#include <oslib/wimp.h> +#include <oslib/wimpspriteop.h> + +#include "utils/log.h" + +#include "riscos/gui/button_bar.h" +#include "riscos/gui.h" +#include "riscos/mouse.h" +#include "riscos/theme.h" +#include "riscos/wimp.h" + +#define BUTTONBAR_SPRITE_NAME_LENGTH 12 +#define BUTTONBAR_VALIDATION_LENGTH 40 + +struct button_bar_button { + wimp_i icon; + bool shaded; + bool separator; + + button_bar_action select_action; + button_bar_action adjust_action; + + int x_pos, y_pos; + int x_size, y_size; + + char sprite[BUTTONBAR_SPRITE_NAME_LENGTH]; + char validation[BUTTONBAR_VALIDATION_LENGTH]; + char opt_key; + const char *help_suffix; + + struct button_bar_button *bar_next; + struct button_bar_button *next; +}; + + +struct button_bar { + /** The applied theme (or NULL to use the default) */ + struct theme_descriptor *theme; + + /** The widget dimensions. */ + int x_min, y_min; + int separator_width; + int vertical_offset; + + bool separators; + + /** The window details and bar position. */ + wimp_w window; + os_box extent; + osspriteop_area *sprites; + int background; + + bool hidden; + + bool edit; + struct button_bar *edit_target; + struct button_bar *edit_source; + void (*edit_refresh)(void *); + void *edit_client_data; + + /** The list of all the defined buttons. */ + + struct button_bar_button *buttons; + + /** The list of the buttons in the current bar. */ + + struct button_bar_button *bar; +}; + +static char null_text_string[] = ""; +static char separator_name[] = "separator"; + +static struct button_bar *drag_start = NULL; +static char drag_opt = '\0'; +static bool drag_separator = false; + +/* + * Private function prototypes. + */ + +static bool ro_gui_button_bar_place_buttons(struct button_bar *button_bar); +static bool ro_gui_button_bar_icon_update(struct button_bar *button_bar); +static bool ro_gui_button_bar_icon_resize(struct button_bar *button_bar); +static void ro_gui_button_bar_drag_end(wimp_dragged *drag, void *data); +static void ro_gui_button_bar_sync_editors(struct button_bar *target, + struct button_bar *source); +static struct button_bar_button *ro_gui_button_bar_find_icon( + struct button_bar *button_bar, wimp_i icon); +static struct button_bar_button *ro_gui_button_bar_find_opt_key( + struct button_bar *button_bar, char opt_key); +static struct button_bar_button *ro_gui_button_bar_find_action( + struct button_bar *button_bar, button_bar_action action); +static struct button_bar_button *ro_gui_button_bar_find_coords( + struct button_bar *button_bar, os_coord pos, + bool *separator, bool *right); + +/* This is an exported interface documented in button_bar.h */ + +struct button_bar *ro_gui_button_bar_create(struct theme_descriptor *theme, + const struct button_bar_buttons buttons[]) +{ + struct button_bar *button_bar; + struct button_bar_button *icon, *new_icon; + int def; + + /* Allocate memory. */ + + button_bar = malloc(sizeof(struct button_bar)); + if (button_bar == NULL) { + LOG("No memory for malloc()"); + return NULL; + } + + /* Set up default parameters. */ + + button_bar->theme = theme; + button_bar->sprites = ro_gui_theme_get_sprites(theme); + button_bar->background = wimp_COLOUR_VERY_LIGHT_GREY; + + button_bar->x_min = -1; + button_bar->y_min = -1; + button_bar->separator_width = 0; + button_bar->vertical_offset = 0; + + button_bar->separators = false; + + button_bar->window = NULL; + + button_bar->hidden = false; + + button_bar->edit = false; + button_bar->edit_target = NULL; + button_bar->edit_source = NULL; + button_bar->edit_refresh = NULL; + button_bar->edit_client_data = NULL; + + button_bar->buttons = NULL; + + /* Process the button icon definitions */ + + icon = NULL; + + for (def = 0; buttons[def].icon != NULL; def++) { + new_icon = malloc(sizeof(struct button_bar_button)); + if (new_icon == NULL) { + break; + } + + if (icon == NULL) { + button_bar->buttons = new_icon; + button_bar->bar = new_icon; + } else { + icon->next = new_icon; + icon->bar_next = new_icon; + } + icon = new_icon; + icon->next = NULL; + icon->bar_next = NULL; + + strncpy(icon->sprite, buttons[def].icon, + BUTTONBAR_SPRITE_NAME_LENGTH); + snprintf(icon->validation, BUTTONBAR_VALIDATION_LENGTH, + "R5;S%s,p%s", icon->sprite, icon->sprite); + + icon->icon = -1; + icon->shaded = false; + icon->separator = false; + + icon->select_action = buttons[def].select; + icon->adjust_action = buttons[def].adjust; + icon->opt_key = buttons[def].opt_key; + icon->help_suffix = buttons[def].help; + } + + /* Add a separator after the last entry. This will be lost if the + * buttons are subsequently set, but is used for the edit source bar. + */ + + if (icon != NULL) + icon->separator = true; + + return button_bar; +} + + +/* This is an exported interface documented in button_bar.h */ + +bool ro_gui_button_bar_link_editor(struct button_bar *target, + struct button_bar *source, void (* refresh)(void *), + void *client_data) +{ + if (target == NULL || source == NULL || + target->edit_target != NULL || + target->edit_source != NULL || + source->edit_target != NULL || + source->edit_source != NULL) + return false; |