summaryrefslogtreecommitdiff
path: root/riscos/gui.c
diff options
context:
space:
mode:
Diffstat (limited to 'riscos/gui.c')
-rw-r--r--riscos/gui.c2949
1 files changed, 1528 insertions, 1421 deletions
diff --git a/riscos/gui.c b/riscos/gui.c
index bb1a318de..2e337e5a2 100644
--- a/riscos/gui.c
+++ b/riscos/gui.c
@@ -21,127 +21,69 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdbool.h>
+#include <string.h>
#include <assert.h>
#include <errno.h>
-#include <fpu_control.h>
#include <signal.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <features.h>
#include <unixlib/local.h>
-#include <curl/curl.h>
-#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 "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 <fpu_control.h>
+#include <oslib/help.h>
+#include <oslib/uri.h>
+#include <oslib/inetsuite.h>
+#include <oslib/pdriver.h>
+#include <oslib/osfile.h>
+#include <oslib/hourglass.h>
+#include <oslib/osgbpb.h>
+#include <oslib/osbyte.h>
+#include <oslib/osmodule.h>
+#include <oslib/osfscontrol.h>
+
+#include "utils/utils.h"
#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/file.h"
+#include "utils/filename.h"
+#include "utils/url.h"
+#include "utils/corestrings.h"
+#include "desktop/gui.h"
#include "desktop/save_complete.h"
#include "desktop/treeview.h"
-#include "render/font.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 "desktop/netsurf.h"
+#include "desktop/browser.h"
+#include "content/urldb.h"
+#include "content/hlcache.h"
+#include "content/backing_store.h"
+
#include "riscos/gui.h"
-#include "riscos/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 "utils/filename.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/url.h"
-#include "utils/utils.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/mouse.h"
+#include "riscos/ucstables.h"
+#include "riscos/filetype.h"
+#include "riscos/font.h"
+#include "riscos/toolbar.h"
+#include "riscos/content-handlers/artworks.h"
+#include "riscos/content-handlers/draw.h"
+#include "riscos/content-handlers/sprite.h"
extern bool ro_plot_patterned_lines;
@@ -163,11 +105,15 @@ static const char *task_name = "NetSurf";
#define CHOICES_PREFIX "<Choices$Write>.WWW.NetSurf."
ro_gui_drag_type gui_current_drag_type;
-wimp_t task_handle; /**< RISC OS wimp task handle. */
-static clock_t gui_last_poll; /**< Time of last wimp_poll. */
-osspriteop_area *gui_sprites; /**< Sprite area containing pointer and hotlist sprites */
+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,
{
@@ -221,38 +167,26 @@ 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);
-
-nsurl *gui_get_resource_url(const char *path)
+
+/**
+ * Callback to translate resource to full url for RISC OS.
+ *
+ * Transforms a resource: path into a full URL. The returned URL is
+ * used as the target for a redirect. The caller takes ownership of
+ * the returned nsurl including unrefing it when finished with it.
+ *
+ * \param path The path of the resource to locate.
+ * \return A string containing the full URL of the target object or
+ * NULL if no suitable resource can be found.
+ */
+static nsurl *gui_get_resource_url(const char *path)
{
static const char base_url[] = "file:///NetSurf:/Resources/";
size_t path_len, length;
@@ -313,14 +247,21 @@ 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;
@@ -339,17 +280,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)
{
@@ -398,11 +338,755 @@ static nserror set_defaults(struct nsoption_s *defaults)
return NSERROR_OK;
}
+
+
+
+/**
+ * Create intermediate directories for Choices and User Data files
+ */
+static void ro_gui_create_dirs(void)
+{
+ char buf[256];
+ char *path;
+
+ /* Choices */
+ path = getenv("NetSurf$ChoicesSave");
+ if (!path)
+ die("Failed to find NetSurf Choices save path");
+
+ snprintf(buf, sizeof(buf), "%s", path);
+ netsurf_mkdir_all(buf);
+
+ /* URL */
+ snprintf(buf, sizeof(buf), "%s", nsoption_charp(url_save));
+ netsurf_mkdir_all(buf);
+
+ /* Hotlist */
+ snprintf(buf, sizeof(buf), "%s", nsoption_charp(hotlist_save));
+ netsurf_mkdir_all(buf);
+
+ /* Recent */
+ snprintf(buf, sizeof(buf), "%s", nsoption_charp(recent_save));
+ netsurf_mkdir_all(buf);
+
+ /* Theme */
+ snprintf(buf, sizeof(buf), "%s", nsoption_charp(theme_save));
+ netsurf_mkdir_all(buf);
+ /* and the final directory part (as theme_save is a directory) */
+ xosfile_create_dir(buf, 0);
+}
+
+
+/**
+ * Ensures the gui exits cleanly.
+ */
+static void ro_gui_cleanup(void)
+{
+ ro_gui_buffer_close();
+ xhourglass_off();
+ /* Uninstall NetSurf-specific fonts */
+ xos_cli("FontRemove NetSurf:Resources.Fonts.");
+}
+
+
+/**
+ * Handles a signal
+ */
+static void ro_gui_signal(int sig)
+{
+ static const os_error error = { 1, "NetSurf has detected a serious "
+ "error and must exit. Please submit a bug report, "
+ "attaching the browser log file." };
+ os_colour old_sand, old_glass;
+
+ ro_gui_cleanup();
+
+ xhourglass_on();
+ xhourglass_colours(0x0000ffff, 0x000000ff, &old_sand, &old_glass);
+ nsoption_dump(stderr, NULL);
+ /*rufl_dump_state();*/
+
+#ifndef __ELF__
+ /* save WimpSlot and DA to files if NetSurf$CoreDump exists */
+ int used;
+ xos_read_var_val_size("NetSurf$CoreDump", 0, 0, &used, 0, 0);
+ if (used) {
+ int curr_slot;
+ xwimp_slot_size(-1, -1, &curr_slot, 0, 0);
+ LOG(("saving WimpSlot, size 0x%x", curr_slot));
+ xosfile_save("$.NetSurf_Slot", 0x8000, 0,
+ (byte *) 0x8000,
+ (byte *) 0x8000 + curr_slot);
+
+ if (__dynamic_num != -1) {
+ int size;
+ byte *base_address;
+ xosdynamicarea_read(__dynamic_num, &size,
+ &base_address, 0, 0, 0, 0, 0);
+ LOG(("saving DA %i, base %p, size 0x%x",
+ __dynamic_num,
+ base_address, size));
+ xosfile_save("$.NetSurf_DA",
+ (bits) base_address, 0,
+ base_address,
+ base_address + size);
+ }
+ }
+#else
+ /* Save WimpSlot and UnixLib managed DAs when UnixEnv$coredump
+ * defines a coredump directory. */
+ _kernel_oserror *err = __unixlib_write_coredump (NULL);
+ if (err != NULL)
+ LOG(("Coredump failed: %s", err->errmess));
+#endif
+
+ xhourglass_colours(old_sand, old_glass, 0, 0);
+ xhourglass_off();
+
+ __write_backtrace(sig);
+
+ xwimp_report_error_by_category(&error,
+ wimp_ERROR_BOX_GIVEN_CATEGORY |
+ wimp_ERROR_BOX_CATEGORY_ERROR <<
+ wimp_ERROR_BOX_CATEGORY_SHIFT,
+ "NetSurf", "!netsurf",
+ (osspriteop_area *) 1, "Quit", 0);
+ xos_cli("Filer_Run <Wimp$ScrapDir>.WWW.NetSurf.Log");
+
+ _Exit(sig);
+}
+
+
+/**
+ * Read a "line" from an Acorn URI file.
+ *
+ * \param fp file pointer to read from
+ * \param b buffer for line, size 400 bytes
+ * \return true on success, false on EOF
+ */
+static bool ro_gui_uri_file_parse_line(FILE *fp, char *b)
+{
+ int c;
+ unsigned int i = 0;
+
+ c = getc(fp);
+ if (c == EOF)
+ return false;
+
+ /* skip comment lines */
+ while (c == '#') {
+ do { c = getc(fp); } while (c != EOF && 32 <= c);
+ if (c == EOF)
+ return false;
+ do { c = getc(fp); } while (c != EOF && c < 32);
+ if (c == EOF)
+ return false;
+ }
+
+ /* read "line" */
+ do {
+ if (i == 399)
+ return false;
+ b[i++] = c;
+ c = getc(fp);
+ } while (c != EOF && 32 <= c);
+
+ /* skip line ending control characters */
+ while (c != EOF && c < 32)
+ c = getc(fp);
+
+ if (c != EOF)
+ ungetc(c, fp);
+
+ b[i] = 0;
+ return true;
+}
+
+
+/**
+ * Parse an Acorn URI file.
+ *
+ * \param file_name file to read
+ * \param uri_title pointer to receive title data, or NULL for no data
+ * \return URL from file, or 0 on error and error reported
+ */
+static char *ro_gui_uri_file_parse(const char *file_name, char **uri_title)
+{
+ /* See the "Acorn URI Handler Functional Specification" for the
+ * definition of the URI file format. */
+ char line[400];
+ char *url = NULL;
+ FILE *fp;
+
+ *uri_title = NULL;
+ fp = fopen(file_name, "rb");
+ if (!fp) {
+ LOG(("fopen(\"%s\", \"rb\"): %i: %s",
+ file_name, errno, strerror(errno)));
+ 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;
+}
+
+
+/**
+ * Parse an ANT URL file.
+ *
+ * \param file_name file to read
+ * \return URL from file, or 0 on error and error reported
+ */
+static char *ro_gui_url_file_parse(const char *file_name)
+{
+ char line[400];
+ char *url;
+ FILE *fp;
+
+ fp = fopen(file_name, "r");
+ if (!fp) {
+ LOG(("fopen(\"%s\", \"r\"): %i: %s",
+ file_name, errno, strerror(errno)));
+ 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;
+ }
+
+ 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;
+}
+
+
+/**
+ * Parse an IEURL file.
+ *
+ * \param file_name file to read
+ * \return URL from file, or 0 on error and error reported
+ */
+static char *ro_gui_ieurl_file_parse(const char *file_name)
+{
+ char line[400];
+ char *url = 0;
+ FILE *fp;
+
+ fp = fopen(file_name, "r");
+ if (!fp) {
+ LOG(("fopen(\"%s\", \"r\"): %i: %s",
+ file_name, errno, strerror(errno)));
+ warn_user("LoadError", strerror(errno));
+ return 0;
+ }
+
+ while (fgets(line, sizeof line, fp)) {
+ if (strncmp(line, "URL=", 4) == 0) {
+ if (line[strlen(line) - 1] == '\n')
+ line[strlen(line) - 1] = '\0';
+ url = strdup(line + 4);
+ if (!url) {
+ fclose(fp);
+ 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;
+ }
+
+ fclose(fp);
+
+ if (!url)
+ warn_user("URIError", 0);
+
+ return url;
+}
+
+
+/**
+ * Handle Message_DataOpen (double-click on file in the Filer).
+ *
+ * \param message The wimp message to open.
+ */
+static void ro_msg_dataopen(wimp_message *message)
+{
+ int file_type = message->data.data_xfer.file_type;
+ char *url = 0;
+ os_error *oserror;
+ nsurl *urlns;
+ nserror error;
+ size_t len;
+
+ switch (file_type) {
+ case 0xb28: /* ANT URL file */
+ url = ro_gui_url_file_parse(message->data.data_xfer.file_name);
+ error = nsurl_create(url, &urlns);
+ free(url);
+ break;
+
+ case 0xfaf: /* HTML file */
+ error = netsurf_path_to_nsurl(message->data.data_xfer.file_name,
+ &urlns);
+ break;
+
+ case 0x1ba: /* IEURL file */
+ url = ro_gui_ieurl_file_parse(message->
+ data.data_xfer.file_name);
+ error = nsurl_create(url, &urlns);
+ free(url);
+ break;
+
+ case 0x2000: /* application */
+ len = strlen(message->data.data_xfer.file_name);
+ if (len < 9 || strcmp(".!NetSurf",
+ message->data.data_xfer.file_name + len - 9))
+ return;
+
+ if (nsoption_charp(homepage_url) &&
+ nsoption_charp(homepage_url)[0]) {
+ error = nsurl_create(nsoption_charp(homepage_url),
+ &urlns);
+ } else {
+ error = nsurl_create(NETSURF_HOMEPAGE, &urlns);
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ /* send DataLoadAck */
+ message->action = message_DATA_LOAD_ACK;
+ message->your_ref = message->my_ref;
+ oserror = xwimp_send_message(wimp_USER_MESSAGE, message, message->sender);
+ if (oserror) {
+ LOG(("xwimp_send_message: 0x%x: %s",
+ oserror->errnum, oserror->errmess));
+ warn_user("WimpError", oserror->errmess);
+ return;
+ }
+
+ if (error != NSERROR_OK) {
+ warn_user(messages_get_errorcode(error), 0);
+ return;
+ }
+
+ /* create a new window with the file */
+ error = browser_window_create(BW_CREATE_HISTORY,
+ urlns,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(urlns);
+ if (error != NSERROR_OK) {
+ warn_user(messages_get_errorcode(error), 0);
+ }
+}
+
+
+/**
+ * Handle Message_DataLoad (file dragged in).
+ */
+static void ro_msg_dataload(wimp_message *message)
+{
+ int file_type = message->data.data_xfer.file_type;
+ char *urltxt = NULL;
+ char *title = NULL;
+ struct gui_window *g;
+ os_error *oserror;
+ nsurl *url;
+ nserror error;
+
+ g = ro_gui_window_lookup(message->data.data_xfer.w);
+ if (g) {
+ if (ro_gui_window_dataload(g, message))
+ return;
+ }
+ else {
+ g = ro_gui_toolbar_lookup(message->data.data_xfer.w);
+ if (g && ro_gui_toolbar_dataload(g, message))
+ return;
+ }
+
+ switch (file_type) {
+ case FILETYPE_ACORN_URI:
+ urltxt = ro_gui_uri_file_parse(message->data.data_xfer.file_name,
+ &title);
+ error = nsurl_create(urltxt, &url);
+ free(urltxt);
+ break;
+
+ case FILETYPE_ANT_URL:
+ urltxt = ro_gui_url_file_parse(message->data.data_xfer.file_name);
+ error = nsurl_create(urltxt, &url);
+ free(urltxt);
+ break;
+
+ case FILETYPE_IEURL:
+ urltxt = ro_gui_ieurl_file_parse(message->data.data_xfer.file_name);
+ error = nsurl_create(urltxt, &url);
+ free(urltxt);
+ break;
+
+ case FILETYPE_HTML:
+ case FILETYPE_JNG:
+ case FILETYPE_CSS:
+ case FILETYPE_MNG:
+ case FILETYPE_GIF:
+ case FILETYPE_BMP:
+ case FILETYPE_ICO:
+ case osfile_TYPE_DRAW:
+ case FILETYPE_PNG:
+ case FILETYPE_JPEG:
+ case osfile_TYPE_SPRITE:
+ case osfile_TYPE_TEXT:
+ case FILETYPE_ARTWORKS:
+ case FILETYPE_SVG:
+ /* display the actual file */
+ error = netsurf_path_to_nsurl(message->data.data_xfer.file_name, &url);
+ break;
+
+ default:
+ return;
+ }
+
+ /* report error to user */
+ if (error != NSERROR_OK) {
+ warn_user(messages_get_errorcode(error), 0);
+ return;
+ }
+
+
+ if (g) {
+ error = browser_window_navigate(g->bw,
+ url,
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+ } else {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ }
+ nsurl_unref(url);
+ if (error != NSERROR_OK) {
+ warn_user(messages_get_errorcode(error), 0);
+ }
+
+
+ /* send DataLoadAck */
+ message->action = message_DATA_LOAD_ACK;
+ message->your_ref = message->my_ref;
+ oserror = xwimp_send_message(wimp_USER_MESSAGE, message,
+ message->sender);
+ if (oserror) {
+ LOG(("xwimp_send_message: 0x%x: %s",
+ oserror->errnum, oserror->errmess));
+ warn_user("WimpError", oserror->errmess);
+ return;
+ }
+
+}
+
+
+/**
+ * Ensure that the filename in a data transfer message is NULL terminated
+ * (some applications, especially BASIC programs use CR)
+ *
+ * \param message message to be corrected
+ */
+static void ro_msg_terminate_filename(wimp_full_message_data_xfer *message)
+{
+ const char *ep = (char*)message + message->size;
+ char *p = message->file_name;
+
+ if ((size_t)message->size >= sizeof(*message))
+ ep = (char*)message + sizeof(*message) - 1;
+
+ while (p < ep && *p >= ' ') p++;
+ *p = '\0';
+}
+
+
+/**
+ * Handle Message_DataSave
+ */
+static void ro_msg_datasave(wimp_message *message)
+{
+ wimp_full_message_data_xfer *dataxfer = (wimp_full_message_data_xfer*)message;
+
+ /* remove ghost caret if drag-and-drop protocol was used */
+// ro_gui_selection_drag_reset();
+
+ ro_msg_terminate_filename(dataxfer);
+
+ if (ro_gui_selection_prepare_paste_datasave(dataxfer))
+ return;
+
+ switch (dataxfer->file_type) {
+ case FILETYPE_ACORN_URI:
+ case FILETYPE_ANT_URL:
+ case FILETYPE_IEURL:
+ case FILETYPE_HTML:
+ case FILETYPE_JNG:
+ case FILETYPE_CSS:
+ case FILETYPE_MNG:
+ case FILETYPE_GIF:
+ case FILETYPE_BMP:
+ case FILETYPE_ICO:
+ case osfile_TYPE_DRAW:
+ case FILETYPE_PNG:
+ case FILETYPE_JPEG:
+ case osfile_TYPE_SPRITE:
+ case osfile_TYPE_TEXT:
+ case FILETYPE_ARTWORKS:
+ case FILETYPE_SVG: {
+ os_error *error;
+
+ dataxfer->your_ref = dataxfer->my_ref;
+ dataxfer->size = offsetof(wimp_full_message_data_xfer, file_name) + 16;
+ dataxfer->action = message_DATA_SAVE_ACK;
+ dataxfer->est_size = -1;
+ memcpy(dataxfer->file_name, "<Wimp$Scrap>", 13);
+
+ error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message*)dataxfer, message->sender);
+ if (error) {
+ LOG(("xwimp_send_message: 0x%x: %s", error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ }
+ break;
+ }
+}
+
+
+/**
+ * Handle Message_DataSaveAck.
+ */
+static void ro_msg_datasave_ack(wimp_message *message)
+{
+ ro_msg_terminate_filename((wimp_full_message_data_xfer*)message);
+
+ if (ro_print_ack(message))
+ return;
+
+ switch (gui_current_drag_type) {
+ case GUI_DRAG_DOWNLOAD_SAVE:
+ ro_gui_download_datasave_ack(message);
+ break;
+
+ case GUI_DRAG_SAVE:
+ ro_gui_save_datasave_ack(message);
+ gui_current_drag_type = GUI_DRAG_NONE;
+ break;
+
+ default:
+ break;
+ }
+
+ gui_current_drag_type = GUI_DRAG_NONE;
+}
+
+
+/**
+ * Handle PreQuit message
+ *
+ * \param message PreQuit message from Wimp
+ */
+static void ro_msg_prequit(wimp_message *message)
+{
+ if (!ro_gui_prequit()) {
+ os_error *error;
+
+ /* we're objecting to the close down */
+ message->your_ref = message->my_ref;
+ error = xwimp_send_message(wimp_USER_MESSAGE_ACKNOWLEDGE,
+ message, message->sender);
+ if (error) {
+ LOG(("xwimp_send_message: 0x%x:%s", error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ }
+}
+
+
+/**
+ * Handle SaveDesktop message.
+ *
+ * \param message SaveDesktop message from Wimp.
+ */
+static void ro_msg_save_desktop(wimp_message *message)
+{
+ os_error *error;
+
+ error = xosgbpb_writew(message->data.save_desktopw.file,
+ (const byte*)"Run ", 4, NULL);
+ if (!error) {
+ error = xosgbpb_writew(message->data.save_desktopw.file,
+ (const byte*)NETSURF_DIR, strlen(NETSURF_DIR), NULL);
+ if (!error)
+ error = xos_bputw('\n', message->data.save_desktopw.file);
+ }
+
+ if (error) {
+ LOG(("xosgbpb_writew/xos_bputw: 0x%x:%s", error->errnum, error->errmess));
+ 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);
+ }
+ }
+}
+
+
/**
- * Initialise the gui (RISC OS specific part).
+ * Handle WindowInfo message (part of the iconising protocol)
+ *
+ * \param message WindowInfo message from the Iconiser
*/
+static void ro_msg_window_info(wimp_message *message)
+{
+ wimp_full_message_window_info *wi;
+ struct gui_window *g;
-static void gui_init(int argc, char** argv)
+ /* allow the user to turn off thumbnail icons */
+ if (!nsoption_bool(thumbnail_iconise))
+ return;
+
+ wi = (wimp_full_message_window_info*)message;
+ g = ro_gui_window_lookup(wi->w);
+
+ /* ic_<task name> will suffice for our other windows */
+ if (g) {
+ ro_gui_window_iconise(g, wi);
+ ro_gui_dialog_close_persistent(wi->w);
+ }
+}
+
+
+/**
+ * Get screen properties following a mode change.
+ */
+static void ro_gui_get_screen_properties(void)
+{
+ static const ns_os_vdu_var_list vars = {
+ os_MODEVAR_XWIND_LIMIT,
+ {
+ os_MODEVAR_YWIND_LIMIT,
+ os_MODEVAR_XEIG_FACTOR,
+ os_MODEVAR_YEIG_FACTOR,
+ os_VDUVAR_END_LIST
+ }
+ };
+ os_error *error;
+ int vals[4];
+
+ error = xos_read_vdu_variables(PTR_OS_VDU_VAR_LIST(&vars), vals);
+ if (error) {
+ LOG(("xos_read_vdu_variables: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("MiscError", error->errmess);
+ return;
+ }
+ screen_info.width = (vals[0] + 1) << vals[2];
+ screen_info.height = (vals[1] + 1) << vals[3];
+}
+
+
+/**
+ * Warn the user if Inet$Resolvers is not set.
+ */
+static void ro_gui_check_resolvers(void)
+{
+ char *resolvers;
+ resolvers = getenv("Inet$Resolvers");
+ if (resolvers && resolvers[0]) {
+ LOG(("Inet$Resolvers '%s'", resolvers));
+ } else {
+ LOG(("Inet$Resolvers not set or empty"));
+ warn_user("Resolvers", 0);
+ }
+}
+
+
+/**
+ * Initialise the RISC OS specific GUI.
+ *
+ * \param argc The number of command line arguments.
+ * \param argv The string vector of command line arguments.
+ */
+static nserror gui_init(int argc, char** argv)
{
struct {
void (*sigabrt)(int);
@@ -417,7 +1101,9 @@ static void gui_init(int argc, char** argv)
int length;
char *nsdir_temp;
byte *base;
- nserror err;
+ 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
@@ -540,27 +1226,35 @@ static void gui_init(int argc, char** argv)
die(error->errmess);
}
- err = treeview_init(12);
- if (err != NSERROR_OK) {
+ ret = treeview_init(12);
+ if (ret != NSERROR_OK) {
die("Failed to initialise treeview");
}
/* Initialise themes before dialogs */
ro_gui_theme_initialise();
+
/* Initialise dialog windows (must be after UI sprites are loaded) */
ro_gui_dialog_init();
+
/* Initialise download window */
ro_gui_download_init();
+
/* Initialise menus */
ro_gui_menu_init();
+
/* Initialise query windows */
ro_gui_query_init();
+
/* Initialise the history subsystem */
ro_gui_history_init();
+
/* Initialise toolbars */
ro_toolbar_init();
+
/* Initialise url bar module */
ro_gui_url_bar_init();
+
/* Initialise browser windows */
ro_gui_window_initialise();
@@ -572,89 +1266,84 @@ static void gui_init(int argc, char** argv)
/* Finally, check Inet$Resolvers for sanity */
ro_gui_check_resolvers();
-}
-/**
- * Create intermediate directories for Choices and User Data files
- */
-void ro_gui_create_dirs(void)
-{
- char buf[256];
- char *path;
-
- /* Choices */
- path = getenv("NetSurf$ChoicesSave");
- if (!path)
- die("Failed to find NetSurf Choices save path");
-
- snprintf(buf, sizeof(buf), "%s", path);
- ro_gui_create_dir(buf);
-
- /* URL */
- snprintf(buf, sizeof(buf), "%s", nsoption_charp(url_save));
- ro_gui_create_dir(buf);
+ /* certificate verification window */
+ ro_gui_cert_postinitialise();
- /* Hotlist */
- snprintf(buf, sizeof(buf), "%s", nsoption_charp(hotlist_save));
- ro_gui_create_dir(buf);
+ /* hotlist window */
+ ro_gui_hotlist_postinitialise();
- /* Recent */
- snprintf(buf, sizeof(buf), "%s", nsoption_charp(recent_save));
- ro_gui_create_dir(buf);
+ /* global history window */
+ ro_gui_global_history_postinitialise();
- /* 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);
-}
+ /* cookies window */
+ ro_gui_cookies_postinitialise();
+ open_window = nsoption_bool(open_browser_at_startup);
-/**
- * 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
- */
-void ro_gui_create_dir(char *path)
-{
- char *cur = path;
- while ((cur = strchr(cur, '.'))) {
- *cur = '\0';
- xosfile_create_dir(path, 0);
- *cur++ = '.';
+ /* 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;
-/**
- * Choose the language to use.
- */
+ /* HTML files */
+ if (strcasecmp(argv[1], "-html") == 0) {
+ ret = netsurf_path_to_nsurl(argv[2], &url);
+ }
+ /* URL files */
+ else if (strcasecmp(argv[1], "-urlf") == 0) {
+ char *urlf = ro_gui_url_file_parse(argv[2]);
+ if (!urlf) {
+ LOG(("allocation failed"));
+ die("Insufficient memory for URL");
+ }
+ ret = nsurl_create(urlf, &url);
+ free(urlf);
+ }
+ /* ANT URL Load */
+ else if (strcasecmp(argv[1], "-url") == 0) {
+ ret = nsurl_create(argv[2], &url);
+ }
+ /* Unknown => exit here. */
+ else {
+ LOG(("Unknown parameters: '%s' '%s'",
+ argv[1], argv[2]));
+ return NSERROR_BAD_PARAMETER;
+ }
+ }
+ /* get user's homepage (if configured) */
+ else if (nsoption_charp(homepage_url) &&
+ nsoption_charp(homepage_url)[0]) {
+ ret = nsurl_create(nsoption_charp(homepage_url), &url);
+ }
+ /* default homepage */
+ else {
+ ret = nsurl_create(NETSURF_HOMEPAGE, &url);
+ }
-void ro_gui_choose_language(void)
-{
- char path[40];
+ /* check for url creation error */
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
- /* if option_language exists and is valid, use that */
- if (nsoption_charp(language)) {
- if (2 < strlen(nsoption_charp(language)))
- nsoption_charp(language)[2] = 0;
- sprintf(path, "NetSurf:Resources.%s", nsoption_charp(language));
- if (is_dir(path)) {
- nsoption_setnull_charp(accept_language,
- strdup(nsoption_charp(language)));
- return;
- }
- nsoption_set_charp(language, NULL);
+ if (open_window) {
+ ret = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
}
+ nsurl_unref(url);
- 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");
+ return ret;
}
@@ -664,7 +1353,6 @@ void ro_gui_choose_language(void)
* RISC OS has no standard way of determining which language the user prefers.
* We have to guess from the 'Country' setting.
*/
-
const char *ro_gui_default_language(void)
{
char path[40];
@@ -704,222 +1392,173 @@ const char *ro_gui_default_language(void)
/**
- * Warn the user if Inet$Resolvers is not set.
- */
-
-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);
- }
-}
-
-
-/**
- * Last-minute gui init, after all other modules have initialised.
+ * 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.
*/
-
-static void gui_init2(int argc, char** argv)
+static nserror ro_path_to_nsurl(const char *path, struct nsurl **url_out)
{
- char *url = 0;
- bool open_window = nsoption_bool(open_browser_at_startup);
-
- /* Complete initialisation of the treeview modules. */
-
- /* certificate verification window */
- ro_gui_cert_postinitialise();
+ 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 */
- /* hotlist window */
- ro_gui_hotlist_postinitialise();
+ /* 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;
+ }
- /* global history window */
- ro_gui_global_history_postinitialise();
+ canonical_path = malloc(1 - spare);
+ if (canonical_path == NULL) {
+ free(canonical_path);
+ return NSERROR_NOMEM;
+ }
- /* cookies window */
- ro_gui_cookies_postinitialise();
+ 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;
+ }
+ /* create a unix path from teh cananocal risc os one */
+ unix_path = __unixify(canonical_path, __RISCOSIFY_NO_REVERSE_SUFFIX, NULL, 0, 0);
- /* 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)
- open_window = false;
+ if (unix_path == NULL) {
+ LOG(("__unixify failed: %s", canonical_path));
+ free(canonical_path);
+ return NSERROR_BAD_PARAMETER;
}
- else if (argc == 3) {
- LOG(("parameters: '%s' '%s'", argv[1], argv[2]));
- open_window = true;
+ free(canonical_path);
- /* HTML files */
- if (strcasecmp(argv[1], "-html") == 0) {
- url = path_to_url(argv[2]);
- if (!url) {
- LOG(("malloc failed"));
- die("Insufficient memory for URL");
- }
- }
- /* URL files */
- else if (strcasecmp(argv[1], "-urlf") == 0) {
- url = ro_gui_url_file_parse(argv[2]);
- if (!url) {
- LOG(("malloc failed"));
- die("Insufficient memory for URL");
- }
- }
- /* ANT URL Load */
- else if (strcasecmp(argv[1], "-url") == 0) {
- url = strdup(argv[2]);
- if (!url) {
- LOG(("malloc failed"));
- die("Insufficient memory for 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]) {
- url = calloc(strlen(nsoption_charp(homepage_url)) + 5, sizeof(char));
- if (!url) {
- LOG(("malloc failed"));
- die("Insufficient memory for URL");
- }
- sprintf(url, "%s", nsoption_charp(homepage_url));
- }
- /* default homepage */
- else {
- url = strdup(NETSURF_HOMEPAGE);
- if (!url) {
- LOG(("malloc failed"));
- die("Insufficient memory for URL");
- }
+ /* 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 (open_window) {
- nsurl *urlns;
- nserror errorns;
-
- errorns = nsurl_create(url, &urlns);
- if (errorns == NSERROR_OK) {
- errorns = browser_window_create(BROWSER_WINDOW_VERIFIABLE |
- BROWSER_WINDOW_HISTORY,
- urlns,
- NULL,
- NULL,
- NULL);
- nsurl_unref(urlns);
- }
- if (errorns != NSERROR_OK) {
- warn_user(messages_get_errorcode(errorns), 0);
- }
+ if (*unix_path == '/') {
+ snprintf(url, urllen, "%s%s", FILE_SCHEME_PREFIX, unix_path + 1);
+ } else {
+ snprintf(url, urllen, "%s%s", FILE_SCHEME_PREFIX, unix_path);
}
+ free(unix_path);
+ /* We don't want '/' to be escaped. */
+ ret = url_escape(url, FILE_SCHEME_PREFIX_LEN, false, "/", &escurl);
free(url);
-}
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
-/**
- * Ensures output logging stream is correctly configured
- */
-static bool nslog_stream_configure(FILE *fptr)
-{
- /* set log stream to be non-buffering */
- setbuf(fptr, NULL);
+ ret = nsurl_create(escurl, url_out);
+ free(escurl);
- return true;
+ return ret;
}
-/** Normal entry point from OS */
-int main(int argc, char** argv)
+
+/**
+ * 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.
+ */
+static nserror ro_nsurl_to_path(struct nsurl *url, char **path_out)
{
- char path[40];
- int length;
- char logging_env[2];
- os_var_type type;
- int used = -1; /* slightly better with older OSLib versions */
- os_error *error;
- nserror ret;
+ lwc_string *urlpath;
+ char *unpath;
+ char *path;
+ bool match;
+ lwc_string *scheme;
+ nserror res;
+ char *r;
- /* Consult NetSurf$Logging environment variable to decide if logging
- * is required. */
- error = xos_read_var_val_size("NetSurf$Logging", 0, os_VARTYPE_STRING,
- &used, NULL, &type);
- if (error != NULL || type != os_VARTYPE_STRING || used != -2) {
- verbose_log = true;
- } else {
- error = xos_read_var_val("NetSurf$Logging", logging_env,
- sizeof(logging_env), 0, os_VARTYPE_STRING,
- &used, NULL, &type);
- if (error != NULL || logging_env[0] != '0') {
- verbose_log = true;
- } else {
- verbose_log = false;
- }
+ if ((url == NULL) || (path_out == NULL)) {
+ return NSERROR_BAD_PARAMETER;
}
- /* initialise logging. Not fatal if it fails but not much we
- * can do about it either.
- */
- nslog_init(nslog_stream_configure, &argc, argv);
+ scheme = nsurl_get_component(url, NSURL_SCHEME);
- /* user options setup */
- ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
- if (ret != NSERROR_OK) {
- die("Options failed to initialise");
+ 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;
}
- nsoption_read("NetSurf:Choices", NULL);
- nsoption_commandline(&argc, argv, NULL);
-
- /* Choose the interface language to use */
- ro_gui_choose_language();
- /* select language-specific Messages */
- if (((length = snprintf(path,
- sizeof(path),
- "NetSurf:Resources.%s.Messages",
- nsoption_charp(language))) < 0) ||
- (length >= (int)sizeof(path))) {
- die("Failed to locate Messages resource.");
+ urlpath = nsurl_get_component(url, NSURL_PATH);
+ if (urlpath == NULL) {
+ return NSERROR_BAD_PARAMETER;
}
- /* common initialisation */
- ret = netsurf_init(path);
- if (ret != NSERROR_OK) {
- die("NetSurf failed to initialise");
+ res = url_unescape(lwc_string_data(urlpath), &unpath);
+ lwc_string_unref(urlpath);
+ if (res != NSERROR_OK) {
+ return res;
}
- artworks_init();
- draw_init();
- sprite_init();
+ /* RISC OS path should not be more than 100 characters longer */
+ path = malloc(strlen(unpath) + 100);
+ if (path == NULL) {
+ free(unpath);
+ return NSERROR_NOMEM;
+ }
- /* Load some extra RISC OS specific Messages */
- messages_load("NetSurf:Resources.LangNames");
+ r = __riscosify(unpath, 0, __RISCOSIFY_NO_SUFFIX,
+ path, strlen(unpath) + 100, 0);
+ free(unpath);
+ if (r == NULL) {
+ free(path);
+ return NSERROR_NOMEM;
+ }
- gui_init(argc, argv);
+ *path_out = path;
- gui_init2(argc, argv);
+ return NSERROR_OK;
+}
- netsurf_main_loop();
- netsurf_exit();
+/**
+ * Ensures output logging stream is correctly configured.
+ */
+static bool nslog_stream_configure(FILE *fptr)
+{
+ /* set log stream to be non-buffering */
+ setbuf(fptr, NULL);
- return 0;
+ return true;
}
/**
* Close down the gui (RISC OS).
*/
-
-void gui_quit(void)
+static void gui_quit(void)
{
urldb_save_cookies(nsoption_charp(cookie_jar));
urldb_save(nsoption_charp(url_save));
@@ -937,237 +1576,9 @@ void gui_quit(void)
/**
- * Handles a signal
- */
-
-void ro_gui_signal(int sig)
-{
- static const os_error error = { 1, "NetSurf has detected a serious "
- "error and must exit. Please submit a bug report, "
- "attaching the browser log file." };
- os_colour old_sand, old_glass;
-
- ro_gui_cleanup();
-
- xhourglass_on();
- xhourglass_colours(0x0000ffff, 0x000000ff, &old_sand, &old_glass);
- nsoption_dump(stderr, NULL);
- /*rufl_dump_state();*/
-
-#ifndef __ELF__
- /* save WimpSlot and DA to files if NetSurf$CoreDump exists */
- int used;
- xos_read_var_val_size("NetSurf$CoreDump", 0, 0, &used, 0, 0);
- if (used) {
- int curr_slot;
- xwimp_slot_size(-1, -1, &curr_slot, 0, 0);
- LOG(("saving WimpSlot, size 0x%x", curr_slot));
- xosfile_save("$.NetSurf_Slot", 0x8000, 0,
- (byte *) 0x8000,
- (byte *) 0x8000 + curr_slot);
-
- if (__dynamic_num != -1) {
- int size;
- byte *base_address;
- xosdynamicarea_read(__dynamic_num, &size,
- &base_address, 0, 0, 0, 0, 0);
- LOG(("saving DA %i, base %p, size 0x%x",
- __dynamic_num,
- base_address, size));
- xosfile_save("$.NetSurf_DA",
- (bits) base_address, 0,
- base_address,
- base_address + size);
- }
- }
-#else
- /* Save WimpSlot and UnixLib managed DAs when UnixEnv$coredump
- * defines a coredump directory. */
- _kernel_oserror *err = __unixlib_write_coredump (NULL);
- if (err != NULL)
- LOG(("Coredump failed: %s", err->errmess));
-#endif
-
- xhourglass_colours(old_sand, old_glass, 0, 0);
- xhourglass_off();
-
- __write_backtrace(sig);
-
- xwimp_report_error_by_category(&error,
- wimp_ERROR_BOX_GIVEN_CATEGORY |
- wimp_ERROR_BOX_CATEGORY_ERROR <<
- wimp_ERROR_BOX_CATEGORY_SHIFT,
- "NetSurf", "!netsurf",
- (osspriteop_area *) 1, "Quit", 0);
- xos_cli("Filer_Run <Wimp$ScrapDir>.WWW.NetSurf.Log");
-
- _Exit(sig);
-}
-
-
-/**
- * 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).
- *
- * \param active return as soon as possible
- */
-
-void gui_poll(bool active)
-{
- 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;
-
- event = wimp_poll_idle(mask, &block, t, 0);
- } else {
- event = wimp_poll(wimp_MASK_NULL | mask, &block, 0);
- }
-
- xhourglass_on();
- gui_last_poll = clock();
- ro_gui_handle_event(event, &block);
-
- /* Only run scheduled callbacks on a null poll
- * We cannot do this in the null event handler, as that may be called
- * from gui_multitask(). Scheduled callbacks must only be run from the
- * top-level.
- */
- if (event == wimp_NULL_REASON_CODE)
- schedule_run();
-
- ro_gui_window_update_boxes();
-
- if (browser_reformat_pending && event == wimp_NULL_REASON_CODE)
- ro_gui_window_process_reformats();
-}
-
-
-/**
- * Process a Wimp_Poll event.
- *
- * \param event wimp event number
- * \param block parameter block
- */
-
-void ro_gui_handle_event(wimp_event_no event, wimp_block *block)
-{
- switch (event) {
- case wimp_NULL_REASON_CODE:
- ro_gui_throb();
- ro_mouse_poll();
- break;
-
- case wimp_REDRAW_WINDOW_REQUEST:
- ro_gui_wimp_event_redraw_window(&block->redraw);
- break;
-
- case wimp_OPEN_WINDOW_REQUEST:
- ro_gui_open_window_request(&block->open);
- break;
-
- case wimp_CLOSE_WINDOW_REQUEST:
- ro_gui_close_window_request(&block->close);
- break;
-
- case wimp_POINTER_LEAVING_WINDOW:
- ro_mouse_pointer_leaving_window(&block->leaving);
- break;
-
- case wimp_POINTER_ENTERING_WINDOW:
- ro_gui_wimp_event_pointer_entering_window(&block->entering);
- break;
-
- case wimp_MOUSE_CLICK:
- ro_gui_wimp_event_mouse_click(&block->pointer);
- break;
-
- case wimp_USER_DRAG_BOX:
- ro_mouse_drag_end(&block->dragged);
- break;
-
- case wimp_KEY_PRESSED:
- ro_gui_keypress(&(block->key));
- break;
-
- case wimp_MENU_SELECTION:
- ro_gui_menu_selection(&(block->selection));
- break;
-
- /* Scroll requests fall back to a generic handler because we
- * might get these events for any window from a scroll-wheel.
- */
-
- case wimp_SCROLL_REQUEST:
- if (!ro_gui_wimp_event_scroll_window(&(block->scroll)))
- ro_gui_scroll(&(block->scroll));
- break;
-
- case wimp_USER_MESSAGE:
- case wimp_USER_MESSAGE_RECORDED:
- case wimp_USER_MESSAGE_ACKNOWLEDGE:
- ro_gui_user_message(event, &(block->message));
- break;
- }
-}
-
-
-/**
- * Handle Open_Window_Request events.
- */
-
-void ro_gui_open_window_request(wimp_open *open)
-{
- os_error *error;
-
- if (ro_gui_wimp_event_open_window(open))
- return;
-
- error = xwimp_open_window(open);
- if (error) {
- LOG(("xwimp_open_window: 0x%x: %s",
- error->errnum, error->errmess));
- warn_user("WimpError", error->errmess);
- return;
- }
-}
-
-
-/**
* Handle Close_Window_Request events.
*/
-
-void ro_gui_close_window_request(wimp_close *close)
+static void ro_gui_close_window_request(wimp_close *close)
{
if (ro_gui_alt_pressed())
ro_gui_window_close_all();
@@ -1180,9 +1591,8 @@ void ro_gui_close_window_request(wimp_close *close)
/**
- * Handle Key_Pressed events.
+ * Handle key press paste callback.
*/
-
static void ro_gui_keypress_cb(void *pw)
{
wimp_key *key = (wimp_key *) pw;
@@ -1199,14 +1609,20 @@ static void ro_gui_keypress_cb(void *pw)
free(key);
}
-void ro_gui_keypress(wimp_key *key)
+
+/**
+ * Handle gui keypress.
+ */
+static void ro_gui_keypress(wimp_key *key)
{
if (key->c == wimp_KEY_ESCAPE &&
(gui_current_drag_type == GUI_DRAG_SAVE ||
gui_current_drag_type == GUI_DRAG_DOWNLOAD_SAVE)) {
- /* Allow Escape key to be used for cancelling a drag save
- (easier than finding somewhere safe to abort the drag) */
+ /* 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 */) {
@@ -1233,7 +1649,7 @@ void ro_gui_keypress(wimp_key *key)
/**
* Handle the three User_Message events.
*/
-void ro_gui_user_message(wimp_event_no event, wimp_message *message)
+static void ro_gui_user_message(wimp_event_no event, wimp_message *message)
{
/* attempt automatic routing */
if (ro_message_handle_message(event, message))
@@ -1263,7 +1679,8 @@ void ro_gui_user_message(wimp_event_no event, wimp_message *message)
break;
case message_MENUS_DELETED:
- ro_gui_menu_closed();
+ ro_gui_menu_message_deleted((wimp_message_menus_deleted *)
+ &message->data);
break;
case message_CLAIM_ENTITY:
@@ -1367,769 +1784,169 @@ void ro_gui_user_message(wimp_event_no event, wimp_message *message)
/**
- * Ensure that the filename in a data transfer message is NUL terminated
- * (some applications, especially BASIC programs use CR)
+ * Process a Wimp_Poll event.
*
- * \param message message to be corrected
- */
-
-void ro_msg_terminate_filename(wimp_full_message_data_xfer *message)
-{
- const char *ep = (char*)message + message->size;
- char *p = message->file_name;
-
- if ((size_t)message->size >= sizeof(*message))
- ep = (char*)message + sizeof(*message) - 1;
-
- while (p < ep && *p >= ' ') p++;
- *p = '\0';
-}
-
-
-/**
- * Handle Message_DataLoad (file dragged in).
+ * \param event wimp event number
+ * \param block parameter block
*/
-
-void ro_msg_dataload(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;
- int tree_file_type = file_type;
- char *urltxt = NULL;
- char *title = NULL;
- struct gui_window *g;
- os_error *oserror;
- nsurl *url;
- nserror error;
-
- g = ro_gui_window_lookup(message->data.data_xfer.w);
- if (g) {
- if (ro_gui_window_dataload(g, message))
- return;
- }
- else {
- g = ro_gui_toolbar_lookup(message->data.data_xfer.w);
- if (g && ro_gui_toolbar_dataload(g, message))
- return;
- }
-
- switch (file_type) {
- case FILETYPE_ACORN_URI:
- urltxt = ro_gui_uri_file_parse(message->data.data_xfer.file_name,
- &title);
- tree_file_type = 0xfaf;
- break;
- case FILETYPE_ANT_URL:
- urltxt = ro_gui_url_file_parse(message->data.data_xfer.file_name);
- tree_file_type = 0xfaf;
- break;
- case FILETYPE_IEURL:
- urltxt = ro_gui_ieurl_file_parse(message->data.data_xfer.file_name);
- tree_file_type = 0xfaf;
+ switch (event) {
+ case wimp_NULL_REASON_CODE:
+ ro_gui_throb();
+ ro_mouse_poll();
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 */
- urltxt = path_to_url(message->data.data_xfer.file_name);
+ case wimp_REDRAW_WINDOW_REQUEST:
+ ro_gui_wimp_event_redraw_window(&block->redraw);
break;
- default:
- return;
- }
-
- if (!urltxt)
- /* error has already been reported by one of the
- * functions called above */
- return;
-
-
- error = nsurl_create(urltxt, &url);
- if (error == NSERROR_OK) {
- if (g) {
- error = browser_window_navigate(g->bw,
- url,
- NULL,
- BROWSER_WINDOW_HISTORY |
- BROWSER_WINDOW_VERIFIABLE,
- NULL,
- NULL,
- NULL);
-
-#ifdef DROPURLHOTLIST /** @todo This was commented out should it be removed? */
- } else if (ro_gui_hotlist_check_window(
- message->data.data_xfer.w)) {
- /* Drop URL into hotlist */
- ro_gui_hotlist_url_drop(message, urltxt);
-#endif
- } else {
- error = browser_window_create(
- BROWSER_WINDOW_VERIFIABLE |
- BROWSER_WINDOW_HISTORY,
- url,
- NULL,
- NULL,
- NULL);
- }
- nsurl_unref(url);
- }
- if (error != NSERROR_OK) {
- warn_user(messages_get_errorcode(error), 0);
- }
-
- free(urltxt);
-
- /* 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;
- }
-
-}
-
-
-/**
- * Parse an Acorn URI file.
- *
- * \param file_name file to read
- * \param uri_title pointer to receive title data, or NULL for no data
- * \return URL from file, or 0 on error and error reported
- */
-
-char *ro_gui_uri_file_parse(const char *file_name, char **uri_title)
-{
- /* See the "Acorn URI Handler Functional Specification" for the
- * definition of the URI file format. */
- char line[400];
- char *url = NULL;
- FILE *fp;
-
- *uri_title = NULL;
- fp = fopen(file_name, "rb");
- if (!fp) {
- LOG(("fopen(\"%s\", \"rb\"): %i: %s",
- file_name, errno, strerror(errno)));
- 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_syntax_error;
- 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_syntax_error:
- fclose(fp);
- warn_user("URIError", 0);
- return 0;
-}
-
-
-/**
- * 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
- */
-
-bool ro_gui_uri_file_parse_line(FILE *fp, char *b)
-{
- int c;
- unsigned int i = 0;
-
- c = getc(fp);
- if (c == EOF)
- return false;
-
- /* skip comment lines */
- while (c == '#') {
- do { c = getc(fp); } while (c != EOF && 32 <= c);
- if (c == EOF)
- return false;
- do { c = getc(fp); } while (c != EOF && c < 32);
- if (c == EOF)
- return false;
- }
-
- /* read "line" */
- do {
- if (i == 399)
- return false;
- b[i++] = c;
- c = getc(fp);
- } while (c != EOF && 32 <= c);
-
- /* skip line ending control characters */
- while (c != EOF && c < 32)
- c = getc(fp);
-
- if (c != EOF)
- ungetc(c, fp);
-
- b[i] = 0;
- return true;
-}
-
-
-/**
- * Parse an ANT URL file.
- *
- * \param file_name file to read
- * \return URL from file, or 0 on error and error reported
- */
-
-char *ro_gui_url_file_parse(const char *file_name)
-{
- char line[400];
- char *url;
- FILE *fp;
-
- fp = fopen(file_name, "r");
- if (!fp) {
- LOG(("fopen(\"%s\", \"r\"): %i: %s",
- file_name, errno, strerror(errno)));
- 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;
- }
-
- 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;
-}
-
-
-/**
- * Parse an IEURL file.
- *
- * \param file_name file to read
- * \return URL from file, or 0 on error and error reported
- */
-
-char *ro_gui_ieurl_file_parse(const char *file_name)
-{
- char line[400];
- char *url = 0;
- FILE *fp;
-
- fp = fopen(file_name, "r");
- if (!fp) {
- LOG(("fopen(\"%s\", \"r\"): %i: %s",
- file_name, errno, strerror(errno)));
- warn_user("LoadError", strerror(errno));
- return 0;
- }
-
- while (fgets(line, sizeof line, fp)) {
- if (strncmp(line, "URL=", 4) == 0) {
- if (line[strlen(line) - 1] == '\n')
- line[strlen(line) - 1] = '\0';
- url = strdup(line + 4);
- if (!url) {
- fclose(fp);
- warn_user("NoMemory", 0);
- return 0;
- }
+ case wimp_OPEN_WINDOW_REQUEST:
+ ro_gui_open_window_request(&block->open);
break;
- }
- }
- 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
- */
-
-void ro_msg_datasave(wimp_message *message)
-{
- wimp_full_message_data_xfer *dataxfer = (wimp_full_message_data_xfer*)message;
-
- /* remove ghost caret if drag-and-drop protocol was used */
-// ro_gui_selection_drag_reset();
-
- ro_msg_terminate_filename(dataxfer);
- if (ro_gui_selection_prepare_paste_datasave(dataxfer))
- return;
-
- switch (dataxfer->file_type) {
- case FILETYPE_ACORN_URI:
- case FILETYPE_ANT_URL:
- case FILETYPE_IEURL:
- case FILETYPE_HTML:
- case FILETYPE_JNG:
- case FILETYPE_CSS:
- case FILETYPE_MNG:
- case FILETYPE_GIF:
- case FILETYPE_BMP:
- case FILETYPE_ICO:
- case osfile_TYPE_DRAW:
- case FILETYPE_PNG:
- case FILETYPE_JPEG:
- case osfile_TYPE_SPRITE:
- case osfile_TYPE_TEXT:
- case FILETYPE_ARTWORKS:
- case FILETYPE_SVG: {
- os_error *error;
-
- dataxfer->your_ref = dataxfer->my_ref;
- dataxfer->size = offsetof(wimp_full_message_data_xfer, file_name) + 16;
- dataxfer->action = message_DATA_SAVE_ACK;
- dataxfer->est_size = -1;
- memcpy(dataxfer->file_name, "<Wimp$Scrap>", 13);
+ case wimp_CLOSE_WINDOW_REQUEST:
+ ro_gui_close_window_request(&block->close);
+ break;
- 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;
- }
-}
+ 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;
-/**
- * Handle Message_DataSaveAck.
- */
+ case wimp_MOUSE_CLICK:
+ ro_gui_wimp_event_mouse_click(&block->pointer);
+ break;
-void ro_msg_datasave_ack(wimp_message *message)
-{
- ro_msg_terminate_filename((wimp_full_message_data_xfer*)message);
+ case wimp_USER_DRAG_BOX:
+ ro_mouse_drag_end(&block->dragged);
+ break;
- if (ro_print_ack(message))
- return;
+ case wimp_KEY_PRESSED:
+ ro_gui_keypress(&(block->key));
+ break;
- switch (gui_current_drag_type) {
- case GUI_DRAG_DOWNLOAD_SAVE:
- ro_gui_download_datasave_ack(message);
+ case wimp_MENU_SELECTION:
+ ro_gui_menu_selection(&(block->selection));
break;
- case GUI_DRAG_SAVE:
- ro_gui_save_datasave_ack(message);
- gui_current_drag_type = GUI_DRAG_NONE;
+ /* Scroll requests fall back to a generic handler because we
+ * might get these events for any window from a scroll-wheel.
+ */
+
+ case wimp_SCROLL_REQUEST:
+ if (!ro_gui_wimp_event_scroll_window(&(block->scroll)))
+ ro_gui_scroll(&(block->scroll));
break;
- default:
+ case wimp_USER_MESSAGE:
+ case wimp_USER_MESSAGE_RECORDED:
+ case wimp_USER_MESSAGE_ACKNOWLEDGE:
+ ro_gui_user_message(event, &(block->message));
break;
}
-
- gui_current_drag_type = GUI_DRAG_NONE;
}
/**
- * Handle Message_DataOpen (double-click on file in the Filer).
+ * Poll the RISC OS wimp for events.
*/
-
-void ro_msg_dataopen(wimp_message *message)
+static void riscos_poll(bool active)
{
- int file_type = message->data.data_xfer.file_type;
- char *url = 0;
- size_t len;
- os_error *oserror;
- nsurl *urlns;
- nserror error;
+ 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;
- if (file_type == 0xb28) /* ANT URL file */
- url = ro_gui_url_file_parse(message->data.data_xfer.file_name);
- else if (file_type == 0xfaf) /* HTML file */
- url = path_to_url(message->data.data_xfer.file_name);
- else if (file_type == 0x1ba) /* IEURL file */
- url = ro_gui_ieurl_file_parse(message->
- data.data_xfer.file_name);
- else if (file_type == 0x2000) { /* application */
- len = strlen(message->data.data_xfer.file_name);
- if (len < 9 || strcmp(".!NetSurf",
- message->data.data_xfer.file_name + len - 9))
- return;
- if (nsoption_charp(homepage_url) &&
- nsoption_charp(homepage_url)[0]) {
- url = strdup(nsoption_charp(homepage_url));
+ /* Poll wimp. */
+ xhourglass_off();
+ track_poll_offset = ro_mouse_poll_interval();
+ if (sched_active || (track_poll_offset > 0)) {
+ os_t t = os_read_monotonic_time();
+
+ if (track_poll_offset > 0) {
+ t += track_poll_offset;
} else {
- url = strdup(NETSURF_HOMEPAGE);
+ t += 10;
}
- if (!url)
- warn_user("NoMemory", 0);
- } else
- return;
-
- /* send DataLoadAck */
- message->action = message_DATA_LOAD_ACK;
- message->your_ref = message->my_ref;
- oserror = xwimp_send_message(wimp_USER_MESSAGE, message, message->sender);
- if (oserror) {
- LOG(("xwimp_send_message: 0x%x: %s",
- oserror->errnum, oserror->errmess));
- warn_user("WimpError", oserror->errmess);
- return;
- }
-
- if (!url)
- /* error has already been reported by one of the
- * functions called above */
- return;
-
- error = nsurl_create(url, &urlns);
- free(url);
- if (error == NSERROR_OK) {
- /* create a new window with the file */
- error = browser_window_create(BROWSER_WINDOW_VERIFIABLE |
- BROWSER_WINDOW_HISTORY,
- urlns,
- NULL,
- NULL,
- NULL);
- nsurl_unref(urlns);
- }
- if (error != NSERROR_OK) {
- warn_user(messages_get_errorcode(error), 0);
- }
-}
-
-/**
- * Handle PreQuit message
- *
- * \param message PreQuit message from Wimp
- */
-
-void ro_msg_prequit(wimp_message *message)
-{
- if (!ro_gui_prequit()) {
- os_error *error;
-
- /* we're objecting to the close down */
- message->your_ref = message->my_ref;
- error = xwimp_send_message(wimp_USER_MESSAGE_ACKNOWLEDGE,
- message, message->sender);
- if (error) {
- LOG(("xwimp_send_message: 0x%x:%s", error->errnum, error->errmess));
- warn_user("WimpError", error->errmess);
+ if (sched_active && (sched_time - t) < 0) {
+ t = sched_time;
}
- }
-}
-
-
-/**
- * Handle SaveDesktop message
- *
- * \param message SaveDesktop message from Wimp
- */
-void ro_msg_save_desktop(wimp_message *message)
-{
- os_error *error;
-
- error = xosgbpb_writew(message->data.save_desktopw.file,
- (const byte*)"Run ", 4, NULL);
- if (!error) {
- error = xosgbpb_writew(message->data.save_desktopw.file,
- (const byte*)NETSURF_DIR, strlen(NETSURF_DIR), NULL);
- if (!error)
- error = xos_bputw('\n', message->data.save_desktopw.file);
+ event = wimp_poll_idle(mask, &block, t, 0);
+ } else {
+ event = wimp_poll(wimp_MASK_NULL | mask, &block, 0);
}
- if (error) {
- LOG(("xosgbpb_writew/xos_bputw: 0x%x:%s", error->errnum, error->errmess));
- warn_user("SaveError", error->errmess);
+ xhourglass_on();
+ gui_last_poll = clock();
+ ro_gui_handle_event(event, &block);
- /* 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);
- }
+ /* 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();
}
-}
-
-/**
- * Handle WindowInfo message (part of the iconising protocol)
- *
- * \param message WindowInfo message from the Iconiser
- */
-
-void ro_msg_window_info(wimp_message *message)
-{
- wimp_full_message_window_info *wi;
- struct gui_window *g;
-
- /* allow the user to turn off thumbnail icons */
- if (!nsoption_bool(thumbnail_iconise))
- return;
-
- wi = (wimp_full_message_window_info*)message;
- g = ro_gui_window_lookup(wi->w);
-
- /* ic_<task name> will suffice for our other windows */
- if (g) {
- ro_gui_window_iconise(g, wi);
- ro_gui_dialog_close_persistent(wi->w);
- }
+ ro_gui_window_update_boxes();
}
/**
- * Convert a RISC OS pathname to a file: URL.
- *
- * \param path RISC OS pathname
- * \return URL, allocated on heap, or 0 on failure
+ * Handle Open_Window_Request events.
*/
-
-char *path_to_url(const char *path)
+void ro_gui_open_window_request(wimp_open *open)
{
- int spare;
- char *canonical_path; /* canonicalised RISC OS path */
- char *unix_path; /* unix path */
- char *escurl;
os_error *error;
- url_func_result url_err;
- int urllen;
- char *url; /* resulting url */
- /* calculate the canonical risc os path */
- error = xosfscontrol_canonicalise_path(path, 0, 0, 0, 0, &spare);
- if (error) {
- LOG(("xosfscontrol_canonicalise_path failed: 0x%x: %s",
- error->errnum, error->errmess));
- warn_user("PathToURL", error->errmess);
- return NULL;
- }
-
- canonical_path = malloc(1 - spare);
- if (canonical_path == NULL) {
- LOG(("malloc failed"));
- warn_user("NoMemory", 0);
- free(canonical_path);
- return NULL;
- }
+ if (ro_gui_wimp_event_open_window(open))
+ return;
- error = xosfscontrol_canonicalise_path(path, canonical_path, 0, 0, 1 - spare, 0);
+ error = xwimp_open_window(open);
if (error) {
- LOG(("xosfscontrol_canonicalise_path failed: 0x%x: %s",
+ LOG(("xwimp_open_window: 0x%x: %s",
error->errnum, error->errmess));
- warn_user("PathToURL", error->errmess);
- free(canonical_path);
- return NULL;
- }
-
- /* create a unix path from teh cananocal risc os one */
- unix_path = __unixify(canonical_path, __RISCOSIFY_NO_REVERSE_SUFFIX, NULL, 0, 0);
-
- if (unix_path == NULL) {
- LOG(("__unixify failed: %s", canonical_path));
- free(canonical_path);
- return NULL;
- }
- free(canonical_path);
-
- /* convert the unix path into a url */
- urllen = strlen(unix_path) + FILE_SCHEME_PREFIX_LEN + 1;
- url = malloc(urllen);
- if (url == NULL) {
- LOG(("Unable to allocate url"));
- free(unix_path);
- return NULL;
- }
-
- if (*unix_path == '/') {
- snprintf(url, urllen, "%s%s", FILE_SCHEME_PREFIX, unix_path + 1);
- } else {
- snprintf(url, urllen, "%s%s", FILE_SCHEME_PREFIX, unix_path);
- }
- free(unix_path);
-
- /* We don't want '/' to be escaped. */
- url_err = url_escape(url, FILE_SCHEME_PREFIX_LEN, false, "/", &escurl);
- free(url); url = NULL;
- if (url_err != URL_FUNC_OK) {
- LOG(("url_escape failed: %s", url));
- return NULL;
+ warn_user("WimpError", error->errmess);
+ return;
}
-
- return escurl;
}
/**
- * Convert a file: URL to a RISC OS pathname.
- *
- * \param url a file: URL
- * \return RISC OS pathname, allocated on heap, or 0 on failure
+ * source bounce callback.
*/
-
-char *url_to_path(const char *url)
+static void ro_gui_view_source_bounce(wimp_message *message)
{
- char *path;
char *filename;
- char *respath;
- url_func_result res; /* result from url routines */
- char *r;
-
- res = url_path(url, &path);
- if (res != URL_FUNC_OK) {
- warn_user("NoMemory", 0);
- return NULL;
- }
-
- res = url_unescape(path, &respath);
- free(path);
- if (res != URL_FUNC_OK) {
- return NULL;
- }
-
- /* RISC OS path should not be more than 100 characters longer */
- filename = malloc(strlen(respath) + 100);
- if (!filename) {
- free(respath);
- warn_user("NoMemory", 0);
- return NULL;
- }
-
- r = __riscosify(respath, 0, __RISCOSIFY_NO_SUFFIX,
- filename, strlen(respath) + 100, 0);
-
- free(respath);
- if (r == 0) {
- free(filename);
- LOG(("__riscosify failed"));
- return NULL;
- }
-
- return filename;
-}
-
-
-/**
- * Get screen properties following a mode change.
- */
-
-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];
+ char command[256];
- error = xos_read_vdu_variables(PTR_OS_VDU_VAR_LIST(&vars), vals);
+ /* 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(("xos_read_vdu_variables: 0x%x: %s",
- error->errnum, error->errmess));
- warn_user("MiscError", error->errmess);
- return;
+ LOG(("xwimp_start_task failed: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
}
- screen_info.width = (vals[0] + 1) << vals[2];
- screen_info.height = (vals[1] + 1) << vals[3];
-}
-
-
-/**
- * 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 source of a content to a text editor.
*/
-
void ro_gui_view_source(hlcache_handle *c)
{
os_error *error;
- char full_name[256];
- char *temp_name, *r;
+ char *temp_name;
wimp_full_message_data_xfer message;
int objtype;
bool done = false;
@@ -2150,8 +1967,7 @@ void ro_gui_view_source(hlcache_handle *c)
}
/* try to load local files directly. */
- temp_name = url_to_path(nsurl_access(hlcache_handle_get_url(c)));
- if (temp_name) {
+ if (netsurf_nsurl_to_path(hlcache_handle_get_url(c), &temp_name) == NSERROR_OK) {
error = xosfile_read_no_path(temp_name, &objtype, 0, 0, 0, 0);
if ((!error) && (objtype == osfile_IS_FILE)) {
snprintf(message.file_name, 212, "%s", temp_name);
@@ -2167,11 +1983,14 @@ void ro_gui_view_source(hlcache_handle *c)
* allow it to be re-used next time NetSurf is started. The
* memory overhead from doing this is under 1 byte per
* filename. */
+ char *r;
+ char full_name[256];
const char *filename = filename_request();
if (!filename) {
warn_user("NoMemory", 0);
return;
}
+
snprintf(full_name, 256, "%s/%s", TEMP_FILENAME_PREFIX,
filename);
full_name[255] = '\0';
@@ -2182,6 +2001,7 @@ void ro_gui_view_source(hlcache_handle *c)
return;
}
message.file_name[211] = '\0';
+
error = xosfile_save_stamped(message.file_name,
ro_content_filetype(c),
(byte *) source_data,
@@ -2210,63 +2030,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("<Wimp$ScrapDir>.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 <Wimp$ScrapDir>.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.
- */
-
-void gui_launch_url(const char *url)
-{
- /* Try ant broadcast first */
- ro_url_broadcast(url);
+ 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");
}
@@ -2276,7 +2076,6 @@ void gui_launch_url(const char *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));
@@ -2318,7 +2117,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;
@@ -2345,81 +2143,390 @@ 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;
}
+
/**
- * Return the filename part of a full path
+ * Generate a riscos path from one or more component elemnts.
+ *
+ * Constructs a complete path element from passed components. The
+ * second (and subsequent) components have a slash substituted for all
+ * riscos directory separators.
*
- * \param path full path and filename
- * \return filename (will be freed with free())
+ * If a string is allocated it must be freed by the caller.
+ *
+ * @param[in,out] str pointer to string pointer if this is NULL enough
+ * storage will be allocated for the complete path.
+ * @param[in,out] size The size of the space available if \a str not
+ * NULL on input and if not NULL set to the total
+ * output length on output.
+ * @param[in] nemb The number of elements.
+ * @param[in] ap The elements of the path as string pointers.
+ * @return NSERROR_OK and the complete path is written to str
+ * or error code on faliure.
*/
+static nserror riscos_mkpath(char **str, size_t *size, size_t nelm, va_list ap)
+{
+ const char *elm[16];
+ size_t elm_len[16];
+ size_t elm_idx;
+ char *fname;
+ size_t fname_len = 0;
+ char *curp;
+ size_t idx;
+
+ /* check the parameters are all sensible */
+ if ((nelm == 0) || (nelm > 16)) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if ((*str != NULL) && (size == NULL)) {
+ /* if the caller is providing the buffer they must say
+ * how much space is available.
+ */
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* calculate how much storage we need for the complete path
+ * with all the elements.
+ */
+ for (elm_idx = 0; elm_idx < nelm; elm_idx++) {
+ elm[elm_idx] = va_arg(ap, const char *);
+ /* check the argument is not NULL */
+ if (elm[elm_idx] == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ elm_len[elm_idx] = strlen(elm[elm_idx]);
+ fname_len += elm_len[elm_idx];
+ }
+ fname_len += nelm; /* allow for separators and terminator */
+
+ /* ensure there is enough space */
+ fname = *str;
+ if (fname != NULL) {
+ if (fname_len > *size) {
+ return NSERROR_NOSPACE;
+ }
+ } else {
+ fname = malloc(fname_len);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
+ }
+ }
+
+ /* copy the elements in with directory separator */
+ curp = fname;
-char *filename_from_path(char *path)
+ /* first element is not altered */
+ memmove(curp, elm[0], elm_len[0]);
+ curp += elm_len[0];
+ /* ensure there is a delimiter */
+ if (curp[-1] != DIR_SEP) {
+ *curp = DIR_SEP;
+ curp++;
+ }
+
+ /* subsequent elemnts have slashes substituted with directory
+ * separators.
+ */
+ for (elm_idx = 1; elm_idx < nelm; elm_idx++) {
+ for (idx = 0; idx < elm_len[elm_idx]; idx++) {
+ if (elm[elm_idx][idx] == DIR_SEP) {
+ *curp = '/';
+ } else {
+ *curp = elm[elm_idx][idx];
+ }
+ curp++;
+ }
+ *curp = DIR_SEP;
+ curp++;
+ }
+ curp[-1] = 0; /* NULL terminate */
+
+ assert((curp - fname) <= (int)fname_len);
+
+ *str = fname;
+ if (size != NULL) {
+ *size = fname_len;
+ }
+
+ return NSERROR_OK;
+
+}
+
+
+/**
+ * Get the basename of a file using posix path handling.
+ *
+ * This gets the last element of a path and returns it. The returned
+ * element has all forward slashes translated into riscos directory
+ * separators.
+ *
+ * @param[in] path The path to extract the name from.
+ * @param[in,out] str Pointer to string pointer if this is NULL enough
+ * storage will be allocated for the path element.
+ * @param[in,out] size The size of the space available if \a
+ * str not NULL on input and set to the total
+ * output length on output.
+ * @return NSERROR_OK and the complete path is written to str
+ * or error code on faliure.
+ */
+static nserror riscos_basename(const char *path, char **str, size_t *size)
{
- char *leafname;
+ const char *leafname;
+ char *fname;
char *temp;
- int leaflen;
-
- temp = strrchr(path, '.');
- if (!temp)
- temp = path; /* already leafname */
- else
- temp += 1;
- leaflen = strlen(temp);
+ if (path == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
- leafname = malloc(leaflen + 1);
+ leafname = strrchr(path, DIR_SEP);
if (!leafname) {
- LOG(("malloc failed"));
- return NULL;
+ leafname = path;
+ } else {
+ leafname += 1;
+ }
+
+ fname = strdup(leafname);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
}
- memcpy(leafname, temp, leaflen + 1);
+ /** @todo check this leafname translation is actually required */
/* and s/\//\./g */
- for (temp = leafname; *temp; temp++)
- if (*temp == '/')
- *temp = '.';
+ for (temp = fname; *temp != 0; temp++) {
+ if (*temp == '/') {
+ *temp = DIR_SEP;
+ }
+ }
- return leafname;
+ *str = fname;
+ if (size != NULL) {
+ *size = strlen(fname);
+ }
+ return NSERROR_OK;
}
+
/**
- * Add a path component/filename to an existing path
+ * Ensure that all directory elements needed to store a filename exist.
+ *
+ * Given a path of x.y.z directories x and x.y will be created.
*
- * \param path buffer containing platform-native format path + free space
- * \param length length of buffer "path"
- * \param newpart string containing unix-format path component to add to path
- * \return true on success
+ * @param fname The filename to ensure the path to exists.
+ * @return NSERROR_OK on success or error code on failure.
*/
+static nserror riscos_mkdir_all(const char *fname)
+{
+ char *dname;
+ char *cur;
+
+ dname = strdup(fname);
-bool path_add_part(char *path, int length, const char *newpart)
+ cur = dname;
+ while ((cur = strchr(cur, '.'))) {
+ *cur = '\0';
+ xosfile_create_dir(dname, 0);
+ *cur++ = '.';
+ }
+
+ free(dname);
+
+ return NSERROR_OK;
+}
+
+/**
+ * Find screen size in OS units.
+ */
+void ro_gui_screen_size(int *width, int *height)
{
- size_t path_len = strlen(path);
+ *width = screen_info.width;
+ *height = screen_info.height;
+}
- /* Append directory separator, if there isn't one */
- if (path[path_len - 1] != '.') {
- strncat(path, ".", length);
- path_len += 1;
+
+/**
+ * Send the debug dump of a content to a text editor.
+ */
+void ro_gui_dump_browser_window(struct browser_window *bw)
+{
+ os_error *error;
+
+ /* open file for dump */
+ FILE *stream = fopen("<Wimp$ScrapDir>.WWW.NetSurf.dump", "w");
+ if (!stream) {
+ LOG(("fopen: errno %i", errno));
+ warn_user("SaveError", strerror(errno));
+ return;
}
- strncat(path, newpart, length);
+ browser_window_debug_dump(bw, stream, CONTENT_DEBUG_RENDER);
+
+ fclose(stream);
- /* Newpart is either a directory name, or a file leafname
- * Either way, we must replace all dots with forward slashes */
- for (path = path + path_len; *path; path++) {
- if (*path == '.')
- *path = '/';
+ /* launch file in editor */
+ error = xwimp_start_task("Filer_Run <Wimp$ScrapDir>.WWW.NetSurf.dump",
+ 0);
+ if (error) {
+ LOG(("xwimp_start_task failed: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
}
+}
- return true;
+
+static struct gui_file_table riscos_file_table = {
+ .mkpath = riscos_mkpath,
+ .basename = riscos_basename,
+ .nsurl_to_path = ro_nsurl_to_path,
+ .path_to_nsurl = ro_path_to_nsurl,
+ .mkdir_all = riscos_mkdir_all,
+};
+
+static struct gui_fetch_table riscos_fetch_table = {
+ .filetype = fetch_filetype,
+
+ .get_resource_url = gui_get_resource_url,
+ .mimetype = fetch_mimetype,
+};
+
+static struct gui_browser_table riscos_browser_table = {
+ .poll = riscos_poll,
+ .schedule = riscos_schedule,
+
+ .quit = gui_quit,
+ .launch_url = gui_launch_url,
+ .create_form_select_menu = gui_create_form_select_menu,
+ .cert_verify = gui_cert_verify,
+ .login = gui_401login_open,
+};
+
+
+static char *get_cachepath(void)
+{
+ char *cachedir;
+ char *cachepath = NULL;
+ nserror ret;
+
+ cachedir = getenv("Cache$Dir");
+ if ((cachedir == NULL) || (cachedir[0] == 0)) {
+ LOG(("cachedir was null"));
+ return NULL;
+ }
+ ret = netsurf_mkpath(&cachepath, NULL, 2, cachedir, "NetSurf");
+ if (ret != NSERROR_OK) {
+ return NULL;
+ }
+ return cachepath;
+}
+
+/**
+ * Normal entry point from RISC OS.
+ */
+int main(int argc, char** argv)
+{
+ char *cachepath;
+ char path[40];
+ int length;
+ os_var_type type;
+ int used = -1; /* slightly better with older OSLib versions */
+ os_error *error;
+ nserror ret;
+ struct netsurf_table riscos_table = {
+ .browser = &riscos_browser_table,
+ .window = riscos_window_table,
+ .clipboard = riscos_clipboard_table,
+ .download = riscos_download_table,
+ .fetch = &riscos_fetch_table,
+ .file = &riscos_file_table,
+ .utf8 = riscos_utf8_table,
+ .search = riscos_search_table,
+ .llcache = filesystem_llcache_table,
+ };
+
+ ret = netsurf_register(&riscos_table);
+ if (ret != NSERROR_OK) {
+ die("NetSurf operation table failed registration");
+ }
+
+ /* Consult NetSurf$Logging environment variable to decide if logging
+ * is required. */
+ error = xos_read_var_val_size("NetSurf$Logging", 0, os_VARTYPE_STRING,
+ &used, NULL, &type);
+ if (error != NULL || type != os_VARTYPE_STRING || used != -2) {
+ verbose_log = true;
+ } else {
+ char logging_env[2];
+ error = xos_read_var_val("NetSurf$Logging", logging_env,
+ sizeof(logging_env), 0, os_VARTYPE_STRING,
+ &used, NULL, &type);
+ if (error != NULL || logging_env[0] != '0') {
+ verbose_log = true;
+ } else {
+ verbose_log = false;
+ }
+ }
+
+ /* initialise logging. Not fatal if it fails but not much we
+ * can do about it either.
+ */
+ nslog_init(nslog_stream_configure, &argc, argv);
+
+ /* user options setup */
+ ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
+ if (ret != NSERROR_OK) {
+ die("Options failed to initialise");
+ }
+ nsoption_read("NetSurf:Choices", NULL);
+ nsoption_commandline(&argc, argv, NULL);
+
+ /* Choose the interface language to use */
+ ro_gui_choose_language();
+
+ /* select language-specific Messages */
+ if (((length = snprintf(path,
+ sizeof(path),
+ "NetSurf:Resources.%s.Messages",
+ nsoption_charp(language))) < 0) ||
+ (length >= (int)sizeof(path))) {
+ die("Failed to locate Messages resource.");
+ }
+
+ /* obtain cache path */
+ cachepath = get_cachepath();
+
+ /* common initialisation */
+ ret = netsurf_init(path, cachepath);
+ free(cachepath);
+ if (ret != NSERROR_OK) {
+ die("NetSurf failed to initialise core");
+ }
+
+ artworks_init();
+ draw_init();
+ sprite_init();
+
+ /* Load some extra RISC OS specific Messages */
+ messages_load("NetSurf:Resources.LangNames");
+
+ ret = gui_init(argc, argv);
+ if (ret != NSERROR_OK) {
+ warn_user(messages_get_errorcode(ret), 0);
+ }
+
+ netsurf_main_loop();
+
+ netsurf_exit();
+
+ return 0;
}