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