NetSurf
gui.c
Go to the documentation of this file.
1/*
2 * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
3 * Copyright 2004-2008 James Bursa <bursa@users.sourceforge.net>
4 * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
5 * Copyright 2005 Richard Wilson <info@tinct.net>
6 * Copyright 2004 Andrew Timmins <atimmins@blueyonder.co.uk>
7 * Copyright 2004-2009 John Tytgat <joty@netsurf-browser.org>
8 *
9 * This file is part of NetSurf, http://www.netsurf-browser.org/
10 *
11 * NetSurf is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * NetSurf is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#include <stdbool.h>
25#include <string.h>
26#include <assert.h>
27#include <errno.h>
28#include <signal.h>
29#include <unixlib/local.h>
30#include <fpu_control.h>
31#include <oslib/help.h>
32#include <oslib/uri.h>
33#include <oslib/inetsuite.h>
34#include <oslib/pdriver.h>
35#include <oslib/osfile.h>
36#include <oslib/hourglass.h>
37#include <oslib/osgbpb.h>
38#include <oslib/osbyte.h>
39#include <oslib/osmodule.h>
40#include <oslib/osfscontrol.h>
41
42#include "utils/utils.h"
43#include "utils/nsoption.h"
44#include "utils/log.h"
45#include "utils/messages.h"
46#include "utils/file.h"
47#include "utils/filename.h"
48#include "utils/url.h"
49#include "utils/corestrings.h"
50#include "netsurf/fetch.h"
51#include "netsurf/misc.h"
52#include "netsurf/content.h"
53#include "netsurf/netsurf.h"
55#include "netsurf/cookie_db.h"
56#include "netsurf/url_db.h"
58#include "desktop/hotlist.h"
60
61#include "riscos/gui.h"
62#include "riscos/bitmap.h"
63#include "riscos/wimputils.h"
64#include "riscos/hotlist.h"
65#include "riscos/buffer.h"
67#include "riscos/print.h"
68#include "riscos/save.h"
69#include "riscos/dialog.h"
70#include "riscos/wimp.h"
71#include "riscos/message.h"
72#include "riscos/help.h"
73#include "riscos/query.h"
74#include "riscos/window.h"
75#include "riscos/toolbar.h"
76#include "riscos/corewindow.h"
77#include "riscos/iconbar.h"
80#include "riscos/cookies.h"
81#include "riscos/pageinfo.h"
82#include "riscos/wimp_event.h"
83#include "riscos/uri.h"
84#include "riscos/url_protocol.h"
85#include "riscos/mouse.h"
86#include "riscos/ucstables.h"
87#include "riscos/filetype.h"
88#include "riscos/font.h"
92
93bool riscos_done = false;
94
95extern bool ro_plot_patterned_lines;
96
97int os_version = 0;
99
100const char * const __dynamic_da_name = "NetSurf"; /**< For UnixLib. */
101int __dynamic_da_max_size = 128 * 1024 * 1024; /**< For UnixLib. */
102int __feature_imagefs_is_file = 1; /**< For UnixLib. */
103/* default filename handling */
104int __riscosify_control = __RISCOSIFY_NO_SUFFIX |
105 __RISCOSIFY_NO_REVERSE_SUFFIX;
106#ifndef __ELF__
107extern int __dynamic_num;
108#endif
109
110const char * NETSURF_DIR;
111
112static const char *task_name = "NetSurf";
113#define CHOICES_PREFIX "<Choices$Write>.WWW.NetSurf."
114
116wimp_t task_handle; /**< RISC OS wimp task handle. */
117static clock_t gui_last_poll; /**< Time of last wimp_poll. */
118osspriteop_area *gui_sprites; /**< Sprite area containing pointer and hotlist sprites */
119
120#define DIR_SEP ('.')
121
122/**
123 * Accepted wimp user messages.
124 */
126 message_HELP_REQUEST,
127 {
128 message_DATA_SAVE,
129 message_DATA_SAVE_ACK,
130 message_DATA_LOAD,
131 message_DATA_LOAD_ACK,
132 message_DATA_OPEN,
133 message_PRE_QUIT,
134 message_SAVE_DESKTOP,
135 message_MENU_WARNING,
136 message_MENUS_DELETED,
137 message_WINDOW_INFO,
138 message_CLAIM_ENTITY,
139 message_DATA_REQUEST,
140 message_DRAGGING,
141 message_DRAG_CLAIM,
142 message_MODE_CHANGE,
143 message_PALETTE_CHANGE,
144 message_FONT_CHANGED,
145 message_URI_PROCESS,
146 message_URI_RETURN_RESULT,
147 message_INET_SUITE_OPEN_URL,
148 message_PRINT_SAVE,
149 message_PRINT_ERROR,
150 message_PRINT_TYPE_ODD,
153 0
154 }
155};
156
157
158static struct
159{
160 int width; /* in OS units */
163
164
165/**
166 * Callback to translate resource to full url for RISC OS.
167 *
168 * Transforms a resource: path into a full URL. The returned URL is
169 * used as the target for a redirect. The caller takes ownership of
170 * the returned nsurl including unrefing it when finished with it.
171 *
172 * \param path The path of the resource to locate.
173 * \return A string containing the full URL of the target object or
174 * NULL if no suitable resource can be found.
175 */
176static nsurl *gui_get_resource_url(const char *path)
177{
178 static const char base_url[] = "file:///NetSurf:/Resources/";
179 const char *lang;
180 size_t path_len, length;
181 char *raw;
182 nsurl *url = NULL;
183
184 /* Map paths first */
185 if (strcmp(path, "adblock.css") == 0) {
186 path = "AdBlock";
187
188 } else if (strcmp(path, "default.css") == 0) {
189 path = "CSS";
190
191 } else if (strcmp(path, "quirks.css") == 0) {
192 path = "Quirks";
193
194 } else if (strcmp(path, "favicon.ico") == 0) {
195 path = "Icons/content.png";
196
197 } else if (strcmp(path, "user.css") == 0) {
198 /* Special case; this file comes from Choices: */
199 nsurl_create("file:///Choices:WWW/NetSurf/User", &url);
200 return url;
201 }
202
203 path_len = strlen(path);
204
206
207 /* Find max URL length */
208 length = SLEN(base_url) +
209 strlen(lang) + 1 + /* <lang> + / */
210 path_len + 1; /* + NUL */
211
212 raw = malloc(length);
213 if (raw != NULL) {
214 /* Insert base URL */
215 char *ptr = memcpy(raw, base_url, SLEN(base_url));
216 ptr += SLEN(base_url);
217
218 /* Add language directory to URL, for translated files */
219 /* TODO: handle non-html translated files */
220 if (path_len > SLEN(".html") &&
221 strncmp(path + path_len - SLEN(".html"),
222 ".html", SLEN(".html")) == 0) {
223 ptr += sprintf(ptr, "%s/", lang);
224 }
225
226 /* Add filename to URL */
227 memcpy(ptr, path, path_len);
228 ptr += path_len;
229
230 /* Terminate string */
231 *ptr = '\0';
232
233 nsurl_create(raw, &url);
234 free(raw);
235 }
236
237 return url;
238}
239
240
241/**
242 * Set colour option from wimp.
243 *
244 * \param opts The netsurf options.
245 * \param wimp wimp colour value
246 * \param option the netsurf option enum.
247 * \param def_colour The default colour value to use.
248 * \return NSERROR_OK on success or error code.
249 */
250static nserror
252 wimp_colour wimp,
253 enum nsoption_e option,
254 colour def_colour)
255{
256 os_error *error;
257 os_PALETTE(20) palette;
258
259 error = xwimp_read_true_palette((os_palette *) &palette);
260 if (error != NULL) {
261 NSLOG(netsurf, INFO,
262 "xwimp_read_palette: 0x%x: %s",
263 error->errnum,
264 error->errmess);
265 } else {
266 /* entries are in B0G0R0LL */
267 def_colour = palette.entries[wimp] >> 8;
268 }
269
270 opts[option].value.c = def_colour;
271
272 return NSERROR_OK;
273}
274
275
276/**
277 * Set option defaults for riscos frontend
278 *
279 * @param defaults The option table to update.
280 * @return error status.
281 *
282 * @todo The wimp_COLOUR_... values here map the colour definitions to
283 * parts of the RISC OS desktop palette. In places this is fairly
284 * arbitrary, and could probably do with re-checking.
285 */
287{
288 /* Set defaults for absent option strings */
289 nsoption_setnull_charp(ca_bundle, strdup("<NetSurf$CABundle>"));
290 nsoption_setnull_charp(cookie_file, strdup("NetSurf:Cookies"));
291 nsoption_setnull_charp(cookie_jar, strdup(CHOICES_PREFIX "Cookies"));
292
293 if (nsoption_charp(ca_bundle) == NULL ||
294 nsoption_charp(cookie_file) == NULL ||
295 nsoption_charp(cookie_jar) == NULL) {
296 NSLOG(netsurf, INFO, "Failed initialising default options");
298 }
299
300 /* RISC OS platform does not generally benefit from disc cache
301 * so the default should be off.
302 */
303 nsoption_set_uint(disc_cache_size, 0);
304
305 /* Override core default treeview font size with 12 pt.
306 * TODO: 12 is the normal desktop font size, but users might run
307 * with something different.
308 */
309 nsoption_set_int(treeview_font_size, 12 * 10);
310
311 /* set default system colours for riscos ui */
312 set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_ActiveBorder, 0x00000000);
313 set_colour_from_wimp(defaults, wimp_COLOUR_CREAM, NSOPTION_sys_colour_ActiveCaption, 0x00dddddd);
314 set_colour_from_wimp(defaults, wimp_COLOUR_VERY_LIGHT_GREY, NSOPTION_sys_colour_AppWorkspace, 0x00eeeeee);
315 set_colour_from_wimp(defaults, wimp_COLOUR_VERY_LIGHT_GREY, NSOPTION_sys_colour_Background, 0x00aa0000);/* \TODO -- Check */
316 set_colour_from_wimp(defaults, wimp_COLOUR_VERY_LIGHT_GREY, NSOPTION_sys_colour_ButtonFace, 0x00aaaaaa);
317 set_colour_from_wimp(defaults, wimp_COLOUR_DARK_GREY, NSOPTION_sys_colour_ButtonHighlight, 0x00cccccc);/* \TODO -- Check */
318 set_colour_from_wimp(defaults, wimp_COLOUR_MID_DARK_GREY, NSOPTION_sys_colour_ButtonShadow, 0x00bbbbbb);
319 set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_ButtonText, 0x00000000);
320 set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_CaptionText, 0x00000000);
321 set_colour_from_wimp(defaults, wimp_COLOUR_MID_LIGHT_GREY, NSOPTION_sys_colour_GrayText, 0x00777777);/* \TODO -- Check */
322 set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_Highlight, 0x00ee0000);
323 set_colour_from_wimp(defaults, wimp_COLOUR_WHITE, NSOPTION_sys_colour_HighlightText, 0x00000000);
324 set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_InactiveBorder, 0x00000000);
325 set_colour_from_wimp(defaults, wimp_COLOUR_LIGHT_GREY, NSOPTION_sys_colour_InactiveCaption, 0x00ffffff);
326 set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_InactiveCaptionText, 0x00cccccc);
327 set_colour_from_wimp(defaults, wimp_COLOUR_CREAM, NSOPTION_sys_colour_InfoBackground, 0x00aaaaaa);
328 set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_InfoText, 0x00000000);
329 set_colour_from_wimp(defaults, wimp_COLOUR_WHITE, NSOPTION_sys_colour_Menu, 0x00aaaaaa);
330 set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_MenuText, 0x00000000);
331 set_colour_from_wimp(defaults, wimp_COLOUR_LIGHT_GREY, NSOPTION_sys_colour_Scrollbar, 0x00aaaaaa);/* \TODO -- Check */
332 set_colour_from_wimp(defaults, wimp_COLOUR_MID_DARK_GREY, NSOPTION_sys_colour_ThreeDDarkShadow, 0x00555555);
333 set_colour_from_wimp(defaults, wimp_COLOUR_VERY_LIGHT_GREY, NSOPTION_sys_colour_ThreeDFace, 0x00dddddd);
334 set_colour_from_wimp(defaults, wimp_COLOUR_WHITE, NSOPTION_sys_colour_ThreeDHighlight, 0x00aaaaaa);
335 set_colour_from_wimp(defaults, wimp_COLOUR_WHITE, NSOPTION_sys_colour_ThreeDLightShadow, 0x00999999);
336 set_colour_from_wimp(defaults, wimp_COLOUR_MID_DARK_GREY, NSOPTION_sys_colour_ThreeDShadow, 0x00777777);
337 set_colour_from_wimp(defaults, wimp_COLOUR_VERY_LIGHT_GREY, NSOPTION_sys_colour_Window, 0x00aaaaaa);
338 set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_WindowFrame, 0x00000000);
339 set_colour_from_wimp(defaults, wimp_COLOUR_BLACK, NSOPTION_sys_colour_WindowText, 0x00000000);
340
341 return NSERROR_OK;
342}
343
344
345
346
347/**
348 * Create intermediate directories for Choices and User Data files
349 */
350static void ro_gui_create_dirs(void)
351{
352 char buf[256];
353 char *path;
354
355 /* Choices */
356 path = getenv("NetSurf$ChoicesSave");
357 if (!path)
358 die("Failed to find NetSurf Choices save path");
359
360 snprintf(buf, sizeof(buf), "%s", path);
362
363 /* URL */
364 snprintf(buf, sizeof(buf), "%s", nsoption_charp(url_save));
366
367 /* Hotlist */
368 snprintf(buf, sizeof(buf), "%s", nsoption_charp(hotlist_save));
370
371 /* Recent */
372 snprintf(buf, sizeof(buf), "%s", nsoption_charp(recent_save));
374
375 /* Theme */
376 snprintf(buf, sizeof(buf), "%s", nsoption_charp(theme_save));
378 /* and the final directory part (as theme_save is a directory) */
379 xosfile_create_dir(buf, 0);
380}
381
382
383/**
384 * Ensures the gui exits cleanly.
385 */
386static void ro_gui_cleanup(void)
387{
389 xhourglass_off();
390 /* Uninstall NetSurf-specific fonts */
391 xos_cli("FontRemove NetSurf:Resources.Fonts.");
392}
393
394
395/**
396 * Handles a signal
397 */
398static void ro_gui_signal(int sig)
399{
400 static const os_error error = { 1, "NetSurf has detected a serious "
401 "error and must exit. Please submit a bug report, "
402 "attaching the browser log file." };
403 os_colour old_sand, old_glass;
404
406
407 xhourglass_on();
408 xhourglass_colours(0x0000ffff, 0x000000ff, &old_sand, &old_glass);
409 nsoption_dump(stderr, NULL);
410 /*rufl_dump_state();*/
411
412#ifndef __ELF__
413 /* save WimpSlot and DA to files if NetSurf$CoreDump exists */
414 int used;
415 xos_read_var_val_size("NetSurf$CoreDump", 0, 0, &used, 0, 0);
416 if (used) {
417 int curr_slot;
418 xwimp_slot_size(-1, -1, &curr_slot, 0, 0);
419 NSLOG(netsurf, INFO, "saving WimpSlot, size 0x%x", curr_slot);
420 xosfile_save("$.NetSurf_Slot", 0x8000, 0,
421 (byte *) 0x8000,
422 (byte *) 0x8000 + curr_slot);
423
424 if (__dynamic_num != -1) {
425 int size;
426 byte *base_address;
427 xosdynamicarea_read(__dynamic_num, &size,
428 &base_address, 0, 0, 0, 0, 0);
429 NSLOG(netsurf, INFO,
430 "saving DA %i, base %p, size 0x%x",
432 base_address,
433 size);
434 xosfile_save("$.NetSurf_DA",
435 (bits) base_address, 0,
436 base_address,
437 base_address + size);
438 }
439 }
440#else
441 /* Save WimpSlot and UnixLib managed DAs when UnixEnv$coredump
442 * defines a coredump directory. */
443 const _kernel_oserror *err = __unixlib_write_coredump (NULL);
444 if (err != NULL)
445 NSLOG(netsurf, INFO, "Coredump failed: %s", err->errmess);
446#endif
447
448 xhourglass_colours(old_sand, old_glass, 0, 0);
449 xhourglass_off();
450
451 __write_backtrace(sig);
452
453 xwimp_report_error_by_category(&error,
454 wimp_ERROR_BOX_GIVEN_CATEGORY |
455 wimp_ERROR_BOX_CATEGORY_ERROR <<
456 wimp_ERROR_BOX_CATEGORY_SHIFT,
457 "NetSurf", "!netsurf",
458 (osspriteop_area *) 1, "Quit", 0);
459 xos_cli("Filer_Run <Wimp$ScrapDir>.WWW.NetSurf.Log");
460
461 _Exit(sig);
462}
463
464
465/**
466 * Read a "line" from an Acorn URI file.
467 *
468 * \param fp file pointer to read from
469 * \param b buffer for line, size 400 bytes
470 * \return true on success, false on EOF
471 */
472static bool ro_gui_uri_file_parse_line(FILE *fp, char *b)
473{
474 int c;
475 unsigned int i = 0;
476
477 c = getc(fp);
478 if (c == EOF)
479 return false;
480
481 /* skip comment lines */
482 while (c == '#') {
483 do { c = getc(fp); } while (c != EOF && 32 <= c);
484 if (c == EOF)
485 return false;
486 do { c = getc(fp); } while (c != EOF && c < 32);
487 if (c == EOF)
488 return false;
489 }
490
491 /* read "line" */
492 do {
493 if (i == 399)
494 return false;
495 b[i++] = c;
496 c = getc(fp);
497 } while (c != EOF && 32 <= c);
498
499 /* skip line ending control characters */
500 while (c != EOF && c < 32)
501 c = getc(fp);
502
503 if (c != EOF)
504 ungetc(c, fp);
505
506 b[i] = 0;
507 return true;
508}
509
510
511/**
512 * Parse an Acorn URI file.
513 *
514 * \param file_name file to read
515 * \param uri_title pointer to receive title data, or NULL for no data
516 * \return URL from file, or 0 on error and error reported
517 */
518static char *ro_gui_uri_file_parse(const char *file_name, char **uri_title)
519{
520 /* See the "Acorn URI Handler Functional Specification" for the
521 * definition of the URI file format. */
522 char line[400];
523 char *url = NULL;
524 FILE *fp;
525
526 *uri_title = NULL;
527 fp = fopen(file_name, "rb");
528 if (!fp) {
529 NSLOG(netsurf, INFO, "fopen(\"%s\", \"rb\"): %i: %s",
530 file_name, errno, strerror(errno));
531 ro_warn_user("LoadError", strerror(errno));
532 return 0;
533 }
534
535 /* "URI" */
536 if (!ro_gui_uri_file_parse_line(fp, line) || strcmp(line, "URI") != 0)
537 goto uri_syntax_error;
538
539 /* version */
541 strspn(line, "0123456789") != strlen(line))
542 goto uri_syntax_error;
543
544 /* URI */
546 goto uri_syntax_error;
547
548 url = strdup(line);
549 if (!url) {
550 ro_warn_user("NoMemory", 0);
551 fclose(fp);
552 return 0;
553 }
554
555 /* title */
557 goto uri_free;
558 if (uri_title && line[0] && ((line[0] != '*') || line[1])) {
559 *uri_title = strdup(line);
560 if (!*uri_title) /* non-fatal */
561 ro_warn_user("NoMemory", 0);
562 }
563 fclose(fp);
564
565 return url;
566
567uri_free:
568 free(url);
569
570uri_syntax_error:
571 fclose(fp);
572 ro_warn_user("URIError", 0);
573 return 0;
574}
575
576
577/**
578 * Parse an ANT URL file.
579 *
580 * \param file_name file to read
581 * \return URL from file, or 0 on error and error reported
582 */
583static char *ro_gui_url_file_parse(const char *file_name)
584{
585 char line[400];
586 char *url;
587 FILE *fp;
588
589 fp = fopen(file_name, "r");
590 if (!fp) {
591 NSLOG(netsurf, INFO, "fopen(\"%s\", \"r\"): %i: %s",
592 file_name, errno, strerror(errno));
593 ro_warn_user("LoadError", strerror(errno));
594 return 0;
595 }
596
597 if (!fgets(line, sizeof line, fp)) {
598 if (ferror(fp)) {
599 NSLOG(netsurf, INFO, "fgets: %i: %s", errno,
600 strerror(errno));
601 ro_warn_user("LoadError", strerror(errno));
602 } else
603 ro_warn_user("LoadError", messages_get("EmptyError"));
604 fclose(fp);
605 return 0;
606 }
607
608 fclose(fp);
609
610 if (line[strlen(line) - 1] == '\n')
611 line[strlen(line) - 1] = '\0';
612
613 url = strdup(line);
614 if (!url) {
615 ro_warn_user("NoMemory", 0);
616 return 0;
617 }
618
619 return url;
620}
621
622
623/**
624 * Parse an IEURL file.
625 *
626 * \param file_name file to read
627 * \return URL from file, or 0 on error and error reported
628 */
629static char *ro_gui_ieurl_file_parse(const char *file_name)
630{
631 char line[400];
632 char *url = 0;
633 FILE *fp;
634
635 fp = fopen(file_name, "r");
636 if (!fp) {
637 NSLOG(netsurf, INFO, "fopen(\"%s\", \"r\"): %i: %s",
638 file_name, errno, strerror(errno));
639 ro_warn_user("LoadError", strerror(errno));
640 return 0;
641 }
642
643 while (fgets(line, sizeof line, fp)) {
644 if (strncmp(line, "URL=", 4) == 0) {
645 if (line[strlen(line) - 1] == '\n')
646 line[strlen(line) - 1] = '\0';
647 url = strdup(line + 4);
648 if (!url) {
649 fclose(fp);
650 ro_warn_user("NoMemory", 0);
651 return 0;
652 }
653 break;
654 }
655 }
656 if (ferror(fp)) {
657 NSLOG(netsurf, INFO, "fgets: %i: %s", errno, strerror(errno));
658 ro_warn_user("LoadError", strerror(errno));
659 fclose(fp);
660 return 0;
661 }
662
663 fclose(fp);
664
665 if (!url)
666 ro_warn_user("URIError", 0);
667
668 return url;
669}
670
671
672/**
673 * Handle Message_DataOpen (double-click on file in the Filer).
674 *
675 * \param message The wimp message to open.
676 */
677static void ro_msg_dataopen(wimp_message *message)
678{
679 int file_type = message->data.data_xfer.file_type;
680 char *url = 0;
681 os_error *oserror;
682 nsurl *urlns;
683 nserror error;
684 size_t len;
685
686 switch (file_type) {
687 case 0xb28: /* ANT URL file */
688 url = ro_gui_url_file_parse(message->data.data_xfer.file_name);
689 error = nsurl_create(url, &urlns);
690 free(url);
691 break;
692
693 case 0xfaf: /* HTML file */
694 error = netsurf_path_to_nsurl(message->data.data_xfer.file_name,
695 &urlns);
696 break;
697
698 case 0x1ba: /* IEURL file */
699 url = ro_gui_ieurl_file_parse(message->
700 data.data_xfer.file_name);
701 error = nsurl_create(url, &urlns);
702 free(url);
703 break;
704
705 case 0x2000: /* application */
706 len = strlen(message->data.data_xfer.file_name);
707 if (len < 9 || strcmp(".!NetSurf",
708 message->data.data_xfer.file_name + len - 9))
709 return;
710
711 if (nsoption_charp(homepage_url) &&
712 nsoption_charp(homepage_url)[0]) {
713 error = nsurl_create(nsoption_charp(homepage_url),
714 &urlns);
715 } else {
716 error = nsurl_create(NETSURF_HOMEPAGE, &urlns);
717 }
718 break;
719
720 default:
721 return;
722 }
723
724 /* send DataLoadAck */
725 message->action = message_DATA_LOAD_ACK;
726 message->your_ref = message->my_ref;
727 oserror = xwimp_send_message(wimp_USER_MESSAGE, message, message->sender);
728 if (oserror) {
729 NSLOG(netsurf, INFO, "xwimp_send_message: 0x%x: %s",
730 oserror->errnum, oserror->errmess);
731 ro_warn_user("WimpError", oserror->errmess);
732 return;
733 }
734
735 if (error != NSERROR_OK) {
737 return;
738 }
739
740 /* create a new window with the file */
742 urlns,
743 NULL,
744 NULL,
745 NULL);
746 nsurl_unref(urlns);
747 if (error != NSERROR_OK) {
749 }
750}
751
752
753/**
754 * Handle Message_DataLoad (file dragged in).
755 */
756static void ro_msg_dataload(wimp_message *message)
757{
758 int file_type = message->data.data_xfer.file_type;
759 char *urltxt = NULL;
760 char *title = NULL;
761 struct gui_window *g;
762 os_error *oserror;
763 nsurl *url;
764 nserror error;
765
766 g = ro_gui_window_lookup(message->data.data_xfer.w);
767 if (g) {
768 if (ro_gui_window_dataload(g, message))
769 return;
770 }
771 else {
772 g = ro_gui_toolbar_lookup(message->data.data_xfer.w);
773 if (g && ro_gui_toolbar_dataload(g, message))
774 return;
775 }
776
777 switch (file_type) {
779 urltxt = ro_gui_uri_file_parse(message->data.data_xfer.file_name,
780 &title);
781 error = nsurl_create(urltxt, &url);
782 free(urltxt);
783 break;
784
785 case FILETYPE_ANT_URL:
786 urltxt = ro_gui_url_file_parse(message->data.data_xfer.file_name);
787 error = nsurl_create(urltxt, &url);
788 free(urltxt);
789 break;
790
791 case FILETYPE_IEURL:
792 urltxt = ro_gui_ieurl_file_parse(message->data.data_xfer.file_name);
793 error = nsurl_create(urltxt, &url);
794 free(urltxt);
795 break;
796
797 case FILETYPE_HTML:
798 case FILETYPE_JNG:
799 case FILETYPE_CSS:
800 case FILETYPE_MNG:
801 case FILETYPE_GIF:
802 case FILETYPE_BMP:
803 case FILETYPE_ICO:
804 case osfile_TYPE_DRAW:
805 case FILETYPE_PNG:
806 case FILETYPE_JPEG:
807 case osfile_TYPE_SPRITE:
808 case osfile_TYPE_TEXT:
810 case FILETYPE_SVG:
811 case FILETYPE_WEBP:
812 /* display the actual file */
813 error = netsurf_path_to_nsurl(message->data.data_xfer.file_name, &url);
814 break;
815
816 default:
817 return;
818 }
819
820 /* report error to user */
821 if (error != NSERROR_OK) {
823 return;
824 }
825
826
827 if (g) {
828 error = browser_window_navigate(g->bw,
829 url,
830 NULL,
832 NULL,
833 NULL,
834 NULL);
835 } else {
837 url,
838 NULL,
839 NULL,
840 NULL);
841 }
843 if (error != NSERROR_OK) {
845 }
846
847
848 /* send DataLoadAck */
849 message->action = message_DATA_LOAD_ACK;
850 message->your_ref = message->my_ref;
851 oserror = xwimp_send_message(wimp_USER_MESSAGE, message,
852 message->sender);
853 if (oserror) {
854 NSLOG(netsurf, INFO, "xwimp_send_message: 0x%x: %s",
855 oserror->errnum, oserror->errmess);
856 ro_warn_user("WimpError", oserror->errmess);
857 return;
858 }
859
860}
861
862
863/**
864 * Ensure that the filename in a data transfer message is NULL terminated
865 * (some applications, especially BASIC programs use CR)
866 *
867 * \param message message to be corrected
868 */
869static void ro_msg_terminate_filename(wimp_full_message_data_xfer *message)
870{
871 const char *ep = (char*)message + message->size;
872 char *p = message->file_name;
873
874 if ((size_t)message->size >= sizeof(*message))
875 ep = (char*)message + sizeof(*message) - 1;
876
877 while (p < ep && *p >= ' ') p++;
878 *p = '\0';
879}
880
881
882/**
883 * Handle Message_DataSave
884 */
885static void ro_msg_datasave(wimp_message *message)
886{
887 wimp_full_message_data_xfer *dataxfer = (wimp_full_message_data_xfer*)message;
888
889 /* remove ghost caret if drag-and-drop protocol was used */
890// ro_gui_selection_drag_reset();
891
893
895 return;
896
897 switch (dataxfer->file_type) {
899 case FILETYPE_ANT_URL:
900 case FILETYPE_IEURL:
901 case FILETYPE_HTML:
902 case FILETYPE_JNG:
903 case FILETYPE_CSS:
904 case FILETYPE_MNG:
905 case FILETYPE_GIF:
906 case FILETYPE_BMP:
907 case FILETYPE_ICO:
908 case osfile_TYPE_DRAW:
909 case FILETYPE_PNG:
910 case FILETYPE_JPEG:
911 case osfile_TYPE_SPRITE:
912 case osfile_TYPE_TEXT:
914 case FILETYPE_SVG:
915 case FILETYPE_WEBP: {
916 os_error *error;
917
918 dataxfer->your_ref = dataxfer->my_ref;
919 dataxfer->size = offsetof(wimp_full_message_data_xfer, file_name) + 16;
920 dataxfer->action = message_DATA_SAVE_ACK;
921 dataxfer->est_size = -1;
922 memcpy(dataxfer->file_name, "<Wimp$Scrap>", 13);
923
924 error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message*)dataxfer, message->sender);
925 if (error) {
926 NSLOG(netsurf, INFO,
927 "xwimp_send_message: 0x%x: %s",
928 error->errnum,
929 error->errmess);
930 ro_warn_user("WimpError", error->errmess);
931 }
932 }
933 break;
934 }
935}
936
937
938/**
939 * Handle Message_DataSaveAck.
940 */
941static void ro_msg_datasave_ack(wimp_message *message)
942{
943 ro_msg_terminate_filename((wimp_full_message_data_xfer*)message);
944
945 if (ro_print_ack(message))
946 return;
947
948 switch (gui_current_drag_type) {
951 break;
952
953 case GUI_DRAG_SAVE:
956 break;
957
958 default:
959 break;
960 }
961
963}
964
965
966/**
967 * Handle PreQuit message
968 *
969 * \param message PreQuit message from Wimp
970 */
971static void ro_msg_prequit(wimp_message *message)
972{
973 if (!ro_gui_prequit()) {
974 os_error *error;
975
976 /* we're objecting to the close down */
977 message->your_ref = message->my_ref;
978 error = xwimp_send_message(wimp_USER_MESSAGE_ACKNOWLEDGE,
979 message, message->sender);
980 if (error) {
981 NSLOG(netsurf, INFO, "xwimp_send_message: 0x%x:%s",
982 error->errnum, error->errmess);
983 ro_warn_user("WimpError", error->errmess);
984 }
985 }
986}
987
988
989/**
990 * Handle SaveDesktop message.
991 *
992 * \param message SaveDesktop message from Wimp.
993 */
994static void ro_msg_save_desktop(wimp_message *message)
995{
996 os_error *error;
997
998 error = xosgbpb_writew(message->data.save_desktopw.file,
999 (const byte*)"Run ", 4, NULL);
1000 if (!error) {
1001 error = xosgbpb_writew(message->data.save_desktopw.file,
1002 (const byte*)NETSURF_DIR, strlen(NETSURF_DIR), NULL);
1003 if (!error)
1004 error = xos_bputw('\n', message->data.save_desktopw.file);
1005 }
1006
1007 if (error) {
1008 NSLOG(netsurf, INFO, "xosgbpb_writew/xos_bputw: 0x%x:%s",
1009 error->errnum, error->errmess);
1010 ro_warn_user("SaveError", error->errmess);
1011
1012 /* we must cancel the save by acknowledging the message */
1013 message->your_ref = message->my_ref;
1014 error = xwimp_send_message(wimp_USER_MESSAGE_ACKNOWLEDGE,
1015 message, message->sender);
1016 if (error) {
1017 NSLOG(netsurf, INFO, "xwimp_send_message: 0x%x:%s",
1018 error->errnum, error->errmess);
1019 ro_warn_user("WimpError", error->errmess);
1020 }
1021 }
1022}
1023
1024
1025/**
1026 * Handle WindowInfo message (part of the iconising protocol)
1027 *
1028 * \param message WindowInfo message from the Iconiser
1029 */
1030static void ro_msg_window_info(wimp_message *message)
1031{
1032 wimp_full_message_window_info *wi;
1033 struct gui_window *g;
1034
1035 /* allow the user to turn off thumbnail icons */
1036 if (!nsoption_bool(thumbnail_iconise))
1037 return;
1038
1039 wi = (wimp_full_message_window_info*)message;
1040 g = ro_gui_window_lookup(wi->w);
1041
1042 /* ic_<task name> will suffice for our other windows */
1043 if (g) {
1044 ro_gui_window_iconise(g, wi);
1046 }
1047}
1048
1049
1050/**
1051 * Get screen properties following a mode change.
1052 */
1054{
1055 static const ns_os_vdu_var_list vars = {
1056 os_MODEVAR_XWIND_LIMIT,
1057 {
1058 os_MODEVAR_YWIND_LIMIT,
1059 os_MODEVAR_XEIG_FACTOR,
1060 os_MODEVAR_YEIG_FACTOR,
1061 os_VDUVAR_END_LIST
1062 }
1063 };
1064 os_error *error;
1065 int vals[4];
1066
1067 error = xos_read_vdu_variables(PTR_OS_VDU_VAR_LIST(&vars), vals);
1068 if (error) {
1069 NSLOG(netsurf, INFO, "xos_read_vdu_variables: 0x%x: %s",
1070 error->errnum, error->errmess);
1071 ro_warn_user("MiscError", error->errmess);
1072 return;
1073 }
1074 screen_info.width = (vals[0] + 1) << vals[2];
1075 screen_info.height = (vals[1] + 1) << vals[3];
1076}
1077
1078
1079/**
1080 * Warn the user if Inet$Resolvers is not set.
1081 */
1082static void ro_gui_check_resolvers(void)
1083{
1084 char *resolvers;
1085 resolvers = getenv("Inet$Resolvers");
1086 if (resolvers && resolvers[0]) {
1087 NSLOG(netsurf, INFO, "Inet$Resolvers '%s'", resolvers);
1088 } else {
1089 NSLOG(netsurf, INFO, "Inet$Resolvers not set or empty");
1090 ro_warn_user("Resolvers", 0);
1091 }
1092}
1093
1094/**
1095 * Determine whether the OS version supports alpha channels.
1096 *
1097 * \return true iff alpha channels are supported, false otherwise.
1098 */
1100{
1101 os_error *error;
1102 int var_val;
1103 bits psr;
1104
1105 psr = 0;
1106 error = xos_read_mode_variable(alpha_SPRITE_MODE,
1107 os_MODEVAR_MODE_FLAGS, &var_val, &psr);
1108 if (error) {
1109 NSLOG(netsurf, ERROR, "xos_read_mode_variable: 0x%x: %s",
1110 error->errnum, error->errmess);
1111 return false;
1112 }
1113
1114 return (var_val == (1 << 15));
1115}
1116
1117/**
1118 * Initialise the RISC OS specific GUI.
1119 *
1120 * \param argc The number of command line arguments.
1121 * \param argv The string vector of command line arguments.
1122 */
1123static nserror gui_init(int argc, char** argv)
1124{
1125 struct {
1126 void (*sigabrt)(int);
1127 void (*sigfpe)(int);
1128 void (*sigill)(int);
1129 void (*sigint)(int);
1130 void (*sigsegv)(int);
1131 void (*sigterm)(int);
1132 void (*sigoserror)(int);
1133 } prev_sigs;
1134 char path[40];
1135 os_error *error;
1136 int length;
1137 char *nsdir_temp;
1138 byte *base;
1139 nsurl *url;
1140 nserror ret;
1141 bool open_window;
1142
1143 /* re-enable all FPU exceptions/traps except inexact operations,
1144 * which we're not interested in, and underflow which is incorrectly
1145 * raised when converting an exact value of 0 from double-precision
1146 * to single-precision on FPEmulator v4.09-4.11 (MVFD F0,#0:MVFS F0,F0)
1147 * - UnixLib disables all FP exceptions by default */
1148
1149 _FPU_SETCW(_FPU_IEEE & ~(_FPU_MASK_PM | _FPU_MASK_UM));
1150
1151 xhourglass_start(1);
1152
1153 /* read OS version for code that adapts to conform to the OS
1154 * (remember that it's preferable to check for specific features
1155 * being present) */
1156 xos_byte(osbyte_IN_KEY, 0, 0xff, &os_version, NULL);
1157
1159 NSLOG(netsurf, INFO, "OS supports alpha sprites: %s",
1160 os_alpha_sprite_supported ? "yes" : "no");
1161
1162 /* the first release version of the A9home OS is incapable of
1163 plotting patterned lines (presumably a fault in the hw acceleration) */
1164 if (!xosmodule_lookup("VideoHWSMI", NULL, NULL, &base, NULL, NULL)) {
1165#if 0 // this fault still hasn't been fixed, so disable patterned lines for all versions until it has
1166 const char *help = (char*)base + ((int*)base)[5];
1167 while (*help > 9) help++;
1168 while (*help == 9) help++;
1169 if (!memcmp(help, "0.55", 4))
1170#endif
1172 }
1173
1174 /* Create our choices directories */
1176
1177 /* Register exit and signal handlers */
1178 atexit(ro_gui_cleanup);
1179 prev_sigs.sigabrt = signal(SIGABRT, ro_gui_signal);
1180 prev_sigs.sigfpe = signal(SIGFPE, ro_gui_signal);
1181 prev_sigs.sigill = signal(SIGILL, ro_gui_signal);
1182 prev_sigs.sigint = signal(SIGINT, ro_gui_signal);
1183 prev_sigs.sigsegv = signal(SIGSEGV, ro_gui_signal);
1184 prev_sigs.sigterm = signal(SIGTERM, ro_gui_signal);
1185 prev_sigs.sigoserror = signal(SIGOSERROR, ro_gui_signal);
1186
1187 if (prev_sigs.sigabrt == SIG_ERR || prev_sigs.sigfpe == SIG_ERR ||
1188 prev_sigs.sigill == SIG_ERR ||
1189 prev_sigs.sigint == SIG_ERR ||
1190 prev_sigs.sigsegv == SIG_ERR ||
1191 prev_sigs.sigterm == SIG_ERR ||
1192 prev_sigs.sigoserror == SIG_ERR)
1193 die("Failed registering signal handlers");
1194
1195 /* Load in UI sprites */
1196 gui_sprites = ro_gui_load_sprite_file("NetSurf:Resources.Sprites");
1197 if (!gui_sprites)
1198 die("Unable to load Sprites.");
1199
1200 /* Find NetSurf directory */
1201 nsdir_temp = getenv("NetSurf$Dir");
1202 if (!nsdir_temp)
1203 die("Failed to locate NetSurf directory");
1204 NETSURF_DIR = strdup(nsdir_temp);
1205 if (!NETSURF_DIR)
1206 die("Failed duplicating NetSurf directory string");
1207
1208 /* Initialise filename allocator */
1210
1211 /* Initialise save complete functionality */
1213
1214 /* Load in visited URLs and Cookies */
1215 urldb_load(nsoption_charp(url_path));
1216 urldb_load_cookies(nsoption_charp(cookie_file));
1217
1218 /* Initialise with the wimp */
1219 error = xwimp_initialise(wimp_VERSION_RO38, task_name,
1221 &task_handle);
1222 if (error) {
1223 NSLOG(netsurf, INFO, "xwimp_initialise: 0x%x: %s",
1224 error->errnum, error->errmess);
1225 die(error->errmess);
1226 }
1227 /* Register message handlers */
1228 ro_message_register_route(message_HELP_REQUEST,
1230 ro_message_register_route(message_DATA_OPEN,
1232 ro_message_register_route(message_DATA_SAVE,
1234 ro_message_register_route(message_DATA_SAVE_ACK,
1236 ro_message_register_route(message_PRE_QUIT,
1238 ro_message_register_route(message_SAVE_DESKTOP,
1240 ro_message_register_route(message_DRAGGING,
1242 ro_message_register_route(message_DRAG_CLAIM,
1244 ro_message_register_route(message_WINDOW_INFO,
1246
1247 /* Initialise the font subsystem (must be after Wimp_Initialise) */
1248 nsfont_init();
1249
1250 /* Initialise the hotlist (must be after fonts) */
1251 hotlist_init(nsoption_charp(hotlist_path),
1252 nsoption_bool(external_hotlists) ?
1253 NULL :
1255
1256 /* Initialise global information */
1259
1260 /* Issue a *Desktop to poke AcornURI into life */
1261 if (getenv("NetSurf$Start_URI_Handler"))
1262 xwimp_start_task("Desktop", 0);
1263
1264 /* Open the templates */
1265 if ((length = snprintf(path, sizeof(path),
1266 "NetSurf:Resources.%s.Templates",
1267 nsoption_charp(language))) < 0 || length >= (int)sizeof(path))
1268 die("Failed to locate Templates resource.");
1269 error = xwimp_open_template(path);
1270 if (error) {
1271 NSLOG(netsurf, INFO, "xwimp_open_template failed: 0x%x: %s",
1272 error->errnum, error->errmess);
1273 die(error->errmess);
1274 }
1275
1276 /* Initialise themes before dialogs */
1278
1279 /* Initialise dialog windows (must be after UI sprites are loaded) */
1281
1282 /* Initialise download window */
1284
1285 /* Initialise menus */
1287
1288 /* Initialise query windows */
1290
1291 /* Initialise toolbars */
1293
1294 /* Initialise url bar module */
1296
1297 /* Initialise browser windows */
1299
1300 /* Done with the templates file */
1301 wimp_close_template();
1302
1303 /* Create Iconbar icon and menus */
1305
1306 /* Finally, check Inet$Resolvers for sanity */
1308
1309 open_window = nsoption_bool(open_browser_at_startup);
1310
1311 /* parse command-line arguments */
1312 if (argc == 2) {
1313 NSLOG(netsurf, INFO, "parameters: '%s'", argv[1]);
1314 /* this is needed for launching URI files */
1315 if (strcasecmp(argv[1], "-nowin") == 0) {
1316 return NSERROR_OK;
1317 }
1318 ret = nsurl_create(NETSURF_HOMEPAGE, &url);
1319 }
1320 else if (argc == 3) {
1321 NSLOG(netsurf, INFO, "parameters: '%s' '%s'", argv[1],
1322 argv[2]);
1323 open_window = true;
1324
1325 /* HTML files */
1326 if (strcasecmp(argv[1], "-html") == 0) {
1327 ret = netsurf_path_to_nsurl(argv[2], &url);
1328 }
1329 /* URL files */
1330 else if (strcasecmp(argv[1], "-urlf") == 0) {
1331 char *urlf = ro_gui_url_file_parse(argv[2]);
1332 if (!urlf) {
1333 NSLOG(netsurf, INFO, "allocation failed");
1334 die("Insufficient memory for URL");
1335 }
1336 ret = nsurl_create(urlf, &url);
1337 free(urlf);
1338 }
1339 /* ANT URL Load */
1340 else if (strcasecmp(argv[1], "-url") == 0) {
1341 ret = nsurl_create(argv[2], &url);
1342 }
1343 /* Unknown => exit here. */
1344 else {
1345 NSLOG(netsurf, INFO, "Unknown parameters: '%s' '%s'",
1346 argv[1], argv[2]);
1347 return NSERROR_BAD_PARAMETER;
1348 }
1349 }
1350 /* get user's homepage (if configured) */
1351 else if (nsoption_charp(homepage_url) &&
1352 nsoption_charp(homepage_url)[0]) {
1353 ret = nsurl_create(nsoption_charp(homepage_url), &url);
1354 }
1355 /* default homepage */
1356 else {
1357 ret = nsurl_create(NETSURF_HOMEPAGE, &url);
1358 }
1359
1360 /* check for url creation error */
1361 if (ret != NSERROR_OK) {
1362 return ret;
1363 }
1364
1365 if (open_window) {
1367 url,
1368 NULL,
1369 NULL,
1370 NULL);
1371 }
1372 nsurl_unref(url);
1373
1374 return ret;
1375}
1376
1377
1378/**
1379 * Determine the default language to use.
1380 *
1381 * RISC OS has no standard way of determining which language the user prefers.
1382 * We have to guess from the 'Country' setting.
1383 */
1385{
1386 char path[40];
1387 const char *lang;
1388 int country;
1389 os_error *error;
1390
1391 /* choose a language from the configured country number */
1392 error = xosbyte_read(osbyte_VAR_COUNTRY_NUMBER, &country);
1393 if (error) {
1394 NSLOG(netsurf, INFO, "xosbyte_read failed: 0x%x: %s",
1395 error->errnum, error->errmess);
1396 country = 1;
1397 }
1398 switch (country) {
1399 case 7: /* Germany */
1400 case 30: /* Austria */
1401 case 35: /* Switzerland (70% German-speaking) */
1402 lang = "de";
1403 break;
1404 case 6: /* France */
1405 case 18: /* Canada2 (French Canada?) */
1406 lang = "fr";
1407 break;
1408 case 34: /* Netherlands */
1409 lang = "nl";
1410 break;
1411 default:
1412 lang = "en";
1413 break;
1414 }
1415 sprintf(path, "NetSurf:Resources.%s", lang);
1416 if (is_dir(path))
1417 return lang;
1418 return "en";
1419}
1420
1421
1422/**
1423 * Create a nsurl from a RISC OS pathname.
1424 *
1425 * Perform the necessary operations on a path to generate a nsurl.
1426 *
1427 * @param[in] path The RISC OS pathname to convert.
1428 * @param[out] url_out pointer to recive the nsurl, The returned url must be
1429 * unreferenced by the caller.
1430 * @return NSERROR_OK and the url is placed in \a url or error code on faliure.
1431 */
1432static nserror ro_path_to_nsurl(const char *path, struct nsurl **url_out)
1433{
1434 int spare;
1435 char *canonical_path; /* canonicalised RISC OS path */
1436 char *unix_path; /* unix path */
1437 char *escaped_path;
1438 os_error *error;
1439 nserror ret;
1440 int urllen;
1441 char *url; /* resulting url */
1442
1443 /* calculate the canonical risc os path */
1444 error = xosfscontrol_canonicalise_path(path, 0, 0, 0, 0, &spare);
1445 if (error) {
1446 NSLOG(netsurf, INFO,
1447 "xosfscontrol_canonicalise_path failed: 0x%x: %s",
1448 error->errnum,
1449 error->errmess);
1450 ro_warn_user("PathToURL", error->errmess);
1451 return NSERROR_NOT_FOUND;
1452 }
1453
1454 canonical_path = malloc(1 - spare);
1455 if (canonical_path == NULL) {
1456 free(canonical_path);
1457 return NSERROR_NOMEM;
1458 }
1459
1460 error = xosfscontrol_canonicalise_path(path, canonical_path, 0, 0, 1 - spare, 0);
1461 if (error) {
1462 NSLOG(netsurf, INFO,
1463 "xosfscontrol_canonicalise_path failed: 0x%x: %s",
1464 error->errnum,
1465 error->errmess);
1466 ro_warn_user("PathToURL", error->errmess);
1467 free(canonical_path);
1468 return NSERROR_NOT_FOUND;
1469 }
1470
1471 /* create a unix path from the cananocal risc os one */
1472 unix_path = __unixify(canonical_path, __RISCOSIFY_NO_REVERSE_SUFFIX, NULL, 0, 0);
1473
1474 if (unix_path == NULL) {
1475 NSLOG(netsurf, INFO, "__unixify failed: %s", canonical_path);
1476 free(canonical_path);
1477 return NSERROR_BAD_PARAMETER;
1478 }
1479 free(canonical_path);
1480
1481 /* url escape the unix path */
1482 ret = url_escape(unix_path, false, "/", &escaped_path);
1483 if (ret != NSERROR_OK) {
1484 free(unix_path);
1485 return ret;
1486 }
1487 free(unix_path);
1488
1489 /* convert the escaped unix path into a url */
1490 urllen = strlen(escaped_path) + FILE_SCHEME_PREFIX_LEN + 1;
1491 url = malloc(urllen);
1492 if (url == NULL) {
1493 NSLOG(netsurf, INFO, "Unable to allocate url");
1494 free(escaped_path);
1495 return NSERROR_NOMEM;
1496 }
1497
1498 if (*escaped_path == '/') {
1499 snprintf(url, urllen, "%s%s",
1500 FILE_SCHEME_PREFIX, escaped_path + 1);
1501 } else {
1502 snprintf(url, urllen, "%s%s",
1503 FILE_SCHEME_PREFIX, escaped_path);
1504 }
1505 free(escaped_path);
1506
1507 ret = nsurl_create(url, url_out);
1508 free(url);
1509
1510 return ret;
1511}
1512
1513
1514/**
1515 * Create a path from a nsurl using posix file handling.
1516 *
1517 * @param[in] url The url to encode.
1518 * @param[out] path_out A string containing the result path which should
1519 * be freed by the caller.
1520 * @return NSERROR_OK and the path is written to \a path or error code
1521 * on faliure.
1522 */
1523static nserror ro_nsurl_to_path(struct nsurl *url, char **path_out)
1524{
1525 lwc_string *urlpath;
1526 size_t unpath_len;
1527 char *unpath;
1528 char *path;
1529 bool match;
1530 lwc_string *scheme;
1531 nserror res;
1532 char *r;
1533
1534 if ((url == NULL) || (path_out == NULL)) {
1535 return NSERROR_BAD_PARAMETER;
1536 }
1537
1538 scheme = nsurl_get_component(url, NSURL_SCHEME);
1539
1540 if (lwc_string_caseless_isequal(scheme, corestring_lwc_file,
1541 &match) != lwc_error_ok)
1542 {
1543 return NSERROR_BAD_PARAMETER;
1544 }
1545 lwc_string_unref(scheme);
1546 if (match == false) {
1547 return NSERROR_BAD_PARAMETER;
1548 }
1549
1550 urlpath = nsurl_get_component(url, NSURL_PATH);
1551 if (urlpath == NULL) {
1552 return NSERROR_BAD_PARAMETER;
1553 }
1554
1555 res = url_unescape(lwc_string_data(urlpath),
1556 lwc_string_length(urlpath),
1557 &unpath_len,
1558 &unpath);
1559 lwc_string_unref(urlpath);
1560 if (res != NSERROR_OK) {
1561 return res;
1562 }
1563
1564 /* RISC OS path should not be more than 100 characters longer */
1565 path = malloc(unpath_len + 100);
1566 if (path == NULL) {
1567 free(unpath);
1568 return NSERROR_NOMEM;
1569 }
1570
1571 r = __riscosify(unpath, 0, __RISCOSIFY_NO_SUFFIX,
1572 path, unpath_len + 100, 0);
1573 free(unpath);
1574 if (r == NULL) {
1575 free(path);
1576 return NSERROR_NOMEM;
1577 }
1578
1579 *path_out = path;
1580
1581 return NSERROR_OK;
1582}
1583
1584
1585/**
1586 * Ensures output logging stream is correctly configured.
1587 */
1588static bool nslog_stream_configure(FILE *fptr)
1589{
1590 /* set log stream to be non-buffering */
1591 setbuf(fptr, NULL);
1592
1593 return true;
1594}
1595
1596
1597/**
1598 * Close down the gui (RISC OS).
1599 */
1600static void gui_quit(void)
1601{
1603 urldb_save(nsoption_charp(url_save));
1612 rufl_quit();
1613 free(gui_sprites);
1614 xwimp_close_down(task_handle);
1615 xhourglass_off();
1616}
1617
1618
1619/**
1620 * Handle Close_Window_Request events.
1621 */
1622static void ro_gui_close_window_request(wimp_close *close)
1623{
1624 if (ro_gui_alt_pressed())
1626 else {
1627 if (ro_gui_wimp_event_close_window(close->w))
1628 return;
1629 ro_gui_dialog_close(close->w);
1630 }
1631}
1632
1633
1634/**
1635 * Handle key press paste callback.
1636 */
1637static void ro_gui_keypress_cb(void *pw)
1638{
1639 wimp_key *key = (wimp_key *) pw;
1640
1641 if (ro_gui_wimp_event_keypress(key) == false) {
1642 os_error *error = xwimp_process_key(key->c);
1643 if (error) {
1644 NSLOG(netsurf, INFO, "xwimp_process_key: 0x%x: %s",
1645 error->errnum, error->errmess);
1646 ro_warn_user("WimpError", error->errmess);
1647 }
1648 }
1649
1650 free(key);
1651}
1652
1653
1654/**
1655 * Handle gui keypress.
1656 */
1657static void ro_gui_keypress(wimp_key *key)
1658{
1659 if (key->c == wimp_KEY_ESCAPE &&
1662
1663 /* Allow Escape key to be used for cancelling a drag
1664 * save (easier than finding somewhere safe to abort
1665 * the drag)
1666 */
1669 } else if (key->c == 22 /* Ctrl-V */) {
1670 wimp_key *copy;
1671
1672 /* Must copy the keypress as it's on the stack */
1673 copy = malloc(sizeof(wimp_key));
1674 if (copy == NULL)
1675 return;
1676 memcpy(copy, key, sizeof(wimp_key));
1677
1679 } else if (ro_gui_wimp_event_keypress(key) == false) {
1680 os_error *error = xwimp_process_key(key->c);
1681 if (error) {
1682 NSLOG(netsurf, INFO, "xwimp_process_key: 0x%x: %s",
1683 error->errnum, error->errmess);
1684 ro_warn_user("WimpError", error->errmess);
1685 }
1686 }
1687}
1688
1689
1690/**
1691 * Handle the three User_Message events.
1692 */
1693static void ro_gui_user_message(wimp_event_no event, wimp_message *message)
1694{
1695 /* attempt automatic routing */
1696 if (ro_message_handle_message(event, message))
1697 return;
1698
1699 switch (message->action) {
1700 case message_DATA_LOAD:
1701 ro_msg_terminate_filename((wimp_full_message_data_xfer*)message);
1702
1703 if (event == wimp_USER_MESSAGE_ACKNOWLEDGE) {
1705 ro_print_dataload_bounce(message);
1707 (wimp_full_message_data_xfer *) message) == false) {
1708 ro_msg_dataload(message);
1709 }
1710 break;
1711
1712 case message_DATA_LOAD_ACK:
1715 break;
1716
1717 case message_MENU_WARNING:
1718 ro_gui_menu_warning((wimp_message_menu_warning *)
1719 &message->data);
1720 break;
1721
1722 case message_MENUS_DELETED:
1723 ro_gui_menu_message_deleted((wimp_message_menus_deleted *)
1724 &message->data);
1725 break;
1726
1727 case message_CLAIM_ENTITY:
1728 ro_gui_selection_claim_entity((wimp_full_message_claim_entity*)message);
1729 break;
1730
1731 case message_DATA_REQUEST:
1732 ro_gui_selection_data_request((wimp_full_message_data_request*)message);
1733 break;
1734
1735 case message_MODE_CHANGE:
1737 rufl_invalidate_cache();
1738 break;
1739
1740 case message_PALETTE_CHANGE:
1741 break;
1742
1743 case message_FONT_CHANGED:
1745 break;
1746
1747 case message_URI_PROCESS:
1748 if (event != wimp_USER_MESSAGE_ACKNOWLEDGE)
1749 ro_uri_message_received(message);
1750 break;
1751 case message_URI_RETURN_RESULT:
1752 ro_uri_bounce(message);
1753 break;
1754 case message_INET_SUITE_OPEN_URL:
1755 if (event == wimp_USER_MESSAGE_ACKNOWLEDGE) {
1756 ro_url_bounce(message);
1757 }
1758 else {
1759 ro_url_message_received(message);
1760 }
1761 break;
1762 case message_PRINT_SAVE:
1763 if (event == wimp_USER_MESSAGE_ACKNOWLEDGE)
1764 ro_print_save_bounce(message);
1765 break;
1766 case message_PRINT_ERROR:
1767 ro_print_error(message);
1768 break;
1769 case message_PRINT_TYPE_ODD:
1770 ro_print_type_odd(message);
1771 break;
1774 break;
1775 case message_QUIT:
1776 riscos_done = true;
1777 break;
1778 }
1779}
1780
1781
1782/**
1783 * Process a Wimp_Poll event.
1784 *
1785 * \param event wimp event number
1786 * \param block parameter block
1787 */
1788static void ro_gui_handle_event(wimp_event_no event, wimp_block *block)
1789{
1790 switch (event) {
1791 case wimp_NULL_REASON_CODE:
1792 ro_gui_throb();
1793 ro_mouse_poll();
1794 break;
1795
1796 case wimp_REDRAW_WINDOW_REQUEST:
1797 ro_gui_wimp_event_redraw_window(&block->redraw);
1798 break;
1799
1800 case wimp_OPEN_WINDOW_REQUEST:
1801 ro_gui_open_window_request(&block->open);
1802 break;
1803
1804 case wimp_CLOSE_WINDOW_REQUEST:
1805 ro_gui_close_window_request(&block->close);
1806 break;
1807
1808 case wimp_POINTER_LEAVING_WINDOW:
1809 ro_mouse_pointer_leaving_window(&block->leaving);
1810 break;
1811
1812 case wimp_POINTER_ENTERING_WINDOW:
1814 break;
1815
1816 case wimp_MOUSE_CLICK:
1817 ro_gui_wimp_event_mouse_click(&block->pointer);
1818 break;
1819
1820 case wimp_USER_DRAG_BOX:
1821 ro_mouse_drag_end(&block->dragged);
1822 break;
1823
1824 case wimp_KEY_PRESSED:
1825 ro_gui_keypress(&(block->key));
1826 break;
1827
1828 case wimp_MENU_SELECTION:
1829 ro_gui_menu_selection(&(block->selection));
1830 break;
1831
1832 /* Scroll requests fall back to a generic handler because we
1833 * might get these events for any window from a scroll-wheel.
1834 */
1835
1836 case wimp_SCROLL_REQUEST:
1837 if (!ro_gui_wimp_event_scroll_window(&(block->scroll)))
1838 ro_gui_scroll(&(block->scroll));
1839 break;
1840
1841 case wimp_USER_MESSAGE:
1842 case wimp_USER_MESSAGE_RECORDED:
1843 case wimp_USER_MESSAGE_ACKNOWLEDGE:
1844 ro_gui_user_message(event, &(block->message));
1845 break;
1846 }
1847}
1848
1849
1850/**
1851 * Poll the RISC OS wimp for events.
1852 */
1853static void riscos_poll(void)
1854{
1855 wimp_event_no event;
1856 wimp_block block;
1857 const wimp_poll_flags mask = wimp_MASK_LOSE | wimp_MASK_GAIN | wimp_SAVE_FP;
1858 os_t track_poll_offset;
1859
1860 /* Poll wimp. */
1861 xhourglass_off();
1862 track_poll_offset = ro_mouse_poll_interval();
1863 if (sched_active || (track_poll_offset > 0)) {
1864 os_t t = os_read_monotonic_time();
1865
1866 if (track_poll_offset > 0) {
1867 t += track_poll_offset;
1868 } else {
1869 t += 10;
1870 }
1871
1872 if (sched_active && (sched_time - t) < 0) {
1873 t = sched_time;
1874 }
1875
1876 event = wimp_poll_idle(mask, &block, t, 0);
1877 } else {
1878 event = wimp_poll(wimp_MASK_NULL | mask, &block, 0);
1879 }
1880
1881 xhourglass_on();
1882 gui_last_poll = clock();
1883 ro_gui_handle_event(event, &block);
1884
1885 /* Only run scheduled callbacks on a null poll
1886 * We cannot do this in the null event handler, as that may be called
1887 * from gui_multitask(). Scheduled callbacks must only be run from the
1888 * top-level.
1889 */
1890 if (event == wimp_NULL_REASON_CODE) {
1891 schedule_run();
1892 }
1893
1895}
1896
1897
1898/**
1899 * Handle Open_Window_Request events.
1900 */
1901void ro_gui_open_window_request(wimp_open *open)
1902{
1903 os_error *error;
1904
1906 return;
1907
1908 error = xwimp_open_window(open);
1909 if (error) {
1910 NSLOG(netsurf, INFO, "xwimp_open_window: 0x%x: %s",
1911 error->errnum, error->errmess);
1912 ro_warn_user("WimpError", error->errmess);
1913 return;
1914 }
1915}
1916
1917
1918/**
1919 * source bounce callback.
1920 */
1921static void ro_gui_view_source_bounce(wimp_message *message)
1922{
1923 char *filename;
1924 os_error *error;
1925 char command[256];
1926
1927 /* run the file as text */
1928 filename = ((wimp_full_message_data_xfer *)message)->file_name;
1929 sprintf(command, "@RunType_FFF %s", filename);
1930 error = xwimp_start_task(command, 0);
1931 if (error) {
1932 NSLOG(netsurf, INFO, "xwimp_start_task failed: 0x%x: %s",
1933 error->errnum, error->errmess);
1934 ro_warn_user("WimpError", error->errmess);
1935 }
1936}
1937
1938
1939/**
1940 * Send the source of a content to a text editor.
1941 */
1943{
1944 os_error *error;
1945 char *temp_name;
1946 wimp_full_message_data_xfer message;
1947 int objtype;
1948 bool done = false;
1949
1950 const uint8_t *source_data;
1951 size_t source_size;
1952
1953 if (!c) {
1954 ro_warn_user("MiscError", "No document source");
1955 return;
1956 }
1957
1958 source_data = content_get_source_data(c, &source_size);
1959
1960 if (!source_data) {
1961 ro_warn_user("MiscError", "No document source");
1962 return;
1963 }
1964
1965 /* try to load local files directly. */
1967 error = xosfile_read_no_path(temp_name, &objtype, 0, 0, 0, 0);
1968 if ((!error) && (objtype == osfile_IS_FILE)) {
1969 snprintf(message.file_name, 212, "%s", temp_name);
1970 message.file_name[211] = '\0';
1971 done = true;
1972 }
1973 free(temp_name);
1974 }
1975 if (!done) {
1976 /* We cannot release the requested filename until after it
1977 * has finished being used. As we can't easily find out when
1978 * this is, we simply don't bother releasing it and simply
1979 * allow it to be re-used next time NetSurf is started. The
1980 * memory overhead from doing this is under 1 byte per
1981 * filename. */
1982 char *r;
1983 char full_name[256];
1984 const char *filename = filename_request();
1985 if (!filename) {
1986 ro_warn_user("NoMemory", 0);
1987 return;
1988 }
1989
1990 snprintf(full_name, 256, "%s/%s", TEMP_FILENAME_PREFIX,
1991 filename);
1992 full_name[255] = '\0';
1993 r = __riscosify(full_name, 0, __RISCOSIFY_NO_SUFFIX,
1994 message.file_name, 212, 0);
1995 if (r == 0) {
1996 NSLOG(netsurf, INFO, "__riscosify failed");
1997 return;
1998 }
1999 message.file_name[211] = '\0';
2000
2001 error = xosfile_save_stamped(message.file_name,
2003 (byte *) source_data,
2004 (byte *) source_data + source_size);
2005 if (error) {
2006 NSLOG(netsurf, INFO,
2007 "xosfile_save_stamped failed: 0x%x: %s",
2008 error->errnum,
2009 error->errmess);
2010 ro_warn_user("MiscError", error->errmess);
2011 return;
2012 }
2013 }
2014
2015 /* begin the DataOpen protocol */
2016 message.your_ref = 0;
2017 message.size = 44 + ((strlen(message.file_name) + 4) & (~3u));
2018 message.action = message_DATA_OPEN;
2019 message.w = 0;
2020 message.i = 0;
2021 message.pos.x = 0;
2022 message.pos.y = 0;
2023 message.est_size = 0;
2024 message.file_type = 0xfff;
2025 ro_message_send_message(wimp_USER_MESSAGE_RECORDED,
2026 (wimp_message*)&message, 0,
2028}
2029
2030
2031/**
2032 * Broadcast an URL that we can't handle.
2033 */
2034static nserror gui_launch_url(struct nsurl *url)
2035{
2036 /* Try ant broadcast */
2038 return NSERROR_OK;
2039}
2040
2041
2042/**
2043 * Choose the language to use.
2044 */
2045static void ro_gui_choose_language(void)
2046{
2047 /* if option_language exists and is valid, use that */
2048 if (nsoption_charp(language)) {
2049 char path[40];
2050 if (2 < strlen(nsoption_charp(language)))
2051 nsoption_charp(language)[2] = 0;
2052 sprintf(path, "NetSurf:Resources.%s", nsoption_charp(language));
2053
2054 if (is_dir(path)) {
2055 nsoption_setnull_charp(accept_language,
2056 strdup(nsoption_charp(language)));
2057 return;
2058 }
2059 nsoption_set_charp(language, NULL);
2060 }
2061
2062 nsoption_set_charp(language, strdup(ro_gui_default_language()));
2063 if (nsoption_charp(language) == NULL)
2064 die("Out of memory");
2065 nsoption_set_charp(accept_language, strdup(nsoption_charp(language)));
2066 if (nsoption_charp(accept_language) == NULL)
2067 die("Out of memory");
2068}
2069
2070
2071/**
2072 * Display a warning for a serious problem (eg memory exhaustion).
2073 *
2074 * \param warning message key for warning message
2075 * \param detail additional message, or 0
2076 */
2077nserror ro_warn_user(const char *warning, const char *detail)
2078{
2079 NSLOG(netsurf, INFO, "%s %s", warning, detail);
2080
2081 if (dialog_warning) {
2082 char warn_buffer[300];
2083 snprintf(warn_buffer, sizeof warn_buffer, "%s %s",
2084 messages_get(warning),
2085 detail ? detail : "");
2086 warn_buffer[sizeof warn_buffer - 1] = 0;
2088 warn_buffer, true);
2089 xwimp_set_icon_state(dialog_warning, ICON_WARNING_HELP,
2090 wimp_ICON_DELETED, wimp_ICON_DELETED);
2092 xos_bell();
2093 } else {
2094 /* probably haven't initialised (properly), use a
2095 non-multitasking error box */
2096 os_error error;
2097 snprintf(error.errmess, sizeof error.errmess, "%s %s",
2098 messages_get(warning),
2099 detail ? detail : "");
2100 error.errmess[sizeof error.errmess - 1] = 0;
2101 xwimp_report_error_by_category(&error,
2102 wimp_ERROR_BOX_OK_ICON |
2103 wimp_ERROR_BOX_GIVEN_CATEGORY |
2104 wimp_ERROR_BOX_CATEGORY_ERROR <<
2105 wimp_ERROR_BOX_CATEGORY_SHIFT,
2106 "NetSurf", "!netsurf",
2107 (osspriteop_area *) 1, 0, 0);
2108 }
2109
2110 return NSERROR_OK;
2111}
2112
2113
2114/**
2115 * Display an error and exit.
2116 *
2117 * Should only be used during initialisation.
2118 */
2119void die(const char * const error)
2120{
2121 os_error warn_error;
2122
2123 NSLOG(netsurf, INFO, "%s", error);
2124
2125 warn_error.errnum = 1; /* \todo: reasonable ? */
2126 strncpy(warn_error.errmess, messages_get(error),
2127 sizeof(warn_error.errmess)-1);
2128 warn_error.errmess[sizeof(warn_error.errmess)-1] = '\0';
2129 xwimp_report_error_by_category(&warn_error,
2130 wimp_ERROR_BOX_OK_ICON |
2131 wimp_ERROR_BOX_GIVEN_CATEGORY |
2132 wimp_ERROR_BOX_CATEGORY_ERROR <<
2133 wimp_ERROR_BOX_CATEGORY_SHIFT,
2134 "NetSurf", "!netsurf",
2135 (osspriteop_area *) 1, 0, 0);
2136 exit(EXIT_FAILURE);
2137}
2138
2139
2140/**
2141 * Test whether it's okay to shutdown, prompting the user if not.
2142 *
2143 * \return true iff it's okay to shutdown immediately
2144 */
2146{
2147 return ro_gui_download_prequit();
2148}
2149
2150
2151/**
2152 * Generate a riscos path from one or more component elemnts.
2153 *
2154 * Constructs a complete path element from passed components. The
2155 * second (and subsequent) components have a slash substituted for all
2156 * riscos directory separators.
2157 *
2158 * If a string is allocated it must be freed by the caller.
2159 *
2160 * @param[in,out] str pointer to string pointer if this is NULL enough
2161 * storage will be allocated for the complete path.
2162 * @param[in,out] size The size of the space available if \a str not
2163 * NULL on input and if not NULL set to the total
2164 * output length on output.
2165 * @param[in] nelm The number of elements.
2166 * @param[in] ap The elements of the path as string pointers.
2167 * @return NSERROR_OK and the complete path is written to str
2168 * or error code on faliure.
2169 */
2170static nserror riscos_mkpath(char **str, size_t *size, size_t nelm, va_list ap)
2171{
2172 const char *elm[16];
2173 size_t elm_len[16];
2174 size_t elm_idx;
2175 char *fname;
2176 size_t fname_len = 0;
2177 char *curp;
2178 size_t idx;
2179
2180 /* check the parameters are all sensible */
2181 if ((nelm == 0) || (nelm > 16)) {
2182 return NSERROR_BAD_PARAMETER;
2183 }
2184 if ((*str != NULL) && (size == NULL)) {
2185 /* if the caller is providing the buffer they must say
2186 * how much space is available.
2187 */
2188 return NSERROR_BAD_PARAMETER;
2189 }
2190
2191 /* calculate how much storage we need for the complete path
2192 * with all the elements.
2193 */
2194 for (elm_idx = 0; elm_idx < nelm; elm_idx++) {
2195 elm[elm_idx] = va_arg(ap, const char *);
2196 /* check the argument is not NULL */
2197 if (elm[elm_idx] == NULL) {
2198 return NSERROR_BAD_PARAMETER;
2199 }
2200 elm_len[elm_idx] = strlen(elm[elm_idx]);
2201 fname_len += elm_len[elm_idx];
2202 }
2203 fname_len += nelm; /* allow for separators and terminator */
2204
2205 /* ensure there is enough space */
2206 fname = *str;
2207 if (fname != NULL) {
2208 if (fname_len > *size) {
2209 return NSERROR_NOSPACE;
2210 }
2211 } else {
2212 fname = malloc(fname_len);
2213 if (fname == NULL) {
2214 return NSERROR_NOMEM;
2215 }
2216 }
2217
2218 /* copy the elements in with directory separator */
2219 curp = fname;
2220
2221 /* first element is not altered */
2222 memmove(curp, elm[0], elm_len[0]);
2223 curp += elm_len[0];
2224 /* ensure there is a delimiter */
2225 if (curp[-1] != DIR_SEP) {
2226 *curp = DIR_SEP;
2227 curp++;
2228 }
2229
2230 /* subsequent elemnts have slashes substituted with directory
2231 * separators.
2232 */
2233 for (elm_idx = 1; elm_idx < nelm; elm_idx++) {
2234 for (idx = 0; idx < elm_len[elm_idx]; idx++) {
2235 if (elm[elm_idx][idx] == DIR_SEP) {
2236 *curp = '/';
2237 } else {
2238 *curp = elm[elm_idx][idx];
2239 }
2240 curp++;
2241 }
2242 *curp = DIR_SEP;
2243 curp++;
2244 }
2245 curp[-1] = 0; /* NULL terminate */
2246
2247 assert((curp - fname) <= (int)fname_len);
2248
2249 *str = fname;
2250 if (size != NULL) {
2251 *size = fname_len;
2252 }
2253
2254 return NSERROR_OK;
2255
2256}
2257
2258
2259/**
2260 * Get the basename of a file using posix path handling.
2261 *
2262 * This gets the last element of a path and returns it. The returned
2263 * element has all forward slashes translated into riscos directory
2264 * separators.
2265 *
2266 * @param[in] path The path to extract the name from.
2267 * @param[in,out] str Pointer to string pointer if this is NULL enough
2268 * storage will be allocated for the path element.
2269 * @param[in,out] size The size of the space available if \a
2270 * str not NULL on input and set to the total
2271 * output length on output.
2272 * @return NSERROR_OK and the complete path is written to str
2273 * or error code on faliure.
2274 */
2275static nserror riscos_basename(const char *path, char **str, size_t *size)
2276{
2277 const char *leafname;
2278 char *fname;
2279 char *temp;
2280
2281 if (path == NULL) {
2282 return NSERROR_BAD_PARAMETER;
2283 }
2284
2285 leafname = strrchr(path, DIR_SEP);
2286 if (!leafname) {
2287 leafname = path;
2288 } else {
2289 leafname += 1;
2290 }
2291
2292 fname = strdup(leafname);
2293 if (fname == NULL) {
2294 return NSERROR_NOMEM;
2295 }
2296
2297 /** @todo check this leafname translation is actually required */
2298 /* and s/\//\./g */
2299 for (temp = fname; *temp != 0; temp++) {
2300 if (*temp == '/') {
2301 *temp = DIR_SEP;
2302 }
2303 }
2304
2305 *str = fname;
2306 if (size != NULL) {
2307 *size = strlen(fname);
2308 }
2309 return NSERROR_OK;
2310}
2311
2312
2313/**
2314 * Ensure that all directory elements needed to store a filename exist.
2315 *
2316 * Given a path of x.y.z directories x and x.y will be created.
2317 *
2318 * @param fname The filename to ensure the path to exists.
2319 * @return NSERROR_OK on success or error code on failure.
2320 */
2321static nserror riscos_mkdir_all(const char *fname)
2322{
2323 char *dname;
2324 char *cur;
2325
2326 dname = strdup(fname);
2327
2328 cur = dname;
2329 while ((cur = strchr(cur, '.'))) {
2330 *cur = '\0';
2331 xosfile_create_dir(dname, 0);
2332 *cur++ = '.';
2333 }
2334
2335 free(dname);
2336
2337 return NSERROR_OK;
2338}
2339
2340/**
2341 * Find screen size in OS units.
2342 */
2344{
2345 *width = screen_info.width;
2346 *height = screen_info.height;
2347}
2348
2349
2350/**
2351 * Send the debug dump of a content to a text editor.
2352 */
2354{
2355 os_error *error;
2356
2357 /* open file for dump */
2358 FILE *stream = fopen("<Wimp$ScrapDir>.WWW.NetSurf.dump", "w");
2359 if (!stream) {
2360 NSLOG(netsurf, INFO, "fopen: errno %i", errno);
2361 ro_warn_user("SaveError", strerror(errno));
2362 return;
2363 }
2364
2366
2367 fclose(stream);
2368
2369 /* launch file in editor */
2370 error = xwimp_start_task("Filer_Run <Wimp$ScrapDir>.WWW.NetSurf.dump",
2371 0);
2372 if (error) {
2373 NSLOG(netsurf, INFO, "xwimp_start_task failed: 0x%x: %s",
2374 error->errnum, error->errmess);
2375 ro_warn_user("WimpError", error->errmess);
2376 }
2377}
2378
2379
2382 .basename = riscos_basename,
2383 .nsurl_to_path = ro_nsurl_to_path,
2384 .path_to_nsurl = ro_path_to_nsurl,
2385 .mkdir_all = riscos_mkdir_all,
2386};
2387
2390
2391 .get_resource_url = gui_get_resource_url,
2392 .mimetype = fetch_mimetype,
2393};
2394
2397
2398 .quit = gui_quit,
2399 .launch_url = gui_launch_url,
2400 .present_cookies = ro_gui_cookies_present,
2401};
2402
2403
2404static char *get_cachepath(void)
2405{
2406 char *cachedir;
2407 char *cachepath = NULL;
2408 nserror ret;
2409
2410 cachedir = getenv("Cache$Dir");
2411 if ((cachedir == NULL) || (cachedir[0] == 0)) {
2412 NSLOG(netsurf, INFO, "cachedir was null");
2413 return NULL;
2414 }
2415 ret = netsurf_mkpath(&cachepath, NULL, 2, cachedir, "NetSurf");
2416 if (ret != NSERROR_OK) {
2417 return NULL;
2418 }
2419 return cachepath;
2420}
2421
2422/**
2423 * Normal entry point from RISC OS.
2424 */
2425int main(int argc, char** argv)
2426{
2427 char *cachepath;
2428 char path[40];
2429 int length;
2430 os_var_type type;
2431 int used = -1; /* slightly better with older OSLib versions */
2432 os_error *error;
2433 nserror ret;
2434 struct netsurf_table riscos_table = {
2436 .window = riscos_window_table,
2437 .corewindow = riscos_core_window_table,
2438 .clipboard = riscos_clipboard_table,
2439 .download = riscos_download_table,
2440 .fetch = &riscos_fetch_table,
2441 .file = &riscos_file_table,
2442 .utf8 = riscos_utf8_table,
2443 .search = riscos_search_table,
2444 .llcache = filesystem_llcache_table,
2445 .bitmap = riscos_bitmap_table,
2446 .layout = riscos_layout_table,
2447 };
2448
2449 ret = netsurf_register(&riscos_table);
2450 if (ret != NSERROR_OK) {
2451 die("NetSurf operation table failed registration");
2452 }
2453
2454 /* Consult NetSurf$Logging environment variable to decide if logging
2455 * is required. */
2456 error = xos_read_var_val_size("NetSurf$Logging", 0, os_VARTYPE_STRING,
2457 &used, NULL, &type);
2458 if (error != NULL || type != os_VARTYPE_STRING || used != -2) {
2459 verbose_log = true;
2460 } else {
2461 char logging_env[2];
2462 error = xos_read_var_val("NetSurf$Logging", logging_env,
2463 sizeof(logging_env), 0, os_VARTYPE_STRING,
2464 &used, NULL, &type);
2465 if (error != NULL || logging_env[0] != '0') {
2466 verbose_log = true;
2467 } else {
2468 verbose_log = false;
2469 }
2470 }
2471
2472 /* initialise logging. Not fatal if it fails but not much we
2473 * can do about it either.
2474 */
2475 nslog_init(nslog_stream_configure, &argc, argv);
2476
2477 /* user options setup */
2479 if (ret != NSERROR_OK) {
2480 die("Options failed to initialise");
2481 }
2482 nsoption_read("NetSurf:Choices", NULL);
2483 nsoption_commandline(&argc, argv, NULL);
2484
2485 /* Choose the interface language to use */
2487
2488 /* select language-specific Messages */
2489 if (((length = snprintf(path,
2490 sizeof(path),
2491 "NetSurf:Resources.%s.Messages",
2492 nsoption_charp(language))) < 0) ||
2493 (length >= (int)sizeof(path))) {
2494 die("Failed to locate Messages resource.");
2495 }
2496
2497 /* initialise messages */
2499
2500 /* obtain cache path */
2501 cachepath = get_cachepath();
2502
2503 /* common initialisation */
2504 ret = netsurf_init(cachepath);
2505 free(cachepath);
2506 if (ret != NSERROR_OK) {
2507 die("NetSurf failed to initialise core");
2508 }
2509
2510 artworks_init();
2511 draw_init();
2512 sprite_init();
2513
2514 /* Load some extra RISC OS specific Messages */
2515 messages_add_from_file("NetSurf:Resources.LangNames");
2516
2517 ret = gui_init(argc, argv);
2518 if (ret != NSERROR_OK) {
2520 }
2521
2522 while (!riscos_done) {
2523 riscos_poll();
2524 }
2525
2526 netsurf_exit();
2528
2529 /* finalise logging */
2531
2532 return 0;
2533}
const char * fetch_filetype(const char *unix_path)
Determine the MIME type of a local file.
Definition: filetype.c:58
int main(int argc, char **argv)
Normal entry point from OS.
Definition: gui.c:6543
Content for image/x-artworks (RISC OS interface).
static nserror artworks_init(void)
Definition: artworks.h:35
int schedule_run(void)
Process events up to current time.
Definition: schedule.c:137
Low-level source data cache backing store interface.
struct gui_llcache_table * filesystem_llcache_table
Browser window creation and manipulation interface.
nserror browser_window_navigate(struct browser_window *bw, struct nsurl *url, struct nsurl *referrer, enum browser_window_nav_flags flags, char *post_urlenc, struct fetch_multipart_data *post_multipart, struct hlcache_handle *parent)
Start fetching a page in a browser window.
nserror browser_window_create(enum browser_window_create_flags flags, struct nsurl *url, struct nsurl *referrer, struct browser_window *existing, struct browser_window **bw)
Create and open a new root browser window with the given page.
nserror browser_window_debug_dump(struct browser_window *bw, FILE *f, enum content_debug op)
Dump debug info concerning the browser window's contents to file.
@ BW_CREATE_HISTORY
this will form a new history node (don't set for back/reload/etc)
@ BW_NAVIGATE_HISTORY
this will form a new history node (don't set for back/reload/etc)
void ro_gui_buffer_close(void)
Closes any open buffer and flushes the contents to screen.
Definition: buffer.c:370
Screen buffering (interface).
@ CONTENT_DEBUG_RENDER
Debug the contents rendering.
Definition: content_type.h:32
Unified cookie database public interface.
void urldb_save_cookies(const char *filename)
Save persistent cookies to file.
Definition: urldb.c:4448
void urldb_load_cookies(const char *filename)
Load a cookie file into the database.
Definition: urldb.c:4281
Useful interned string pointers (interface).
#define FILE_SCHEME_PREFIX_LEN
File url prefix length.
Definition: corestrings.h:33
#define FILE_SCHEME_PREFIX
File url prefix.
Definition: corestrings.h:30
static nserror hotlist_save(const char *path)
Definition: hotlist.c:113
nserror hotlist_init(const char *load_path, const char *save_path)
Initialise the hotlist.
Definition: hotlist.c:1290
void ro_gui_dialog_close_persistent(wimp_w parent)
Close persistent dialogs associated with a window.
Definition: dialog.c:638
void ro_gui_dialog_open(wimp_w w)
Open a dialog box, centred on the screen.
Definition: dialog.c:297
wimp_w dialog_warning
Definition: dialog.c:77
void ro_gui_dialog_init(void)
Load and create dialogs from template file.
Definition: dialog.c:103
void ro_gui_dialog_close(wimp_w close)
Close a dialog box.
Definition: dialog.c:335
Content for image/x-drawfile (RISC OS interface).
static nserror draw_init(void)
Definition: draw.h:35
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_NOSPACE
Insufficient space.
Definition: errors.h:59
@ NSERROR_NOT_FOUND
Requested item not found.
Definition: errors.h:34
@ NSERROR_BAD_PARAMETER
Bad Parameter.
Definition: errors.h:48
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_OK
No error.
Definition: errors.h:30
const char * filename_request(void)
Request a new, unique, filename.
Definition: filename.c:68
bool filename_initialise(void)
Initialise the filename provider.
Definition: filename.c:178
#define TEMP_FILENAME_PREFIX
Definition: filename.h:27
const char * type
Definition: filetype.cpp:44
struct gui_bitmap_table * riscos_bitmap_table
bitmap operations table
Definition: bitmap.c:818
void ro_gui_download_init(void)
Load the download window template.
Definition: download.c:189
bool ro_gui_download_prequit(void)
Respond to PreQuit message, displaying a prompt message if we need the user to confirm the shutdown.
Definition: download.c:1680
struct gui_download_table * riscos_download_table
Definition: download.c:1697
void ro_gui_download_datasave_ack(wimp_message *message)
Handle Message_DataSaveAck for a drag from a download window.
Definition: download.c:1010
void nsfont_init(void)
Initialize font handling.
Definition: font.c:116
void ro_gui_wimp_get_desktop_font(void)
Retrieve the current desktop font family, size and style from the WindowManager in a form suitable fo...
Definition: font.c:607
struct gui_layout_table * riscos_layout_table
Definition: font.c:622
RISC OS font interface.
nserror ro_gui_global_history_finalise(void)
Free any resources allocated for the global history window.
RISc OS global history interface.
void ro_gui_hotlist_add_cleanup(void)
Clean up RMA storage used by the Message_HotlistAddURL protocol.
Definition: hotlist.c:730
nserror ro_gui_hotlist_finalise(void)
Free any resources allocated for the cookie window.
Definition: hotlist.c:586
Hotlist (interface).
#define message_HOTLIST_CHANGED
Definition: hotlist.h:34
#define message_HOTLIST_ADD_URL
Definition: hotlist.h:30
nserror ro_gui_local_history_finalise(void)
Free any resources allocated for the local history window.
RISC OS local history interface.
void ro_mouse_pointer_leaving_window(wimp_leaving *leaving)
Process Wimp_PointerLeaving events by terminating an active mouse track and passing the details on to...
Definition: mouse.c:224
os_t ro_mouse_poll_interval(void)
Return the desired polling interval to allow the mouse tracking to be carried out.
Definition: mouse.c:272
void ro_mouse_drag_end(wimp_dragged *dragged)
Process Wimp_DragEnd events by terminating an active drag track and passing the details on to any reg...
Definition: mouse.c:146
void ro_mouse_poll(void)
Process Null polls for any drags and mouse trackers that are currently active.
Definition: mouse.c:71
Mouse dragging and tracking support interface for RISC OS.
void ro_print_dataload_bounce(wimp_message *m)
Handle a bounced dataload message.
Definition: print.c:488
void ro_print_cleanup(void)
Cleanup after printing.
Definition: print.c:502
void ro_print_error(wimp_message *m)
Handle message_PRINT_ERROR.
Definition: print.c:370
bool ro_print_ack(wimp_message *m)
Handle message_DATASAVE_ACK for the printing protocol.
Definition: print.c:429
struct gui_window * ro_print_current_window
Definition: print.c:79
void ro_print_save_bounce(wimp_message *m)
Handle a bounced message_PRINT_SAVE.
Definition: print.c:351
void ro_print_type_odd(wimp_message *m)
Handle message_PRINT_TYPE_ODD.
Definition: print.c:391
void ro_gui_selection_data_request(wimp_full_message_data_request *req)
Responds to DATA_REQUEST message, returning information about the clipboard contents if we own the cl...
void ro_gui_selection_claim_entity(wimp_full_message_claim_entity *claim)
Responds to CLAIM_ENTITY message notifying us that the caret and selection or clipboard have been cla...
struct gui_clipboard_table * riscos_clipboard_table
bool ro_gui_selection_prepare_paste_datasave(wimp_full_message_data_xfer *dataxfer)
Prepare to paste data from another application (step 2)
void ro_gui_selection_prepare_paste(wimp_w w, ro_gui_selection_prepare_paste_cb cb, void *pw)
Prepare to paste data from another application.
void ro_gui_selection_dragging(wimp_message *message)
Handler for Message_Dragging, used to implement auto-scrolling and ghost caret when a drag is in prog...
bool ro_gui_selection_prepare_paste_dataload(wimp_full_message_data_xfer *dataxfer)
Prepare to paste data from another application (step 3)
void ro_gui_selection_drag_claim(wimp_message *message)
Text selection import/export (interface).
Browser window handling (interface).
#define ro_gui_window_close_all
Close all browser windows.
Definition: window.h:148
void ro_gui_iconbar_initialise(void)
Initialise the iconbar menus, create an icon and register the necessary handlers to look after them a...
Definition: iconbar.c:66
Iconbar icon and menus (interface).
Public content interface.
struct nsurl * hlcache_handle_get_url(const struct hlcache_handle *handle)
Retrieve the URL associated with a high level cache handle.
const uint8_t * content_get_source_data(struct hlcache_handle *h, size_t *size)
Retrieve source of content.
Definition: content.c:1209
Interface to platform-specific fetcher operations.
Interface to platform-specific miscellaneous browser operation table.
nserror nslog_init(nslog_ensure_t *ensure, int *pargc, char **argv)
Initialise the logging system.
Definition: log.c:190
bool verbose_log
flag to enable verbose logging
Definition: log.c:31
void nslog_finalise(void)
Shut down the logging system.
Definition: log.c:299
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
void ro_gui_menu_init(void)
Create menu structures.
Definition: menus.c:116
void ro_gui_menu_message_deleted(wimp_message_menus_deleted *deleted)
Handle Message_MenusDeleted, removing our current record of an open menu if it matches the deleted me...
Definition: menus.c:442
void ro_gui_menu_warning(wimp_message_menu_warning *warning)
Handle Message_MenuWarning.
Definition: menus.c:381
void ro_gui_menu_selection(wimp_selection *selection)
Handle menu selection.
Definition: menus.c:326
bool ro_message_handle_message(wimp_event_no event, wimp_message *message)
Attempts to route a message.
Definition: message.c:192
bool ro_message_send_message(wimp_event_no event, wimp_message *message, wimp_t task, void(*callback)(wimp_message *message))
Sends a message and registers a return route for a bounce.
Definition: message.c:57
bool ro_message_register_route(unsigned int message_code, void(*callback)(wimp_message *message))
Registers a route for a message code.
Definition: message.c:157
Automated RISC OS message routing (interface).
nserror messages_add_from_file(const char *path)
Read keys and values from messages file into the standard Messages hash.
Definition: messages.c:177
const char * messages_get_errorcode(nserror code)
lookup of a message by errorcode from the standard Messages hash.
Definition: messages.c:248
const char * messages_get(const char *key)
Fast lookup of a message by key from the standard Messages hash.
Definition: messages.c:241
Localised message support (interface).
NetSurf core interface registration, construction and destruction.
void netsurf_exit(void)
Finalise NetSurf core.
Definition: netsurf.c:232
nserror netsurf_init(const char *store_path)
Initialise netsurf core.
Definition: netsurf.c:107
nserror netsurf_register(struct netsurf_table *table)
Register operation table.
Definition: gui_factory.c:777
nserror nsurl_create(const char *const url_s, nsurl **url)
Create a NetSurf URL object from a URL string.
void nsurl_unref(nsurl *url)
Drop a reference to a NetSurf URL object.
const char * nsurl_access(const nsurl *url)
Access a NetSurf URL object as a string.
lwc_string * nsurl_get_component(const nsurl *url, nsurl_component part)
Get part of a URL as a lwc_string, from a NetSurf URL object.
@ NSURL_SCHEME
Definition: nsurl.h:45
@ NSURL_PATH
Definition: nsurl.h:52
struct nsurl nsurl
NetSurf URL object.
Definition: nsurl.h:31
@ base
Definition: punycode.c:19
void ro_gui_query_init(void)
Definition: query.c:76
nserror ro_gui_cookies_finalise(void)
Free any resources allocated for the cookie window.
Definition: cookies.c:478
nserror ro_gui_cookies_present(const char *search_term)
make the cookie window visible.
Definition: cookies.c:449
Interface to riscos cookie viewing using riscos core window.
struct core_window_table * riscos_core_window_table
Definition: corewindow.c:974
RISC OS core window interface.
char * fetch_mimetype(const char *ro_path)
Find a MIME type for a local file.
Definition: filetype.c:154
int ro_content_filetype(struct hlcache_handle *c)
Determine the RISC OS filetype for a content.
Definition: filetype.c:243
RISC OS filetpe interface.
#define FILETYPE_HTML
Definition: filetype.h:38
#define FILETYPE_PNG
Definition: filetype.h:59
#define FILETYPE_ARTWORKS
Definition: filetype.h:65
#define FILETYPE_GIF
Definition: filetype.h:50
#define FILETYPE_CSS
Definition: filetype.h:44
#define FILETYPE_ICO
Definition: filetype.h:56
#define FILETYPE_JPEG
Definition: filetype.h:62
#define FILETYPE_WEBP
Definition: filetype.h:71
#define FILETYPE_JNG
Definition: filetype.h:41
#define FILETYPE_MNG
Definition: filetype.h:47
#define FILETYPE_BMP
Definition: filetype.h:53
#define FILETYPE_SVG
Definition: filetype.h:68
#define FILETYPE_IEURL
Definition: filetype.h:35
#define FILETYPE_ANT_URL
Definition: filetype.h:32
#define FILETYPE_ACORN_URI
Definition: filetype.h:29
void ro_gui_screen_size(int *width, int *height)
Find screen size in OS units.
Definition: gui.c:2343
static void ro_gui_cleanup(void)
Ensures the gui exits cleanly.
Definition: gui.c:386
static bool ro_gui_uri_file_parse_line(FILE *fp, char *b)
Read a "line" from an Acorn URI file.
Definition: gui.c:472
const char *const __dynamic_da_name
For UnixLib.
Definition: gui.c:100
static void ro_gui_check_resolvers(void)
Warn the user if Inet$Resolvers is not set.
Definition: gui.c:1082
ro_gui_drag_type gui_current_drag_type
Definition: gui.c:115
static void riscos_poll(void)
Poll the RISC OS wimp for events.
Definition: gui.c:1853
static nsurl * gui_get_resource_url(const char *path)
Callback to translate resource to full url for RISC OS.
Definition: gui.c:176
void ro_gui_view_source(struct hlcache_handle *c)
Send the source of a content to a text editor.
Definition: gui.c:1942
static struct gui_fetch_table riscos_fetch_table
Definition: gui.c:2388
static void ro_msg_datasave(wimp_message *message)
Handle Message_DataSave.
Definition: gui.c:885
int __dynamic_da_max_size
For UnixLib.
Definition: gui.c:101
int width
Definition: gui.c:160
static nserror gui_launch_url(struct nsurl *url)
Broadcast an URL that we can't handle.
Definition: gui.c:2034
osspriteop_area * gui_sprites
Sprite area containing pointer and hotlist sprites.
Definition: gui.c:118
static nserror riscos_mkpath(char **str, size_t *size, size_t nelm, va_list ap)
Generate a riscos path from one or more component elemnts.
Definition: gui.c:2170
bool ro_gui_prequit(void)
Test whether it's okay to shutdown, prompting the user if not.
Definition: gui.c:2145
static void ro_gui_user_message(wimp_event_no event, wimp_message *message)
Handle the three User_Message events.
Definition: gui.c:1693
const char * NETSURF_DIR
Definition: gui.c:110
#define CHOICES_PREFIX
Definition: gui.c:113
static nserror gui_init(int argc, char **argv)
Initialise the RISC OS specific GUI.
Definition: gui.c:1123
static nserror set_defaults(struct nsoption_s *defaults)
Set option defaults for riscos frontend.
Definition: gui.c:286
static void ro_gui_get_screen_properties(void)
Get screen properties following a mode change.
Definition: gui.c:1053
wimp_t task_handle
RISC OS wimp task handle.
Definition: gui.c:116
static bool nslog_stream_configure(FILE *fptr)
Ensures output logging stream is correctly configured.
Definition: gui.c:1588
nserror ro_warn_user(const char *warning, const char *detail)
Display a warning for a serious problem (eg memory exhaustion).
Definition: gui.c:2077
static void ro_msg_save_desktop(wimp_message *message)
Handle SaveDesktop message.
Definition: gui.c:994
#define DIR_SEP
Definition: gui.c:120
static void ro_gui_close_window_request(wimp_close *close)
Handle Close_Window_Request events.
Definition: gui.c:1622
bool riscos_done
Definition: gui.c:93
static void gui_quit(void)
Close down the gui (RISC OS).
Definition: gui.c:1600
void ro_gui_dump_browser_window(struct browser_window *bw)
Send the debug dump of a content to a text editor.
Definition: gui.c:2353
static void ro_gui_keypress_cb(void *pw)
Handle key press paste callback.
Definition: gui.c:1637
static void ro_gui_handle_event(wimp_event_no event, wimp_block *block)
Process a Wimp_Poll event.
Definition: gui.c:1788
static nserror set_colour_from_wimp(struct nsoption_s *opts, wimp_colour wimp, enum nsoption_e option, colour def_colour)
Set colour option from wimp.
Definition: gui.c:251
static void ro_gui_signal(int sig)
Handles a signal.
Definition: gui.c:398
bool ro_plot_patterned_lines
One version of the A9home OS is incapable of drawing patterned lines.
Definition: plotters.c:45
static char * ro_gui_url_file_parse(const char *file_name)
Parse an ANT URL file.
Definition: gui.c:583
static void ro_msg_dataopen(wimp_message *message)
Handle Message_DataOpen (double-click on file in the Filer).
Definition: gui.c:677
void die(const char *const error)
Display an error and exit.
Definition: gui.c:2119
static nserror ro_nsurl_to_path(struct nsurl *url, char **path_out)
Create a path from a nsurl using posix file handling.
Definition: gui.c:1523
static char * get_cachepath(void)
Definition: gui.c:2404
static void ro_gui_choose_language(void)
Choose the language to use.
Definition: gui.c:2045
static nserror ro_path_to_nsurl(const char *path, struct nsurl **url_out)
Create a nsurl from a RISC OS pathname.
Definition: gui.c:1432
static nserror riscos_mkdir_all(const char *fname)
Ensure that all directory elements needed to store a filename exist.
Definition: gui.c:2321
int __feature_imagefs_is_file
For UnixLib.
Definition: gui.c:102
static void ro_msg_window_info(wimp_message *message)
Handle WindowInfo message (part of the iconising protocol)
Definition: gui.c:1030
static clock_t gui_last_poll
Time of last wimp_poll.
Definition: gui.c:117
static void ro_msg_prequit(wimp_message *message)
Handle PreQuit message.
Definition: gui.c:971
static nserror riscos_basename(const char *path, char **str, size_t *size)
Get the basename of a file using posix path handling.
Definition: gui.c:2275
void ro_gui_open_window_request(wimp_open *open)
Handle Open_Window_Request events.
Definition: gui.c:1901
static void ro_gui_keypress(wimp_key *key)
Handle gui keypress.
Definition: gui.c:1657
static void ro_msg_dataload(wimp_message *message)
Handle Message_DataLoad (file dragged in).
Definition: gui.c:756
static void ro_gui_view_source_bounce(wimp_message *message)
source bounce callback.
Definition: gui.c:1921
static void ro_gui_create_dirs(void)
Create intermediate directories for Choices and User Data files.
Definition: gui.c:350
bool os_alpha_sprite_supported
Definition: gui.c:98
int height
Definition: gui.c:161
static struct gui_misc_table riscos_misc_table
Definition: gui.c:2395
static bool ro_gui__os_alpha_sprites_supported(void)
Determine whether the OS version supports alpha channels.
Definition: gui.c:1099
static ns_wimp_message_list task_messages
Accepted wimp user messages.
Definition: gui.c:125
static void ro_msg_terminate_filename(wimp_full_message_data_xfer *message)
Ensure that the filename in a data transfer message is NULL terminated (some applications,...
Definition: gui.c:869
static const char * task_name
Definition: gui.c:112
int os_version
Definition: gui.c:97
int __riscosify_control
Definition: gui.c:104
static char * ro_gui_ieurl_file_parse(const char *file_name)
Parse an IEURL file.
Definition: gui.c:629
static struct gui_file_table riscos_file_table
Definition: gui.c:2380
const char * ro_gui_default_language(void)
Determine the default language to use.
Definition: gui.c:1384
static char * ro_gui_uri_file_parse(const char *file_name, char **uri_title)
Parse an Acorn URI file.
Definition: gui.c:518
static void ro_msg_datasave_ack(wimp_message *message)
Handle Message_DataSaveAck.
Definition: gui.c:941
static struct @46 screen_info
int __dynamic_num
os_t sched_time
Time of soonest scheduled event (valid only if sched_active is true).
Definition: schedule.c:52
nserror riscos_schedule(int t, void(*callback)(void *p), void *p)
Schedule a callback.
Definition: schedule.c:93
bool sched_active
Items have been scheduled.
Definition: schedule.c:50
#define ICON_WARNING_HELP
Definition: gui.h:197
struct gui_search_table * riscos_search_table
Definition: search.c:85
ro_gui_drag_type
Definition: gui.h:69
@ GUI_DRAG_SAVE
Definition: gui.h:69
@ GUI_DRAG_NONE
Definition: gui.h:69
@ GUI_DRAG_DOWNLOAD_SAVE
Definition: gui.h:69
#define ICON_WARNING_MESSAGE
Definition: gui.h:195
void ro_gui_interactive_help_request(wimp_message *message)
Attempts to process an interactive help message request.
Definition: help.c:89
Interactive help (interface).
nserror ro_gui_pageinfo_finalise(void)
Free any resources allocated for the page info window.
Definition: pageinfo.c:307
Interface to page info core window for RISC OS.
File/object/selection saving (Interface).
void ro_gui_theme_initialise(void)
Initialise the theme handler.
Definition: theme.c:68
void ro_toolbar_init(void)
Initialise the RISC OS toolbar widget.
Definition: toolbar.c:199
Window toolbars (interface).
void ro_gui_throb(void)
Animate the "throbbers" of all browser windows.
Definition: window.c:4778
struct gui_window * ro_gui_toolbar_lookup(wimp_w window)
Convert a toolbar RISC OS window handle to a gui_window.
Definition: window.c:4836
void ro_gui_window_update_boxes(void)
Redraw any pending update boxes.
Definition: window.c:4699
bool ro_gui_toolbar_dataload(struct gui_window *g, wimp_message *message)
Handle Message_DataLoad (file dragged in) for a toolbar.
Definition: window.c:4657
struct gui_window_table * riscos_window_table
Definition: window.c:4258
bool ro_gui_alt_pressed(void)
Returns true iff one or more Alt keys is held down.
Definition: window.c:5042
void ro_gui_window_iconise(struct gui_window *g, wimp_full_message_window_info *wi)
Window is being iconised.
Definition: window.c:4531
struct gui_window * ro_gui_window_lookup(wimp_w window)
Convert a RISC OS window handle to a gui_window.
Definition: window.c:4823
bool ro_gui_window_dataload(struct gui_window *g, wimp_message *message)
Handle Message_DataLoad (file dragged in) for a window.
Definition: window.c:4481
void ro_gui_window_quit(void)
Destroy all browser windows.
Definition: window.c:4766
void ro_gui_window_initialise(void)
Initialise the browser window module and its menus.
Definition: window.c:4262
void ro_gui_drag_box_cancel(void)
Definition: save.c:1364
void ro_gui_saveas_quit(void)
Clean-up function that releases our sprite area and memory.
Definition: save.c:216
void ro_gui_save_datasave_ack(wimp_message *message)
Handle Message_DataSaveAck for a drag from the save dialog or browser window, or Clipboard protocol.
Definition: save.c:1420
void save_complete_init(void)
Initialise save complete module.
Save HTML document with dependencies (interface).
Content for image/x-riscos-sprite (RISC OS interface).
static nserror sprite_init(void)
Definition: sprite.h:35
Interface to utility string handling.
Browser window data.
function table for fetcher operations.
Definition: fetch.h:33
const char *(* filetype)(const char *unix_path)
Determine the MIME type of a local file.
Definition: fetch.h:45
/brief function table for file and filename operations.
Definition: file.h:50
nserror(* mkpath)(char **str, size_t *size, size_t nemb, va_list ap)
Generate a path from one or more component elemnts.
Definition: file.h:68
Graphical user interface browser misc function table.
Definition: misc.h:39
nserror(* schedule)(int t, void(*callback)(void *p), void *p)
Schedule a callback.
Definition: misc.h:58
first entry in window list
Definition: gui.c:298
char * url
Definition: gui.h:154
char * title
Definition: gui.h:153
struct browser_window * bw
The 'content' window that is rendered in the gui_window.
Definition: gui.c:316
High-level cache handle.
Definition: hlcache.c:66
NetSurf operation function table.
Definition: gui_table.h:48
struct gui_misc_table * misc
Browser table.
Definition: gui_table.h:57
union nsoption_s::@149 value
colour c
Definition: nsoption.h:120
#define alpha_SPRITE_MODE
Definition: tinct.h:162
uint32_t colour
Colour type: XBGR.
Definition: types.h:35
struct gui_utf8_table * riscos_utf8_table
Definition: ucstables.c:725
UCS conversion tables (interface) This is only used if nothing claims Service_International,...
void ro_uri_message_received(wimp_message *msg)
Definition: uri.c:43
void ro_uri_bounce(wimp_message *msg)
Definition: uri.c:110
nserror url_escape(const char *unescaped, bool sptoplus, const char *escexceptions, char **result)
Escape a string suitable for inclusion in an URL.
Definition: url.c:131
nserror url_unescape(const char *str, size_t length, size_t *length_out, char **result_out)
Convert an escaped string to plain.
Definition: url.c:67
Interface to URL parsing and joining operations.
void ro_gui_url_bar_fini(void)
Finalise the url bar module.
Definition: url_bar.c:1603
bool ro_gui_url_bar_init(void)
Initialise the url bar module.
Definition: url_bar.c:1578
Unified URL information database public interface.
nserror urldb_save(const char *filename)
Export the current database to file.
Definition: urldb.c:3094
nserror urldb_load(const char *filename)
Import an URL database from file, replacing any existing database.
Definition: urldb.c:2876
void ro_url_broadcast(const char *url)
Broadcast an ANT URL message.
Definition: url_protocol.c:151
void ro_url_message_received(wimp_message *message)
Handle a Message_InetSuiteOpenURL.
Definition: url_protocol.c:52
void ro_url_bounce(wimp_message *message)
Handle a bounced Message_InetSuiteOpenURL.
Definition: url_protocol.c:224
ANT URL launching protocol (interface).
nserror netsurf_mkdir_all(const char *fname)
Ensure that all directory elements needed to store a filename exist.
Definition: file.c:313
nserror netsurf_nsurl_to_path(struct nsurl *url, char **path_out)
Create a path from a nsurl.
Definition: file.c:301
nserror netsurf_path_to_nsurl(const char *path, struct nsurl **url)
Create a nsurl from a path.
Definition: file.c:307
nserror netsurf_mkpath(char **str, size_t *size, size_t nelm,...)
Generate a path from one or more component elemnts.
Definition: file.c:288
Default operations table for files.
struct nsoption_s * nsoptions_default
global default option table.
Definition: nsoption.c:46
static struct nsoption_s defaults[]
The table of compiled in default options.
Definition: nsoption.c:64
nserror nsoption_dump(FILE *outf, struct nsoption_s *opts)
Write all options to a stream.
Definition: nsoption.c:832
nserror nsoption_read(const char *path, struct nsoption_s *opts)
Read choices file and set them in the passed table.
Definition: nsoption.c:696
struct nsoption_s * nsoptions
global active option table.
Definition: nsoption.c:45
nserror nsoption_commandline(int *pargc, char **argv, struct nsoption_s *opts)
Process commandline and set options approriately.
Definition: nsoption.c:856
nserror nsoption_init(nsoption_set_default_t *set_defaults, struct nsoption_s **popts, struct nsoption_s **pdefs)
Initialise option system.
Definition: nsoption.c:608
nserror nsoption_finalise(struct nsoption_s *opts, struct nsoption_s *defs)
Finalise option system.
Definition: nsoption.c:663
Option reading and saving interface.
#define nsoption_charp(OPTION)
Get the value of a string option.
Definition: nsoption.h:331
#define nsoption_setnull_charp(OPTION, VALUE)
set string option in default table if currently unset
Definition: nsoption.h:376
#define nsoption_set_int(OPTION, VALUE)
set an integer option in the default table
Definition: nsoption.h:348
nsoption_e
Definition: nsoption.h:131
#define nsoption_set_charp(OPTION, VALUE)
set string option in default table
Definition: nsoption.h:372
#define nsoption_bool(OPTION)
Get the value of a boolean option.
Definition: nsoption.h:304
#define nsoption_set_uint(OPTION, VALUE)
set an unsigned integer option in the default table
Definition: nsoption.h:351
Interface to a number of general purpose functionality.
#define SLEN(x)
Calculate length of constant C string.
Definition: utils.h:88
bool is_dir(const char *path)
Check if a directory exists.
Definition: utils.c:94
void ro_gui_set_icon_string(wimp_w w, wimp_i i, const char *text, bool is_utf8)
Set the contents of a text or sprite icon to a string.
Definition: wimp.c:269
osspriteop_area * ro_gui_load_sprite_file(const char *pathname)
Load a sprite file into memory.
Definition: wimp.c:806
void ro_gui_scroll(wimp_scroll *scroll)
Generic window scroll event handler.
Definition: wimp.c:1131
General RISC OS WIMP/OS library functions (interface).
bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer)
Handles a mouse click event in a registered window.
Definition: wimp_event.c:639
bool ro_gui_wimp_event_redraw_window(wimp_draw *redraw)
Handle any redraw window requests.
Definition: wimp_event.c:1129
bool ro_gui_wimp_event_scroll_window(wimp_scroll *scroll)
Handle any scroll window requests.
Definition: wimp_event.c:1147
bool ro_gui_wimp_event_open_window(wimp_open *open)
Handle any open window requests.
Definition: wimp_event.c:1089
bool ro_gui_wimp_event_close_window(wimp_w w)
Service any close window handlers.
Definition: wimp_event.c:1107
bool ro_gui_wimp_event_pointer_entering_window(wimp_entering *entering)
Handle any pointer entering window requests.
Definition: wimp_event.c:1165
bool ro_gui_wimp_event_keypress(wimp_key *key)
Handle any registered keypresses, and the standard RISC OS ones.
Definition: wimp_event.c:885
Automated RISC OS WIMP event handling (interface).
A collection of grubby utilities for working with OSLib's wimp API.
#define PTR_WIMP_MESSAGE_LIST(l)
Definition: wimputils.h:53
#define PTR_OS_VDU_VAR_LIST(l)
Definition: wimputils.h:66
static nserror path(const struct redraw_context *ctx, const plot_style_t *pstyle, const float *p, unsigned int n, const float transform[6])
Plots a path.
Definition: plot.c:821
static nserror line(const struct redraw_context *ctx, const plot_style_t *style, const struct rect *line)
Plots a line.
Definition: plot.c:579