From 80bee65a71a7e85cb800e5d1d1f58525c855cb09 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 4 Jun 2014 16:44:29 +0100 Subject: remove forward declarations from risc os gui.c cleanup filetype magic numbers. --- riscos/download.c | 1 + riscos/filetype.c | 74 +- riscos/filetype.h | 126 +++ riscos/gui.c | 2928 ++++++++++++++++++++++++------------------------- riscos/gui.h | 9 - riscos/gui/url_bar.c | 1 + riscos/print.c | 1 + riscos/save.c | 1 + riscos/url_complete.c | 1 + riscos/window.c | 1 + 10 files changed, 1570 insertions(+), 1573 deletions(-) create mode 100644 riscos/filetype.h diff --git a/riscos/download.c b/riscos/download.c index 6109d6933..a03ff474b 100644 --- a/riscos/download.c +++ b/riscos/download.c @@ -63,6 +63,7 @@ #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 diff --git a/riscos/filetype.c b/riscos/filetype.c index d71c500c0..0a546d833 100644 --- a/riscos/filetype.c +++ b/riscos/filetype.c @@ -24,7 +24,7 @@ #include "content/content.h" #include "content/fetch.h" #include "content/hlcache.h" -#include "riscos/gui.h" +#include "riscos/filetype.h" #include "utils/config.h" #include "utils/log.h" #include "utils/utils.h" @@ -60,13 +60,7 @@ static char type_buf[BUF_SIZE]; static int cmp_type(const void *x, const void *y); -/** - * 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. - */ +/* exported interface documented in riscos/filetype.h */ const char *fetch_filetype(const char *unix_path) { struct type_entry *t; @@ -154,12 +148,7 @@ 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 - */ +/* exported interface documented in riscos/filetype.h */ char *fetch_mimetype(const char *ro_path) { os_error *e; @@ -246,12 +235,7 @@ int cmp_type(const void *x, const void *y) return *p < q->file_type ? -1 : (*p == q->file_type ? 0 : +1); } -/** - * Determine the RISC OS filetype for a content. - * - * \param content The content to examine. - * \return The RISC OS filetype corresponding to the content - */ +/* exported interface documented in riscos/filetype.h */ int ro_content_filetype(hlcache_handle *c) { lwc_string *mime_type; @@ -270,25 +254,21 @@ int ro_content_filetype(hlcache_handle *c) return file_type; } -/** - * Determine the native RISC OS filetype to export a content as - * - * \param c The content to examine - * \return Native RISC OS filetype for export - */ + +/* exported interface documented in riscos/filetype.h */ int ro_content_native_type(hlcache_handle *c) { switch (ro_content_filetype(c)) { - case 0xc85: /* jpeg */ - case 0xf78: /* jng */ - case 0xf83: /* mng */ - case 0x695: /* gif */ - case 0x69c: /* bmp */ - case 0x132: /* ico */ - case 0xb60: /* png */ + 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 0xaad: /* svg */ + case FILETYPE_SVG: /* svg */ case 0xaff: /* draw */ return osfile_TYPE_DRAW; default: @@ -298,12 +278,8 @@ int ro_content_native_type(hlcache_handle *c) return osfile_TYPE_DATA; } -/** - * Determine the RISC OS filetype for a MIME type - * - * \param mime_type MIME type to consider - * \return Corresponding RISC OS filetype - */ + +/* exported interface documented in riscos/filetype.h */ int ro_content_filetype_from_mime_type(lwc_string *mime_type) { int file_type, index; @@ -329,15 +305,11 @@ int ro_content_filetype_from_mime_type(lwc_string *mime_type) return file_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 - */ + +/* exported interface documented in riscos/filetype.h */ int ro_content_filetype_from_type(content_type type) { switch (type) { - case CONTENT_HTML: return 0xfaf; + case CONTENT_HTML: return FILETYPE_HTML; case CONTENT_TEXTPLAIN: return 0xfff; case CONTENT_CSS: return 0xf79; default: break; @@ -345,12 +317,8 @@ int ro_content_filetype_from_type(content_type type) { return 0; } -/** - * Determine the type of a local file. - * - * \param unix_path Unix style path to file on disk - * \return File type - */ + +/* exported interface documented in riscos/filetype.h */ bits ro_filetype_from_unix_path(const char *unix_path) { unsigned int len = strlen(unix_path) + 100; diff --git a/riscos/filetype.h b/riscos/filetype.h new file mode 100644 index 000000000..115c1ef3b --- /dev/null +++ b/riscos/filetype.h @@ -0,0 +1,126 @@ +/* + * Copyright 2014 Vincent Sanders + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file riscos/filetype.h + * RISC OS filetpe interface. + */ + +#ifndef _NETSURF_RISCOS_FILETYPE_H_ +#define _NETSURF_RISCOS_FILETYPE_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 content The content to examine. + * \return The RISC OS filetype corresponding to the content + */ +int ro_content_filetype(struct hlcache_handle *c); + +/** + * 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/riscos/gui.c b/riscos/gui.c index 691264d89..e6602acf8 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -21,131 +21,65 @@ * along with this program. If not, see . */ +#include +#include #include #include -#include #include -#include -#include -#include -#include -#include -#include #include -#include -#include "oslib/font.h" -#include "oslib/help.h" -#include "oslib/hourglass.h" -#include "oslib/inetsuite.h" -#include "oslib/os.h" -#include "oslib/osbyte.h" -#include "oslib/osfile.h" -#include "oslib/osfscontrol.h" -#include "oslib/osgbpb.h" -#include "oslib/osmodule.h" -#include "oslib/osspriteop.h" -#include "oslib/pdriver.h" -#include "oslib/plugin.h" -#include "oslib/wimp.h" -#include "oslib/wimpspriteop.h" -#include "oslib/uri.h" -#include "rufl.h" - -#include "utils/config.h" -#include "utils/filename.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/utils.h" #include "utils/corestrings.h" -#include "content/content.h" -#include "content/hlcache.h" -#include "content/urldb.h" -#include "content/fetchers/resource.h" #include "desktop/gui.h" -#include "desktop/netsurf.h" -#include "utils/nsoption.h" #include "desktop/save_complete.h" #include "desktop/treeview.h" -#include "render/font.h" -#include "utils/file.h" +#include "desktop/netsurf.h" +#include "content/urldb.h" +#include "content/hlcache.h" -#include "riscos/content-handlers/artworks.h" -#include "riscos/bitmap.h" -#include "riscos/buffer.h" -#include "riscos/cookies.h" -#include "riscos/dialog.h" -#include "riscos/content-handlers/draw.h" -#include "riscos/global_history.h" #include "riscos/gui.h" -#include "riscos/gui/url_bar.h" -#include "riscos/help.h" +#include "riscos/wimputils.h" #include "riscos/hotlist.h" -#include "riscos/iconbar.h" -#include "riscos/menus.h" -#include "riscos/message.h" -#include "riscos/mouse.h" +#include "riscos/buffer.h" +#include "riscos/textselection.h" #include "riscos/print.h" -#include "riscos/query.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/content-handlers/sprite.h" -#include "riscos/textselection.h" -#include "riscos/theme.h" -#include "riscos/toolbar.h" -#include "riscos/treeview.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/url_complete.h" -#include "riscos/wimp.h" -#include "riscos/wimp_event.h" -#include "riscos/wimputils.h" -#include "riscos/window.h" +#include "riscos/mouse.h" #include "riscos/ucstables.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 +#include "riscos/filetype.h" +#include "riscos/content-handlers/artworks.h" +#include "riscos/content-handlers/draw.h" +#include "riscos/content-handlers/sprite.h" extern bool ro_plot_patterned_lines; @@ -167,11 +101,15 @@ static const char *task_name = "NetSurf"; #define CHOICES_PREFIX ".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 */ +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. */ +/** + * Accepted wimp user messages. + */ static ns_wimp_message_list task_messages = { message_HELP_REQUEST, { @@ -225,37 +163,25 @@ static ns_wimp_message_list task_messages = { } }; + static struct { - int width; /* in OS units */ - int height; + int width; /* in OS units */ + int height; } screen_info; -static void ro_gui_create_dirs(void); -static void ro_gui_create_dir(char *path); -static void ro_gui_choose_language(void); -static void ro_gui_signal(int sig); -static void ro_gui_cleanup(void); -static void ro_gui_handle_event(wimp_event_no event, wimp_block *block); -static void ro_gui_close_window_request(wimp_close *close); -static void ro_gui_check_resolvers(void); -static void ro_gui_keypress(wimp_key *key); -static void ro_gui_user_message(wimp_event_no event, wimp_message *message); -static void ro_msg_dataload(wimp_message *block); -static char *ro_gui_uri_file_parse(const char *file_name, char **uri_title); -static bool ro_gui_uri_file_parse_line(FILE *fp, char *b); -static char *ro_gui_url_file_parse(const char *file_name); -static char *ro_gui_ieurl_file_parse(const char *file_name); -static void ro_msg_terminate_filename(wimp_full_message_data_xfer *message); -static void ro_msg_datasave(wimp_message *message); -static void ro_msg_datasave_ack(wimp_message *message); -static void ro_msg_dataopen(wimp_message *message); -static void ro_gui_get_screen_properties(void); -static void ro_msg_prequit(wimp_message *message); -static void ro_msg_save_desktop(wimp_message *message); -static void ro_msg_window_info(wimp_message *message); -static void ro_gui_view_source_bounce(wimp_message *message); +/** + * 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/"; @@ -317,14 +243,21 @@ static nsurl *gui_get_resource_url(const char *path) return url; } + /** - * set option from wimp + * 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) + wimp_colour wimp, + enum nsoption_e option, + colour def_colour) { os_error *error; os_PALETTE(20) palette; @@ -343,17 +276,16 @@ set_colour_from_wimp(struct nsoption_s *opts, 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. - * + * @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) { @@ -402,1678 +334,1634 @@ static nserror set_defaults(struct nsoption_s *defaults) return NSERROR_OK; } + /** - * Initialise the gui (RISC OS specific part). + * Create directory structure for a path + * + * Given a path of x.y.z directories x and x.y will be created + * + * \param path the directory path to create */ - -static void gui_init(int argc, char** argv) +static void ro_gui_create_dir(char *path) { - struct { - void (*sigabrt)(int); - void (*sigfpe)(int); - void (*sigill)(int); - void (*sigint)(int); - void (*sigsegv)(int); - void (*sigterm)(int); - } prev_sigs; - char path[40]; - os_error *error; - int length; - char *nsdir_temp; - byte *base; - nserror err; + char *cur = path; + while ((cur = strchr(cur, '.'))) { + *cur = '\0'; + xosfile_create_dir(path, 0); + *cur++ = '.'; + } +} - /* 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)); +/** + * Create intermediate directories for Choices and User Data files + */ +static void ro_gui_create_dirs(void) +{ + char buf[256]; + char *path; - xhourglass_start(1); + /* Choices */ + path = getenv("NetSurf$ChoicesSave"); + if (!path) + die("Failed to find NetSurf Choices save path"); - /* 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); + snprintf(buf, sizeof(buf), "%s", path); + ro_gui_create_dir(buf); - /* 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; - } + /* URL */ + snprintf(buf, sizeof(buf), "%s", nsoption_charp(url_save)); + ro_gui_create_dir(buf); - /* Create our choices directories */ - ro_gui_create_dirs(); + /* Hotlist */ + snprintf(buf, sizeof(buf), "%s", nsoption_charp(hotlist_save)); + ro_gui_create_dir(buf); - /* 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); + /* Recent */ + snprintf(buf, sizeof(buf), "%s", nsoption_charp(recent_save)); + ro_gui_create_dir(buf); - 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) - die("Failed registering signal handlers"); + /* Theme */ + snprintf(buf, sizeof(buf), "%s", nsoption_charp(theme_save)); + ro_gui_create_dir(buf); + /* and the final directory part (as theme_save is a directory) */ + xosfile_create_dir(buf, 0); +} - /* 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"); +/** + * 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."); +} - /* Initialise filename allocator */ - filename_initialise(); - /* Initialise save complete functionality */ - save_complete_init(); +/** + * 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; - /* Load in visited URLs and Cookies */ - urldb_load(nsoption_charp(url_path)); - urldb_load_cookies(nsoption_charp(cookie_file)); + ro_gui_cleanup(); - /* 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); + xhourglass_on(); + xhourglass_colours(0x0000ffff, 0x000000ff, &old_sand, &old_glass); + nsoption_dump(stderr, NULL); + /*rufl_dump_state();*/ - /* Initialise the font subsystem */ - nsfont_init(); +#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); - /* 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); - } - - err = treeview_init(12); - if (err != NSERROR_OK) { - die("Failed to initialise treeview"); + 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. */ + _kernel_oserror *err = __unixlib_write_coredump (NULL); + if (err != NULL) + LOG(("Coredump failed: %s", err->errmess)); +#endif - /* 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(); + xhourglass_colours(old_sand, old_glass, 0, 0); + xhourglass_off(); - /* Done with the templates file */ - wimp_close_template(); + __write_backtrace(sig); - /* Create Iconbar icon and menus */ - ro_gui_iconbar_initialise(); + 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 .WWW.NetSurf.Log"); - /* Finally, check Inet$Resolvers for sanity */ - ro_gui_check_resolvers(); + _Exit(sig); } + /** - * Create intermediate directories for Choices and User Data files + * 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 */ -void ro_gui_create_dirs(void) +static bool ro_gui_uri_file_parse_line(FILE *fp, char *b) { - char buf[256]; - char *path; + int c; + unsigned int i = 0; - /* Choices */ - path = getenv("NetSurf$ChoicesSave"); - if (!path) - die("Failed to find NetSurf Choices save path"); + c = getc(fp); + if (c == EOF) + return false; - snprintf(buf, sizeof(buf), "%s", path); - ro_gui_create_dir(buf); + /* 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; + } - /* URL */ - snprintf(buf, sizeof(buf), "%s", nsoption_charp(url_save)); - ro_gui_create_dir(buf); + /* read "line" */ + do { + if (i == 399) + return false; + b[i++] = c; + c = getc(fp); + } while (c != EOF && 32 <= c); - /* Hotlist */ - snprintf(buf, sizeof(buf), "%s", nsoption_charp(hotlist_save)); - ro_gui_create_dir(buf); + /* skip line ending control characters */ + while (c != EOF && c < 32) + c = getc(fp); - /* Recent */ - snprintf(buf, sizeof(buf), "%s", nsoption_charp(recent_save)); - ro_gui_create_dir(buf); + if (c != EOF) + ungetc(c, fp); - /* Theme */ - snprintf(buf, sizeof(buf), "%s", nsoption_charp(theme_save)); - ro_gui_create_dir(buf); - /* and the final directory part (as theme_save is a directory) */ - xosfile_create_dir(buf, 0); + b[i] = 0; + return true; } /** - * Create directory structure for a path - * - * Given a path of x.y.z directories x and x.y will be created + * Parse an Acorn URI file. * - * \param path the directory path to create + * \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 */ -void ro_gui_create_dir(char *path) +static char *ro_gui_uri_file_parse(const char *file_name, char **uri_title) { - char *cur = path; - while ((cur = strchr(cur, '.'))) { - *cur = '\0'; - xosfile_create_dir(path, 0); - *cur++ = '.'; + /* 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))); + 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) { + 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 */ + warn_user("NoMemory", 0); } + fclose(fp); + + return url; + +uri_free: + free(url); + +uri_syntax_error: + fclose(fp); + warn_user("URIError", 0); + return 0; } /** - * Choose the language to use. + * Parse an ANT URL file. + * + * \param file_name file to read + * \return URL from file, or 0 on error and error reported */ - -void ro_gui_choose_language(void) +static char *ro_gui_url_file_parse(const char *file_name) { - /* 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)); + char line[400]; + char *url; + FILE *fp; - if (is_dir(path)) { - nsoption_setnull_charp(accept_language, - strdup(nsoption_charp(language))); - return; - } - nsoption_set_charp(language, NULL); + fp = fopen(file_name, "r"); + if (!fp) { + LOG(("fopen(\"%s\", \"r\"): %i: %s", + file_name, errno, strerror(errno))); + warn_user("LoadError", strerror(errno)); + return 0; } - 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"); + if (!fgets(line, sizeof line, fp)) { + if (ferror(fp)) { + LOG(("fgets: %i: %s", + errno, strerror(errno))); + warn_user("LoadError", strerror(errno)); + } else + 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) { + warn_user("NoMemory", 0); + return 0; + } + + return url; } /** - * Determine the default language to use. + * Parse an IEURL file. * - * RISC OS has no standard way of determining which language the user prefers. - * We have to guess from the 'Country' setting. + * \param file_name file to read + * \return URL from file, or 0 on error and error reported */ - -const char *ro_gui_default_language(void) +static char *ro_gui_ieurl_file_parse(const char *file_name) { - char path[40]; - const char *lang; - int country; - os_error *error; + char line[400]; + char *url = 0; + FILE *fp; - /* 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; + fp = fopen(file_name, "r"); + if (!fp) { + LOG(("fopen(\"%s\", \"r\"): %i: %s", + file_name, errno, strerror(errno))); + warn_user("LoadError", strerror(errno)); + return 0; } - 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"; + + 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); + warn_user("NoMemory", 0); + return 0; + } break; + } + } + if (ferror(fp)) { + LOG(("fgets: %i: %s", + errno, strerror(errno))); + warn_user("LoadError", strerror(errno)); + fclose(fp); + return 0; } - sprintf(path, "NetSurf:Resources.%s", lang); - if (is_dir(path)) - return lang; - return "en"; -} + fclose(fp); -/** - * Warn the user if Inet$Resolvers is not set. - */ + if (!url) + warn_user("URIError", 0); -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")); - warn_user("Resolvers", 0); - } + return url; } -/** - * Convert a RISC OS pathname to a file: URL. - * - * \param path RISC OS pathname - * \return URL, allocated on heap, or 0 on failure - */ /** - * Create a nsurl from a RISC OS pathname. - * - * Perform the necessary operations on a path to generate a nsurl. + * Handle Message_DataOpen (double-click on file in the Filer). * - * @param[in] path The RISC OS pathname to convert. - * @param[out] url 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. + * \param message The wimp message to open. */ -static nserror ro_path_to_nsurl(const char *path, struct nsurl **url_out) +static void ro_msg_dataopen(wimp_message *message) { - 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 */ + int file_type = message->data.data_xfer.file_type; + char *url = 0; + os_error *oserror; + nsurl *urlns; + nserror error; + size_t len; - /* 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)); - warn_user("PathToURL", error->errmess); - return NSERROR_NOT_FOUND; - } + 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; - canonical_path = malloc(1 - spare); - if (canonical_path == NULL) { - free(canonical_path); - return NSERROR_NOMEM; - } + case 0xfaf: /* HTML file */ + error = netsurf_path_to_nsurl(message->data.data_xfer.file_name, + &urlns); + break; - 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)); - warn_user("PathToURL", error->errmess); - free(canonical_path); - return NSERROR_NOT_FOUND; - } + case 0x1ba: /* IEURL file */ + url = ro_gui_ieurl_file_parse(message-> + data.data_xfer.file_name); + error = nsurl_create(url, &urlns); + free(url); + break; - /* create a unix path from teh cananocal risc os one */ - unix_path = __unixify(canonical_path, __RISCOSIFY_NO_REVERSE_SUFFIX, NULL, 0, 0); + 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 (unix_path == NULL) { - LOG(("__unixify failed: %s", canonical_path)); - free(canonical_path); - return NSERROR_BAD_PARAMETER; - } - free(canonical_path); + 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; - /* 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; + default: + return; } - 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); + /* 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)); + warn_user("WimpError", oserror->errmess); + return; } - 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; + if (error != NSERROR_OK) { + warn_user(messages_get_errorcode(error), 0); + return; } - ret = nsurl_create(escurl, url_out); - free(escurl); - - return ret; + /* 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) { + warn_user(messages_get_errorcode(error), 0); + } } + /** - * Create a path from a nsurl using posix file handling. - * - * @parm[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. + * Handle Message_DataLoad (file dragged in). */ -static nserror ro_nsurl_to_path(struct nsurl *url, char **path_out) +static void ro_msg_dataload(wimp_message *message) { - 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); + 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; - if (lwc_string_caseless_isequal(scheme, corestring_lwc_file, - &match) != lwc_error_ok) - { - return NSERROR_BAD_PARAMETER; + g = ro_gui_window_lookup(message->data.data_xfer.w); + if (g) { + if (ro_gui_window_dataload(g, message)) + return; } - lwc_string_unref(scheme); - if (match == false) { - return NSERROR_BAD_PARAMETER; + else { + g = ro_gui_toolbar_lookup(message->data.data_xfer.w); + if (g && ro_gui_toolbar_dataload(g, message)) + return; } - urlpath = nsurl_get_component(url, NSURL_PATH); - if (urlpath == NULL) { - return NSERROR_BAD_PARAMETER; - } + 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; - res = url_unescape(lwc_string_data(urlpath), &unpath); - lwc_string_unref(urlpath); - if (res != NSERROR_OK) { - return res; + 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; } - /* RISC OS path should not be more than 100 characters longer */ - path = malloc(strlen(unpath) + 100); - if (path == NULL) { - free(unpath); - return NSERROR_NOMEM; + /* report error to user */ + if (error != NSERROR_OK) { + warn_user(messages_get_errorcode(error), 0); + return; } - r = __riscosify(unpath, 0, __RISCOSIFY_NO_SUFFIX, - path, strlen(unpath) + 100, 0); - free(unpath); - if (r == NULL) { - free(path); - return NSERROR_NOMEM; + + 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) { + warn_user(messages_get_errorcode(error), 0); } - *path_out = path; - return NSERROR_OK; + /* 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)); + warn_user("WimpError", oserror->errmess); + return; + } + } /** - * Last-minute gui init, after all other modules have initialised. + * 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 gui_init2(int argc, char** argv) +static void ro_msg_terminate_filename(wimp_full_message_data_xfer *message) { - nsurl *url; - nserror ret; - bool open_window; + const char *ep = (char*)message + message->size; + char *p = message->file_name; - /* Complete initialisation of the treeview modules. */ + if ((size_t)message->size >= sizeof(*message)) + ep = (char*)message + sizeof(*message) - 1; - /* certificate verification window */ - ro_gui_cert_postinitialise(); + while (p < ep && *p >= ' ') p++; + *p = '\0'; +} - /* hotlist window */ - ro_gui_hotlist_postinitialise(); - /* global history window */ - ro_gui_global_history_postinitialise(); +/** + * Handle Message_DataSave + */ +static void ro_msg_datasave(wimp_message *message) +{ + wimp_full_message_data_xfer *dataxfer = (wimp_full_message_data_xfer*)message; - /* cookies window */ - ro_gui_cookies_postinitialise(); + /* remove ghost caret if drag-and-drop protocol was used */ +// ro_gui_selection_drag_reset(); - open_window = nsoption_bool(open_browser_at_startup); + ro_msg_terminate_filename(dataxfer); - /* 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; - } - ret = nsurl_create(NETSURF_HOMEPAGE, &url); - } - else if (argc == 3) { - LOG(("parameters: '%s' '%s'", argv[1], argv[2])); - open_window = true; + if (ro_gui_selection_prepare_paste_datasave(dataxfer)) + return; - /* 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; - } - } - /* 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); - } + 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; - /* check for url creation error */ - if (ret != NSERROR_OK) { - warn_user(messages_get_errorcode(ret), 0); - return; - } + 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, "", 13); - if (open_window) { - ret = browser_window_create(BW_CREATE_HISTORY, - url, - NULL, - NULL, - NULL); - if (ret != NSERROR_OK) { - warn_user(messages_get_errorcode(ret), 0); + 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)); + warn_user("WimpError", error->errmess); + } } + break; } - nsurl_unref(url); } -/** - * Ensures output logging stream is correctly configured + +/** + * Handle Message_DataSaveAck. */ -static bool nslog_stream_configure(FILE *fptr) +static void ro_msg_datasave_ack(wimp_message *message) { - /* set log stream to be non-buffering */ - setbuf(fptr, NULL); + ro_msg_terminate_filename((wimp_full_message_data_xfer*)message); - return true; -} + if (ro_print_ack(message)) + return; + switch (gui_current_drag_type) { + case GUI_DRAG_DOWNLOAD_SAVE: + ro_gui_download_datasave_ack(message); + break; -/** - * Close down the gui (RISC OS). - */ + case GUI_DRAG_SAVE: + ro_gui_save_datasave_ack(message); + gui_current_drag_type = GUI_DRAG_NONE; + break; -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(); + default: + break; + } + + gui_current_drag_type = GUI_DRAG_NONE; } /** - * Handles a signal + * Handle PreQuit message + * + * \param message PreQuit message from Wimp */ - -void ro_gui_signal(int sig) +static void ro_msg_prequit(wimp_message *message) { - 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(); + if (!ro_gui_prequit()) { + os_error *error; - 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); + /* 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)); + warn_user("WimpError", error->errmess); } } -#else - /* Save WimpSlot and UnixLib managed DAs when UnixEnv$coredump - * defines a coredump directory. */ - _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 .WWW.NetSurf.Log"); - - _Exit(sig); -} - - -/** - * Ensures the gui exits cleanly. - */ - -void ro_gui_cleanup(void) -{ - ro_gui_buffer_close(); - xhourglass_off(); - /* Uninstall NetSurf-specific fonts */ - xos_cli("FontRemove NetSurf:Resources.Fonts."); } /** - * Poll the OS for events (RISC OS). + * Handle SaveDesktop message. * - * \param active return as soon as possible + * \param message SaveDesktop message from Wimp. */ - -static void riscos_poll(bool active) +static void ro_msg_save_desktop(wimp_message *message) { - 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 (active) { - event = wimp_poll(mask, &block, 0); - } else if (sched_active || (track_poll_offset > 0) || - browser_reformat_pending) { - 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; + os_error *error; - event = wimp_poll_idle(mask, &block, t, 0); - } else { - event = wimp_poll(wimp_MASK_NULL | mask, &block, 0); + 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); } - xhourglass_on(); - gui_last_poll = clock(); - ro_gui_handle_event(event, &block); + if (error) { + LOG(("xosgbpb_writew/xos_bputw: 0x%x:%s", error->errnum, error->errmess)); + warn_user("SaveError", error->errmess); - /* 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(); + /* 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)); + warn_user("WimpError", error->errmess); + } } - - ro_gui_window_update_boxes(); - - if (browser_reformat_pending && event == wimp_NULL_REASON_CODE) - ro_gui_window_process_reformats(); } /** - * Process a Wimp_Poll event. + * Handle WindowInfo message (part of the iconising protocol) * - * \param event wimp event number - * \param block parameter block + * \param message WindowInfo message from the Iconiser */ - -void ro_gui_handle_event(wimp_event_no event, wimp_block *block) +static void ro_msg_window_info(wimp_message *message) { - 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; + wimp_full_message_window_info *wi; + struct gui_window *g; - /* Scroll requests fall back to a generic handler because we - * might get these events for any window from a scroll-wheel. - */ + /* allow the user to turn off thumbnail icons */ + if (!nsoption_bool(thumbnail_iconise)) + return; - case wimp_SCROLL_REQUEST: - if (!ro_gui_wimp_event_scroll_window(&(block->scroll))) - ro_gui_scroll(&(block->scroll)); - break; + wi = (wimp_full_message_window_info*)message; + g = ro_gui_window_lookup(wi->w); - case wimp_USER_MESSAGE: - case wimp_USER_MESSAGE_RECORDED: - case wimp_USER_MESSAGE_ACKNOWLEDGE: - ro_gui_user_message(event, &(block->message)); - break; + /* ic_ will suffice for our other windows */ + if (g) { + ro_gui_window_iconise(g, wi); + ro_gui_dialog_close_persistent(wi->w); } } /** - * Handle Open_Window_Request events. + * Get screen properties following a mode change. */ - -void ro_gui_open_window_request(wimp_open *open) +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]; - if (ro_gui_wimp_event_open_window(open)) - return; - - error = xwimp_open_window(open); + error = xos_read_vdu_variables(PTR_OS_VDU_VAR_LIST(&vars), vals); if (error) { - LOG(("xwimp_open_window: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); + LOG(("xos_read_vdu_variables: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("MiscError", error->errmess); return; } + screen_info.width = (vals[0] + 1) << vals[2]; + screen_info.height = (vals[1] + 1) << vals[3]; } /** - * Handle Close_Window_Request events. + * Warn the user if Inet$Resolvers is not set. */ - -void ro_gui_close_window_request(wimp_close *close) +static void ro_gui_check_resolvers(void) { - 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); + char *resolvers; + resolvers = getenv("Inet$Resolvers"); + if (resolvers && resolvers[0]) { + LOG(("Inet$Resolvers '%s'", resolvers)); + } else { + LOG(("Inet$Resolvers not set or empty")); + warn_user("Resolvers", 0); } } /** - * Handle Key_Pressed events. + * Initialise the RISC OS specific GUI. + * + * \param argc The number of command line arguments. + * \param argv The string vector of command line arguments. */ - -static void ro_gui_keypress_cb(void *pw) +static nserror gui_init(int argc, char** argv) { - 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)); - warn_user("WimpError", error->errmess); - } + struct { + void (*sigabrt)(int); + void (*sigfpe)(int); + void (*sigill)(int); + void (*sigint)(int); + void (*sigsegv)(int); + void (*sigterm)(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; } - free(key); -} + /* Create our choices directories */ + ro_gui_create_dirs(); -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)) { + /* 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); - /* 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; + 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) + die("Failed registering signal handlers"); - /* 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)); + /* Load in UI sprites */ + gui_sprites = ro_gui_load_sprite_file("NetSurf:Resources.Sprites"); + if (!gui_sprites) + die("Unable to load Sprites."); - 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)); - warn_user("WimpError", error->errmess); - } + /* 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(); -/** - * Handle the three User_Message events. - */ -void ro_gui_user_message(wimp_event_no event, wimp_message *message) -{ - /* attempt automatic routing */ - if (ro_message_handle_message(event, message)) - return; + /* Initialise global information */ + ro_gui_get_screen_properties(); + ro_gui_wimp_get_desktop_font(); - switch (message->action) { - case message_DATA_LOAD: - ro_msg_terminate_filename((wimp_full_message_data_xfer*)message); + /* Issue a *Desktop to poke AcornURI into life */ + if (getenv("NetSurf$Start_URI_Handler")) + xwimp_start_task("Desktop", 0); - 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; + /* 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); + } - case message_DATA_LOAD_ACK: - if (ro_print_current_window) - ro_print_cleanup(); - break; + ret = treeview_init(12); + if (ret != NSERROR_OK) { + die("Failed to initialise treeview"); + } - case message_MENU_WARNING: - ro_gui_menu_warning((wimp_message_menu_warning *) - &message->data); - break; + /* Initialise themes before dialogs */ + ro_gui_theme_initialise(); - case message_MENUS_DELETED: - ro_gui_menu_message_deleted((wimp_message_menus_deleted *) - &message->data); - break; + /* Initialise dialog windows (must be after UI sprites are loaded) */ + ro_gui_dialog_init(); - case message_CLAIM_ENTITY: - ro_gui_selection_claim_entity((wimp_full_message_claim_entity*)message); - break; + /* Initialise download window */ + ro_gui_download_init(); - case message_DATA_REQUEST: - ro_gui_selection_data_request((wimp_full_message_data_request*)message); - break; + /* Initialise menus */ + ro_gui_menu_init(); - case message_MODE_CHANGE: - ro_gui_get_screen_properties(); - rufl_invalidate_cache(); - break; + /* Initialise query windows */ + ro_gui_query_init(); - case message_PALETTE_CHANGE: - break; + /* Initialise the history subsystem */ + ro_gui_history_init(); - case message_FONT_CHANGED: - ro_gui_wimp_get_desktop_font(); - break; + /* Initialise toolbars */ + ro_toolbar_init(); - 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); + /* 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"); } - 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: - netsurf_quit = true; - break; + 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; } /** - * Ensure that the filename in a data transfer message is NUL terminated - * (some applications, especially BASIC programs use CR) + * Determine the default language to use. * - * \param message message to be corrected + * RISC OS has no standard way of determining which language the user prefers. + * We have to guess from the 'Country' setting. */ - -void ro_msg_terminate_filename(wimp_full_message_data_xfer *message) +const char *ro_gui_default_language(void) { - 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; + char path[40]; + const char *lang; + int country; + os_error *error; - while (p < ep && *p >= ' ') p++; - *p = '\0'; + /* 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"; } /** - * Handle Message_DataLoad (file dragged in). + * 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 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. */ - -void ro_msg_dataload(wimp_message *message) +static nserror ro_path_to_nsurl(const char *path, struct nsurl **url_out) { - 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; + 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 */ - 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; + /* 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)); + warn_user("PathToURL", error->errmess); + return NSERROR_NOT_FOUND; } - 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; + canonical_path = malloc(1 - spare); + if (canonical_path == NULL) { + free(canonical_path); + return NSERROR_NOMEM; + } - case FILETYPE_IEURL: - urltxt = ro_gui_ieurl_file_parse(message->data.data_xfer.file_name); - error = nsurl_create(urltxt, &url); - free(urltxt); - break; + 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)); + warn_user("PathToURL", error->errmess); + free(canonical_path); + return NSERROR_NOT_FOUND; + } - 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; + /* create a unix path from teh cananocal risc os one */ + unix_path = __unixify(canonical_path, __RISCOSIFY_NO_REVERSE_SUFFIX, NULL, 0, 0); - default: - return; + if (unix_path == NULL) { + LOG(("__unixify failed: %s", canonical_path)); + free(canonical_path); + return NSERROR_BAD_PARAMETER; } + free(canonical_path); - /* report error to user */ - if (error != NSERROR_OK) { - warn_user(messages_get_errorcode(error), 0); - return; + /* 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 (g) { - error = browser_window_navigate(g->bw, - url, - NULL, - BW_NAVIGATE_HISTORY, - NULL, - NULL, - NULL); + if (*unix_path == '/') { + snprintf(url, urllen, "%s%s", FILE_SCHEME_PREFIX, unix_path + 1); } else { - error = browser_window_create(BW_CREATE_HISTORY, - url, - NULL, - NULL, - NULL); - } - nsurl_unref(url); - if (error != NSERROR_OK) { - warn_user(messages_get_errorcode(error), 0); + snprintf(url, urllen, "%s%s", FILE_SCHEME_PREFIX, unix_path); } + free(unix_path); - - /* 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)); - warn_user("WimpError", oserror->errmess); - return; + /* 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; } /** - * Parse an Acorn URI file. + * Create a path from a nsurl using posix file handling. * - * \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 + * @parm[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. */ - -char *ro_gui_uri_file_parse(const char *file_name, char **uri_title) +static nserror ro_nsurl_to_path(struct nsurl *url, char **path_out) { - /* See the "Acorn URI Handler Functional Specification" for the - * definition of the URI file format. */ - char line[400]; - char *url = NULL; - FILE *fp; + lwc_string *urlpath; + char *unpath; + char *path; + bool match; + lwc_string *scheme; + nserror res; + char *r; - *uri_title = NULL; - fp = fopen(file_name, "rb"); - if (!fp) { - LOG(("fopen(\"%s\", \"rb\"): %i: %s", - file_name, errno, strerror(errno))); - warn_user("LoadError", strerror(errno)); - return 0; + if ((url == NULL) || (path_out == NULL)) { + return NSERROR_BAD_PARAMETER; } - /* "URI" */ - if (!ro_gui_uri_file_parse_line(fp, line) || strcmp(line, "URI") != 0) - goto uri_syntax_error; + scheme = nsurl_get_component(url, NSURL_SCHEME); - /* version */ - if (!ro_gui_uri_file_parse_line(fp, line) || - strspn(line, "0123456789") != strlen(line)) - goto uri_syntax_error; + 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; + } - /* URI */ - if (!ro_gui_uri_file_parse_line(fp, line)) - goto uri_syntax_error; + urlpath = nsurl_get_component(url, NSURL_PATH); + if (urlpath == NULL) { + return NSERROR_BAD_PARAMETER; + } - url = strdup(line); - if (!url) { - warn_user("NoMemory", 0); - fclose(fp); - return 0; + res = url_unescape(lwc_string_data(urlpath), &unpath); + lwc_string_unref(urlpath); + if (res != NSERROR_OK) { + return res; } - /* 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 */ - warn_user("NoMemory", 0); + /* RISC OS path should not be more than 100 characters longer */ + path = malloc(strlen(unpath) + 100); + if (path == NULL) { + free(unpath); + return NSERROR_NOMEM; } - fclose(fp); - return url; + r = __riscosify(unpath, 0, __RISCOSIFY_NO_SUFFIX, + path, strlen(unpath) + 100, 0); + free(unpath); + if (r == NULL) { + free(path); + return NSERROR_NOMEM; + } -uri_free: - free(url); + *path_out = path; -uri_syntax_error: - fclose(fp); - warn_user("URIError", 0); - return 0; + return NSERROR_OK; } /** - * 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 + * Ensures output logging stream is correctly configured. */ - -bool ro_gui_uri_file_parse_line(FILE *fp, char *b) +static bool nslog_stream_configure(FILE *fptr) { - 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); + /* set log stream to be non-buffering */ + setbuf(fptr, NULL); - b[i] = 0; return true; } /** - * Parse an ANT URL file. - * - * \param file_name file to read - * \return URL from file, or 0 on error and error reported + * Close down the gui (RISC OS). */ - -char *ro_gui_url_file_parse(const char *file_name) +static void gui_quit(void) { - char line[400]; - char *url; - FILE *fp; + 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(); +} - fp = fopen(file_name, "r"); - if (!fp) { - LOG(("fopen(\"%s\", \"r\"): %i: %s", - file_name, errno, strerror(errno))); - warn_user("LoadError", strerror(errno)); - return 0; - } - if (!fgets(line, sizeof line, fp)) { - if (ferror(fp)) { - LOG(("fgets: %i: %s", - errno, strerror(errno))); - warn_user("LoadError", strerror(errno)); - } else - warn_user("LoadError", messages_get("EmptyError")); - fclose(fp); - return 0; +/** + * 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); } +} - fclose(fp); - if (line[strlen(line) - 1] == '\n') - line[strlen(line) - 1] = '\0'; +/** + * Handle key press paste callback. + */ +static void ro_gui_keypress_cb(void *pw) +{ + wimp_key *key = (wimp_key *) pw; - url = strdup(line); - if (!url) { - warn_user("NoMemory", 0); - return 0; + 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)); + warn_user("WimpError", error->errmess); + } } - return url; + free(key); } /** - * Parse an IEURL file. - * - * \param file_name file to read - * \return URL from file, or 0 on error and error reported + * Handle gui keypress. */ - -char *ro_gui_ieurl_file_parse(const char *file_name) +static void ro_gui_keypress(wimp_key *key) { - char line[400]; - char *url = 0; - FILE *fp; + if (key->c == wimp_KEY_ESCAPE && + (gui_current_drag_type == GUI_DRAG_SAVE || + gui_current_drag_type == GUI_DRAG_DOWNLOAD_SAVE)) { - fp = fopen(file_name, "r"); - if (!fp) { - LOG(("fopen(\"%s\", \"r\"): %i: %s", - file_name, errno, strerror(errno))); - warn_user("LoadError", strerror(errno)); - return 0; - } + /* 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; - 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); - warn_user("NoMemory", 0); - return 0; - } - break; + /* 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)); + warn_user("WimpError", error->errmess); } } - if (ferror(fp)) { - LOG(("fgets: %i: %s", - errno, strerror(errno))); - warn_user("LoadError", strerror(errno)); - fclose(fp); - return 0; - } - - fclose(fp); - - if (!url) - warn_user("URIError", 0); - - return url; } /** - * Handle Message_DataSave + * Handle the three User_Message events. */ - -void ro_msg_datasave(wimp_message *message) +static void ro_gui_user_message(wimp_event_no event, 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)) + /* attempt automatic routing */ + if (ro_message_handle_message(event, message)) 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, "", 13); + switch (message->action) { + case message_DATA_LOAD: + ro_msg_terminate_filename((wimp_full_message_data_xfer*)message); - 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)); - warn_user("WimpError", error->errmess); + 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; - } -} + break; + case message_DATA_LOAD_ACK: + if (ro_print_current_window) + ro_print_cleanup(); + break; -/** - * Handle Message_DataSaveAck. - */ + case message_MENU_WARNING: + ro_gui_menu_warning((wimp_message_menu_warning *) + &message->data); + break; -void ro_msg_datasave_ack(wimp_message *message) -{ - ro_msg_terminate_filename((wimp_full_message_data_xfer*)message); + case message_MENUS_DELETED: + ro_gui_menu_message_deleted((wimp_message_menus_deleted *) + &message->data); + break; - if (ro_print_ack(message)) - return; + case message_CLAIM_ENTITY: + ro_gui_selection_claim_entity((wimp_full_message_claim_entity*)message); + break; - switch (gui_current_drag_type) { - case GUI_DRAG_DOWNLOAD_SAVE: - ro_gui_download_datasave_ack(message); + case message_DATA_REQUEST: + ro_gui_selection_data_request((wimp_full_message_data_request*)message); break; - case GUI_DRAG_SAVE: - ro_gui_save_datasave_ack(message); - gui_current_drag_type = GUI_DRAG_NONE; + case message_MODE_CHANGE: + ro_gui_get_screen_properties(); + rufl_invalidate_cache(); break; - default: + 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: + netsurf_quit = true; break; } - - gui_current_drag_type = GUI_DRAG_NONE; } /** - * Handle Message_DataOpen (double-click on file in the Filer). + * Process a Wimp_Poll event. + * + * \param event wimp event number + * \param block parameter block */ - -void ro_msg_dataopen(wimp_message *message) +static void ro_gui_handle_event(wimp_event_no event, wimp_block *block) { - 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; + switch (event) { + case wimp_NULL_REASON_CODE: + ro_gui_throb(); + ro_mouse_poll(); + break; - case 0xfaf: /* HTML file */ - error = netsurf_path_to_nsurl(message->data.data_xfer.file_name, - &urlns); - break; + case wimp_REDRAW_WINDOW_REQUEST: + ro_gui_wimp_event_redraw_window(&block->redraw); + 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 wimp_OPEN_WINDOW_REQUEST: + ro_gui_open_window_request(&block->open); + 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; + case wimp_CLOSE_WINDOW_REQUEST: + ro_gui_close_window_request(&block->close); + break; - 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; + case wimp_POINTER_LEAVING_WINDOW: + ro_mouse_pointer_leaving_window(&block->leaving); + break; - default: - return; - } + case wimp_POINTER_ENTERING_WINDOW: + ro_gui_wimp_event_pointer_entering_window(&block->entering); + break; - /* 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)); - warn_user("WimpError", oserror->errmess); - return; - } + case wimp_MOUSE_CLICK: + ro_gui_wimp_event_mouse_click(&block->pointer); + break; - if (error != NSERROR_OK) { - warn_user(messages_get_errorcode(error), 0); - return; - } + case wimp_USER_DRAG_BOX: + ro_mouse_drag_end(&block->dragged); + break; - /* 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) { - warn_user(messages_get_errorcode(error), 0); - } -} + case wimp_KEY_PRESSED: + ro_gui_keypress(&(block->key)); + break; + case wimp_MENU_SELECTION: + ro_gui_menu_selection(&(block->selection)); + break; -/** - * Handle PreQuit message - * - * \param message PreQuit message from Wimp - */ + /* Scroll requests fall back to a generic handler because we + * might get these events for any window from a scroll-wheel. + */ -void ro_msg_prequit(wimp_message *message) -{ - if (!ro_gui_prequit()) { - os_error *error; + case wimp_SCROLL_REQUEST: + if (!ro_gui_wimp_event_scroll_window(&(block->scroll))) + ro_gui_scroll(&(block->scroll)); + break; - /* 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)); - warn_user("WimpError", error->errmess); - } + case wimp_USER_MESSAGE: + case wimp_USER_MESSAGE_RECORDED: + case wimp_USER_MESSAGE_ACKNOWLEDGE: + ro_gui_user_message(event, &(block->message)); + break; } } /** - * Handle SaveDesktop message + * Poll the OS for events (RISC OS). * - * \param message SaveDesktop message from Wimp + * \param active return as soon as possible */ - -void ro_msg_save_desktop(wimp_message *message) +static void riscos_poll(bool active) { - 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)); - 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)); - warn_user("WimpError", error->errmess); - } - } -} + 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 (active) { + event = wimp_poll(mask, &block, 0); + } else if (sched_active || (track_poll_offset > 0) || + browser_reformat_pending) { + os_t t = os_read_monotonic_time(); -/** - * Handle WindowInfo message (part of the iconising protocol) - * - * \param message WindowInfo message from the Iconiser - */ + if (track_poll_offset > 0) + t += track_poll_offset; + else + t += 10; -void ro_msg_window_info(wimp_message *message) -{ - wimp_full_message_window_info *wi; - struct gui_window *g; + if (sched_active && (sched_time - t) < 0) + t = sched_time; - /* allow the user to turn off thumbnail icons */ - if (!nsoption_bool(thumbnail_iconise)) - return; + event = wimp_poll_idle(mask, &block, t, 0); + } else { + event = wimp_poll(wimp_MASK_NULL | mask, &block, 0); + } - wi = (wimp_full_message_window_info*)message; - g = ro_gui_window_lookup(wi->w); + xhourglass_on(); + gui_last_poll = clock(); + ro_gui_handle_event(event, &block); - /* ic_ will suffice for our other windows */ - if (g) { - ro_gui_window_iconise(g, wi); - ro_gui_dialog_close_persistent(wi->w); + /* 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(); + if (browser_reformat_pending && event == wimp_NULL_REASON_CODE) + ro_gui_window_process_reformats(); +} /** - * Get screen properties following a mode change. + * Handle Open_Window_Request events. */ - -void ro_gui_get_screen_properties(void) +void ro_gui_open_window_request(wimp_open *open) { - 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 (ro_gui_wimp_event_open_window(open)) + return; + + error = xwimp_open_window(open); if (error) { - LOG(("xos_read_vdu_variables: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("MiscError", error->errmess); + LOG(("xwimp_open_window: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); return; } - screen_info.width = (vals[0] + 1) << vals[2]; - screen_info.height = (vals[1] + 1) << vals[3]; } /** - * Find screen size in OS units. + * source bounce callback. */ - -void ro_gui_screen_size(int *width, int *height) +static void ro_gui_view_source_bounce(wimp_message *message) { - *width = screen_info.width; - *height = screen_info.height; + 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)); + 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; @@ -2161,64 +2049,43 @@ void ro_gui_view_source(hlcache_handle *c) } -void ro_gui_view_source_bounce(wimp_message *message) +/** + * Broadcast an URL that we can't handle. + */ +static nserror gui_launch_url(struct nsurl *url) { - 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)); - warn_user("WimpError", error->errmess); - } + /* Try ant broadcast */ + ro_url_broadcast(nsurl_access(url)); + return NSERROR_OK; } /** - * Send the debug dump of a content to a text editor. + * Choose the language to use. */ - -void ro_gui_dump_browser_window(struct browser_window *bw) +static void ro_gui_choose_language(void) { - os_error *error; - - /* open file for dump */ - FILE *stream = fopen(".WWW.NetSurf.dump", "w"); - if (!stream) { - LOG(("fopen: errno %i", errno)); - warn_user("SaveError", strerror(errno)); - return; - } - - browser_window_debug_dump(bw, stream); - - fclose(stream); + /* 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)); - /* launch file in editor */ - error = xwimp_start_task("Filer_Run .WWW.NetSurf.dump", - 0); - if (error) { - LOG(("xwimp_start_task failed: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); + if (is_dir(path)) { + nsoption_setnull_charp(accept_language, + strdup(nsoption_charp(language))); + return; + } + nsoption_set_charp(language, NULL); } -} - - -/** - * 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; + 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"); } @@ -2228,7 +2095,6 @@ static nserror gui_launch_url(struct nsurl *url) * \param warning message key for warning message * \param detail additional message, or 0 */ - void warn_user(const char *warning, const char *detail) { LOG(("%s %s", warning, detail)); @@ -2270,7 +2136,6 @@ void warn_user(const char *warning, const char *detail) * * Should only be used during initialisation. */ - void die(const char * const error) { os_error warn_error; @@ -2297,21 +2162,19 @@ void die(const char * const error) * * \return true iff it's okay to shutdown immediately */ - bool ro_gui_prequit(void) { return ro_gui_download_prequit(); } + void PDF_Password(char **owner_pass, char **user_pass, char *path) { - /*TODO:this waits to be written, until then no PDF encryption*/ + /** @todo this waits to be written, until then no PDF encryption */ *owner_pass = NULL; } -#define DIR_SEP ('.') - /** * Generate a riscos path from one or more component elemnts. * @@ -2474,6 +2337,46 @@ static nserror riscos_basename(const char *path, char **str, size_t *size) } +/** + * 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(".WWW.NetSurf.dump", "w"); + if (!stream) { + LOG(("fopen: errno %i", errno)); + warn_user("SaveError", strerror(errno)); + return; + } + + browser_window_debug_dump(bw, stream); + + fclose(stream); + + /* launch file in editor */ + error = xwimp_start_task("Filer_Run .WWW.NetSurf.dump", + 0); + if (error) { + LOG(("xwimp_start_task failed: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } +} + + static struct gui_file_table riscos_file_table = { .mkpath = riscos_mkpath, .basename = riscos_basename, @@ -2500,7 +2403,9 @@ static struct gui_browser_table riscos_browser_table = { }; -/** Normal entry point from OS */ +/** + * Normal entry point from RISC OS. + */ int main(int argc, char** argv) { char path[40]; @@ -2563,7 +2468,7 @@ int main(int argc, char** argv) if (((length = snprintf(path, sizeof(path), "NetSurf:Resources.%s.Messages", - nsoption_charp(language))) < 0) || + nsoption_charp(language))) < 0) || (length >= (int)sizeof(path))) { die("Failed to locate Messages resource."); } @@ -2581,9 +2486,10 @@ int main(int argc, char** argv) /* Load some extra RISC OS specific Messages */ messages_load("NetSurf:Resources.LangNames"); - gui_init(argc, argv); - - gui_init2(argc, argv); + ret = gui_init(argc, argv); + if (ret != NSERROR_OK) { + warn_user(messages_get_errorcode(ret), 0); + } netsurf_main_loop(); diff --git a/riscos/gui.h b/riscos/gui.h index 8f849ae14..1dcc1e13c 100644 --- a/riscos/gui.h +++ b/riscos/gui.h @@ -170,15 +170,6 @@ void gui_create_form_select_menu(struct browser_window *bw, struct form_control void ro_gui_history_init(void); void ro_gui_history_open(struct gui_window *g, bool pointer); -/* in filetype.c */ -const char *fetch_filetype(const char *unix_path); -char *fetch_mimetype(const char *ro_path); -int ro_content_filetype(struct hlcache_handle *c); -int ro_content_native_type(struct hlcache_handle *c); -int ro_content_filetype_from_mime_type(lwc_string *mime_type); -int ro_content_filetype_from_type(content_type type); -bits ro_filetype_from_unix_path(const char *unix_path); - /* in schedule.c */ extern bool sched_active; extern os_t sched_time; diff --git a/riscos/gui/url_bar.c b/riscos/gui/url_bar.c index 5421dbc1c..c55fa614d 100644 --- a/riscos/gui/url_bar.c +++ b/riscos/gui/url_bar.c @@ -47,6 +47,7 @@ #include "riscos/wimp_event.h" #include "riscos/window.h" #include "riscos/ucstables.h" +#include "riscos/filetype.h" #define URLBAR_HEIGHT 52 #define URLBAR_FAVICON_SIZE 16 diff --git a/riscos/print.c b/riscos/print.c index c539f011c..16e657b51 100644 --- a/riscos/print.c +++ b/riscos/print.c @@ -43,6 +43,7 @@ #include "utils/log.h" #include "utils/messages.h" #include "utils/utils.h" +#include "riscos/filetype.h" #define ICON_PRINT_TO_BOTTOM 1 diff --git a/riscos/save.c b/riscos/save.c index bc7918cf2..cc8612bb5 100644 --- a/riscos/save.c +++ b/riscos/save.c @@ -70,6 +70,7 @@ #include "riscos/wimp.h" #include "riscos/wimp_event.h" #include "riscos/ucstables.h" +#include "riscos/filetype.h" //typedef enum //{ diff --git a/riscos/url_complete.c b/riscos/url_complete.c index b15de0ff3..5f45cd514 100644 --- a/riscos/url_complete.c +++ b/riscos/url_complete.c @@ -38,6 +38,7 @@ #include "riscos/wimp_event.h" #include "riscos/wimputils.h" #include "utils/utils.h" +#include "riscos/filetype.h" #define MAXIMUM_VISIBLE_LINES 7 diff --git a/riscos/window.c b/riscos/window.c index 876ad0eda..e1eaf871d 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -92,6 +92,7 @@ #include "riscos/wimputils.h" #include "riscos/window.h" #include "riscos/ucstables.h" +#include "riscos/filetype.h" void gui_window_redraw_window(struct gui_window *g); -- cgit v1.2.3